Ana içeriğe geç

Uluslararasılaştırma Modülü

i18n

Internationalization (i18n) support for Weeb CLI.

This module provides multi-language support through JSON-based translation files. Supports Turkish (tr), English (en), German (de), and Polish (pl).

The translation system uses dot-notation for nested keys and supports string interpolation with keyword arguments.

Example

Basic usage::

from weeb_cli.i18n import i18n

# Get translated string
message = i18n.t("menu.search", "Search Anime")

# With interpolation
greeting = i18n.t("welcome.user", name="John")

# Change language
i18n.set_language("tr")

Attributes:

Name Type Description
LOCALES_DIR Path

Directory containing translation JSON files.

i18n I18n

Global i18n instance for application-wide use.

I18n

Internationalization manager for multi-language support.

Loads and manages translation strings from JSON files, providing a simple interface for retrieving localized text with support for nested keys and string interpolation.

Attributes:

Name Type Description
language str

Current language code (e.g., 'en', 'tr', 'de', 'pl').

translations Dict[str, Any]

Loaded translation dictionary.

Source code in weeb_cli/i18n.py
class I18n:
    """Internationalization manager for multi-language support.

    Loads and manages translation strings from JSON files, providing
    a simple interface for retrieving localized text with support for
    nested keys and string interpolation.

    Attributes:
        language (str): Current language code (e.g., 'en', 'tr', 'de', 'pl').
        translations (Dict[str, Any]): Loaded translation dictionary.
    """

    def __init__(self) -> None:
        """Initialize i18n with language from config or default to English."""
        try:
            self.language: str = config.get("language", "en")
        except Exception as e:
            from weeb_cli.services.logger import debug
            debug(f"[I18n] Config read failed, defaulting to English: {e}")
            self.language = "en"
        self.translations: Dict[str, Any] = {}
        self.load_translations()

    def set_language(self, language_code: str) -> None:
        """Set the active language and reload translations.

        Args:
            language_code: Language code (e.g., 'en', 'tr', 'de', 'pl').
        """
        self.language = language_code
        config.set("language", language_code)
        self.load_translations()

    def load_translations(self) -> None:
        """Load translation file for the current language.

        Falls back to English if the requested language file doesn't exist.
        Silently handles file read errors by using an empty dictionary.
        """
        file_path = LOCALES_DIR / f"{self.language}.json"
        if not file_path.exists():
            file_path = LOCALES_DIR / "en.json"

        try:
            with open(file_path, "r", encoding="utf-8") as f:
                self.translations = json.load(f)
        except (json.JSONDecodeError, OSError) as e:
            from weeb_cli.services.logger import debug
            debug(f"[I18n] Failed to load translations for '{self.language}': {e}")
            self.translations = {}

    def get(self, key_path: str, default: Optional[str] = None, **kwargs: Any) -> str:
        """Get translated string by dot-notation key path.

        Supports nested keys using dot notation (e.g., 'menu.search.title')
        and string interpolation using keyword arguments.

        Args:
            key_path: Dot-separated path to translation key (e.g., 'menu.search').
            default: Default value if key not found. If None, returns key_path.
            **kwargs: Variables for string interpolation using .format().

        Returns:
            Translated and interpolated string, or default/key_path if not found.

        Example:
            >>> i18n.get("welcome.message", name="John")
            "Welcome, John!"
            >>> i18n.get("missing.key", "Default Text")
            "Default Text"
        """
        keys = key_path.split(".")
        value: Any = self.translations

        for key in keys:
            if isinstance(value, dict):
                value = value.get(key)
            else:
                return default if default is not None else key_path

        if value is None:
            return default if default is not None else key_path

        if isinstance(value, str):
            try:
                return value.format(**kwargs)
            except KeyError:
                return value

        return value

    # Alias for convenience
    t = get

__init__

__init__() -> None

Initialize i18n with language from config or default to English.

Source code in weeb_cli/i18n.py
def __init__(self) -> None:
    """Initialize i18n with language from config or default to English."""
    try:
        self.language: str = config.get("language", "en")
    except Exception as e:
        from weeb_cli.services.logger import debug
        debug(f"[I18n] Config read failed, defaulting to English: {e}")
        self.language = "en"
    self.translations: Dict[str, Any] = {}
    self.load_translations()

