Software localization

The Best Angular Libraries for Internationalization

Wondering which internationalization library to use to get your Angular app ready for translation? Check out our curated list for the best options.
Angular internationalization and localization blog post featured image | Phrase

Google’s Angular has always set itself apart from other declarative UI solutions by being a complete framework that scales with your app: It has modules, dependency injection, a powerful CLI, strong naming conventions, and more. This makes Angular a go-to for giants like Samsung, PayPal, Upwork, and even Microsoft. Unsurprisingly, Google has also made sure that we get a built-in Angular localization solution, @angular/localize.

While it is our top general recommendation, Angular’s i18n (internationalization) library does come with trade-offs. For smaller applications, some third-party offerings might be a better fit. In this article, we’ll compare the best Angular i18n libraries so you can choose the best one for your project.

We’ll cover the following Angular i18n libraries:

  • @angular/localize (Angular’s first-party i18n library)
  • ngx-translate
  • Transloco
  • angular-i18next (community Angular integration with i18next)

Rating criteria

Of course, any library that made this list covers the i18n essentials: configuring supported languages and defining translated strings that can be injected into templates or TypeScript. (This allows us to switch between different languages in our app).

In addition, we made sure to rate libraries by criteria for production and long-term maintenance:

  • Popularity (NPM downloads per week)
  • Frequency of updates
  • Quality of documentation
  • Bundle size (according to Bundlephobia)

We also looked at some extra i18n features:

  • Complex plural support for languages like Arabic and Russian
  • Localized number and date formatting
  • ICU (International Components for Unicode) standard syntax support
  • Angular Universal SSR (server-side rendering) support
  • Ionic Framework support

🤿 Go deeper » “What’s ICU?”, you may be wondering. The Missing Guide to the ICU Message Format answers that and more.

NPM trends Angular libraries blog post | Phrase

NPM Trends graph showing Angular i18n library downloads over 2022

A note on bundle sizes

We’ve used NPM bundle sizes from Bundlephobia as part of our rating criteria. These sizes do not account for tree shaking. Moreover, some libraries have developer tooling that wouldn’t normally get bundled in your production builds. So we recommend trying out the library you like and seeing what the actual production bundle weighs in for you. Take the bundle sizes in this article as a relative comparison metric.

🔗 Resource » If you want a comparison of the best overall JavaScript i18n libraries, covering vanilla JS, React, Vue, and more, check out our roundup, The Best JavaScript I18n Libraries.

@angular/localize (built-in Angular i18n)

The first-party i18n package included with Angular, @angular/localize is robust, performant, and feature-complete. Aligned to the Angular philosophy, @angular/localize is built to scale with your team and project. However, the library does need a bit of work to set up. It also requires message extraction and compilation to work with translations during development. All in all, however, Angular’s built-in @angular/localize is our recommended go-to for most projects.

Ratings

Rating criteria Rating Notes
Popularity ⭐️⭐️⭐️⭐️⭐️ ~815k downloads per week
Update frequency ⭐️⭐️⭐️⭐️⭐️ Part of Angular; updated ≥ once a month
Documentation quality ⭐️⭐️⭐️⭐️ Guide + API reference
Added bundle size ⭐️⭐️⭐️⭐️⭐️ 3kB minified + gzipped

With ~815 thousand NPM downloads per week at the time of writing, @angular/localize is top of our list for popularity. The library has been adopted by many and will likely continue to flourish. In fact, since @angular/localize is part of Angular, Google’s engineers are updating the library at an excellent cadence of at least once a month.

When it comes to documentation, Angular’s i18n guide is a good start. The early developer experience can be tricky, however, and the guide can skim over some things. On the other hand, as you would expect from Google, good API documentation is on offer.

🔗 Resource » We walk through @angular/localize setup step-by-step, as well as cover the ins and outs of using the library, in The Ultimate Guide to Angular Localization.

The featherweight in our list, @angular/localize, adds a tiny 3kb minified + gzipped to your app bundle. This is likely due to the library baking localizations directly into versions of your production app (more on that shortly).

Features

