@@ -28,45 +28,41 @@ class I18Next:
2828 def __init__ (self ) -> None :
2929 self .translations_by_locale : dict [str , Translation ] = dict ()
3030
31- # The translation used to look up strings in unsupported locales.
32- self .default_translation : Translation | None = None
33-
3431 def add_translation (self , locale : str , * , json_dict : dict [str , Any ] | None = None ) -> Translation :
3532 translation = Translation (babel_locale = babel .Locale .parse (locale , sep = "-" ))
3633 self .translations_by_locale [locale ] = translation
3734 if json_dict :
3835 translation .load_json_dict (json_dict )
3936 return translation
4037
41- def find_string (self , key : str , locale : str , substitutions : SubstitutionDict | None = None ) -> String | None :
42- """Find the string that will be localized, applying fallbacks and variant selection."""
43- translation = self .translations_by_locale .get (locale , self .default_translation )
44- candidate_translations = [translation ] + translation .fallbacks if translation else []
45- for candidate_translation in candidate_translations :
46- if string := candidate_translation .find_string (key , substitutions ):
47- if string .template .can_render (substitutions ):
48- return string
38+ def find_string (self , key : str , locales : list [str ], substitutions : SubstitutionDict | None = None ) -> String | None :
39+ """Find the string that will be localized, trying each locale in order."""
40+ for locale in locales :
41+ if t := self .translations_by_locale .get (locale ):
42+ if string := t .find_string (key , substitutions ):
43+ if string .template .can_render (substitutions ):
44+ return string
4945
50- raise LocalizationError (locale , key )
46+ raise LocalizationError (locales , key )
5147
52- def localize (self , string_key : str , locale : str , substitutions : SubstitutionDict | None = None ) -> str :
48+ def localize (self , string_key : str , locales : list [ str ] , substitutions : SubstitutionDict | None = None ) -> str :
5349 """Finds a translated string in the best matching locale and performs substitutions."""
54- if string := self .find_string (string_key , locale , substitutions ):
50+ if string := self .find_string (string_key , locales , substitutions ):
5551 return string .render (substitutions )
5652 else :
57- raise LocalizationError (locale , string_key )
53+ raise LocalizationError (locales , string_key )
5854
5955 def localize_with_markup (
60- self , string_key : str , locale : str , substitutions : SubstitutionDict | None = None
56+ self , string_key : str , locales : list [ str ] , substitutions : SubstitutionDict | None = None
6157 ) -> Markup :
6258 """
6359 Finds a translated string that might contain markup in the best matching locale,
6460 and performs substitutions in a way that results in a markup-safe string.
6561 """
66- if string := self .find_string (string_key , locale , substitutions ):
62+ if string := self .find_string (string_key , locales , substitutions ):
6763 return string .render_with_markup (substitutions )
6864 else :
69- raise LocalizationError (locale , string_key )
65+ raise LocalizationError (locales , string_key )
7066
7167
7268class Translation :
@@ -76,7 +72,6 @@ def __init__(self, *, babel_locale: babel.Locale) -> None:
7672 # The Babel library locale for this translation. Used to resolved plural forms.
7773 self .babel_locale = babel_locale
7874 self .strings_by_key : dict [str , String ] = dict ()
79- self .fallbacks : list [Translation ] = []
8075
8176 @property
8277 def locale (self ) -> str :
@@ -116,13 +111,13 @@ def find_string(self, key: str, substitutions: SubstitutionDict | None = None) -
116111 def localize (self , string_key : str , substitutions : SubstitutionDict | None = None ) -> str :
117112 string = self .find_string (string_key , substitutions )
118113 if string is None :
119- raise LocalizationError (locale = self .locale , string_key = string_key )
114+ raise LocalizationError (locales = [ self .locale ] , string_key = string_key )
120115 return string .render (substitutions )
121116
122117 def localize_with_markup (self , string_key : str , substitutions : SubstitutionDict | None = None ) -> Markup :
123118 string = self .find_string (string_key , substitutions )
124119 if string is None :
125- raise LocalizationError (locale = self .locale , string_key = string_key )
120+ raise LocalizationError (locales = [ self .locale ] , string_key = string_key )
126121 return string .render_with_markup (substitutions )
127122
128123
@@ -203,12 +198,12 @@ class StringSegment:
203198
204199
205200class LocalizationError (Exception ):
206- """Raised failing to localize a string, e.g. if it is not found in any fallback locale ."""
201+ """Raised failing to localize a string, e.g. if it is not found in any of the given locales ."""
207202
208- def __init__ (self , locale : str , string_key : str ):
209- self .locale = locale
203+ def __init__ (self , locales : list [ str ] , string_key : str ):
204+ self .locales = locales
210205 self .string_key = string_key
211- super ().__init__ (f"Could not localize string { string_key } for locale { locale } " )
206+ super ().__init__ (f"Could not localize string { string_key } for locales { locales } " )
212207
213208
214209def full_string_key (key : str , * , relative_base : str | None ) -> str :
0 commit comments