Traducción automática, no revisada por un hablante nativo. El inglés es la referencia.

Primeros pasosAún no está en GitHubFuente: docs/i18n.md

Localización del motor

El texto del motor dirigido a las personas está en 17 idiomas además del inglés: nl, pl, pt-BR, pt-PT, fi, sv, da, nb, cs, uk, ru, de, fr, es, et, ja, zh-Hans. El inglés es la fuente; en-XA es una configuración regional ficticia que acentúa, encierra entre corchetes y rellena cada mensaje, de modo que una prueba pueda ver si el texto pasó al catálogo. El marco es Project Fluent (fluent-bundle, unic-langid); el código es src/i18n/.

Qué se localiza y qué nunca#

Se localiza (lo lee una persona) Nunca se localiza (lo lee un programa)
mensajes y errores de la línea de comandos claves y valores JSON de result.json y report.json
la línea de resumen de cada ejecución encabezados y filas de CSV
el texto de los gráficos SVG (títulos, ejes, leyendas, pies) nombres de archivo
report.html: encabezados, tablas, notas, pies códigos de error (E-CLOCK-VERSION)
palabras de veredicto (VALIDATED, MODELLED, PARTIAL) la matriz de verificación, las definiciones de unidades, la procedencia
las descripciones de los tipos de escenario (list_kinds(lang))
advertencias de carácter consultivo, descargos de responsabilidad y avisos (engine-legal-*) los mismos textos dentro de JSON, que siguen en inglés
report.html de la campaña de iq, la página de comparación de estudios, la clasificación de bench, el informe de resiliencia summary.html de un paquete de evidencias y el PNG del observatorio: ambos se incluyen en un manifiesto mediante hash (el del paquete, además, firmado), por lo que se generan en inglés sea cual sea el idioma

Los números en el texto para personas usan la marca decimal del idioma (una coma en 15 de los 18 idiomas; un punto en en, ja, zh-Hans y en-XA). Los números en los archivos de máquina usan siempre el punto. Un recuento (una variable llamada n, count, n_*, num_* o *_count) llega a Fluent como un número, de modo que una traducción puede escribir { $n -> [one] ... [few] ... *[other] ... }.

Elegir el idioma#

  • Línea de comandos: --lang <tag>, luego KSHANA_LANG, LC_ALL, LC_MESSAGES, LANG, luego inglés. pt es pt-BR; solo pt-PT es el de Portugal. zh es el simplificado; el tradicional se rechaza con la lista de etiquetas admitidas.
  • Biblioteca: api::run_toml_lang(toml, lang), run_toml_bilingual, run_toml_human, run_scenario_lang, list_scenario_kinds_json_lang(lang).
  • Python: lang=None en run, run_full, run_typed, validate_toml, error_kind, list_kinds, scenario_kinds; run_human(toml, lang); error_info(toml, lang).
  • WebAssembly: un lang final opcional en run_typed, run, chart_svg, summary, table_csv, run_all, error_kind, list_kinds, scenario_kinds; run_human(toml, lang); error_info(toml, lang); register_catalogue(tag, ftl_text).
  • MCP: lang en run_scenario y list_scenario_kinds.

Errores y sus códigos#

Cada mensaje de error tiene un código estable, el identificador del mensaje en mayúsculas (e-clock-version es E-CLOCK-VERSION), el mismo en todos los idiomas. El texto de la línea de comandos en inglés no cambia. En otro idioma la línea es text [E-CODE]; con --verbose sigue una segunda línea code: E-CODE en todos los idiomas. La API ofrece KshanaError::code() y error_info ({kind, code, message}); los errores de MCP llevan {kind, code, message} como datos del error. Compare por el código, nunca por el texto.

Cómo funciona una ejecución en otro idioma (la regla de ejecutar dos veces)#

Un archivo de máquina no debe depender del idioma. Por eso una ejecución en otro idioma ejecuta el escenario dos veces: una en inglés, cuyos result.json, report.json y CSV son los archivos de máquina, y otra en el idioma del usuario, para el resumen, el gráfico y report.html. El inglés es una sola ejecución, byte por byte igual a la de antes.

Medido, nativo, compilación de lanzamiento, inglés y luego --lang de (segundos): leo-navmsg-fit-interval-trade 9,2 -> 17,9, cislunar-arc-recovery 7,8 -> 14,1, lunar-station-coverage 7,8 -> 15,0, clock-ensemble 5,8 -> 11,6, leo-navmsg-model-comparison 5,1 -> 10,5, leo-ppp-convergence 2,8 -> 6,2; cada uno de los demás escenarios incluidos tarda menos de 4 s; los 173 escenarios incluidos cuando se midió tardaron 64 s en inglés en conjunto. El coste es exactamente el doble para otro idioma. WebAssembly no se midió (aquí no hay wasm-bindgen); con el factor de navegador de aproximadamente 4 es un minuto para el tipo de escenario más lento.

Una página evita la espera mostrando de inmediato el resultado en inglés y llamando a run_human(toml, lang) después: esa es solo la segunda ejecución, devuelve {summary, svg}, y Studio puede decir «traduciendo...» hasta que llega.

Elemento de 0,41: una sola ejecución. Generar ambas a partir de un registro de (message id, arguments). Se evaluó y no se construyó: los resultados de t! se inspeccionan, se miden y se calculan con hash después de generarse (anchos de texto de los gráficos, hashes de procedencia sobre el texto de salida), y num() da formato en el punto de llamada, de modo que un registro metería marcadores de posición en los archivos de máquina y haría que sus bytes dependieran de la reproducción. Requiere t!/num que devuelvan marcadores, un finalizador en cada escritor y una prueba de identidad byte a byte por escritor.

WebAssembly#

La compilación wasm incorpora solo el catálogo en inglés. Los otros dieciséis añadirían unos 150 kB gzip cada uno. Una página obtiene i18n/<lang>/engine.ftl al elegir un idioma y llama a register_catalogue(tag, text); si falla la obtención o el registro, la página sigue en inglés. En nativo, la línea de comandos y el paquete wheel de Python incorporan los 18.

Tamaño, .wasm sin optimizar de cargo build --release --target wasm32-unknown-unknown --features wasm --lib (antes de wasm-bindgen y wasm-opt), base bc04e98f frente a esta rama: 18,71 MB -> 19,88 MB en bruto, 5,43 MB -> 5,79 MB gzip, +357 kB gzip. El catálogo en inglés ocupa 521 kB en bruto, 153 kB gzip de ellos; el resto es fluent-bundle y sus dependencias. Esto se acepta tal como se midió.

El catálogo#

i18n/<tag>/engine.ftl contiene los mensajes, con identificadores con el prefijo engine-. i18n/en/engine.ftl es la fuente; los demás archivos son de los traductores y pueden carecer de mensajes (cada uno recurre al inglés mensaje por mensaje). Listas complementarias en i18n/en/: engine-counts.txt (mensajes con variables de recuento, para las formas de plural), engine-numbers.txt (números pasados como marcadores), engine-fragments.txt (mensajes que son fragmentos de una frase ensamblada en tiempo de ejecución: se deben fusionar en mensajes de frase completa, nunca aumentar).

Pruebas#

tests/i18n_catalogue.rs prueba el inglés: cada mensaje tiene una plantilla original registrada y se muestra exactamente como ese texto; se usa cada identificador; las variables coinciden; la configuración regional ficticia muestra cada mensaje. i18n_api.rs, i18n_kinds.rs, i18n_legal.rs cubren los puntos de entrada, las descripciones de los tipos de escenario y los textos legales. i18n_ratchet.rs falla si un nuevo literal de cadena que leería una persona elude el catálogo: tolerancia por archivo en tests/fixtures/i18n/allow.json, que puede bajar y nunca subir. scripts/i18n_compare.py ejecuta escenarios completos con un binario de referencia y con el actual, y compara cada archivo de salida.

Cómo mover una cadena al catálogo: docs/design/i18n-migration.md.

Dependencias y licencias#

El marco añade fluent-bundle 0,16 (Apache-2.0 OR MIT) y unic-langid 0,9 (MIT OR Apache-2.0), con sus crates transitivos: fluent-syntax y fluent-langneg (Apache-2.0 OR MIT), intl-memoizer (Apache-2.0 OR MIT), intl_pluralrules (Apache-2.0/MIT), type-map (MIT/Apache-2.0), self_cell (Apache-2.0 OR GPL-2.0-only: se usa la alternativa Apache-2.0, que deny.toml permite), tinystr y zerovec (Unicode-3.0), rustc-hash, smallvec, thiserror, displaydoc (MIT OR Apache-2.0). Todas son permisivas según la lista allow de deny.toml; thiserror aparece en dos versiones (1 y 2), lo que multiple-versions = "warn" solo informa. La lista de licencias se leyó de cargo metadata; cargo deny check no está instalado en el entorno de redacción y se ejecuta en la CI de integración.