Jeden artykuł, 19 języków: struktura plików, prompt tłumaczeniowy, 5 realnych pułapek, jak POST za jednym razem.
Oficjalna dokumentacja Anthropic i OpenAI jest tylko po angielsku. To ogromna luka w globalnym ekosystemie treści dla programistów AI. how2claude tę lukę zasypuje — każdy artykuł wychodzi jednocześnie w 19 językach: zh / en / zh-TW / ja / ko / es / pt-BR / id / vi / tr / ar / fr / de / it / ru / uk / pl / he / th.
Najmowanie tłumaczy nie jest realistyczne (20 tłumaczeń na artykuł, każde po kilka tysięcy dolarów). Oddanie tego Claude sprowadza koszt krańcowy niemal do zera — ale rzucenie przez płot „przetłumacz na japoński" zwraca tekst z wyraźnym posmakiem translatora i zanikłym głosem autora. Poniżej pełny flow na zrobienie tego dobrze: struktura plików, jak napisać prompt tłumaczeniowy, gdzie Claude z pewnością się potknie, jak wysłać 19 języków plus tweety per język do API jednym POST-em.
Dwie zupełnie różne rzeczy.
Tłumaczenie przenosi znaczenie z języka A do B — to, co robi Google Translate. Czyta się „poprawnie", ale „płasko".
Lokalizacja zachowuje rejestr, rytm i poziom techniczny autora, przepisując w „głosie tech-bloga" języka docelowego. Wynik czyta się, jakby napisał to rodzimy użytkownik.
Tłumaczenie dla Claude to robota na 5 minut; lokalizacja wymaga, by prompt doprecyzował:
Polecenie /write-article w how2claude niesie wymóg stylistyczny dla każdego języka:
| Plik języka | Wymóg stylistyczny |
|---|---|
ja.md |
Ton tech-bloga, naturalna japońszczyzna |
ko.md |
Ton tech-bloga, naturalny koreański |
zh-TW.md |
Użycie tajwańskie, znaki tradycyjne |
ar.md |
Współczesny standardowy arabski (pisany) |
id.md |
Standardowy indonezyjski |
Wygląda jak jedna dodatkowa linia. Ale dla Claude decydująca — bez niej domyślnie wychodzi „tłumaczenie podręcznikowe".
Jeden katalog na draft, 20 plików:
docs/drafts/let-claude-translate-articles/
├── meta.json # title + summary dla wszystkich 19 języków
├── zh.md # chiński (źródło, pisany pierwszy)
├── en.md # angielski (pierwsza fala tłumaczeń)
├── zh-TW.md
├── ja.md
├── ko.md
├── ...(kolejne 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",
"pl": "Pozwolić Claude przetłumaczyć jeden artykuł na 19 języków",
"...": "..."
},
"summary": {
"pl": "Jeden artykuł, 19 języków: struktura plików, prompt tłumaczeniowy, 5 realnych pułapek, jak POST za jednym razem.",
"...": "..."
}
}
Pierwsza linia każdego pliku .md to # tytuł, reszta to treść. Title nie jest pobierany z pierwszej linii md — tylko z meta.json, dzięki czemu każdy język ma dopracowany krótki tytuł, a nie pierwsze zdanie artykułu, które przy tłumaczeniu mogło się rozciągnąć.
Dwa błędne flow:
Źle: tłumaczenie łańcuchowe. zh → en → ja → ko → ...
Problem: ja opiera się na en, ko na ja — każdy skok gubi trochę sensu. Przy th (tajskim) to informacja z czwartej ręki.
Dobrze: tłumaczenie promieniste. Zamknąć zh → wygenerować en / ja / ko / ar / id / ... wprost ze źródła.
Każdy język wychodzi bezpośrednio z oryginału, bez przystanków.
Struktura prompta (opakowana w /write-article):
Oto artykuł tech-bloga o X, źródło po chińsku:
[pełne zh.md]
Przetłumacz na następujące języki z wymogami dla każdego:
- ja.md: ton tech-bloga, naturalna japońszczyzna
- ko.md: ton tech-bloga, naturalny koreański
- ar.md: współczesny standardowy arabski (pisany)
...
Reguły:
1. Zachowaj bezpośredni, profesjonalny, lekko autoironiczny rejestr autora
2. Nie tłumacz bloków kodu, poleceń, nazw API, URL-i
3. Nagłówki, podnagłówki, tok akapitów można przekomponować
4. Wygeneruj osobny title per język — krótki, z hakiem, nie dosłowny przekład tytułu oryginału
Tłumaczenie 18 języków równolegle, jedna sesja Claude załatwia sprawę. Ważny szczegół: robić w tej samej sesji / tej samej wersji modelu — głos dryfuje między sesjami i generacjami modelu.
X liczy znaki CJK (chiński/japoński/koreański) surowiej. Poprosiłem Claude, żeby generował tweety z tym ograniczeniem:
Przy pierwszym przebiegu trzy chińskie tweety wyszły poza limit (160, 164, 152). Claude przetłumaczył angielskie tweety dosłownie — angielski tweet na 260 znaków w chińskim wypada dokładnie na granicy.
Reguła: chińskie tweety trzeba przepisywać, nie tłumaczyć. Wymagania: sufit 140 znaków, hak obowiązkowy, utrata części detali dopuszczalna.
zh → zh-TW zaprasza do lenistwa: przepuścić przez konwerter uproszczonych-na-tradycyjne. Znaki się zgadzają, słownictwo nie:
| zh | zh-TW (źle) | zh-TW (dobrze) |
|---|---|---|
| 文件 | 文件 | 檔案 |
| 信息 | 信息 | 資訊 |
| 软件 | 軟件 | 軟體 |
| 视频 | 視頻 | 影片 |
Prosząc Claude o zh-TW, powiedz obie rzeczy: „użycie tajwańskie, znaki tradycyjne". „Tylko tradycyjne" da konwersję znaków.
Arabski i hebrajski czyta się od prawej do lewej. Po stronie Rails potrzeba <html dir="rtl"> i wariantów rtl: Tailwinda. Ale sam przekład też ma pułapki:
unicode-bidi: isolate, inaczej kod zostanie „wciągnięty" w przepływ RTL، zamiast ,, ؟ zamiast ?. Claude domyślnie używa znaków angielskich; trzeba to jasno powiedzieć2026) wewnątrz akapitu płynącego od prawej do lewej. Przeglądarki sobie radzą, ale Claude w surowym tekście często mieszaPotoczne sformułowania z oryginału („załatwić jednym strzałem", „wdepnąć w bagno", „pojechać na bandzie") Claude tłumaczy na japoński/koreański domyślnie formalnymi formami pisanymi (「一気に実装」「落とし穴」「失敗」) — sens się zgadza, ton wyparowuje.
Lek: napisać w promptcie — „zachowaj bezpośredni, lekko autoironiczny, nieformalny ton tech-bloga; bez akademizowania". Nawet wtedy niektóre języki (niemiecki, rosyjski) wylądują ociupinę bardziej „formalnie" niż źródło — same języki mają bias w kierunku rejestru pisanego.
Stringi w kodzie są w dwóch kubłach — tekst UI (tłumaczymy) i placeholdery/nazwy zmiennych (nie):
t("pricing.page_title") # nie tłumaczyć (i18n key)
"user_id" # nie tłumaczyć (nazwa zmiennej)
"Monthly subscription" # pokazywane jako przykład w tekście → nie tłumaczyć
Dla wszystkiego, co graniczy z kodem, „nie tłumaczyć" jest bezpieczniejszym domyślnym. To, co naprawdę trzeba tłumaczyć, to pliki i18n locale (config/locales/xx.yml), i to jest osobna robota.
/publish-article wysyła POST draftu na 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": [...], ... }
}
Jeden request ~300KB (19 języków × ~15KB). Serwer rozkłada na tabele DB:
articles, title / summary / content są jsonb kluczowane po localex_queue_tweets, per locale + konto, wysyłana do kolejki harmonogramuTweety idą tylko do locale z podłączonym kontem X (obecnie en/zh/ja/ko/ar/id — 6). Języki bez konta wysyłają []. Sprawdzanie kont:
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
Pozwolić Claude przetłumaczyć jeden artykuł na 19 języków — pełna checklista:
dir="rtl" + wariantów rtl: Tailwinda po stronie Rails. Mieszana interpunkcja i izolacja bloków kodu — osobna robota.Prawdziwe wąskie gardło to nie jakość tłumaczenia — modele klasy Claude 4 tłumaczą na japoński/koreański/arabski/rosyjski niemal na poziomie native'a. Wąskie gardło to czy jesteś gotów postawić jeden artykuł przed czytelnikami w 19 językach jednocześnie. Technicznie to 5 minut. Od strony contentu — chęć obsłużenia 200× większej publiczności za jednym razem.