Feature Included Notes
Complex plural support
Localized numbers and dates
ICU Message format
Angular Universal SSR support ✅ (✋) ✋ Might require workarounds (see below)
Ionic Framework support Likely impossible or difficult (see below)

@angular/localize is i18n feature-complete. It supports the ICU message format by default, which means it also supports complex plurals. Built into the library are pipes and functions for formatting localized dates and numbers.

While @angular/localize should work fine with Angular’s server-side rendering solution, Angular Universal, some scenarios might need extra work to ensure the 2 libraries cooperate. These threads might provide more insight if you hit a hitch there:

As far as we can tell @angular/localize doesn’t work with the Ionic mobile framework. This might be because the i18n library builds a version of your app for each language, and you need to swap between them—likely tricky for Ionic. We haven’t tried @angular/localize with Ionic ourselves, but our research suggests that no one is using the combo. Our take: Stick to web apps with @angular/localize.

What’s it like to use

@angular/localize uses a build-time localization strategy. This is different from all the other libraries we’re covering here. Let’s briefly go over how build-time localization works.

After the library is installed and set up (see our guide for more information), we mark our strings as localizable in your components.

<!-- src/app/some/feature.component.html -->

<div>
  <!-- 👇 Note the `i18n` marker we've added. -->

  <p i18n>Schedule your appointment now.</p>

</div>Code language: HTML, XML (xml)

We then extract your marked strings using the provided command-line command:

% ng extract-i18n --output-path src/localeCode language: Bash (bash)

The command will output a translation file for our base/default language. If we assume that’s English, we’d get the following:

<!-- src/locale/messages.xlf -->

<?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="7285274704628585281" datatype="html">
        <source>Schedule your appointment now.</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/some/feature.component.html</context>
          <context context-type="linenumber">4</context>
        </context-group>
      </trans-unit>
    </body>
  </file>
</xliff>Code language: HTML, XML (xml)

We can then copy this file for each of our supported locales and translate our strings. Here’s what an Arabic translation file would look like:

<!-- src/locale/messages.ar.xlf -->

<?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="7285274704628585281" datatype="html">
        <source>Schedule your appointment now.</source>
       
        <!-- 👇 Add translation within <target> tags -->
        <target>حدد موعدك الآن</target>

        <!-- //… -->

      </trans-unit>
    </body>
  </file>
</xliff>Code language: HTML, XML (xml)

Once we’ve added our translations, we build our app with the localize flag from the command line:

% ng build --localizeCode language: Bash (bash)

This will build multiple versions of our app, one for each supported locale. The translation strings will be baked into the components of each version. Your distribution directory would look like the following.

.
└── dist/
    └── app-name/
        ├── ar/
        │   ├── assets/
        │   ├── index.html
        │   └── ...
        └── en-US/
            ├── assets/
            ├── index.html
            └── ...Code language: plaintext (plaintext)

Angular localize demo app | Phrase

A demo app localized with @angular/localize. See how to build this app in our full guide.

This i18n at build-time approach is a trade-off. It offers good performance since translations are baked right into the localized app versions. On the other hand, switching between locales means loading a new version of your app. This usually isn’t a big deal, since most people will switch to their language once. The main problem with build-time i18n is that it makes testing translations during development a bit cumbersome.

🔗 Resource » We show you how to better test translations when developing with @angular/localize in The Ultimate Guide to Angular Localization.

@angular/localize, like Angular in general, is meant to scale with you. Its build-time i18n strategy is great for large web apps and large teams with translators on board. Given that the library is a part of Angular and has complete i18n features, @angular/localize is our top recommendation for your Angular i18n needs.

However, if you’re making an app that you know will stay small, or you want to build a mobile app with the Ionic framework, then @angular/localize might not be for you. Read on to see how ngx-translate can fit the bill there.

ngx-translate

Built as an alternative to @angular/localize, ngx-translate uses a runtime localization strategy. We’ll get to see this in action in a bit; for now just know that ngx-translate is easier to start using than Angular’s built-in i18n. And ngx-translate is the only library on this list with a track record of working with the Ionic mobile framework. Now, ngx-translate isn’t built for peak performance, nor is it getting very frequent updates. For small apps that might not matter, and that’s where ngx-translate’s quick setup and lightweight translation format can shine.

