i18next / i18next-browser-languageDetector

language detector used in browser environment for i18next

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Only first language in list of browser languages is considered?

dgmstuart opened this issue Β· comments

πŸ› Bug Report

It seems like only the first item in the user's list of browser languages is used, even if that language is not supported by the application, but there are items later in that list which are supported?

Scenario:

  • The app supports en, sv,fr
  • The app has a fallback of en
  • The user's browser languages (Chrome) are ['es', 'sv', 'en'] (checked both in Chrome settings and in the console with navigator.languages)

Expected behaviour:

  • sv should be used, since:

    1. it's a language in the user's preferred languages in the browser
    2. it's a language which the app supports
    3. it's the earliest detected language in the list which is supported by the app
  • sv should be stored in localstorage

  • the i18n object should include:

    {
    'language': 'sv',
    'languages': ['sv', 'en'],
    'resolvedLanguage':'sv'
    }

Actual behaviour:

  • the fallback en is used for translations

  • es is stored in localstorage

  • the i18n object includes:

    {
    'language': 'es',
    'languages': ['es', 'en'],
    'resolvedLanguage':'en'
    }

Code

Everything I've seen looking at the source code and other issues seems to suggest that the intention is to fetch all the languages from the browser: (

if (navigator.languages) { // chrome only; not an array, so can't use .push.apply instead of iterating
for (let i = 0; i < navigator.languages.length; i++) {
found.push(navigator.languages[i]);
}
}
)

...and to return all of them so that i18next can pick the best match, though for older versions of i18next it falls back to just picking the first one:

if (this.services.languageUtils.getBestMatchFromCodes) return detected; // new i18next v19.5.0
return detected.length > 0 ? detected[0] : null; // a little backward compatibility

So I'm wondering if there's an issue with that check and it's using the fallback behaviour of just picking the first language in the list?

Or is there some issue with my config? Am I supposed to explicitly be telling LanguageDetector that I'm using i18next? Seems unlikely:

import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import en from "./locales/en.json";
import fr from "./locales/fr.json";
import sv from "./locales/sv.json";

i18n.use(LanguageDetector).use(initReactI18next).init({
  resources: { en, fr, sv },
  fallbackLng: "en",
});

source: https://github.com/dgmstuart/bingo-frontend/blob/a5ca62efdb0ec448629e36f7792f02ca5bf2ee15/src/i18n.ts

App

The app I'm trying this is open source: https://github.com/dgmstuart/bingo-frontend

I'm happy to make a minimal reproduction app, but I wanted to check first if this was just my misunderstanding or misconfiguration.

My Environment:

  • runtime version: browser: chrome
  • i18next version: 23.11.2
  • os: Mac

getBestMatchFromCodes will pick the first detected lng code if you do not specify the supportedLngs option:

import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import en from "./locales/en.json";
import fr from "./locales/fr.json";
import sv from "./locales/sv.json";

i18n.use(LanguageDetector).use(initReactI18next).init({
  resources: { en, fr, sv },
  supportedLngs: ['en', 'sv', 'fr'],
  fallbackLng: "en",
});

Oh neat! Thank you πŸ™

I found it in the list of configuration options now, but I didn't see it in any of the example code - I'm happy to make a documentation PR if you think that's helpful?

Is it used for anything else, or is it specific to this plugin? It doesn't seem to need to be defined for translations to work?

it's not really specific to this languageDetector plugin...

feel free to provide a pr

Added a PR here: #284

I understand that supportedLngs isn't specific to this plugin, but am I correct in understanding that it is only used in relation to language detection?

I tried to find a place on https://www.i18next.com/ to add some documentation, but the docs there all seem to delegate any documentation about language detection to the individual plugins, which makes sense, but makes it hard to add any examples.