Localization & Multi-language Support
What is Localization vs Internationalization?
Section titled “What is Localization vs Internationalization?”- Localization (often abbreviated as l10n) is the process of adapting your application for a specific language or region:
- For example, translating text, adjusting date formats (
04/29/2026in the US vs29/04/2026in France), using the correct currency symbol ($vs€), and so on.
- For example, translating text, adjusting date formats (
- Internationalization (often abbreviated as i18n) is the process of designing your code to support multiple locales in the first place:
- For example, using translation keys instead of hardcoded strings, structuring translation files, and building helper classes that load the right language at runtime.
- In practice, you do both together. You internationalize your application once (build the translation infrastructure), then localize it for each supported language (create the actual translation files).
- Instead of hardcoding text like “Welcome” directly in your views, you use translation keys such as
trans('home.welcome')that display different text depending on the user’s language preference. This means the same view template can serve content in English, French, or any other supported language without duplicating code.
How It Works
Section titled “How It Works”When a user visits your application, the following flow determines which language to display:
- The user visits the application, optionally with a language parameter such as
?lang=fr. - A
LocaleMiddlewaredetects the preferred language based on the URL parameter, a saved session value, or the default locale. - The application loads the appropriate translation file (e.g.,
lang/fr/messages.jsonfor French). - Views use
trans('home.welcome')instead of hardcoded text. - The translation helper returns the French value (“Bienvenue”) from the loaded file.
- The user sees content in their preferred language.
Locale Detection Priority
Section titled “Locale Detection Priority”The middleware checks three sources in order:
- URL parameter:
?lang=fr(the user explicitly selects a language, highest priority) - Session value: a previously saved preference (persists across page navigation)
- Default locale: English (fallback when no parameter or session value exists)
File Organization
Section titled “File Organization”Translation files are organized by locale, with each language in its own folder:
/lang /en messages.json /fr messages.jsonTranslation Keys
Section titled “Translation Keys”Translations use dot notation to organize keys hierarchically inside JSON files:
{ "home": { "title": "Home", "welcome": "Welcome to our store" }, "nav": { "home": "Home", "products": "Products" }}You access these in views with trans('home.welcome') or trans('nav.home').
Key Concepts
Section titled “Key Concepts”Fallback Mechanism
Section titled “Fallback Mechanism”If a translation key is missing in the requested language, the translator automatically falls back to the default language. For example, if products.new_arrival does not exist in the French translation file, the English value is used instead. This ensures your application never displays a broken or missing label.
Placeholders
Section titled “Placeholders”Translations can include placeholders for dynamic values. In the JSON file, placeholders are wrapped in % characters:
{ "user": { "greeting": "Hello, %name%! You have %count% messages." }}When calling the translation function, pass the values as an associative array:
trans('user.greeting', ['%name%' => 'Alice', '%count%' => 3])// Returns: "Hello, Alice! You have 3 messages."Translation Domains
Section titled “Translation Domains”Symfony organizes translations into domains, which act as separate namespaces. In this course, all translations use the default messages domain. This means all keys live in messages.json files. Larger applications might use separate domains (e.g., validators.json, admin.json) to keep translations organized.
Symfony Translation Component
Section titled “Symfony Translation Component”This course uses the Symfony Translation component, a widely adopted PHP library for internationalization. It supports multiple file formats (JSON, YAML, XLIFF, PHP arrays), provides automatic fallback for missing translations, and caches loaded translations for performance. You install it with Composer and configure it through a helper class that you will build in the localization lab.