Saltar al contenido
Saltar al contenido

Referencia / Configuración

Página traducida automáticamente

Esta página se tradujo automáticamente, así que puede contener errores o sonar un poco rara. La versión en inglés es la fuente de la verdad. Leer el original en inglés.

Formatos

Todos los formatos de archivo i18n que admite verbatra, cómo lee y escribe sus archivos cada uno y qué conserva una escritura para que los diffs queden limpios.

Un adaptador de formato lee un archivo de locale en una forma neutral y lo escribe de vuelta con la forma propia del archivo. Pon en la clave format de tu configuración uno de estos ids:

formatArchivosPlaceholdersPluralesArchivo de destino ausenteSintaxis de placeholder nativa
i18next-jsonJSON de i18next (.json){{name}}, $t(...)sufijo CLDR en la clavese crea{{name}}
vue-i18n-jsonJSON de vue-i18n (.json){name}, {0}pipe en el valorse crea{name}, %{name}, ${name}
next-intl-jsonJSON de next-intl (.json)argumentos y etiquetas ICUplural, selectordinal de ICUse crea{name}, %{name}, ${name}
ngx-translate-jsonJSON de ngx-translate (.json){{name}}ningunose crea{{name}}
xliffXLIFF 1.2 y 2.0 (.xlf, .xliff)elementos en línea, {...}ningunose rechaza{{name}}, {name}, %{name}, ${name}
yamlYAML (.yml, .yaml){{name}}ningunose crea{{name}}
arbARB de Flutter (.arb)argumentos y etiquetas ICUplural, selectordinal de ICUse crea{name}, %{name}, ${name}
propertiesproperties de Java/Spring (.properties)MessageFormat {0}, {count}ningunose crea{name}, %{name}, ${name}
apple-strings.strings de Apple, con su .stringsdictprintf %@, %dcategorías de .stringsdictse creaprintf %s
apple-xcstringsXcode String Catalogs (.xcstrings)printf %@, %lldvariations.pluralse rechazaprintf %s
android-xmlstrings.xml de Androidprintf %s, %1$scantidades de <plurals>se creaprintf %s
gettext-pogettext (.po, .pot)printf, %(name)smsgstr[n]se creaprintf %s, %(name)s
iniINI (.ini){name}, {0}ningunose crea{name}, %{name}, ${name}
resxrecursos de .NET (.resx)compuesto {0}, {1:C}, con nombre {name}ningunose crea{{name}}, {name}, %{name}, ${name}

Haz coincidir el formato con tu librería de i18n: decide qué placeholders compara la comprobación de integridad.

Los cuatro formatos JSON

Los cuatro leen objetos JSON anidados con hojas de cadena.

i18next-json

