ソートリーダーシップ//8 読了時間

スタートアップのためのi18n:国際化のタイミング(そして書き直しを避ける方法)

Eray Gündoğmuş
共有

シリーズAの頃、ほぼすべてのスタートアップで交わされる会話があります。誰かがアナリティクスを見て、登録者の30%が非英語圏の国から来ていることに気づきます。プロダクトは英語のみです。これらのコホートからの解約は壊滅的です。エンジニアリングリードが言います、「国際化が必要だ」と。

そして見積もりが返ってきます:最低6か月。

その見積もりはほぼ常に正確で、ほぼ常に避けられるものです。

i18nを後付けする本当のコスト

CSA Researchによると、消費者の87%は自分の言語で代替品がある場合、英語のみのプロダクトからは購入しません。ローカリゼーション市場は2023年に62.7億ドルに達し、成長を続けています。これはニッチな数字ではありません——あなたがコードベースにひっそりとインストールした、アドレス可能な市場の上限を表しています。

後付けが高コストな理由は、国際化が技術的に難しいからではありません。i18nを考慮せずにアプリケーションが構築される方法にあります:

  • 200のコンポーネントに散らばった文字列リテラル
  • 米国の慣習にハードコードされた日付と数値のフォーマット
  • 英語テキストに合わせてサイズ設定されたデータベース列
  • 一度も検討されなかった右から左へのレイアウト
  • 英語の文法的前提を中心に構造化されたコンテンツ
  • 単一地域に結び付けられたタイムゾーン処理

これらはそれぞれ、初日に正しく行うのは安価です。しかし、コードベースが40,000行になり、元の前提の上に構築してきた4人のエンジニアがいる18か月目に解きほぐすのは苦痛です。

6か月の見積もりは翻訳を追加するためではありません。i18nを考慮せずに構築されたアプリケーションの部分を監査して書き直すためです。翻訳は作業の20%。残りの80%は考古学です。

実際にはいつ国際化すべきか?

この質問には2つの部分があります:アーキテクチャをi18n対応にするタイミングと、実際に複数の言語をリリースするタイミングです。

アーキテクチャ:常に初日から。

最初からi18n対応で構築するコストは約2時間のセットアップです。何も翻訳しません。翻訳者を採用しません。ただ、扉を閉じない意思決定をするだけです。

  • 文字列をハードコードする代わりにリソースファイルに外部化する
  • ロケール対応の日付/時刻ライブラリを使用する(Luxon、ロケールサポート付きdate-fns、Temporal)
  • Intl.NumberFormatをラップする数値フォーマットアプローチを選ぶ
  • テキスト拡張のためにUIにスペースを確保する(ドイツ語は英語より30%長くなることがある)
  • 最初からロケールをユーザー設定として保存する

これは早すぎる最適化ではありません。オーバーエンジニアリングでもありません。変更したい可能性のある設定値に環境変数を使う理由と同じです——特定のニーズを見越しているのではなく、特定の落とし穴を避けているのです。

翻訳のリリース:シグナルを得た後。

初日にフランス語をリリースする必要はありません。準備ができている必要があります。実際に第2言語に投資する決断はデータに基づくべきです:

  • ターゲット市場からオーガニックな登録を見ている
  • 販売会話で取引を成立させるために必要とされている
  • 英語普及率が低い市場に参入している
  • 特定言語のカスタマーコホートがより高い率で解約している

そのシグナルが現れたとき、「i18n対応」とは6か月ではなく1週間で第2言語をリリースできることを意味します。

3か月タイムライントラップ

チームが陥るパターンはこうです:i18nが必要だと知っていて、間違いを犯したくないので「適切なi18nプロジェクト」を計画します。3か月と見積もります。その見積もりには以下が含まれます:

  • 既存文字列の監査
  • 翻訳パイプラインの構築
  • 翻訳管理システムの統合
  • 翻訳ベンダーとの調整
  • すべてのロケールでのQA

プロジェクトが計画中の間、ロードマップは進み続けます。3か月のプロジェクトは機能をリリースしないため、常に優先度が下げられます。最終的に優先されるころには、コードベースが成長したため5か月のプロジェクトになっています。

罠はi18nをビッグバンの移行として扱うことです。代替案は、アーキテクチャから始めて段階的に構築する基盤として扱うことです。

最小限のi18nセットアップ

シードステージのReactまたはNext.jsアプリにおける「i18n対応」が実践でどのように見えるかを示します。セットアップに2時間かかり、翻訳の準備ができるまで継続的なオーバーヘッドはゼロです。

ステップ1:文字列外部化アプローチを選ぶ。

表示文字列をハードコードしないでください。最低限、JSONファイルに入れてください。より良いのは:最初から型付きのソリューションを使用することです。

// 悪い — ハードコードされた文字列
<button>Get started for free</button>

// より良い — 外部化、今は英語のみでも
// messages/en.json
{
  "cta.getStarted": "Get started for free"
}

// コンポーネント
const t = useTranslations();
<button>{t('cta.getStarted')}</button>

まだ翻訳プラットフォームは必要ありません。英語のみであっても、ロケールごとに1つのJSONファイルで十分です。インライン文字列の代わりにt()を使う習慣が重要です。