Ratings

Rating criteria Rating Notes
Popularity ⭐️⭐️⭐️⭐️⭐️ ~775k downloads per week
Update frequency ⭐️⭐️ Updated once or twice a year
Documentation quality ⭐️⭐️⭐️⭐️ Guide + API reference
Added bundle size ⭐️⭐️⭐️ 4–23kB minified + gzipped (see below)

Only second in popularity (and by a narrow margin) to @angular/localize, ngx-translate enjoys a critical mass of ~775 thousand NPM downloads per week. So while the library is only getting updated a couple of times per year, it might be mature enough for you to use without worrying about missing or broken features.

ngx-translate’s GitHub one-pager documentation gets you started with the library quickly, and provides an API reference. The library isn’t very big, so the on-hand docs have you covered.

🔗 Resource » If you’re looking for a more detailed tutorial, code along with our Angular Tutorial on Localizing with ngx-translate.

The library itself weighs in at a svelte 4.1kB minified + gzipped. However, to get all the i18n features we’ve listed here, you’ll need to add the MessageFormat library (22.2kB), as well as some other small plugins. This makes your added bundle size in the range of 4–23kB.

Features

Feature Included Notes
Complex plural support With third-party MessageFormat plugin
Localized numbers and dates With third-party MessageFormat plugin
ICU Message format With third-party MessageFormat plugin
Angular Universal SSR support With additional loader
Ionic Framework support

ngx-translate has full i18n features when complimented by its suite of community plugins.

The ICU MessageFormat and complex plurals are handled by a third-party plugin that wires up the messageformat library to ngx-translate. Updated about as frequently as ngx-translate itself, the plugin seems reasonably reliable.

🗒️ Note » The MessageFormat plugin also seems to allow for localized date and number formatting, although we’ve yet to try this ourselves.

A simple loader written by ngx-translate’s original author gets the ngx-translate working with Angular’s official SSR solution, Angular Universal.

Because ngx-translate uses a runtime localization strategy—a single version of your app can switch between locales—it seamlessly works with the Ionic Framework. (More on runtime localization in a moment).

🔗 Resource » We have a step-by-step guide to localizing Ionic Apps with ngx-translate.

What’s it like to use

Unlike @angular/localize, ngx-translate uses runtime localization. This means that after we install and configure the library (see our guide for more there), we simply add your translations to JSON files in our project’s assets directory.

// src/assets/i18n/en.json

// English translations
{
  "READ_MORE": "Read more"
}Code language: JSON / JSON with Comments (json)
// src/assets/i18n/ar.json

// Arabic translations
{
	"READ_MORE": "إقرأ المريد"
}Code language: JSON / JSON with Comments (json)

In our components, we can pull in our translated strings using the translate pipe provided by ngx-translate.

<!-- src/app/some/feature.component.html -->

<div>
  <p>{{ "READ_MORE" | translate }}</p>
</div>Code language: HTML, XML (xml)

To change the active locale at runtime, we can call a use() method that ngx-translate provides.

<!-- src/app/lang/lang-switcher.component.html -->

<nav>
  <ul>
    <!-- Calling changeLang() 👇 to switch language at 
         runtime. -->
    <li><a (click)="changeLang('en')">English</a></li>

    <li><a (click)="changeLang('ar')">Arabic</a></li>
  </ul>
</nav>Code language: HTML, XML (xml)
// src/app/lang/lang-switcher.component.ts

import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Component({
  selector: 'lang-switcher',
  templateUrl: './lang-switcher.component.html',
})
export class LangSwitcher {
  translate: TranslateService;

  // Inject ngx-translate translate service 
  // into component.
  constructor(translate: TranslateService) {
    this.translate = translate;
  }

  // Call `translate.use()` to switch language 
  // at runtime.
  changeLang(newLang: string) {
    this.translate.use(newLang);
  }
}Code language: TypeScript (typescript)

ngx-translate demo | Phrase

