記事概要
結構ハマって苦しんだので、ほかに苦しむ人が減るように記事を書きます。
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
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
{
"change-language": "Change language,"
"welcome": "Welcome to my app"
}
locals / ja.json
{
"change-language": "言語を切り替える",
"welcome": "国際化の世界へようこそ"
}
locals / sv.json
{
"change-language": "Ändra språket",
"welcome": "Välkommen till min app"
}
components / i18nText.jsx
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
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',
が採用されます。ここでは英語を設定しています。
多分この認識であってると思いますが、自信が無いので、自信ニキ・ネキはマサカリを投げつけてください
コンポーネント化したので見栄えが多少良くなって可読性も向上してる(気がする)
参考にした記事や動画
コンポーネント化の仕組みとかを参考にした。
Githubにソースコードを公開しているので大変参考になった。
言語切り替え設定ボタンの実装など動画内で説明されている。でもたぶん、電源を切ると設定が消えると思うのでAsyncStorage
とかを使って端末に保存する仕組みを自分で実装するハメになりそう
公式ドキュメント