angular / angular

Deliver web apps with confidence 🚀
https://angular.dev
MIT License
95.65k stars 25.2k forks source link

i18n Support in Angular Library #29536

Closed rahulrsingh09 closed 3 years ago

rahulrsingh09 commented 5 years ago

Is this Possible with the current approach of angular libraries , can we have i18n support for Libraries so that i can build the lib using locale specific data .

Currently in the Angular Docs both these topics are under different Leaf Nodes and not related . But we feel it's a valid requirement of having Libraries work with i18n

rmedaer commented 5 years ago

It's (not yet) possible to do i18n in libraries (as far as I know). However, as explained by @ocombe it will be included with ivy.

I recommend the following talk for more details : https://www.youtube.com/watch?v=miG-ghJhFPc

rmedaer commented 5 years ago

If you are using ng-packagr as builder/packager for your Angular libraries, is here your answer for current version (a.k.a without ivy): https://github.com/ng-packagr/ng-packagr/issues/695

rahulrsingh09 commented 5 years ago

@rmedaer Thanks for the links, So untill and unless Ivy comes to the rescue we have no other options? Also if we plan on usong ng-packager will be it possible to have i18n support for Libs as the link mentioned is still and open issue ? can you please shed some more light on the same .

rmedaer commented 5 years ago

Actually to answer I also have few questions:

Also if we plan on usong ng-packager will be it possible to have i18n support for Libs as the link mentioned is still and open issue ?

I guess ng-packagr guys will not work-hard on previous Angular renderer because ivy is planned for Q1/Q2 2019. About next angular release (8.0.0) I cannot answer this since new i18n on ivy is not yet finished. Again as far as I know (as external observer) @ocombe just started to implement translation loaders. Meaning that "provides translation to/from libraries" will depends on services in top of i18n compilation/configuration...

I guess the best to advice you is @ocombe and actually he already did a lot here.

rahulrsingh09 commented 5 years ago

@rmedaer w.r.t your questions these are things i am looking at

Would you like to package your library with translations ? Yes (or) would you like to provide translations from your application ?( Maybe both if possible else No ) Are you compiling in AOT or JIT ? AOT (Lib only complies in AOT if i am not wrong) Did you listen to ngx-translate ? Even if ivy will deprecate ngx-translate it might be an alternative for now.(Presently we are looking at ngx-translate Is it the only way as of now ..)

fjoalland commented 5 years ago

Any more news about this issue?

SantiagoIlli commented 4 years ago

See this comment

vgb1993 commented 4 years ago

I also need my libs to provide their own translations.

JanEggers commented 4 years ago

@ocombe any news?

ocombe commented 4 years ago

@petebacondarwin ? ^

petebacondarwin commented 4 years ago

So two PRs that are in flight to help support translations in libraries are:

I am working a full tilt on this stuff, except for the odd ngcc fix.

ozkoidi commented 4 years ago

Any news or estimated release date for this?

jimbarrett33 commented 4 years ago

@petebacondarwin

Thanks for this new feature for merging multiple translation files per locale. I tried it locally using a direct script call to "translate" as per your integration/ivy-i18n/package.json and it seems to work well. I just had a few questions as we are trying to make i18n decisions for multiple apps in our (growing) Angular monorepo going forward.

1) I noticed the code for new feature is in 10.0.0-rc.6, so will the code be intgrated with angular.json and the cli when 10.x is initially released?

2) Will the discovery and reporting of missing translations take into account the new translations array?

3) Any plans or chance that ng xi18n could also look at this array and add the missing translations to the locations specified in the array?

Thanks.

petebacondarwin commented 4 years ago

@jimbarrett33 :

  1. I don't believe that this will get integrated into the CLI in time for 10.0.0. It is not a major change so it may well land in 10.1.0 - let's ask @clydin
  2. Can you give me some more explanation of how this would work?
  3. How would this work in practice?
clydin commented 4 years ago

Multiple translation file support is currently scheduled for inclusion in version 10.1.

jimbarrett33 commented 4 years ago

@petebacondarwin

