Back to Guides
ガイド

10件のよくある i18n のミスと回避方法

開発者が犯す最もよくある i18n のミスとその対処法を学びましょう。これらのベストプラクティスでアプリのローカリゼーション品質を向上させましょう。

5 最短読了時間
著者: shipglobal.dev
#i18n#developer#user experience#best practices#internationalization#common mistakes

Internationalisierung(i18n)は簡単そうに見えますが、ドイツ語話者のユーザーがボタンが途切れて表示され、日本語話者のユーザーが意味が崩れた文の断片を受け取り、アラビア語話者のユーザーが完全に崩れたレイアウトを目にすることが分かったとき、それは別物になります。これは端数のケースではありません。 lokalisierung に初めて取り組む多くの開発チームが陥りがちな一般的な誤りの予測可能な結果です。 このガイドでは、最も頻繁に起こる i18n の 10 の誤りを取り上げ、それらがなぜ発生するのかを正確に説明し、それぞれを順を追ってどのように修正するかを示します。 新しいアプリを作る場合も、既存のものを後付けで改善する場合も、この落とし穴を避けることで、数週間のデバッグを節約し、世界中のユーザーに洗練された体験を提供します。

エラー #1: ハードコーディングされた文字列

i18n の最も基本的なエラーは、ハードコーディングされた文字列です。これは、開発者が最初に機能を動かすことに集中し、「後で整理する」と計画するために起こります。しかし、後でというのは決して来ず、突然何千もの文字列が何百ものファイルに分散してしまいます。

['最初の UI コード行を記述する前に i18n フレームワークを設定する', 'テンプレートとコンポーネント内の生の文字列を検出するリンター・プラグインを使用する', '翻訳キーを説明的に保ち、機能やページごとに整理する']

最初の UI コード行を書く前に i18n フレームワークを設定してください。

テンプレートとコンポーネントでハードコーディングされた文字列を検出するリントプラグインを使用してください。

翻訳キーは機能やページごとに説明的で整理されたままにしてください。

典型的なシナリオ

1

開発者がJSX内にボタンのラベルを直接書きます: <button>Submit Order</button>.

2

アプリは英語で提供され、問題なく動作します。6か月後、企業はドイツへ拡張します。

3

ローカライゼーションチームは2,000件以上のハードコードされた文字列を発見します。後付けの作業には3週間かかり、47個のバグを引き起こします。

なぜこれは問題なのか

成熟したコードベースでは、ハードコーディングされた文字列は数千にも及ぶことがあります。後から抽出するには、すべてのファイルに触れ、すべてのコンポーネントを再度テストし、あらゆる場所でリグレッションをリスクにします。

ハードコードされた文字列は、ソースコード、テンプレート、またはコンポーネントに直接埋め込まれています。コード自体を変更せずに、実行時に抽出、翻訳、交換することはできません。

英語以外のローカルにいるユーザーは、翻訳されていないUI要素が翻訳された内容と混在して見え、混乱したり不作法な印象を与えます。

対処方法

すべてのユーザーに表示される文字列を初めからリソースファイルに外部化します。

1

最初のコンポーネントを記述する前に i18n フレームワークを設定します(例: next-intl、react-i18next、vue-i18n)。

2

リソースファイル構造を作成(例: messages/de.json)し、t('checkout.submitButton') のような翻訳キーを通じてすべての文字列を参照します。

3

UI コンポーネント内の生の文字列を検出するリンティング規則やプリコミットフックを追加します。

エラー #10: すべてを文字通り翻訳する

すべてのコンテンツを翻訳するべきではありません。ブランド名、法人名、技術用語、特定の製品名は元の言語のままにしておくべきです。過度な翻訳は法的問題、ブランドの不整合、ユーザーの混乱を招く可能性があります。

["『翻訳しない』用語集を維持し、すべての翻訳者と共有してください", 'ブランド名と法的用語には、'ロックされた'セグメントや別のネームスペースを使用してください', 'あいまいな文字列には常に文脈ノートを提供して、誤訳を防いでください']

『翻訳不可』用語集を管理し、すべての翻訳者と共有してください

ブランド用語や法的用語には、ロックされたセグメントまたは別々のネームスペースを使用してください

曖昧な文字列には常にコンテキストノートを提供して誤訳を防いでください

典型的なシナリオ

1

翻訳ファイルには企業名『CloudForge Inc.』と技術用語『OAuth 2.0 Token』が通常の翻訳可能な文字列として含まれています。

2

スペイン語の翻訳者は「CloudForge」を「ForjaNube」に、「OAuth 2.0 Token」を「ficha OAuth 2.0」に翻訳してしまう。

3

結果: ユーザーは企業を実名で見つけられず、スペイン語のドキュメンテーションを読む開発者は、未知の翻訳済み用語に混乱します。

なぜそれが問題なのか

法的文書のブランド名の誤訳が1つあるだけで契約が無効になることがあります。過度な翻訳を修正するには、各言語の各文字列を検討する必要があり、数週間の作業になります。

文脈なしで全ての文字列を翻訳に送ると、翻訳者がブランド名(『Apple』→『Apfel』)、法的用語(『GmbH』→『LLC』)や英語のままであるべき技術的表記を誤って翻訳してしまう可能性があります。

ユーザーは、馴染みのあるブランド名で製品を見つけられず、法的文書は誤った会社を参照し、技術文書は 'API Endpoint' のような用語が翻訳されると理解不能になります。

これを解決する方法

翻訳できない内容を明確にマークし、翻訳者に文脈メモを提供してください。

1

変更せずそのままにしておくべきすべてのブランド名、製品名、法人名、専門用語を列挙した「翻訳不可」用語集を作成してください。

2

翻訳不可の内容には、別のネームスペースや特別なキーを使用してください。多くの i18n ツールは、翻訳者が編集できない「ロックされた」セグメントをサポートしています。

3

翻訳ファイルに文脈を説明する翻訳者向けのコメント/説明を追加してください: 「これはブランド名です — 翻訳しないでください」または「専門用語 — 英語のままにする」。

エラー #2: 文字列の連結

断片から文をつなぐと英語では論理的に見えることが多いですが、他の言語では機能しません。語順、文法、文の構造は言語ごとに大きく異なり、結合された文字列は翻訳できません。

['翻訳されたフラグメントを連結して文を作らない', '明確さのために位置指定子('{name}')の代わりに名前付きプレースホルダーを使用('{name}')、位置指定子({0})を避ける', '翻訳者にコンテキストコメントを提供し、各プレースホルダーの内容を説明する']

翻訳された断片を連結して文を作らないでください。

明確さのために名前付きプレースホルダー('{name}')を使用('{name}')、位置指定子({0})を避ける

翻訳者のために、各プレースホルダーが何を含むかを説明する文脈コメントを提供してください。

典型的なシナリオ

1

開発者は書く: 'You have ' + count + ' items in your ' + cartType + ' cart' — 英語では完璧に機能します。

2

ドイツ語の翻訳者は3つの別々の断片を受け取り、語順を変える必要があるため、文法的に正しい文を作成できません。

3

結果: ドイツのユーザーは 'Sie haben 5 Artikel in Ihrem Warenkorb Standard' を見てしまい、ぎこちなく専門的でない。

なぜこれが問題なのか

連結された文字列はすべて時限爆弾です。20言語で50の連結文字列があると、手動で修正する必要のある1,000の潜在的な文法エラーが発生します。

'Willkommen ' + userName + ', du hast ' + count + ' neue Nachrichten' のような文字列の連結は、特定の語順を前提とします。翻訳者は文脈のない断片を受け取り、順序を変更できません。

ユーザーは文法的に誤った文を見ます。ドイツ語では動詞が文の末尾に来ることが多いです。アラビア語では全体の構造が逆転します。結果は意味をなさないように読めます。

これを解決する方法

名前付きプレースホルダを含むパラメータ化されたメッセージを使用して、翻訳者が文全体の順序を再配置できるようにします。

1

連結を避け、プレースホルダー付きの単一メッセージキーに置き換え: 'cart.summary': 'あなたの'{cartType}'カートには{count}アイテムがあります。'

2

変数を翻訳関数のパラメータとして渡す: t('cart.summary', { count: 5, cartType: 'Premium' }).

3

翻訳者は自由に並べ替え可能: 'あなたの'{cartType}'カートには{count}アイテムがあります' — 正しいドイツ語。

エラー #3: 複数形の処理を無視する

英語には二つの複数形があります。単数と複数形。開発者はしばしばすべての言語が同じように機能すると考えています。そうではありません。ポーランド語には4つの形があり、アラビア語には6つ、そしてフランス語のような言語でさえ英語とは異なるゼロ形を扱います。

['数を扱う内容には常に ICU MessageFormat または同等のライブラリを使用してください', '独自の複数形ロジックは決して書かないでください — CLDR の規則を信頼してください', '0、1、2、5、21、100 などの値で複数形をテストして、すべてのカテゴリを網羅します']

可算コンテンツには常に ICU MessageFormat または同等のライブラリを使用します

独自の複数形ロジックを書かないでください — CLDR の規則を信頼してください

0、1、2、5、21、100 などの値を使って複数形をテストし、すべてのカテゴリをカバーします

典型的なシナリオ

1

開発者は書く: count + (count === 1 ? 'Datei' : 'Dateien') — ドイツ語を正しく扱います。

2

ポーランド語の翻訳者は4つの形を必要とします: 1 plik, 2-4 pliki, 5-21 plików, 22-24 pliki. 単純な三項演算子では表現できません。

3

結果: ポーランド語のユーザーは '5 pliki'(誤った形)を見て、正しくは '5 plików' となる。アプリは壊れているように見える。

なぜこれは問題なのか

アプリ内の数えられる名詞はすべて複数形の扱いが必要です。50個のような文字列と20言語では、1,000個の複数形ルールがあり、それらを手動で管理するのは不可能です。

単純な if/else チェック (count === 1 ? 'Datei' : 'Dateien') はドイツ語と英語だけを扱います。CLDR は最大6つの複数形カテゴリを定義します:zero, one, two, few, many, other。各言語は異なるサブセットを使用します。

ユーザーは '1 Nachrichten' のような文法的に誤ったテキストや、完全に誤った複数形を目にします。フォーマルな文脈では信頼性が損なわれます。

これを解決する方法

ICU MessageFormatを使用すると、すべてのCLDR複数形ルールをデフォルトでサポートします。

1

ICU構文でメッセージを定義します: 'fileCount': '{count, plural, one {# Datei} other {# Dateien}}'.

2

翻訳者は各言語に必要な複数形をすべて提供します。ポーランド語: '{count, plural, one {# plik} few {# pliki} many {# plików} other {# pliku}}'.

3

アクティブなロケールの CLDR ルールに基づいて、実行時に自動的に正しい形を選択します。

エラー #4: 固定されたUI要素の幅

デザイナーは英語でピクセル・パーフェクトのレイアウトを作成し、開発者はそれを固定幅で実装します。しかし、翻訳されたテキストは大幅に長くなることも短くなることもあります。ドイツ語のテキストは英語より約30%長く、中国語のテキストは約50%短くなることがあります。

['翻訳可能なテキストを含む要素には決して固定ピクセル幅を使用しない', 'ベースラインとしてテキストを40%拡張することを計画 — いくつかの言語はさらに拡張します', 'レイアウトには CSS Flexbox や Grid を使用して、可変のコンテンツ長さに対応します']

翻訳可能なテキストを含む要素には、固定ピクセル幅を決して使用しないでください

ベースラインとしてテキストを40%拡張することを計画します — 一部の言語はさらに拡張します

可変長のコンテンツに適応するレイアウトには CSS Flexbox または Grid を使用してください

典型的なシナリオ

1

デザイナーは5つのボタンからなるナビゲーションバーを作成し、それぞれ幅を正確に100pxに設定します。英語版では見栄えが良いです。

2

ドイツ語の翻訳: 'Settings' は 'Einstellungen' (13 対 8 文字)、'Submit' は 'Absenden' (8 対 6) となる。ナビバーがはみ出します。

3

結果: モバイルデバイスではボタンが互いに重ね合わせられるか、テキストが切れてしまい、ドイツ語話者にとってのナビゲーションが使い物にならなくなります。

なぜこれは問題なのか

固定幅の各要素は破損点になる可能性があります。典型的なアプリにはテキストの長さに耐える何百ものボタン、ラベル、カードがあります。

固定幅のコンテナ(width: 120px)と固定サイズのボタンは、テキストが長くなると切れたりはみ出したりします。CSS overflow: hidden はコンテンツを黙って隠し、overflow: visible はレイアウトを崩します。

ユーザーは '設定' などの途中で切れたラベルを見たり、隣接する要素を重ねるボタンを見たりします。重要な操作は読みづらくなったり、クリックできなくなることがあります。

対処方法

すべてのロケールのコンテンツの長さに合わせて柔軟なレイアウトを設計・実装してください。

1

固定幅を min-width、max-width、Flex レイアウトに置き換えます。CSS Grid または Flexbox を使ってスペースを動的に分配してください。

2

テキストコンテナを改 行可能に設定します: overflow-wrap: break-word を使用し、翻訳可能なコンテンツには white-space: nowrap を避けてください。

3

すべての文字列を40%長くする疑似ローカリゼーションでUIをテストし、Worst Caseをシミュレートします — 翻訳者に文字列を送る前に。

エラー #5: 日付と数字のフォーマット

データと数字は普遍的に見えるが、01/02/2025 は米国では 1月2日、欧州では 2月1日を意味します。カンマとピリオドは数値の意味を変えます:1,000.50(USA)対 1.000,50(ドイツ)。これを間違えると混乱、データの誤り、信頼喪失につながります。

['データや数字を文字列テンプレートで手動でフォーマットしないでください — いつでも Intl-API を使ってください', 'すべてのデータを ISO 8601 に内部保存し、通貨は内部的には最小単位(セン)で保存', '異なる小数点区切り、日付の順序、カレンダーシステムを持つロケールでテストします']

データや数字を文字列テンプレートで手動でフォーマットしないでください — いつも Intl-API を使用してください

すべてのデータを ISO 8601 形式で、通貨は内部的に最小単位(セント)で保存してください

異なる小数点区切り、日付順序、カレンダー体系を使用するロケールでテストしてください

典型的なシナリオ

1

開発者は日付を MM/DD/YYYY、価格を $1,234.50 の形式でフォーマットします — 米国のユーザーにとって正しいです。

2

ドイツのユーザーは日付を 03/04/2025 と見て、3月4日として解釈します(DD/MM/YYYY の慣例)。価格 $1,234.50 は 1.234,50 と表示されるべきです。

3

結果: ユーザーは誤った日付のフライトを予約し、料金表示の形式を疑問視します。ドイツ市場ではサポートチケットが15%増加します。

なぜこれは問題なのか

日付と数値のフォーマットはアプリ内のあらゆるデータ表示に影響します。表、グラフ、フォーム、請求書、レポート。グローバルな修正で何百ものインスタンスをカバーします。

toLocaleDateString('en-US') のようにハードコードされたフォーマット文字列や、テンプレートリテラルを用いた手動形式設定は、利用者の実際のロケールを無視します。正しいロケールであっても、暦系が異なると問題が生じます(グレゴリオ暦 vs ヒジュリ暦)。

ユーザーはデータを誤って読み取り、誤った形式でデータを入力します。03/04/2025 を見るヨーロッパのユーザーは、それを3月4日ではなく4月3日として解釈する可能性があり、予定の取りこぼしや予約の間違いにつながります。

これを解決する方法

組み込みの Intl-APIまたはロケール対応のフォーマットライブラリを、すべての日付、時刻、数字、通貨に対して使用してください。

1

データの日付には Intl.DateTimeFormat(locale) を、価格には Intl.NumberFormat(locale, { style: 'currency', currency }) を使用して、手動のフォーマットを置換してください。

2

内部的には ISO 8601 形式 (YYYY-MM-DD) でデータを保存し、表示時にのみユーザーのロケールでフォーマットしてください。

3

重要な日付/数値表示を、少なくとも5つの異なるロケール(en-US、de-DE、ja-JP、ar-SA、zh-CN)でテストし、最も重要な形式のバリエーションをカバーします。

エラー #6: RTL言語を忘れる

説明: 右から左へ書かれる RTL 言語(アラビア語、ヘブライ語、ペルシャ語など)は5億人を超える人々に使われています。しかし、ほとんどのアプリは左から右(LTR)レイアウトのみで設計されています。RTL サポートはテキストをひっくり返すことだけを意味せず、UI 全体を鏡像化する必要があります。

['初期から論理的な CSS プロパティのみを使用します(inline-start/end、block-start/end)', "スプリントレビューごとに HTML 要素で dir='rtl' を使ってアプリをテストします", 'ナビゲーション、アイコン、フォーム、進捗表示の RTL テストチェックリストを作成します']

最初の日から論理的な CSS プロパティ(inline-start/end、block-start/end)のみを使用してください

各スプリントレビューで HTML 要素の dir='rtl' でアプリをテストしてください

ナビゲーション、アイコン、フォーム、進捗表示の RTL テストチェックリストを作成してください

一般的なシナリオ

1

開発者はアプリ全体で margin-left: 16px および text-align: left を使用しています — 標準的な LTR の実践です。

2

アプリはサウジアラビアで起動します。戻るボタンは前方を指し、サイドバーは間違った側に表示され、数値データは整列していません。

3

結果: アラビア語ユーザーはアプリを30秒で離脱します。問題を解決するために、チームは4週間の緊急CSSリファクタリングを必要とします。

なぜこれは問題なのか

RTL サポートはアプリの各コンポーネントに及びます。後から RTL を導入するには、通常、すべての CSS ルールの約30〜50%を書き直す必要があり、すべてのアイコンとレイアウトを確認する必要があります。

CSS のプロパティ(margin-left、padding-right、text-align: left、float: left)は方向をハードコードします。方向を示すアイコン(矢印、進捗表示)は誤った方向を指します。 border-radius の値さえも鏡像対応にする必要があります。

アラビア語話者は、ナビゲーションが間違った角に表示され、進行バーが逆に動き、UI 要素と衝突するテキストが表示されます。アプリは違和感があり、使い物になりません。

これを解決する方法

ロジカルな CSS プロパティを使用し、初期から RTL レイアウトでテストしてください。

1

すべての物理的な CSS プロパティを論理的な同等物に置き換えます: margin-left → margin-inline-start, padding-right → padding-inline-end, text-align: left → text-align: start.

2

アクティブなロケールに基づいて HTML ルート要素に dir 属性を設定します。RTL 固有のオーバーライドには CSS の :dir(rtl) 擬似クラスを使用してください。

3

方向性を示すすべてのアイコンを確認します。方向依存のアイコンを鏡像版に置き換えるか、RTL コンテキストには CSS transform: scaleX(-1) を使用してください。

エラー #7: テキスト入りの画像

テキストを画像に埋め込むことは、ヒーローバナー、ボタン、インフォグラフィック、スクリーンショットなどのローカライズの悪夢です。テキストを含む各画像は言語ごとに再作成され、デザインコストが増大し、リリースが遅れます。

['翻訳可能なテキストを直接ラスタ画像(PNG、JPG)に埋め込まないでください', 'ヒーロー バナーと CTA の背景画像には CSS のテキストオーバーレイを使用してください', 'App Store のリスティングやマーケティングページのスクリーンショット生成を自動化してください']

翻訳可能なテキストをラスタ画像(PNG、JPG)に直接埋め込まないでください

ヒーロー表示とCTAの背景画像には CSS テキストオーバーレイを使用してください

App Storeのリストとマーケティングページのスクリーンショット生成を自動化する

一般的なシナリオ

1

デザイナーが 'Start Your Free Trial' のテキストを画像自体に直接埋め込んだプロモーション用バナーを作成します。

2

ローカライズチームはすべてのUI文字列を翻訳しますが、ドイツ語のページのバナーにはまだ英語のテキストが表示されています。

3

結果: ドイツ語のランディングページには混乱を招く英語のバナーがあります。15言語分のローカライズされたバナーを作成するには3日間のデザイン作業が必要で、ローンチを遅らせます。

なぜこれは問題なのか

典型的なマーケティングページにはテキストを含む画像が5〜10枚あります。15言語だと75〜150の画像バリエーションを作成・維持・デザイン変更ごとに更新する必要があります。

画像に埋め込まれたテキスト(PNG、JPG、テキストが埋め込まれた SVG)は翻訳ツールで抽出できません。各ローカライズ版は、デザイナーがソースファイルを手動で編集し、エクスポートしてアップロードする必要があります。

ユーザーは、外国語のテキストが入った画像を表示され、またはさらに悪いことに、翻訳済みのUIと未翻訳の画像が混在しているのを目にします。これにより一貫性が欠け、ブランドへの信頼が損なわれます。

これを解決するには

テキストをCSSオーバーレイ、翻訳可能なテキスト要素を参照するSVG、または動的な画像生成を使用して画像から分離します。

1

翻訳可能なテキストを背景画像の上に置くためにCSSを使用します:テキストレイヤーを画像コンテナの上に絶対配置します。

2

インフォグラフィックやダイアグラムには、翻訳キーを参照する <text> 要素を持つ SVG を使用し、未加工の文字列を埋め込まないでください。

