‹ Prev | Next ›

Localization

AI makes translating an app cheap now. Generating a full, accurate translation set for a language takes minutes, so the hard part is gone and only the plumbing is left. This starter handles that plumbing, so you drop in a lang folder and it works. A sample Canadian French translation ships wired all the way through, so it is a real working feature rather than an empty scaffold.

Two locale systems

There are two locales in play and they are deliberately kept separate.

The user locale is a frontend preference. It is stored on the user, returned in the API, and uses the web tag format like en-US. The UI reads it for its language toggle, date, and number formatting.

Laravel's translation locale is what __() resolves against, keyed to the folders under lang. PHP and Laravel favor the underscore style, so folders are en, fr_CA.

They do not need to match and should not be forced to. The frontend keeps en-US, Laravel keeps fr_CA. The only point they meet is converting a stored user preference into a translation locale, handled in one place on the user model.

Request locale

Request responses use the client's Accept-Language header. The middleware resolves whatever the frontend sends to the closest available translation, falling back to the base language when a region is not translated.

Since it reads the header, the frontend decides what gets sent, which depends on how the frontend is built. If the user has a saved preference it loads onto the frontend first and gets sent back on each request. Slightly roundabout, but it keeps the server reading one source instead of reconciling a header against a stored value per request.

Storing the locale on the user

The header only covers live requests. Queued emails, notifications, and anything running in a background job have no header to read. The stored user locale covers those, so every part of the app can use the user's language and stay consistent, not just the screens they are on.

It also follows the person rather than the device. Logging in on a new device is already in their language.

© Websanova 2026 About Privacy