Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why ngx-translate exists if we already have built-in Angular2+ i18n ? #495

Closed
chaouiy opened this issue Apr 3, 2017 · 180 comments
Closed

Why ngx-translate exists if we already have built-in Angular2+ i18n ? #495

chaouiy opened this issue Apr 3, 2017 · 180 comments

Comments

@chaouiy
Copy link

chaouiy commented Apr 3, 2017

why should someone choose this package instead of the official i18n module ?

@SamVerschueren
Copy link
Collaborator

Because you don't always want to reload your entire application when someone switches the language. Angular i18n forces you to build the application per language.

@chaouiy
Copy link
Author

chaouiy commented Apr 3, 2017

As mentioned in the official documentation we have the choice between JIT/AOT compilation

@jlberrocal
Copy link
Contributor

Because they aim to different purposes, for example try to change your application language with a click with the native library of angular

@ocombe
Copy link
Collaborator

ocombe commented Apr 3, 2017

Hello,

this is a good question, and as I am working on i18n in the Angular core team I am probably the best to answer this.

The idea behind this lib has always been to provide support for i18n until Angular catches up, after that this lib will probably be deprecated. For now, there are still a few differences between Angular i18n and this library:

  • Angular only works with one language at a time, you have to completely reload the application to change the lang. The JIT support only means that it works with JIT, but you still have to provide the translations at bootstrap because it will replace the text in your templates during the compilation whereas this lib uses bindings, which means that you can change the translations at any time. The downside is that bindings take memory, so the Angular way is more performant. But if you use OnPush for your components you will probably never notice the difference
  • Angular only supports using i18n in your templates for now, I'm working on the feature that will allow you to use it in your code, but it's still a work in progress. This lib works both in code and templates
  • Angular supports either XLIFF or XMB (both are XML formats), whereas this lib supports JSON by default but you can write your own loader to support any format that you want (there's a loader for PO files for example)
  • Angular supports ICU expressions (plurals and select), but this library doesn't
  • Angular supports html placeholders including angular code, whereas this library only supports regular html (because it's executed at runtime, and not during compilation, and there is no $compile in Angular like there was in AngularJS)
  • The API of this library is more complete because it is executed at runtime it can offer more things (observables, events, ...) which Angular doesn't have (but doesn't really need given that you can not change the translations)

@chaouiy
Copy link
Author

chaouiy commented Apr 3, 2017

Perfect Answser TY !

@chaouiy chaouiy closed this as completed Apr 3, 2017
@josersleal
Copy link

So why dont you at angular call the guys from ngx and integrate ngx instead of reinventing the wheel?
Ins't that the point of open source?

@ocombe
Copy link
Collaborator

ocombe commented May 15, 2017

@josersleal that's exactly what they did, the angular team hired me to improve i18n for everyone
But there is no way to integrate my lib directly into the core, after working for 3 months for the core team I can tell you that Angular i18n is much more complex and elaborate than my lib. It handles a lot of more complex stuff, and it does it without all the bugs and shortcomings that my lib has.
I understand that it's frustrating that the core doesn't evolve as fast as what a library can do, but there are reasons for that, and the first one is that you cannot implement something and change it whenever you see that you forgot to include a use case. Everything has to be thoroughly planned and thought.
Still, you will have most of the things that this lib can do in the core in the future, but it might take a year before we get there unfortunately. The good news is that it's going to be much better than my naive implementation.

@josersleal
Copy link

josersleal commented May 15, 2017 via email

@jaska45
Copy link

jaska45 commented Aug 1, 2017

Olivier has done a great job. The native Angular I18N has many advantages over all 3rd party I18N libraries.

  • Minimal impact to templates. You don't have to refactor all elements to use translator pipe but simply mark them with i18n attributes.
  • The original string in in the template an not in resource file such as .json
  • Extract tool will extract strings from templates and hopefully soon from .ts too.
  • Extract tool extracts source code location and optional description and meaning. Developers can easily add comments that are essential in many cases.

Of course this approach has some limitations:

  • Cannot reuse the same string on multiple places. That would be a nice new features
  • Source code cannot easily use the string defined in the template. Of course code can find the DOM element and get the string from there. Would be a nice to have an easy way to refer a template string from .ts.

@aghilesh
Copy link

aghilesh commented Aug 2, 2017

@ocombe : Is there any plan to add runtime language switching feature on i18n+AOT ? Right now application is planned to use ngx-translate over i18n because of the run-time switching constraint.

@ocombe
Copy link
Collaborator

ocombe commented Aug 9, 2017 via email

@imraqes
Copy link

imraqes commented Aug 16, 2017

How dificult is it to move from ngx-translate to angular i18n, I have already implemented ngx-translate so if I have to change is it too much work around ?

@jlberrocal
Copy link
Contributor

is a totally different structure, however i don't see a possible reason for change ngx-translate for native i18n

@neridonk
Copy link

Does anyone know when this : Angular only supports using i18n in your templates for now, I'm working on the feature that will allow you to use it in your code, but it's still a work in progress.

will happen?

@ocombe
Copy link
Collaborator

ocombe commented Aug 29, 2017

It won't be for 5.0, it should be before 6.0 (so before march 2018). Unfortunately I don't have a more precise date

@DerekJDev
Copy link

@ocombe My application is currently using this library to do the translations, would you recommend switching to the angular i18n to not run into future problems? Would it be worth the time to switch over?

@ocombe
Copy link
Collaborator

ocombe commented Sep 21, 2017

if you can (meaning if you don't need translations in the code), it's definitively worth it yes

@DerekJDev
Copy link

Good to know @ocombe , thanks!

@jasonever
Copy link

@ocombe

I need your advice , i'm building a chat application (Web and Mobile app) .. So i'm confused about going ahead with using Angular i18n or Ng-Translator ? especially i saw your comment in github before that in March2018 Angular will release an edition that i18n has more features like dynamic load feature same like NG-Translator ..so i will be able to switch to another language without reloading the app (in realtime) is this correct or what ? i need your advice .. Thanks :)

@ocombe
Copy link
Collaborator

ocombe commented Jan 20, 2018

The way it's going, you'll never be able to dynamically change the language in Angular. It's clearly not a priority for Google and they don't think it's a problem if you have to reload the app completely to change the locale.

@denizengin
Copy link

@ocombe How about being able to do translations in code, is that likely to arrive soon to Angular i18n?

@ocombe
Copy link
Collaborator

ocombe commented Jan 24, 2018

Yes that's coming soon, we are adding runtime i18n in v6.0 and then code translations right after that (or maybe at the same time)

@beachjf
Copy link

beachjf commented Feb 4, 2018

The main problem with the fact that every language has their own app is it's really difficult to make the app share the same session. I'm actually facing this issue with angular 5 app combinnr with identify server

@ibagaric
Copy link

ibagaric commented Feb 5, 2018

@ocombe I am in the moment where i need to decide, should I use Angular i18n or ngx-translate.
In the future, will Angular i18n have possibility to export translates to JSON or PO file.
Is there any easy way to read XLIFF or XMB format with some GUI so it can be easily given to translators.
What lib to use, what is your advice? Thanks in advance!

@ocombe
Copy link
Collaborator

ocombe commented Feb 5, 2018

In the future, will Angular i18n have possibility to export translates to JSON or PO file.

yes, I'm lobbying hard to get this, and we'll have it one way or another (either we support it ourselves, or we open the API and I'll make a lib for it)

Is there any easy way to read XLIFF or XMB format with some GUI so it can be easily given to translators.

there are a lot of websites for translators that you can use, some of them have a free tiers
some good ones include:

  • poeditor (claims to supports angular)
  • crowdin (free for open source)
  • oneskyapp (unlimited free tiers as long as you translate yourself)

What lib to use, what is your advice? Thanks in advance!

if you can use the official implementation, then use that, it's more performant, the limitation is that it's limited to what is offered whereas with ngx translate you can always extend it via plugins, or even fork it if necessary

@jaska45
Copy link

jaska45 commented Feb 6, 2018

Please do not add any new formats! You already have three: XMB, XLIFF 1.2 and XLIFF 2.0. Most other platforms have only one :-)

Almost all online translation services claim to support XLIFF. The reality is that XLIFF is very complex format and Angular's extract tool can create pretty complex XLIFF. Especially if you have plurals, genders, links or inline formatting elements. In addition Angular XLIFF files contain many proprietary properties such as meaning and location. What I have noticed is that a generic XLIFF parser/scanner cannot properly handle Angular's resource files. This is why it is better that the localization tool uses a dedicated Angular parser that can property handle the resource files.

But this is perfectly fine. The main task of a localization tools is to scan the source files and in that process extract all information that is needed. I am glad that Angular resources contain all the information needed to fully extract strings and enable continuous localization where translation and development can work independently to each other.

@sujithgowda
Copy link

@ocombe thank you so much.

@ArulRozario
Copy link

ArulRozario commented Jan 6, 2020

@ocombe is it possible to have i18n in angular libraries. you mentioned it in one of your talks. If so please suggest some sources for reference.

@ocombe
Copy link
Collaborator

ocombe commented Jan 6, 2020

You can add i18n to your libraries with the current v9 RC, just add i18n attributes on the template text to translate, and use $localize in your code.
But if you use $localize, your library will only work with ivy (and make sure to add @angular/localize as a peer dependency).
From there, you can either add the translations manually (the current CLI extraction won't pick them up), or use my lib @locl/cli to extract the text to translate.

@karolinatomczak
Copy link

karolinatomczak commented Jan 8, 2020

It will be available with ivy in Angular v9. The only thing that won't be possible is to change the language without reloading the app...

@ocombe Does it mean that not only template text will be translatable but also dynamically passed messages? I have a variable in the component.ts and displaying it {{ variableName }} in the template. Would this work or would I need to put all the possible text in the template and use some ngIfs to display the correct one?

@ocombe
Copy link
Collaborator

ocombe commented Jan 8, 2020

yes, code translations work in v9 (what you call "dynamically passed messages"), the syntax is the following:

const text = $localize`some dynamic text in your code with ${variableName}`

@karolinatomczak
Copy link

@ocombe Thank you. One more thing, what about splitting the translations files per module? We have a shell app that uses many lazy loaded modules and would need to load only the translations we need. Is it possible with i18n? (When I try to find an answer it always mentions ngx-translate so sorry if it's described somewhere)

@ocombe
Copy link
Collaborator

ocombe commented Jan 29, 2020

Localize + Locl allows you to lazy load translations with a module when you lazy load a route, I'm working on adding an example to make it easier (and I'll also implement some helpers to make it smoother).
You can extract translations per module with the Locl cli extract tool (meaning that the extraction tool generates one file per module).

@shral
Copy link

shral commented Feb 3, 2020

@ocombe Thank you for the information and your work!
Do you know if, with the currently available version of Angular (9.0.0-rc.13), one can translate a dynamic string (that is coming, let say, from a JSON file)?
(I have many json schema files with descriptions and titles, that are loaded dynamically (that are used for other things too, not only Angular UI, so adding internationalization id-s in there is not really an option in my case)).

@ocombe
Copy link
Collaborator

ocombe commented Feb 5, 2020

@shral yes, you can do totally do that with just Angular i18n, but you'll need to use Locl to load the translation files at runtime (Angular i18n only allows you to load those at build time for now)...
And you need to load the translations files before you load the module that contains the dynamic translations, so if it's part of your main app then you need to load them before bootstrap, if it's part of a lazy loaded module then you can load them when you lazy load the module

@shral
Copy link

shral commented Feb 6, 2020

Thank you @ocombe for your response!
I'm loading the JSON Schema files only if I need them (for example only on a specific click event), but how can I translate the text that's coming from JSON. I have tried $localize like this:

    Object.keys(jsonData).forEach(key=>{
      jsonData[key] = $localize jsonData[key];  //Hier I'm getting an error.. one of the error is that it needs an `TemplateStringsArray` instead of string but how can I convert a string to 'TemplateStringsArray'?
    })
  • How can I translate those files, (I have looked on your demo but couldn't find something that it could help me)?
  • So far I can see the function getTranslations() in locl/core is just loading the JSON file, but that I can do with the angular HttpClient module too, why should I use your function?
  • In the getTranslations() you are calling platformBrowserDynamic().bootstrapModule where should this function be located, how do you use that when you have a project generated with angular-cli (where the bootstrap is hapening in the bootstrap parameter of @NgModule in app.module.ts?

@pdbruno
Copy link

pdbruno commented Mar 17, 2020

Hi @ocombe , I'm starting a large-scale Angular project from scratch and really want to get internationalization right from the start. From what I've read so far, a combination of $localize, the i18n template tags and the loadTranslations function seems to be the best choice. Are these functionalities going to get long-term support from the official Angular team? Will there be any new official features promoting this way of approaching i18n? Thank you very much for your contribution!

@ocombe
Copy link
Collaborator

ocombe commented Mar 19, 2020

@pdbruno yes, this is going to be supported like any other official package.
There will be new features, Pete B. Darwin from the Angular team is working on adding more support for runtime translations, and they also need to update the docs.

@ghost
Copy link

ghost commented Apr 24, 2020

I need to split a language file into several separate files. It is possible?

@kazeshini178
Copy link

You can add i18n to your libraries with the current v9 RC, just add i18n attributes on the template text to translate, and use $localize in your code.
But if you use $localize, your library will only work with ivy (and make sure to add @angular/localize as a peer dependency).

@ocombe What would I need to include in the library setting to allow for this to work? Currently if i add $localize to my library and build I get an error saying Cannot find name $localize.
Cant seem to find what I'm missing

@ranitg
Copy link

ranitg commented Jul 5, 2020

Localize + Locl allows you to lazy load translations with a module when you lazy load a route, I'm working on adding an example to make it easier (and I'll also implement some helpers to make it smoother).
You can extract translations per module with the Locl cli extract tool (meaning that the extraction tool generates one file per module).

@kazeshini178
Copy link

So that works when my module is included in the project and using lazy loading, currently my problem is when the module is external to the main application and lazy loaded in (include into the project as an npm dependency) to allow use to version our modules.
At that point using $localize in the code errors since the polyfill is not includes in the module, and angular doesnt recommend bundling polyfills in external modules.

@sorohan
Copy link

sorohan commented Jul 17, 2020

@kazeshini178 you can workaround this issue by declaring the $localize global in your library.

export type TranslateFn = (
  messageParts: TemplateStringsArray,
  expressions: readonly any[]
) => [TemplateStringsArray, readonly any[]];

export interface LocalizeFn {
  (messageParts: TemplateStringsArray, ...expressions: readonly any[]): string;
  translate?: TranslateFn;
  locale?: string;
}

declare const $localize: LocalizeFn;

I think the best thing would be if these types were provided in a type package (I've made a feature request and PR for it), so you can just add this to your library's tsconfig:

"types": [
      "@angular/localize"
    ],

@sorohan
Copy link

sorohan commented Jul 20, 2020

@kazeshini178, there is some info in this issue on a different workaround, for now, to include this where you're using $localize:

import type {} from '@angular/localize/init';

But that will still not bundle the $localize in your library. The application will still need to add the localize import to the polyfills.

@kazeshini178
Copy link

@sorohan, didnt even think of just "mocking" the interface that would be available main app. Thanks think that would work for me, will give it a go.

But that will still not bundle the $localize in your library. The application will still need to add the localize import to the polyfills

Thats perfect, and also what I would of expected

@s4m0r4m4
Copy link

@ocombe - just wanted to say thank you for this comment thread and all your hard work, this has helped clarify the right path forward for internationalization of my angular application.

@wzaieddev
Copy link

hi,
i'm new on angular, i would like to develop multi Language application using i18n build in module.
i followed the tutorial to do it and it works fine and i deploy the application to IIS web server by writing some instraction for URL Rewrite.

My question is: is there any way to detect user preferred browser language, when i used the ngx-translate libraery it was very easy to do it, how can i do the same thing with i18n ?

@AkourMohamed
Copy link

AkourMohamed commented Jan 27, 2021

hi,
i'm new on angular, i would like to develop multi Language application using i18n build in module.
i followed the tutorial to do it and it works fine and i deploy the application to IIS web server by writing some instraction for URL Rewrite.

My question is: is there any way to detect user preferred browser language, when i used the ngx-translate libraery it was very easy to do it, how can i do the same thing with i18n ?

same question.
can someone explain???

@dsnoeck
Copy link

dsnoeck commented Jan 28, 2021

Hello @AkourMohamed & @wzaieddev,
Here is my functionto get browser language:

this.availableLangs is a list of languages that I can use in my application, like: ['en', 'fr', 'es']

import concat from 'lodash-es/concat';
import filter from 'lodash-es/filter';
import first from 'lodash-es/first';
import intersection from 'lodash-es/intersection';
import isEmpty from 'lodash-es/isEmpty';
import isNil from 'lodash-es/isNil';

  /**
   * Get the first browser language
   */
  getFirstBrowserLang(): string {
    const cleanBrowserLangs = filter(this.getBrowserLanguages(), (lang: string) => {
      return !isNil(lang) && !isEmpty(lang);
    });
    const browserLangs: string[] = uniq(
      map(cleanBrowserLangs, (browserLang: string) => {
        // We don't manage localisation yet (i.e.: en-GB => en, FR -> fr)
        return lowerCase(replace(browserLang, /-.*/, ''));
      }),
    );

    return first(intersection(browserLangs, this.availableLangs));
  }

  /**
   * Get all languages of the browser
   */
  getBrowserLanguages(): string[] {
    const navigator: Navigator = window.navigator || window.clientInformation || null;

    return concat(navigator.language, navigator.languages);
  }

@wzaieddev
Copy link

Hello @AkourMohamed & @wzaieddev,
Here is my functionto get browser language:

this.availableLangs is a list of languages that I can use in my application, like: ['en', 'fr', 'es']

import concat from 'lodash-es/concat';
import filter from 'lodash-es/filter';
import first from 'lodash-es/first';
import intersection from 'lodash-es/intersection';
import isEmpty from 'lodash-es/isEmpty';
import isNil from 'lodash-es/isNil';

  /**
   * Get the first browser language
   */
  getFirstBrowserLang(): string {
    const cleanBrowserLangs = filter(this.getBrowserLanguages(), (lang: string) => {
      return !isNil(lang) && !isEmpty(lang);
    });
    const browserLangs: string[] = uniq(
      map(cleanBrowserLangs, (browserLang: string) => {
        // We don't manage localisation yet (i.e.: en-GB => en, FR -> fr)
        return lowerCase(replace(browserLang, /-.*/, ''));
      }),
    );

    return first(intersection(browserLangs, this.availableLangs));
  }

  /**
   * Get all languages of the browser
   */
  getBrowserLanguages(): string[] {
    const navigator: Navigator = window.navigator || window.clientInformation || null;

    return concat(navigator.language, navigator.languages);
  }

Hi @dsnoeck,
thank you for the response, i have one more question: where should we put this function? on app.component.ts for example ? could you show us how you have used this function? it will be very helpful
because the focus is, where is the point of application where should we put the browser detection langue.
Best Regards
Zaied Wael

@dsnoeck
Copy link

dsnoeck commented Feb 1, 2021

The simplest is to call it from your ngOnInit() method of the app.component.ts

@datnd-miagi
Copy link

datnd-miagi commented May 5, 2021

Hello every one!
I have the following code in the ts file:

    public heading(): string {
        if (this._paramType === "query") {
            return "Define a New Query Parameter";
        }
        if (this._paramType === "header") {
            return "Define a New Header Parameter";
        }
        if (this._paramType === "cookie") {
            return "Define a New Cookie Parameter";
        }
        if (this._paramType === "formData") {
            return "Define a New Form Data Parameter";
        }
    }

and .html

<entity-editor (onClose)="close()" (onSave)="save()" [context]="context" entityType="{{ _paramType }}Parameter" *ngIf="isOpen()"
               [showRequiredFieldsMessage]="true" [heading]="heading()" [valid]="isValid() && nameInput.valid">

I am looking for how can translate text in ts file, $ localize or ngx-translate can handle this problem

@vladonemo
Copy link

vladonemo commented Dec 2, 2021

@datnd-miagi I believe that adding $localize template literal tag handler in front of each string would do the trick:

 public heading(): string {
        if (this._paramType === "query") {
            return $localize`Define a New Query Parameter`;
        }
        if (this._paramType === "header") {
            return $localize`Define a New Header Parameter`;
        }
        if (this._paramType === "cookie") {
            return $localize`Define a New Cookie Parameter`;
        }
        if (this._paramType === "formData") {
            return $localize`Define a New Form Data Parameter`;
        }
    }

@twoco
Copy link

twoco commented Nov 6, 2022

I like ngx-translate more than the Angular i18n. At least what I've seen so far. To be honest I haven't tried it myself yet. Do I understand it correctly? You have to build the same Angular app for each language and e.g. use location URLs for your Angular app? If so, it's impossible to that for e.g. Cordova / Capacitor (Ionic) mobile apps using Angular. What do you mean with "reload" app? Reload on another URL with two letter code included (another path)? Or just use global settings storaged somewhere or use navigator.language?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests