Free

Bảo Claude viết thread tweet đa ngôn ngữ không vượt giới hạn

Thread đa ngôn ngữ không phải bài toán dịch: nói 'write' thay vì 'translate', và chặn bản nháp bằng script .length cục bộ.


Hôm nay đăng 5 bài. Mỗi bài có thread tweet 6 ngôn ngữ (en / zh / ja / ko / ar / id), mỗi ngôn ngữ 4 tweet — tổng 120 tweet.

4/5 bài phải cắt bớt thread tiếng Trung. Số liệu gốc (script in ra, định dạng 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

Cùng một kịch bản mỗi lần: viết 4 tweet tiếng Anh trước (mỗi tweet 230–260 ký tự, sát trần 280), rồi bảo Claude "tạo bản tiếng Trung từ bốn tweet này". Bản tiếng Trung gần như luôn vượt 140.

Không phải bug, mà là sai từ khóa. Ngay khi bạn nói "translate", Claude chuyển sang dịch câu-theo-câu — nhưng thread đa ngôn ngữ không phải bài toán dịch. Mỗi ngôn ngữ phải viết mới từ đầu theo ngân sách ký tự riêng của nó. Bài này nói về cách để bản nháp đầu tiên của Claude đã sát giới hạn, không phải cắt gọt 3–5 vòng.


Nguyên nhân gốc: X tính CJK gấp đôi × Claude mặc định dịch sát câu

Quy tắc đếm ký tự của X

Giới hạn độ dài của X không tính theo "số ký tự", mà theo weighted characters:
- Chữ Latin, chữ số, dấu câu: 1 weight mỗi ký tự
- CJK (Trung/Nhật/Hàn), một số emoji: 2 weight mỗi ký tự
- Trần tổng mỗi tweet: 280 weight

Hiệu ứng thực tế:
- Tweet tiếng Anh: trần 280 ký tự
- Tweet thuần tiếng Trung: trần 140 ký tự (140 × 2 = 280)
- Trộn lẫn: mỗi ký tự tính 1 hoặc 2

Nên "dịch tweet tiếng Anh 260 ký tự sang tiếng Trung" không có nghĩa bản tiếng Trung 260 ký tự — bản tiếng Trung chỉ có khoảng 130 ký tự thực. Mọi dấu câu, ngoặc kép, backtick trong bản Anh vẫn chiếm chỗ, và mỗi ký tự Trung tính gấp đôi. Dịch sát gần như chắc chắn tràn.

Từ "translate" kích hoạt chế độ dịch sát của Claude

Khi Claude thấy "translate these 4 EN tweets to ZH", nước đi đầu tiên của nó là giữ nguyên cấu trúc câu tiếng Anh và chỉ đổi từ sang tiếng Trung:

  • EN: "Production 400/500 isn't like local. User's already staring at a blank screen after hitting Pay."
  • ZH dịch sát của Claude: "生产环境的 400/500 和本地并不相同。用户已经点击了『付款』并看着一个空白屏幕。" (40 ký tự Trung)

Ý nghĩa đúng, nhưng:
- Giữ "并不相同" (dài hơn "不同" một ký tự)
- Giữ "已经点击了" ("刚点完" ngắn hơn)
- Giữ "并看着一个空白屏幕" ("看着空白屏" ngắn hơn)

Mỗi sự dư thừa được giữ lại đều ngốn ký tự. Tích lũy qua 4 tweet, thừa 20–40 ký tự là chuyện bình thường, và đã vượt giới hạn.

Prompt có hiệu quả: "viết lại" thay vì "dịch"

So sánh hai cách diễn đạt:

Không hiệu quả:

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

Hiệu quả:

"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"

Khác biệt:

  1. "write" thay "translate" — kích hoạt chế độ sáng tác của Claude, không phải chế độ dịch.
  2. "fresh pass" / "same argument" — cho phép Claude tổ chức lại câu.
  3. "don't preserve EN sentence structure" — chặn thẳng hành vi mặc định.
  4. "cut detail if needed" — cho quyền bỏ nội dung để vừa độ dài (không có thì Claude giữ mọi sự kiện và tràn).
  5. Ngân sách tường minh mỗi ngôn ngữ — "≤ 140 chars" hiệu quả hơn "short" 100 lần.

Sanity check tại chỗ: Ruby + .length

Đừng đếm bằng mắt. Viết một script nhỏ chạy mọi bản nháp:

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

String#length của Ruby trả về số codepoint Unicode — mỗi ký tự CJK tính là 1. X tính CJK theo weight 2, nhưng giới hạn tweet tiếng Trung là 140 codepoint (vì 140 × 2 = 280 weighted), nên .length trực tiếp trùng với trần của X. Các trường hợp biên:

  • Số codepoint của emoji (🧵 là 1 codepoint, nhưng một số emoji là chuỗi nhiều codepoint)
  • Ký tự độ rộng 0 (ZWJ v.v.)

Với đại đa số tweet CJK, .length của Ruby sai lệch ±1 so với X. Dùng nó làm cổng chặn tại chỗ hiệu quả hơn thử đăng lên X 100 lần.

Bẫy emoji và backtick

Khi tweet tiếng Trung phải cắt, hai nhóm này bị gọt đầu tiên:

Backtick

Trích dẫn code như `kamal exec` ngốn 1 ký tự mỗi backtick trong tiếng Trung — 2 ký tự mỗi trích dẫn, không đóng góp nghĩa. Cách xử lý:

  • Dùng dấu hai chấm: "命令 kamal exec" ngắn hơn "`kamal exec`"
  • Nếu thực sự phải giữ backtick, chỉ cho định danh then chốt, không phải cả dòng shell

Emoji

🧵 chỉ ở tweet đầu. Các emoji khác trong tweet tiếng Trung — cân nhắc kỹ. Mỗi emoji cơ bản ngốn 2 ký tự (1 codepoint + đôi khi modifier ZWJ).

Dấu câu fullwidth vs halfwidth

  • Dấu câu CJK (「」、,。——): 2 weight mỗi ký tự
  • Dấu câu ASCII ("",-): 1 weight mỗi ký tự
  • Khi tweet tiếng Trung trộn ngoặc kép: dùng ngoặc halfwidth ('X') — tiết kiệm 2 ký tự mỗi cặp so với fullwidth (「X」)

Bốn hướng mặc định sai của Claude cần chặn

Khi sinh thread đa ngôn ngữ, chặn bốn điều này:

1. Dịch sát giữ cấu trúc EN

Triệu chứng: câu tiếng Trung xuất hiện cụm như "并不相同", "已经点击了", "一个空白屏幕" — rõ ràng dịch thẳng từ tiếng Anh.

Chặn: viết "don't preserve EN sentence structure" / "use natural ZH phrasing" trực tiếp trong prompt.

2. Không chủ động kiểm tra độ dài

Triệu chứng: Claude nói "done" sau khi sinh, đầu ra vượt giới hạn, mà Claude không biết.

Chặn: yêu cầu Claude tự đếm độ dài từng tweet ("count each tweet's char length and flag any over the limit"), hoặc chạy script tại chỗ làm cổng chặn. Tôi chọn script — Ruby chính xác hơn Claude.

3. Bỏ qua weight của ngoặc kép và emoji

Triệu chứng: khi Claude đếm, nó quên weight thêm của emoji và ngoặc fullwidth.

Chặn: đừng hỏi Claude "có vượt giới hạn không?" — chạy .length tại chỗ rồi dựa trên số bắt Claude rút gọn.

4. Vị trí 🧵 không nhất quán

Triệu chứng: lúc thì mỗi tweet đều có 🧵, lúc chỉ tweet 1, lúc rơi ở tweet 4/4.

Chặn: khóa trong prompt — "🧵 only on tweet 1". Claude mặc định không biết quy ước hình ảnh của thread.

Checklist

Sáu quy tắc để có bản nháp đầu đa ngôn ngữ sát giới hạn:

  1. Nói "write", không "translate". Dịch kích hoạt dịch sát = giữ cấu trúc EN = tràn.
  2. Ngân sách tường minh mỗi ngôn ngữ. "≤ 140 chars" hơn "short" 100 lần.
  3. Quyền cắt nội dung. "cut detail if needed" báo Claude được phép mất sự kiện để vừa độ dài.
  4. Ruby .length tại chỗ làm cổng. Chính xác hơn Claude tự đếm, nhanh hơn thử đăng lên X.
  5. Trong tiếng Trung, cắt backtick và emoji trước. Mỗi backtick 1 ký tự, mỗi emoji 2 ký tự.
  6. Khóa vị trí 🧵 trong prompt. Claude mặc định không biết quy ước thread.

Insight thực sự: Claude viết được thread đa ngôn ngữ đúng — nhưng phản xạ mặc định của nó là "dịch". Việc của bạn là xoay nó sang "sáng tác độc lập mỗi ngôn ngữ" qua prompt. Thêm cổng .length, thread tiếng Trung của bài cuối hôm nay bản nháp đầu đã 140/140 khít — không cần cắt.