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 ready event missing

See original GitHub issue

I’m submitting a…


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

Current behavior

I have a list of objects used for a dropdown containing a key from which a localized label is created. As the list is to be sorted by its localized label alphabetically the translation has to be done in code instead of within the template. The user is able to switch the language during app usage. The documentation mentions the langChanges$ Observable to get informed on these language changes so we can update the list:

transloco.langChanges$.pipe(
  takeUntil(this.unsubscribe$)
).subscribe(() => this.updateList());

If the language is switched to for the first time the langChange event is emitted before the corresponding language file has been loaded and thus errors are written to the console as well as leaving the labels untranslated. First workaround is to wait for the load event of the translation file too:

transloco.langChanges$.pipe(
  takeUntil(this.unsubscribe$),
  switchMap(() => transloco.events$)
).subscribe(() => this.updateList())

But then of course this won’t work if the file has already been fetched, getting us to

transloco.langChanges$.pipe(takeUntil(this.unsubscribe$)).subscribe(() => {
  const testKey: string = 'existing-key';
  if (testKey !== transloco.translate('existing-key')) {
    this.determineFilterKeys();
  } else {
    transloco.events$.pipe(take(1)).subscribe(() => this.updateList()));
  }
);

But you still get errors logged on the console and this does feel way too complicated.

Expected behavior

The langChanges event should be emitted if the language is ready in that either the file with translations is already present or successfully loaded. Alternatively there should be a languageReady event or similar.

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

Loading of translation should be part of the language switch.

Environment


Angular version: 8.2.14
transloco version: 2.12.1


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: 12.2.0  
- Platform:  Mac/Windows

Others:

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:7
  • Comments:21 (15 by maintainers)

github_iconTop GitHub Comments

7reactions
FloNeucommented, Feb 19, 2021

This still isn’t merged yet - where is the problem to add a cleanway to allow this… for example only fire the language switch event after the required lang is available… i have the problem that i have to translate the labels on an object in code… and in the view i can’t bind to an observable because it comes from a lib. So when i switch from initial lang to alternating lang and trigger my translation onChange - i get the keys back because the language isn’t there yet… all order ways are somehow hacky… This should just work imho

2reactions
ChazUKcommented, Aug 19, 2020

@shaharkazaz Thanks for the demo. I had a few problems with the loader as I want to reuse it across many components, so updated that to

export const availableLangs = ['en', 'es'];

export const scopeLoader = (importer, scope = null, root = 'i18n') => {
  return availableLangs.reduce((acc, lang) => {
    acc[scope ? `${scope}/${lang}` : lang] = () => importer(lang, root);
    return acc;
  }, {});
};

This can then be included on general components which don’t need “in code” translations, omitting the scope in the loader:

@Component({
  selector: 'app-general',
  template: `
    <ng-container *transloco="let t; read: 'generalComponent'">{{
      t('title')
    }}</ng-container>
  `,
  providers: [
    {
      provide: TRANSLOCO_SCOPE,
      useValue: {
        scope: 'generalComponent',
        loader: scopeLoader((lang, root) => import(`./${root}/${lang}.json`)),
      },
    },
  ],
})
export class GeneralComponent

And now can also be used in components which require “in code” translations

const loader = scopeLoader(
  (lang, root) => import(`./${root}/${lang}.json`),
  'inCode'
);

@Component({
  selector: 'app-in-code',
  template: `
    <div #view></div>
  `,
  providers: [
    {
      provide: TRANSLOCO_SCOPE,
      useValue: {
        scope: 'inCode',
        loader
      },
    },
  ],
})
export class InCodeComponent implements OnInit {
  constructor(
    protected translocoService: TranslocoService,
    @Inject(TRANSLOCO_SCOPE) protected scope,
  ) {}

  ngOnInit() {
    this.translocoService.langChanges$
      .pipe(
        switchMap(lang => {
          console.log('Active lang is:', lang);
          return this.translocoService.load(`${this.scope.scope}/${lang}`, {
            inlineLoader: loader,
          });
        })
      )
      .subscribe(v => {
        console.log('Lang changed and scope loaded!', v);
      });
  }
}

Tested and working! Will look forward to the new function.

Read more comments on GitHub >

github_iconTop Results From Across the Web

No results found

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