Interpolación {{double-brace}}; el plural sale del sufijo CLDR de la clave (_zero, _one, _two, _few, _many, _other). Las referencias de anidamiento $t(common.foo) y $t(common.foo, { options }) se protegen como placeholders; solo cuenta el prefijo predeterminado $t(, sin paréntesis anidados en las opciones.

vue-i18n-json

Tokens de llave simple {name} y {0}, con nombres en cualquier escritura ({número}). El plural sale de un pipe en el valor.

next-intl-json

Los valores son ICU MessageFormat: los nombres de argumentos y de etiquetas de texto enriquecido son los placeholders, y el cuerpo ICU se mantiene textual salvo que cada plural y selectordinal recibe las ramas CLDR del idioma de destino. Un valor que no parsea como ICU se notifica como inválido y se omite.

ngx-translate-json

Interpolación {{double-brace}}, sin referencias de anidamiento, plurales ni ICU. Un archivo puede ser plano (claves con puntos) o anidado, y cada uno conserva su estilo al escribir; un destino nuevo se escribe anidado. Un archivo que mezcla ambos falla con MIXED_STRUCTURE.

La salvaguarda contra fabricaciones de llave simple

Bajo i18next-json, ngx-translate-json y yaml, un token {name} es texto literal que una traducción puede reformular, pero uno que nunca apareció en el origen se rechaza como fabricación. Solo se protege esa dirección: con interpolation.prefix y suffix propios de llave simple, un placeholder perdido no se detecta.

Diseños con namespaces

files.pattern es una ruta literal, nunca un glob: public/locales/{locale}/*.json busca un archivo llamado *.json y falla con SOURCE_UNREADABLE. Un solo namespace funciona tal cual se configura:

verbatra.config.ts
files: {
  pattern: "public/locales/{locale}/common.json",
},

Una configuración por namespace

Para varios namespaces, escribe una configuración por cada uno y ejecútalas una tras otra:

verbatra translate --config verbatra.common.config.ts
verbatra translate --config verbatra.auth.config.ts

Solo el namespace que se ejecutó en último lugar conserva la detección de cambios

Todas las configuraciones de un mismo directorio comparten verbatra.lock.json, y cada ejecución reemplaza las líneas base del locale con sus propias claves, así que una cadena editada de un namespace anterior se lee como sincronizada y no se vuelve a traducir. Para volver a traducirla, borra la clave (o el archivo de destino) para que cuente como faltante.

XLIFF

XLIFF 1.2 (file/body/trans-unit) y 2.0 (file/unit/segment), una lista plana de unidades.

  • Claves. El id de la unidad, luego resname, luego una posición que se desplaza cuando las unidades se mueven, así que dale a cada unidad un id. Una unidad 2.0 con varios segmentos recibe claves <id>#<n>. Una clave duplicada falla con INVALID_STRUCTURE.
  • Origen o traducción. Un documento es el origen cuando el locale coincide con su source-language (srcLang en 2.0; un idioma sin región coincide con sus formas regionales) y no declara ese locale como su destino; lo demás es una traducción, salvo un documento que no declara ninguno de los dos idiomas: es el origen si no contiene ningún <target>. Un destino que comparte idioma con el origen (en a en-GB) debe declarar target-language (trgLang).
  • Valores que faltan. Un <target> ausente, vacío o, en 1.2, marcado con state="new" o "needs-translation" falta, y también un target de 2.0 igual a su origen en un segmento marcado con state="initial". El texto de <source> nunca se copia en su lugar.
  • Escrituras en su sitio. Cada valor va a su <target>, que se crea tras <source> si no existe, y un estado new o needs-translation de 1.2 o initial de 2.0 (con su subState) pasa a translated. <source>, los atributos y <note> quedan intactos.
  • Las unidades que faltan se añaden como copia de la unidad de origen (sin sus targets ni el <alt-trans> de 1.2) en el <file> correspondiente. Un valor sin unidad a la que ir hace fallar la escritura con INVALID_STRUCTURE nombrando la clave; un origen ilegible la hace fallar sin nombrar ninguna. verbatra extract añade unidades de origen con solo un <source>; en 2.0 la clave debe ser un NMTOKEN válido (u1#0 se rechaza).
  • Marcado en línea. g, x, bx, ex, bpt, ept, ph, it, mrk de 1.2, ph, pc, sc, ec, mrk, sm, em, cp de 2.0, y cualquier secuencia {...} son todos placeholders protegidos en cualquiera de las dos versiones. Al escribir, solo estos (más un <sub> de 1.2 dentro de bpt, ept, ph, it) siguen siendo marcado; cualquier otra cosa, como <b>, se convierte en texto.
  • Escapado. El texto se lee como texto (A &amp; B es A & B) y se escapa una vez al escribir; el texto que coincide exactamente con un elemento permitido, como &lt;x id="1"/&gt;, se escribe como ese elemento, y <!DOCTYPE y <!ENTITY como texto.
  • Las notas (las <notes> de la unidad en 2.0) son contexto de solo lectura.
  • Entrada rechazada. Un documento con una declaración DTD o de entidad falla con INVALID_XML.

YAML

Un árbol anidado como los formatos JSON, con interpolación {{double-brace}} de i18next y la salvaguarda contra fabricaciones, detectado por extensión. Los comentarios no se conservan. Las claves escalares no string pasan a ser cadenas (1: se lee como "1"), un mapa o una secuencia usados como clave fallan con INVALID_STRUCTURE, la sintaxis malformada falla con INVALID_YAML, y la expansión de alias está acotada.

ARB

El .arb de Flutter: un objeto plano de mensajes con metadatos @key y globales @@.

  • Los mensajes son ICU, manejados exactamente igual que next-intl-json.
  • Los metadatos nunca se traducen y se fusionan de vuelta en su sitio; un destino existente corrupto hace fallar la escritura. @key.description es contexto de solo lectura.
  • Una escritura contiene exactamente sus mensajes. Un mensaje que queda fuera (eliminado con prune, o rechazado en la revisión) se elimina junto con su bloque @key; los globales @@ se quedan.
  • @@locale va primero. Un destino creado empieza con él, escrito como gen-l10n (pt_BR); uno existente conserva su valor y se mueve arriba, y nunca se añade uno. Corrige a mano un valor que no coincide con el nombre de archivo, o flutter gen-l10n falla.

Properties

Los .properties de Java y Spring: líneas planas de clave/valor, con las claves conservadas literalmente.

  • La sintaxis sigue a java.util.Properties (separadores, comentarios, líneas de continuación, escapes). Los archivos se leen como UTF-8 y lo que no es ASCII se escribe como \uXXXX.
  • Las escrituras conservan el orden de claves, los comentarios y las líneas en blanco, reescribiendo cada línea existente en su sitio y añadiendo las claves nuevas en el orden del origen. Una clave duplicada mantiene su primera posición y su último valor.
  • Los finales de línea siguen al archivo: cualquier CRLF significa todo CRLF, un archivo solo con CR sigue con CR, y si no, LF.
  • Los placeholders son java.text.MessageFormat: {0}, {0,number}, {count} (nombres en cualquier escritura) y los argumentos plural, select, selectordinal y choice. El entrecomillado con comilla simple no se interpreta, así que '{0}' sigue contando como placeholder.

Apple .strings

Sentencias "key" = "value";, con los plurales en el .stringsdict hermano (mismo directorio y mismo nombre base), que se leen y escriben juntos.

  • Solo UTF-8. Un archivo UTF-16 falla con INVALID_STRUCTURE; vuelve a guardarlo como UTF-8.
  • Comentarios. Un comentario /* ... */ antes de una entrada es contexto de solo lectura; los comentarios // se conservan. Los escapes \", \\, \n, \t y \U se decodifican; al escribir solo se escapan la comilla, la barra invertida, el salto de línea y el tabulador.
  • Las escrituras conservan el orden, los comentarios y las líneas en blanco; una clave eliminada se va con su propio comentario. Un destino ausente se crea, directorio .lproj y .stringsdict incluidos.
  • Los placeholders son printf: %@, %d, %1$@, %%, con banderas, ancho y longitud como decoración; un reordenamiento posicional se acepta. Un % suelto ("50% off") no lo es.
  • Plurales. Cada categoría del .stringsdict pasa a ser <key>_<category> (photo_count_one), y solo hacen el ciclo completo las categorías que tiene un locale. Los errores nombran el archivo y la clave; la clave de formato, el nombre de la variable y el tipo de valor sobreviven a una reescritura.
  • Diseño. {locale}.lproj/Localizable.strings no necesita ningún estilo de locale especial.

Xcode String Catalogs (.xcstrings)

Un único catálogo JSON con todos los locales, el sustituto de .strings desde Xcode 15.

  • Un archivo para todos los locales. files.pattern sigue necesitando {locale}, pero {locale} se expande a una cadena vacía, así que todos los locales se resuelven al mismo archivo ({locale}Localizable.xcstrings da Localizable.xcstrings). Toda escritura se serializa sobre él, así que los locales se ejecutan de uno en uno incluso con --concurrency.
  • Claves. Una clave sin localization de sourceLanguage usa el texto de la clave como origen; una localization de destino ausente cuenta como sin traducir.
  • Los plurales bajo variations.plural pasan a ser <key>_<category>, solo para las categorías presentes.
  • Los placeholders son printf, como en .strings; %lld equivale a %d.
  • Las claves con shouldTranslate: false nunca se envían ni se modifican.
  • Las escrituras parchean el documento. Solo cambian las localizations tocadas, un valor nuevo recibe state: "translated" y el resto queda idéntico en lo semántico, aunque el archivo se vuelve a serializar como JSON con 2 espacios. Crea el catálogo primero en Xcode.
  • Los errores nombran el archivo y, dentro de una entrada, la clave y el locale.

Android strings.xml

res/values/strings.xml para el origen y res/values-<qualifier>/strings.xml para cada destino; pon files.localeStyle: "android" (configuración).

  • Entradas. <string name> es una entrada; <plurals> pasa a ser key[quantity] por cada <item>, solo para las cantidades presentes.
  • Se omiten. Los recursos con translatable="false", <string-array> y un <string> con elementos en línea (<b>, <xliff:g>, CDATA) se conservan tal cual; formatted="false" se traduce con normalidad.
  • Escapado. \', \", \n, \t y un \@ o \? inicial se decodifican y se vuelven a escapar al escribir.
  • Los placeholders son printf: %s, %d, %1$s, %%; un % suelto no lo es.
  • Las escrituras parchean el archivo, borran las claves eliminadas y crean un archivo ausente con su directorio.
  • Limitaciones. Una clave traducida que después pasa a ser de paso directo en el origen se elimina del destino. --prune no sabe nada de cantidades plurales, así que puede borrar cantidades que solo existen en el destino.
  • Los errores nombran una raíz distinta de <resources>, un nombre o una cantidad no válidos, o una clave duplicada; una DTD o una entidad se rechaza.

gettext .po/.pot

Entradas msgid/msgstr con clave por msgid.

  • msgctxt se une a su msgid en una sola clave con U+E000; un origen que contenga ese carácter se rechaza.
  • Los plurales tienen clave por índice, key[n], no por categoría CLDR. Plural-Forms se conserva literalmente y solo su nplurals acota los índices; las entradas plurales sin él se rechazan, como hace msgfmt --check.
  • Marcas y comentarios. Un valor #, fuzzy se lee como actual y la marca se conserva. Los comentarios #. son contexto de solo lectura; #: y las demás marcas se conservan, los bloques #~ quedan inertes y la cabecera nunca se toca. Un .pot con msgstr vacío se lee sin problemas, pero en un catálogo de origen cada msgstr es el texto que se traduce, así que uno vacío se omite con SOURCE_VALUE_EMPTY.
  • Un destino ausente se crea con una cabecera mínima y, para plurales, un Plural-Forms dimensionado al índice más alto (siembra desde una plantilla real para la gramática exacta).
  • Los placeholders son printf, %(name)s incluido.
  • Los errores nombran el msgid y la línea. --prune no sabe nada de índices plurales, así que puede borrar formas que solo existen en el destino.

INI

Un nivel de cabeceras [section] sobre líneas key=value.

  • Claves. Una clave en [home] es home.title; las claves por encima de la primera sección conservan su nombre a secas, y los puntos literales se escapan.
  • Las escrituras solo cambian valores, conservando grafía, espacios, comentarios y líneas en blanco. Una clave nueva va al final de su sección, una sección nueva al final del archivo.
  • Valores. Los valores entre comillas dobles se desentrecomillan decodificando \\, \", \n, \r, \t, y un valor que lo necesita se escribe entrecomillado. Un ; en medio de la línea forma parte del valor.
  • Los placeholders son {name} y {0}, con nombres en cualquier escritura; sin plurales.
  • Errores. Una cabecera mal formada lanza un AdapterError; una línea sin = se conserva literalmente.

.NET .resx

Elementos <data name><value> bajo <root>, reclamados solo por .resx.

  • Las escrituras solo parchean valores: todo lo demás vuelve sin cambios, con el salto de línea del archivo; una marca de orden de bytes se descarta, y un elemento <data> nuevo, o uno cuyo valor tiene espacios en los extremos, recibe xml:space="preserve".
  • No se traducen. Los <data> con type o mimetype, y los nombres que empiezan por >> o $, se conservan tal cual. Un <comment> es contexto de solo lectura.
  • Los placeholders son elementos de formato compuesto y huecos con nombre tomados enteros ({0}, {1,-10}, {2:C}, {when:d}), así que se rechaza uno renombrado; {{, }} y las llaves sueltas también se protegen. Sin comprobación ICU ni plurales.
  • Un destino ausente se crea con las cabeceras estándar.
  • Claves rechazadas. Un valor que el destino tiene como entrada tipada, de diseñador o con marcado, o una clave que no se podría volver a leer, hace fallar la escritura con un AdapterError que la nombra.
  • Errores. Se rechazan el XML no válido, una raíz distinta de <root> y una DTD o una entidad.

Orden de claves del documento

Los formatos JSON, YAML y ARB conservan el orden del documento: las claves con forma de entero como "404" no se suben al principio, las claves nuevas se añaden en el orden del origen, y los metadatos ARB conservan su posición. XLIFF actualiza los targets en su sitio, así que su orden nunca cambia.

Claves con puntos y colisiones

En i18next-json, vue-i18n-json y next-intl-json, una hoja literal con puntos como "foo.bar" hace el viaje de ida y vuelta tal como está escrita; ngx-translate-json la lee como una ruta anidada. En los demás formatos, una misma ruta escrita de las dos formas ("foo.bar" junto a "foo": { "bar": ... }) falla con INVALID_STRUCTURE; ngx-translate-json rechaza claves planas con puntos junto a objetos anidados y claves con puntos dentro de objetos anidados con MIXED_STRUCTURE.

Cómo se leen y escriben los archivos

  • Límites. El tamaño de entrada y la profundidad de anidamiento están acotados (INPUT_TOO_LARGE, MAX_DEPTH_EXCEEDED).
  • Escrituras atómicas. Un archivo temporal se renombra a su sitio, sin dejar nunca medio archivo.
  • Formato. Los formatos XML conservan el fin de línea y el salto de línea final y sangran los elementos nuevos como sus vecinos. Una entrada nueva de gettext va tras una línea en blanco; un .po creado nombra su locale en Language (pt_BR).
  • Hojas que no son cadenas. En los formatos JSON, YAML y ARB, una hoja numérica, booleana o null se acepta pero nunca se traduce, y una reescritura la descarta; un array falla con INVALID_STRUCTURE.
  • Los errores son estructurados y sin secretos; consulta los códigos de error de adaptador.

Formatos externos a verbatra

Otro formato puede venir de tu propio adaptador con un id custom: como custom:toml, ejecutado a través del SDK como código de confianza: consulta Escribe un adaptador de formato propio.

Marcado en línea en los valores

La comprobación de paridad del marcado se aplica en todos los formatos, etiqueta por etiqueta:

  • xliff protege sus propios elementos en línea como placeholders; el resto del HTML, como <b>, se compara como marcado.
  • next-intl-json y arb tratan un <b>...</b> emparejado como placeholder y comparan un <br/> autocerrado como marcado; una etiqueta con atributos es ICU no válido y se rechaza.
  • android-xml compara los valores decodificados, así que &lt;b&gt; es <b>.
  • Cualquier otro formato no tiene concepto de marcado, así que solo esta comprobación lo ve.
Editar en GitHub

En esta página