A demo app localized with ngx-translate. See how it was made in our guide.

Runtime localization means we don’t need to extract our strings from our components to translate them. Nor do we need to compile the translated strings back into our app at build-time. We work with one version of our app, which makes testing our localizations during development quite easy.

On the other hand, runtime localization performs a bit worse than its build-time counterpart. Whereas translations are baked into app versions with build-time localization, runtime localization has separate translation files loaded from the network. This is normally OK since translation files are small when well-organized. So for smaller apps, and certainly for Ionic usage, ngx-translate might be just what the doctor ordered.

🔗 Resource » Our Angular Tutorial on Localizing with ngx-translate is a deeper step-by-step guide for using ngx-translate.

But you might be looking for a runtime localization library with more frequent updates, and more first-party support/plugins. For that, Transloco is certainly worth a look.

Transloco

Transloco is proof that star ratings alone can’t capture the experience of using a library. More than any i18n library on this list, Transloco has a great developer experience. It’s remarkably easy to set up and start using. Transloco is a well-maintained, feature-complete i18n library to boot.

🗒️ Note » Transloco uses runtime localization. See the previous ngx-translate section if you want a comparison of runtime and build-time localization strategies.

Ratings

Rating criteria Rating Notes
Popularity ⭐️⭐️⭐️ ~93k downloads per week
Update frequency ⭐️⭐️⭐️⭐️ Updated multiple times per year
Documentation quality ⭐️⭐️⭐️⭐️ Guide + API reference
Added bundle size ⭐️⭐️ 8–40kB minified + gzipped (see below)

At the time of writing Transloco is being downloaded ~93k times per week, an order of magnitude lower than @angular/localize and ngx-translate. Very much a vibrant project, however, Transloco is being updated frequently throughout the year.

The library has very good documentation, with a ‘getting started’ guide and in-depth API coverage. The Transloco team has even put together a video guide series to get you up and running quickly.

🔗 Resource » Our Angular Tutorial on Localizing with Transloco details setting up and using the library.

The core Transloco package weighs in at ~8kB minified + gzipped. To get all the i18n features we cover here, however, you need to add the MessageFormat and Locale L10n plugins: another 27kB and 5kB, respectively. So you’re looking at an added bundle size of 8–40kB, depending on your needs.

Features

Feature Included Notes
Complex plural support With first-party MessageFormat plugin
Localized numbers and dates With first-party Locale L10n plugin
ICU Message format With first-party MessageFormat plugin
Angular Universal SSR support
Ionic Framework support N/A Should work in theory; no info available

Like ngx-translate, Transloco handles ICU messages, and their support for complex plurals, through a MessageFormat plugin. This is a first-party plugin, so it’s written and maintained by Transloco’s core team.

Another among Transloco’s first-part add-ons is the Locale L10N plugin, which provides pipes for formatting localized dates and numbers.

🗒️ Note » A roundup of other plugins are available for Transloco, covering persisting translations or the user’s language and preloading translations.

SSR support seems to be built right into Transloco and should work with minimal setup.

As for the Ionic framework, we haven’t found any examples in the wild of Ionic apps localized with Transloco. However, since Transloco uses runtime localization, it should be possible to use with Ionic. We might attempt to tackle this ourselves in a future article.

What’s it like to use

Transloco is refreshingly easy to get started with. To install and **configure the library we run one command from the command line:

% ng add @ngneat/translocoCode language: Bash (bash)

The installer will ask us which languages we want to support in our app, and whether or not we’re using SSR. It then adds configuration files and a new module, which it imports into app.module.ts. And that’s it! We’re ready to localize.

// src/assets/i18n/en.json

{
  "rateLabel": "Rate our customer service:"
}Code language: JSON / JSON with Comments (json)
// src/assets/i18n/es.json

{
  "rateLabel": "Califique nuestro servicio de atención al cliente:"
}Code language: JSON / JSON with Comments (json)

In our templates, we can use the transloco directive to pull in the t translation function:

<!-- // src/form/form.component.html -->

<ng-container *transloco="let t">
  <label>{{ t("rateLabel") }}</label>
