-
Notifications
You must be signed in to change notification settings - Fork 1.7k
bug: Translation fallback doesn't resolve base locale to regional file (e.g. "da" → "da-DK") #2842
Description
Description
The load_translation method in config.py only falls back from regional to base locale (da-DK → da), but never resolves a base locale to an available regional file (da → da-DK). This means most users with regional translation files never actually see them.
Root Cause
In backend/chainlit/config.py, the fallback logic is:
parent_language = language.split("-")[0] # "da" → "da"
# 1. Try exact match: da.json
# 2. Try parent: da.json ← identical when input has no region!
# 3. Fall back to: en-US.jsonWhen a browser sends da (which is the default for most Danish browsers), steps 1 and 2 both look for da.json. Neither step ever tries da-DK.json, even though that file exists.
Impact
This affects all translations that use regional codes:
| File | Browser sends | Found? |
|---|---|---|
es.json |
es |
Yes |
nl.json |
nl |
Yes |
ja.json |
ja |
Yes |
da-DK.json |
da |
No |
de-DE.json |
de |
No |
fr-FR.json |
fr |
No |
zh-CN.json |
zh |
No |
he-IL.json |
he |
No |
el-GR.json |
el |
No |
Users affected by this silently fall back to en-US with a warning in the logs:
WARNING - chainlit - Translation file for da not found. Using default translation en-US.
In a production deployment, this warning appeared 443 times in 4 hours — once per page load for every Danish user.
Suggested Fix
Add an upward lookup step that scans for {base_locale}-*.json when the exact and parent lookups fail:
def load_translation(self, language: str):
parent_language = language.split("-")[0]
translation_dir = Path(config_translation_dir)
# 1. Exact match (e.g. "da-DK.json")
exact = translation_dir / f"{language}.json"
if is_path_inside(exact, translation_dir) and exact.is_file():
return json.loads(exact.read_text(encoding="utf-8"))
# 2. Parent/base language (e.g. "da.json")
parent = translation_dir / f"{parent_language}.json"
if is_path_inside(parent, translation_dir) and parent.is_file():
logger.warning(f"Translation file for {language} not found. Using parent translation {parent_language}.")
return json.loads(parent.read_text(encoding="utf-8"))
# 3. Regional variant (e.g. "da" → find "da-DK.json")
if language == parent_language:
for candidate in sorted(translation_dir.glob(f"{parent_language}-*.json")):
if is_path_inside(candidate, translation_dir) and candidate.is_file():
variant = candidate.stem
logger.info(f"Translation file for {language} not found. Using regional variant {variant}.")
return json.loads(candidate.read_text(encoding="utf-8"))
# 4. Default fallback
default = translation_dir / f"{DEFAULT_LANGUAGE}.json"
if is_path_inside(default, translation_dir) and default.is_file():
logger.warning(f"Translation file for {language} not found. Using default translation {DEFAULT_LANGUAGE}.")
return json.loads(default.read_text(encoding="utf-8"))
return {}Environment
- Chainlit version: 2.10.0
- Python version: 3.13
- OS: Linux (AKS)
Workaround
Setting language = "da-DK" in config.toml under [UI] forces the specific locale, but this overrides the language for all users, including non-Danish speakers.
Alternatively, deploying a copy of da-DK.json as da.json works but shouldn't be necessary.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status