Files
frigate-camera-control-bridge/frigate_camera_control_bridge/i18n.py
T

82 lines
2.6 KiB
Python

import gettext
import logging
import os
from pathlib import Path
LOG = logging.getLogger("frigate-camera-control-bridge")
TRANSLATION_DOMAIN = "frigate_camera_control_bridge"
DEFAULT_LANGUAGE = "en"
DEFAULT_LOCALE_DIR = Path(__file__).resolve().parents[1] / "locale"
LOCALE_DIR = Path(os.environ.get("LOCALE_DIR", DEFAULT_LOCALE_DIR))
_TRANSLATIONS = {}
_AVAILABLE_LANGUAGES = None
def parse_po_language_name(path):
# gettext compiled catalogs do not expose a friendly language name, so the
# editable .po file may carry an optional Language-Name header for the GUI.
try:
text = path.read_text(encoding="utf-8")
except OSError:
return None
for line in text.splitlines():
if line.startswith('"Language-Name:'):
return line.split(":", 1)[1].strip().strip("\\n\"")
return None
def available_languages():
# Discover languages dynamically from locale/*/LC_MESSAGES/*.mo. Adding a
# language should not require a code change; ship a new .po/.mo pair instead.
global _AVAILABLE_LANGUAGES
if _AVAILABLE_LANGUAGES is not None:
return _AVAILABLE_LANGUAGES
languages = {DEFAULT_LANGUAGE: DEFAULT_LANGUAGE.upper()}
if LOCALE_DIR.exists():
for item in sorted(LOCALE_DIR.iterdir()):
if not item.is_dir():
continue
code = item.name
catalog = item / "LC_MESSAGES" / f"{TRANSLATION_DOMAIN}.mo"
if catalog.exists():
languages[code] = (
parse_po_language_name(item / "LC_MESSAGES" / f"{TRANSLATION_DOMAIN}.po")
or code.upper()
)
_AVAILABLE_LANGUAGES = languages
return languages
def normalize_language(value):
if not value:
return DEFAULT_LANGUAGE
base = str(value).lower().replace("_", "-").split("-", 1)[0]
return base if base in available_languages() else DEFAULT_LANGUAGE
def translation_for(lang):
# fallback=True makes English msgids work even if a translation file is
# missing, which is useful while developing a new language catalog.
lang = normalize_language(lang)
if lang not in _TRANSLATIONS:
_TRANSLATIONS[lang] = gettext.translation(
TRANSLATION_DOMAIN,
localedir=str(LOCALE_DIR),
languages=[lang],
fallback=True,
)
return _TRANSLATIONS[lang]
def text_for(lang, msgid, **kwargs):
text = translation_for(lang).gettext(msgid)
if kwargs:
try:
return text.format(**kwargs)
except KeyError as exc:
LOG.warning("missing translation placeholder %s for %s", exc, msgid)
return text