set_language

set_language(language_code: str) -> None

Set the active language and reload translations.

Parameters:

Name Type Description Default
language_code str

Language code (e.g., 'en', 'tr', 'de', 'pl').

required
Source code in weeb_cli/i18n.py
def set_language(self, language_code: str) -> None:
    """Set the active language and reload translations.

    Args:
        language_code: Language code (e.g., 'en', 'tr', 'de', 'pl').
    """
    self.language = language_code
    config.set("language", language_code)
    self.load_translations()

load_translations

load_translations() -> None

Load translation file for the current language.

Falls back to English if the requested language file doesn't exist. Silently handles file read errors by using an empty dictionary.

Source code in weeb_cli/i18n.py
def load_translations(self) -> None:
    """Load translation file for the current language.

    Falls back to English if the requested language file doesn't exist.
    Silently handles file read errors by using an empty dictionary.
    """
    file_path = LOCALES_DIR / f"{self.language}.json"
    if not file_path.exists():
        file_path = LOCALES_DIR / "en.json"

    try:
        with open(file_path, "r", encoding="utf-8") as f:
            self.translations = json.load(f)
    except (json.JSONDecodeError, OSError) as e:
        from weeb_cli.services.logger import debug
        debug(f"[I18n] Failed to load translations for '{self.language}': {e}")
        self.translations = {}

get

get(key_path: str, default: Optional[str] = None, **kwargs: Any) -> str

Get translated string by dot-notation key path.

Supports nested keys using dot notation (e.g., 'menu.search.title') and string interpolation using keyword arguments.

Parameters:

Name Type Description Default
key_path str

Dot-separated path to translation key (e.g., 'menu.search').

required
default Optional[str]

Default value if key not found. If None, returns key_path.

None
**kwargs Any

Variables for string interpolation using .format().

{}

Returns:

Type Description
str

Translated and interpolated string, or default/key_path if not found.

Example

i18n.get("welcome.message", name="John") "Welcome, John!" i18n.get("missing.key", "Default Text") "Default Text"

Source code in weeb_cli/i18n.py
def get(self, key_path: str, default: Optional[str] = None, **kwargs: Any) -> str:
    """Get translated string by dot-notation key path.

    Supports nested keys using dot notation (e.g., 'menu.search.title')
    and string interpolation using keyword arguments.

    Args:
        key_path: Dot-separated path to translation key (e.g., 'menu.search').
        default: Default value if key not found. If None, returns key_path.
        **kwargs: Variables for string interpolation using .format().

    Returns:
        Translated and interpolated string, or default/key_path if not found.

    Example:
        >>> i18n.get("welcome.message", name="John")
        "Welcome, John!"
        >>> i18n.get("missing.key", "Default Text")
        "Default Text"
    """
    keys = key_path.split(".")
    value: Any = self.translations

    for key in keys:
        if isinstance(value, dict):
            value = value.get(key)
        else:
            return default if default is not None else key_path

    if value is None:
        return default if default is not None else key_path

    if isinstance(value, str):
        try:
            return value.format(**kwargs)
        except KeyError:
            return value

    return value

get_locales_dir

get_locales_dir() -> Path

Get the locales directory path.

Handles both development and frozen (PyInstaller) environments.

Returns:

Type Description
Path

Path to the locales directory containing translation files.

Source code in weeb_cli/i18n.py
def get_locales_dir() -> Path:
    """Get the locales directory path.

    Handles both development and frozen (PyInstaller) environments.

    Returns:
        Path to the locales directory containing translation files.
    """
    if getattr(sys, 'frozen', False):
        base_path = Path(sys._MEIPASS)
        possible_path = base_path / "weeb_cli" / "locales"
        if possible_path.exists():
            return possible_path
        return base_path / "locales"

    return Path(__file__).parent / "locales"

Genel Bakış

i18n modülü, JSON tabanlı çeviri dosyaları aracılığıyla çok dilli destek sağlar. Türkçe (tr), İngilizce (en), Almanca (de) ve Lehçe (pl) destekler.

Kullanım Örnekleri

Temel Çeviri

from weeb_cli.i18n import i18n

