Internationalization is the process of designing and preparing your app to be usable in different languages.

The internationalization allows the application to translate to different languages and related formats such as data, for example.

The internationalization is a feature that you can use if your application needs different languages but also you can use this if it is necessary has different labels to the same component in a different context.

You will find these many languages, including in java and angular as well.

Install

To prepare your application to the use of this resource you need to install to modules, the core and http-loader:

"npm install @ngx-translate/core @ngx-translate/http-loader --save"

Configurations and Declarations

Also, you need to define where these files will be after the build. This configuration is inside the 'angular.json' file in the property assets.

Everything defined inside this property will be copied to the dist folder. If your file is inside the i18n folder, then, it should be declared in the assets to be found by the application.

"architect": {
  "build": {
    "builder": "@angular-devkit/build-angular:browser",
    "options": {
       ...
       "assets": [
       "src/assets/i18n"
...

Your class AppModule should import the classes related to a translator and a method that you can explicitly define where to find your file.

If you declare the folder for the files, it should be the same declared in the assets property. A good example you can see here.

...
import {TranslateLoader, TranslateModule} from "@ngx-translate/core";
import {TranslateHttpLoader} from "@ngx-translate/http-loader";
...
@NgModule({
   ...
   imports: [
     ...
     // ngx-translate and the loader module
     TranslateModule.forRoot({
       loader: {
         provide: TranslateLoader,
         useFactory: HttpLoaderFactory,
         deps: [HttpClient]
      }
    })
   ],
   ...
})
...
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

If you have more than one source you can declare the list:

export function HttpLoaderFactory(http: HttpClient) {
     return new MultiTranslateHttpLoader(http, [
         {prefix: './assets/i18n/', suffix: '.json'},
         {prefix: './assets/i18n/countries', suffix: '.json'}
         ]);
}

Another way to declare the translate file is in the import, where explicitly you add the path:

import * as translationEn from './assets/i18n/en.json';
import * as translationEs from './assets/i18n/es.json';

PS: You can use different formats, not only json. In Angular guide you can see the use of a different format.

Using

To use the translate file you have to reference the key declared in your translate file with pies and directive. It's possible using parameters as well.

Pipe: translation pipe — { { 'yourkey' | translate } }
Pipe and param: 

{ { 'yourkey' | translate: { 'name':'YourPameter'} } }

Directive: <element [translate]="'yourkey'"></element> Directive and param: <p [translate]="'yourkey'" [translateParams]="{name: 'YourParam'}"></p>

Using more than one fragments

Sometimes, use only one file to describe all the applications can make the maintenance a little hard. Then, it maybe better to break in small files.

The problem is that the translation needs to use only one complete file ([en,fr].json). One solution is to add a preprocessing to converge all these files to one.

There is a module that can do this. It's ngx-i18n-combine. The problem is that the module adds a new level (the name of the file) in the final file. It's good if you have duplicate keys. It will avoid conflicts. If you are expected this it will not be a problem. You just need to remember this when using the Html files.

However, that extra level can be a problem. Another solution is to use module json-concat. It will only add each file on the and separated by a comma and all the json file will be inside the "{}". The problem is the opposite of the combine. If you have duplicate keys it will be a problem. You need to know your files to make the better decision of which module to use.

In both cases, it's necessary to have a script defined in the package.json in the "scripts" tag. The scripts should be executed before the build.

"scripts": {
"concat-json": "json-concat src/i18n/bp src/i18n/fragments src/assets/i18n/en.json",
"combine-json": "ngx-i18n-combine -i ./src/i18n/fragments -o src/assets/i18n/en.json"

Pay attention to the output source. It should be the same declared in assets property in the 'angular.json' file. The build will get this file and add it to the dist folder. Both module you can give folder such input or a list of files.

Asynchronous

If you need pass parameters to the message in your json but the values cames from a service, for example, when the page is rendered there is a possibility that your message will not populate with the parameters.

To guarantee the correct renderization with the values you need to use the asynchroous way to use the translate service.

In your init method add the code below. It will put the parameters in the messages as soon as the data is recovered.

//json files
{
  "firstName": "Your first name is { { paramFirstName } }",
  "lastName": "Your name is { { paramLastName } }"
}

// ngOnInit method
  this.translate.get(['firstName', 'lastName'],
      [{paramFirstName: "Maria"}, { paramLastName: "Silva"}]})
    .subscribe(translations => {
      this.firstName = translations['firstName'];
      this.lastName = translations['lastName'];
    });

Conclusion

The use of the translate is not a big deal. If you are migrating probably you will have some incompatibilities issues regarding with version.

The big decision, in fact, is if you will use a big file or fragments. Don't worry. There's no right answer. Take your decision and go on.

References