【JS】言語に応じて対応するページに振り分ける方法。ただし注意点あり・・・

多言語サイトで、言語に応じてページを振り分けたい。そのようなサイトを作る機会があったので、今回はJSでブラウザの言語設定を取得して振り分ける方法を紹介したいと思います。

## リダイレクトさせる、その前に
よし、これからリダイレクトさせるぞ！と意気込んでいるかと思いますが、ひとつ悲しいお知らせがあります。**Googleはリダイレクトは推奨していません**。なぜならクローラが正しくページを見つけられないからです。

```
ユーザーの言語設定に応じて、動的にコンテンツを変更する方法や、ユーザーをリダイレクトする方法を採用する場合は、
コンテンツのすべてのパターンを Google が見つけてクロールするとは限らないことにご注意ください。
```
他にもIPアドレスで判断して振り分ける方法もおすすめしていません。なるべくなら、リダイレクトなど動的な振り分けはしないほうがよいです。
[多地域、多言語のサイトの管理](https://support.google.com/webmasters/answer/182192?hl=ja)


## ブラウザの言語設定を取得してページを振り分ける方法
具体的に方法をみていきたいと思います。今回私はざっくり以下のような方法をとりました。

- ブラウザの言語設定を取得
- sessionStorageで初回か判定
- switchで飛ばしたいページに飛ばす

### 完成形
先に完成形です。

```ridirect.js
    /**
     * 言語設定に応じてリダイレクト
     *
     * @returns {undefined}
     */
    function ridirectURL() {
      const baseUrl = 'https://example.com/';
      const browserLang = (window.navigator.languages && window.navigator.languages[0]) ||
        window.navigator.language ||
        window.navigator.userLanguage ||
        window.navigator.browserLanguage;

      // console.log(browserLang); ←コンソールにブラウザの言語設定を表示させる

      switch(browserLang) {
        // 英語
        case 'en':
        case 'en-US':
          location.href = `${baseUrl}en`;
          break;
        // 簡体字
        case 'zh-CN':
        case 'zh-Hans':
        case 'zh-SG':
          location.href = `${baseUrl}cs/`;
          break;
        // 繁体字
        case 'zh-Hant':
        case 'zh-MO':
        case 'zh-HK':
        case 'zh-TW':
          location.href = `${baseUrl}ct/`;
          break;
        default:
          break;
      }
    };

    /**
     * セッション初回の判定
     *
     * @returns {undefined}
     */
    function firstOrNot() {
      // sessionStorageに 'access' というアイテムがなかったら
      if(!sessionStorage.getItem('access')){
        sessionStorage.setItem('access', 0); // sessionStorageにアイテムをセット
        ridirectURL(); // 前述のリダイレクト処理を実行
      }
    };
```

### ブラウザの言語設定を取得
[javascriptでブラウザの言語設定を取得する](https://qiita.com/shogo82148/items/548a6c9904eb19269f8c)の記事を参考にブラウザの言語設定を取得します。

各言語はディレクトリを分けて作っています。
基本は日本語ページ、それ以外に対応する言語があれば、そのページに振り分けます。計４種類。

```
// 日本語
https://example.com/
// 英語
https://example.com/en/
// 中国語 簡体字
https://example.com/cn/
// 中国語 繁体字
https://example.com/ct/
```
#### 言語コードについて
取得される言語コードですが、 `ja` のように言語コードだけの場合と、 `ja-JP`と言語コードと国コードがハイフンつなぎになっている場合もあります。

```
属性には単一の「言語タグ」を Tags for Identifying Languages (BCP47) で定義された書式で持ちます。
```
[MDN:lang](https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/lang)
[Tags for Identifying Languages BCP47](https://www.ietf.org/rfc/bcp/bcp47.txt)

詳しくは↑を参照ですが、なかなか細かく定義されていますので、興味がある人は目を通してみてください。


```js
    /**
     * 言語設定に応じてリダイレクト
     *
     * @returns {undefined}
     */
    function ridirectURL() {
      const baseUrl = 'https://example.com/';
      const browserLang = (window.navigator.languages && window.navigator.languages[0]) ||
        window.navigator.language ||
        window.navigator.userLanguage ||
        window.navigator.browserLanguage;

      switch(browserLang) {
        // 英語
        case 'en':
        case 'en-US': // アメリカ英語
          location.href = `${baseUrl}en/`;
          break;
        // 簡体字
        case 'zh-CN': // 中国語
        case 'zh-Hans': // 簡体字
        case 'zh-SG': // シンガポール
          location.href = `${baseUrl}cs/`;
          break;
        // 繁体字
        case 'zh-Hant': // 繁体字
        case 'zh-MO': // マカオ
        case 'zh-HK': // 香港
        case 'zh-TW': // 台湾
          location.href = `${baseUrl}ct/`;
          break;
        default:
          break;
      }
    };
```

**ちょっと補足**
`zh-MO`(中華人民共和国マカオ特別行政区) ですが、端末によっては簡体字と繁体字の両方設定できるものもありました。今回は繁体字に振り分けることにしました。このように、言語設定に応じて細かく振り分けるとなるとなかなか大変です。

また、上の例では全てのブラウザ言語設定に対して、対応したページに振り分けられないかもしれません。言語コードの条件判定は適宜設定してください。


### sessionStorageで初回か判定
[WebStorageAPIを使って初回アクセス時だけLoadingを表示する](https://qiita.com/kfunnytokyo/items/8c7777fa28fef10782d6) の記事を参考にsessionStorageを使い、セッションの初回かどうかを判定。2回目以降なら、なにもさせないようにします。

```js
    /**
     * セッション初回の判定
     *
     * @returns {undefined}
     */
    function firstOrNot() {
      // sessionStorageに 'access' というアイテムがなかったら
      if(!sessionStorage.getItem('access')){
        sessionStorage.setItem('access', 0); // sessionStorageにアイテムをセット
        ridirectURL(); // 前述のリダイレクト処理を実行
      }
    };
```

**ぼやき**
もっとわかりやすい関数名にしたい・・・

## まとめ
というわけでJSでブラウザの言語設定を取得して、対応する言語ページに振り分ける処理を紹介しました。最初の方にいったとおり、動的に言語ページを切り替えるのはおすすめできません。それでもどうしてもというときに参考にしてみてください。

また多言語サイトを作る際は`hreflang`の設定も忘れず行いましょう。
[ページのローカライズ版について Google に知らせる](https://support.google.com/webmasters/answer/189077)

---

**参考**
[WHATWG Living Standard:  langおよびxml:lang属性](https://momdo.github.io/html/dom.html#the-lang-and-xml:lang-attributes)
[言語コード](https://so-zou.jp/web-app/tech/data/code/language.htm)
[window.navigator.language](https://developer.mozilla.org/ja/docs/Web/API/NavigatorLanguage/language)
[地球の歩き方: マカオ](https://www.arukikata.co.jp/country/MO/)
[地元マカオ人に聞いた！マカオで食べるべきおすすめマカオグルメ8選](https://tripnote.jp/macau/osusume-gourmet-macau)