A Python port of the Invisible Internet Project (I2P)
at main 72 lines 2.3 kB view raw
1"""i18n translation support. 2 3Loads Java .properties files and provides locale-specific message lookup 4with parameter interpolation. 5 6Ported from net.i2p.util.Translate and TranslateReader. 7""" 8 9from __future__ import annotations 10 11import os 12import re 13 14 15class TranslateReader: 16 """Load Java .properties translation files.""" 17 18 def load(self, path: str) -> dict[str, str]: 19 """Load a .properties file into a dict. 20 21 Returns empty dict if file not found. 22 """ 23 result: dict[str, str] = {} 24 try: 25 with open(path, encoding="utf-8") as f: 26 for line in f: 27 line = line.rstrip("\n\r") 28 if not line or line.startswith("#") or line.startswith("!"): 29 continue 30 # Split on first = or : 31 m = re.match(r"([^=:]+?)\s*[=:]\s*(.*)", line) 32 if m: 33 result[m.group(1).strip()] = m.group(2) 34 except OSError: 35 pass 36 return result 37 38 39class Translate: 40 """Locale-specific message lookup with interpolation.""" 41 42 def __init__(self) -> None: 43 self._locale: str = "en" 44 self._strings: dict[str, str] = {} 45 self._reader = TranslateReader() 46 47 def set_locale(self, locale: str) -> None: 48 self._locale = locale 49 50 def get_locale(self) -> str: 51 return self._locale 52 53 def add_strings(self, strings: dict[str, str]) -> None: 54 """Add translations to the current set.""" 55 self._strings.update(strings) 56 57 def load_bundle(self, directory: str, bundle_name: str) -> None: 58 """Load a properties file from directory for current locale.""" 59 path = os.path.join(directory, f"{bundle_name}_{self._locale}.properties") 60 props = self._reader.load(path) 61 self._strings.update(props) 62 63 def get_string(self, key: str, *params: str) -> str: 64 """Look up a translated string, with optional parameter substitution. 65 66 Returns the key itself if not found (Java convention). 67 Parameters are substituted for {0}, {1}, etc. 68 """ 69 value = self._strings.get(key, key) 70 for i, param in enumerate(params): 71 value = value.replace(f"{{{i}}}", str(param)) 72 return value