Website translation

Angular i18n Build-Time vs Runtime Explained

Angular i18n Build-Time vs Runtime Explained
Updated on
June 22, 2026

Internationalization in Angular can follow two different models – build-time or runtime. The official approach uses @angular/localize, which generates a separate build for each language. This setup is stable and fast at runtime, but it requires planning for multiple deployments and no in-app language switching.

To implement it, you mark text in templates and TypeScript, extract translations into files, then build one version of the app per locale. Each language is served from its own URL, so users switch languages through navigation rather than a toggle inside the app.

If you need dynamic switching without reloads, runtime libraries handle that instead. Popular options include ngx-translate and angular-i18next. These load translations on demand and update the UI instantly, with different trade-offs around setup, performance, and SSR support.

In this article, we explain how the built-in Angular internationlization (i18n) workflow works, how to deploy it, and when a runtime library is a better fit.

How @angular/localize works

Angular’s built-in internationalization uses a build-time workflow. You prepare translations ahead of deployment, then ship one compiled version of the app per language.

There’s no runtime language switching, so the setup focuses on extraction and build configuration.

Let’s go over the full workflow:

  1. Mark text for translation in templates and TypeScript. Use the i18n attribute for HTML content and attributes, and use $localize in TypeScript so strings are included in the same extraction process.
  2. Extract messages into a translation file using the Angular CLI. This generates an XLIFF file by default, with options for other formats based on your setup, containing message IDs and source text.
  3. Translate the extracted file and keep identifiers stable. Add custom IDs where needed so updates to source text don’t break existing translations or cause silent mismatches.
  4. Build and deploy one version of the app per locale. Configure locales in angular.json, then generate language-specific bundles that are served from separate routes or domains.

Pluralization uses ICU expressions. You define cases such as =0, =1, or other, and Angular selects the correct form based on the active locale. Languages differ in how many forms they require, so plan message structure early.

Nested ICU expressions follow the same pattern but increase complexity, so keep them readable and test across locales.

Building and deploying multi-locale Angular apps

With Angular’s build-time i18n, deployment is tied directly to how you configure angular.json. You define a source locale and a set of target locales, each mapped to a translation file.

During the build, Angular compiles the app once, then applies localized replacements as a post-processing step. This means you are not running full builds per language, but you still end up with separate output bundles for each locale.

Each locale produces its own version of the app, usually served from a subpath or domain. A common setup uses paths like /en/ and /fr/, with each pointing to its corresponding build output. This structure is required because the translated content is baked into the files, so switching languages means loading a different build.

Server configuration becomes part of the i18n setup. You need routing rules that map incoming requests to the correct locale version.

The implementation varies wildly by environment – raw rewrite rules in Nginx versus a few declarative lines in Firebase Hosting – but the goal is the same. Requests must resolve to the right localized bundle based on URL structure or redirect logic.

Angular also supports automatic language detection when using server-side rendering. The server can read the browser’s Accept-Language header, then redirect users to the matching locale path. This improves the first visit experience, but it still results in a full page load when switching languages later.

In development, the Angular dev server can serve multiple locales using subpaths. This helps with testing, but switching between languages still requires a refresh because each locale is a separate build output.

This model has clear infrastructure implications. You manage multiple build artifacts, configure routing for each locale, and handle redirects at the server level. CI pipelines must account for translation updates and rebuild localized outputs when content changes.

An alternative approach avoids this complexity. A reverse proxy model, such as Weglot’s, sits between the server and the browser. It translates content on the fly and serves all languages from a single deployment. This removes the need for multiple builds and routing rules. More on Weglot later on!

Comparing runtime libraries: ngx-translate, Transloco, and angular-i18next

Runtime libraries solve a different problem than Angular’s built-in i18n. Instead of compiling translations into the app, they load them at runtime and update the UI without a full reload.

This makes them a better fit when users need to switch languages inside the app or when content changes frequently.

ngx-translate is the most widely used option. It supports instant language switching through translate.use(), with translations loaded from JSON files or APIs. It works well in smaller apps and is the only option here with confirmed Ionic compatibility. SSR is possible with TransferState and custom loaders, though it requires setup. Recent versions added a provider-based API, which aligns better with standalone components.

Transloco focuses on structure and scalability. It provides built-in SSR support and a neater setup with ng add. It also supports scoped translations, which lets you lazy-load language files per feature. This reduces bundle size and keeps large apps maintainable. Language switching uses setActiveLang() and updates the UI immediately.

angular-i18next wraps the i18next ecosystem. It’s useful if your team already uses i18next in other frameworks and wants consistency across projects. It supports plugins from the i18next core, including ICU handling. Language switching typically requires a reload, which limits its use in apps that expect instant updates.