</ng-container>Code language: HTML, XML (xml)

We can switch the active locale using Transloco’s setActiveLang() method.

<!-- // src/lang-switcher/lang-switcher.component.html -->

<nav>
  <ul>
    <li><a (click)="setLang('en')">English</a></li>
    <li><a (click)="setLang('es')">Spanish</a></li>
  </ul>
</nav>Code language: HTML, XML (xml)
// src/lang-switcher/lang-switcher.component.ts

import { Component } from '@angular/core';
import { TranslocoService } from '@ngneat/transloco';

@Component({
  // ...
})
export class LangSwitcherComponent {

  // Injecting the Transloco service into our
  // component 👇
  constructor(private translocoService: TranslocoService) {}

  // Using `setActiveLang` to switch the runtime
  // locale 👇
  setLang(newLang: string) {
    this.translocoService.setActiveLang(newLang);
  }
}Code language: TypeScript (typescript)

Transloco demo | Phrase

A demo app localized with Transloco. See how to build this app in our full guide.

Transloco is unmatched in its developer experience and ease of use. First-party plugins and continuous updates round out the package, making the library an easy recommendation for runtime Angular localization. The only caveat here might be Ionic, and we recommend trying Transloco with Ionic in a small proof of concept before jumping into production.

But you might be coming to Angular from another front-end library, like React. In this case, there’s a chance that you’re already familiar with the massively popular i18next library. If this sounds like you, consider angular-i18next.

angular-i18next (i18next)

angular-i18next is an outlier when it comes to Angular i18n libraries. The unofficial Angular wrapper for i18next isn’t as popular as other Angular i18n offerings. i18next itself is no slouch, though; it’s arguably one of the most popular i18n solutions on the planet. And if you’ve used i18next before, you might want to stick with the i18n library you know.

🗒️ Note » angular-i18next uses runtime localization. See the ngx-translate section above if you want a comparison of runtime and build-time localization strategies.

Ratings

Rating criteria Rating Notes
Popularity ⭐️⭐️ ~11k downloads per week
Update frequency ⭐️⭐️⭐️⭐️ Updated multiple times per year
Documentation quality ⭐️⭐️⭐️ Guide + cookbook
Added bundle size ⭐️⭐️ 20.9–29.7kB minified + gzipped (see below)

At ~11k NPM downloads per week (at the time of writing), angular-i18next can look like small fish next to the other libraries here. Consider, however, that angular-i18next is simply a community-made Angular adapter for i18next—and that library sees close to 4 million weekly downloads at the time of writing!

Sergey Romanchuk, the developer behind angular-i18next, is updating the wrapper library at least a few times per year. This should keep angular-i18next up to date with major changes in both Angular and i18next.

We found the library’s documentation a bit hit-or-miss. A senior dev will be able to parse through it and get the library working. The guide on offer doesn’t always lay things out in a manner that’s easy to walk through, however. And you’ll probably have to jump between the angular-i18next docs and core i18next docs to find all you’re looking for.

🔗 Resource » We fill in the gaps with our Angular Tutorial on Localizing with I18next.

i18next is a bit beefy with its bundle footprint. At a bare minimum, you’ll need both the core i18next library (15.3kB minified + gzipped) and the Angular adapter, angular-i18next (5.6kB). To get all the i18n features we cover here, you’ll probably want these packages as well:

  • i18next-icu (provides ICU message support) — 1.3kB
  • i18next-http-backend (loads translation files from the network) — 5.2kB
  • i18next-browser-languagedetector (detects and persists the user’s language) — 2.3kB

So you’re looking at a range of 20.9kB–29.7kB for your added bundle size.

Features

Feature Included Notes
Complex plural support
Localized numbers and dates
ICU Message format With first-party plugin
Angular Universal SSR support N/A Should work in theory; no info available
Ionic Framework support N/A No info available

i18next supports complex plurals out of the box by using JavaScript’s built-in Intl.PluralRules under the hood. You can also have ICU messages and plural in your app by adding a first-party ICU plugin.

Similarly, number and date formatting use JavaScript’s Intl libraries under the hood, and so provide robust localization options.

