Background
Flarum's translation fallback chain is hardcoded to English. When a string is missing in the active locale, the Symfony translator falls back to en:
// src/Locale/LocaleServiceProvider.php
$translator->setFallbackLocales(['en']);
This is the single source of fallback for both the backend (Flarum\Locale\Translator::getCatalogue walks the fallback catalogue) and the frontend (Flarum\Frontend\AddTranslations pre-flattens the chain into the locale JS bundle via array_replace). LocaleManager itself holds no fallback config — it delegates entirely to this Symfony translator.
Problem
Forums whose primary language is not English get a degraded experience when a translation is incomplete: missing keys surface in English rather than in a language closer to their audience. For example, a German-language community using a regional/derived locale (or a partially-translated extension) would prefer to fall back to standard German before English, not jump straight to English.
There is already a precedent for richer fallback in core: LocaleManager::getJsFiles()/getCssFiles() strip the region suffix (e.g. de-formal → de) for asset files — but this one-level, assets-only fallback does not apply to translation strings, which always go straight to en.
Proposal
Make the fallback locale configurable, with en as the default (no behavior change unless configured).
Open questions for discussion:
- Config surface — a new admin setting (e.g.
fallback_locale), an extend.php extender, or both?
- Chain vs. single locale — support an ordered chain (
['de', 'en']) or just a single configurable fallback that always terminates in en?
- Automatic region fallback — should
de-formal automatically fall back to de then en for translation strings (mirroring the existing asset behavior), independent of an explicit setting?
- Cache invalidation — the fallback is baked into the compiled frontend locale assets, so changing the setting must trigger an asset recompile / locale cache clear.
Affected code
src/Locale/LocaleServiceProvider.php — setFallbackLocales(['en'])
src/Locale/LocaleManager.php — region-stripping asset fallback
src/Frontend/AddTranslations.php — server-side flattening of the chain
Background
Flarum's translation fallback chain is hardcoded to English. When a string is missing in the active locale, the Symfony translator falls back to
en:This is the single source of fallback for both the backend (
Flarum\Locale\Translator::getCataloguewalks the fallback catalogue) and the frontend (Flarum\Frontend\AddTranslationspre-flattens the chain into the locale JS bundle viaarray_replace).LocaleManageritself holds no fallback config — it delegates entirely to this Symfony translator.Problem
Forums whose primary language is not English get a degraded experience when a translation is incomplete: missing keys surface in English rather than in a language closer to their audience. For example, a German-language community using a regional/derived locale (or a partially-translated extension) would prefer to fall back to standard German before English, not jump straight to English.
There is already a precedent for richer fallback in core:
LocaleManager::getJsFiles()/getCssFiles()strip the region suffix (e.g.de-formal→de) for asset files — but this one-level, assets-only fallback does not apply to translation strings, which always go straight toen.Proposal
Make the fallback locale configurable, with
enas the default (no behavior change unless configured).Open questions for discussion:
fallback_locale), anextend.phpextender, or both?['de', 'en']) or just a single configurable fallback that always terminates inen?de-formalautomatically fall back todethenenfor translation strings (mirroring the existing asset behavior), independent of an explicit setting?Affected code
src/Locale/LocaleServiceProvider.php—setFallbackLocales(['en'])src/Locale/LocaleManager.php— region-stripping asset fallbacksrc/Frontend/AddTranslations.php— server-side flattening of the chain