Overview

Skill Level: Any Skill Level

Built-in angular internationalization allows for multiple builds, each in a different language which works when hosted across multiple domains, but insufficient for dynamic language selection. Utilize an external package to hot-swap language files (json)

Ingredients

There are many complex scenarios that are project-dependent. This is just a simple use case of it.

 

  • Angular application (this was developed using Angular 8 but possible in earlier versions)

  • Loader (http-loader in demo)

  • Npm

  • Ngx-translate package (MIT-equivalent license)

Step-by-step

  1. Add package

    To add the ngx-translate package, simply run:

     

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

     

    Note that the http-loader is the basic loader used in tutorials. It is possible to write your own loader if needed.

  2. Import & Configure Module

    Import the new modules in app.module.ts. Note you will also need the angular HttpClient module.

     

    import { HttpClient } from ‘@angular/common/http’;

    import { TranslateLoader, TranslateModule } from ‘@ngx-translate/core’;

    import { TranslateHttpLoader } from ‘@ngx-translate/http-loader’;

     

    Add to NgModules:

     

    @NgModule({

    imports: [

    TranslateModule.forRoot({

          loader: {

              provide: TranslateLoader,

              useFactory: HttpLoaderFactory,

              deps: [HttpClient]

        }

     })

    ]

  3. Connect to Loader

    Define a loader and add it to your modules. If using the default loader, add the following after the import statements:

     

    . . .

    export function HttpLoaderFactory(http: HttpClient) {

      return new TranslateHttpLoader(http, ‘/assets/i18n/’, ‘.json’);

    }

     

    @NgModule({

    . . .

  4. Use language service

    In the app.component.ts, import the translation service and add it to your constructor as usual. Then configure the service.

     

     

    import { TranslateService } from ‘@ngx-translate/core’;

     

    @Component …

     

    Export class AppComponent implements OnInit {

          constructor (private translate: TranslateService) {

                      // add supported languages

                      this.translate.addLangs([‘en’, ‘fr’]);

                      // set a language to use

                      this.translate.use(this.language);

                      // set a default language in case of loading issues

                      this.translate.setDefaultLang(this.language);

          }

          . . .

    }

  5. Add language files

    Add your language files – typically in assets/i18n folder.

    Files should be JSON format, named by the language (e.g.: English file named ‘en.json’)

    e.g.:

     

    {

          “WELCOME_TEXT”: “Hello there!”,

          “WELCOME_TEXT_2”: “Hello there {{value}}!”,

    }

     

  6. Implement translations (html)

    Utilize the pipe or directive feature dynamically translate text.

     

    E.g. Pipe:

     

    {{ ‘WELCOME_TEXT’ | translate }}

     

    Displayed as :

    Hello there!

     

    E.g.: Pipe with parameters:

     

    {{ ‘WELCOME_TEXT_2’ | translate:{value: ‘Bob’} }}

     

    Displayed as :

    Hello there Bob!

     

    E.g.: Directive:

     

    <div translate>WELCOME_TEXT</div>

     

     

    E.g.: Directive with parameters:

     

    <div translate [translateParams]=”{value: ‘Bob’}”>WELCOME_TEXT_2</div>

     

     

    For further usage examples and options, see the package documentation

  7. Implement translations (ts)

    Utilize the service to dynamically translate objects displayed in the UI.

     

    import { TranslateService } from ‘@ngx-translate/core’;

     

    @Component  . . . 

     

    Export class AppComponent implements OnInit {

          constructor (private translate: TranslateService) {

    this.translate.stream([‘TAB_1’, ‘TAB_2’]).subscribe(tsn => {

          this.label_1 = tsn[‘TAB_1’];

          this.label_2 = tsn[‘TAB_2’];

    });

    }

    . . . 

     

     

    This is just an example and can be modified to enable dynamic label inputs and mapping of outputs.

    For further usage examples and options, see the package documentation

     

  8. Swap languages

    To swap languages, possibly by a dropdown, just use the same translate service.

    E.g.:

     

    . . . 

    changeLanguage(lang: string) {

           this.translate.use(lang);

    }

     

  9. Multiple font-family support (optional)

    A scenario I faced is the font-family I selected did not support some languages.

    A workaround I used was to leverage another font family (that looked similar) for the languages that are not supported in the original font.

     

    To do this, I leveraged “unicode-range” argument in css cascading.

     

     

    @font-face {

        font-family: ‘Brandon Grotesque Light’;

        font-style: normal;

        font-weight: normal;

        src: local(‘Brandon Grotesque Light’),

            url(‘brandon-grotesque-light.woff’) format(‘woff’)

    }

     

    @font-face {

        font-family: ‘Brandon Grotesque Light’;

        font-style: normal;

        font-weight: normal;

        src: local(‘Brandon Grotesque Light’),

            url(‘Montserrat-Light.ttf’) format(‘truetype’);

        unicode-range: U+0400-04FF, U+0500-052F, U+2DE0–2DFF, U+A640–A69F, U+1C80–1C8F, U+1D2B, U+1D78, U+FE2E–FE2F;

    }

     

    Now I could import and use this one font-family that would hot-swap another for the unsupported language. E.g.:

     

     

    $font-brandon-grotesque-light: “Brandon Grotesque Light”;

     

    . . .

    body {

        font-family: $font-brandon-grotesque-light;                                                                    

    }

     

     

     

     

Join The Discussion