Search Engine Optimization (SEO) is important for many Angular single-page applications (SPAs). You can build SEO-friendly Angular websites with Angular Universal, but how do you make your app SEO-friendly in every language your website supports? Google, Yandex, and Baidu, might request your pages in English, Spanish, Russian, or Chinese: how do you make your server-side rendering return the correct language?

The answer is ngx-translate, the internationalization (i18n) and localization library for Angular. This module makes it easy to use translation files that provide the correct language for both client-side and server-side rendering. This post will show you how to use it.

In this post we will:

Create an Angular application with one component, the home page

Add server-side rendering for SEO purposes with Angular Universal

Set up internationalization in four languages with ngx-translate

To accomplish the tasks in this post you will need to install the following:

Set up the Angular project and run Hello World!

Every Angular project begins with installation and initialization of the packages. Type the following at the command prompt:

ng new angular-universal-i18n --style css --routing false

When the project is initialized, navigate to its directory:

cd angular-universal-i18n

And run the application by typing:

ng serve -o

You should see following output in the console:

** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ ** Date: 2018-10-29T08:58:37.685Z

Hash: cb54e4608cfb1115882b

Time: 7682ms

chunk {main} main.js, main.js.map (main) 10.7 kB [initial] [rendered]

chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 227 kB [initial] [rendered]

chunk {runtime} runtime.js, runtime.js.map (runtime) 5.22 kB [entry] [rendered]

chunk {styles} styles.js, styles.js.map (styles) 15.9 kB [initial] [rendered]

chunk {vendor} vendor.js, vendor.js.map (vendor) 3.29 MB [initial] [rendered]

The -o flag will open the application in your default browser. (In Chrome version 63 or higher you must set flags to open HTTP links and sites without a valid security certificate, such as localhost). You can navigate manually to the URL provided in the command output.

You should see the following screen in your browser:

Implement server-side rendering with Angular Universal

Now we are ready to add server-side rendering to our application with Angular Universal, a technology that renders web pages on the server so your site’s pages can be quickly and easily read by a search engine crawler. To install it, execute this command:

ng add @ng-toolkit/universal

Verify server-side rendering is working

Check to see if Angular Universal is working correctly by running the app and performing a curl request on it:

npm run build:prod;npm run server curl http://localhost:8080

If you don’t want to use curl you can open the URL in a browser and inspect the page source. The results, as follows, should be the same:

If you want to catch up to this step:



cd angular-universal-i18n

git co step1

npm install

ng serve -o git clone https://github.com/maciejtreder/angular-universal-i18n.git cd angular-universal-i18ngit co step1npm installng serve -o

Add internationalization to the app with ngx-translate

Let’s make our application more friendly for users around the world. To achieve that, we are going to add internationalization (i18n) to it with the ngx-translate library. We will provide our website visitors with clickable links they can use to switch between different translations. Those translations will be loaded from .json files for each language by ngx-translate . For each translate key in our app.component.html template a translated value will be injected.

The first step is installation of dependencies:

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

Create the following file structure for the translations:

src/assets/i18n/en.json

src/assets/i18n/es.json

src/assets/i18n/ru.json

src/assets/i18n/zh.json

Place the following key-value pairs in each file. For src/assets/i18n/en.json :

{

"Welcome to": "Welcome to",

"Here are some links to help you start": "Here are some links to help you start"

}

src/assets/i18n/es.json :

{

"Welcome to": "Bienvenido a",

"Here are some links to help you start": "Aquí hay algunos enlaces para ayudarte a comenzar"

}

src/assets/i18n/ru.json :

{

"Welcome to": "Добро пожаловать в",

"Here are some links to help you start": "Вот несколько ссылок, которые помогут вам начать"

}

src/assets/i18n/zh.json :

{

"Welcome to": "欢迎来到",

"Here are some links to help you start": "以下是一些可帮助您入门的链接"

}

We have provided translations in four languages. Now we’ll implement the translation mechanism in our application. Import the ngx-translate module and translations loader by replacing the contents of src/app/app.browser.module.ts with the following code:

What we did here is import HttpClientModule from the @angular/common/http library. We need it to provide an HttpClient , which is injected into the factory method and used for loading translation files using HTTP requests:

Finally, we import the TranslateModule and provide our loader into it:

We also need to import TranslateModule into the src/app/app.module.ts file:

Replace the code in the src/app/app.component.html template with the following to provide translation keys and links for switching between languages:

The final step in providing internationalization in the browser-side code is to implement the switchLanguage method in our component and provide default translations for the active region. Make following changes in the src/app/app.component.ts :

ng serve -o

After navigating to http://localhost:4200 and changing the selected language to Español we can see:

If you want to catch up to this step:



cd angular-universal-i18n

git co step2

npm install

ng serve -o git clone https://github.com/maciejtreder/angular-universal-i18n.git cd angular-universal-i18ngit co step2npm installng serve -o

Add server-side internationalization

Check to see if our client-side implementation broke anything on the server side. Start the app in server mode by running the following commands:

npm run build:prod

npm run server

After navigating to http://localhost:8080 we can see that our app is no longer working:

More error information can be seen in the console:

To fix this issue we need to provide TranslateModule in the server module as well. Make following changes in the src/app/app.server.module.ts :

We also need to make changes in src/app/app.component.ts to implement i18n on the server side. Replace the contents with the following code:

The additional code determines the current language for the user agent by reading the HTTP accept-language header sent by user agent (browser or web crawler) when requesting the page at the URI specified by the user agent. To retrieve this header we need to inject a @REQUEST provided in @nguniversal/express-engine/tokens .

After that we determine if we are executing code on the browser side or server side by using the isPlatformBrowser method together with the @PLATFORM_ID token. If we are on the browser side we set the language in the same way as previously, by retrieving it from the translate service. If we are on the server side we read it from the header with:

lang = (this.request.headers['accept-language'] || '').substring(0, 2);

We also need to make small change in the typescript configuration file, src/tsconfig.app.json :

We added the node value to the types section. We need that because we are using fs to load translation files directly from the file-system when we are performing server-side rendering.

Test server-side internationalization rendering

We are done with translations on the server side. Check it out by running the application and performing a curl request with a customized header. Build and run the app as follows:

npm run build:prod

npm run server

Then make the curl request specifying Russian (ru_RU) as the current user agent language:

curl http://localhost:8080 --header "accept-language: ru_RU"

Alternately, you can inspect the page source in your browser’s developer tools after clicking Pусский язык on the home page. Note, however, that using “View page source” will reload the page and show you the English (or your default) language version.

The results should look like this:

Yay! As we expect, our website is rendered on the server side, and the Russian translations have been applied!

If you want to catch up to this step:



cd angular-universal-i18n

git co step3

npm install

npm run build:prod

npm run server git clone https://github.com/maciejtreder/angular-universal-i18n.git cd angular-universal-i18ngit co step3npm installnpm run build:prodnpm run server

Summary

Today we covered an important challenge for all mature applications: internationalization. As you can see; you can bring internationalization to server-side rendering, making your application search engine optimized in every language that you support.

This post is originally published on the Twilio Blog. If you want to learn more about Angular Universal techniques, check out my post on the Twilio blog: Getting Started with Serverless Angular Universal on AWS Lambda.

The GitHub repository, for the code used in this post can be found here: https://github.com/maciejtreder/angular-universal-i18n. You can also contact me via contact@maciejtreder.com, https://www.maciejtreder.com or @maciejtreder (GitHub, Twitter, StackOverflow, LinkedIn).