Add localization support and language selection

Introduces English and Spanish translation files, integrates localization throughout dialogs, and adds a language selection tab to the custom options dialog. UI strings are now loaded via the localization manager, enabling dynamic language switching and improved internationalization.
This commit is contained in:
Your Name
2025-09-30 20:53:59 +03:00
parent 0376c1c4cd
commit c5916d57c0
12 changed files with 1293 additions and 311 deletions
+43 -41
View File
@@ -4,6 +4,8 @@ from PySide6.QtCore import QObject, Qt, Signal
from PySide6.QtGui import QColor
from PySide6.QtWidgets import QCheckBox, QHBoxLayout, QHeaderView, QSizePolicy, QTableWidget, QTableWidgetItem, QWidget
from src.utils.ytsage_localization import _
if TYPE_CHECKING:
from src.gui.ytsage_gui_main import YTSageApp
@@ -22,14 +24,14 @@ class FormatTableMixin:
self.format_table.setColumnCount(8)
self.format_table.setHorizontalHeaderLabels(
[
"Select",
"Quality",
"Extension",
"Resolution",
"File Size",
"Codec",
"Audio",
"Notes",
_("formats.select"),
_("formats.quality"),
_("formats.extension"),
_("formats.resolution"),
_("formats.file_size"),
_("formats.codec"),
_("formats.audio"),
_("formats.notes"),
]
)
@@ -183,7 +185,7 @@ class FormatTableMixin:
# Configure columns based on mode
if is_playlist_mode:
self.format_table.setColumnCount(5)
self.format_table.setHorizontalHeaderLabels(["Select", "Quality", "Resolution", "Notes", "Audio"])
self.format_table.setHorizontalHeaderLabels([_("formats.select"), _("formats.quality"), _("formats.resolution"), _("formats.notes"), _("formats.audio")])
# Configure column visibility and resizing for playlist mode
self.format_table.setColumnHidden(5, True)
@@ -202,14 +204,14 @@ class FormatTableMixin:
self.format_table.setColumnCount(8)
self.format_table.setHorizontalHeaderLabels(
[
"Select",
"Quality",
"Extension",
"Resolution",
"File Size",
"Codec",
"Audio",
"Notes",
_("formats.select"),
_("formats.quality"),
_("formats.extension"),
_("formats.resolution"),
_("formats.file_size"),
_("formats.codec"),
_("formats.audio"),
_("formats.notes"),
]
)
# Ensure all columns are visible
@@ -262,14 +264,14 @@ class FormatTableMixin:
# Column 1: Quality (Always shown)
quality_text = self.get_quality_label(f)
quality_item = QTableWidgetItem(quality_text)
# Set color based on quality
if "Best" in quality_text:
# Set color based on quality (check both English and Spanish terms)
if any(term in quality_text for term in ["Best", "Óptima", "Mejor"]):
quality_item.setForeground(QColor("#00ff00")) # Green for best quality
elif "High" in quality_text:
elif any(term in quality_text for term in ["High", "Alta", "Alto"]):
quality_item.setForeground(QColor("#00cc00")) # Light green for high quality
elif "Medium" in quality_text:
elif any(term in quality_text for term in ["Medium", "Media", "Medio"]):
quality_item.setForeground(QColor("#ffaa00")) # Orange for medium quality
elif "Low" in quality_text:
elif any(term in quality_text for term in ["Low", "Baja", "Bajo"]):
quality_item.setForeground(QColor("#ff5555")) # Red for low quality
self.format_table.setItem(row, 1, quality_item)
@@ -278,7 +280,7 @@ class FormatTableMixin:
# Column 2: Resolution (Always shown)
resolution = f.get("resolution", "N/A")
if f.get("vcodec") == "none":
resolution = "Audio only"
resolution = _("formats.audio_only_resolution")
self.format_table.setItem(row, 2, QTableWidgetItem(resolution))
# Column 3: Notes for playlist mode, Extension for normal mode
@@ -299,11 +301,11 @@ class FormatTableMixin:
# Column 4 in playlist mode, Column 6 in normal mode: Audio Status
needs_audio = f.get("acodec") == "none" and f.get("vcodec") != "none" # Only mark video-only as needing merge
audio_status = "Will merge audio" if needs_audio else ("✓ Has Audio" if f.get("vcodec") != "none" else "Audio Only")
audio_status = _("formats.will_merge_audio") if needs_audio else (_("formats.has_audio") if f.get("vcodec") != "none" else _("formats.audio_only"))
audio_item = QTableWidgetItem(audio_status)
if needs_audio:
audio_item.setForeground(QColor("#ffa500"))
elif audio_status == "Audio Only":
elif audio_status == _("formats.audio_only"):
audio_item.setForeground(QColor("#cccccc")) # Neutral color for audio only
else: # Has Audio (Video+Audio)
audio_item.setForeground(QColor("#00cc00")) # Green for included audio
@@ -369,13 +371,13 @@ class FormatTableMixin:
# Audio quality
abr = format_info.get("abr", 0)
if abr >= 256:
return "Best Audio"
return _("formats.best_audio")
elif abr >= 192:
return "High Audio"
return _("formats.high_audio")
elif abr >= 128:
return "Medium Audio"
return _("formats.medium_audio")
else:
return "Low Audio"
return _("formats.low_audio")
else:
# Video quality
height = 0
@@ -387,17 +389,17 @@ class FormatTableMixin:
pass
if height >= 2160:
return "Best (4K)"
return _("formats.best_4k")
elif height >= 1440:
return "Best (2K)"
return _("formats.best_2k")
elif height >= 1080:
return "High (1080p)"
return _("formats.high_1080p")
elif height >= 720:
return "High (720p)"
return _("formats.high_720p")
elif height >= 480:
return "Medium (480p)"
return _("formats.medium_480p")
else:
return "Low Quality"
return _("formats.low_quality")
def _get_format_notes(self, format_info) -> str:
"""Generate helpful format notes based on format info."""
@@ -410,11 +412,11 @@ class FormatTableMixin:
# Better file size categories
if file_size > 50 * 1024 * 1024: # Over 50MB
notes.append("Large size")
notes.append(_("formats.large_size"))
elif file_size > 15 * 1024 * 1024: # 15-50MB
notes.append("Medium size")
notes.append(_("formats.medium_size"))
elif file_size > 5 * 1024 * 1024: # 5-15MB
notes.append("Standard size")
notes.append(_("formats.standard_size"))
else: # Under 5MB
notes.append("Small size")
@@ -422,11 +424,11 @@ class FormatTableMixin:
vcodec = format_info.get("vcodec", "")
if vcodec != "none":
if "avc1" in vcodec: # H.264
notes.append("Compatible")
notes.append(_("formats.compatible"))
elif "av01" in vcodec: # AV1
notes.append("Efficient")
notes.append(_("formats.efficient"))
elif "vp9" in vcodec: # VP9
notes.append("High quality")
notes.append(_("formats.high_quality"))
# Add quick mobile compatibility check
if "avc1" in vcodec and file_size < 8 * 1024 * 1024: