Saltar al contenido
duxt

Servir las traducciones como colecciones propias

Añadir una dimensión de locale a una fuente en lugar de un segmento de locale a la ruta de contenido.

Contexto

La capa traducía su interfaz a siete locales y servía un único conjunto de páginas a todos ellos: useDuxtPath() quitaba el segmento de locale antes de cada consulta de contenido, así que /de-DE/guides/deploying y /guides/deploying resolvían al mismo archivo. Content v3 no tiene noción de locale — una colección es un árbol — así que las páginas traducidas necesitaban una decisión y no un ajuste.

Lo que hacen los generadores comparables se leyó en lugar de suponerse. Starlight, VitePress, Docusaurus y MkDocs ponen todos las traducciones en una carpeta por idioma; solo Starlight tiene un recurso documentado para una página que le falta a un idioma. Pasado cierto tamaño, la traducción abandona la herramienta por completo: React lleva de.react.dev como repositorio propio, y Vue una organización vuejs-translations entera, porque quienes traducen trabajan con su propio calendario y su propia revisión. OpenCode construyó un agente que traducía su documentación en CI, lo ejecutó y lo apagó; diecisiete idiomas llevan parados desde entonces.

El coste se midió antes de elegir la forma: las compilaciones sobre 1 … 200 colecciones escalan de forma lineal, a razón de unos 2,2 s y 0,63 MB de base de datos cada una, sin punto de inflexión. La matriz no tiene un techo que fuerce la mano del diseño.

Decisión

Una fuente gana una lista locales, y una ref también, resuelta como ya lo está status (ref.locales ?? source.locales). Una cadena es una carpeta dentro del path de la fuente; un objeto mueve ese idioma a su propia carpeta, repositorio o ref.

El locale por defecto es el árbol de path mismo, sin carpeta, así que añadir la clave no mueve ninguna URL que un sitio ya sirva.

El locale no forma parte de la ruta de contenido. Pertenece al enrutado de i18n, que de todos modos lo pone delante de la ruta. Original y traducción viven por tanto bajo rutas de contenido idénticas, en colecciones separadas.

Una página que le falta a un idioma recae por una cadena — el locale, su idioma base, una región hermana, el fallbackLocale de vue-i18n, el original sin traducir — y al lector se le dice, en un aviso, qué idioma se le está mostrando.

Consecuencias

Ninguna comparación de rutas del tema cambia: la navegación, las redirecciones, el rastro, la puntuación de la página más próxima del 404 y el selector de idioma siguen funcionando sobre una ruta que nunca llevó locale. El recurso es una consulta más para la misma ruta, en lugar de una redirección o un segundo esquema de resolución.

useDuxtNavigation y la búsqueda siguen a useDuxtCollection, así que ambos pasaron a tener en cuenta el locale sin que hubiera que cambiarlos.

Un sitio que no define nada obtiene exactamente lo que tenía: una colección llamada docs, una entrada en el manifiesto, una consulta por página.

Ahora dos configuraciones pueden discrepar de una forma que produce una página vacía en lugar de un error — content.config.ts resuelve el locale por defecto sin acceso a la configuración de Nuxt. Por eso el módulo duxt comprueba sourceOptions.defaultLocale contra i18n.defaultLocale y falla la compilación cuando difieren, en lugar de inyectar uno en el otro y dejar a Content calculando la otra respuesta.

Las traducciones multiplican colecciones, y la compilación paga por cada una de forma lineal. La cifra pertenece a la documentación, porque quien la consume decide la matriz.

Los fragmentos siguen a las páginas. _partials/ es una colección POR IDIOMA, nombrada como las colecciones de páginas — duxt_partials para el original, duxt_partials_de a su lado — y :partial{name} recorre la misma cadena de respaldo que recorrió la página. Tiene que ser la misma cadena: que una página y los bloques que incluye caigan en idiomas distintos es justo como se acaba con una página traducida a medias sin que nada lo indique.

La primera versión de esta decisión compartía UNA colección de fragmentos sin traducir entre todos los idiomas. Era defendible mientras nada traducía un fragmento, y dejó de serlo en el momento en que una pasada de traducción produjo docs/de/_partials/: archivos que ninguna colección leía, y una página alemana que representaba una nota de instalación en inglés sin señal alguna de que hubiera ocurrido.

Alternativas consideradas

Un segmento de locale en el prefijo de contenido. Simétrico con repo y version, y habría obligado a toda comparación de rutas del tema a aprender sobre locales — para una URL que i18n ya prefija, y que entonces se escribiría dos veces.

Un sufijo de archivo — installation.de-DE.md junto al original. Sin multiplicación de colecciones, y falla justo en el caso que los proyectos grandes tienen de verdad: obliga a que la traducción esté en el mismo repositorio y en la misma ref que el original.

404 para una traducción ausente. Lo que hace VitePress por omisión. Castiga al lector por un hueco que dejó quien escribe, y esconde a todos los demás que la traducción está incompleta.

¿Le ha resultado útil esta página?