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

[i18n] plans #16477

Closed
20 tasks
ocombe opened this issue May 2, 2017 · 310 comments
Closed
20 tasks

[i18n] plans #16477

ocombe opened this issue May 2, 2017 · 310 comments
Assignees
Milestone

Comments

@ocombe
Copy link
Contributor

ocombe commented May 2, 2017

Here is the list of features / fixes planned for i18n.

If you want new i18n features to be added to Angular, don't hesitate to ask below and I'll let you know if that's feasible and if you should open an issue for it.
If you have a bug, open an issue (no need to discuss about it here).

For Ivy

Note: runtime translations and most of the new features will only be available with ivy

Features

Issues

Not prioritized

Features

Issues

@ocombe ocombe mentioned this issue May 2, 2017
21 tasks
@jlutz777
Copy link

jlutz777 commented May 9, 2017

I would like to see the ability to do dynamic bindings in aot mode. There are two use cases in particular to back up why this should be added to the roadmap.

The first is the basic use case where you don't want separate applications for every language. This requires some sort of redirect logic outside the app and doesn't allow dynamic changing of the language without a complete reload of the site.

The second is the case where you are embedding the app in mobile using cordova. As far as I know your choice is to jit, thus slowing down the site, creating a separate app for every language, or including every language in the app (which of course bloats it). None of these are good options. It seems Ionic doesn't use i18n, and I wonder if this is the reason why.

@ocombe
Copy link
Contributor Author

ocombe commented May 9, 2017

@jlutz777 those are 2 valid use case, this subject has been discussed internally lately and I've been advocating for that too. It is not easily possible yet given how i18n and AoT work in Angular, but it might be in the future once we get the new compilation process for AoT in v5.
I'll add it to the roadmap once/if we have something official and concrete about it.

@vishalbhardwaj26
Copy link

I am working on Electron + Angular 2 app and now trying to add support for Localization for multiple langauge using i18n feature with Angular. Actually extraction of template-string and converting them in different language file formats are clearly documented, though I am still not able to much clear about and looking for:

  • Can i switch language dynamically? or do I need to build application separately for different language.
  • Can I manage/consolidate all strings at one place (in the form of key/value pair), so that I can change
    the string at one place to be effected at multiple place?
  • Can i access the localized file from anywhere other than template to get specific language string with
    provided key? (same as i asked above).

@ocombe
Copy link
Contributor Author

ocombe commented May 11, 2017

Points 2 and 3 will be resolved with the feature "Use translation strings outside of a template - #11405".
For the point 1 see the answer I gave to @jlutz777 above. For now you still have to build the app in multiple languages, or use JIT which can dynamically load translations at bootstrap (it's not switching at runtime, but it's still better than having to bundle it x times).

@figuerres
Copy link

the UI language used in an application should be something that does not require building multiple versions of the same application. this should not in any way be a "compiler" issue. if it is then the compiler is flawed. the issues should be one of making the application design such that the text can be loaded from a data file at run time. that should be done with a module / library that can be loaded and used like any other. do not make that a compiler function at all.

@ocombe
Copy link
Contributor Author

ocombe commented May 22, 2017

@figuerres it's something that will be changed in the future, no promises yet but we are aware of this issue and we are looking at possible solutions, using an external file is one of them

@rjcorwin
Copy link

Hi @ocombe - It looks like we're probably going to use i18n in Angular for our application. Are there any features in the docs you think might become deprecated or have breaking changes in the coming months? Any info would be greatly appreciated. And thanks again for the DVD!

@ocombe
Copy link
Contributor Author

ocombe commented Jun 1, 2017

