skip to content

In Angular i18n, an agency returned messages.de.xlf but the German build still shows some English; how are missing translations handled, and how do you catch them before release?

level: seniorimportance: should knowfreq 30%

answer

  1. the build falls back rather than failing
  2. a three-level build option
  3. warning is the default
  4. a target-less unit behaves differently
  5. diff the source file against each translation

basics

~20 s

An untranslated message is built with its source text; i18nMissingTranslation makes that a warning (default), an error or ignored. Units without a target fall back to source with only a parse warning, so CI also needs a diff check.

solid answer

~40 s

When the merge step finds no translation for a message ID, it inlines the **source text** and reports it. The application builder's `i18nMissingTranslation` option sets the level: `warning` by default, `error` to fail the build, or `ignore`. So English leaking into a German build usually means one of three things: messages added or reworded after the file was sent (new IDs), IDs edited by a tool or translator, or units the agency left **without a `<target>`**. The last case is the subtle one: the XLIFF parser falls back to the unit's `<source>` and only warns `Missing <target> element`, so `i18nMissingTranslation: "error"` does not catch it. Before release, set the option to `error` in the production configuration, treat target-less units as failures, and diff the freshly extracted source file against each translation file.

code

json · 22 lines
json
{
  "projects": {
    "shop": {
      "i18n": {
        "sourceLocale": "en-US",
        "locales": {
          "de": "src/locale/messages.de.xlf",
          "ja": "src/locale/messages.ja.xlf"
        }
      },
      "architect": {
        "build": {
          "builder": "@angular/build:application",
          "options": { "localize": true },
          "configurations": {
            "production": { "i18nMissingTranslation": "error" }
          }
        }
      }
    }
  }
}

go deeper

for a junior

Recall that an untranslated message shows its source text, and that i18nMissingTranslation can be warning, error or ignore.

for a middle

Explain the difference between an ID absent from the file and a unit that has no target, and which one the option reports.

for a senior

Design the release gate: error in production, treating target-less units as failures, and diffing re-extracted source IDs against every locale's file.

for a principal

Decide how strict the gate is per locale and release, balancing shipping speed against untranslated copy, and agree turnaround terms with the vendor.

## The scenario A shop ships English, German and Japanese builds. The translation agency returns `messages.de.xlf`, the team merges it, and after release the checkout page shows a mix of German and English. To diagnose this you need to know exactly how Angular's merge step treats a missing translation. ## How merging looks up a translation At build time each marked message is looked up **by ID** in the locale's translation data. Three outcomes are possible: 1. **A target exists for the ID.** It is inlined, with placeholders substituted. 2. **No unit has the ID.** This is a **missing translation**: the build inlines the source text and records a diagnostic that names the message ID and its source text. 3. **A unit has the ID but no `<target>`.** The XLIFF parsers (1.2 and 2.0) warn `Missing <target> element` and **use the `<source>` as the translation**. From the merge step's point of view the message is translated, with English text. Case 3 happens naturally with the documented workflow, because every translation file starts as a copy of the source file with sources and no targets. ## The `i18nMissingTranslation` option The application builder decides what a missing translation (case 2) does: | Value | Effect | | --- | --- | | `warning` (default) | Build succeeds, a warning is logged, the source text is used | | `error` | The build fails | | `ignore` | Build succeeds silently with source text | ```json { "configurations": { "production": { "i18nMissingTranslation": "error" } } } ``` An `error` in the production configuration is the usual gate. Keep `warning` in development, where untranslated new strings are expected. ## Why English still leaks with `error` set - **Target-less units.** Case 3 is not a missing translation, so the option never fires; the only signal is a parse warning per unit. - **Targets copied from source.** A vendor tool may pre-fill `<target>` with the English source. The build cannot tell that from a real translation. ## A CI check that closes the gaps 1. Run `ng extract-i18n` on the release commit and parse the new source file. 2. For each locale's translation file, compute **IDs in the source but not in the translation** (new or reworded messages), **IDs in the translation but not in the source** (orphans to delete), and **units with no target, or a target identical to the source** where the language requires a difference. 3. Fail the pipeline on the first and third lists; report the second. 4. Build with `i18nMissingTranslation: "error"` as a second line of defence. 5. Treat the build's `Missing <target> element` warnings as errors in CI output. ## Other diagnostics the merge step reports - **Duplicate translations.** A locale can list several translation files; when two supply the same ID, the later one wins and `i18nDuplicateTranslation` (warning by default) reports it. - **Placeholder mismatch.** A target referencing a placeholder the message does not have is reported as an **error**, whatever `i18nMissingTranslation` says. - **Locale mismatch.** A file whose declared target language differs from the configured locale produces a warning. ## Summary - Missing ID: source text plus a diagnostic whose level `i18nMissingTranslation` sets, warning by default. - Missing `<target>`: source text plus only a parse warning, so the option does not catch it. - Release safety comes from `error` in production plus a diff-based CI check.

  • Why does a freshly copied Angular translation file not trigger missing-translation errors even though nothing is translated?
    Every unit in the copy has its ID and a `<source>` but no `<target>`. The XLIFF parser warns `Missing <target> element` and falls back to the source, so each message counts as translated with English text. `i18nMissingTranslation` only fires when the ID is absent altogether.
  • A locale in angular.json lists two translation files that both translate the same ID. Which wins?
    The files are merged in order, so the later file's translation overwrites the earlier one. The builder reports a duplicate-translation diagnostic whose level `i18nDuplicateTranslation` controls, a warning by default.

saying these in an interview costs you the question

  • A missing translation fails the Angular build by default
  • Setting i18nMissingTranslation to error catches every untranslated unit
  • Missing translations render as blank text
  • The agency file is complete if the build shows no errors
  • Only runtime testing can find untranslated messages