3

マーケティング資料のアプリスクリーンショットには、Fastlane(モバイル)やPlaywright(Web)などのツールを使って各ロケールのスクリーンショットを取得するように自動化します。

エラー#8:欠落している翻訳が処理されていない

開発中は翻訳は常に不完全です。新機能は翻訳者が翻訳できる量を超えて文字列を追加します。適切なフォールバック処理がなければ、翻訳が欠落するとクラッシュ、UI 要素の空白、または利用者に表示される未翻訳のキーが発生します。

['i18n設定に少なくとも1つのフォールバック言語を常に設定します', '欠落している翻訳キーを監視システムに記録して追跡します', 'ロケールを公開する前に最小翻訳カバレッジ率を設定します']

i18n 設定で常に最低1つのフォールバック言語を設定してください

不足している翻訳キーを監視システムにログとして記録して追跡してください

ロケールを公開する前に最低限の翻訳カバレッジを設定してください

典型的なシナリオ

1

開発者は 'Premium Features' の新しいセクションを 15 個の新しい翻訳キーとともに追加します。英語版がすぐに提供されます。

2

フランス語の翻訳はまだ完成していません。フランス語のページには未加工のキーが表示されます: 'premium.feature1.title'、 'premium.feature1.description'。

3

結果: フランス語の利用者は開発者側のキー名が並ぶ壊れたページを見ています。サポートチームには数十件のバグ報告が寄せられます。

なぜ問題なのか

アプリが大きくなるほど、英語の文字列と他の言語の翻訳の間のギャップは拡大します。100言語、2,000の文字列を持つアプリは、いつでも10,000を超える翻訳が欠落している可能性があります。

フォールバック処理がないと、欠落した翻訳キーは undefined、null、または生のキー文字列を返します(例: 'checkout.confirmButton')。テンプレートエンジンはエラーを出すことがあり、ページがクラッシュしたり、何もレンダリングされなかったりします。

ユーザーは壊れたUIを見ます:空のボタン、欠落したラベル、または 'nav.settings.title' のような意味のわからない文字列が表示され、実際のテキストの代わりになります。混乱を招き、プロフェッショナルでなくなります。

解決策

フォールバックチェーンを設定し、すべてのロケールにわたる翻訳のカバレッジを監視します。

1

i18n 設定にフォールバック言語チェーンを設定します。欠落しているフランス語(fr)キーは自動的に英語(en)にフォールバックします。

2

未翻訳のキーを監視システム(例:Sentry、Datadog)にログする Missing-Key ハンドラを追加し、ユーザー体験を崩さずに対応します。

3

ローカルごとの翻訳カバレッジを追跡し、カバレッジが閾値(例: 95%)を下回った場合にリリースをブロックする翻訳カバレッジダッシュボードを作成します。

エラー #9: 文字コードの問題

文字コードの問題はローカリゼーションの静かなキラーです。英語と欧州言語では問題ないように見えますが、中国語、日本語、韓国語、アラビア語、絵文字を追加すると、文字化けが表示されます。これらのバグは見つけるのが難しいことで有名です。

['すべての場所でUTF-8エンコーディングを使用します — ソースファイル、データベース、API応答およびHTMLメタタグ', 'MySQL で utf8 のような 3 バイトのサブセットではなく utf8mb4 を使用します', 'CJK、日本語、絵文字を含む実際のコンテンツで、エンコーディングの問題を早期に検出するためにテストします']

すべての場所で UTF-8 エンコーディングを使用してください — ソースファイル、データベース、API 応答、HTML メタタグ

MySQL では utf8mb4 を使用してください(utf8 ではなく)、絵文字を含む全Unicode範囲をサポートします

CJK、中国語・日本語・韓国語の実際のコンテンツ、アラビア語、絵文字でエンコードの問題を早期に検出してください

典型的なシナリオ

1

開発者は、従来の標準である latin1 コレーションを使用した MySQL データベースを設定します。アプリのソースコードは UTF-8 を使用します。

2

日本のユーザーは本名で登録します。データベースは '田中太郎' を損傷したバイトとして保存します。

3

結果: ユーザーのプロフィールには壊れたテキストが表示されます。さらに悪いことに、すべてのCJK名の検索とソートが壊れて、数千人のユーザーに影響します。

なぜそれが問題なのか

