Free

Claude に 1 本の記事を 19 言語に翻訳させる

1 本 19 言語:ファイル構成、翻訳 prompt、5 つの実戦的落とし穴、1 回 POST のやり方。


Anthropic と OpenAI の公式ドキュメントは英語のみ。これは世界の AI 開発者向けコンテンツエコシステムにおける大きな空白だ。how2claude はまさにこの空白を埋めにいく——毎記事を 19 言語同時配信:zh / en / zh-TW / ja / ko / es / pt-BR / id / vi / tr / ar / fr / de / it / ru / uk / pl / he / th。

人力では現実的じゃない(1 記事につき 20 人分の訳、1 本数千ドル)。Claude にやらせれば限界コストはほぼゼロ——ただし「ja に翻訳して」と投げるだけだと機械翻訳臭プンプンで著者の声が消えた原稿が返ってくる。本稿はこれを正しくやる完全フロー:ファイル構成、翻訳 prompt の書き方、Claude が必ず外すポイント、19 言語+言語別ツイートを 1 回の POST で API に送る方法。


核心判断:翻訳 vs ローカライゼーション

この 2 語は大きく違う。

翻訳は A 言語の意味を B 言語に移すこと——Google Translate がやることだ。読んで「正しい」、でも「平板」。

ローカライゼーションは原文の語調、リズム、専門性を保ちつつ、対象言語読者の「技術ブログ語調」で書き直すこと。結果はネイティブが書いたように読める。

Claude に翻訳させるのは 5 分の仕事、ローカライゼーションは prompt で次を明示する必要がある:

  • 対象読者(開発者、技術チーム)
  • 語調リファレンス(どのブログに近いか)
  • 原文保持すべき語(API 名、フレームワーク名、コマンド、URL)
  • 再構成を許す箇所(長文を短く割る、比喩を対象言語読者に馴染むものに置き換える)

how2claude の /write-article コマンドは各言語にスタイル要件を埋め込んである:

言語ファイル スタイル要件
ja.md 技術ブログ語調、自然な日本語
ko.md 技術ブログ語調、自然な韓国語
zh-TW.md 台湾の言い回し、繁体字
ar.md 標準アラビア語(現代書面語)
id.md 標準インドネシア語

1 行の差に見えるが、Claude にとっては決定的——これが無いとデフォルトで「教科書訳」を生成する。

ファイル構成:19 言語が 1 ディレクトリに同居

草稿 1 本につきディレクトリ 1 つ、20 ファイル:

docs/drafts/let-claude-translate-articles/
├── meta.json        # 全 19 言語の title + summary
├── zh.md            # 中国語(原文、最初に執筆)
├── en.md            # 英語(第一陣の翻訳)
├── zh-TW.md
├── ja.md
├── ko.md
├── ...(あと 14)
└── th.md

meta.json

{
  "category_slug": "use-cases",
  "series_slug": "writing",
  "free": true,
  "title": {
    "zh": "让 Claude 把一篇文章翻译成 19 种语言",
    "en": "Letting Claude Translate One Article Into 19 Languages",
    "ja": "Claude に 1 本の記事を 19 言語に翻訳させる",
    "...": "..."
  },
  "summary": {
    "ja": "1 本 19 言語:ファイル構成、翻訳 prompt、5 つの実戦的落とし穴、1 回 POST のやり方。",
    "...": "..."
  }
}

.md ファイルの 1 行目は # タイトル、以降本文。title は md の 1 行目から取らず meta.json から取る——こうすることで各言語の title は専用に磨かれた短文になり、記事冒頭で間延びしたタイトル文にならない。

フロー:zh を書いたら 18 言語に放射する

間違いがちなフロー 2 種:

誤:連鎖翻訳。zh → en → ja → ko → ...
問題:ja は en ベース、ko は ja ベース、1 跳ごとに原意が少しずつ漏れる。th(タイ語)に着く頃には 4 次情報だ。

正:放射翻訳。zh を完成させる → zh から直接 en / ja / ko / ar / id / ... を一斉生成。
全言語が原文から直接生成、中継地点なし。

具体的な prompt 構造(/write-article にパッケージ化済み):

これは X についての技術ブログ記事、中国語原文:
[zh.md 全文]

以下の言語に翻訳、言語別要件:
- ja.md: 技術ブログ語調、自然な日本語
- ko.md: 技術ブログ語調、自然な韓国語
- ar.md: 標準アラビア語(現代書面語)
...

要件:
1. 著者の直接的、専門的、やや自嘲的な語調を保持
2. コードブロック、コマンド、API 名、URL は翻訳しない
3. 見出し、小見出し、段落構成は再構成可
4. title は別出し、短く、フック付き、原題の直訳ではない

18 言語を並行翻訳、Claude 1 セッションで片付く。重要なのは 1 点:同一セッション/同一モデルバージョンでやる——セッション跨ぎやモデル跨ぎで voice がドリフトする。

5 つの実戦的落とし穴

1. ツイート文字数制限は言語で違う

X は CJK(中・日・韓)文字により厳しい計数をかける。Claude にツイート生成させた時こう指定した:

  • 中国語ツイート ≤ 140 字
  • その他 ≤ 280 文字

初回生成で中国語ツイート 3 本が超過(160、164、152 字)。Claude が英語ツイートを直訳したため——英語 260 文字を中国語に訳すとちょうど限界に当たる。

