-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial 5 Localization ja
ゴール: LockedIn CLIが33言語を話すしくみを理解し、さらに別の言語をエージェントに 追加させる練習をすること。多言語対応はエージェント向けの題材として非常に優秀です。 任せられる程度に機械的でありながら、テストゲート、レイアウト規則、文法レビューという 本物の制約があるため、レビューする力が鍛えられます。
← 前へ: チュートリアル4 プロンプトとレビュー · ホーム に戻る
スペイン語、ヒンディー語、日本語、簡体字中国語、その他の同梱言語でCLIを起動すると、 表示のすべてが切り替わります。スプラッシュ、ヘルプの表、各コマンドの出力、 チャットセッション、法的な小さな注意書きまで。ジョークだけではなく、目に見える面すべてです。
lockedin --lang ja post
LOCKEDIN_LANG=hi lockedin
lockedin --lang zh aura言語は起動時に自動判定され、優先順位は次のとおりです。
-
--langフラグ(--lang ja、--lang=fr、-l ja) - 環境変数
LOCKEDIN_LANG - ロケール(
LC_ALL/LC_MESSAGES/LANG、続いてOS・ランタイムのロケール) - フォールバックとしての英語
normalizeLang() は通常、ロケールの先頭サブタグを見ます。de-DE は de になりますが、
tlh が偶然 tl になることはありません。fil と tgl はタガログ語(tl)へ、
ノルウェー語 nb・nn は no へ、旧インドネシア語コード in は id へ、
旧ヘブライ語コード iw は he へ対応づけています。2つの地域コードは先頭サブタグに
畳まず、そのまま保持します。pt-BR・pt_BR は正規の地域コードを選び、汎用の pt は
後方互換のブラジル・ポルトガル語バンドルのままです(どちらもブラジル・ポルトガル語で、同じ pools/UI を共有します)。
en-SG・en_SG はシングリッシュ(汎用の en は英語の
まま)です。香港繁体字中国語も同種の例外で、
zh-HK、zh_HK.UTF-8、zh-Hant-HK は zh-HK、汎用の zh と中国本土向けタグは
簡体字中国語(zh)になります。
その場で切り替える — /language パネル。 CLIはもともと別の言語で起動できました
(--lang、LOCKEDIN_LANG)。今度はセッションの途中で切り替えられます。/language
(別名 /lang、/languages)と入力すると、33言語がコード順に、それぞれの文字で一覧表示され、
/language el で残りのセッションの言語が切り替わります。肝は脱出口です。切り替え後はパネルが
新しい言語で描き直され、続けて直前まで使っていた言語で、戻るための正確な方法——いまなら
/language en、次回起動時なら lockedin --lang en——を表示します。うっかり 日本語 や
ಕನ್ನಡ に迷い込んでも取り残されません。(2回切り替えると、LOCKEDIN_LANG が指す言語も
併せて案内されます。)--lang と LOCKEDIN_LANG はこれまでどおりです。/a11y と同じく、
これは真面目な実用機能で、風刺ではありません。
翻訳対象のテキストはすべて、言語ごとのバンドルに入っています。形はこうです。
{ meta: { lang: 'ja', name: '日本語', dir: 'ltr' },
pools: { HOOKS: [ /* 約25個 */ ], LESSONS: [ /* ... */ ], /* ... */ },
ui: { buzzwordDensity: 'バズワード密度:', /* ラベルや見出し */ } }-
poolsは第2章で見たコンテンツの配列(ジョーク本体)です。 -
uiは画面の枠組みにあたる文字列(ラベル、見出し、短いテンプレート)です。
英語は src/lockedin.js 内にある基準バンドルで、他の32個のモジュールは src/content/*.js にあります。
ar, bn, bo, de, el, en-SG, es, eu, fa, fi, fr, he,
hi, id, is, it, ja, kn, ms, nl, no, pl, pt, pt-BR,
ru, sv, tl, tr, uk, ur, zh, zh-HK です
(pt-BR は pt の pools/UI を再利用しますが、個別に登録されます)。
各バンドルは BUNDLES に登録され、SUPPORTED_LANGS はそのキーから作られます。
renderHelp() の --lang コード一覧もこの生成リストを表示するため、ui 側で手書きの一覧を
持つ必要はありません。
setLang('fr'); // 現在の言語をフランス語バンドルに向ける
// L = 現在のpools、U = 現在のui
pick(L.HOOKS) // フランス語のフック
U.buzzwordDensity // "Densité de jargon : "すべてのレンダラーが L と U を読む(文字列を直接埋め込まない)ので、
setLang を呼ぶだけで体験全体が切り替わります。仕掛けはこれだけです。
言語の追加を安全にしてくれる不変条件が、これです。
どのバンドルも、英語とまったく同じ
pools/uiのキーを持つこと。
これは33個すべてのバンドルについてテストで強制されています。英語に新しいUI文字列を足したのに
ウクライナ語で訳し忘れたら、npm test が赤になり、どのキーが足りないかを教えてくれます。
中途半端に翻訳された言語をこっそり出荷することは、そもそもできません。
文字体系によって、ターミナルのレイアウトは別々の壊れ方をします。
-
日本語、簡体字中国語、香港繁体字中国語には East Asian Wide / Fullwidth の文字があります。
vw()はそれらを 2カラムとして数え、wrap()は空白のない長いトークンを強制的に折り返すので、CJKの文字列も カードやボックスからはみ出しません。 -
ヒンディー語とカンナダ語には、マートラーやヴィラーマのような非間隔・囲み結合記号
(
Mn/Me)があります。vw()はこれらを0カラムとして数えるため、表示幅が水増しされません。 -
box()は各行をパディングする前に折り返します。長い翻訳バナーが枠線を突き破ることはありません。 - 各バンドルは
sentenceEndとlistSep(たとえば./。、,/、)を持ち、 ジェネレータが組み立てる文が自然に読めるようにしています。
新しい言語を追加するときも、カードのヘッダー文字列(cardSubtitle、cardMeta、cardFooter)は
表示幅60カラム以下に収める必要があります。アラビア語・ペルシャ語・ヘブライ語・ウルドゥー語は
meta.dir: 'rtl' を設定します。一部のターミナルが制御文字を枠付きラベルとして表示するため、
既定の出力にはbidi制御文字を含めません。対応を確認済みのターミナルでは
LOCKEDIN_BIDI=on により、折り返し後の釣り合ったisolateを明示的に有効化できます。
その場合もANSI、ASCIIコマンド、コピー時の論理順序を維持し、アクセシブル出力では常に
制御文字を除去します。未指定時はRTL/LTR混在順序が単純になる場合がありますが、
対応状況をプローブや推測で決めることはありません。
一部のテンプレートは {cap} のようなプレースホルダーで、ユーザーが入力した生の句を差し込みます。
ここはスロット単位で直訳してはいけません。差し込まれるのは整った名詞とは限らず、ユーザーが書いた
節そのものかもしれないからです。
実際の注意例として、日本語テンプレートで {cap} の直後に は を置くと、{cap} が完全な節だった
場合に不自然になります。解決策は「もっと頑張って訳す」ことではなく、名詞化を入れる、置き場所を変える
など、どんな入力でも文として成立する形にテンプレートを組み替えることです。
本章の演習は、今でも同じやり方で成立します。自分で(あるいはエージェントに頼んで)正しさを確認できる 言語を選び、最後まで通してみましょう。まずは仕様を書きます。
デンマーク語(
da)を追加する。src/content/da.jsを{ meta, pools, ui }バンドルとして作成し、英語と同じキーを持たせ、全項目を翻訳する (コンテンツプールは各約25件、UI文字列はすべて)。src/lockedin.jsのBUNDLESにdaを登録する。--lang daとda-*ロケールで選択できること。カードのヘッダー文字列は 幅の上限を守ること。npm testは緑のままとし、既存のローカライズ済みテストに倣って デンマーク語の不変条件テストと検出テストを追加すること。
あとは第3〜4章のループを回します。
- まず計画。 「コードを書く前に、変更するファイルと、英語とのキーの一致をどう保つかを 教えてください。」
-
まずテスト。 「失敗するテストを追加してください。
daの検出、daのキーの一致、そして デンマーク語の reflect / connect の不変条件です。バンドルはまだ作らないでください。」 -
実装。 「では既存バンドルをキー単位で翻訳して
src/content/da.jsを作り、登録して、 テストを通してください。乱数はpick/shuffleのみです。」 -
ゲートとレビュー。
npm testを回し、lockedin --lang da postを実行し、そして差分を読むこと。 全キーが翻訳されていますか? 罫線はまだ揃っていますか?{cap}を含むテンプレートは、 生のユーザー節を入れても自然ですか?
言語まるごとは重すぎる、という場合の小さめの練習問題もどうぞ。
- 「33個の言語バンドルすべてに
TAGLINEを1つずつ追加し、件数を揃えたままにしてください。」 - 「カンナダ語の
cardFooterが表示幅60カラム以下か確認し、結合記号をどう測ったかも説明してください。」 - 「
ja.jsからuiのキーを1つ削除したときに落ちるテストを見せてください。」
-
src/content/es.jsを眺めてみてください。新しいバンドルの雛形として今でも素直な例です。 -
docs/HANDOFF.mdの「Adding a language」を読み返してみましょう。 - コマンドリファレンス で多言語のジョークもどうぞ。
これでチュートリアルは全章終了です。あなたはもう、AIエージェントに指示して、テストゲートの内側で 機能を作り、さらにそれを多言語化できます。33言語、そしてまだ増やせます。同意する人は👇
Tutorial
- 1 · Orientation
- 2 · How the Code Works
- 3 · Your First Agent Task
- 4 · Prompting & Reviewing
- 5 · Localization
Reference
Satire · Sátira · 風刺. Not affiliated with LinkedIn. GPL-3.0-or-later.