免费

让 Claude 写多语言推文 thread 不超限

多语言 thread 不是翻译问题:用 write 替代 translate,配 .length 本地闸门,一版就近限。


今天发了 5 篇文章。每篇带 6 种语言的推文 thread(en / zh / ja / ko / ar / id),每种语言 4 条,一共 120 条推文。

其中 4 篇都得给中文推文做裁剪。原始数字(script 打印,格式 chars/limit):

zh[1]=160/140 OVER
zh[2]=164/140 OVER
zh[3]=152/140 OVER
...
id[3]=286/280 OVER
zh[2]=163/140 OVER
zh[3]=148/140 OVER
zh[2]=152/140 OVER

每次都是同样的模式:英文四条先写好(每条 230-260 字符,接近 280 的限额),然后让 Claude "基于这四条生成中文版"。结果中文版本基本都超 140。

这事不是 bug,是你对 Claude 说了错词——"翻译"两个字会让它逐句翻,而多语言 thread 不是翻译问题,每种语言都得按自己的限额从头写。本文讲怎么让 Claude 第一版就近限,不用 3-5 轮裁剪。


根本原因:X 对 CJK 加权 × Claude 默认逐句翻

X 的字符计数规则

X 的长度限制不是按"字符数"算,而是按 weighted characters
- 拉丁字母、数字、标点:1 weight 每字符
- CJK 字符(中/日/韩)、某些 emoji:2 weight 每字符
- 推文总上限 280 weight

实际效果:
- 英文推文上限 280 字符
- 纯中文推文上限 140 字符(140 × 2 = 280)
- 中英混排按每字符 1 或 2 算

所以"英文 260 字符翻成中文"不是中文版 260 字——中文版只有 130 字的空间。英文保留的所有标点、引号、代码块 backtick 都还占位,但中文字符每个都 double。翻译出来必然超。

"translate" 这个词触发 Claude 的逐句翻

Claude 看到 "translate these 4 EN tweets to ZH" 时,第一反应是保留英文句子结构,只把字换成中文

  • 英文:"Production 400/500 isn't like local. User's already staring at a blank screen after hitting Pay."
  • Claude 逐句翻:"生产环境的 400/500 和本地并不相同。用户已经点击了『付款』并看着一个空白屏幕。"(40 字)

意思对,但:
- 保留了"并不相同"(比"不同"多一字)
- 保留了"已经点击了"("刚点完"更短)
- 保留了"并看着一个空白屏幕"("看着空白屏"更短)

每一处保留的冗余都占字——积累 4 条,差个 20-40 字轻松,然后就超限了

有效的 prompt:用"重写"替代"翻译"

对比两个措辞:

无效 prompt

"Translate these 4 English tweets to Chinese, Japanese, Korean, Arabic, Indonesian."

有效 prompt

"For each of these 4 points, write a thread in ZH / JA / KO / AR / ID. Each language gets a fresh pass — same argument, adjusted for that language's tweet budget.

  • ZH: ≤ 140 chars per tweet, hook-first, cut detail if needed
  • other languages: ≤ 280 chars
  • use each language's natural phrasing, don't preserve EN sentence structure
  • each tweet must be self-contained but add 🧵 only on tweet 1"

差别:
1. "write" 替代 "translate"——触发 Claude 的创作模式,不是翻译模式
2. "fresh pass" / "same argument"——允许 Claude 重新组织句子
3. "don't preserve EN sentence structure"——直接挡掉默认行为
4. "cut detail if needed"——给它删内容的权限(不给的话它会保留全部事实再超限)
5. 每语言明确限额——数字写死,不是"short"

本地 sanity check:Ruby 脚本 + .length

别依赖肉眼数。写个小脚本每次都跑:

tweets.each do |loc, list|
  list.each_with_index do |t, i|
    len = t.length
    limit = loc == "zh" ? 140 : 280
    status = len > limit ? "OVER" : "ok"
    puts "#{loc}[#{i}]=#{len}/#{limit} #{status}"
  end
end

Ruby String#length 返回 Unicode codepoints——对 CJK 字符每个算 1。X 把 CJK 按 2 weighted char 算,但中文推文限 140 codepoints(因为 140 × 2 = 280 weighted),所以 .length 直接和 X 的限额对齐。误差只来自:
- emoji 的 codepoint 数(🧵 是 1 codepoint,但有些 emoji 由多个 codepoint 组成)
- 零宽字符(ZWJ 等)

绝大多数情况下 Ruby .length 对 CJK 推文 ± 1 字符就和 X 计数一致。用它做前置闸门比上 X 试发靠谱 100 倍。

emoji 和 backtick 坑

中文推文里要省字,两类字符最先砍:

backtick(`

代码引用 `kamal exec` 在中文语境里每个 backtick 吃 1 字——一段代码引用就吃 2 字,还不贡献语义。做法:
- 能用冒号提示的就用冒号:「命令 kamal exec」而不是「`kamal exec`
- 真必要保留 backtick 的地方只给关键标识符,不给整段 shell

emoji

🧵 只在 thread 第一条加。其他 emoji 在中文推文里慎用——每个 emoji 基本占 2 字(1 codepoint + 有时候 ZWJ 修饰符)。

全角 vs 半角标点

  • 中文标点(「」、,。——)一个字符 weighted 2
  • 英文标点("",-)一个字符 weighted 1
  • 推文在中文里混用引号时:用半角引号'X')比全角(「X」)每对省 2 字

Claude 默认走错的 4 方向

让 Claude 生成多语言 thread 时这 4 个要拦:

1. 逐句翻译保留英文结构

症状:中文句子里出现「并不相同」「已经点击了」「一个空白屏幕」这种显然从英文直译过来的表达。

拦法:prompt 里明写 "don't preserve EN sentence structure"、"use natural ZH phrasing"。

2. 不主动做长度计算

症状:Claude 生成完说"done",实际超限但它不知道。

拦法:prompt 要求 Claude 生成完自己数一遍("count each tweet's char length and flag any over the limit"),或者你本地跑 script 作为闸门。我选后者——Claude 自己数不如 Ruby 精确。

3. 引号和 emoji 不计入

症状:Claude 数的时候忽略 emoji 和全角引号的额外 weight。

拦法:不要问 Claude "是否超限"——直接本地算 .length,再根据结果让 Claude 缩。

4. 只在第一条加 🧵(或全加)

症状:有时候 Claude 每条都加 🧵、有时候只加第一条、有时候加在 4/4 结尾。

拦法:prompt 明写"🧵 only on tweet 1"。这件事 Claude 不默认知道 thread 的视觉约定。

清单

让 Claude 第一版就生成近限多语言 thread 的 6 条:

  1. 用 "write" 替代 "translate"。翻译触发逐句翻 = 保留英文结构 = 超限。
  2. 每种语言明确限额:"≤ 140 chars" 比 "short" 有效 100 倍。
  3. 给删内容的权限"cut detail if needed" 让 Claude 知道它可以损失细节去适配长度。
  4. 本地 Ruby .length 做前置闸门。比 Claude 自己数准、比上 X 试发快。
  5. 中文推文里先砍 backtick 和 emoji。每个 backtick 吃 1 字,每个 emoji 吃 2 字。
  6. 🧵 位置要在 prompt 里写死,Claude 不默认知道 thread 视觉约定。

真正的洞见:Claude 能写对多语言 thread,但它默认的反应是"翻译"——你要用 prompt 把它拨到"按每语言独立重写"的模式。加上 .length 闸门后,今天最后一篇的中文推文第一版就是 140/140 整好——不用裁剪。