法則:中国語ツイートは翻訳ではなく書き直し。要件:140 字上限、フック必須、細部の欠落は許容。

2. 繁体中国語は文字変換ではない

zhzh-TW で手抜きしがち:簡体→繁体変換ツールに通す。字は合うが語彙が合わない:

zh zh-TW(誤) zh-TW(正)
文件 文件 檔案
信息 信息 資訊
软件 軟件 軟體
视频 視頻 影片

Claude に zh-TW を頼む時は両方言う:「台湾の言い回し、繁体字」。「繁体字だけ」だと文字変換しか返らない。

3. RTL 言語(ar、he)はレイアウトで外す

アラビア語、ヘブライ語は右から左に書く。Rails 側は <html dir="rtl">、Tailwind は rtl: variants。ただし翻訳自体にも落とし穴:

  • コードブロック内の英語は翻訳しないが、アラビア語段落がコードブロックを囲む時、ブラウザに unicode-bidi: isolate を入れないとコードが RTL 方向に「吸われる」
  • 句読点混在:アラビア語は , の代わりに ،? の代わりに ؟ を使う。Claude はデフォルトで英語記号を使うので明示指定が要る
  • 数字の向き:アラビア語で数字は左から右(2026)、段落全体の流れは右から左。ブラウザが処理してくれるが、Claude が生のテキストを書く時によく混乱する

4. Claude はデフォルトで著者の声を「重厚化」する

原文の口語表現("一把梭"、"踩坑"、"翻车")を Claude は日本語韓国語でデフォルトで書面表現(「一気に実装」「落とし穴」「失敗」)に訳す——意味は合うが著者の語調が消える。

修正法:prompt に明記——「原文の直接的、やや自嘲的、くだけた技術ブログ語調を保持、学術化しない」。それでも一部の言語(ドイツ語、ロシア語)は原文よりやや「フォーマル」に着地する——言語自体が書面バイアスを持つ。

5. プレースホルダと変数は翻訳しない

コード内の文字列は 2 種——UI テキスト(翻訳する)とプレースホルダ/変数名(翻訳しない):

t("pricing.page_title")        # 翻訳しない(i18n key)
"user_id"                      # 翻訳しない(変数名)
"Monthly subscription"         # 文中で読者に例示する場合 → 翻訳しない

コード隣接の文字列は「翻訳しない」をデフォルトにしておくと安全。本当に翻訳すべきは i18n locale ファイル(config/locales/xx.yml)、あれは別件だ。

配信:19 言語を 1 回の POST で

/publish-article は草稿を how2claude.com/api/articles に POST する:

{
  "category_slug": "use-cases",
  "series_slug": "writing",
  "free": true,
  "thread": true,
  "title":   { "zh": "...", "en": "...", "ja": "...", ... },
  "summary": { "zh": "...", "en": "...", ... },
  "content": { "zh": "<md>", "en": "<md>", ... },
  "tweets":  { "en": ["...", "..."], "zh": [...], ... }
}

1 リクエスト約 300KB(19 言語 × 約 15KB)。サーバ側で DB に分解:

  • articles テーブル、title / summary / content は jsonb、locale キー
  • x_queue_tweets テーブル、locale + account で分配、配信キューに投入

ツイートは X アカウントが連携済みの locale のみに投げる(現在 en/zh/ja/ko/ar/id の 6 つ)、未連携言語は tweets に [] を送る。アカウント確認:

Account.all.each { |a| puts "#{a.locale}: #{a.name}" }
# en: @how2claude
# zh: @howtoclaude
# ja: @how2claude_ja
# ko: @how2claude_ko
# ar: @how2claude_ar
# id: @how2claude_id

チェックリスト

Claude に 1 本の記事を 19 言語翻訳させる完全チェックリスト:

  1. zh(または en)を先に完成、それを元に他 18 言語を放射翻訳——連鎖させない。
  2. 言語別スタイル要件を prompt に入れる:「自然な日本語」では足りない、「技術ブログ語調、自然な日本語」と言う。
  3. title と summary は別翻訳、本文冒頭から抜かない。meta.json で全 19 言語の title/summary を集約管理。
  4. 翻訳しないものを明示列挙:コードブロック、コマンド、API 名、URL、i18n key、変数名。翻訳するのは説明文、比喩、段落構成。
  5. ツイートは翻訳ではなく書き直し。中国語 140 字、他言語 280 文字。英語直訳は常に制限超過。
  6. 繁体中国語は「台湾の言い回し+繁体字」と言う、でないと文字変換だけで語彙が大陸寄りのまま。
  7. RTL 言語(ar、he)は Rails 側で dir="rtl" + Tailwind rtl: variants。句読点混在とコードブロック分離は別途処理。
  8. 全言語 1 回の POST——19 content + 19 title/summary + 各連携アカウントのツイート、1 リクエストでバックエンドに送る。

本当のボトルネックは翻訳品質ではない——Claude 4 級モデルは日本語・韓国語・アラビア語・ロシア語への翻訳品質がネイティブに近い。ボトルネックは1 本の記事を 19 言語の読者の前に出す覚悟があるかどうか。技術的には 5 分で終わる。コンテンツ的には、200 倍の読者に同時に届ける意思が要るだけだ。