angular-localize

The preset for Angular's built-in i18n with @angular/localize. It reads angular.json, i18n attributes and $localize, with custom or generated ids, and the XLIFF, XMB, JSON and ARB translation files.

The angular-localize preset supports Angular's built-in i18n with @angular/localize.

Detection

The preset applies when the project depends on @angular/localize and angular.json has an i18n block. Libraries such as ng-bootstrap depend on @angular/localize without translating anything, so the dependency alone is not enough.

x18n.config.ts
import { defineConfig } from '@x18n/core'

export default defineConfig({
  presets: ['angular-localize'],
})

Locale files

The preset reads the i18n block of every project in angular.json:

  • sourceLocale, as a string or as { "code": "..." }, is the source locale. Angular's default is en-US.
  • Each entry of locales is a translation file, as a path, a list of paths or { "translation": ... }.
  • The source file is the one ng extract-i18n writes: messages.xlf, messages.xmb, messages.json or messages.arb in the outputPath of the extract-i18n target, after its format and outFile options.
angular.json
{
  "projects": {
    "app": {
      "i18n": {
        "sourceLocale": "en-GB",
        "locales": {
          "tr": "src/locale/messages.tr.xlf"
        }
      },
      "architect": {
        "extract-i18n": {
          "options": { "outputPath": "src/locale" }
        }
      }
    }
  }
}

Every format of ng extract-i18n is supported:

FormatSource fileTranslation files
XLIFF 1.2 (xlf, the default)messages.xlfmessages.tr.xlf with <target> elements
XLIFF 2.0 (xlf2)messages.xlfmessages.tr.xlf with <target> elements
XMB (xmb)messages.xmbmessages.tr.xtb
JSON (json)messages.jsonmessages.tr.json
ARB (arb)messages.arbmessages.tr.arb

An XLIFF file with a target language, or with a <target>, is a translation file: x18n reads and writes its targets. A new target keeps the placeholder markup of its <source>, so equiv-text, disp and type stay. JSON files hold their messages in translations, and the @@locale and @id entries of ARB files are metadata. Keys are flat: the id home.title is one key.

x18n does not create a translation file that is missing. As in Angular's guide, create it by copying the source file, then set the target language: target-language="tr" on <file> in XLIFF 1.2, trgLang="tr" on <xliff> in XLIFF 2.0, "locale": "tr" in JSON or "@@locale": "tr" in ARB.

Supported syntax

In templates, the i18n attribute and i18n-* attributes, with an optional meaning and description:

src/app/home.html
<h1 i18n="@@home.title">Hello</h1>
<p i18n="site intro|Shown on the home page">Welcome, {{ name }}!</p>
<a title="Blog" i18n-title>Blog</a>

In TS and JS files, $localize tagged templates, and the inline template of a component:

src/app/app.routes.ts
const title = $localize`:@@title.projects:Projects`
const greeting = $localize`Hi ${name}:userName:!`

A message with a custom id (@@home.title) uses it. A message without one gets the id Angular computes from its text and meaning, and x18n computes the same: the <p> above is 8889534073701065911. ICU expressions, nested elements, @if, @for and @switch blocks and custom placeholder names ({{ count // i18n(ph="count") }}) count. An ICU inside text is a message of its own, as Angular extracts it.

A generated id changes with the text, so renaming such a key in x18n does not change the template. Custom ids are easier to manage.

Placeholders

Angular placeholders: {$INTERPOLATION}, {$START_LINK}, {$CLOSE_LINK}. XLIFF and XMB placeholders read the same way.