question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Language fallback doesn't work properly

See original GitHub issue

I’m submitting a…


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request
[ ] Other... Please describe:

Current behavior

Custom TranslocoFallbackStrategy not working properly. It will skip some of the fallback langs. Because the this.failedCounter is misused. the fallbacks variable is re-evaluate on each failure, because the parameter passed to this.fallbackStrategy.getNextLangs(lang) is the current failed language. It’s not the original failed language. So when this.failedCounter’s value increases to 1. It will ignore the first element in new fallbacks.

Given the original lang zh-Hans-CN:

  1. Load zh-Hans-CN failed.
  2. getNextLangs() returns ['zh-Hans', 'zh', 'en']. failedCounter is 0. It will try to load zh-Hans. And increase failedCounter to 1
  3. Load zh-Hans failed
  4. getNextLangs() returns ['zh', 'en'], because handleFailure receives zh-Hans as parameter instead of zh-Hans-CN. failedCounter is 1. It will try to load en. Error Here: ‘zh’ is skipped!

https://github.com/ngneat/transloco/blob/master/projects/ngneat/transloco/src/lib/transloco.service.ts#L558

  private handleFailure(lang: string, mergedOptions) {
    const splitted = lang.split('/');
    const fallbacks = mergedOptions.fallbackLangs || this.fallbackStrategy.getNextLangs(lang);
    const nextLang = fallbacks[this.failedCounter];
    this.failedLangs.add(lang);

Expected behavior

Given the original lang zh-Hans-CN, and getNextLangs() returns ['zh-Hans', 'zh', 'en'].

Transloco should try to load files in the following order:

  1. zh-Hans-CN.json
  2. zh-Hans.json
  3. zh.json
  4. en.json

In above scenario, zh.json will be skipped.

Minimal reproduction of the problem with instructions

For bug reports please provide the STEPS TO REPRODUCE and if possible a MINIMAL DEMO of the problem, for that you could use our stackblitz example

What is the motivation / use case for changing the behavior?

Environment


Angular version: X.Y.Z


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:3
  • Comments:23 (22 by maintainers)

github_iconTop GitHub Comments

1reaction
zhongspcommented, Feb 16, 2021
  • As a fix for the current situation the getNextLangs should be called only once on the first language failure.

    • Totally agree. This is what I’m trying to do in the fix PR. The getNextLangs() is only called at the first time of loading translation failed. And the langs in NextLangs in tried one by one, until loading a translation successfully. In the meanwhile, getNextLangs() must not be evaluated again.
  • In the future I think that getNextLangs should be replaced with getNextLang, so the strategy will decide individually for each failed lang what should be loaded next.

    • I really like this idea. From a API consumer perspective, provide a single fallback language according to the failed one is enough. It’s simpler and easier to understand. From transloco perspective, it’s easier to implement, I think.

@shaharkazaz

1reaction
zhongspcommented, Feb 14, 2021

@shaharkazaz Thanks very much for replying.

This is my custom TranslocoFallbackStrategy:

export class LanguageFallbackStrategy implements TranslocoFallbackStrategy {
  static readonly defaultLang = 'en';

  /**
   * @example
   * 
   * failedLang: 'zh-Hans-CN'
   * Returns: ['zh-Hans', 'zh', 'en']
   *
   * lang: 'fr-CA'
   * Returns: ['fr', 'en']
   */
  getNextLangs(failedLang: string): string[] {
    const langs = this.getAllLangs(failedLang);
    return failedLang === langs[0] ? langs.slice(1) : langs;
  }

  /**
   * @example
   * 
   * lang: 'zh-Hans-CN'
   * Returns: ['zh-Hans-CN', 'zh-Hans', 'zh', 'en']
   *
   * lang: 'fr-CA'
   * Returns: ['fr-CA', 'fr', 'en']
   */
  getAllLangs(lang: string): string[] {
    if (this.isLangValid(lang)) {
      const langs: string[] = [];

      // For example, `zh-Hans-CN` may next check for
      // `zh-Hans`, then if `zh-Hans` is not found, `zh`.
      const splitted = lang.split('-');
      splitted.reduce((acc, cur) => {
        const lang = acc ? `${acc}-${cur}` : `${cur}`;
        langs.unshift(lang);
        return lang;
      }, '');

      // append the default language to the end
      const lastLang = langs[langs.length - 1];
      if (lastLang !== LanguageFallbackStrategy.defaultLang) {
        langs.push(LanguageFallbackStrategy.defaultLang);
      }

      return langs;
    } else {
      return [LanguageFallbackStrategy.defaultLang];
    }
  }
}

And add it to root providers:

export const translocoFallbackStrategy = {
  provide: TRANSLOCO_FALLBACK_STRATEGY,
  useClass: LanguageFallbackStrategy,
};

@NgModule({
  imports: [TranslocoModule],
  exports: [TranslocoModule],
})
export class I18nModule {
  static forRoot(): ModuleWithProviders<I18nModule> {
    return {
      ngModule: I18nModule,
      providers: [
        acceptLanguageInterceptor,
        selectBrowserLanguageProvider,
        translocoConfig,
        translocoFallbackStrategy,
        translocoLoader,
      ],
    };
  }
}

I thought this is all I need to code to make the language fallback work. However, this is not working as I expected. 😄

Read more comments on GitHub >

github_iconTop Results From Across the Web

Language fallback not working for a specific language
As noted in another answer, ensure the fallback language value is set in your "de" language item. Be sure to add the patch...
Read more >
TYPO3 9,10,11 Languages ​fallback doesn't seem to work ...
The language en-de should refer to english (master) as a fallback. In TYPO3 itself I created the sys_languages ​​and also translated 1 page...
Read more >
[SOLVED] Localizable Array: language fallbacks don't work
Language fallbacks are applied properly for arrays as well. I guess that the issue is likely caused by squidex not being able to...
Read more >
Sort out and fix language fallback inconsistencies - Drupal
Here's a well-shuffled list: EntityRepository::getTranslationFromContext returns the passed-in entity translationif it does not find a fallback.
Read more >
Language Fallback Module: Endless Fallback Problem Fix
The idea behind the fix is to create a new method which will check if the fallback language equals the current language or...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found