Un article en 19 langues : structure des fichiers, prompt de traduction, 5 pièges réels, comment POST d'un coup.
La documentation officielle d'Anthropic et d'OpenAI est uniquement en anglais. C'est un trou béant dans l'écosystème mondial de contenu pour développeurs IA. how2claude comble ce trou — chaque article sort simultanément en 19 langues : zh / en / zh-TW / ja / ko / es / pt-BR / id / vi / tr / ar / fr / de / it / ru / uk / pl / he / th.
Recruter des traducteurs humains n'est pas viable (20 traductions par article, plusieurs milliers de dollars chacune). Laisser Claude faire ramène le coût marginal près de zéro — mais balancer un « traduis ça en japonais » par-dessus la barrière renvoie un texte à l'arôme de traduction automatique et dont la voix de l'auteur s'est volatilisée. Ce qui suit, c'est le flux complet pour faire ça correctement : structure des fichiers, comment écrire le prompt de traduction, les endroits où Claude va forcément déraper, comment POST 19 langues plus les tweets par langue à l'API en un seul appel.
Deux choses très différentes.
La traduction déplace le sens de la langue A à la langue B — ce que fait Google Translate. Ça se lit « correct » mais « plat ».
La localisation préserve le registre, le rythme et le niveau technique de l'auteur, en réécrivant dans la « voix de blog technique » propre à la langue cible. Le résultat se lit comme s'il avait été écrit par un natif.
Traduire, c'est 5 minutes de travail pour Claude ; localiser exige que le prompt précise :
La commande /write-article de how2claude embarque une exigence de style par langue :
| Fichier de langue | Exigence de style |
|---|---|
ja.md |
Voix de blog technique, japonais naturel |
ko.md |
Voix de blog technique, coréen naturel |
zh-TW.md |
Usage taïwanais, caractères traditionnels |
ar.md |
Arabe standard moderne (écrit) |
id.md |
Indonésien standard |
Ça ressemble à une ligne de plus. Mais pour Claude, c'est décisif — sans elle, le défaut est « traduction de manuel scolaire ».
Un répertoire par brouillon, 20 fichiers :
docs/drafts/let-claude-translate-articles/
├── meta.json # title + summary pour les 19 langues
├── zh.md # chinois (source, écrit en premier)
├── en.md # anglais (première vague de traductions)
├── zh-TW.md
├── ja.md
├── ko.md
├── ...(14 autres)
└── 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",
"fr": "Laisser Claude traduire un article en 19 langues",
"...": "..."
},
"summary": {
"fr": "Un article en 19 langues : structure des fichiers, prompt de traduction, 5 pièges réels, comment POST d'un coup.",
"...": "..."
}
}
La première ligne de chaque fichier .md est # titre, le reste est le corps. Le title n'est pas extrait de la première ligne du md — il vient de meta.json, de sorte que chaque langue a un titre ciselé court, pas la phrase d'ouverture qui aurait pu s'étirer à la traduction.
Deux flux à éviter :
Faux : traduction en chaîne. zh → en → ja → ko → ...
Problème : ja est basé sur en, ko sur ja — chaque saut fait fuiter un peu de sens. Arrivé à th (thaï), c'est de l'information de quatrième main.
Juste : traduction radiale. Finaliser zh → générer en / ja / ko / ar / id / ... directement depuis la source.
Chaque langue sort directement de l'original, sans relais intermédiaire.
Structure du prompt (empaquetée dans /write-article) :
Voici un article de blog technique sur X, source chinoise :
[zh.md complet]
Traduis dans les langues suivantes, avec les exigences par langue :
- ja.md : voix de blog technique, japonais naturel
- ko.md : voix de blog technique, coréen naturel
- ar.md : arabe standard moderne (écrit)
...
Règles :
1. Préserve le registre direct, professionnel, légèrement autodérisoire de l'auteur
2. Ne traduis pas les blocs de code, commandes, noms d'API, URL
3. Titres, sous-titres, flux des paragraphes peuvent être recomposés
4. Produis un title séparé par langue — court, avec une accroche, pas la traduction littérale du titre original
Traduire 18 langues en parallèle, une session Claude suffit. Détail clé : le faire dans la même session / la même version de modèle — la voix dérive entre sessions et entre générations de modèle.
X compte les caractères CJK (chinois/japonais/coréen) plus strictement. J'ai demandé à Claude de générer des tweets avec cette contrainte :
Au premier jet, trois tweets chinois dépassaient (160, 164, 152). Claude avait traduit les tweets anglais littéralement — un tweet anglais à 260 caractères devient chinois pile à la limite.
Règle : les tweets chinois doivent être réécrits, pas traduits. Exigences : plafond 140 caractères, accroche obligatoire, perte de détail tolérée.
zh → zh-TW, c'est la paresse facile : passer par un convertisseur simplifié-vers-traditionnel. Les caractères correspondent, le vocabulaire non :
| zh | zh-TW (faux) | zh-TW (juste) |
|---|---|---|
| 文件 | 文件 | 檔案 |
| 信息 | 信息 | 資訊 |
| 软件 | 軟件 | 軟體 |
| 视频 | 視頻 | 影片 |
Quand on demande zh-TW à Claude, il faut dire les deux : « usage taïwanais, caractères traditionnels ». « Traditionnel seulement » donne une conversion de caractères.
L'arabe et l'hébreu se lisent de droite à gauche. Côté Rails, il faut <html dir="rtl"> et les variantes rtl: de Tailwind. Mais la traduction elle-même a des pièges :
unicode-bidi: isolate, sinon le code est « aspiré » dans le flux RTL، à la place de ,, ؟ à la place de ?. Claude utilise la ponctuation anglaise par défaut ; il faut l'expliciter2026) à l'intérieur d'un paragraphe de droite à gauche. Les navigateurs gèrent, mais Claude s'emmêle souvent en écrivant du texte brutLes tournures familières de l'original (« tout balancer d'un coup », « poser le pied dedans », « se prendre le mur ») Claude les traduit en japonais/coréen dans des formes écrites formelles (「一気に実装」「落とし穴」「失敗」) — le sens est là, le ton s'évapore.
Correctif : l'écrire dans le prompt — « préserve la voix de blog technique directe, légèrement autodérisoire, informelle ; ne pas académiser ». Même comme ça, certaines langues (allemand, russe) atterriront un cran plus « formelles » que la source — les langues elles-mêmes ont un biais vers le registre écrit.
Les chaînes dans le code sont dans deux seaux — texte UI (on traduit) et placeholders/noms de variables (non) :
t("pricing.page_title") # ne pas traduire (i18n key)
"user_id" # ne pas traduire (nom de variable)
"Monthly subscription" # affiché comme exemple dans le texte → ne pas traduire
Pour tout ce qui est adjacent au code, « ne pas traduire » est le défaut le plus sûr. Ce qui se traduit vraiment, ce sont les fichiers de locale i18n (config/locales/xx.yml), c'est un autre travail.
/publish-article POST le brouillon sur how2claude.com/api/articles :
{
"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": [...], ... }
}
Une requête fait ~300KB (19 langues × ~15KB). Le serveur éclate vers les tables :
articles, title / summary / content sont des jsonb indexés par localex_queue_tweets, par locale + compte, dispatché dans une file de planificationLes tweets ne partent qu'aux locales avec compte X connecté (actuellement en/zh/ja/ko/ar/id — 6). Les langues sans compte envoient []. Interroger les comptes :
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
Laisser Claude traduire un article en 19 langues — checklist complète :
dir="rtl" + variantes rtl: de Tailwind côté Rails. Ponctuation mixte et isolement des blocs de code se traitent séparément.Le vrai goulet n'est pas la qualité de traduction — les modèles de classe Claude 4 traduisent vers le japonais/coréen/arabe/russe à un niveau quasi natif. Le goulet, c'est si vous êtes prêt à mettre un article devant des lecteurs en 19 langues. Techniquement, ça prend 5 minutes. Sur le plan du contenu, il faut une volonté de servir 200× l'audience d'un coup.