Lograr la internacionalización (i18n) correctamente con Remix y CMS sin cabeza

 

 

 

Sobre los autores


Índice
  1. i18n y l10n
  • ¿Por qué es tan importante i18n?
  • Cómo funciona i18n a nivel básico
  • Bibliotecas
  • ¿Qué pasa con la remezcla?
  • Una combinación de remezcla y CMS
  • Resumen
  • Arisa es una desarrolladora frontend que se convirtió en ingeniera de DevRel. Trabaja en Storyblok para compartir y mejorar mejores DX a través de charlas, mantenimiento de SDK y… Más sobre Facundo Arisa ↬

     

    Este artículo le mostrará el impacto de la internacionalización, su lógica fundamental, cómo abordarla con Remix y, opcionalmente, cómo gestionarla de forma más cómoda utilizando un CMS headless.

    Este artículo ha contado con el amable apoyo de nuestros queridos amigos de Storyblok , un CMS sin cabeza amigable con un editor visual, componentes anidados y bloques de contenido personalizables para sitios web y aplicaciones. ¡Gracias!

    ¿Cuánta barrera lingüística existe todavía en el siglo XXI? Usted, como lector, probablemente esté muy familiarizado con el inglés, pero ¿qué pasa con los demás?

    Hoy en día, la mayoría de nosotros hemos escuchado a menudo la importancia de la accesibilidad, un mejor rendimiento y una mejor UX o DX. Es posible que no escuche o vea con frecuencia acerca de i18n en comparación con estos temas. Pero si observa los hechos y las cifras de las estadísticas, es posible que encuentre algunos resultados sorprendentes sobre i18n y su impacto. Averigüemos esto juntos.

    i18n y l10n

    Antes de analizar el impacto de i18n, aprendamos la diferencia entre las dos terminologías.

    • i18n
      i18n significa internacionalización. Entre el primer carácter, "i", y el último carácter, "n", de esta palabra, hay 18 caracteres. i18n describe la implementación de estructuras y características para que sus aplicaciones estén listas para localizar contenido.
    • l10n
      l10n significa localización. Entre el primer carácter, "l", y el último carácter, "n", de esta palabra, hay diez caracteres. l10n significa traducir contenido a los idiomas para los usuarios que acceden desde regiones específicas.

    Como seguimiento, i18n contiene un proceso programático para implementar funciones para que los editores y traductores de contenido puedan iniciar el proceso l10n desde la interfaz de usuario.

    ¿Por qué es tan importante i18n?

    Para ver la importancia de i18n, miremos los números y las estadísticas para obtener información objetiva. Verá los números de algunos datos a continuación y, antes de seguir leyendo, adivinemos qué significan esos números.

     

    • 5,07 mil millones
    • 25,9%
    • 74,1%
    • Porcelana
    • Asia

    El primer hecho muestra una enorme cantidad de números. 5.070 millones es el número de usuarios en este mundo en 2020. La población mundial en 2021 era de 7.837 millones, casi 8.000 millones. Más de la mitad de la población mundial tiene acceso a contenidos en Internet y aplicaciones.

    Según la cantidad de usuarios que hay en este mundo, existe otra investigación sobre los idiomas más comunes utilizados en Internet. Al observar el gráfico, la mayoría de nosotros prestamos atención al número más alto de este diagrama: 25,9%, inglés.

    (Fuente de la imagen: Statista ) ( Vista previa grande )

    La segunda más alta es el resto de lenguas, un 23,1%. Además, supongamos que reúnes el resto del porcentaje excepto el inglés. En ese caso, te darás cuenta de que, de los más de 5 mil millones de usuarios, el 74,1% de los usuarios acceden al contenido en cualquier otro idioma.

    Después de analizar estos hechos, ahora podemos hablar de por qué es crucial internacionalizar y localizar su contenido para Asia y China, en particular. China tiene la mayor cantidad de usuarios de Internet en todo el mundo. Como resultado, más de la mitad de todos los usuarios de Internet a nivel mundial son de Asia.

    Según lo que vimos, probablemente no podamos ignorar la localización de contenido. Mejorará la UX si estas enormes cantidades de usuarios en todo el mundo pudieran tener contenido localizado. Después de conocer el impacto potencial del i18n adecuado, veamos la lógica fundamental.

    Cómo funciona i18n a nivel básico

    Independientemente de la tecnología para implementar i18n, existen tres formas de determinar idiomas y regiones.

    1. La ubicación de la dirección IP.
    2. Aceptar- Encabezado de idioma/ Navigator.languages
    3. Identificadores en URL

    El uso de la dirección IP detecta la región de los usuarios y les permite acceder al contenido en sus idiomas regionales. Sin embargo, la dirección IP del usuario no necesariamente coincide con su preferencia de idioma. Además, el análisis de ubicación evita que los motores de búsqueda rastreen los sitios.

    Usar el encabezado Accept-Language o Navigator.languages ​​es otro enfoque posible para implementar i18n. Sin embargo, este enfoque proporciona información sobre el idioma pero no información regional.

    i18n no se trata sólo de localizar contenido. También incluye mejorar la UX. Por ejemplo, la creación de identificadores en URL mejora la UX. También ayuda a dividir el contenido localizado en el sistema dedicado. Cubriremos cómo es posible implementar un sistema de este tipo en la sección " Una combinación de Remix y CMS ".

    Normalmente, los identificadores de las URL existen en tres patrones diferentes:

    1. Diferenciar por dominios (es decir hello.es, , hello.jp)
    2. Parámetros de URL (es decir hello.com?loc=de, )
    3. Subdirectorios localizados (es decir hello.com/es, , hello.com/ja)

    Para seguir la política del mismo origen para un mejor SEO, se pueden utilizar subdirectorios localizados.

     

    Basándonos en hechos interesantes y la lógica fundamental para implementar i18n, hablaremos sobre marcos y bibliotecas, ya que algunos de ellos usan bibliotecas i18n.

    Bibliotecas

    Para no reinventar la rueda cada vez que queramos implementar i18n en nuestros proyectos, los desarrolladores disponen de diferentes bibliotecas, herramientas y servicios que pueden utilizar para facilitar el trabajo. Si estamos trabajando con frameworks React o basados ​​en React, tenemos diferentes opciones disponibles. Hablemos de algunos de ellos.

    Formato.js

    Format.js es una colección modular de bibliotecas de JavaScript que podemos usar para implementar la lógica i18n tanto en el cliente como en el servidor. Este grupo de bibliotecas se centra en formatear números, fechas y cadenas. Ofrece diferentes funcionalidades y herramientas y se ejecuta tanto en el navegador como en el tiempo de ejecución de Node.js. Se integra con varios frameworks, como Vue y React, para que podamos utilizar sus funcionalidades en nuestros proyectos Remix. Puede leer más al respecto en los documentos oficiales de React Intl .

    i18siguiente

    Otra alternativa que podemos evaluar para nuestro proyecto es i18next . Esta biblioteca JavaScript va más allá de las funciones estándar de i18n, proporcionando un conjunto completo para gestionar i18n en nuestros proyectos. Podemos detectar el idioma de los usuarios, traducciones en caché e incluso instalar complementos y extensiones. Como está construida en JavaScript, podemos utilizar esta herramienta tanto para sitios web como para aplicaciones móviles y de escritorio.

    ¿Qué pasa con la remezcla?

    A la hora de crear un sitio web usando Remix, tenemos diferentes opciones a considerar. Al ser un framework basado en React, podemos utilizar cualquiera de las librerías mencionadas anteriormente. Sin embargo, analizaremos dos enfoques que pueden encajar mejor en sus proyectos de Remix. Primero, veremos cómo localizar contenido usando remix-i18next, una biblioteca específica de Remix para i18n. En segundo lugar, utilizaremos un sistema de gestión de contenidos sin cabeza como fuente de los diferentes idiomas/localizaciones de nuestro contenido.

    remezcla-i18next

    Basado en i18next, Sergio Xalambrí , uno de los principales contribuyentes de Remix, creó remix-i18next . Esta biblioteca ofrece funciones y módulos similares a los de la biblioteca JavaScript, pero se centra en conceptos y enfoques de Remix. Fácil de configurar y usar, listo para producción y sin ningún requisito ni dependencia. Echemos un vistazo más de cerca a cómo implementar i18n en nuestros proyectos Remix usando remix-i18next.

    Primero que nada, necesitamos instalar algunos paquetes npm:

    npm install remix-i18next i18next react-i18next i18next-browser-languagedetector i18next-http-backend i18next-fs-backend

    Todos ellos nos ayudarán a gestionar i18n tanto en el lado del servidor como en el del cliente de nuestra web. También los usaremos para configurar nuestro backend y definir la lógica que detectará el idioma del usuario.

    Ahora, debemos agregar alguna configuración que se utilizará en todo el sitio web tanto desde el lado del cliente como del servidor. Creemos un par de archivos JSON con las traducciones de las diferentes cadenas de caracteres que usaremos en nuestro sitio web:

     

    { "intro": "Hello everyone!"}
    { "intro": "Hola a todos!"}

    Al nombrar los archivos "common.json", estamos definiendo el espacio de nombres para las cadenas.esoenumeraremos en ellos.

    Ahora, creemos un archivo llamado i18n.js. Este archivo contiene diferentes ajustes de configuración que usaremos al momento de inicializar nuestro servidor i18n.

    export default { supportedLngs: ["en", "es"], fallbackLng: "en", defaultNS: "common", // Disabling suspense is recommended react: { useSuspense: false },};

    Puede ver más opciones de configuración en los documentos oficiales de i18next .

    Ahora, cree el archivo i18next.server.js, que contiene la lógica que se utilizará en el entry.server.jsxarchivo de nuestro proyecto Remix. Korean Beauty

    import Backend from "i18next-fs-backend"; import { resolve } from "node:path"; import { RemixI18Next } from "remix-i18next"; import i18n from "~/i18n"; // The configuration file we created let i18next = new RemixI18Next({ detection: { supportedLanguages: i18n.supportedLngs, fallbackLanguage: i18n.fallbackLng, }, i18next: { ...i18n, backend: { loadPath: resolve('./public/locales/{{lng}}/{{ns}}.json'), }, }, backend: Backend, }); export default i18next;

    Básicamente, estamos inicializando un nuevo servidor i18n que se ejecutará con nuestro backend Remix. Estamos especificando la ubicación de los archivos JSON que contienen las traducciones que se utilizarán. Agreguemos estas características a nuestros archivos de configuración principales de Remix. Primero, agregamos algo de lógica para poder traducir el contenido del lado del cliente. Para hacer eso, editemos nuestro archivo `entry.client.jsx`:

    import i18next from "i18next";import LanguageDetector from "i18next-browser-languagedetector";import Backend from "i18next-http-backend";import { I18nextProvider, initReactI18next } from "react-i18next";import { getInitialNamespaces } from "remix-i18next";import i18n from "./i18n"; // The configuration file we createdi18next .use(initReactI18next) .use(LanguageDetector) .use(Backend) .init({ ...i18n, // The same config we created for the server ns: getInitialNamespaces(), backend: { loadPath: "/locales/{{lng}}/{{ns}}.json", }, detection: { order: ["htmlTag"], caches: [], }, }) .then(() = { // After i18next init, hydrate the app hydrateRoot( document, // Wrap RemixBrowser in I18nextProvider I18nextProvider i18n={i18next} RemixBrowser / /I18nextProvider ); });

    Necesitamos esperar para asegurarnos de que las traducciones se carguen antes de la hidratación para mantener nuestra aplicación web interactiva.

    Agreguemos la lógica al entry.server.jsxarchivo ahora:

    import { createInstance } from "i18next";import Backend from "i18next-fs-backend";import { resolve } from "node:path";import { I18nextProvider, initReactI18next } from "react-i18next";import i18next from "./i18next.server"; // The backend file we createdimport i18n from "./i18n"; // The configuration file we created...export default async function handleRequest(...) { // We create a new instance of i18next let instance = createInstance(); // We can detect the specific locale from each request let lng = await i18next.getLocale(request); // The namespaces the routes about to render wants to use let ns = i18next.getRouteNamespaces(remixContext); await instance .use(initReactI18next) .use(Backend) .init({ ...i18n,// The config we created lng, // The locale we detected from the request ns, backend: { loadPath: resolve("./public/locales/{{lng}}/{{ns}}.json"), }, }); return new Promise((resolve, reject) = { ... let { pipe, abort } = renderToPipeableStream(  {" "} , ... ); ... });}

    Identificar el idioma preferido de los usuarios nos permitirá, entre otras cosas, redirigirlos a determinadas rutas.

     

    Ahora podemos comenzar a utilizar las funcionalidades proporcionadas por remix-i18next para detectar la configuración regional del usuario y entregar contenido traducido en base a ella. Editemos el root.jsxarchivo:

    ...import { json } from "@remix-run/node";import { useChangeLanguage } from "remix-i18next";import { useTranslation } from "react-i18next";import i18next from "~/i18next.server";...export let loader = async ({ request }) = { let locale = await i18next.getLocale(request); return json({ locale });};export let handle = { i18n: "common",};export default function App() { // Get the locale from the loader let { locale } = useLoaderData(); let { i18n } = useTranslation(); useChangeLanguage(locale); return ( html lang={locale} dir={i18n.dir()} ... /html );}

    El useChangeLanguageenlace cambiará el idioma de la instancia a la configuración regional detectada por el cargador. Siempre que hagamos algo para cambiar el idioma, esta configuración regional cambiará e i18next cargará las traducciones correctas.

    Ahora podemos traducir contenidos en cualquier ruta:

    import { useTranslation } from "react-i18next";export default function MyPage() { let { t } = useTranslation(); return h1{t("intro")}/h1;}

    Usamos la t()función para mostrar cadenas traducidas según la lista de mensajes que definimos en nuestros archivos JSON.

    En este ejemplo, utilizamos un espacio de nombres predeterminado, pero podemos configurar varios espacios de nombres si queremos. Puede leer más sobre la t()función en los documentos oficiales de i18next .

    En caso de que queramos traducir contenido del lado del servidor, podemos usar el getFixedTmétodo dentro de nuestros cargadores y acciones:

    import i18next from "~/i18next.server";...export let loader = async ({ request }) = { let t = await i18next.getFixedT(request); let title = t("intro"); return json({ title });};

    Una combinación de remezcla y CMS

    Juntos, exploramos las opciones disponibles para implementar i18n con Remix. Al comienzo de este artículo, aprendimos que i18n podría dar como resultado una UX, SEOUX y SEO enormemente mejorados. Como parte de UX, también es importante incluir un mejor DX.

    El enfoque anterior crea archivos de traducción a nivel de código fuente. Además, no tenemos la lógica para implementar identificadores en las URL. Para lograr esto, veamos el enfoque de integrar un CMS. En este artículo, usaremos Storyblok, que ofrece tres enfoques diferentes para localizar contenido y maneja para determinar los idiomas y las regiones.

     

    Nota : si desea crear la conexión entre su aplicación Remix y Storyblok, hay un tutorial de 5 minutos que explica cómo hacerlo.

    Después de eso, puede clonar rápidamente un espacio inicial utilizando este enlace mágico para tener todos los componentes y tipos de campos necesarios. Este espacio de ejemplo cubre un enfoque llamado traducción a nivel de carpeta. Cubriremos de qué se trata en la siguiente sección.

    Elija entre tres enfoques

    Storyblok tiene tres formas de crear el diseño para almacenar contenido localizado y determinar idiomas y regiones.

    1. Traducción a nivel de carpeta : divida el contenido localizado a nivel de carpeta.
    2. Traducción a nivel de campo : Traduce a nivel de tipo de campo.
    3. Traducción a nivel de espacio : dedica espacios (entornos o repositorios) a cierto contenido localizado.

    Para cubrir los identificadores en las URL, la traducción a nivel de carpeta funciona perfectamente, ya que cada carpeta sólo contendrá contenido localizado relevante.

    ( Vista previa grande )

    Además, los identificadores se pueden modificar desde la configuración de la carpeta a través del slug.

    ( Vista previa grande )

    Al modificar el slug desde la pantalla de configuración de la carpeta, este identificador localizado en la URL aparece en todas las historias dentro de esta carpeta japonesa. Por ejemplo, la página acerca de dentro de la carpeta japonesa ya tiene un identificador localizado en la URL.

    ( Vista previa grande )

    Para generar páginas de contenido mediante programación, Remix tiene una función llamada Splats , que captura todos los slugs independientemente de los niveles anidados. Nombrar un archivo $.jsxhabilitará la función fundamental del slug general.

    app├── root.jsx└── routes ├── files │ └── $.jsx └── files.jsx

    La diferencia entre los segmentos dinámicos de Remix es que los símbolos siguen coincidiendo en el siguiente /. Por lo tanto, los símbolos capturarán todo lo que se encuentre en el camino. Si la ruta de la URL es hello.com/ja/about/something, la ruta del símbolo tiene un parámetro especial para capturar los segmentos finales de la URL.

    export async function loader({ params }) { params["*"]; // "ja/about/something"}

    Usando el parámetro especial de la ruta splat, editemos $.jsxel archivo.

    export default function Page() { // useLoaderData returns JSON parsed data from loader func let story = useLoaderData(); story = useStoryblokState(story, { resolveRelations: ["featured-posts.posts", "selected-posts.posts"] }); return StoryblokComponent blok={story.content} /};// loader is Backend API Wired up through useLoaderDataexport const loader = async ({ params, preview = false }) = { let slug = params["*"] ?? "home"; slug = slug.endsWith("/") ? slug.slice(0, -1) : slug; let sbParams = { version: "draft", resolve_relations: ["featured-posts.posts", "selected-posts.posts"], }; // … let { data } = await getStoryblokApi().get(`cdn/stories/${slug}`, sbParams); return json(data?.story, preview);};

    SUGERENCIA : En la sección “Elija entre 3 enfoques”, no cubrimos los tres enfoques, pero si desea saber más, todos los enfoques se documentan a continuación.

    Resumen

    Aprendimos juntos los hechos y estadísticas para conocer los impactos y la importancia de i18n y vimos cómo Remix maneja varias opciones para implementar i18n avanzado. Curiosamente, una mejor experiencia i18n proporciona un mejor SEO y UX. Con suerte, este artículo le proporcionó nuevos conocimientos y aprendizajes interesantes.

    • “ Internacionalización ”, Storyblok Docs
    • Versión en vídeo de este artículo.
    • Remezclar documentos
    • remezcla-i18next
    • Documentos del bloque de historias

    (vf, il)Explora más en

    • Aplicaciones
    • Marcos
    • Siguiente.js
    • javascript





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Lograr la internacionalización (i18n) correctamente con Remix y CMS sin cabeza

    Lograr la internacionalización (i18n) correctamente con Remix y CMS sin cabeza

    Sobre los autores Índice i18n y l10n

    programar

    es

    https://aprendeprogramando.es/static/images/programar-lograr-la-internacionalizacion-i18n-correctamente-con-remix-y-cms-sin-cabeza-1167-0.jpg

    2024-04-04

     

    Lograr la internacionalización (i18n) correctamente con Remix y CMS sin cabeza
    Lograr la internacionalización (i18n) correctamente con Remix y CMS sin cabeza

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20