Globalization: i18nとアプリの多言語対応とは

著者: IT Sectr 公開日: 2026-02-26 読了時間: 8 分

Globalization(グローバリゼーション、国際化、i18n)— ソースコードを変更せずにモバイルアプリケーションを複数の言語や地域フォーマットで動作させるための準備プロセスです。コードからの文字列リソースの抽出、日付・数値・通貨の異なるフォーマットのサポート、テキスト方向(LTR/RTL)の考慮、異なる言語へのレイアウト適応が含まれます。iOSではNSLocalizedStringとLocalizable.stringsが使用され、Androidではvalues-{lang}ディレクトリ内のstrings.xmlが使用されます。詳細は、Appleの国際化ドキュメントをご覧ください。

重要なポイント

  • Globalization (i18n) — アプリケーションコードを複数の言語や地域に対応させる準備
  • NSLocalizedString — Localizable.stringsから翻訳済み文字列を取得するSwiftマクロ
  • strings.xml — 各言語のリソース文字列を保存するAndroidのXMLファイル
  • RTL — 右から左に記述する言語(アラビア語、ヘブライ語、ウルドゥー語)のサポート
  • フォーマット — 日付、数値、通貨はLocale依存のAPIを通じてフォーマットする必要がある

Globalization (i18n) とは何か、なぜ必要なのか?

Globalization(略称i18n — 「i」と「n」の間に18文字)— あらゆる言語と地域で動作するためのアプリケーションのアーキテクチャレベルの準備です。i18nの重要なルール:ソースコード内にハードコードされたテキスト文字列があってはなりません。代わりに、文字列はリソースファイルに抽出され、コードはキーを通じてそれらにアクセスします。新しい言語を追加する際には、翻訳ファイルを追加するだけで済みます — コードは変更されません。これが、文字列自体を翻訳するローカリゼーション(l10n)との違いです。

ビジネス上の根拠 — グローバリゼーションは市場を拡大します。Common Sense Advisory(2023)によると、70%以上のユーザーが母国語のアプリでの購入を好みます。10言語へのローカリゼーションは潜在的なオーディエンスを80%増加させます。i18nがない場合、新しい言語への拡張ごとにコードの変更が必要となり、市場投入が遅れ、コストが5~10倍に増加します。適切なi18nアーキテクチャにより、最小限のコストで40以上の言語をサポートできます。

i18nの構成要素:文字列の外部化、複数形対応(1/2/5+)、日付と数値のフォーマット(DateFormatter/SimpleDateFormat)、RTL言語のサポート(Right-to-Left)、ロケール固有のソート(Collator)、地域記号(桁区切り、小数点)。IT Sectrでは、i18nを後付けではなくアーキテクチャ段階で組み込みます — これにより、その後のローカリゼーションで最大60%の時間を節約できます。

iOSでの国際化: NSLocalizedStringとXLIFF

NSLocalizedString — 翻訳を扱うための主要なSwiftマクロです。形式:NSLocalizedString("key", comment: "翻訳者向けの説明")。このマクロは、デバイスの現在のロケール(NSLocale.preferredLanguages)に基づいてLocalizable.stringsから自動的に文字列を置き換えます。キーに対応する翻訳が見つからない場合は、キー自体または開発言語(通常はen)の値が返されます。Appleは、英語の文字列をキーとして使用するのではなく、意味のあるキーを使用することを推奨しています。

swift
// Localizable.strings (en)
// "welcome_title" = "Welcome!";
// Localizable.strings (ru)
// "welcome_title" = "ようこそ!";

// Swiftコード — 全言語で統一
titleLabel.text = NSLocalizedString(
    "welcome_title",
    comment: "ウェルカム画面のタイトル"
)

// Localizable.stringsdictによる複数形
// 
// <dict>
//     <key>items_count</key>
//     <dict>
//         <key>NSStringLocalizedFormatKey</key>
//         <string>%#@items@</string>
//         <key>items</key>
//         <dict>
//             <key>one</key>
//             <string>%d個の商品</string>
//             <key>few</key>
//             <string>%d個の商品</string>
//             <key>many</key>
//             <string>%d個の商品</string>
//         </dict>
//     </dict>
// </dict>

// 複数形の使用
let items = 5
let label = String.localizedStringWithFormat(
    NSLocalizedString("items_count", comment: ""), items
)

XLIFF — 開発者と翻訳者の間での翻訳交換フォーマットです。Xcodeは翻訳用のすべての文字列を含むXLIFFファイルをエクスポートします(Editor → Export for Localization)。翻訳者はCATツール(Trados、memoQ、Smartcat)でXLIFFを処理します。翻訳後、XLIFFはXcodeにインポートされます(Editor → Import Localizations)。XLIFFは自動的にすべての.lprojディレクトリを更新します。これは本番環境におけるiOSアプリのローカリゼーションの標準的なワークフローです。

