Building a Multilingual Application
This guide walks you through adding i18n support to your Angular application. You’ll learn how to mark text for translation, extract messages, create translation files for multiple languages, and build your app for all locales. File locations and code examples are clearly marked.
Step 1: Mark Text in Templates with i18n
Section titled “Step 1: Mark Text in Templates with i18n”Add the i18n attribute to any HTML element whose text content you want to translate. You can also provide a description and a custom ID for stable references.
File to edit: src/app/app.component.html (or any component template)
<!-- Simple text --><h1 i18n>Welcome to My App</h1>
<!-- With description and custom ID --><p i18n="A friendly greeting|@@greetingMessage">Hello, user!</p>
<!-- For attributes like title or alt --><img [src]="logo" i18n-title title="Company Logo" />
<!-- Pluralization and ICU expressions --><div i18n>{count, plural, =0 {No items} =1 {One item} other {{{count}} items}}</div>Explanation:
- The
i18nattribute marks the element for translation. - The optional
@@customIdgives the translation a stable identifier (useful when the source text changes slightly). - For attributes, use
i18n-attributeName(e.g.,i18n-title). - Angular supports pluralization and ICU expressions directly in templates.
Step 2: Extract Translations to a Source File
Section titled “Step 2: Extract Translations to a Source File”Run the Angular extractor to create a translation source file containing all marked texts.
Command (run from project root):
ng extract-i18n --output-path src/localeWhere the file is created:
This creates a folder src/locale/ (if it doesn’t exist) and places the file messages.xlf inside it. You can change the format using --format (e.g., --format=xlf2 or --format=json).
Expected output:
src/ locale/ messages.xlf # Source language (usually English)Explanation:
- The
ng extract-i18ncommand scans all templates and collects texts marked withi18n. - The output path
src/localeis where you’ll store all translation files. - You can also specify the format with
--format=xlf(default),--format=xlf2, or--format=json.
Step 3: Create Locale-Specific Translation Files
Section titled “Step 3: Create Locale-Specific Translation Files”For each language you want to support, create a copy of the source file and translate its content.
File structure example (after adding French and Spanish):
src/ locale/ messages.xlf (source) messages.fr.xlf (French translations) messages.es.xlf (Spanish translations)How to do it:
- Copy
messages.xlfand rename it to include the locale code, e.g.,messages.fr.xlf. - Open the new file and translate each
<target>element. In XLIFF format, each<trans-unit>looks like:
<trans-unit id="greetingMessage" datatype="html"> <source>Hello, user!</source> <target>Bonjour, utilisateur !</target> <note priority="1" from="description">A friendly greeting</note></trans-unit>Explanation:
- The
<source>element contains the original text (usually English). - You fill the
<target>element with the translated text for that locale. - The
idattribute must match the@@customIdyou used, or a generated ID. - Repeat for every locale you support.
Step 4: Configure Angular to Support Multiple Locales
Section titled “Step 4: Configure Angular to Support Multiple Locales”Edit angular.json to tell Angular which locales you support and where to find the translation files.
Locate the projects -> your-project-name -> architect section.
Add or modify the build and serve configurations as shown below.
"projects": { "your-project-name": { "architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist/your-project-name", "index": "src/index.html", "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.app.json", "assets": ["src/favicon.ico", "src/assets"], "styles": ["src/styles.css"], "scripts": [] }, "configurations": { "production": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ], "optimization": true, "outputHashing": "all" }, "fr": { "localize": ["fr"] }, "es": { "localize": ["es"] } } }, "serve": { "builder": "@angular-devkit/build-angular:dev-server", "configurations": { "production": { "browserTarget": "your-project-name:build:production" }, "fr": { "browserTarget": "your-project-name:build:fr" }, "es": { "browserTarget": "your-project-name:build:es" } } } } }}Explanation:
- The
localizeoption in each configuration tells Angular to build for that specific locale. - You can also set the default locale and supported locales in
angular.jsonunderprojects -> your-project-name -> i18n.
Add i18n project configuration (optional but recommended):
"i18n": { "sourceLocale": "en", "locales": { "fr": "src/locale/messages.fr.xlf", "es": "src/locale/messages.es.xlf" }}This tells Angular where to find each translation file.
Step 5: Build the App for All Locales
Section titled “Step 5: Build the App for All Locales”Now you can build your application for each configured locale.
Build all locales at once:
ng build --localizeThis command generates a separate folder for each locale inside the output path.
For example, if outputPath is dist/my-app, you’ll get:
dist/ my-app/ en/ (if English is the source locale) fr/ es/Build a specific locale:
ng build --configuration=frServe a specific locale during development:
ng serve --configuration=frExplanation:
--localizebuilds all locales defined in the configuration.- Using
--configurationwith a locale name builds only that locale. - The output folders are named after the locale codes.
Step 6: (Optional) Runtime Locale Switching
Section titled “Step 6: (Optional) Runtime Locale Switching”If you prefer to switch languages without rebuilding, you can use runtime translation with @angular/localize. This approach loads translation files on demand.
- Ensure
@angular/localizeis installed (it is included by default in Angular projects). - Import
$localizein yourpolyfills.ts:
import "@angular/localize/init";- Load translation files at runtime (e.g., using HTTP) and set the locale using
LOCALE_IDprovider. - Use Angular’s
i18npipes and directives as usual.
Note: Runtime switching requires additional setup and is not covered in detail here. Refer to the Angular i18n documentation for advanced scenarios.
Summary of Key File Locations
Section titled “Summary of Key File Locations”| File / Folder | Purpose |
|---|---|
src/app/**/*.html | Templates containing i18n markers |
src/locale/messages.xlf | Extracted source translations |
src/locale/messages.fr.xlf | French translation file (create one per locale) |
angular.json | Project configuration with locale settings and build targets |
dist/your-app/ | Output folder – contains locale subfolders after building with --localize |
Example: HTML with Multiple Languages (Marked for Translation)
Section titled “Example: HTML with Multiple Languages (Marked for Translation)”Here’s a complete example showing different i18n features:
<!-- src/app/example.component.html --><h1 i18n="@@pageTitle">Welcome to our store</h1>
<p i18n="Product count|@@productCount">{productCount, plural, =0 {No products available} =1 {One product} other {{{productCount}} products}}</p>
<button i18n="Button label|@@addToCart">Add to cart</button>
<img [src]="imageUrl" i18n-alt alt="Product image" />Explanation:
- Custom IDs (
@@pageTitle) keep translations stable even if the English text changes slightly. - Plural rules are defined using ICU syntax.
- Attributes like
altare translated withi18n-alt.
Now you have a complete i18n setup for your Angular application. For further details, refer to the official Angular i18n guide.