skip to content

In Laravel's config/app.php, what do locale, fallback_locale and faker_locale each control, and which environment variables set them?

level: middleimportance: should knowfreq 32%

answer

  1. three keys, three APP_ variables
  2. fallback serves missing group-file lines
  3. faker_locale defaults to en_US
  4. fake() and factories, not translations
  5. config writes skip a built translator

basics

~10 s

locale (APP_LOCALE, default en) is the starting translation locale; fallback_locale (APP_FALLBACK_LOCALE, default en) supplies group-file lines the active locale lacks; faker_locale (APP_FAKER_LOCALE, default en_US) only sets the language of fake() and factory data.

solid answer

~40 s

All three keys sit in the skeleton's `config/app.php`. `locale`, from `APP_LOCALE` with default `en`, is the locale the translator starts every request with and what `App::currentLocale()` returns until something calls `App::setLocale()`. `fallback_locale`, from `APP_FALLBACK_LOCALE` with default `en`, is the second locale the translator tries when a short key is missing in the active one, and whose text and plural rules `trans_choice()` uses in that case; JSON sentence keys never consult it. `faker_locale`, from `APP_FAKER_LOCALE` with default `en_US`, has nothing to do with translation: it selects the Faker locale behind the `fake()` helper and model factories. Change the first two at runtime with `App::setLocale()` and `App::setFallbackLocale()`, not by writing config, because a translator that is already built keeps its own copy.

code

ini · 3 lines
ini
APP_LOCALE=pl
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=pl_PL

go deeper

for a junior

Recall the three keys in config/app.php, their APP_ environment variables and their defaults: en, en and en_US.

for a middle

Explain what each key feeds: the translator's start locale, its second lookup for short keys, and the Faker generator, plus why the setters beat config writes.

for a senior

Spot configuration bugs in production: fallback pointing at an incomplete locale, JSON gaps the fallback cannot fill, env() calls that break under config:cache.

for a principal

Choose the fallback language for a multi-region product, weighing the most complete translation against the language most users can read.

## The three keys at a glance | Key | Env variable | Skeleton default | Used by | |---|---|---|---| | `locale` | `APP_LOCALE` | `en` | the translator's starting locale, `App::currentLocale()` | | `fallback_locale` | `APP_FALLBACK_LOCALE` | `en` | the translator's second lookup for short keys | | `faker_locale` | `APP_FAKER_LOCALE` | `en_US` | the `fake()` helper and model factories | The skeleton writes each as `env('APP_...', default)` inside `config/app.php`, so the values are baked in when you run `php artisan config:cache`. ## locale The **default locale** is read when the translator singleton is first built: its constructor receives `app.locale`. From then on the translator holds its own copy, which is why `App::setLocale()` exists: it updates the config value and the translator together and fires `LocaleUpdated`. ## fallback_locale The **fallback locale** is handed to the translator with `setFallback()` when it is built. It matters in three places: 1. A short key such as `hr.leave` missing from `lang/pl/hr.php` is looked up in the fallback locale's `lang/en/hr.php` before the translator gives up. 2. `trans_choice()` uses the fallback locale's line *and* its plural rules when the active locale lacks the key. 3. It is **not** consulted for JSON sentence keys: a sentence missing from `lang/pl.json` returns the sentence itself. `App::setFallbackLocale('de')` changes it at runtime, updating config and translator together. Setting the fallback to the same value as the locale simply removes the second lookup. ## faker_locale The **Faker locale** controls generated test and seed data only. The `fake()` helper reads `app.faker_locale` and caches one Faker generator per locale in the container; the factory layer and the `WithFaker` test trait read the same key. A Polish HR portal whose `faker_locale` is still `en_US` gets English-looking names and addresses in its seeded data, whatever `APP_LOCALE` says. `fake('pl_PL')` asks for a specific locale in one call. ## Changing values at runtime - `App::setLocale()` and `App::setFallbackLocale()` update both config and the translator. - `config(['app.locale' => 'de'])` updates only config. If the translator has not been resolved yet in this process it will pick the new value up when it is built; if it already exists it keeps the old locale, so `__()` output does not change. That order dependency is why the setters are the only safe route. - `env('APP_LOCALE')` in application code returns `null` after `config:cache`; read `config('app.locale')` or `App::currentLocale()` instead. ## Pitfalls - Treating `faker_locale` as a translation setting, or `locale` as a data-generation setting. - Expecting `fallback_locale` to fill gaps in JSON translation files. - Leaving `APP_FALLBACK_LOCALE` pointing at a locale with incomplete files, so the fallback itself misses and raw keys appear. ## A worked example: the HR portal's settings A portal whose head office works in Polish, with English as the common second language, might use: - `APP_LOCALE=pl`, so anonymous pages and anything that never sets a locale speak Polish; - `APP_FALLBACK_LOCALE=en`, because the English files are the ones every feature ships with first, so a missing Polish short key shows English rather than a raw key; - `APP_FAKER_LOCALE=pl_PL`, so seeded demo employees have Polish names and addresses that exercise the layouts the real users will see. Choosing the fallback is a product decision: the language with the **most complete** files is usually safer than the language most users speak, because a fallback that itself misses produces raw keys. ## Checking the configuration 1. `php artisan config:show app` prints the resolved values of all three keys. 2. `php artisan about` shows the `Locale` value among its environment details. 3. After changing `.env` on a server that caches config, rebuild the cache; until then the old values stay in effect.

  • Does fallback_locale help when a sentence is missing from lang/pl.json?
    No. The translator loads JSON only for the active locale; on a miss it tries group-file parsing, which does use the fallback, but a sentence key matches no group file, so the sentence itself is returned. The fallback only rescues short keys stored in PHP group files.
  • Why might config(['app.locale' => 'de']) in a service provider appear to work in one app and not in another?
    The translator is a deferred singleton that copies `app.locale` when first built. If nothing resolved it before the config write, the new value is picked up; if something already translated a string, the translator keeps the old locale. `App::setLocale()` avoids the order dependency.

saying these in an interview costs you the question

  • faker_locale sets the language of validation messages in tests
  • fallback_locale also fills sentences missing from JSON translation files
  • Writing config(['app.locale' => 'de']) always switches __() output
  • The default fallback_locale is null, so there is no second lookup
  • APP_FAKER_LOCALE defaults to the same value as APP_LOCALE