目次
CDN Translation Delivery:Edge Cacheによるi18nパフォーマンス完全ガイド
翻訳の配信は、見えないところに潜むパフォーマンスの問題です。アプリのページ読み込みが1秒以下であり、画像が最適化され、バンドルがコード分割されていても、翻訳の到着が遅れると、ユーザーはレイアウトのずれ、ローディングスピナー、あるいはより深刻な問題として未翻訳のキーが画面上でちらつくのを目にすることになります。
このガイドでは、better-i18nがCloudflare R2とEdge Cachingを使って翻訳配信の問題をどのように解決するかを説明し、エンジニアリングチームが利用できるすべてのCDNオペレーションを詳しく解説します。
翻訳配信がi18nパフォーマンスに重要な理由
従来のi18nセットアップでは、翻訳をアプリケーション内にバンドルします。誤字を修正したり新しい言語を追加するたびに、完全な再ビルドと再Deployが必要になります。モバイルアプリの場合、それはApp Storeのレビューを待つことを意味します。Webアプリの場合、エンジニアリング以外の変更をブロックするDeployパイプラインを意味します。
CDN翻訳配信は、翻訳コンテンツをアプリケーションコードから切り離します。翻訳はEdgeに存在し、ユーザーに最も近いCloudflareノードから提供されます。アプリは実行時にHTTPでそれらを取得します。
パフォーマンスの特性:
- 50ms未満の配信 — 最寄りのEdgeノードから(世界300以上の拠点)
- オリジンへのラウンドトリップゼロ — キャッシュ済み翻訳の場合
- インクリメンタルな更新 — アプリケーションの再Deployなし
- 並列ローディング — 現在のページが必要とするNamespaceのみ
それを可能にするURL構造
better-i18nのすべての翻訳ファイルは、決定論的なURLパターンに従います:
https://cdn.better-i18n.com/{org}/{project}/{locale}/{namespace}.json
この構造は意図的にシンプルで予測可能です。これが意味するのは:
- ブラウザキャッシュがネイティブに動作します — 各ロケール・Namespaceペアは一意で安定したURLを持ちます
- Service Workerが既知のパスをプリキャッシュできます — ディスカバリリクエストなしに
- CDN Edgeノードがパスごとに独立してキャッシュします —
fr/auth.jsonのキャッシュミスはen/common.jsonに影響しません - あらゆるHTTPクライアントが利用できます — SDKなし、認証なし、特別なヘッダーなし
いくつかの実際の例:
# English common translations https://cdn.better-i18n.com/acme/web-app/en/common.json # Turkish authentication strings https://cdn.better-i18n.com/acme/web-app/tr/auth.json # Japanese dashboard translations https://cdn.better-i18n.com/acme/web-app/ja/dashboard.json
各プロジェクトには/{org}/{project}/manifest.jsonにマニフェストがあり、利用可能なすべてのロケールを一覧表示します。モバイルSDKはこれを使用して、ロケールリストをハードコードせずに実行時に言語を自動検出します。
UploadとMerge:CDN更新の2つのモデル
better-i18nはCDN上の翻訳を更新するための2つの異なるアプローチを提供します。
フルUpload(cdn.uploadとcdn.uploadBatch)
UploadはR2上のNamespace・ロケールファイル全体を置き換えます:
# Single file better-i18n cdn upload --locale en --namespace common # Multiple files in one operation better-i18n cdn upload-batch --locales en,tr,fr --namespaces common,auth
バッチUploadが適切な選択なのは:
- 初めて新しい言語を公開するとき
- 大規模な再構築後にCDNファイルを再構築するとき
- TMSから完全な翻訳エクスポートをDeployするとき
バッチオペレーションは内部的に最適化されています — R2への書き込みとキャッシュの無効化がバッチ処理されるため、順次個別Uploadと比べて合計伝播時間が短縮されます。
インクリメンタルMerge(cdn.merge)
MergeはR2から既存ファイルを読み取り、キーレベルの変更を適用し、結果を書き戻します:
better-i18n cdn merge --locale en --namespace common --keys "welcome,nav.home"
Mergeに含まれないキーは変更されずに残ります。インクリメンタルな更新にはより安全な選択肢です。なぜなら:
- 偶発的な上書きなし — ファイル内の他のキーは保持されます
- 並行安全性 — 複数のチームメンバーやCIパイプラインが異なるキーを競合なくMergeできます
- より小さな変更範囲 — 指定されたキーのみが変更されます
Mergeプレビュー(cdn.mergePreview)
Mergeを実行する前に結果をプレビューします:
better-i18n cdn merge-preview --locale en --namespace common --keys "welcome"
これは、どのキーが追加、更新、または変更なしに残るかを示すdiffを返します。データベースマイグレーションを適用前にレビューするように、CIパイプラインでMergeプレビューを使用してCDN Deployをレビューステップの後ろに置きます。
重複検出:CDNペイロードをスリムに保つ
翻訳プロジェクトが成長するにつれて、重複が蓄積します。「保存」ボタンの文字列がcommon.json、settings.json、profile.jsonの3つすべてに同一の値で存在することがあります。重複するたびにCDNのペイロードが増え、メンテナンスの手間が生じます — 1つを更新して他を忘れてしまいます。
重複の検出(cdn.detectDuplicates)
better-i18n cdn detect-duplicates
これはプロジェクト内のすべてのCDNファイルをスキャンし、Namespace間で同一の翻訳値を共有するキーのレポートを生成します。レポートには以下が示されます:
- どのキーが重複しているか
- どのNamespaceにそれらが含まれているか
- 共有されている値
クリーンアップ(cdn.cleanupDuplicates)
better-i18n cdn cleanup-duplicates --target-namespace common
これは重複をターゲットNamespace(通常common)に統合し、ソースNamespaceから削除します。オペレーションは内部でMergeを使用するため、並行アクセスに安全です。
ベストプラクティス: 大規模な翻訳インポートやNamespaceの再編成後にcdn.detectDuplicatesを実行します。CDNペイロードを最小限に保つために定期的なクリーンアップをスケジュールしてください。
CDNライフサイクル管理
Setup(cdn.setup)
プロジェクトのCDN配信を初期化します:
better-i18n cdn setup
これはR2バケット構造を作成し、Cloudflare Worker EdgeルーティングをConfigし、キャッシュルールを設定します。プロジェクトでCDN配信を初めて有効にする際に一度実行します。
ファイル管理
CDNの状態を監査するためにすべてのDeployされたファイルをリスト表示します:
better-i18n cdn list-files
各ファイルのロケール、Namespace、サイズ、最終更新タイムスタンプを返します。Deployの確認や古いファイルの特定に役立ちます。
Namespaceを廃止したりロケールを削除する際に個別ファイルを削除します:
better-i18n cdn delete-file --locale en --namespace legacy-feature
Teardown(cdn.uninstall)
CDN配信を完全に削除します:
better-i18n cdn uninstall
R2ストレージ、Edge設定、キャッシュルールをクリーンアップします。プロジェクトを移行したりアプリケーションを廃止する際に使用します。
実際のパフォーマンス
本番環境でのCDN翻訳配信の姿:
| メトリクス | 値 |
|---|---|
| Edgeロケーション | 300以上(Cloudflareネットワーク) |
| キャッシュヒット遅延 | 50ms未満(典型値) |
| キャッシュミス遅延 | 200ms未満(R2オリジンフェッチ) |
| 伝播時間 | 公開後10秒未満 |
| Egressコスト | 0円(Cloudflare R2) |
ゼロEgressコストの側面は強調する価値があります。従来のCDNセットアップはGB単位で帯域幅を課金します。R2では、翻訳配信のコストはトラフィック量に関係なく固定です。月に1,000万回の翻訳フェッチを提供するプロジェクトも、1,000回のプロジェクトも同じ料金を支払います。
翻訳のNamespaceベースのコード分割
Namespaceモデルは翻訳のコード分割として機能します。すべての翻訳を事前にロードする代わりに:
❌ /en/all-translations.json (450 KB)
アプリは現在のルートが必要とするものだけをロードします:
✅ /en/common.json (12 KB) + /en/auth.json (4 KB) = 16 KB
これにより、大規模な翻訳セットを持つアプリの初期ページロードが90%以上削減されます。Edge Cachingと組み合わせると、次のページナビゲーションは新しいNamespaceのみをフェッチします — dashboard.jsonはユーザーがダッシュボードに移動したときにロードされ、それより前にはロードされません。
統合アプローチ
SDK統合(推奨)
公式SDKはCDNフェッチ、キャッシュ、フォールバックを自動的に処理します:
@better-i18n/next— ISR/SSGサポートを備えたサーバーサイドフェッチ@better-i18n/use-intl— TanStack RouterとViteアプリ向けクライアントサイドフェッチ@better-i18n/expo— MMKV/AsyncStorageキャッシュを使ったオフラインファースト
各SDKはi18n.config.tsのプロジェクト識別子からCDN URLを解決します。手動でURLを構築する必要はありません。
直接HTTP(あらゆるプラットフォーム)
CDNはシンプルなHTTPSエンドポイントです。認証なし、特別なヘッダーなし:
curl https://cdn.better-i18n.com/acme/web-app/en/common.json
これにより、better-i18nの翻訳はあらゆるプラットフォームから利用可能になります:iOS(Swift)、Android(Kotlin)、バックエンドサービス(Go、Python、Ruby)、ゲームエンジン、IoTデバイス — HTTP GETリクエストを送信できるものなら何でも。
Publish-to-CDNパイプライン
翻訳を編集してから世界中に配信するまでの完全なワークフロー:
- 編集 — ダッシュボード、REST API、またはMCPツール
- 保留中の変更をプレビュー —
getPendingChangesでDeployされる内容を確認 - MergeResultをプレビュー —
cdn.mergePreviewでキーレベルのdiffを表示(オプション) - 公開 —
publishTranslationsがcdn_upload同期ジョブをトリガーします - モニタリング —
getSyncs/getSyncでDeployステータスを追跡 - 確認 —
cdn.listFilesで更新されたファイルがライブであることを確認
これにより、エンジニアリングチームはコードDeployと同じ厳密さを翻訳Deployに対しても持てます:プレビュー、公開、モニタリング、確認。
はじめに
- プロジェクトを作成 — dash.better-i18n.comで
cdn.setupを実行 — R2ストレージとEdgeルーティングを初期化するために- 翻訳を追加してCDNに公開します
- 統合 — フレームワークSDKまたは直接HTTPで
- モニタリング —
cdn.listFilesとcdn.detectDuplicatesで
CDN配信は無料プランを含むすべてのプランで利用できます。翻訳は初日からEdgeでキャッシュされます。