Free

Hacer que Claude escriba threads de tweets multilingües sin pasarse del límite

Los threads multilingües no son un problema de traducción: di 'write', no 'translate', y filtra los borradores con un script .length local.


Hoy publiqué 5 artículos. Cada uno lleva un thread de tweets en 6 idiomas (en / zh / ja / ko / ar / id), 4 tweets por idioma — 120 tweets en total.

4 de 5 necesitaron recortar el thread en chino. Los números crudos (impresos por mi script, formato 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

Siempre el mismo patrón: se escriben primero los cuatro tweets en inglés (cada uno de 230–260 caracteres, rozando el techo de 280) y luego le pido a Claude que "genere la versión china a partir de estos cuatro". La versión china casi siempre pasa de 140.

No es un bug, es la palabra equivocada. En cuanto dices "translate", Claude empieza a ir línea por línea — pero un thread multilingüe no es un problema de traducción. Cada idioma hay que escribirlo desde cero contra su propio presupuesto de caracteres. Este post trata de cómo conseguir que el primer borrador de Claude ya esté cerca del límite, sin gastar 3–5 rondas recortando.


Causa raíz: X pesa doble el CJK × Claude tiende por defecto a traducir literal

Cómo cuenta caracteres X

El límite de X no es "número de caracteres", es weighted characters:
- Letras latinas, dígitos, puntuación: 1 weight por carácter
- CJK (chino/japonés/coreano), algunos emojis: 2 weight por carácter
- Tope total por tweet: 280 weight

Efecto práctico:
- Tweet en inglés: 280 caracteres
- Tweet puro en chino: 140 caracteres (140 × 2 = 280)
- Mezclado: cada carácter suma 1 o 2

Así que "traducir un tweet inglés de 260 caracteres al chino" no te da una versión china de 260 caracteres — la versión china tiene unos 130 caracteres reales de espacio. Toda la puntuación, comillas y backticks del original inglés siguen ocupando lugar, y cada carácter chino cuenta doble. Traducir literal casi garantiza el desborde.

La palabra "translate" enciende el modo literal de Claude

Cuando Claude ve "translate these 4 EN tweets to ZH", su primer movimiento es preservar la estructura de la frase inglesa y sólo cambiar las palabras:

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

El significado es correcto, pero:
- Preserva "并不相同" (un carácter más que "不同")
- Preserva "已经点击了" ("刚点完" es más corto)
- Preserva "并看着一个空白屏幕" ("看着空白屏" es más corto)

Cada redundancia preservada se come caracteres. Acumulado en 4 tweets, son 20–40 caracteres de más fácil, y ya estás pasado del límite.

El prompt que funciona: "reescribir", no "traducir"

Compara las dos formulaciones:

Lo que no funciona:

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

Lo que sí:

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

Las diferencias:

  1. "write" reemplaza a "translate" — activa el modo composición de Claude, no el modo traducción.
  2. "fresh pass" / "same argument" — da permiso a Claude para reordenar las frases.
  3. "don't preserve EN sentence structure" — bloquea de frente el comportamiento por defecto.
  4. "cut detail if needed" — le da permiso para soltar contenido por longitud (sin eso conserva todos los hechos y se pasa).
  5. Presupuesto explícito por idioma — "≤ 140 chars" es 100 veces más efectivo que "short".

Verificación local: Ruby + .length

No cuentes a ojo. Escribe un script pequeño que corra en cada borrador:

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 en Ruby devuelve codepoints Unicode — cada carácter CJK cuenta como 1. X pesa CJK al doble, pero el límite de un tweet en chino es 140 codepoints (porque 140 × 2 = 280 weighted), así que .length se alinea directamente con el tope de X. Las excepciones:

  • Cuenta de codepoints de emojis (🧵 es 1 codepoint, pero algunos emojis son secuencias de varios)
  • Caracteres de ancho cero (ZWJ, etc.)

Para la gran mayoría de tweets CJK, .length de Ruby queda a ±1 del recuento de X. Usarlo como compuerta local supera por 100× a probar publicando en X.

Trampas de emojis y backticks

Cuando hay que recortar un tweet chino, estas dos categorías caen primero:

Backticks

Citas de código como `kamal exec` se comen 1 carácter por backtick en un tweet en chino — 2 caracteres por referencia, cero valor semántico. Soluciones:

  • Usa dos puntos: "命令 kamal exec" es más corto que "`kamal exec`"
  • Si tienes que conservar backticks, sólo para el identificador clave, no para la línea de shell completa

Emojis

🧵 sólo en el tweet 1. Los demás emojis en tweets chinos — piénsalo dos veces. Cada emoji básicamente cuesta 2 caracteres (1 codepoint + en algunos casos modificadores ZWJ).

Puntuación de ancho completo vs. mitad

  • Puntuación CJK (「」、,。——): 2 weight cada una
  • Puntuación ASCII ("",-): 1 weight cada una
  • Cuando un tweet chino mezcla comillas: usa comillas de mitad ('X') — ahorra 2 caracteres por par frente a las de ancho completo (「X」)

Cuatro sesgos por defecto de Claude que hay que interceptar

Al generar threads multilingües bloquea estos cuatro:

1. Traducción literal preservando la estructura EN

Síntoma: frases chinas con expresiones como "并不相同", "已经点击了", "一个空白屏幕" que son calcos obvios del inglés.

Bloqueo: escribe "don't preserve EN sentence structure" / "use natural ZH phrasing" directamente en el prompt.

2. No comprueba longitud por iniciativa propia

Síntoma: Claude termina y dice "done", el output pasa del límite, y él no lo nota.

Bloqueo: pídele a Claude que cuente la longitud de cada tweet ("count each tweet's char length and flag any over the limit"), o mete un script local como compuerta. Yo elijo el script — Ruby le gana a Claude contando.

3. Ignorar el weight de comillas y emojis

Síntoma: cuando Claude cuenta, se olvida del weight extra de emojis y comillas de ancho completo.

Bloqueo: no le preguntes "¿pasa del límite?" — corre .length local y con los números pídele que recorte.

4. Inconsistencia en la posición del 🧵

Síntoma: a veces pone 🧵 en cada tweet, a veces sólo en el 1, a veces aterriza en el 4/4.

Bloqueo: fíjalo en el prompt — "🧵 only on tweet 1". Claude no conoce por defecto las convenciones visuales de un thread.

Checklist

Seis reglas para conseguir un primer borrador multilingüe al límite:

  1. Di "write", no "translate". Traducir activa el modo literal = estructura EN preservada = se pasa.
  2. Presupuesto explícito por idioma. "≤ 140 chars" pesa 100× más que "short".
  3. Permiso para cortar contenido. "cut detail if needed" le dice a Claude que puede perder hechos para caber.
  4. Ruby .length local como compuerta. Más preciso que la cuenta de Claude, más rápido que probar en X.
  5. En chino, quita primero backticks y emojis. Cada backtick come 1 carácter, cada emoji come 2.
  6. Fija la posición del 🧵 en el prompt. Claude no sabe por defecto las convenciones de thread.

La verdadera idea: Claude puede escribir bien threads multilingües — pero su reacción por defecto es "traducir". Tu trabajo es cambiarlo a "componer independientemente por idioma" vía prompt. Con la compuerta de .length, el thread chino del último artículo de hoy salió 140/140 al primer borrador. Sin recortes.