Thanks for the quick response.

  1. what I mean is...currently a build for a locale will report on missing translations for $localize translations. Just wanted to make sure that this will still work.

  2. ng xi18n currently finds and extracts translations and writes them to the single "outputPath" such as "src/locale". I was thinking that it could extract the translation and put them in the "src/locale" of the module of the component where the i18n tag originated. After thinking about this a little more, that could get very complex.

Also, one additional question or feature request if it doesn't exist:

  1. Is there an option to actually write out the merged file? This would allow tracking all of the app's translations in one place for source control and/or sending to a translator.
petebacondarwin commented 4 years ago

Sorry for the slow response:

  1. Missing translations will still be reported.
  2. Yeah, there are so many potential paths for this sort of thing. I am not ruling it out but initially I want to keep it pretty simplistic.
  3. I am not quite sure what this means. The merged file would contain all the translations brought in from the different translation files that are listed in the input array. They are already translated, so I am not sure why you would send them to a translator.
jimbarrett33 commented 4 years ago

@petebacondarwin Thanks and no worries. I'll explain how for #4 would be of help to us.

In some cases, we may not always send the translations for libraries separately to a translator. Instead, we would send a complete file for the app, knowing that on return of the translations we would be responsible for getting the updated translations to the various libs (or we have the option of using the "old" way and point angular.json to the single translation file once an app is stable).

Also, for a specific application, the merged file can act as "the" record for translations for that app. And if the write process maintains some sort of order (like the order of the input array), when checked into source control we would be able to track the diffs more easily for a single app as part of the dev process.

In practice, I think this may have to be a utility-type cli option that would run locally outside of the normal build process since the output file could be inside the source tree and the build process wouldn't (couldn't ?) write a file there. I haven't thought the design through completely.

Hope that helps.

petebacondarwin commented 4 years ago

I think we are at cross purposes here... merging in the sense that I was talking about is merging pre-translated files into the application for distribution. I think that you are talking about merging the source messages when extracting messages into a file that can be sent for translation. Is that correct?

jimbarrett33 commented 4 years ago

Yes, that sounds correct. I guess the only difference I was thinking about is that the extract process currently extracts to the messages.xlf file without existing translations, i.e. without the <target> element. Instead, I was looking for the existing translations (if there are any) be extracted also and into the messages.<locale>.xlf file.

Honestly, except for possibly the first "major" extraction, themessages.xlf file is not that useful for us because syncing that with the messages.<locale>.xlffile is a real pain.

After the i18n process has been started -- a release of the software has already happened -- what we have been doing for new translations is manually adding them to the appropriate lib's messages.<locale>.xlf file with a placedholder like in the target element such as <target>???</target> so we/the translator can identify the new strings that require translation.

meriturva commented 4 years ago

@petebacondarwin Just to know and take the right decision on our side: is i18n library support (extraction tool for libraries) landing on 10.1 version?

petebacondarwin commented 4 years ago

OK, so the items discussed here should be available via the CLI in 10.1

IgorWolbers commented 4 years ago

Hi @petebacondarwin. (If this existing question is not the correct place to post let me know and I will create a new question.)

I was very excited to see this change in the release notes but I am not sure as to how to use it. Is there a link with documentation that can be followed?

from the release notes

