Gaming industry under DDoS attack. Get DDoS protection now. Start onboarding
  1. Home
  2. Developers
  3. How to Enhance Internationalization (i18n) Support Using @messageformat and ngx-translate-messageformat-compiler in Angular Applications

How to Enhance Internationalization (i18n) Support Using @messageformat and ngx-translate-messageformat-compiler in Angular Applications

  • By Gcore
  • June 8, 2023
  • 4 min read
How to Enhance Internationalization (i18n) Support Using @messageformat and ngx-translate-messageformat-compiler in Angular Applications

In the digital landscape where diverse user bases and global reach are paramount, localizing content for different languages is a critical task. One efficient solution to this task lies within message formatting in JavaScript, particularly in the context of Angular applications. Two libraries, @messageformat and ngx-translate-messageformat-compiler, play pivotal roles in enhancing internationalization (i18n) support. By providing localized content that respects the grammatical and structural peculiarities of different languages, these libraries significantly improve the user experience.

Understanding @messageformat and ngx-translate-messageformat-compiler

@messageformat is a standalone library for handling message formatting in JavaScript. It provides a comprehensive implementation of the MessageFormat syntax, supporting a wide range of language features and customization options. It can be used independently or in conjunction with ngx-translate-messageformat-compiler to handle message formatting in Angular applications.

The ngx-translate-messageformat-compiler library is an extension of the ngx-translate library, and allows for message formatting using the MessageFormat syntax. Message formatting is essential for handling language-specific pluralization, gender, and other complex language patterns. It compiles the MessageFormat strings into JavaScript functions, enabling efficient translation and rendering of dynamic content.

Real-World Applications of @messageformat and ngx-translate-messageformat-compiler

Both libraries are important in Angular applications because they allow for the translation and formatting of user-visible text, accommodating the grammatical and structural nuances of different languages. This improves the user experience by providing localized content that feels natural and appropriate to users in different regions or language preferences.

Tackling Pluralization Differences Across Languages

One of the use cases of this library is tackling pluralization differences between languages. Pluralization rules can vary widely across languages, creating a complex problem when it comes to translating and formatting user-visible text. For instance, in English, it’s fairly straightforward—we typically add an “s” for plurals. But in many other languages, the rules are more complicated, with different forms used depending on the number of items.

For example, consider how the phrase about the number of results found would be presented in English, Russian, and German:

  • English: Found no result. Found one result. Found # results.
  • Russian: Результатов не найдено. Нашел один результат. Найдено 3 результата (In between plural form, and it is not easy to solve). Найдено # результатов.
  • German: Keine Ergebnisse gefunden. Ein Ergebnis gefunden. Es wurden # Ergebnisse gefunden.

In the case of Russian, the in-between form for three results illustrates the complexity of plural forms that cannot be directly translated from English. Similarly, the German phrase changes structure entirely depending on the number of results.

The @messageformat and ngx-translate-messageformat-compiler libraries are designed to handle these kinds of linguistic complexities, ensuring that your application communicates effectively and naturally in any language.

Installation

Now that we understand the significance of @messageformat and ngx-translate-messageformat-compiler, it’s time to get practical. In this section, we offer a step-by-step guide to set up and install ngx-translate in your Angular application. Let’s start with the installation process.

First, let’s set up ngx-translate:

npm install @ngx-translate/core @ngx-translate/http-loader --saveAdding library to root module app.module.ts:	import { NgModule } from '@angular/core';	import { BrowserModule } from '@angular/platform-browser';	import { HttpClient, HttpClientModule } from '@angular/common/http';	import { TranslateCompiler, TranslateLoader, TranslateModule } from '@ngx-translate/core';	import { TranslateHttpLoader } from '@ngx-translate/http-loader';	import { TranslateMessageFormatCompiler } from 'ngx-translate-messageformat-compiler';	    import { AppComponent } from './app.component';	    export function createTranslateLoader(http: HttpClient) {        return new TranslateHttpLoader(http, './assets/i18n/', '.json');	}	    @NgModule({    	declarations: [        	AppComponent,    	],    	imports: [        	BrowserModule,        	HttpClientModule,        	TranslateModule.forRoot({            	loader: {                	provide: TranslateLoader,                	useFactory: (createTranslateLoader),                	deps: [HttpClient],            	},        	})    	],    	bootstrap: [AppComponent],	})	export class AppModule {	}

Then, set up simple application with translation:

app.component.html:<ul>  <li *ngFor="let lang of languages">	<a (click)="changeLangTo(lang)">  	{{ lang }}	</a>  </li></ul> <section>  <p>	{{ "GREETING" | translate }}  </p></section>app.component.ts:import { Component } from '@angular/core';import { TranslateService } from '@ngx-translate/core'; @Component({	selector: 'app-root',	templateUrl: './app.component.html',	styleUrls: ['./app.component.css'],})export class AppComponent {	languages = ['en', 'ru', 'de']; 	constructor(private readonly translateService: TranslateService) {    	translateService.setDefaultLang('en');  	  translateService.use('en');	} 	changeLangTo(lang: string): void {    	this.translateService.use(lang);	}}en.json:{  "GREETING": "Hello!"}ru.json:{  "GREETING": "Привет!"}de.json:{  "GREETING": "Hallo!"}

