i18next + i18next-browser-languagedetectorでの開発時には、localStorageに注意する

ちょっとハマりそうになったので覚書。 起きたこと i18next + i18next-browser-languagedetector + react-i18nextで多言語化 言語切り替えスイッチを実装 「ブラウザの設 […]

広告ここから
広告ここまで

目次

    ちょっとハマりそうになったので覚書。

    起きたこと

    • i18next + i18next-browser-languagedetector + react-i18nextで多言語化
    • 言語切り替えスイッチを実装
    • 「ブラウザの設定言語」を変えても、言語が変わらない

    原因

    言語切り替え(i18n.changeLanguage)を行うと、localStorageに選択した言語が書き込まれます。

    そのため、i18next-browser-languagedetectorがlocalStorageの値を優先して翻訳するようになっていました。

    対策案1: 都度localStorageを消す

    ブラウザの設定言語を読んだ時の挙動を確認したい場合のみ、localStorageの値を消しましょう。

    特に設定を変えていない場合、i18nextLngで保存されていますので、ブラウザの開発ツールを使って必要になったら消しましょう。

    対策案2: localStorageの優先度を下げる

    どうしてもブラウザの設定を優先したい場合、優先順位を下げると良さそうです。

    import LanguageDetector from 'i18next-browser-languagedetector';
    
    const detector = new LanguageDetector(null, {
      order: ['querystring', 'cookie',  'navigator', 'localStorage', 'htmlTag'],
      htmlTag: document.documentElement,
    });

    navigatorがブラウザの言語設定ですので、localStorageより前に出してやるとよいでしょう。

    上のサンプルコードでは、Cookieやクエリストリングでの指定には負けることに注意です。

    余談: i18next-browser-languagedetectorを使うなら、lngは指定しない

    i18nextを使う場合、以下のように設定を書きます。

    import i18next from 'i18next';
     
    i18next.init({
      lng: 'en', 
      debug: false,
      resources: {
        en: {
          translation: {
            "key": "hello world"
          }
        }
      }
    });

    i18next-browser-languagedetectorを使いたくなると、直感的にはこう書くのが良さそうです。

    import i18next from 'i18next';
    import LanguageDetector from 'i18next-browser-languagedetector';
     
    i18next
      .use(LanguageDetector)
      .init({
      lng: 'en', 
      debug: false,
      resources: {
        en: {
          translation: {
            "key": "hello world"
          }
        }
      }
    });

    ですが、ここにはちょっとした罠があります。それは、「intlngを消す必要がある」ことです。

    Detectorよりもint()lngが優先されますので、このままでは常に英語(en)が表示されます。

    なにかしらのdetectorを使う場合は、lngを消すようにしましょう。

    import i18next from 'i18next';
    import LanguageDetector from 'i18next-browser-languagedetector';
     
    i18next
      .use(LanguageDetector)
      .init({
      debug: false,
      resources: {
        en: {
          translation: {
            "key": "hello world"
          }
        }
      }
    });

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark