1.2.1 · 開発基盤

アプリを多言語対応しよう

2026.07.12約4分

00Overview

01Story

Situation

1.2 のとおり、まず 2 言語対応を目指す。最初に手をつけるのは、アプリ本体の表示文字列である。

Complication

しかし、画面のコードに文字列を直書きしていると、後から各言語へ置き換えるのは地獄になる。どこに何の文字列があるか探し回ることになり、言語を 1 つ足すたびに全画面を触ることになる。

Question

アプリの表示文字列を、どうすれば低コストで多言語化できる構造にできるか?

02Solution

Criteria

  • 表示文字列が一か所に集約されていること
  • 翻訳を AI にまとめて任せられること
  • 後から言語を足すのが容易なこと

Answer

表示文字列を「言語ファイル」として外に出す。コードからは文字列そのものではなくキーで参照し、実際の文言は言語ごとのファイルに持たせる。翻訳は、その言語ファイルを AI に渡して「この言語ファイルを○語に翻訳して」と頼むだけ。最終確認はするが、大部分は AI が仕上げてくれる。

Reason

文字列が一か所に集約されていれば、翻訳も差し替えも一度で済むからである。 コードに散らばっていると、AI もどこを訳せばいいか分からず、言語追加のたびに全画面を触ることになる。言語ファイルにまとめておけば、AI がまとめて訳せて、言語を足すのもファイルを 1 枚増やすだけになる。

大事なのは、翻訳の技術ではない。
多言語化しやすい構造で、最初から実装しておくことである。

ただし、一つ落とし穴がある。キーと値だけを AI に渡すと、その単語がどの画面の何を指すのか分からず、誤訳する。「Home」が家なのか先頭画面なのか、AI には判断できない。だから各文字列に、「どの画面の、何のための言葉か」という文脈をコメントで添えておく。これが訳の精度を大きく左右する。

この 2 つから、2 言語対応で意味を予測し、意味情報として開発時に意味を残すことで、飛躍的に精度を上げることができる。

Options

  • 画面に文字列を直書きする — 最初は速いが、多言語化の段になって全画面を触る羽目になる。だから採らなかった。
  • 機械翻訳 API を都度呼ぶ — 文脈理解が弱く誤訳が増える上、運用コストもかかる。AI にファイルごと文脈つきで訳させる方が質が高い。

03Result

Good

構造さえ整えれば、2 言語対応がそのまま 5 言語・50 言語へスケールする。手順は同じで、増えるのは言語ファイルの枚数だけ。地味で膨大な翻訳を、AI に任せられるようになった。

Bad

AI も、文脈がなければ誤訳する。特に専門用語や、言葉遊びを含む表現は要注意で、最終確認は欠かせない。構造と文脈を用意するのは、あくまで人の仕事である。

Follow-up

アプリ本体が多言語化できたら、次はそれを世に出すためのストア申請情報を多言語化する。続きは 1.2.2 アプリ申請を多言語対応しよう

■ 再現できる方法

この構成を自分で再現したい人向けのメモ。読み物ではないので、指示文は数行だけ表示してスクロールにしてある。

はじめに、下記を貼り付けで実行。

このアプリを多言語対応にしたいですが、今はまだ UI を作っている途中なので、
最初は日本語と英語の 2 言語だけで土台を作ってください。
(あとで全言語に広げるので、そのとき楽になる構造にしておいてほしい)

【作ってほしいもの】
1. i18n-js のセットアップ(i18n.js)
   - expo-localization で端末の言語を判定
   - 対応外の言語は英語にフォールバック(defaultLocale = 'en')
   - 今は locales/ja.json と locales/en.json の 2 つだけ import
   - 将来ここに import を足すだけで言語を増やせるコメントを残す
2. 翻訳ファイル
   - locales/ja.json(日本語=マスター)
   - locales/en.json(英語)
   - キーは snake_case で意味を表す名前にする
   - 変数の埋め込みは %{変数名} 形式にする
3. アプリのコードの文字列を i18n.t('キー') に置き換える
   - 画面に直書きされている日本語・英語の文字列を全部キー化する

【ルール】
- 翻訳キーは ja.json を正とし、en.json はその対訳にする
- ハードコードされた表示文字列が残らないようにする
  (i18n.t() を通さない生の文字列が画面に出ていないかチェック)

作り終えたら、今後 UI に文言を足すときにどういう手順でキーを追加すれば
いいか(ja.json に足す → en.json に足す → i18n.t で参照)を簡単に
まとめてください。

次に多言語対応するときに、下記を貼り付けで実行。

UI がほぼ固まったので、多言語対応を全言語に広げてください。
ja.json をマスターとして、そこから各言語に翻訳します。

【やってほしいこと】
1. UI 文字列(i18n)を 44 ロケールに拡張
   - 対象言語:
     zh, zh-TW, ko, es, fr, de, pt, it, nl, ar, ru, tr, hi, uk, he,
     id, ms, th, vi, da, sv, no, fi, pl, cs, sk, hu, ro, hr, el, ca,
     bn, gu, kn, ml, mr, or, pa, ta, te, ur, sl
     (= ja / en に上記を足して 44)
   - locales/<lang>.json を各言語分そろえる。ja.json のキー構造を完全に踏襲し、
     値だけ各言語に翻訳する(キーの過不足がないこと)
   - i18n.js の import を全言語分そろえる
   - 繁体字(zh-TW / zh-HK 等)と簡体字(zh)を取り違えないように

2. アプリ名(plist)を 50 ロケールに拡張
   - locales/plist/<lang>.json に CFBundleDisplayName だけを持つ
   - 対象は 50 ロケール:
     ja, en-US, en-AU, en-CA, en-GB, zh-Hans, zh-Hant, ko, es-ES, es-MX,
     fr-FR, fr-CA, de-DE, it, pt-BR, pt-PT, nl-NL, ru, uk, tr, ar-SA, he,
     hi, id, ms, th, vi, da, sv, no, fi, pl, cs, sk, hu, ro, hr, el, ca,
     bn-BD, gu-IN, kn-IN, ml-IN, mr-IN, or-IN, pa-IN, ta-IN, te-IN, ur-PK,
     sl-SI

3. app.json の言語設定を拡張
   - ios.infoPlist.CFBundleLocalizations に上記ロケールを列挙
   - locales セクションに各 plist/<lang>.json へのパスを列挙

【ルール・注意】
- 翻訳はすべて ja.json / plist/ja.json を正として訳す
- 変数埋め込み %{変数名} は各言語でもそのまま残す(訳して壊さない)
- 未対応言語は英語にフォールバックする方針は維持
- アラビア語・ヘブライ語など RTL 言語も文字列は用意する
  (レイアウトの RTL 対応が必要な箇所があれば指摘してください)

作り終えたら、キーの数が全言語で一致しているか(欠けや余りがないか)を
確認した結果を報告してください。