React nativeとExpoの構成でreact-i18nextとexpo-localizationを組合わせて国際化ローカリゼーションを行う

# 記事概要
結構ハマって苦しんだので、ほかに苦しむ人が減るように記事を書きます。
React nativeとExpoの構成で国際化ローカリゼーションをスマホアプリに行います。

似たような記事は、いくらでも検索で見つかりますが、Expo対応という点がこの記事のセールスポイントかなと思います。よりニッチで汎用性が無いとも言えますね。

## 補足
この記事でよく頻発するキーワード`i18n`はInternationalization（インターナショナリゼーション）の略で、国際化対応を意味します。

## 使用ライブラリ
+ i18next
+ react-i18next 
+ expo-localization
　
i18next react-i18next expo-localizationを動かす。
最小構成を意識したので、ロジックが理解しやすい記事になったと思う。

## 作業手順
ライブラリをインストールする
↓
言語ファイル(json)を各種言語別に用意する
↓
i18next.jsを作り、ライブラリ・言語ファイルを各種インポートする。
↓
`<I18nText>`コンポーネント作成
↓
i18next.jsをindex.jsxで読み込む
↓
`<I18nText>`コンポーネントとjsonファイルで翻訳するテキストを作成する。

## 翻訳ロジック

`expo-localization`の`Localization.locale`で端末の使用言語を取得する。
↓
翻訳したい言語を
`<I18nText>言語.json:キーを書く</I18nText>`　とjsonに書く
端末の使用言語が翻訳言語リストの中にあれば、言語の切り替えが行われる。
↓
なければデフォルト言語が使用される。


## ライブラリをインストール
```
npm install i18next react-i18next expo-localization
```
## ライブラリの説明
+ i18next react-i18next 言語ファイルの切り替えを行う　ローカライズの肝
+ expo-localization　端末の情報を取得する

## ディレクトリ構成
```
.
├── app/
│   └── index.jsx
├── commponets/
│   └── i18nText.jsx
└── localization/
    ├── locals/
    │   ├── en.json
    │   ├── ja.json
    │   ├── sv.json
    │   └── /お好みの言語/
    └── i18next.js
```
結構ディレクトリ構成は自由度が高いので適宜個人でわかりやすいように設定して貰えたらいいなと思います。

# localization / i18next.js

```React
import i18next from 'i18next';
import {initReactI18next} from 'react-i18next';
import * as Localization from 'expo-localization';

import en from './locales/en.json';
import sv from './locales/sv.json';
import ja from './locales/ja.json';

export const languageResources = {
    en: {translation: en}, 
    sv: {translation: sv},
    ja: {translation: ja},
};

const deviceLanguage = Localization.locale;



i18next.use(initReactI18next).init({
    compatibilityJSON: 'v3',
    lng: deviceLanguage,
    fallbackLng: 'en',
    resources: languageResources,
});

export default i18next;
```
各種言語ファイルを読み込んで`expo-localization`の`Localization.locale`で端末の使用言語を取得してそれを代入している。

## 各種言語ファイル　採用する言語はお好みで

## locals / en.json

```json
{
    "change-language": "Change language,"
    "welcome": "Welcome to my app"
}
```
## locals / ja.json

```json
{
    "change-language": "言語を切り替える",
    "welcome": "国際化の世界へようこそ"
}
```
## locals / sv.json

```json
{
    "change-language": "Ändra språket",
    "welcome": "Välkommen till min app"
}
```

## components / i18nText.jsx
```React
import React from 'react';
import {useTranslation} from 'react-i18next';
import {Text, TextStyle} from 'react-native';

const I18nText = (props) => {
    const {children, style, translate = true} = props;

    const {t, i18n} = useTranslation();

    return <Text style={style}>{translate ? t(children) : children}</Text>;
};

export default I18nText;
```
単純化するためにコンポーネント化　するかどうかは個人の判断にゆだねる

`<Text>`コンポーネントと使い方は微妙に違う。jsonファイルと組み合わせて翻訳機能を利用したいテキストをjsonファイルに書く　キーを書くだけ。


## app / index.jsx
```React
import React from 'react';
import { View } from 'react-native';
import I18next from "../localization/i18next";
import I18nText from "../components/i18nText";


function Index() {
    return (
        <View>
           <I18nText>welcome</I18nText>
           <I18nText>change-language</I18nText> 
        </View>
    );
}

export default Index;
```
最小構成で申し訳ないけれど、動けばいいので見栄えは気にしない
日本語を端末に設定しているとja.jsonのwelcomeに書いた言葉が表示される。
英語であればen.jsonとなる。色々動かして検証してみて下さい

端末に設定してある言語が`languageResources`にない場合は、デフォルト言語として`fallbackLng: 'en',`が採用されます。ここでは英語を設定しています。
多分この認識であってると思いますが、自信が無いので、自信ニキ・ネキはマサカリを投げつけてください


コンポーネント化したので見栄えが多少良くなって可読性も向上してる(気がする)

## 参考にした記事や動画

コンポーネント化の仕組みとかを参考にした。

https://medium.com/@eeshan97/i18next-in-react-native-multi-language-e6422c4ddae8

Githubにソースコードを公開しているので大変参考になった。
言語切り替え設定ボタンの実装など動画内で説明されている。でもたぶん、電源を切ると設定が消えると思うので`AsyncStorage`とかを使って端末に保存する仕組みを自分で実装するハメになりそう　

https://www.youtube.com/watch?v=g_efptBp0tY&t=14s



## 公式ドキュメント

https://react.i18next.com/

https://docs.expo.dev/versions/latest/sdk/localization/