10.0.0 (2020-06-24)

  • localize: support merging multiple translation files (#36792)

My understanding is that you can have multiple translation files (like .xlf files) and that these are merged into a localized deployment (first message id encountered wins if there is conflict). I tried altering my angular.json file accordingly but the cli throws an exception on build as this is not supported. Here is an example from my angular.json where I would have text value specific overrides for users in Belgium that spoke Dutch, the benefit here is that I do not have to maintain the common values in multiple files.

"projects": {
  "app-name": {
  "i18n": {
    "sourceLocale": "en",
    "locales": {
      "nl": {
        "translation": "Resources/translations.xliff2.nl.xlf",
        "baseHref": ""
      },
      "nl-BE": {
        "translation": ["Resources/translations.xliff2.nl-BE.xlf", "Resources/translations.xliff2.nl.xlf"],
        "baseHref": ""
      }

The error when running ng build --localize

An unhandled exception occurred: Workspace config file cannot be loaded: c:\full\project\path\angular.json Schema validation failed with the following errors: Data path ".projects['app-name'].i18n.locales['nl-BE']" should be string. Data path ".projects['app-name'].i18n.locales['nl-BE'].translation" should be string. Data path ".projects['app-name'].i18n.locales['nl-BE']" should match exactly one schema in oneOf. See "C:\Users\user\AppData\Local\Temp\ng-kqmoRL\angular-errors.log" for further details.

Could you point me in the right direction on how to make this work or perhaps I misinterpreted the point of this feature entirely?

Environment version information:

Angular CLI: 10.0.2
Node: 10.19.0
OS: win32 x64

Angular: 10.0.4
... animations, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: <error>

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.1000.2
@angular-devkit/build-angular      0.1000.2
@angular-devkit/build-optimizer    0.1000.2
@angular-devkit/build-webpack      0.1000.2
@angular-devkit/core               10.0.2
@angular-devkit/schematics         10.0.2
@angular/cdk                       10.0.2
@angular/cli                       10.0.2
@angular/material                  10.0.2
@angular/material-moment-adapter   10.0.2
@ngtools/webpack                   10.0.2
@schematics/angular                10.0.2
@schematics/update                 0.1000.2
rxjs                               6.5.5
typescript                         3.9.6
webpack                            4.43.0
petebacondarwin commented 4 years ago

@IgorWolbers I'm afraid this is not yet implemented in the CLI. It is only available in the standalone localize-translate binary that comes with @angular/localize. Hopefully the integration into CLI will be available in 10.1.0

IgorWolbers commented 4 years ago

Is there an existing open issue that I can subscribe to so I will be notified when the changes have been included in the cli and released?

Thank you @petebacondarwin and also thank you for your work on angular, it is a fantastic framework.

petebacondarwin commented 4 years ago

There are now:

impurity-dev commented 3 years ago

Is i18n definitively supported in an angular library and CLI now? If so, what version?

petebacondarwin commented 3 years ago

Yes it is supported, and has been since about v10.1.0. The question is really how ergonomic this is... for example there is a question of whether a library can/should provide standard translations, and if so how it would provide these.

wasdJens commented 3 years ago

For angular components from a separate library it works fine when you have the component tagged with i18n - When running ng xi18n inside your application that consumes the library you get the tags inside the .xlf for these components.

But what about the usage of $localize inside a service for example? When running ng xi18n inside the library itself the translations are created but not when running it inside an application. Do we need to merge these two translation files or is the extraction of the $localize not supported and we can only have translations in components?

Sorry to dig out such an old issue but I could only find information about localization with applications and not much about libraries.

petebacondarwin commented 3 years ago

@wasdJens - could you provide an example of this not working? I thought it should, since the $localize calls would make there way into your final application build, where the i18n extractor would grab them...

wasdJens commented 3 years ago

@petebacondarwin Gonna try to provide a sample library / app configuration since the working project is closed code.

wasdJens commented 3 years ago

Hey, sorry for late response from my side.

I have tried to pinpoint my issue to maybe a misconfigured project / library. I have also created a sample repo with three angular projects inside:

When running ng extract-i18n in the v11 app $localize seems to work and is extracted from the library.

<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="en-US" datatype="plaintext" original="ng2.template">
    <body>
      <trans-unit id="6480943972743237078" datatype="html">
        <source>You have 10 users</source>
        <context-group purpose="location">
          <context context-type="sourcefile">../angular-localize-issue/dist/projects/test-lib/src/lib/sample-component/sample-component.component.ts</context>
          <context context-type="linenumber">9</context>
        </context-group>
      </trans-unit>
      <trans-unit id="8def8481e91291a52f9baa31cbdb313e6a6ca02b" datatype="html">
        <source>Hello i18n!</source>
        <context-group purpose="location">
          <context context-type="sourcefile">../angular-localize-issue/dist/projects/test-lib/src/lib/sample-component/sample-component.component.ts</context>
          <context context-type="linenumber">15</context>
        </context-group>
        <note priority="1" from="description">An introduction header for this sample</note>
      </trans-unit>
    </body>
  </file>
</xliff>

When installing the library in the other angular application (Running 10.2.4) and running ng xi18n (Since ng extract-i18n is not yet supported there according to the docs) I get the following response (Missing the $localize)

<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="en-US" datatype="plaintext" original="ng2.template">
    <body>
      <trans-unit id="8def8481e91291a52f9baa31cbdb313e6a6ca02b" datatype="html">
        <source>Hello i18n!</source>
        <context-group purpose="location">
          <context context-type="sourcefile">node_modules/test-lib/lib/sample-component/sample-component.component.d.ts</context>
          <context context-type="linenumber">2</context>
        </context-group>
        <note priority="1" from="description">An introduction header for this sample</note>
      </trans-unit>
    </body>
  </file>
</xliff>

I can reproduce the same behavior in our real source code (Also running under angular 10.2.4). I am not quite sure if this is a problem with angular itself or the configuration I am using is incorrect. Our solution is most likely to bump to Angular 11 since we are not using any advanced features that are no longer supported or other issues.

petebacondarwin commented 3 years ago

Thanks for looking into this further @wasdJens.

This sounds like it is working as expected in v11 and not (as expected) in v10. The Ivy extraction was not available in earlier versions of Angular. So indeed your solution is to update to the latest version.

I am going to close this as it appears that there is no problem with the latest version of Angular.

michaelhunziker commented 3 years ago

@petebacondarwin: I just wanted to try to extract messages from my Angular library (project generated with the latest CLI, 11.1.4): ng extract-i18n test-lib (the documentation states that the last parameter is the name of the Angular library: https://angular.io/cli/extract-i18n)

Unfortunately I get the following error:

Project 'test-lib' does not support the 'extract-i18n' target.

Versions:

Repo: https://github.com/michaelhunziker/angular-i18n-library/

What am I doing wrong?

Maybe you could also verify my understanding of the current Angular library translation process:

  1. Extract messages from the library using: ng extract-i18n test-lib. This results in a messages.xlf file containing only translations from that library 'test-lib'.
  2. Create language specific XLF translation files for the library.
  3. Publish the library to npm (including these XLF translation files)
  4. Consume the library in another app (e.g. 'some-app') as an npm dependency and use 36792 to merge the library translations files into the translation files of 'some-app'.
destus90 commented 3 years ago

@michaelhunziker perhaps you didn't define extract-i18n builder for that lib? Something like https://github.com/michaelhunziker/angular-i18n-library/blob/main/angular.json#L76-L81

michaelhunziker commented 3 years ago

@destus90 I just added that target: https://github.com/michaelhunziker/angular-i18n-library/commit/3a4be6e3bb9a741bcaeeb449051af3f882f29d0b

When running ng extract-i18n test-lib I now get:

The "path" argument must be of type string. Received type undefined

This seems to be a duplicate of https://github.com/angular/angular-cli/issues/17140#issue-574538931

Obviously ng extract-i18n is still not working for libraries and we have to use localize-extract according to this answer

petebacondarwin commented 3 years ago

@michaelhunziker - yes that is correct. I am sorry that the docs are a bit behind on this. And also that extracting messages from libraries is not straightforward.

michaelhunziker commented 3 years ago

@petebacondarwin thanks for your confirmation!

It's working now with localize-extract: https://github.com/michaelhunziker/angular-i18n-library/blob/main/README.md

I also had to add import '@angular/localize/init'; to public-api.ts in order to use $localize within the library: https://github.com/michaelhunziker/angular-i18n-library/blob/main/projects/test-lib/src/public-api.ts#L4 as documented here: https://github.com/angular/angular/issues/36757#issuecomment-660318825

petebacondarwin commented 3 years ago

Glad to hear it.

angular-automatic-lock-bot[bot] commented 3 years ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.