# Çevrilmiş dize al
message = i18n.t("menu.search", "Anime Ara")
error = i18n.t("errors.network", "Ağ hatası")

Dize İnterpolasyonu

from weeb_cli.i18n import i18n

# İsimlendirilmiş parametrelerle
greeting = i18n.t("welcome.user", name="Ahmet")
# Sonuç: "Hoş geldin, Ahmet!"

progress = i18n.t("download.progress", 
                  current=5, 
                  total=12, 
                  percent=42)
# Sonuç: "İndiriliyor 5/12 (%42)"

Dil Değiştirme

from weeb_cli.i18n import i18n

# Türkçe'ye geç
i18n.set_language("tr")

# Almanca'ya geç
i18n.set_language("de")

İç İçe Anahtarlar

Çeviri dosyaları iç içe JSON yapısı kullanır:

{
  "menu": {
    "search": "Anime Ara",
    "downloads": "İndirmeler",
    "settings": "Ayarlar"
  },
  "errors": {
    "network": "Ağ bağlantısı başarısız",
    "not_found": "Anime bulunamadı"
  }
}

Nokta notasyonu ile erişim:

i18n.t("menu.search")      # "Anime Ara"
i18n.t("errors.network")   # "Ağ bağlantısı başarısız"

Desteklenen Diller

Kod Dil Durum
en İngilizce ✅ Tamamlandı
tr Türkçe ✅ Tamamlandı
de Almanca ✅ Tamamlandı
pl Lehçe ✅ Tamamlandı

Çeviri Dosyaları

Çeviri dosyaları weeb_cli/locales/ içinde bulunur:

weeb_cli/locales/
├── en.json
├── tr.json
├── de.json
└── pl.json

Çeviri Ekleme

Yeni bir dil eklemek için:

  1. weeb_cli/locales/<dil_kodu>.json oluşturun
  2. en.json'dan yapıyı kopyalayın
  3. Tüm dizeleri çevirin
  4. i18n.set_language("<dil_kodu>") ile test edin

Geri Dönüş Davranışı

  • Bir anahtar bulunamazsa, varsayılan değeri veya anahtar yolunu döndürür
  • Bir çeviri dosyası yoksa, İngilizce'ye geri döner
  • İngilizce dosyası eksikse, boş çeviriler döndürür

API Referansı

Internationalization manager for multi-language support.

Loads and manages translation strings from JSON files, providing a simple interface for retrieving localized text with support for nested keys and string interpolation.

Attributes:

Name Type Description
language str

Current language code (e.g., 'en', 'tr', 'de', 'pl').

translations Dict[str, Any]

Loaded translation dictionary.

Source code in weeb_cli/i18n.py
class I18n:
    """Internationalization manager for multi-language support.

    Loads and manages translation strings from JSON files, providing
    a simple interface for retrieving localized text with support for
    nested keys and string interpolation.

    Attributes:
        language (str): Current language code (e.g., 'en', 'tr', 'de', 'pl').
        translations (Dict[str, Any]): Loaded translation dictionary.
    """

    def __init__(self) -> None:
        """Initialize i18n with language from config or default to English."""
        try:
            self.language: str = config.get("language", "en")
        except Exception as e:
            from weeb_cli.services.logger import debug
            debug(f"[I18n] Config read failed, defaulting to English: {e}")
            self.language = "en"
        self.translations: Dict[str, Any] = {}
        self.load_translations()

    def set_language(self, language_code: str) -> None:
        """Set the active language and reload translations.

        Args:
            language_code: Language code (e.g., 'en', 'tr', 'de', 'pl').
        """
        self.language = language_code
        config.set("language", language_code)
        self.load_translations()

    def load_translations(self) -> None:
        """Load translation file for the current language.

        Falls back to English if the requested language file doesn't exist.
        Silently handles file read errors by using an empty dictionary.
        """
        file_path = LOCALES_DIR / f"{self.language}.json"
        if not file_path.exists():
            file_path = LOCALES_DIR / "en.json"

        try:
            with open(file_path, "r", encoding="utf-8") as f:
                self.translations = json.load(f)
        except (json.JSONDecodeError, OSError) as e:
            from weeb_cli.services.logger import debug
            debug(f"[I18n] Failed to load translations for '{self.language}': {e}")
            self.translations = {}

    def get(self, key_path: str, default: Optional[str] = None, **kwargs: Any) -> str:
        """Get translated string by dot-notation key path.

        Supports nested keys using dot notation (e.g., 'menu.search.title')
        and string interpolation using keyword arguments.

        Args:
            key_path: Dot-separated path to translation key (e.g., 'menu.search').
            default: Default value if key not found. If None, returns key_path.
            **kwargs: Variables for string interpolation using .format().

        Returns:
            Translated and interpolated string, or default/key_path if not found.

        Example:
            >>> i18n.get("welcome.message", name="John")
            "Welcome, John!"
            >>> i18n.get("missing.key", "Default Text")
            "Default Text"
        """
        keys = key_path.split(".")
        value: Any = self.translations

        for key in keys:
            if isinstance(value, dict):
                value = value.get(key)
            else:
                return default if default is not None else key_path

        if value is None:
            return default if default is not None else key_path

        if isinstance(value, str):
            try:
                return value.format(**kwargs)
            except KeyError:
                return value

        return value

    # Alias for convenience
    t = get

