Salida en árabe correcta desde el primer intento
Objetivo: Árabe que se renderiza, se lee y se siente nativo desde el primer intento, en cualquier formato de salida.
1. Decide tres cosas antes de escribir nada
| Decisión | Valor por defecto | Cambiar cuando |
|---|---|---|
| Configuración regional de la audiencia | ar + región si se conoce (ar-SA, ar-EG, ar-AE, ar-MA...) | El usuario nombre un país/ciudad/mercado |
| Dígitos | Occidentales 0-9 para UI, precios, teléfonos, código, gráficos. Arábigo-indios ٠-٩ para texto formal/editorial dirigido a Egipto, Arabia Saudita, Irak, el Levante, Sudán, Yemen | El usuario lo solicita, o la marca/región usa claramente ٠-٩. Magreb (MA/DZ/TN) siempre usa 0-9 |
| Registro | Árabe moderno estándar (فصحى), claro y moderno, no clásico | El usuario solicita un dialecto (egipcio, del Golfo, levantino...) o el canal es informal (promociones de WhatsApp, publicaciones en redes sociales): consulta references/writing.md |
Nunca mezcles sistemas de dígitos en una misma pieza de salida.
2. Reglas principales (aplican a todo tipo de salida)
- Declara la dirección en la raíz, una vez. Luego deja que todo herede.
❌
<html>+style="direction:rtl"esparcido en elementos ✅<html lang="ar" dir="rtl">· docx<w:bidi/>+<w:rtl/>· pptxrtl="1"· FlutterDirectionality(textDirection: TextDirection.rtl)/locale: Locale('ar') - Usa direcciones lógicas, nunca izquierda/derecha. "Inicio" es el lado derecho en árabe.
❌
margin-left,ml-4,text-left,left: 0,EdgeInsets.only(left:)✅margin-inline-start,ms-4,text-start,inset-inline-start: 0,EdgeInsetsDirectional.only(start:) - Aísla islas LTR (números de teléfono, correos electrónicos, URLs, código, nombres en inglés junto a números, números negativos).
❌
اتصل على +966 50 123 4567.→ se renderiza como4567 123 50 966+✅اتصل على <bdi dir="ltr">+966 50 123 4567</bdi>.· texto plano: envuelve en LRI…PDI (…) o pon LRMantes de-5 - Los campos de entrada para teléfono, correo electrónico, URL, código, IBAN, contraseñas permanecen
dir="ltr"incluso dentro de un formulario RTL (aliñalos context-end). - Solo refleja iconos direccionales. Las flechas de atrás/adelante, cheurones, enviar, responder, deshacer/rehacer, dirección de progreso se voltean. Los controles de reproducción/pausa, controles multimedia, marcas de verificación, relojes, búsqueda, logotipos, marcas comerciales y números no.
- Tipografía: usa una fuente diseñada para árabe (lista en
references/typography.md), interlineado ≥ 1.6 para texto de cuerpo, y deja espacio arriba y abajo para tashkeel. Nunca apliquesletter-spacing/tracking-*,uppercase,italico alturas ajustadas conoverflow:hiddenal árabe. - Shaping: texto sin procesar a renderizadores que dan forma, texto con forma al resto. Nunca ambos.
Los navegadores, Word, LibreOffice, PowerPoint, WeasyPrint, Chromium PDF, matplotlib ≥ 3.11, Pillow con libraqm, fpdf2 con
set_text_shaping()dan forma al árabe por sí mismos: pasa la cadena sin procesar. reportlab, PyMuPDFinsert_text, OpenCV, matplotlib ≤ 3.10, Pillow sin raqm dibujan glifo por glifo: pasaprepare(text)descripts/shape_text.py. Volver a dar forma a un texto para un renderizador que ya lo hace lo invierte de nuevo (verificado en matplotlib 3.11 y Pillow+raqm). - Puntuación árabe:
،coma,؛punto y coma,؟signo de interrogación,«»comillas. Mantén.y!. No uses espacio antes de la puntuación y un espacio después. - Escribe en árabe de forma nativa, no traduzcas palabra por palabra. Verbos imperativos para botones (
أرسل,احفظ,ابدأ الآن), y sin orden de palabras del inglés. Consultareferences/writing.md. - Formatea números/fechas/moneda con la configuración regional, no con concatenación de cadenas. Usa
Intl.NumberFormat('ar-SA', ...)/Intl.DateTimeFormat('ar-EG-u-nu-latn', ...), y establece siemprenu(dígitos) yca(calendario) explícitamente.
3. Carga la referencia para tu tipo de salida
Lee solo lo que la tarea necesita:
| Salida | Leer |
|---|---|
| HTML, CSS, Tailwind, React, Next.js, Vue, React Native, Flutter, HTML de correo electrónico | references/web.md + references/bidi.md |
| Árabe mixto + inglés/números en cualquier lugar (incl. markdown, texto plano, SMS, cadenas JSON) | references/bidi.md |
| Fuentes, interlineado, tashkeel, pesos, justificación | references/typography.md |
| Word (.docx), PowerPoint (.pptx), PDF | references/documents.md |
| matplotlib, Pillow, SVG, canvas, OpenCV, Plotly, cualquier imagen con texto | references/charts-images.md |
| Redacción, traducción, dialectos, números, fechas, moneda, nombres, Hégira | references/writing.md |
4. Qué se voltea en RTL y qué no
| Se voltea (refleja el diseño) | Permanece igual |
|---|---|
| Orden de lectura, alineación de texto, orden de navegación, lado de la barra lateral | Números de teléfono, tarjetas de crédito, IBANs (siempre LTR) |
Migas de pan, paginación, steppers: "siguiente" apunta a la izquierda. El texto › > ( se voltea automáticamente, pero → y los iconos SVG no | Bloques de código, salida de terminal, URLs, correos electrónicos |
| Flechas de atrás/siguiente, cheurones, dirección de deslizamiento del carrusel/slider | Eje x de gráficos de series temporales (el tiempo corre de izquierda a derecha). Los ejes de categorías pueden voltearse |
| Orden de columnas de tabla (primera columna a la derecha) | Controles multimedia (reproducir ▶, avance rápido), relojes, marcas de verificación |
| Barras de progreso y controles deslizantes se llenan desde la derecha | Logotipos, marcas comerciales, fotos, mapas |
Etiquetas de formulario a la derecha, botón de cerrar × a la izquierda de un diálogo | Expresiones matemáticas y los números mismos (1,234.5 sigue siendo 1,234.5) |
| Lado de deslizamiento de toasts/drawers, insignias en avatares, viñetas de listas | Atajos de teclado (Ctrl+S) |
5. Antes de terminar
- Ejecuta el linter en cualquier código que hayas producido (solo necesita la biblioteca estándar de Python):
python <skill-dir>/scripts/rtl_check.py <archivo-o-carpeta>Corrige cadaerror. Corrige laswarnings a menos que sean intencionales, y marca las intencionales con un comentariortl-ok. - Renderiza y mira cuando puedas, luego verifica que las letras estén conectadas, la primera palabra esté a la derecha, la puntuación esté en el extremo izquierdo y los números se lean en el orden correcto:
- HTML:
python -m playwright screenshot --full-page file://$PWD/index.html shot.png(onpx playwright screenshot …). Si no hay navegador disponible,weasyprint index.html out.pdfda una representación estática. - docx/pptx:
soffice --headless --convert-to pdf file.docx, luego rasteriza el PDF. - PDF → PNG:
python -c "import pymupdf; pymupdf.open('f.pdf')[0].get_pixmap(dpi=110).save('f.png')" - Imágenes/gráficos: abre el PNG que escribiste.
- HTML:
- Si los scripts no pueden ejecutarse (sin Python, sin shell), revisa esta lista de verificación manualmente:
-
dir="rtl"raíz +lang="ar…"(o el equivalente del formato) - sin
left/righten espaciado, posicionamiento o alineación - teléfonos/correos electrónicos/URLs/código aislados y LTR
- iconos direccionales reflejados, otros sin cambios
- fuente árabe cargada, interlineado ≥ 1.6, sin
letter-spacing,italicniuppercase - texto en imágenes/PDF: la ruta de shaping coincide con el renderizador (regla 7)
-
،؛؟usados, un sistema de dígitos, MSA natural (o el dialecto solicitado)
-
Scripts
scripts/rtl_check.py <ruta>: analiza HTML/CSS/Tailwind/JSX/TSX/Vue/Svelte/React Native/Flutter en busca de errores RTL. Imprimearchivo:línea, el problema y la corrección exacta. Código de salida 1 en errores. Solo stdlib.scripts/shape_text.py:prepare(text, target)para renderizadores que no dan forma al árabe. Detecta el soporte nativo de matplotlib/Pillow y devuelve el texto sin cambios cuando no se necesita shaping. Usaarabic-reshaper+python-bidi(instalados con pip bajo demanda) o recurre a un shaper incorporado de stdlib.python shape_text.py --checkinforma lo que esta máquina necesita.