And the result will look like this:

Now, it’s time to add @messageformat and ngx-translate-messageformat-compiler:

npm install @messageformat/core ngx-translate-messageformat-compiler --save

After installation, TranslateModule needs to be configured to use TranslateMessageFormatCompiler:

	import { TranslateCompiler } from '@ngx-translate/core';	import { TranslateMessageFormatCompiler } from 'ngx-translate-messageformat-compiler';	    ....	    @NgModule({    	declarations: [        	AppComponent,    	],    	imports: [        	BrowserModule,        	HttpClientModule,        	TranslateModule.forRoot({            	loader: {                	provide: TranslateLoader,                	useFactory: (createTranslateLoader),                	deps: [HttpClient],            	},            	compiler: {                	provide: TranslateCompiler,                	useClass: TranslateMessageFormatCompiler,            	},        	})    	],    	bootstrap: [AppComponent],	})	export class AppModule {	}

It’s also possible to configure MessageFormat by providing a configuration object for the MESSAGE_FORMAT_CONFIG injection token. Here’s the default:

{	biDiSupport: false,	formatters: {},	strictNumberSign: false,	currency: "USD"}

MessageFormat instances offer various options to control their behavior. These options include customFormatters, biDiSupport, and strict mode, which allow for customization and influence over how MessageFormat operates. Learn more in the official docs.

Usage

After setting up ngx-translate, let’s now tackle our initial problem: incorporating these translations into our .json files using the appropriate format. When using MessageFormat in conjunction with ngx-translate, it’s important to note some key differences from ngx-translate’s default syntax:

  1. Accessing object properties in placeholders is not supported. For instance, syntax like Hello {name.prop} {name.prop2} won’t work.
  2. Simple placeholders are enclosed in single curly braces instead of double. So, we need to use Hello {name} instead of the default Hello {{name}}.

Let’s examine the basic structure of a formatter to better understand these concepts:

{variable, formatter, option {#(variable placeholder) interpolated text}}

Here are the translation strings:

	en.json	{    	"RESULT_TEXT": "{count, plural, =0{Found no results} one{Found one result} other{Found # results} }"	} 	de.json	{    	"RESULT_TEXT": "{count, plural, =0{Keine Ergebnisse gefunden} one{Ein Ergebnis gefunden} other{Es wurden # Ergebnisse gefunden} }"	} 	ru.json	{    	"RESULT_TEXT": "{count, plural, =0{Результатов не найдено} one{Нашел один результат} few{Найдено # результата} other{Найдено # результатов} }"	}

Let’s modify our code to see the results:

app.component.html:.... <p>	{{ "RESULT_TEXT" | translate : { count: resultCount } }}</p><button (click)="decrement()">	-</button>|<button (click)="increment()">	+</button> ....app.component.ts:.... resultCount = 0; .... increment(): void {	this.resultCount++;} decrement(): void {	this.resultCount--;} ....

Finally, we get:

Extend Capabilities with Additional Formatters

It doesn’t end here. The versatility of MessageFormat extends beyond the basic usage, offering an array of ready-to-use formatters to accommodate a variety of scenarios, enhancing its adaptability and functionality. The options include:

  • Select
  • Plural – what we used here
  • Date
  • Duration
  • Number
  • Time

MessageFormat’s flexibility also allows us to create custom formatters for unique or exceptional cases that may arise. This ability to tailor the library to our specific needs underlines the power and utility of MessageFormat in the world of internationalization.

Conclusion

In summary, @messageformat simplifies the task of creating dynamic and localized messages by allowing placeholders and variable substitution. It eliminates the need for manual string concatenation and provides support for language-specific rules and variations, making it easier to build multi-language applications.

Related articles

What's the difference between multi-cloud and hybrid cloud?

Multi-cloud and hybrid cloud represent two distinct approaches to distributed computing architecture that build upon the foundation of cloud computing to help organizations improve their IT infrastructure.Multi-cloud environments involve us

What is multi-cloud? Strategy, benefits, and best practices

Multi-cloud is a cloud usage model where an organization utilizes public cloud services from two or more cloud service providers, often combining public, private, and hybrid clouds, as well as different service models, such as Infrastructur

What is cloud migration? Benefits, strategy, and best practices

Cloud migration is the process of transferring digital assets, such as data, applications, and IT resources, from on-premises data centers to cloud platforms, including public, private, hybrid, or multi-cloud environments. Organizations can

What is a private cloud? Benefits, use cases, and implementation

A private cloud is a cloud computing environment dedicated exclusively to a single organization, providing a single-tenant infrastructure that improves security, control, and customization compared to public clouds.Private cloud environment

What is a cloud GPU? Definition, types, and benefits

A cloud GPU is a remotely rented graphics processing unit hosted in a cloud provider's data center, accessible over the internet via APIs or virtual machines. These virtualized resources allow users to access powerful computing capabilities

What is cloud networking: benefits, components, and implementation strategies

Cloud networking is the use and management of network resources, including hardware and software, hosted on public or private cloud infrastructures rather than on-premises equipment. Over 90% of enterprises are expected to adopt cloud netwo

Subscribe to our newsletter

Get the latest industry trends, exclusive insights, and Gcore updates delivered straight to your inbox.