Internationalization with Angular v10
Tags: angular, i18n, internationalization
Published: 2020-06-25 12:36:02

# Goal
To render and deploy our Angular app in 3 languages:
1. English (will be generated by default, no setup required)
2. French
3. Spanish

# Setup
Assuming that you already have an Angular project, follow these steps:
* Add localisation package with `ng add @angular/localize`
* Add the following scripts to `package.json` :
```json
  "scripts": {
    ...
    "start": "ng serve",
    "build": "ng build --prod",
    "extract": "ng xi18n --output-path=src/locale",
    "start:fr": "npm start -- --configuration=fr --port 4201",
    "start:es": "npm start -- --configuration=es --port 4202",
    "build:i18n": "npm run build -- --localize"
  },
```
* Add the `i18n` attribute with `[title] | [description] @@[tag]` to all hardcoded strings which you'd like to be translated, like this :
```html
  <h1 i18n="Profile page title | A title for the Profile page @@profilePageTitle">
    Profile
  </h1>
```
* Run `npm run extract` to extract the language translation file at `src/locale/messages.xlf`. It will look like this :
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="en-US" datatype="plaintext" original="ng2.template">
    <body>
      <trans-unit id="profilePageTitle" datatype="html">
        <source>Profile</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/profile-settings/profile-settings.component.html</context>
          <context context-type="linenumber">4</context>
        </context-group>
        <note priority="1" from="description"> A title for the Profile page </note>
        <note priority="1" from="meaning">Profile page title </note>
      </trans-unit>
    </body>
  </file>
</xliff>

```
* Create a copy of this file and rename these 2 as :
  1. `messages.fr.xlf` (for French translations)
  2. `messages.es.xlf` (for Spanish translations)
* Modify the `projects` section `angular.json` in the following way to build and serve the different language builds:
```json
  "projects": {
    "<your-project-name>": {
      ...
      "architect": {
        "build": {
          ...
          "configurations": {
            ...
            "fr": {
              "localize": ["fr"]
            },
            "es": {
              "localize": ["es"]
            }
          }
        },
        "serve": {
          ...
          "configurations": {
            ...
            "fr": {
              "browserTarget": "<your-project-name>:build:fr"
            },
            "es": {
              "browserTarget": "<your-project-name>:build:es"
            }
          }
        },
        ...
      },
      "i18n": {
        "locales": {
          "fr": "src/locale/messages.fr.xlf",
          "es": "src/locale/messages.es.xlf"
        }
      }
    }
  },
```
* Add translations of the targeted word "Profile" in the translation files in their respective languages with the `<target>` tag :
```xml
        <!-- messages.fr.xlf -->
        <source>Profile</source>
        <target>Profil</target>

        <!-- messages.es.xlf -->
        <source>Profile</source>
        <target>Perfil</target>
```
* Check if the translations are working by running
  1. `npm run start` or `ng serve` for English (default)
  2. `npm run start:fr` or `ng serve -c=fr` for French
  3. `npm run start:es` or `ng serve -c=es` for Spanish
* Build the app for all languages by running `npm run build:i18n` or `ng build --prod --localize`. It will create 3 build folders under `dist/<your-project-name>` :
  1. en-US
  2. fr
  3. es
* Deploy folder `dist/<your-project-name>` to any static hosting services (like Firebase). Your sites will be available at
  1. `https://your.site/en-US/` (English)
  2. `https://your.site/fr/` (French)
  3. `https://your.site/es/` (Spanish)

# Switch between the sites from inside the app
Create a `switch-language` component with a dropdown listing all the languages offered. On selection of any language, redirect the user to the corresponding site.
Additionally, hide the component if you're in `development` mode.
```typescript
import { Component, OnInit, isDevMode } from '@angular/core'

@Component({
  selector: 'app-switch-language',
  template: `
    <select
      *ngIf="!isDev"
      [(ngModel)]="siteLocale"
      #language
      (change)="onChange(language.value)"
    >
      <option *ngFor="let lang of languageList" [value]="lang.code">
        {{ lang.label }}
      </option>
    </select>
  `,
})
export class SwitchLanguageComponent implements OnInit {
  isDev = isDevMode()
  siteLanguage: string
  siteLocale: string
  languageList = [
    { code: 'en-US', label: 'English' },
    { code: 'fr', label: 'French' },
    { code: 'es', label: 'Spanish' },
  ]

  ngOnInit() {
    this.siteLocale = window.location.pathname.split('/')[1]
    this.siteLanguage = this.languageList.find(
      (f) => f.code === this.siteLocale
    )?.label
    if (!this.siteLanguage) {
      this.onChange(this.languageList[0].code)
    }
  }

  onChange(selectedLangCode: string) {
    window.location.href = `/${selectedLangCode}`
  }
}

```

# Repository
{% github batbrain9392/blueface-assignment %}