Packaging an Angular library with i18n support
Asked Answered
W

2

32

Angular's i18n is great, and tools like ng-packagr makes component library packaging extremely easy, but can they be combined?

What if i want to package and distribute a component library having translatable components? Is it possible? How do I package such a library? Will translation files be shipped together with the package, or should they be defined in the main app?

It'd be great if someone could point me at some doc. Thanks

Worldbeater answered 15/3, 2018 at 14:41 Comment(2)
I am facing the same problem now. Have you found a solution?Butt
Here's a simple solution I've found out! https://mcmap.net/q/470164/-how-can-i-localize-my-angular-11-libraryPelagias
R
8

When you generate a translation file for the main app with the CLI (with ng xi18n), elements with the attribute i18n in the library are imported in the translation file. You can then define the translations in the main app.

Reclaim answered 5/6, 2018 at 7:0 Comment(6)
That is correct. But there is another way where you can define the translations in your component library, thats how some ng elements do, like ng bootstrap. It switch locale languages based on the server locale configuration.Martimartial
How did you solve this warning "No name was provided for external module '@ngx-translate/i18n-polyfill' in output.globals – guessing 'i18nPolyfill'" ? I ahve tried to add it to paths but it won't work. If I add it to ng-package.json in umdModuleIds list then it will go away, but is this correct way to use it. Maybe this is new topic but I think you maybe have already solve it.Trivalent
But what if I want to distribute official translations of my library with it? How do I approach this?Lenoralenore
I have yet to start preparing my library for distribution, once I get to that stage I might come up with something. Will keep in mind posting here, although I'm not sure it would be any time soon :)Lenoralenore
Also interested in this. Haven't found anything about distributing translations with an Angular library.Mcclees
@Lenoralenore did you find a way to do it?Grahamgrahame
B
-1

There are two ways of doing so - statically providing the assets and bundling on build time or configuring translation path on runtime.

  1. In order to statically include files on build time, you just use setTranslations in the code, as mentioned in https://github.com/ngx-translate/core docs. Then, you can just bundle your translations with the code.

  2. Better would be to let consumer know what to use. In order to properly be able to provide path to translation files (assuming standard structure, where every translation is residing in a separate file containing language in the name), you can do something as follows:

    interface TranslationsConfig {
      prefix: string;
      suffix: string;
    }
    
    export const TRANSLATIONS_CONFIG = new InjectionToken('TRANSLATIONS_CONFIG');
    
    @NgModule({
      declarations: [],
      imports: [
        NgxTranslateModule,
      ],
      exports: [
        NgxTranslateModule,
      ]
    })
    export class TranslateModule {
      public static forRoot(config: TranslationsConfig): ModuleWithProviders {
        return {
          ngModule: TranslateModule,
          providers: [
            {
              provide: TRANSLATIONS_CONFIG,
              useValue: config
            },
            ...NgxTranslateModule.forRoot({
              loader: {
                provide: TranslateLoader,
                useFactory: HttpLoaderFactory,
                deps: [HttpClient, TRANSLATIONS_CONFIG]
            }
          }).providers
        ],
      };
    }
    

    }

This code makes sure that when building library, AOT will be able to resolve types (hence InjectionToken etc.) and allows to create custom translations loader.

Now it's only up to you to implement loader factory or class that will use the config! This is mine (I'm using POs for my translations):

export function HttpLoaderFactory(http: HttpClient, config: TranslationsConfig) {
  return new TranslatePoHttpLoader(http, config.prefix, config.suffix);
}

Please do remember to export every class and function that you're using in the module as that's prerequisite for AOT (and libraries are built with AOT by default).

To use this whole solution, wherever you use your main library module or this translation module, you can just call TranslateModule.forRoot(/* Your config here */). If this is not the main module exported, more on using hierarchical modules with forRoot here:

How to use .forRoot() within feature modules hierarchy

Borgia answered 5/4, 2019 at 10:2 Comment(2)
Should still we use the ng-packagr tool in Angular 7.2 when packaging a library ?Overseas
Question was not about ngx-translateObellia

© 2022 - 2024 — McMap. All rights reserved.