flarum / flarum/framework

Make the translation fallback locale configurable (currently hardcoded to `en`)

Open
#4,763 2 comments 1 reaction 0 assignees View on GitHub
Dominant language
PHP
Stars
6.7k
Forks
883
Avg merge
15h 16m
Merged PRs (30d)
73

Description

### 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`:

```php
// 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:

1. **Config surface** — a new admin setting (e.g. `fallback_locale`), an `extend.php` extender, or both?
2. **Chain vs. single locale** — support an ordered chain (`['de', 'en']`) or just a single configurable fallback that always terminates in `en`?
3. **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?
4. **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

Contributor guide

Open the contributing guide

Research direction

Start by reading src/Locale/LocaleServiceProvider.php, src/Locale/LocaleManager.php, and src/Frontend/AddTranslations.php to trace the backend and frontend fallback paths. Resolve the proposed configuration surface, fallback-chain behavior, region fallback, and cache invalidation before implementation. Done means the configured fallback is applied consistently to server translations and compiled locale assets, with tests covering the default and configured behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, php, symfony
Domain
backend, frontend, internationalization
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.