ウェブとネイティブUIを支えるローカリゼーションワークフロー
実践的なローカリゼーションワークフロー:翻訳キーを整理し、所有権を明確にし、複数形を扱い、QAを行ってWebとネイティブUIの崩れを防ぐ方法。

管理されていないローカリゼーションで何がまずくなるか
管理されていないローカリゼーションは、まず小さくてイライラする問題が起き、それがやがて高コストな問題につながります。昨日は収まっていたラベルが今日には溢れる。キーが抜けて生の識別子が表示される。英語では問題なかった複数形が別の言語では不自然、あるいは失礼に聞こえることもあります。
多くのチームは、プレッシャーの下で同じ問題を何度も直すことになります:
- 切れたボタン、切り詰められた見出し、アイコンと重なるテキスト
- 英語にフォールバックするかキー名がそのまま表示される欠損キー
- 間違った複数形(例えば
"1 items")や性別に依存する言語での文法崩れ - 同じ概念で画面ごとに異なる言い回し
- 翻訳が入らないまま出荷された画面への直前の応急対応
Webとネイティブでは壊れ方が違います。Webはレイアウトが柔軟なので、特定のビューポートやブラウザで初めて問題が見えることがあります。テキストが予期せず折り返し、ボタンを押し下げたり、グリッドを壊したりします。ネイティブでは余白が厳格です。長い翻訳で重要な要素が画面外に押し出されたり、アクセシビリティ用の大きなフォントでぶつかったり、コンポーネントが自動リサイズしないために切れてしまったりします。
堅牢なローカリゼーションワークフローは、キーを安定させ、翻訳をレビュー可能にし、UIチェックを定期化することで多くの問題を防げます。これによりアップデートが予期せぬ問題なく出せるようになります。ただし、元の英語が不明確だとこれは直せません。元の文言が文脈無しの「Open」や「Apply」のように曖昧だと、翻訳は推測になってしまいます。
単純な成功定義は「すべてが翻訳されている」ではなく、次の通りです:
- Webとネイティブの画面でUIが読みやすく保たれる
- キーが頻繁に変わらないのでアップデートが速い
- QAでユーザーより先に問題を発見できる
例:カート画面で "{count} item(s)" のように放置すると、複数形や間隔の問題が生じます。管理されたアプローチでは適切な複数形ルールを強制し、ドイツ語でボタンが30%大きくなるようなケースをリリース前に検出できます。
所有権と単一の真実のソースを決める
ローカリゼーションが崩壊する最大の理由は、誰も「どのテキストが正しいか」に答えられないことです。文字列の単一の真実のソースを選び、それを明文化して守ってください。そのソースはリポジトリのファイル、翻訳プラットフォーム、内部テーブルなどどれでも構いませんが、争いの際に決着する「一か所」である必要があります。
役割は職名でなく意思決定で定義します。意味とトーンを承認する人(多くはProductやMarketing)、コード内でキーを安定して使いやすくする人(多くはEngineering)、UI制約を守る人(多くはDesign)などが必要です。特にWebとネイティブで振る舞いが違う場合、DesignがUI制約を守る役割を持つと衝突が減ります。
衝突の多くを避ける分業例:
- キー作成者:画面を出荷する人が、UIに新しいテキストが必要なときにキーを作る。
- 文言承認者:PMやコピーオーナーがベース言語を承認する。
- 翻訳編集者:翻訳者は翻訳値を変更できるが、キー名は変更できない。
- キー変更:キーの廃止やマージはキー所有者のみが行い、理由を注記する。
リリースが停滞しないようレスポンスタイムの期待値も決めます。例:新規キー申請は1営業日以内に受理、ベース言語の承認は2日以内、UI破壊や法務文言の緊急修正は数時間以内。
具体例:新しい「パスワード再設定」フローをWebとネイティブで作るとします。開発者がキーを追加し、PMが英語の最終文言を承認し、翻訳者が他言語を埋めます。翻訳者が "Reset" を "Change" の方が適切だと気づいた場合は翻訳を更新できますが、キー名はそのままにします。PMが画面間で文言を再利用したい場合も、構造的な変更はキー所有者だけが行うというルールにします。
キー戦略:再利用、安定性、画面境界
良いワークフローは一つのルールから始まります:キーは識別子であり、英語の文ではない。部品番号のように扱ってください。後で文言を変えても通常キーは変えません。
意味が異なるときに新しいキーを作り、意味が同じなら再利用します。プロファイル画面の「Save」と設定画面の「Save」は、どちらも「変更を保存する」なら同じキーを共有できます。しかし「Save」が「ブックマークする」なら異なる動詞が必要で別キーにすべきです。
短いUIラベルと長いコンテンツは分けましょう。ボタンのラベル、ヘルパーヒント、エラーメッセージは翻訳の仕方や長さ制限が違うため、別キーにしておくとトーンや句読点を調整しやすくなります。
画面境界と同一表現を強制しない設計
Webとネイティブで再利用を目指すのは良いですが、プラットフォームごとに自然な言い回しが必要なら強制しないでください。ネイティブの許可ダイアログはWebのツールチップより明確で丁寧な文が必要なことがあります。その場合は概念は共有しつつ、プラットフォーム専用のキーを用意して各UIが自然に読めるようにします。
現実的なパターンとしては、機能とUIタイプでキーをグループ化し、その境界内で再利用することです:
- 同じ機能内で意味が同じなら再利用する
- UIタイプ(ラベル、ヘルプ、エラー、システムプロンプト)ごとにキーを分ける
- 表現を変える必要があるときだけプラットフォームバリアントを使う
- キーは安定させ、表示テキストだけを変える
- コンテキストメモ(表示箇所、文字数制限)を追加する
例:Web管理パネルとネイティブの現場アプリに同じ「顧客を削除」がある場合、コアのアクションラベルは再利用できますが、ネイティブの確認文がより強い警告を要するなら別キーにします。
翻訳キーの命名と整理
読みやすい命名はローカリゼーションを退屈にします。人が文字列を素早く見つけられ、翻訳者が文脈を得られ、キーは英語が変わっても安定します。
どこにあるか、何か、何のためか、バリアントかどうかの4つに答える読みやすい慣習を使ってください。Webとネイティブで有効な簡単なパターン:
<product_or_domain>.<screen_or_flow>.<component>.<purpose>[.<variant>]
たとえばカスタマーポータルでは portal.login.button.submit や portal.orders.empty_state.title のようにします。これにより画面やフロー別にキーが整理され、コンポーネントで検索しやすくなります。
悪いキーは曖昧すぎるか現在の英語文に縛られすぎています:
- 良い例:
portal.profile.field.email.label - 悪い例:
emailText(スコープや意図がない) - 悪い例:
please_enter_your_email(文言が変わると壊れる) - 良い例:
portal.checkout.error.payment_failed - 悪い例:
error_12
バリアントは句読点や混在した大文字でハックしないで明示的にしてください。狭いモバイルヘッダ用に短いラベルが必要なら、.title.short といったバリアントを追加します。大文字小文字の違いが必要な場合は、プラットフォームで安全に変換できないときだけ別キーにします(例:...button.save と ...button.save_titlecase)。
プレースホルダにもルールが必要です。翻訳者に推測させないためです。
- 名前付きプレースホルダを使う:
{user_name},{count},{date} - 連結は避ける:"Hello " + name のようにしない
- 単位は言語依存なら文字列内に入れる:
{count} itemsではなく{count} itemsを一つの文字列にする - 形式を定義する:ISO日付、通貨、またはプラットフォーム固有の日付形式
- トリッキーな文字列には短い注記を付ける(例:
{count}が0を取り得るか)
再作業を防ぐ複数形と文法ルール
複数形はワークフローがまず壊れる部分です。多くのチームはすべての言語に "one" と "many" しかないと仮定し、後でUIが不自然になったり修正が必要になったりします。
言語には複数のカテゴリがあることを想定してください。英語は主に one と other ですが、ロシア語、ポーランド語、アラビア語、チェコ語などは few や many、zero のような形を使います。早い段階で単一パターンに固執すると、後でWebとネイティブの両方で文字列を書き直す羽目になります。
複数形文字列は1つの標準に統一し、すべての場所(Web、iOS、Android、バックエンドでレンダリングされる文)で同じ方式にしてください。実用的なアプローチは、フォームごとに別キーにするのではなく、複数形を含む1つのキーを保存することです。CLDRのカテゴリに基づいたフォームを使うと実際の言語規則に合います。
UI文を "You have " + count + " messages" のようにパーツで作るのは避けてください。語順は変わるし、言語によっては数に応じて語尾や格が変わるからです。
実用的なキーのパターン
メッセージカウンタのような場合、安定した1つのキーを定義し数値はパラメータにしてください。翻訳者には言語ごとに必要なフォームを提供します。
- 概念ごとに1つのキー(例:
inbox.message_count) - CLDRフォームをサポート(zero, one, two, few, many, other)
- 文中に
{count}のようなプレースホルダを使う - 意味が不明瞭なら翻訳者向けの注記を付ける(たとえば “messages” が未読かどうか)
性別や格について
複数形だけでは足りないこともあります。ユーザーに呼びかける文("Welcome, Alex")や役割の参照("assigned to him/her")は、言語によって性別で単語が変わることがあります。前置詞の後で格が変わる言語もあります。
その場合は文法的に異なる文字列を別で用意してください。目標はキーを少なくすることですが、文脈で「正しい」翻訳でも不自然に見える事態をQAで減らすことが重要です。
プラットフォーム間のフォーマットとレイアウト制約
正しい翻訳でもUIを壊すことがあります。Webとネイティブはテキストのレンダリングが異なるため、ワークフローにはフォーマットルールとレイアウトチェックを含めるべきです。
数値、金額、日付の表示方法を標準化してください。"$" + amount のように連結したり、ラベル内で日付形式をハードコーディングしたりしないでください。ロケールに応じたフォーマットを使い、区切り文字や順序を期待通りにします(1,000.50 vs 1 000,50; 日-月-年 vs 月-日-年)。タイムゾーンはよく罠になります:タイムスタンプはUTCで保存し、ユーザーのローカルゾーンでフォーマットし、特定ゾーンの時間であるなら明記してください(例:店舗受取時間)。
テキスト方向も注意点です。右から左(RTL)言語をサポートするならレイアウトのミラーリングや句読点の扱いを計画してください。矢印や戻るボタンなど方向を示すアイコンは反転が必要なことが多いです。完全対応していなくても、レビューで簡単にRTLを確認する流れを入れてください。
モバイルではフォントと余白がWebよりも影響を受けやすいです。Webで収まっている文字列がSwiftUIやKotlinで折り返してしまうことがあります。最小フォントサイズ、折り返しの許容範囲、デフォルトフォントがカバーしないスクリプト用の代替フォントを決めてください。
アクセシビリティもローカライズ時にチェックが必要です。スクリーンリーダーは数字や省略形、混在言語を意外な読み方をすることがあります。
ほとんどの問題を防ぐレイアウトガードレール:
- テキストの拡張(30–50%)を想定し、固定幅のボタンは避ける
- 動的値(カウント、価格、日付)は別のフォーマット済みトークンにする
- カスタムパターンではなくプラットフォームネイティブの日付・数値フォーマッタを使う
- リリース前に1つのRTLロケールと1つの「長いテキスト」ロケールをテストする
- コアフロー(ログイン、チェックアウト、設定)でスクリーンリーダーチェックを行う
例:"Total: $1,234.50" は "1 234,50 €" のように記号が後ろに来たり、スペースや読み上げで区切りが必要になったりします。
新しい画面からリリースまでのステップバイステップワークフロー
ローカリゼーションワークフローは、画面設計の段階で始める必要があります。UIが「完成」してから始めると、翻訳を急いだり、切れたテキストを出荷したり、一時的に文字列をハードコードしたりすることになります。
各ラベル、ボタン、メッセージを設計時に翻訳キーとして追加してください。ベース言語のデフォルトテキストを書き、表示箇所やアクションの説明などのコンテキストを添えます。checkout.pay_button のようなキーは、翻訳者にそれが動詞の "Pay" なのかラベルの "Payment" なのかを伝えないと役に立ちません。
UIはプレースホルダとベース言語のフォールバックを使って実装します。変数は明示的にし(例:{name}、{count})、文をつなぎ合わせるのは避けてください。文をパーツでつなぐと文法が崩れやすくなります。
翻訳を依頼する際は翻訳者が正確に訳せるように必要な情報を添えます:画面ごとのスクリーンショット(または短いビデオ)、タイトな箇所の文字数制限(タブ、ボタン、バッジ)、トーンや用語の注記、動的プレースホルダの一覧と意味。
翻訳が戻ってきたら早めにマージしてWebとネイティブ両方をビルドし、リスクが高い画面をクイックUIチェックしてください:ログイン、オンボーディング、チェックアウト、設定。切れたテキスト、重なり、欠損キー、誤った複数形を探します。
最後にリリースしてモニタリングします。欠損キー、デフォルトへのフォールバック、頻繁にオーバーフローする画面を追跡してください。
翻訳者に正確さのための情報を与える
正確な翻訳は翻訳が始まる前から始まります。翻訳者がキーと英語フレーズしか見ていないと推測になります。これが言葉が合っているのに場面が違う、あるいは無礼に聞こえる原因です。
簡単な "コンテキストパック" を各文字列に付けるだけで多くの推測を排除できます。画面とコンポーネント、ユーザーの目的、トーン(フレンドリー、丁寧、緊急)を記載してください。ボタンラベル、エラーメッセージ、メニュー項目、ヘルプ文のようにカテゴリを明記すると翻訳が変わります。
スペースが厳しい場合は事前に伝えてください。Webとネイティブで崩れ方が違うため、重要な箇所の制限を明確にします:短いボタンラベル、タブタイトル、トースト、固定カード内のテキストなど。一行で収める必要があるかどうか、折り返して良い場合はどこで安全かを伝えます。
「翻訳しない」部分ははっきり指示します。プロダクト名、プラン名、クーポンコード、APIフィールド、{name} のようなプレースホルダは翻訳されては困ることが多いので明記してください。
実用的なパッケージ例(文字列ごと):
- スクリーンショットまたは画面名(例:"Checkout - Payment method")
- 種別と意図(支払いを確定するボタン)
- トーン注記(落ち着いた、安心感のある)
- 制約(最大18文字、1行のみ)
- 保護トークン(製品名、統合名、
{amount})
法務文やサポートコンテンツは別のフローで扱ってください。法務は承認が必要で更新が遅くなることが多いので、プロダクトUI文字列とは別にバージョン管理します。サポート記事やヘルプは長文翻訳が必要で別システムに置くのが楽です。
例:モバイルの "Continue" ボタンはWebより文字数制限が厳しいかもしれません。翻訳者がその制限を知っていれば、展開する言語で短い動詞を選んでくれます。
壊れたUIを防ぐQAとレビューのループ
ローカリゼーション起因のUI崩壊は最初は「バグ」らしく見えません。欠損ラベルや2行に折り返したボタン、プレースホルダが間違って表示されるなどです。良いワークフローはこうした問題をユーザーより前に見つけます。
開発ビルドで疑似ローカライズを始めてください。本物の文字列を長く・アクセント付きのバージョン(例:"[!!! Šéttïñĝš !!!]")に置き換え、長さを30–50%膨らませます。これで切断や重なり、ハードコーディングされた文字列がすぐ露呈します。
さらに各ビルドに自動チェックを入れます。人間が数百行をレビューして見逃すような単純ミスを検出できます:
- 任意ロケールでの欠損キー(フォールバックがあると気づきにくい)
- 未使用のキー(古い文字列が溜まっているサイン)
- プレースホルダ不一致(
"Hello, {name}"と"Hello, {username}"の違い) - ロケールに対する無効な複数形(zero, one, few, many)
- モバイル文字列内の生HTMLなどの禁止パターン
その後、明確な手動サインオフループを使います。Productは意味とトーンを、QAはレイアウトとインタラクションを確認します。
テストマトリクスは小さくて厳格に保ちます。すべてをテストする必要はありません。まず壊れやすいものをテストしてください:ログイン/サインアップ、パスワードリセット、チェックアウト/支払い確認、設定とプロフィール編集、通知、空状態、テーブルや小さなボタンを含む画面。
問題を報告するときは修正がしやすいよう具体的に書きます。ロケール、デバイスとOSバージョン(またはブラウザと幅)、期待されるテキスト、実際のテキスト、切れている箇所のスクリーンショットを含めてください。複数形やプレースホルダの問題なら、該当キーとレンダリング結果を貼ると早く直せます。
よくあるミスと回避方法
多くのローカリゼーションバグは “翻訳の問題” ではなく“ワークフローの問題” で、壊れたUIや欠損テキスト、混乱するメッセージとして現れます。
よくある落とし穴は、文言を変えたいだけなのにキー名を変更してしまうことです。checkout.button.pay を checkout.button.pay_now に変えると、過去の翻訳がすべて "欠損" になります。キーは安定させ、デフォルト言語の文字列を更新し、意味が変わったならコンテキストを追加してください。
別の問題は一部のプラットフォームで文字列をハードコードしてしまうことです。Webチームはキーを使っているのに、モバイルが手早く直すために直書きしてしまうと、数週間後にiOSだけ英語のまま、ということが起きます。「ユーザー向け文字列をハードコードしない」ルールをWebとネイティブで共有してください。
プレースホルダは語順の仮定で微妙なミスを生みます。英語なら "{count} items" で良くても、他言語では語順や語尾が変わることを想定して名前付きプレースホルダを使い、プラットフォーム間で一貫させてください。
早期に捕まえるべきミス:
- キーをコピーとして扱い既存翻訳を壊す。キーは安定化する。
- 意味が違うのに1つのキーを使い回す。意図が違うなら分割する。
- プレースホルダのスタイルを混ぜる(名前付きと番号付きを混在させない)。
- 英語だけでテストする。長くなる言語と短く表示される言語の両方を確認する。
- フォールバック動作を決めずに出荷する。欠損時にどう振る舞うかを合意しておく。
一つの「長い言語」だけテストするのは不十分です。ドイツ語は拡張が多く、中国語は余白問題を隠すことがあります。どちらも簡易チェックをし、複数形のエッジケース(0,1,2など)も試してください。
リリース前にフォールバック動作を合意しておきます。例:フランス語が欠けている場合は英語にフォールバックして欠損キーをログに残し、重要画面に欠損がある時だけリリースをブロックする、など。
クイックチェックリストと実用的な次のステップ
ローカリゼーションワークフローは、チェックが小さく繰り返せると健全に保てます。目標は明確:驚きの文字列を減らし、壊れたレイアウトを減らし、翻訳の駆け込みを減らすことです。
UI変更をマージする前に、一般的な "うっかり" を素早く確認します:
- 新しいキーは命名ルールに従い正しいネームスペース(画面や機能)に置かれている
- プレースホルダがすべての言語で正確に一致している(同じ変数、同じ意味)
- 対応言語について複数形が完全である(英語の単数/複数だけでない)
- UIにハードコードされたテキストが残っていない(エラーや空状態も含む)
- 新しい/変更したテキストにスクリーンショットや明確な注記といった基本的なコンテキストが付いている
出荷前にはローカリゼーションが壊れやすい箇所に絞った短いリリースQAを行います。時間を区切って一貫して行うこと:各プラットフォームの主要ユーザーフロー、1つのRTLチェック、長文が出る画面(設定、法務、オンボーディング、テーブル、狭いボタン)、およびいくつかのロケールでの日付/数値/通貨フォーマットの検証。
チームに合った頻度を設定してください。多くのチームは週次で翻訳を更新し、リリースの1–2日前に文字列をフリーズします。要点は、リリース直前の文言変更と最終QAを混ぜないことです。
すぐに効果が出る次のステップ:規約(キー命名、プレースホルダ、複数形ルール、所有権)を書き出し、パイロット画面を1つ終端まで作って、壊れる箇所を基に調整してください。
バックエンド、Web UI、ネイティブモバイルを単一プラットフォーム(例:AppMaster)で構築している場合、同じ画面とロジックが同じ慣習を共有できるため、キーとプレースホルダの一貫性を保ちやすくなります。その慣習を安定して維持することが、ローカリゼーションを脆弱ではなく習慣的な運用に変える鍵です。
よくある質問
まず文字列を一か所で管理すること、キー命名のルールを決めること、そして英語の文言が変わってもキーは変えないルールを導入してください。最後に、リリース前に欠損キー、オーバーフロー、複数形の問題を検出する小さなQAルーチンを追加します。
競合が起きたときに“勝つ”単一のシステムを決めます。たとえばリポジトリ内の翻訳ファイルや翻訳プラットフォームのエクスポートなどです。全員がそのソースを通して編集し、コードはそれを消費するだけ、という運用にします。
役職ではなく責任で決めます。ベース言語の意味とトーンを承認する人、キー構造と廃止を管理する人、翻訳値だけを編集する翻訳者——といった分担を決めると、無断のキー変更やリリース直前のコピー変更によるビルド破綻を防げます。
意味が変わるときに新しいキーを作り、意味が同じなら再利用します。英語の表現が似ていても意図が違えばキーを分けてください。これで翻訳の一貫性が保てます。
キーは識別子として扱い、英語の文をそのままキーにしないこと。機能、画面/フロー、コンポーネント、用途といったスコープを含めると良いです。例:portal.checkout.button.pay はボタン文言が変わっても有用です。
多くの言語は単数/複数だけでは足りません。1つの概念ごとにキーを作り、言語ごとに必要な複数形カテゴリ(CLDRに基づく zero/one/two/few/many/other など)をサポートしてください。文中に {count} を入れて、翻訳者が語順を自由にできるようにします。
パーツを連結して文を作らないでください(例:"Hello " + name)。語順や語尾が言語によって変わるためです。代わりに {user_name} のような名前付きプレースホルダを一貫して使い、それぞれが何を意味するかを文書化します。
テキストは30〜50%長くなると想定して設計し、ラベルが折り返せるか、フォントサイズやアクセシビリティ設定で崩れないかをチェックします。Webとネイティブで必要な文字数が違うなら、翻訳者にその制限を伝えてください。
開発段階で疑似ローカライズを使い、文字列を長く・アクセント付きにして表示してみると、埋め込み文字列や切断の問題がすぐ分かります。ビルド時に欠損キー、未使用キー、プレースホルダ不一致、無効な複数形などを自動チェックするのも効果的です。手動レビューはログインやチェックアウトなど“壊れやすい”フローに絞ります。
ベース言語にフォールバックして、欠損キーはログに残して素早く補う運用にすると多くのリリースを止めずに済みます。ただし、法務系や重要な画面は欠損がある場合にリリースを止める方針にすると安全です。


