Browser language is not set correctly
Closed this issue · 4 comments
Hi Roberto,
We just updated our app to Angular v9 and we updated your library after that and we got it to work, except for setting the browser language. We support multipe languages, but setting the browser to en-GB and loading the app it defaults back to en-US (default locale). If I set the browser to nl-NL it works fine and it loads the dutch translations in the initial load. (Changing languages after the initial load works fine).
In the docs I have seen the L10nUserLanguage
class-interface, but I don't want the user-language loaded from the server. So I'm not sure if I can/have to use that.
I have also tried it in your angular-l10n-app but it didn't work their either. The only changes I made in your app are the following:
l10n-config.ts:
export const l10nConfig: L10nConfig = {
format: 'language-region',
providers: [
{ name: 'app', asset: './assets/i18n/app', options: { version: '9.0.0' } }
],
fallback: false,
cache: true,
keySeparator: '.',
defaultLocale: { language: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles' },
schema: [
{ locale: { language: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles' }, dir: 'ltr', text: 'United States' },
*{ locale: { language: 'en-GB', currency: 'GBP', timeZone: 'Europe/London' }, dir: 'ltr', text: 'United Kingdom' },*
{ locale: { language: 'it-IT', currency: 'EUR', timeZone: 'Europe/Rome' }, dir: 'ltr', text: 'Italia' }
],
defaultRouting: true
};
And I added the app-en-GB.json
and the lazy-en-GB.json
files to the i18n folder.
I then run the app using the ng serve -o
command. The app loads in the broswer, but it defaults back to en-US and when I click the United Kindom button it correctly loads the en-GB file.
Hopefully you can help me figure this out.
Kind Regards
The behavior of the browser language has not changed in the new version: when you use a language-region
format, during the first load the library tries to take the language:
- from the link (if any)
- then in the storage (if any)
- finally the default
That's because getBrowserLanguage
method takes only the first part (the language), since not all browsers return the region:
angular-l10n/projects/angular-l10n/src/lib/models/utils.ts
Lines 37 to 46 in 97b1fc6
You can change the way the browser language is obtained by implementing L10nUserLanguage
class-interface: https://robisim74.github.io/angular-l10n/injectables/L10nUserLanguage.html#source
Thank you for your quick response.
It is still not clear to me how the getBrowserLanguage
method get's into play based on the bullets you provided. (but maybe that's not really important)
I'm now trying to implement the get method from the L10nnUserLanguage
but so far without success. Hopefully you can point me in the right direction. What I'm trying to do is the following
app.component.ts
export class AppComponent implements OnInit, L10nUserLanguage {
constructor(
@Inject(L10N_LOCALE) public locale: L10nLocale,
private _translation: L10nTranslationService
) { }
ngOnInit(): void {
...
}
get(): Promise<string> {
return Promise.resolve('nl');
}
setLocale(locale: L10nLocale): void {
this._translation.setLocale(locale);
}
}
for now I'm tryig to return a static language code that we support, but the locale is still set to en-US (default). If and when I get that working I can apply my own logic to get the language.
For completion I'll include our l10n-config.ts
export const l10nConfig: L10nConfig = {
format: 'language-region',
providers: [
{ name: 'app', asset: '/shared-files-output/locale', options: { version: '9.1.0' } }
],
fallback: true,
cache: true,
keySeparator: '.',
defaultLocale: { language: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles'},
schema: [
{ locale: { language: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles'}, dir: 'ltr', text: 'United States' },
{ locale: { language: 'en-GB', currency: 'GBP', timeZone: 'Europe/London'}, dir: 'ltr', text: 'United Kingdom' },
{ locale: { language: 'nl', currency: 'EUR', timeZone: 'Europe/Amsterdam'}, dir: 'ltr', text: 'Nederland' },
{ locale: { language: 'fr',currency: 'EUR', timeZone: 'Europe/Paris'}, dir: 'ltr', text: 'France' },
{ locale: { language: 'de', currency: 'EUR', timeZone: 'Europe/Berlin'}, dir: 'ltr', text: 'Deutschland' }
],
defaultRouting: true
};
Hopefully you can help me figure this out.
Kind Regards
As in the docs (https://github.com/robisim74/angular-l10n#user-language), the library tries to take the user's browser language, before falling back on the default locale: only the language
, not language-region
, because there are inconsistencies between browsers for language-region
.
If you want language-region
, you have to override L10nUserLanguage
, for example:
@Injectable() export class UserLanguage implements L10nUserLanguage {
public get(): Promise<string | null> {
let browserLanguage = null;
if (navigator !== undefined && navigator.language) {
// Takes the complete locale, not only the language as in the the default version
console.log(navigator.language);
browserLanguage = navigator.language;
}
return Promise.resolve(browserLanguage);
}
}
and then in AppModule
:
L10nTranslationModule.forRoot(
l10nConfig,
{
userLanguage: UserLanguage
}
)
Plus, you're using a mix of formats at the same time, not only language-region
like en-GB
, but also only language
like nl
, therefore you should change again:
@Injectable() export class UserLanguage implements L10nUserLanguage {
public get(): Promise<string | null> {
let browserLanguage = null;
if (navigator !== undefined && navigator.language) {
console.log(navigator.language);
const lang = navigator.language.split('-')[0];
if (lang === 'en') {
// Takes the complete locale
browserLanguage = navigator.language;
} else {
// Takes only the language
browserLanguage = lang;
}
}
return Promise.resolve(browserLanguage);
}
}
Thanks again for the quick reply.
I was missing the part of adding it to the AppModule. It's working as a charm now.
Thank you very much.