エンコードの問題はスタック全体に広がります。誤って設定されたデータベースの照合順序は何百万のデータを損傷させる可能性があり、修復には高価なデータ移行が必要になります。

スタック全体でのエンコードの一貫性がない — ソースファイルはUTF-8、データベースはLatin-1、API応答はWindows-1252 — マルチバイト文字を壊します。設定が1つでも間違っているレイヤーは『日本語』を『????』または『日本èª』に変えてしまいます。

ユーザーは自分の言語が表示されるべき場所に破損したテキスト、疑問符、空のボックスを見る。最悪の場合、フォーム入力がデータベースに永久的に損傷する。

対処方法

アプリケーションスタックの各層でUTF-8エンコードを一貫して強制します。

1

すべてのソースファイルをUTF-8に設定します(エディタと .editorconfigを設定)。HTMLに <meta charset='UTF-8'> を追加し、APIの応答には 'Content-Type: application/json; charset=utf-8' を含めます。

2

データベースを utf8mb4 に設定します(MySQL で utf8 は 3 バイトのサブセットです)。接続の照合順序を utf8mb4_unicode_ci に設定します。

3

ターゲット文字体系をカバーするフォントを選択します:ラテン文字、キリル文字、CJK、アラビア語、デーヴァナーガリー。最適な読み込みのためにシステムフォントスタックまたは言語サブセットを備えた Google Fonts を使用します。

i18n の実装をテストする

文字数拡張テスト

すべての翻訳済み文字列を30〜40%拡大して、ドイツ語・フィンランド語・ギリシャ語のように語彙が豊かな言語で起こるテキストの拡張をシミュレートします。これには固定幅のコンテナ、切り捨てられたラベル、はみ出すボタンが含まれ、翻訳を始める前に適用されます。多くの疑似ローカリゼーションツールはこれを組み込み機能として提供しています。

"送信" → "Ṡééééñðéñ_éxpáñðéð" (40%長い)

疑似ローカリゼーション

疑似ローカリゼーションは各文字をアクセント付きの等価文字に置換します(例: 'a' → 'á' )、および文字列を [!! と !!] のようなマークで囲みます。これにより、ハードコードされた文字列と翻訳システムから来た文字列を即座に識別できます。回帰を自動的に検出するため、CIパイプラインの一部として疑似ローカリゼーションを実行してください。

画面上の [!! !!] で囲まれていないすべてのテキストはハードコーディングされており、外部化する必要があります。このテストは、見落とされた文字列の約95%を1分未満で検出します。

"メッセージを送信" → "[!! Ñáçḥŕíçḥṫ ṡéñðéñ !!]"

RTLレイアウトテスト

アラビア語やヘブライ語の翻訳がなくても、HTMLのルート要素に dir='rtl'を追加して RTL レイアウトをテストできます。これにより、方向性 CSS のバグを即座に検出できます。誤った配置のアイコン、片方の余白が不正、壊れたナビゲーション、誤って並べ替えられた Flex アイテムなどです。これをスプリントレビューの標準チェックにしましょう — 切り替えには約10秒かかり、通常の本番環境での修正に数週間かかる問題を捉えます。

i18nチェックリスト

['ユーザーに表示されるすべての文字列をリソースファイルに外部化する', '文を作成するための文字列連結を使用しない', 'ICUメッセージフォーマットまたは equivalent を用いた複数形の規則を実装', '日付、時刻、数値のフォーマットにはロケール対応のAPIを使用する', 'アラビア語またはヘブライ語の内容を含むRTLレイアウトをテスト', 'テキストを含む要素に固定幅を設けず、柔軟なUIを設計', 'フォールバック言語を設定し、キーが欠落している場合をテスト', 'すべてのファイルとデータベースでUTF-8エンコーディングを一貫して使用', '各市場向けにApp StoreとGoogle Playのメタデータをローカライズ', '各言語のスクリーンショットとマーケティング資産を更新']

記事を共有

アプリの翻訳の準備はできていますか?

AIを活用した翻訳で、iOS・Android・Webアプリを29言語以上に翻訳します。

無料で開始

関連コンテンツ

ガイド

アプリのターゲット言語を選択

アプリのローカリゼーションに適した言語を選ぶためのデータ駆動型ガイド。市場規模、ARPU、競争状況に基づいて最良のROIをもたらす言語を学びましょう。

7 min
target languagesmarket researchlocalization strategy