SwiftUIとi18n

SwiftUIはTextイニシャライザを通じてNSLocalizedStringと連携します。SwiftUIのテキストは自動的に国際化されます:Text("welcome_title")はNSLocalizedStringと同じようにLocalizable.stringsで翻訳を検索します。複数形の場合は、Text("%d items", count: items)を使用します。SwiftUIはText(date, style: .date)を通じて日付フォーマットをサポートし、自動的にLocale.currentを使用します。Appleは新しいプロジェクトにSwiftUIを推奨しています。国際化がより透過的だからです。

Androidでの国際化: strings.xmlとRTL

Android i18nはリソースシステムに基づいています。デフォルト言語(通常は英語)の文字列はres/values/strings.xmlに配置されます。各言語に対して個別のディレクトリが作成されます:res/values-ru/strings.xml(ロシア語)、res/values-de/strings.xml(ドイツ語)、res/values-fr/strings.xml(フランス語)。Androidはデバイスのシステム言語(Locale.getDefault())に基づいて自動的に文字列を選択します。正確なロケールが見つからない場合は、ベース(values/strings.xml)が使用されます。

kotlin
// res/values/strings.xml(英語、デフォルト)
<resources>
    <string name="welcome_title">Welcome!</string>
    <string name="items_count">%d item(s)</string>
</resources>

// res/values-ru/strings.xml(ロシア語)
<resources>
    <string name="welcome_title">ようこそ!</string>
    <plurals name="items_count">
        <item quantity="one">%d個の商品</item>
        <item quantity="few">%d %d個の商品</item>
        <item quantity="many">%d %d個の商品</item>
    </plurals>
</resources>

// Kotlinコード
textView.text = getString(R.string.welcome_title)

// 複数形
val items = 5
textView.text = resources.getQuantityString(
    R.plurals.items_count, items, items
)

// コード内のRTLサポート
textView.textDirection = View.TEXT_DIRECTION_LOCALE
// Manifest: supportsRtl="true"

RTL(Right-to-Left) — テキストを右から左に読む言語(アラビア語、ヘブライ語、ウルドゥー語、ペルシア語)のサポートです。Androidはandroid:layoutDirectionとandroid:textDirection属性を通じてRTLをサポートします。マニフェストでandroid:supportsRtl="true"を指定すると、Androidが自動的にレイアウトをミラーリングします。NavDrawer、戻る/進むアイコン、テキストの配置は両方向で機能する必要があります。コードでは、LEFT/RIGHTの代わりにView.LAYOUT_DIRECTION_LOCALEとGravity.START/ENDを使用します。

ローカライズされたリソース

Android Resource Qualifiersを使用すると、文字列だけでなく、画像(res/drawable-ru/)、レイアウト(res/layout-ru/)、アニメーション、色もローカライズできます。アラビア語とヘブライ語には、要素をミラーリングした個別のレイアウトが必要です — res/layout-ar/(アラビア語)を使用します。Androidは地域バリアントもサポートしています:values-rUS、values-rGB、values-de-DE。修飾子は組み合わせることができます:values-ldrtl-ru — RTLディスプレイ用のロシア語。

地域フォーマット: iOSとAndroidの日付、数値、通貨

日付と時刻 — i18nの重要な側面の一つです。地域によって異なるフォーマットが使用されます:ロシア — DD.MM.YYYY、米国 — MM/DD/YYYY、日本 — YYYY.MM.DD。固定フォーマット(yyyy-MM-dd)をユーザーに表示するために使用するのは誤りです。iOSではLocale(identifier: locale)を指定したDateFormatterを使用し、AndroidではDateFormat.getDateInstance(DateFormat.SHORT, locale)を使用します。音声アシスタントやAI検索の場合は、内部的にISO 8601形式で日付を扱う必要があります。

数値と通貨 — 地域によって異なる区切り記号が使用されます:1,234.56(米国)vs 1.234,56(ロシア)、1 234,56(フランス)。iOS:.locale = localeを指定したNumberFormatter。Android:DecimalFormatSymbols(locale)を指定したDecimalFormat。通貨の場合:¥1,234(日本)vs $1,234.56(米国)vs 1 234,56 ₽(ロシア)。通貨と数値を手動で連結しないでください — NumberFormatter.currencyCodeと.currencySymbolを使用します。

地域日付数値通貨
ロシア31.12.20241 234,561 234,56 ₽
米国12/31/20241,234.56$1,234.56
ドイツ31.12.20241.234,561.234,56 €
日本2024/12/311,234¥1,234
サウジアラビア31/12/20241,234.561,234.56 SAR

