Translation of custom angular packages

Without shipping a translation file

Marius Schröder
Aug 5 · 5 min read

At the moment I work a lot with Angular packages, which contain different components built upon default material components by myself. Those smaller packages are served to make the overall project a little bit cleaner and to differentiate the various sub projects.

Eventually you get to the point where you have to remember that the components may need to become multilingual.

Considering of translation in the Angular context, you first encounter concepts such as Internationalization (i18n) or ngx-translate. Even if the i18n-out-of-the-box-solution is not suitable for our application, ngx-translate has emerged as the better option for me personally, as it is much easier to handle and does not generate files on the go.

Reusability comes first

Since this topic was created for one reason only (reusability), we attach great importance to this as well. Therefore, it is necessary to create a solid base, where we can built upon. So we are creating a new Angular application and a library project as well — really fast forward.

ng new translation


ng generate library ngx-translation


Other options (angular routing, hammerJS, stylesheet type) do not matter, because we won’t generate reusable components in this package.

Because the project will be based on ngx-translate we will need to install those two dependencies:

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

After a few seconds of waiting, you should be good to go.

These dependencies should best be declared in the “package.jsonof the library as dependencies or at least as peer dependencies, since this necessarily depends on it.

Since I am also want to translate angular material components like the paginator, I’ve also added the @angular/material peer dependency.

I’ve also written a medium blog post regarding dependencies and versioning.

Also we are deleting the component files from the folder, because we only need a module and a service.

This is the base of the project. Next we will continue with the base of the translation.

The idea behind

We will write a custom loader which is reading the basic translation files () from the application and merges them with the translation provided by each component. Components, which need a translation should register at a registry service so we can read out the translation for each component.

Sequence of the idea

Basic translation with ngx-translate

As a next step, we will need a module, which we can later import in other custom modules or projects. Due the good documentation of ngx-translate for shared modules it is very simple. So first, we will basically generate a shared module in our library, which will later import, export and provide us with everything we need, to translate custom components.

Shared module named “translation.module.ts”

It basically imports the TranslateModule of @ngx-translate/core, defines the TranslationLoader (which is our own) to use, provides the application with a TranslationRegistryService and an initialization function (for setting default parameters).

TranslationRegistryService

The TranslationRegistryService should be a simple service which is providing the Loader with the translations of components. So basically it consists of two methods. One method needs to save a binding to the registered component and another method needs to collect up the translations.

Registry Service

To identify each component, I’ve added an identification (“id”) property to it. Also I chose a subject to notify my translation service, when a new component “registered”.

TranslationLoader

The TranslationLoader is doing the real work. It has to load the normal translation files (under ./assets/i18n/*.json) and merge them with the provided translation objects of registered components. Let’s go to the actual coding.

The most necessary thing here is the merge function. Everything stands and falls with the merge function, which combines the basic translation object from the JSON file with the translation objects of the components.

A good example can be found here:

https://stackoverflow.com/a/34749873/4198052

Since we provided our custom loader in the module, each time, the translation is getting reloaded (by trigger or something else), the loader is getting called. The rest of our code of the custom loader is looking like the following, which is using our merge functions:

TranslationLoader

Our translation loader requests the newest version of the translation files () and uses the merge functions to combine those objects with the language object of the translation registry.

Last but not least, we could provide the developer with an abstract class, so he is not missing out the necessary functions:

TranslationBase

The developer can now extend this abstract class from his components. He has to provide an ‘id’, which just can be the name of the component.

Caution: It’s not working with this.constructor.name because this is not available for production builds.

Furthermore its required to pass in a TranslationRegistry-Instance for registering the translation. If this is all done, it can be used as simple as the following code.

Extending TranslationBase

Additional

In some cases, it is necessary to reload the current language, which can be done by ngx-translate service.

If this is all done, the translation can be used normally done by ngx-translate.

Example

In my next story, i will describe how to translate material components like the Material Paginator

Conclusion

Due to this implementation and the extension of the custom loader, its pretty easy to translate custom components which ship their own translation and still preserve the advantages of the basic ngx-translate. Go multilingual!

Special thanks to Thomas Sebastian Jensen, which provided me with feedback.

Please also feel free to provide feedback.

medialesson

We help our customers design, architect, develop and operate modern, intelligent, beautiful and usable apps on any platform powered by the Cloud, IoT and AI.

Thanks to Sebastian Jensen

Marius Schröder

Written by

Software Developer @ medialesson GmbH

medialesson

We help our customers design, architect, develop and operate modern, intelligent, beautiful and usable apps on any platform powered by the Cloud, IoT and AI.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade