Lingvit
  • Angular
  • i18n
  • Guide

Angular translation: ngx-translate vs automatic translation (2026)

8 min read

Angular ships two approaches to i18n — a compile-time framework built into the platform and a popular runtime library — plus the option of DOM-based automatic translation that requires no code changes at all. Here is how each one works, when it fits, and how to choose.

Angular's two built-in i18n approaches

Angular has its own i18n framework, @angular/localize, which uses XLIFF files and compile-time translation. The key characteristic: you run a separate build per locale. Each language produces its own optimised bundle with translations baked in at build time — the fastest possible runtime because there is no translation lookup overhead in the browser.

The popular third-party alternative is @ngx-translate/core, which works at runtime. You ship one bundle and load locale JSON files on startup. Users switching languages get the new strings without a page reload.

Supporting data for Angular Translation: ngx-translate vs Automatic Translation (2026), table 1 of 2
ApproachWhen translations applyBundles per language
@angular/localizeBuild timeOne per locale
@ngx-translate/coreRuntime (startup)One shared bundle
Automatic translationRuntime (DOM)One shared bundle

Scroll horizontally to view every column.

ngx-translate in practice

@ngx-translate/core is the most widely used Angular i18n library outside of the built-in framework. The core pattern involves three pieces:

  • TranslateModule — imported into every Angular module (or standalone component) that needs translations. Provides the pipe and directive.
  • TranslateService — injected into components that need to switch language programmatically or access translations in TypeScript.
  • translate pipe — used in templates: {{ "HELLO" | translate }}. Reactive: updates automatically when the active language changes.
  • HttpLoader — the default loader fetches /assets/i18n/fr.json on language switch. You maintain one JSON file per locale.

The ecosystem is mature: community packages handle ICU-style plurals, lazy-loaded translation modules, and server-side rendering. Most Angular teams that started projects before Angular 13 are on ngx-translate.

The Angular i18n cost

Both built-in approaches carry a maintenance overhead that is easy to underestimate at the start of a project.

@angular/localize: one CI build per locale

A separate build per language is fast for visitors but expensive in CI. At 5 languages, build time and artifact storage roughly quintuples. At 10+ languages — a common target for global products — the matrix becomes a real infrastructure problem: longer pipelines, more storage, more complex deployment.

ngx-translate: locale JSON files to maintain

Every string in the app needs a key in every locale JSON file. As the app grows, keeping files in sync becomes a source of bugs: missing keys fall back silently, stale translations ship without warning, and type-safe key management requires additional tooling to enforce.

Both: translation files are a moving target

UI copy changes frequently during product development. Every string change means updating XLIFF or JSON files, re-extracting keys, and coordinating with translators or a translation management system. For teams without a dedicated localization workflow, this overhead accumulates quickly.

When Angular's i18n tooling is the right call

The built-in Angular i18n stack genuinely excels in specific contexts:

  • Enterprise apps with a dedicated localization team. If you have professional translators, a TMS, and a review workflow, XLIFF extraction plugs directly into those processes.
  • Compliance-requiring human-approved translations. Financial, legal, or medical apps that must not ship unreviewed copy benefit from the explicit translation approval step that XLIFF workflows enforce.
  • Heavy ICU message format usage. Plural and select rules (e.g., “{count, plural, one {1 result} other {# results}}”) are first-class citizens in @angular/localize and well-supported in ngx-translate with an ICU plugin.
  • Build-time optimisation per locale is required. If bundle size is critical and each market has genuinely different content (not just translated strings), per-locale builds allow tree-shaking unused locale-specific code.

When automatic translation wins

DOM-based automatic translation — adding a script tag to the Angular app's host page — skips the translation pipeline entirely. There are clear scenarios where this is the better choice:

  • Existing Angular app adding multilingual without rebuilding. A working app with no i18n investment can become multilingual today without touching a single component.
  • Startup teams without i18n engineers. Setting up ngx-translate or @angular/localize correctly takes time. A script tag can reduce integration work, but setup time varies by app.
  • SaaS dashboards with rapidly changing UI. When the UI copy changes weekly, maintaining translation files becomes a full-time job. Automatic translation keeps up with the DOM without any file updates.
  • Time to market matters. Reaching French, German, Spanish, and Japanese users in a day — not a quarter — is a real competitive advantage for many products.

How Lingvit works with Angular

Lingvit is added to an Angular app via a single script tag in src/index.html before the closing </body> tag.

Angular's change detection updates the DOM as components re-render. Lingvit uses a MutationObserver to detect those DOM mutations and translate new content as it appears — this works correctly with both zone.js-based change detection and the newer signal-based reactivity introduced in Angular 16+.

  • Angular 15+ Standalone Components

    Works without modification. Standalone components render to the same DOM; MutationObserver captures all updates regardless of whether the app uses NgModule or standalone architecture.

  • Angular Universal / SSR

    Server-side rendering is supported. The script tag is added to the server-rendered HTML template. After hydration, MutationObserver handles any client-side DOM updates from Angular's router or component re-renders.

  • Older NgModule pattern

    Apps on Angular 12 and earlier using NgModules work identically. The script tag is host-page level — it has no dependency on the Angular version or module system inside the app.

Setup comparison

Supporting data for Angular Translation: ngx-translate vs Automatic Translation (2026), table 2 of 2
Step@angular/localizengx-translateLingvit
Installng add @angular/localizeInstall package, configure TranslateModule—
Mark stringsAdd i18n attribute to every elementWrap every string with translate pipe—
Translation filesExtract XLIFF, fill per localeWrite JSON per locale—
CI pipelineBuild matrix per localeSingle buildSingle build
Add languagesNew build per localeNew JSON fileDashboard toggle
Script tag in index.htmlNot neededNot neededOne tag before </body>

Scroll horizontally to view every column.

Frequently asked questions

Does Lingvit work with Angular SSR / Angular Universal?

Yes. Add the Lingvit script tag to the HTML template served by the server (typically src/index.html or the Express server template). The widget initialises after Angular hydrates the page on the client side, and MutationObserver handles subsequent DOM updates from Angular's router and component re-renders.

Does it work with Angular Material components?

Yes. Angular Material renders standard DOM elements — MatButton, MatInput, MatTable, and all other components produce normal HTML that MutationObserver observes. Tooltips and overlays that attach to the document body are also captured.

What about Nx monorepos with multiple Angular apps?

Each Angular app in an Nx monorepo is a separate deployable with its own index.html. Add the Lingvit script tag to each app's index.html independently. You can use the same Lingvit project for apps on the same domain, or separate projects per app — the dashboard lets you manage both configurations.