ステップ2:初日からロケール対応フォーマット。

// 悪い — ハードコードされた米国フォーマット
const formatted = `$${price.toFixed(2)}`;
const date = new Date(ts).toLocaleDateString('en-US');

// 良い — ロケール対応
const formatted = new Intl.NumberFormat(locale, {
  style: 'currency',
  currency: 'USD'
}).format(price);

const date = new Intl.DateTimeFormat(locale, {
  dateStyle: 'medium'
}).format(new Date(ts));

後で第2のロケールを追加すると、フォーマットは自動的に機能します。80ファイルにわたるgrep-and-replaceは不要です。

ステップ3:テキスト拡張を考慮してデザインする。

UIに余裕を持たせてください。テキストが長くなっても優雅に対応するCSSを使用してください。テキストコンテナのピクセル固定幅を避けてください。これはデザインでコストゼロですが、ドイツ語をリリースする際のQAで実際のコストを節約します。

ステップ4:ロケールをファーストクラスのユーザー属性として保存する。

1つの言語をリリースしている場合でも、ユーザーモデルにpreferred_localeを保存してください。第2言語を追加すると、既存ユーザーはすでにロケール設定が保存されています。ライブデータの下でスキーマを移行する必要はありません。

スタートアップよくある間違い

「必要になったらi18nを追加する」 必要になる瞬間は、適切に行う時間がない瞬間です。決断を引き起こすシグナル——フランス語を必要とする主要顧客、地域的なgo-to-marketの推進——は常に緊急性を伴って現れます。

カスタム翻訳パイプラインの構築。 翻訳管理は解決済みの問題です。カスタムソリューションは構築に数週間、メンテナンスに数か月かかります。既存のツールを使用してください。

ローカリゼーションを単なる翻訳として扱う。 言語はローカリゼーションの20%です。通貨、日付形式、住所形式、法的要件、RTLサポート、ロケール固有のUX慣習——これらが残りの80%です。壊れたレイアウトの翻訳された文字列は、やはり壊れた体験です。

翻訳者にJSONファイルへの直接アクセスを与える。 人間の翻訳者はJSONを手動で編集すべきではありません。エラー率が高く、フィードバックサイクルが遅いです。文脈、文字数制限、用語の一貫性強制を備えた翻訳作業用に構築されたUIが必要です。

英語の語順が一般化できると仮定する。 JavaScriptの文字列補間で翻訳された文字列を連結すると、異なる文法構造を持つ言語では壊れます。変数を含むものにはICUメッセージフォーマットを使用してください。

// 悪い — 英語の語順を仮定
t('welcome') + ' ' + userName + '!'

// 良い — ICUフォーマット、ロケールはトークンを並べ替えられる
t('welcome', { name: userName })
// en: "Welcome, {name}!"
// ja: "{name}さん、ようこそ!"

意思決定フレームワーク

これを使って現在の状況と次のステップを判断してください:

ステージi18nアーキテクチャアクティブな翻訳
プロダクト前外部化された文字列、ロケール対応フォーマットをセットアップなし
PMF前基盤を維持、まだ翻訳しないなし
PMF後、シリーズA前国際的なシグナルが見えたら、上位2言語を翻訳場合による
シリーズA以降ローカリゼーションをプロダクト要件として扱うあり

重要な洞察:アーキテクチャの決断と翻訳の決断は独立しています。アーキテクチャの決断は今行ってください。翻訳の決断はデータが示すときに行ってください。

実践的なチェックリスト

次のコンポーネントを書く前に、これを確認してください:

  • 文字列が外部化されている(JSX/テンプレートにハードコードされていない)
  • 日付フォーマットはロケール対応APIを使用している
  • 数値と通貨フォーマットはIntl.NumberFormatを使用している
  • ユーザーモデルにlocaleフィールドがある
  • UIレイアウトが30%長いテキストでテストされている
  • 翻訳可能な部分との文字列連結がない
  • 変数を含む文字列にICUメッセージフォーマットを使用している
  • 複数形が正しく処理されている(単に「s」を追加するだけでなく)

これらすべてをチェックするのに2時間かかります。スケールでいずれかを見逃すと、数週間のコストがかかります。

実践ではどのように見えるか

実際に複数の言語をリリースする準備ができたとき、ワークフローは「考古学的発掘」から「翻訳プロジェクト」に変わります。必要なもの:

  1. ソース文字列を翻訳者にエクスポートする方法
  2. 翻訳のレビュープロセス
  3. コードデプロイなしで文字列を更新するデプロイパイプライン
  4. 各ユーザーへの適切なロケールのランタイム配信

Better i18nでは、この特定の問題を中心にプラットフォームを構築しました——React、Next.js、Vue、Svelteのための型安全なSDK、翻訳がコードのようにレビューを経るGitベースの翻訳ワークフロー、そして再デプロイなしで翻訳を更新できるCDN配信。価格ページの無料プランは、予算コミットメントなしに基盤を構築したい初期段階のチームのためにサイズ設定されています。技術的な部分がどのように組み合わさるかを確認したい場合は、開発者向けページに全体像があります。

6か月の書き直しは避けられないものではありません。2時間の決断が長すぎるほど先延ばしにされた結果です。

Comments

Loading comments...