get

get(key_path: str, default: Optional[str] = None, **kwargs: Any) -> str

Get translated string by dot-notation key path.

Supports nested keys using dot notation (e.g., 'menu.search.title') and string interpolation using keyword arguments.

Parameters:

Name Type Description Default
key_path str

Dot-separated path to translation key (e.g., 'menu.search').

required
default Optional[str]

Default value if key not found. If None, returns key_path.

None
**kwargs Any

Variables for string interpolation using .format().

{}

Returns:

Type Description
str

Translated and interpolated string, or default/key_path if not found.

Example

i18n.get("welcome.message", name="John") "Welcome, John!" i18n.get("missing.key", "Default Text") "Default Text"

Source code in weeb_cli/i18n.py
def get(self, key_path: str, default: Optional[str] = None, **kwargs: Any) -> str:
    """Get translated string by dot-notation key path.

    Supports nested keys using dot notation (e.g., 'menu.search.title')
    and string interpolation using keyword arguments.

    Args:
        key_path: Dot-separated path to translation key (e.g., 'menu.search').
        default: Default value if key not found. If None, returns key_path.
        **kwargs: Variables for string interpolation using .format().

    Returns:
        Translated and interpolated string, or default/key_path if not found.

    Example:
        >>> i18n.get("welcome.message", name="John")
        "Welcome, John!"
        >>> i18n.get("missing.key", "Default Text")
        "Default Text"
    """
    keys = key_path.split(".")
    value: Any = self.translations

    for key in keys:
        if isinstance(value, dict):
            value = value.get(key)
        else:
            return default if default is not None else key_path

    if value is None:
        return default if default is not None else key_path

    if isinstance(value, str):
        try:
            return value.format(**kwargs)
        except KeyError:
            return value

    return value

set_language

set_language(language_code: str) -> None

Set the active language and reload translations.

Parameters:

Name Type Description Default
language_code str

Language code (e.g., 'en', 'tr', 'de', 'pl').

required
Source code in weeb_cli/i18n.py
def set_language(self, language_code: str) -> None:
    """Set the active language and reload translations.

    Args:
        language_code: Language code (e.g., 'en', 'tr', 'de', 'pl').
    """
    self.language = language_code
    config.set("language", language_code)
    self.load_translations()

load_translations

load_translations() -> None

Load translation file for the current language.

Falls back to English if the requested language file doesn't exist. Silently handles file read errors by using an empty dictionary.

Source code in weeb_cli/i18n.py
def load_translations(self) -> None:
    """Load translation file for the current language.

    Falls back to English if the requested language file doesn't exist.
    Silently handles file read errors by using an empty dictionary.
    """
    file_path = LOCALES_DIR / f"{self.language}.json"
    if not file_path.exists():
        file_path = LOCALES_DIR / "en.json"

    try:
        with open(file_path, "r", encoding="utf-8") as f:
            self.translations = json.load(f)
    except (json.JSONDecodeError, OSError) as e:
        from weeb_cli.services.logger import debug
        debug(f"[I18n] Failed to load translations for '{self.language}': {e}")
        self.translations = {}