ソート(照合) — アルファベット順は言語によって異なります。スペイン語では「ch」は「c」の後に来ます。スウェーデン語では「ä」はアルファベットの最後に来ます。ドイツ語では「ß」は「ss」としてソートされます。iOS:LocalizedComparison(String.localizedCompare)。Android:Collator.getInstance(locale)。ユーザーに表示する文字列にcompareTo()を使用しないでください — Unicode Code Point順を使用するため、地域のルールを考慮しません。

モバイルアプリ国際化のベストプラクティス

アーキテクチャの原則 — 最初のコミットからi18nを開始します。コード内のすべての文字列は、i18nが設定されるまで存在しないラッパー関数(tr("key"))を通る必要があります — これにより、開発者は即座に文字列を外部化せざるを得なくなります。英語の文字列をキーとして使用しないでください — 英語の表現が変更された場合、すべての翻訳を更新する必要があります。意味のあるキーを使用してください:「profile.title」、「settings.language.label」。

擬似ローカリゼーション — 実際の翻訳前のi18nテスト手法です。各ラテン文字をダイアクリティカルマーク付き文字(á、é、ñ、ü)に置き換えてエンコーディングを確認し、[XXX]プレフィックスを追加して文字列の切り捨てを確認します。Xcode:実行スキーマ — 「Double-Length Pseudolanguage」疑似言語。Android:開発者オプション — RTLレイアウト方向を強制、システムフォントスケール200%まで。擬似ローカリゼーションは、翻訳者を介さずにi18nの問題の80%を発見します。

IT Sectr i18nチェックリスト — リリース前に以下を確認します:(1)コード内にハードコードされた文字列がないこと(例外:ログ)、(2)複数形がすべての言語で正しく機能すること、(3)日付/数値がLocale APIを通じてフォーマットされていること、(4)RTL言語でレイアウトが正しく表示されること、(5)最大スケーリング時に文字列が切り捨てられないこと、(6)擬似ローカリゼーションでエラーが検出されなかったこと、(7)ストアで宣言されたすべての言語に完全な翻訳セットがあること。

よくある質問

i18nとl10nの違いは何ですか?

i18n(国際化)— コードの準備:文字列の外部化、RTLサポート、フォーマット。開発者が一度行います。l10n(ローカリゼーション)— 特定の言語への文字列の翻訳。翻訳者が各ロケールに対して複数回行います。i18nはアーキテクチャ、l10nはコンテンツです。i18nなしでは、ローカリゼーションは原則的に不可能です。

SwiftでNSLocalizedStringはどのように機能しますか?

NSLocalizedString — デバイスの現在のロケールのLocalizable.stringsでキーによって値を検索するマクロです。翻訳が見つかった場合はそれを返し、見つからなかった場合はキーを返します。形式:NSLocalizedString("key", comment: "説明")。パラメータを使用したフォーマットには、String.localizedStringWithFormat()を使用します。

Androidのstrings.xmlはどのように構成されていますか?

strings.xml — res/values/{lang}/ディレクトリ内の翻訳ファイルです。ベースバージョンはvalues/strings.xmlに、翻訳はvalues-ru/strings.xmlにあります。コードはgetString(R.string.key)を通じてアクセスします。Androidはシステム言語に基づいて自動的に適切なファイルを選択します。複数形には、zero/one/few/many/other修飾子を指定した<plurals>リソースが使用されます。

i18nの文脈でのRTLとは何ですか?

RTL(Right-to-Left)— アラビア語、ヘブライ語、ウルドゥー語、ペルシア語の書記方向です。Android:マニフェストでsupportsRtl="true"、android:layoutDirection、Gravity.START/END。iOS:強制RTLにはUISemanticContentAttribute.forceLeftToRight。レイアウトはミラーリングされる必要があります:メニューは右側、テキストは右から左、ナビゲーションアイコンは反転。

公開に必須の言語はどれですか?

グローバル公開の最小セット:英語、スペイン語、フランス語、ドイツ語、日本語、中国語、韓国語、ポルトガル語、ロシア語、イタリア語。App Storeでは最低限英語のローカリゼーションが必要です。追加のロケールごとに潜在的なオーディエンスが拡大します。ローカル市場の場合は、1~2言語で十分です。

まとめ

  • Globalization (i18n) — 複数の言語と地域に対応するためのアプリケーションのアーキテクチャレベルの準備
  • NSLocalizedString — Localizable.stringsとXLIFFエクスポートによる文字列翻訳のSwiftマクロ
  • strings.xml — values-{lang}ディレクトリに翻訳を持つAndroidリソース
  • RTL — アラビア語、ヘブライ語、ウルドゥー語、ペルシア語の必須サポート
  • フォーマット — 日付と数値はLocale APIを通じて厳密にフォーマットされ、手動では行われない
  • 複数形 — iOS:stringsdict、Android:6つの数量形を持つ<plurals>
  • 擬似ローカリゼーション — 翻訳前のi18nテスト手法(問題の80%を発見)

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください