How can I localize my Angular 11 library?

5.5k views Asked by At

I'm refactoring my Angular 11 application into libraries. My regular application is localized using @angular/localize as a dev dependency, so I have made use of the $localize directive in part of my code. I need to move this code with this directive into a library, but I can't figure out how to do this.

In my library's package.json file, I've added a peer-dependency on @angular/localize to match the devDependency in my application:

{
  "name": "example",
  "version": "0.0.1",
  "peerDependencies": {
    "@angular/common": "^11.0.0",
    "@angular/core": "^11.0.0",
    "@angular/localize": "~11.0.0"
  },
  "dependencies": {
    "tslib": "^2.0.0"
  }
}

However the compiler reports that it can't find $localize when I try to do ng build <library name>.

× Compiling TypeScript sources through NGC
ERROR: projects/example/src/lib/example.service.ts:52:23 - error TS2304: Cannot find name '$localize'.

52         description = $localize `example localized text`;
                         ~~~~~~~~~

How can I use the $localize directive in my library?

>ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 11.0.1
Node: 12.18.3
OS: win32 x64

Angular: 11.0.0
... animations, cdk, common, compiler, compiler-cli, core, forms
... localize, material, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1100.1
@angular-devkit/build-angular   0.1100.1
@angular-devkit/core            11.0.1
@angular-devkit/schematics      11.0.1
@angular/cli                    11.0.1
@schematics/angular             11.0.1
@schematics/update              0.1100.1
ng-packagr                      11.0.3
rxjs                            6.6.3
typescript                      4.0.5
5

There are 5 answers

2
Carlos de Cumont On

Not sure, try to add this to your entry file:

import '@angular/localize/init';
2
user1 On

You have to put import '@angular/localize/init'; inside src/polyfills.ts of the main project. Also have to configure the angular.json for your main project (not the library) to be able to use the localization.

You have to configure the angular.json like so depending on your locales:

"projects": {
    "the-name-of-your-project": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "scss"
        }
      },
      "i18n": {
        "sourceLocale": "en-US",
        "locales": {
          "fr": "fr-messages.xlf"
        }
      },
      ...
      "architect": {
        ...
        "configurations": {
            "fr": { "localize": ["fr"] },
            ...
         }
      },
      "serve": {
          ...
          "configurations": {
            "fr": {
                "browserTarget": "angular-material-timepicker:build:fr"
              }
           }
           ...
       }

}

You can check out the different sections that I had in my project and with which everything was working by clicking these links: 1, 2, 3 or view the whole file.

The problem with this approach is that if you have it as a dependency, all the users of your library will have to install it and put and configure it manually as well, even if they don't need it.

I'm managing this angular material timepicker module and I removed this dependency in favour of using this - Mark element attributes for translations. Notice the i18n-title attribute:

<img [src]="logo" i18n-title title="Angular logo" />

So now all users have to do is just use the i18n-<name_of_input> and everything works fine and you don't need to bother dealing with localize.

So if your library component/directive has an input lets say title that you want to be translated you can just put i18n-title="some title|An introduction title for this sample@@introductionComponent" and everything works great.

0
Ion Prodan On

Solved it by:

  1. Creating a typings.d.ts file next to the library's src folder.
  2. Put inside: declare function $localize(messageParts: TemplateStringsArray, ...expressions: readonly any[]): string;

Error disappear and compiler finds the translation parts with no problem.

0
Salahuddin Ahmed On

Try installing @angular/localize package first

npm install @angular/localize

Then, try importing @angular/localize/init in your polyfills.ts file

import @angular/localize/init
2
Mohammad Dayyan On

First: install @angular/localize package.

npm i @angular/localize -D

Second: Find entryFile in your ng-package.json file, in my case public-api.ts

{
  "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
  "dest": "../../dist/ngx-my-lib",
  "lib": {
    "entryFile": "src/public-api.ts" // <=== this line
  }
}

Third: add import '@angular/localize/init'; to your entryFile, in my case public-api.ts

import '@angular/localize/init'; // <=== this line

export * from './lib/ngx-my-lib.service';
export * from './lib/ngx-my-lib.component';
export * from './lib/ngx-my-lib.module';