Hey @rjsteinert! Glad to know that!
There's only one breaking change planned for now, it's the auto generation of IDs. The method will change and the IDs will not match anymore, but there will be a cli migration tool to update your translation files (and a parameter that you can use to only migrate when you're ready).

@actra-gschuster
Copy link

actra-gschuster commented Jun 23, 2017

I googled a lot about this topic today and am wondering if there could be a "simple" solution like replacing i18n-tags with a call to a service instead of the translation?

Current:
<span i18n>Hello world</span> => rendered to <span>Hello world</span>

My idea:
<span i18n>Hello world</span> => rendered to <span>{{i18nservice.translate('pass-in-the-generated-message-id')}}</span>

This way the real translation could be done dynamically in AOT as the service could be filled from an API, file etc. and even switching locales wouldn't be much more than i18nservice.setLocale('de-DE') with loading a new source.
Text extraction with xi18n-tool would still work as before and we could leverage the message ids generated anyways to use as index for the translation service.
The current implementation would also still work flawlessly as ngc could simply look for a "--use-i18nservice" flag and otherwise compile as until now.

One problem I can currently identify is the injection of the i18nservice into each and every component as it has to exist in the components context to be callable, but that should be solvable in one way or another.

Any thoughts on this?

@ocombe
Copy link
Contributor Author

ocombe commented Jun 26, 2017

It is one of the things that we're considering yes, there's still the problem of how to treat code blocks inside of those translations when the compiler isn't available at runtime (AOT). It would mean that we cannot use angular components/directives/pipes inside of translations...

@actra-gschuster
Copy link

actra-gschuster commented Jun 26, 2017

Yes, didn't think of that.
I'm currently developing a POC/workaround that inlines all translations into the HTML at the build step (webpack), wrapping them into ng-containers with ng-switch.
For i18n-attributes it's using a directive setting them on nativeElement.
The translations themselves also get "rendered" then to replace all those <x id=".. "/> placeholders.

It's ugly but works...can't wait for ng to support it natively.
Will publish the POC later this week, maybe it can be of use for your further conception.

@actra-gschuster
Copy link

actra-gschuster commented Jun 26, 2017

I came up with a "solution" that suits my needs until there's an implementation.
The pre-loader now renders HTML for all locales before handing over to the compiler, works like a charm so far.

Repo: https://github.com/actra-development-oss/ng-i18n-aot-loader
NPM: https://www.npmjs.com/package/@actra-development-oss/ng-i18n-aot-loader

@figuerres
Copy link

possibly a component could have an attribute that tells the system / compiler that it needs a service.
that service then takes and id and a locale and returns the localized text / markup.
all the localized text is stored on the server as resources that the service can read from.

if a component does not have the attribute no locale run-time.
if the component has it then it call get the localized data at run-time.
the compiler just builds the data files and hooks up the service.

this seems to me like a good way to handle the most common need for most applications and not require sites to build and maintain multiple copies of the same app.

@actra-gschuster
Copy link

actra-gschuster commented Jun 28, 2017

I had that idea, too.
Problem is that translations can contain bindings and thus would open the system for code injection when loading translation files from external resources.
Additionally, a compiler would be needed to resolve those bindings dynamically depending on the translation.

IMHO a valid solution could be the way I implemented as POC (see comment above) to inline translations at compile time, just in a more elegant, integrated way.
Both problems mentioned above would be eliminated, only downside I can imagine is possibly the bundle size, it'd grow to "plain bundle" + (translated html-size * locales).
That could be lowered by only ng-switching the i18n-tagged html instead of the whole document but still there's a problem for i18n-*-tags.

@figuerres
Copy link

well here is the thing; some times you have limits ....

from a practical stand point it might be better to not have that, you can have a chunk of text that can be given in multiple languages. end of the story.

you need to have a data bound chunk ? ok but that is not inside the internationalized text, it has to be separate. you can still use html and css to style and format the result. but you can't embed or combine them in every way you can think of.
like say a div or a p tag can have a number of spans one span is the text and another span is a bound date the text span is bound to the i18n locale service, the date is bound to some date service the two spans are in a paragraph tag that formats them.

Keep it simple, make it work for 95% of all users first then figure out the edge cases.

@actra-gschuster
Copy link

I don't see that as an edge case, it's business as usual.
Angular is a business-grade framework so many, if not all, of the i18n-users will require bindings, or at least pluralization and selects, inside texts.

<span i18n>Hello, {user.gender, select, m {Mr.}, f {Ms.}} {{user.name}}</span>
How would you solve that with separated strings?
Simple answer: you can't, as you cannot know the rules of the target language, not every language follows the format 'greeting', 'gender', 'name'.

Separating those chunks would:

  • kill context, the translator wouldn't get the meaning of the complete sentence
  • merging the chunks in the right order by CSS isn't possible, you'd have to specify rules for each and every translation, so either the CSS-guy needs to know the target languages or the translation-guy needs to know CSS, neither is acceptable.

The core i18n works in angular as expected and is usable for business-grade apps, the only thing missing apparently is AOT-compatibility, so I don't get your standpoint why a powerful, working system should be replaced by something not half that capable requiring multiple times the work to get it done.

@ocombe
Copy link
Contributor Author

ocombe commented Jun 28, 2017

We have a meeting tomorrow to find a solution to this problem.

@figuerres
Copy link

@ocombe glad to hear this, i hope this leads to some good stuff for a future release of Angular , here at work we are really loving how most of it works for our development needs!

@SteveRuben
Copy link

@ocombe , is it possible to change language without relaoding the entire document ? I explain :
I'm on page named "about" but when I change the language, i'm redirected to main entry page of my application .

@actra-gschuster
Copy link

While working on my i18n-app I also came across the known "bug" that external stylesheets from e.g. @angular/material (residing in node_modules) could not be resolved and thus the ng-xi18n-tool failed.
I implemented an "ignore missing files"-HostContext for the extraction tool, also as POC but added as PR #17845 to have it linked to the main repo.

@ocombe as you seem to be very active on this topic would you mind having a look at the PR and giving feedback?

@ocombe
Copy link
Contributor Author

ocombe commented Jun 30, 2017

Thanks, I'll take a look at it.

@RAJKUMAR-PATTNAIK
Copy link

It's been few days searching a way to implement internalization on whole project including dynamic data, but found nothing concrete. Can you please suggest me something else that at least help me for the time being. Thank you.

@jean-philippe-bousselin
Copy link

jean-philippe-bousselin commented Sep 18, 2017

Hello @ocombe! Can we have a follow up concerning the point raised by @jlutz777 (about dynamic bindings, thus not having one app per language) ?

Thanks a lot for your work!

@ocombe
Copy link
Contributor Author

ocombe commented Sep 18, 2017

@vicb is working on it right now, it'll be in 5.x (not 5.0 but most likely 5.1)

@trotyl
Copy link
Contributor

trotyl commented Sep 18, 2017

@ocombe Should the checklist be updated? I can see some of them already been merged in newer versions. And that'll better reflect your hard works. 😃

@ocombe
Copy link
Contributor Author

ocombe commented Sep 18, 2017

yes, good idea, I'll update it
edit: updated

@ocombe
Copy link
Contributor Author

ocombe commented Feb 11, 2020

You can extract translations from templates.
If you want to use $localize in your code as well, you should take a look at Locl: https://github.com/loclapp/locl/
@locl/cli will let you extract from code & templates

@petebacondarwin
Copy link
Member

@vekunz - the forecast is still valid. Moreover, as @ocombe points out, the current CLI translation extraction mechanism works just fine for any translation that is within an Angular template (i.e. stuff that is marked by the i18n tags). The only thing you are not able to extract using the core tools right now are calls to $localize within your own code (e.g. in a service or component).

@petebacondarwin
Copy link
Member

The $localize call itself is a stable API.

The tooling that does translations and extraction (specifically at compile time) is still non-public. But this is not a concern unless you are planning on building your own tooling around it (like @ocombe is doing at Locl!).

@vekunz
Copy link

vekunz commented Feb 11, 2020

Thank you @petebacondarwin, with this, we could duplicate the texts from code into a "hidden" component template for extraction. Then the extraction and the translation both should work, shouldn't it?

@ocombe With the forecast that extraction works with Angular 9.1, our manager wouldn't pay for your solution. Especially because we don't need live switching of languages and translated routes.

@petebacondarwin
Copy link
Member

we could duplicate the texts from code into a "hidden" component template for extraction

Yes indeed, this workaround would work for now.

@JustDoItSascha
Copy link

JustDoItSascha commented Feb 11, 2020

I'm confused: Will the runtime translation also be possible in 9.1? Or just the extracting outside of templates? Or none of these?

For me the runtime translations would be a killer feature. To deploy multiple bundles and forcing the user to reload the whole page is not a good usability I think.

@destus90
Copy link
Contributor

@JustDoItSascha
I've created a simple demo, which demonstrate runtime translation.
https://stackblitz.com/edit/ivy-vjqzd9?file=src%2Fapp%2Fapp.component.ts

@albyrock87
Copy link

Hi! I'm trying to call loadTranslations in main.ts because strings are translated while JavaScript parses imports, but that's not enough.

main.ts imports AppModule that imports AppComponent (where I'm using $localize).

To make it work I'm doing:

loadTranslations(......);
import('./app/app.module').then(m => platformBrowserDynamic(). bootstrapModule(m.AppModule);

Now this works but causes Angular's "complier.js" bundle to be included in the vendor bundle.

Any way to avoid that? Thanks

@cexbrayat
Copy link
Member

Currently, loadTranslations needs to be called before the application starts, so it can be done in polyfills.ts. And if you want to load an other set of translations, you then have to reload the page. If you want to understand a bit more why, I wrote https://blog.ninja-squad.com/2019/12/10/angular-localize/ to explain it.

@ocombe
Copy link
Contributor Author

ocombe commented Feb 12, 2020

Currently, loadTranslations needs to be called before the application starts, so it can be done in polyfills.ts.

It's even worse than that, it needs to be called before any module file is imported, that's why it works if you put it in polyfills.ts (which is executed before the main app file), but if you want to use it in your "main" file then you need to use a dynamic import(...) for the module

@vekunz it's a good reason to not use my lib for now 😊 that being said Locl is not just about extraction, I intend to add a lot of other tools to simplify i18n

@Karasuni
Copy link

Is there any intention of implementing runtime i18n in Angular ever? We've been expecting the feature for almost three years and now Ivy's here and it's still only half-baked.

@michaelfaith
Copy link

Is there any intention of implementing runtime i18n in Angular ever? We've been expecting the feature for almost three years and now Ivy's here and it's still only half-baked.

My understanding is that Ivy, in many ways, is an enabler for things to come. Unsurprising that the i18n needle did move incredibly with the release of Ivy, but it should unleash the potential for big changes down the road. That's been my read of it, and my hope, anyway.

@petebacondarwin
Copy link
Member

petebacondarwin commented Feb 12, 2020

@Karasuni - I think we need to clarify what runtime translation actually means for the core Angular framework because there is quite a bit of confusion about it.

The changes that we made for v9 involve the $localize based translation. The primary aim of this was to decouple translation from the Angular compiler, so that it enables a number of nice improvements:

The first of this, which is immediately available to all users of v9, is to speed up generation of translated applications. Previously, the entire build pipeline had to be run for each language that you wanted to translate your app into. Now the main compilation of your application only has to be run one and the final translation process, which is significantly shorter is run for each language on the output of the build. To support this there is the new @angular/localize package, changes inside the Angular compiler and a whole load of work inside the Angular CLI to make this as seamless and transparent as possible

Secondly, since the $localize tags can be left in the distributed code, it is now also possible to do the translation in the browser (at runtime, rather than at compile time). This is what we mean in the core Angular framework as runtime translation. But please not that the final outcome of this is effectively the same as translation at compile time. The translation happens only once; if you want to change the language at runtime then you must restart the whole application (e.g. via a reload). This has the benefit of allowing the project to deploy a single distributable with numerous translation files, which is helpful in a small number of use cases where you do not want to generate all the different translations up front. There are some tricky issues around loading the translations early enough as pointed out by @ocombe and others here. You could consider https://www.locl.app/ for more help with doing this.

Note that this "runtime" translation can also be used on lazy loaded routes so it might be feasible to have different routes in different languages depending upon how you set things up.

Since there is not a single approach to this loading of translations that works for all scenarios, we have not baked this into the CLI or provided stable public APIs to support this yet. Once we get a better understanding of the use cases then we might be able to add more support for this. In the meantime things like Locl might help if you don't want to venture into working it out for yourself.

Finally, note that dynamic changing of translated strings at runtime is specifically not supported (by design) by the core Angular framework. Hooking the translated strings into Angular's change detection system would put too much strain on most applications and ruin performance. From my interactions with the community I have seen hardly any real world scenarios where this is actually needed over and above restarting the application on language change. If this is a requirement for your application then you could achieve it by using a custom built pipe on your strings in templates that pulls in translations, and maybe even calls $localize on the fly to translate but it does not look like this would be very performant. Otherwise you could consider a more dynamic approach like https://netbasal.gitbook.io/transloco/.


The main changes coming in the next minor version of Angular will be improved translation extraction, which will be able to identify and extract localized strings from TS code - currently the CLI extraction only handles localized strings in templates.

Changes to improve runtime translation, as described above, would not appear until after 9.1 at the earliest.

@Karasuni
Copy link

Finally, note that dynamic changing of translated strings at runtime is specifically not supported (by design) by the core Angular framework. Hooking the translated strings into Angular's change detection system would put too much strain on most applications and ruin performance. From my interactions with the community I have seen hardly any real world scenarios where this is actually needed over and above restarting the application on language change.

I might be mistaken but in this thread alone many people expressly showed interest in the ability to change the language live, at runtime, without having to rebuild or reload the application. Or does everyone here have a different definition of runtime translation?

I do not want to reload an application just to switch a language. For example when a user is on a page with a form a full page reload for a switch in translation will be jarring to the user.

@petebacondarwin
Copy link
Member

Just to be clear. What I meant to say is that lots of people have come up to me to say that they absolutely need live language changing in their application. But when you dig into the reasons it turns out that they don't. I am not saying that there are no scenarios that require this, but in my experience over the last year, I have come across very few.

Question: why would a user need to switch languages when the go to a particular form on your app?

@vekunz
Copy link

vekunz commented Feb 12, 2020

I don't think that live switching is necessary also. How often do you change the language of a website? Usually one time, at maximum. And for this one time, a page reload is not that critical. As @petebacondarwin said, almost all scenarios for live switching are not relevant real-world scenarios but only "nice to have."

@ewok-janitor
Copy link

Or does everyone here have a different definition of runtime translation?

I absolutely need runtime translations. Our customers need to be able to edit and update translations in the field, not just on the build server. So, runtime, as opposed to compile time.

Actual switching of languages after page load is a nice-to-have.

@Karasuni
Copy link

Just to be clear. What I meant to say is that lots of people have come up to me to say that they absolutely need live language changing in their application. But when you dig into the reasons it turns out that they don't. I am not saying that there are no scenarios that require this, but in my experience over the last year, I have come across very few.

Question: why would a user need to switch languages when the go to a particular form on your app?

You might be right that it not a solid requirement. I might attempt deploying translations on load but it will completely transform the user experience of the applications that are currently able to switch language dynamically - without reload or changing position in the page - with an external library. Translations has been a heated topic for a very long time.

I do have an important question: Can translation files be loaded asynchronously? All my translations are stored in a database as being able to update them without a rebuild is important.

@ocombe
Copy link
Contributor Author

ocombe commented Feb 12, 2020

yes they can be loaded asynchronously, but you need to delay the start of your application until they have been loaded

@TomDemulierChevret
Copy link

TomDemulierChevret commented Feb 12, 2020

Just to be clear. What I meant to say is that lots of people have come up to me to say that they absolutely need live language changing in their application. But when you dig into the reasons it turns out that they don't. I am not saying that there are no scenarios that require this, but in my experience over the last year, I have come across very few.
Question: why would a user need to switch languages when the go to a particular form on your app?

You might be right that it not a solid requirement. I might attempt deploying translations on load but it will completely transform the user experience of the applications that are currently able to switch language dynamically - without reload or changing position in the page - with an external library. Translations has been a heated topic for a very long time.

Technically you can reload the entire app and still keep the user where he was.
You "just" need to have a state-driven app (with ngxs, ngrx, or any other state management library) which is stored somewhere and retrieved at startup.

The only trick would be to keep scroll position but that's feasable too.

@mlc-mlapis
Copy link
Contributor

@petebacondarwin I have to say that I agree with you. I don't know real end-users (except testers in dev phase) who are switching an app permanently between languages when using it. Sure, they do it probably at the beginning if they open it in a different one somehow, but later, it's a rare case.

@vekunz
Copy link

vekunz commented Feb 12, 2020

Or does everyone here have a different definition of runtime translation?

I absolutely need runtime translations. Our customers need to be able to edit and update translations in the field, not just on the build server. So, runtime, as opposed to compile time.

Actual switching of languages after page load is a nice-to-have.

I'm not sure, what your customers are doing, but "editing of translations live in the production website" doesn't sound like a common scenario.

@Alir3z4
Copy link

Alir3z4 commented Feb 12, 2020

I don't see changing language live (without page reload) to be such a deal breaker.
Changing a language for a user happens only once;

Think about it, how many times you have changed your phone language ? probably once or you just rolled with the default language.

Watching for language changes in order to do live change without page reload brings a lot of performance penalty for something that is barely used for the lifetime of a user.

Ultimately, in comes down to 3 things for me;

  1. Extract translations from templates and TS files.
    • Update source lang asset.
    • Update translation as well (if I have multiple languages, fr, en, de... I want all of them to be updated with new translations keys and removed ones.)
  2. One build for all the translations (Having 1 build for each translations is fine as well, as long as it doesn't multiple the build time.)
  3. Getting available languages and change the language with reload.

@albyrock87
Copy link

@Karasuni
You can fetch translations async and only then load the angular app.
See my comment above on how to load the app.module asynchronous using import(...).

@tatsujb
Copy link

tatsujb commented Feb 12, 2020

personally I use Wikipedia to figure out what the title of a movie that I know was "translated" to in another language.

in this day and age being bilingual or trilingual is more than commonplace (aside from within the US, no harm meant).

the user might want to live switch languages it's completely plausible. the Wikipedia example is a positive result of having enabled this, I don't see why we should stifle other potential uses before they live to see the light of day under the pretext of performance.

even ocombe's ngx-translate which has to be the tantamount example for you guys of "poor performance translations" ran perfectly fast enough for the everyday user.

I personally am trilingual and I can't settle on using one language : all languages are beautiful to me

with all that said I cannot agree with this :

Think about it, how many times you have changed your phone language ? probably once or you just rolled with the default language.

@vekunz
Copy link

vekunz commented Feb 12, 2020

Wikipedia is the worst example of this because the different languages of an article are actually independent articles. Normally you don't need different languages of the exact same site. Even if you work quadrilingual.
And if you actually need live switching, you can use either the workaround with the custom translation pipe, which @petebacondarwin mentioned or the new tool from @ocombe.

@petebacondarwin
Copy link
Member

OK, so I don't think that this is really the best place to have this discussion. I am concerned that (while have all been very reasonable so far) we might slip into negative discussion. I'm afraid that for the foreseeable future the Angular framework will not provide a live language switching solution out of the box.

I feel that the value of this issue has run its course. I have moved the open issues and PRs that are linked in the description of this issue to https://github.com/angular/angular/milestone/101 and I am going to close and lock this PR.

If you have new issues of feature requests then please do open up a new issue and tag me in it.

@angular angular locked as off-topic and limited conversation to collaborators Feb 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests