gilsdav / ngx-translate-router

Translate routes using ngx-translate
130 stars 44 forks source link

Unable to set defaultLanguage in TranslateModule #86

Closed yaniv14 closed 4 years ago

yaniv14 commented 4 years ago

Hi,

When using your package I am unable to set defaultLanguage in TranslateModule. When settings defaultLanguage I am getting Error: Cannot instantiate cyclic dependency! Router

This is my setup:

    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      },
      defaultLanguage: 'he'
    }),
    RouterModule.forRoot(
      appRoutes,
      {
        preloadingStrategy: PreloadAllModules,
        onSameUrlNavigation: 'reload',
        scrollPositionRestoration: 'top',
        enableTracing: !environment.production
      }
    ),
    LocalizeRouterModule.forRoot(appRoutes, {
      parser: {
        provide: LocalizeParser,
        useFactory: (translate, location, settings, http) =>
          new LocalizeRouterHttpLoader(translate, location, settings, http),
        deps: [TranslateService, Location, LocalizeRouterSettings, HttpClient]
      }
    })

Can you please advise?

gilsdav commented 4 years ago

Hello @yaniv14 Does it work as expected if you use translateService.setDefaultLang(lang) into the app component constructor instead of the "defaultLanguage" parameter ? Like here. What the version of ngx-translate ans ngx-translate-router do you use ?

yaniv14 commented 4 years ago

Hi @gilsdav When doing translateService.setDefaultLang(lang) the translation works fine, I am getting the correct translated string by language that was setup by translateService.setDefaultLang. But the router language (in url) stays in en so I am ending up with different languages for router and translation.

"@gilsdav/ngx-translate-router": "^3.1.2"
"@gilsdav/ngx-translate-router-http-loader": "^1.1.2"
"@ngx-translate/core": "^13.0.0"
"@ngx-translate/http-loader": "^6.0.0"
gilsdav commented 4 years ago

@yaniv14 I forgot (in my last answer) so say you that ngx-translate-router automaticaly set default and language. Here the documentation part:

LocalizeRouter depends on ngx-translate core service and automatically initializes it with selected locales. Following code is run on LocalizeParser init:

this.translate.setDefaultLang(cachedLanguage || languageOfBrowser || firstLanguageFromConfig);
// ...
this.translate.use(languageFromUrl || cachedLanguage || languageOfBrowser || firstLanguageFromConfig);

Both languageOfBrowser and languageFromUrl are cross-checked with locales from config.

You don't have to set it yourself.

If you don't like this default lang computing (cachedLanguage || languageOfBrowser || firstLanguageFromConfig), you can set your own defaultLangFunction into the config.

yaniv14 commented 4 years ago

@gilsdav I really appreciate your time and effort to help me. In my case all users are directed straight to the main domain (no lang prefixed). On first visit the server is attaching a data attribute that contains a preferred language by user country (detect by IP). What I am trying to achieve is that only on first visit, before LOCALIZE_DEFAULT_LANGUAGE is being set, the default language will be determined by this data attribute that was setup by the country detection (and add proper prefix to urls). After that all language of translation and/or router will be continue to determined by localStorage value.

what I doing right now (with no luck) is:

this.appLangByCountry = this.el.nativeElement.dataset.lang;

this.currentLang = localStorage.getItem('LOCALIZE_DEFAULT_LANGUAGE') || this.appLangByCountry || this.translate.getBrowserLang();

this.translate.addLangs(['he', 'en']);
this.translate.setDefaultLang(this.currentLang);
this.translate.use(this.currentLang);

and this is not working because either the LOCALIZE_DEFAULT_LANGUAGE is being set before those lines are called or its being overwritten later.

Thank you

gilsdav commented 4 years ago

Your welcome @yaniv14

I think this is typically something to do into defaultLangFunction.

Here is a pseudocode of how to use it:

LocalizeRouterModule.forRoot(routes, {
    defaultLangFunction: (locales, cachedLang, browserLang) => {
        return cachedLang ||
            document.querySelector('yourElement').dataset.lang ||
            browserLang ||
            locales[0];
    }
})

I didn't do it in the example but I think you must check if the lang returned by dataset.lang is contained by the locales array.

yaniv14 commented 4 years ago

@gilsdav Working like a charm. Thank you very much