Idiomas
Cómo elige Learnio un idioma, dónde está cada traducción y cómo cambiar un texto o añadir un idioma nuevo a cada aplicación.
Para el paquete Full Stack
Los idiomas incluidos
Cada aplicación viene en inglés, el predeterminado, y en árabe, que se muestra de derecha a izquierda. Cada aplicación tiene sus propias traducciones:
| Aplicación | Archivos de traducción | Archivos por idioma |
|---|---|---|
| Sitio para estudiantes | frontend/messages/<namespace>/<locale>.json | 22 |
| Panel de administración | admin-dashboard/messages/<namespace>/<locale>.json | 24 |
| API | back-end/src/i18n/translations/<locale>/<namespace>.json | 18 |
Un namespace es un área de la aplicación, como layouts, auth o courses. Algunos son carpetas anidadas, por ejemplo messages/dashboard/courses/en.json.
Cómo se elige el idioma
El idioma es la primera parte de la dirección: /en/courses o /ar/courses. No hay cookie de idioma ni detección desde el navegador.
- Una dirección sin idioma se redirige al predeterminado, el inglés:
/coursesva a/en/courses. En el panel de administración,/va a/en/dashboard. - El selector de idioma abre la misma página con el otro prefijo.
- Cada solicitud a la API lleva el idioma de la página en el encabezado
Accept-Language, así que la API responde en ese idioma.
Para abrir en árabe por defecto, pon defaultLocale en "ar" en src/config/locales.ts en el sitio para estudiantes, y en src/proxy.ts en el panel de administración.
Cambia un texto
Cada palabra de la pantalla viene de un archivo de mensajes. Busca el texto que ves para encontrar su clave y luego cámbialo en todos los idiomas.
frontendgrep -rn "All rights reserved" messagesAsí se encuentra la línea de copyright del pie de página, con la clave footer.copyright en messages/layouts/en.json. Cambia la misma clave en ar.json:
"footer": {
"copyright": "© {year} Learnio. All rights reserved."
}- Conserva tal cual los marcadores como
{year}y las etiquetas como<brand>. El código los rellena. - Cambia la clave en todos los archivos de idioma. Una clave que falta en un idioma muestra su ruta en lugar del texto.
yarn devdetecta el cambio. Una versión de producción incluye los mensajes, así que vuelve a construirla.
Con las notificaciones pasa lo mismo: la API solo guarda un tipo, como enrollment_created, y cada aplicación lo redacta a partir de sus propios archivos. En el panel de administración están en header.notifications.types en messages/dashboard/<locale>.json; en el sitio para estudiantes, en notifications.types en el mismo archivo.
Cursos, artículos y otros contenidos
El texto que escribes en el panel de administración, como los títulos de los cursos, las lecciones, las categorías, los artículos del blog y los perfiles de instructores, se guarda una sola vez con ambos idiomas, como un valor JSON con una clave en y una ar:
{ "en": "Project Management", "ar": "إدارة المشاريع" }- Los formularios del panel de administración muestran una pestaña en inglés y otra en árabe para cada uno de estos campos.
- La API devuelve ambos valores y cada frontend muestra el del idioma de la página. Si ese está vacío, muestra el otro, así que un curso nunca se queda sin nombre.
- La API ya devuelve resueltos los resultados de búsqueda, a partir del encabezado
Accept-Language. - En los datos de demostración de
yarn seed, las categorías, los artículos del blog, los perfiles de instructores, los cuestionarios y los títulos de las secciones de los cursos tienen texto en árabe. Los títulos y las descripciones de los cursos y los títulos de las lecciones llevan el texto en inglés en ambas claves, así que tradúcelos en el panel de administración.
El contenido tiene exactamente dos idiomas
La validación de la API espera un valor en y otro ar en estos campos y rechaza cualquier otra clave, y los editores del panel tienen dos pestañas. Añadir un tercer idioma de contenido implica cambiar las entidades y los DTO de la API, los campos multilingües del panel y su función auxiliar localizedText. La localizedText del sitio para estudiantes ya lee la clave que corresponde al idioma de la página. Sin esos cambios, una página en un nuevo idioma de interfaz muestra el contenido en inglés.
Qué traduce la API
- Los mensajes de respuesta, como los textos de éxito y de error que el panel de administración muestra en sus alertas, vienen de
src/i18n/translations/<locale>/<namespace>.jsona través deI18nServiceensrc/i18n/i18n.service.ts. - Los correos electrónicos se redactan en
mail.json. Los correos de verificación y de restablecimiento de contraseña usan el idioma de la solicitud. Los recibos y las confirmaciones de inscripción usan el idioma en que se hizo el pedido. Los correos en árabe se muestran de derecha a izquierda. - Los nombres de los países están en
countries.json.
El idioma se toma de la cabecera Accept-Language. Un código regional como ar-SA cuenta como ar. Una solicitud sin cabecera, o en un idioma que la API no admite, recibe el idioma por defecto. Una clave que falta en un idioma recurre a su texto en el idioma por defecto y, si no, a la propia clave.
- El idioma por defecto es la entrada Default Language (
default_locale) de la pestaña App Settings de Settings en el panel de administración,enen los datos iniciales. Un cambio se aplica a la siguiente solicitud, sin reiniciar. La API rechaza un valor que no sea uno de sus idiomas, así que una errata no puede dejarla respondiendo en un idioma sin traducciones. - La API lee sus archivos de traducción una sola vez, al iniciarse: reiníciala después de editar uno.
yarn buildlos copia endist/.
Añade un idioma al sitio para estudiantes
Los pasos usan el francés, fr, como ejemplo. Usa un código de dos letras en minúsculas: varios helpers reconocen el idioma como un primer segmento de dos letras en la dirección. Las rutas están dentro de frontend/.
Añade el código a la lista de idiomas
src/config/locales.tses la única lista que lee el sitio para estudiantes: las rutas, la redirección, el cargador de mensajes, el script que definelangydirantes del primer pintado, el selector de idioma, las solicitudes a la API, la redirección de inicio de sesión, los metadatos de las páginas, el mapa del sitio y cada número y fecha que formatea. Añade el código alocalesy dale una entrada en los tres mapas de al lado. El compilador señala cualquiera que te falte.frontend/src/config/locales.tsexport const locales = ["en", "ar", "fr"] as const; export const OG_LOCALES: Record<Locale, string> = { en: "en_US", ar: "ar_AE", fr: "fr_FR" }; export const LOCALE_FLAGS: Record<Locale, FlagIconCode> = { en: "US", ar: "AE", fr: "FR" }; export const LOCALE_FORMAT_TAGS: Record<Locale, string> = { en: "en-US", ar: "ar-EG", fr: "fr-FR" };Entrada Qué define OG_LOCALESEl idioma de la tarjeta para compartir de la página ( og:locale)LOCALE_FLAGSLa bandera que muestra el selector de idioma, como código de país LOCALE_FORMAT_TAGSCómo se escriben los números y las fechas. Usa una etiqueta con región, como fr-FR, para que las cifras y los nombres de los meses no dependan del navegador.RTL_LOCALESAñade el código si el idioma se escribe de derecha a izquierda. JOINING_SCRIPT_LOCALESAñade el código si su escritura une las letras, como la árabe. El logotipo de texto de la página de inicio se dibuja entonces como contornos, porque Safari deja esas letras sin unir en el texto SVG. Crea los archivos de mensajes
Copia cada archivo en inglés a su lado con el nuevo código y luego traduce los valores. Conserva las claves.
Terminalenfrontendfind messages -name en.json -exec sh -c 'cp "$1" "$(dirname "$1")/fr.json"' _ {} \;En PowerShell:
TerminalenfrontendGet-ChildItem messages -Recurse -Filter en.json | ForEach-Object { Copy-Item $_.FullName (Join-Path $_.DirectoryName 'fr.json') }Revisa las fuentes
Inter se carga con el subconjunto
latinensrc/app/layout.tsx, que cubre el francés, el español o el alemán. Añadelatin-extpara idiomas como el polaco, el checo o el turco. Para otro sistema de escritura, carga ahí una fuente para él y añade una regla para sulangensrc/styles/base.css, como hace la árabe.Abre el nuevo idioma
Reinicia
yarn devy abre localhost:3030/frLocal.Resultado esperado: La página muestra tu texto traducido, el selector incluye el nuevo idioma, y cada página lo nombra en sus alternativas
hreflangy en el mapa del sitio.
El pago necesita que la API conozca el idioma
El pago envía el idioma de la página con el pedido, y la API solo acepta ahí los idiomas de su propia lista. Hasta que el código se añada también a la API (Añadir un idioma a la API), una compra hecha desde una página en el nuevo idioma se rechaza.
Añade un idioma al panel de administración
El panel de administración guarda su lista de idiomas en tres archivos. Los pasos usan fr; usa un código de dos letras en minúsculas. Las rutas están dentro de admin-dashboard/.
Añade el código a las tres listas
localesensrc/config/i18n.ts, que carga los mensajes.localesensrc/proxy.ts, que redirige las direcciones sin idioma.localesensrc/app/[locale]/layout.tsx, que decide qué direcciones existen.
Crea los archivos de mensajes
Copia cada archivo en inglés con el nuevo código y luego traduce los valores.
Terminalenadmin-dashboardfind messages -name en.json -exec sh -c 'cp "$1" "$(dirname "$1")/fr.json"' _ {} \;Actualiza los helpers
src/hooks/locale/useLocale.tsaceptaen,fr,esyar. Añade tu código si no es uno de ellos.src/hooks/locale/useDirection.tssolo trataarcomo de derecha a izquierda. Amplía la comprobación para otro idioma de derecha a izquierda.src/lib/api/client-utils/locale.tsysrc/lib/api/client-utils/auth.tssolo reconocenenyaren la dirección. Añade tu código.
Añádelo al selector de idioma
En
src/components/LanguageSwitcher.tsx, importa la bandera decountry-flag-icons/react/3x2y añade una entrada alanguages.admin-dashboard/src/components/LanguageSwitcher.tsximport { US, SA, FR } from "country-flag-icons/react/3x2"; const languages = [ { code: "en", country: "US" as const, Flag: US }, { code: "ar", country: "SA" as const, Flag: SA }, { code: "fr", country: "FR" as const, Flag: FR }, ];Revisa las fuentes
Las fuentes se cargan en
src/app/layout.tsx, ysrc/styles/base.csscambia a la fuente árabe parahtml[lang="ar"]. Un idioma con otro sistema de escritura necesita su propia fuente y una regla equivalente.
Los nombres de la marca en src/config/brand.config.ts solo tienen valores en y ar, y el inglés se muestra para cualquier otro idioma.
Añade un idioma a la API
Las rutas están dentro de back-end/.
Copia la carpeta de traducciones
Después, traduce los 18 archivos que contiene.
Terminalenback-endcp -R src/i18n/translations/en src/i18n/translations/frEn PowerShell:
Terminalenback-endCopy-Item -Recurse src/i18n/translations/en src/i18n/translations/frAñade el código a la lista de idiomas admitidos
SUPPORTED_LOCALESensrc/i18n/locales.tses la única lista de la API. La leen las traducciones, la validación del pago, el idioma fijado en cada pedido, las páginas de pago, los emails y sus enlaces a los dos frontends. Hasta que el código esté ahí, las solicitudes en el nuevo idioma reciben el idioma por defecto.back-end/src/i18n/locales.tsexport const SUPPORTED_LOCALES = ['en', 'ar', 'fr'] as const;Revisa los dos lugares que comprueban el árabe
src/modules/mail/templates/layout.tsmaqueta un email de derecha a izquierda solo paraar; amplíalo para otro idioma que se escriba de derecha a izquierda. Las dos búsquedas,src/modules/search/search.service.tsysrc/modules/public/student-search.service.ts, leen un título guardado solo en árabe o en inglés, porque el contenido tiene dos idiomas. Encuéntralas:Terminalenback-endgrep -rn "=== 'ar'" srcReinicia la API
Lee los archivos de traducción al iniciarse. Para producción,
yarn buildlos copia endist/.