robisim74 / angular-l10n

Angular library to translate texts, dates and numbers
MIT License
380 stars 59 forks source link

Fallback when key doesn't exist #304

Closed davidgerrard closed 4 years ago

davidgerrard commented 4 years ago

Hi,

I am trying to fallback to en-US for a key if the key in it-IT doesn't exist, but I currently get returned the key. I am using the demo app you provided to test this out. I have set the L10nConfig 'fallback' to true, and tried to implement a fallback provider, without success.

To test, I have removed the 'home.title' key from the app-it-IT.json. I expect the app to use 'home.title' from the app-en-US.json instead. If the key doesn't exist in the app-en-US either, then I expect the missing translation to trigger, which it does.

In previous versions I think setting the fallback option automatically looked up the key in the default locale.

I'm not sure what I am missing. Could you shed some light on this please?

robisim74 commented 4 years ago

Hi @davidgerrard,

Fallback operation has not changed since previous versions: by default, the library does not fallback to another language.

You have two ways to do this:

davidgerrard commented 4 years ago

I've done some more investigating on this and it seems like it is not working for lazy loaded modules. I have implemented a custom L10nTranslationFallback and L10nMissingTranslationHandler class which works for the app component.

If there is no matching key in it-IT, it uses the key in en-US and translates.

If I try the same in the lazy loaded module, I just get the key, even though I can see it hitting the L10nMissingTranslationHandler I have. The data is there when I debug it, but the value is not returned to the component in the lazy loaded module.

I have imported L10nTranslationModule to the lazy module, and also tried to use the resolve as per the docs.

Very strange.

robisim74 commented 4 years ago

Could you create a repro or at least post the custom classes?

davidgerrard commented 4 years ago

Yes sorry I was in the middle of creating one to try and show you :-)

Here is the stackblitz: https://stackblitz.com/edit/angular-l10n-lazy-fallback

I change the locale in the app component to it-IT.

Repro steps,

  1. Click the load lazy component button > all strings should have itIT in them
  2. In the locale-it-IT.json file, remove /rename the keys
  3. Save and refresh the app
  4. Notice now that the 2 param strings disappear for some reason.

The 2 plain strings fallback to en-US as expected. This is working here but not in my app, so I will have to keep digging on that one. But the other parameterised strings I would also expect to fallback to en-US.

Using version 9.2. Thanks.

robisim74 commented 4 years ago

OK, now I got it.

The problem here is that you are never actually preloading your fallback file (you are assuming that en-US is initially loaded, but this depends on the language of the user, and then you force it on it-IT (and lazy loaded module won't work).

As I said, you have two ways to achieve that:

The easiest way is the first:

export class TranslationFallback implements L10nTranslationFallback {
    ...
    get(language: string, provider: L10nProvider): Observable<any>[] {
        const loaders: Observable<any>[] = [];

        if (this.config.cache) {
            loaders.push(
                this.cache.read(`${provider.name}-fallback-${language}`,
                    this.translationLoader.get('en-US', provider)));
            loaders.push(
                this.cache.read(`${provider.name}-${language}`,
                    this.translationLoader.get(language, provider)));
        } else {
            loaders.push(this.translationLoader.get('en-US', provider));
            loaders.push(this.translationLoader.get(language, provider));
        }

        return loaders;
    }
}

So you don't need the custom MissingTranslationHandler, unless you need to trace the missing keys.

davidgerrard commented 4 years ago

Thanks, I had something like that originally. I've moved the setting locale earlier too as part of init and it looks like it is working as expected now. Thanks for the help!