Saltar al contenido principal

Distribución de bibliotecas compatibles con i18n

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

En aplicaciones/monorepos de gran escala, no todos los componentes/bibliotecas residen en el mismo repositorio/proyecto y pueden distribuirse de manera diferente. Si bien existen múltiples formas de resolver este problema, esta guía busca proporcionar un enfoque que hemos visto funcionar muy bien en grandes organizaciones de ingeniería.

Concepto de alto nivel

Las cadenas traducidas son básicamente activos, al igual que CSS, configuración estática o imágenes. La estructura de alto nivel típicamente contiene varias capas:

  • Componentes/Bibliotecas reutilizables que contienen cadenas traducidas, los cuales pueden estar anidados.

  • Aplicaciones de nivel superior que consumen esos componentes/bibliotecas.

Jerarquía de distribución

Cada función/biblioteca sería responsable de:

Declaración en package.json

Esto es similar a usar el atributo style para declarar CSS. Puedes declarar algo como

{
"name": "my-library",
"version": "1.0.0",
"lang": "my-strings",
"supportedLocales": ["en", "en-GB", "ja"]
}

donde my-strings es la carpeta que contiene tus cadenas traducidas en tus supportedLocales:

my-strings
|- en.json
|- en-GB.json
|- ja.json

La aplicación consumidora puede recorrer node_modules buscando archivos package.json con estos campos y agregar las cadenas en un único paquete (o múltiples paquetes), sirviendo esos JSON como prefiera.

Esto brinda flexibilidad para ubicar las traducciones donde se desee mientras estén declaradas en package.json. Sin embargo, también genera un costo adicional de procesamiento a nivel de aplicación y fomenta inconsistencias en la ubicación de salida.

Declaración mediante convención

Esto es similar a la Declaración en package.json, excepto que las traducciones siempre se generan en lang/{locale}.json. La aplicación principal puede hacer

formatjs compile "node_modules/**/lang/en.json" --ast --out-file lang/en.json

para agregar todas las cadenas pre-traducidas de sus bibliotecas.

my-lib
|- src
|- lang
|- en.json
|- en-GB.json
|- ja.json
|- node_modules
|- library1
|- lang
|- en.json
|- en-GB.json
|- ja.json
|- library2
|- lang
|- en.json
|- en-GB.json
|- ja.json

Esto proporciona consistencia y minimiza el costo de procesamiento de diferentes archivos de manifiesto, pero también es menos flexible.

información

Hemos observado que el enfoque por convention funciona mejor en grandes organizaciones de ingeniería debido a la aplicación de convenciones y estructura, mientras que el enfoque por manifest funciona mejor en entornos más abiertos.

Paso del objeto intl

El núcleo de una aplicación i18n es el objeto intl, que contiene mensajes precompilados, configuraciones regionales, formatos y caché. Por lo tanto, este objeto debe inicializarse únicamente en el nivel superior de la aplicación.

Las bibliotecas de componentes pueden declarar intl: IntlShape como prop y posteriormente pasarlo directamente así:

import {IntlShape} from 'react-intl'
import {MyButton, MyForm} from 'my-components'
interface Props {
intl: IntlShape
}

function MyFeature(props: Props) {
return (
<div>
<MyButton intl={props.intl} />
<MyForm intl={props.intl} />
</div>
)
}

or passing down via context using RawIntlProvider:

import {IntlShape, RawIntlProvider} from 'react-intl'
import {MyButton, MyForm} from 'my-components'
interface Props {
intl: IntlShape
}

function MyFeature(props: Props) {
return (
<RawIntlProvider value={props.intl}>
<MyButton />
<MyForm />
</RawIntlProvider>
)
}