Internationalization is the need of most modern apps today.If your application is developed in Angular, there are various libraries available, which you can use to present the app in multiple locales and reach out to your audience in various regions of the world.
Angular provides a module to accomplish the same. However, it is complex in comparison to some of the other libraries available for the purpose, which, you can integrate with your app.
Here, We will learn as to how we can use Angular i18n and then, we will reason as to why it should be preferred over other strategies.
Use Angular CLI to run below command
ng add @angular/localize
This will allow you to use Angular's Localization in your project.
Next, we mark static text in template files for translations.
<p i18n >Welcome to Angular Internationalization!</p>
Mark element attributes for translations by using i18n-attribute with any attribute of any element. You also can assign a meaning, description, and custom ID with the i18n-attribute="meaning|description@@id" syntax.
Below is an example for the same.
<input type="password" i18n-placeholder ="passwordPlaceholder|Placeholder for Password@@001" placeholder="password" name="password" />
Please note that meaning, description and Id are optional, and Angular will auto generate an Id for you, if you don't mention one.
Angular provides Data transformation pipes that use the LOCALE_ID token to format data according to the locale.
- DatePipe: Formats a date value.
- CurrencyPipe: Transforms a number to a currency string.
- DecimalPipe: Transforms a number into a decimal number string.
- PercentPipe: Transforms a number to a percentage string.
To override the value of LOCALE_ID, add the locale parameter, for Example,{{amount | currency : 'en-US'}}
For a list of available Locales please refer to this.
Now, that we have prepared templates for translation, we can proceed to process them.
Extract Source Language File
Run the below command in Angular CLI.
ng xi18n
This creates a source language file named messages.xlf in your project's root directory.
The xi18n command can read and write files in three translation formats:
- XLIFF 1.2 (default)
- XLIFF 2
- XML Message Bundle (XMB)
You can specify the translation format explicitly with the --format
command option.
The messages.xlf looks like below.Notice that, it has translation units,with an Id generated for it. It also captures other metadata, like file location and line number.
<trans-unit id="7d1069de6c435fab320e5305cbaf139af1b0189f" datatype="html">
<source>Welcome!</source>
<context-group purpose="location">
<context context-type="sourcefile">app/login/login.component.html</context>
<context context-type="linenumber">23</context>
</context-group>
</trans-unit>
Duplicate the messages.xlf file for each locale of your interest, and rename it.For example, you can rename it to messages.pa.xlf for Punjabi Language.
Please note that below code snippet has an additional target tag for translation of the source Language text.
<trans-unit id="7d1069de6c435fab320e5305cbaf139af1b0189f" datatype="html">
<source>Welcome!</source>
<target> ਜੀ ਆਇਆਂ ਨੂੰ !</target>
<context-group purpose="location">
<context context-type="sourcefile">app/login/login.component.html</context>
<context context-type="linenumber">23</context>
</context-group>
</trans-unit>
Similarly, add target tags to all translation units, in all the messages.lang.xlf files, corresponding to the number of languages your app may be supporting.
Define Locales in the Configuration
In angular.json , Under build's Configurations, define a configuration for each locale.Notice that, en-US
is Locale_ID for English, You can refer here for other Languages.
"en-US": {
"outputPath": "dist/browser/en",
"baseHref": "/en/",
"i18nLocale": "en-US",
"i18nFormat": "xlf",
"i18nFile": "src/messages.xlf",
"i18nMissingTranslation": "error",
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
outputPath
signifies path in the root directory of the Project,
where this build will be generated, once run.Angular i18n supports aot
by default. baseHref
indicates the ref on the website, which loads the locale.
Similarly, Under angular.json's , serve Configurations, define serve configs for each locale. Here production
indicates the default, and en-US
indicates application served in English. You should include all the locales your app is supporting. demoproject
is the name of the project here.
"production": {
"browserTarget": "demoproject:build:production"
},
"en-US": {
"browserTarget": "demoproject:build:en-US"
},
Please note, that build and serve configurations are defined in angular.json for each locale, which indicates that, a separate build and deployment will be created and run for each locale.
Now, you can build and run the application in your desired locale, by the following command on CLI. Below is an example for Punjabi Language.
ng build --configuration=pa-Guru && ng serve --configuration=pa-Guru
In case, you want multiple locales to be running in parallel, add the --port
switch with serve command, to serve the app on a different port for a different locale.
This gives us a basic implementation of Angular i18n, with separate build and deployment for each locale. But,Our goal is to be able to switch the locales from the Url itself. Also, it is important to understand the motivation to pick angular i18n mechanism instead of other simpler available libraries.
This will be covered in a separate blog post. That is where Server Side Rendering comes into play.
click here for Part 2 of the blog post.
Top comments (3)
Keep up the good work ..
It seems the server is not rendering the i18n texts, interpolated texts are ok but not the translations, any idea?
Did you run ng build --configuration=locale_id on cli. Do you get any error?
Also, please check your paths and how the dist folder is getting generated
Some comments have been hidden by the post's author - find out more