実際のペイロードは、文章だけでできていることのほうが稀です。title や body を持つのと同じオブジェクトに、id、slug、アセットURL、テンプレート名、enumコードといった、コンテンツを識別したり結び付けたりする値も入っています。こうした値は、翻訳に通しても入力時と完全に同一でなければなりません。厄介なのは、壊れ方が静かなことです。翻訳対象のテキストの隣に id というフィールド名があると、モデルは "post-42" のほうがローカライズしたほうが自然だと判断したり、URLを正規化したり、enumを「修正」したりするかもしれません。識別子が1つでも変われば、モデルが親切を働いたそのロケールで、本番環境のリンク切れやルックアップ失敗が起きます。
lockedKeys を使えば、こうした推測に任せずに済みます。変えてはいけないキーを、完全一致の名前または glob で指定すると、ローカライゼーションエンジンはその値を翻訳対象から外し、すべての対象ロケールについて outputData に元の値をそのまま差し戻して 返します。ロックされた値は、翻訳も、正規化も、書き換えもされません。どのロケールでも、入れた識別子がそのまま返ってきます。
lockedKeys は create-jobs リクエストのフィールドです。リクエスト全体の形式と 202 レスポンスについては Create jobs を参照してください。このページでは、lockedKeys に何を書くかと、そのマッチ方法だけを扱います。
名前でキーをロックする#
lockedKeys を data と一緒に渡します。各エントリはパターンで、いちばんシンプルなのは保持したいキー名をそのまま書く方法です。
{
"sourceLocale": "en",
"targetLocales": ["de", "fr"],
"data": {
"id": "post-42",
"title": "How async APIs reduce latency",
"tags": ["performance", "infra"],
"author": { "id": "u_abc", "name": "Sam" },
"body": "Async APIs let your app stay responsive while translations process in the background."
},
"lockedKeys": ["id"]
}単純なパターン id は、キー id が完全なセグメントとして現れる場所なら、どこにでもマッチします。ここではトップレベルの id と、ネストされた author.id の両方です。ドイツ語とフランス語のすべてのジョブの outputData では、"post-42" と "u_abc" が一切変わりません。翻訳されるのは title、name、body だけです。tags はロック対象のパスを含まないのでそのままロックされず、文字列の値はほかのテキストと同じように翻訳されます。
この最後の点は大事です。疑い深い人が真っ先に聞く質問への答えでもあるので、ここではっきりさせておきましょう。
ロックした値は翻訳される?
いいえ。lockedKeys で指定したキーは翻訳対象から除外され、ソースの値がすべての対象ロケールの outputData にそのまま差し戻されます。送った値は変更されずに返ってきます。翻訳も、正規化も、書き換えもされません。ロックは、モデルに守ってもらうためのヒントではなく、lockedKeys を通じて結果を保証する仕組みです。
どこにあっても名前で一致、必要なら位置で一致#
単純なパターンはキー名そのもので、完全なセグメントとして、任意の深さで、ツリー内のどこにあっても その名前にマッチします。audioSrc が異なる親の下に12か所あるなら、パターン audioSrc を1つ書くだけで、その12か所すべてをロックできます。出現箇所ごとにパスを列挙する必要はありません。これがいちばんよくある使い方で、1行で済みます。
位置まで細かく制御したいとき、たとえばある出現箇所だけをロックして別の箇所はロックしない、あるいは配列の全要素だけをロックしてそれ以外は対象外にしたい、といった場合は、/ をパス区切りにした glob を使います。配列インデックスも通常のセグメントとして扱われるので、users/0/email も users/*/email も有効なパスです。
| パターン | ロックされる対象 |
|---|---|
audioSrc | ツリー内の任意の深さにある、すべての audioSrc リーフ |
metadata | その場所に現れる metadata サブツリー全体 |
metadata/author | その並びが現れる場所すべての metadata/author と、その配下すべて |
users/*/email | すべてのユーザーの email — * は1セグメントとして任意のインデックスにマッチ |
users/0/email | 最初のユーザーのメールアドレスだけ |
**/{audioSrc,imageSrc} | ブレース展開で両方のリーフ名を指定 |
上の2つのパターンは、仕様として単一のリーフより広い範囲をロックします。metadata は、そのキーの下にあるサブツリー全体をロックします。つまり、その配下の値は、翻訳できそうに見えるかどうかに関係なく、すべて保持されます。metadata/author は、その並びが現れる場所ならどこでもロックし、さらにその配下すべて も対象にします。ブロック全体が構造そのもの、たとえば設定オブジェクトや生の埋め込みであるならサブツリーロックを使い、ほかは翻訳したいが中の1フィールドだけ保持したいならリーフロック(metadata/author/name)を使ってください。
regex ではなく glob
* はちょうど1つのパスセグメントにマッチし、** は任意個のセグメントをまたぎ、{a,b} は候補を並べたブレース展開です。文字クラスやトークンの一部一致はありません。パターンは部分文字列ではなく、完全なパスセグメント単位で評価されます。正規表現ではなく users/*/email を書いてください。
返ってくる結果#
ロックで変わるのは、モデルが何を翻訳するかだけです。返ってくる結果の構造は変わりません。outputData は入力の構造をそのまま映します。ロックされたキーは元の位置に元の値のまま残り、その周囲の翻訳対象文字列だけが翻訳されます。削除、リネーム、並べ替えは一切起きません。
上の入力例では、どのロケールの outputData にも id: "post-42" と author.id: "u_abc" がそのまま入り、title、name、body は対象言語に翻訳されます。ジョブレスポンス全体、つまり outputData、ステージごとの steps、ステータスについては Get a single job を参照してください。
先に押さえておきたい制限は1つ#
lockedKeys で指定できるのは、1リクエストあたり最大100パターン です。上限があるのはパターン数であって、マッチするキー数ではありません。audioSrc や users/*/email を1つ使うだけで、大きなペイロード全体にまたがる何千もの値をロックでき、それでも1パターンとして数えられます。100個近い別々のパターンが必要になっているなら、多くの場合は、より広い glob(**/{id,slug,href})やサブツリーロックで同じ意図をもっと少ない記述で表せます。
lockedKeys はリクエスト単位の、その場限りの指定でもあります。キーをロックするのはこのジョブグループだけです。だから、どの ジョブでも絶対に翻訳したくない語、たとえば製品名、商標付きの機能名、常に字面どおりに保ちたい単位などは、エンジンの用語集で「翻訳しない」エントリとして管理するのが長期的には適切です。これはすべての呼び出しに自動で適用されます。Glossaries を参照してください。lockedKeys は特定のペイロード構造にひもづく構造的なフィールドに使い、すべてのコンテンツで共通する語彙には用語集を使ってください。
