6

I'm localizing my Angular app using Angular's i18n tools, which extract text from HTML templates into an xlf file, and then build a localized version of the whole app using AOT (ahead of time compilation).

My question is: Can is use this framework to extract string literals in typescript code, so they are listed in the same xlf file and replaced in the localized AOT build?

Ideally, I'd like to write something like this in my typescript code:

foo() {
   this.bar = i18n('baz');

and the string 'baz' would be listed in the xlf file I send to my translator.

Alternatively, if this isn't possible, is there a library that does something similar? I.e. extract strings from typescript code into an xlf file, then replaces them either at runtime or during build?

4
  • 1
    github.com/ngx-translate/i18n-polyfill Commented Mar 6, 2018 at 7:09
  • @JBNizet: I think this is exactly what I've been looking for, since there's no native support in Angular (yet). If you write an answer, I'll accept it. Commented Mar 6, 2018 at 11:00
  • How did you use it? The only thing I've found in its description is using string interpoation, which is totally useless. Is there any way to get values from translations .xlf files? I've manged to extract the ids to files but have no idea on how to use them Commented Jul 10, 2019 at 14:46
  • @Konstantin, see my answer below Commented Apr 3, 2020 at 7:22

4 Answers 4

10

I can confirm what @JB Nizet is referring to in his answer is now working in Angular 9, so this works:

  foo() {
    const appTitle = $localize`:@@siteTitle:Example Title`;
    // appTitle is now translated based on locale

    titleService.setTitle(appTitle); 
  }

You can read more about it here https://github.com/angular/angular/blob/master/packages/localize/init/index.ts

Sign up to request clarification or add additional context in comments.

1 Comment

5

There is no official support yet, but Olivier Combe, who is both the writer of ngx-translate (that you could use), and a member of the Angular team responsible for i18n, has written a speculative polyfill, that you could use.

Comments

1

$localize uses this mechanic to let us write:

@Component({
  template: '{{ title }}'
})
export class HomeComponent {
  title = $localize`You have 10 users`;
}

Note that you don’t have to import the function. As long as you add import '@angular/localize/init' once in your application, $localize will be added to the global object.

You can then translate the message the same way you would for a template. But, right now (v9.0.0), the CLI does not extract these messages with the xi18n command as it does for templates.

If you serve the application and no translation is found, $localize simply displays the original string, and logs a warning in the console:

No translation found for "6480943972743237078" ("You have 10 users").

So you have to manually add it to your messages.fr.xlf with the given ID if you want to try:

<trans-unit id="6480943972743237078">
  <source>You have 10 users</source>
  <target>Vous avez 10 utilisateurs</target>
</trans-unit>

The template of my HomeComponent then displays Vous avez 10 utilisateurs!

check this link : https://blog.ninja-squad.com/2019/12/10/angular-localize/

2 Comments

This should now be the accepted answer, using Angular 11 and Ivy.
PS: if you don't want to edit your translation files manually, you could use ngx-i18nsupport / xliffmerge: github.com/martinroob/ngx-i18nsupport/wiki/…
0

I agree with @azerafati and his mentioned approach that's newly introduced in Angular 9 with Ivy, which is also not properly documented in Angular I18N docs because it needs to be properly equipped and one of the most important thing it lacks is the extraction which is not supported by Angular yet.

If you run the extraction command(xi18n) for your app you will get the extracted strings to an xlf format file from all the html files where you have mentioned the i18n attribute. But it won't extract anything you have mentioned in your .ts file as above mentioned by @azerafati.

How to acheive? Yah there always a way around, I have found one. Let me know if this helps:

Create a dummy component which should not be part of any routes and this should not appear in UI.Make sure its just to include it in the app.module or respective feature modules so that it can be translated during extraction. Define all your string that need to be translated in (.ts) file and refer those using the $localize approach. And you are ready to go.

translate.component.html

<div>
  <label i18n="@@Home.RuntimeTrans">
     This is runtime translation string
  </label>
</div>

And use it in the code as

home.component.ts

  this.foo = $localize`:@@Home.RuntimeTrans:`

And then if you need you can use the same in any html page as interpolation.

1 Comment

Yuck! That breaks code locality in the worst way... Hopefully this will change in some future version. I'll stick with the older Angular version and use the i18n-polyfill until then

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.