Heads up » You can’t mix and match the built-in and ICU formatting. For example, if you use ICU plural formatting, you can’t use the built-in plural formatting. You probably won’t want to, so this is just FYI.

We couldn’t find any examples of angular-i18next being used with Angular Universal (SSR), but i18next itself works on the server. So it should be possible to use the i18n library with Universal. We recommend trying it out in a small project to see what it looks like.

Neither could we find cases of angular-i18next being used with Ionic. The library does use runtime localization, so it should be compatible with Ionic. Again, try the combo out before jumping into production with Ionic and angular-i18next.

What’s it like to use

After installing and configuring angular-i18next (see our guide for more information), we add our translations to JSON files, much like Transloco and ngx-translate. We’re supporting English and Greek here:

// src/assets/lang/en/translation.json

{
    "welcome": "Welcome to Phrase i18next"
}Code language: JSON / JSON with Comments (json)
// src/assets/lang/el/translation.json

{
    "welcome": "Καλως ήλθατε στο Phrase i18next"
}Code language: JSON / JSON with Comments (json)

To pull these translations into our component templates, we use the handy i18next pipe.

<!-- src/app/app.component.html -->

<h1>{{ "welcome" | i18next }}</h1>Code language: HTML, XML (xml)

And to switch languages, the changeLanguage() method does the trick.

<!-- src/app/app.component.html -->

<!-- ... -->

<select (change)="onLangChanged($event)" [value]="lang">
  <option value="en">English</option>
  <option value="el">Ελληνικά</option>
</select>Code language: HTML, XML (xml)
// src/app/app.component.ts

import { Component, Inject } from '@angular/core';
import { ITranslationService, I18NEXT_SERVICE } from 'angular-i18next';

@Component({
  // ...
})
export class AppComponent {
  lang = '';

  // Injecting i18next's translation service 👇
  constructor(
    @Inject(I18NEXT_SERVICE) private i18NextService: ITranslationService
  ) {
    this.lang = this.i18NextService.language;
  }

  onLangChanged(event: Event) {
    const newLang = (event.target as HTMLInputElement).value;

		// Switching the active locale with changeLanguage() 👇
    this.i18NextService.changeLanguage(newLang).then(() => {
      this.lang = newLang;

      // ✋ Note that we have to reload the page for the
      // change to take effect
      document.location.reload();
    });
  }
}Code language: TypeScript (typescript)

If you’re porting your app from another front-end framework—and this app is already using i18next—consider angular-i18next. Your familiarity with i18next might sway you here as well.

In any case, it’s hard to go wrong with i18next: Its flexibility and ecosystem make it a wildly popular choice in the front-end community at large. It’s less popular as an Angular i18n solution, however, so you’ll have to make your own judgment there.

Our verdict

What about our judgments? Well, in our opinion, the overall winner is @angular/i18n. It’s hard to beat a mature i18n library that’s built and maintained by the Angular team.

If you’re working with the Ionic framework, ngx-translate has a good track record. And for an excellent developer experience, Transloco is refreshingly pleasant to use. If you already depend on i18next, angular-i18next is more than capable of bringing your localizations to your Angular app.

We hope you’ve found this comparison of Angular i18n libraries useful. If you’re ready to take your i18n game to the next level, check out the Phrase Localization Suite. The integrated suite of localization automation technology comes with a dedicated software localization platform, Phrase Strings.

With tons of tooling to automate your translation workflow and integrations with GitHub, GitLab, Bitbucket, and more, Phrase Strings can take care of the heavy lifting for i18n. Your translators pick up the localizations you’ve pushed and use Phrase Strings’ beautiful web panel to organize and translate into as many languages as needed.

When your translations are ready, you can pull them back into your project with a single command (or automatically)—so you can stay focused on the code you love. Sign up for a free trial to see why developers love working with Phrase Strings.

String Management UI visual | Phrase

Phrase Strings

Take your web or mobile app global without any hassle

Adapt your software, website, or video game for global audiences with the leanest and most realiable software localization platform.

Explore Phrase Strings