Here’s a more direct comparison:

Library Build Model Language Switching UX SSR Support Ionic Compatibility ICU Support Key Features/Notes
ngx-translate Runtime Runtime switch via translate.use() Supported via TransferState and custom loaders. Only confirmed Ionic option Via plugin ~1M weekly downloads. Now includes provideTranslateService() + inject()
Transloco Runtime Runtime switch via setActiveLang() Built-in Not explicitly detailed Via plugin ng add auto-setup, scoped lazy loading, signal-based API
angular-i18next Runtime Requires page reload on switch Not explicitly detailed Not explicitly detailed Via i18next core/plugin ~12k weekly downloads (Angular adapter); Best for cross-framework i18next teams

The choice depends on how your app handles language changes and scale:

  • Use ngx-translate if you need a simple setup or Ionic support.
  • Use Transloco for SSR or large apps with modular translation needs.
  • Use angular-i18next if you want alignment with i18next across multiple platforms.

💡 If runtime switching isn’t required and you prefer minimal client logic, Angular’s built-in i18n remains the better option.

Translating Angular apps without code changes

There’s a third option besides Angular’s built-in i18n and runtime libraries: external website translation tools. These tools sit outside the Angular app and translate the rendered output rather than strings inside the codebase.

As mentioned, Weglot uses a reverse proxy model. It sits between the server and the browser, detects the HTML response, then serves translated versions to visitors. This means you don’t mark strings with i18n, manage JSON translation files, or rebuild the app for each locale. Setup is faster because the translation layer is handled outside Angular.

This approach also changes where translation work happens. Instead of editing files in the project, translators use a visual dashboard. They can review pages and apply glossary rules without touching templates or TypeScript. For content-heavy marketing sites, that can reduce developer involvement.

Language switching can also feel smoother. Weglot supports a JavaScript-based switcher that updates the visible language without requiring a full Angular rebuild process. That makes it easier to launch multilingual content quickly.

The trade-off is control. Because translation happens after Angular renders the page, this model doesn’t handle app logic that depends on language inside TypeScript. It’s also a less-than-ideal fit for Ionic apps and offline-first apps, where content needs to live inside the application itself rather than behind a proxy.

SEO also depends on setup. Reverse proxy translation can support indexable translated pages, but a simple JavaScript snippet alone doesn’t create SEO-friendly localized URLs. That’s important if organic search traffic is part of the goal.

This model is best for teams that want multilingual pages without changing application code. It’s less suitable when language affects routing or business logic. It also requires an active subscription, since translated content remains tied to the service.

Choosing the right Angular i18n approach

The right approach to Angular internationalization depends on how your app handles languages in practice.

Build-time i18n prioritizes performance and stability, while runtime libraries focus on flexibility inside the UI. External tools remove most of the implementation work but shift control outside the codebase.

Choose @angular/localize when runtime performance is vital and your team is comfortable managing separate localized builds in CI. It fits best when language switching can happen through navigation rather than inside the app.

Choose ngx-translate when users need to switch languages without a reload and you want a widely adopted runtime option. It’s the strongest fit here for Ionic projects and smaller Angular apps.

Choose Transloco when you need runtime switching plus stronger structure for larger apps. It’s a good match for SSR setups and for teams that want scoped, lazy-loaded translation files.

Choose Weglot when the goal is a multilingual website without adding translation logic to the Angular codebase. It’s best for content delivery and fast rollout, not for apps where TypeScript behavior needs to change by language.

{{demo-banner}}

direction icon
Discover Weglot

Good things come to those who wait. International traffic doesn’t.

We’ll get your first languages live. You decide how far you want to go. Try Weglot for free today.

In this article, we're going to look into:
Rocket icon

Ready to get started?

The best way to understand the power of Weglot is to see it for yourself. Test it for free and without any engagement.

A demo website is available in your dashboard if you’re not ready to connect your website yet.

Read articles you may also like

FAQ icon

Common questions

Can you switch languages at runtime with @angular/localize?

arrow

No. Each language is compiled into its own build and served from a separate subdirectory. Switching languages means loading a different version of the app, not updating content in place.

How do you translate strings in TypeScript using $localize?

arrow

Use the $localize tag directly in your code, the same way you mark text in templates. These strings are included during extraction, then replaced with translated content at build time.

What happens to translation IDs when source text changes?

arrow

The ID changes and existing translations no longer match. This can fail if not configured. Use custom IDs and enable missing translation errors to catch issues early.

Does ngx-translate work with standalone components?

arrow

Yes. Recent versions added full support through provider-based APIs, so it works with standalone setups.

Blue arrow

Blue arrow

Blue arrow