Skip to main content

Qué se consigue en esta página

Distribuirás los mensajes de tu paquete en varios idiomas y permitirás que la aplicación que lo usa cambie solo los textos que necesite. También se organiza cómo tratar las claves de traducción y los marcadores de posición como una API pública y cómo conservar las personalizaciones al actualizar el paquete. Internacionalización cubre las operaciones básicas en una aplicación y Desarrollo de paquetes para Laravel cubre los fundamentos del registro y la publicación. Esta página profundiza en la implementación de ServiceProvider, FileLoader y Translator de Laravel 13.
loadTranslationsFrom() registra desde dónde se cargan las traducciones, y publishes() registra el destino de la copia de archivos. Para usar las traducciones, no es obligatorio que el usuario ejecute vendor:publish.

Distribuir traducciones PHP con espacio de nombres

Si quieres tener claves propias del paquete, usa el formato de array PHP y un espacio de nombres. El siguiente es un ejemplo de un paquete llamado Acme\Courier.
Prepara los valores predeterminados en japonés en lang/ja/messages.php.
Prepara también el inglés como respaldo en lang/en/messages.php.
Registra la carga y, opcionalmente, la publicación en el método boot() del service provider.
Al usarlas, se especifican el espacio de nombres, el nombre del archivo y la clave del array. El código de idioma es ja, de acuerdo con la configuración de Laravel. Es distinto de jp, que se usa en las URL de este sitio de documentación.
El espacio de nombres courier es el segundo argumento de loadTranslationsFrom(). No se determina automáticamente a partir del nombre del paquete de Composer.

Las traducciones PHP no reemplazan el archivo completo

En la aplicación que usa el paquete, si se utiliza el directorio de idiomas estándar, basta con escribir solo las claves que se quieren cambiar en lang/vendor/courier/ja/messages.php. Aunque se haya cambiado el directorio de idiomas, se usa la ruta bajo $this->app->langPath('vendor/courier').
En este ejemplo solo cambia queued, y failed usa la traducción japonesa del paquete.

Orden de carga de FileLoader

ServiceProvider::loadTranslationsFrom() registra el espacio de nombres después de que se resuelva el Translator. La lectura real de los archivos se produce cuando se solicita una traducción. FileLoader::loadNamespaced() carga el archivo de idioma del paquete registrado y pasa ese array a loadNamespaceOverrides(). Allí lee vendor/{namespace}/{locale}/{group}.php en cada ruta de idioma del cargador y reemplaza los valores con array_replace_recursive(). El TranslationServiceProvider estándar pasa al cargador la ruta de idiomas del framework y la de la aplicación, en ese orden. Aunque exista una extensión que registre rutas adicionales, el array de sobrescritura cargado después tiene prioridad sobre la misma clave.
Si el espacio de nombres no está registrado, FileLoader::loadNamespaced() devuelve un array vacío. Colocar archivos en lang/vendor/courier no compensa haber olvidado registrar el service provider. Además, si otro paquete registra el mismo espacio de nombres, la ruta registrada se reemplaza, así que elige un nombre que no colisione.

Las traducciones JSON no tienen un espacio de nombres propio del paquete

Las traducciones JSON, que usan el texto como clave, se registran indicando el directorio como se muestra a continuación. Es una opción distinta de las traducciones PHP anteriores.
Ejemplo de lang/ja.json del paquete:
loadJsonTranslationsFrom() no tiene un argumento de espacio de nombres. Las traducciones JSON registradas comparten el mismo espacio de claves con otros paquetes y con la aplicación.

Las traducciones JSON se sobrescriben en el ja.json de la aplicación

FileLoader::loadJsonPaths() lee primero las rutas JSON registradas, después las rutas de idioma habituales, y las combina con array_merge(). En la configuración estándar, la misma clave de texto en el lang/ja.json de la aplicación sobrescribe el valor del paquete.
  • Si varios paquetes usan la misma clave de texto, prevalece el valor del JSON cargado en último lugar. Evita diseños que dependan del orden de los providers.
  • lang/vendor/courier/ja.json no es un destino de sobrescritura del cargador JSON estándar. Aunque reutilices para JSON la configuración de publicación pensada para PHP, esa ubicación no se lee automáticamente.
  • Aunque publiques el JSON del paquete con publishes() en el lang/ja.json de la aplicación, el contenido de los archivos no se fusiona. Para no romper las traducciones existentes, indica al usuario un procedimiento para añadir solo las claves necesarias.
Translator::get() comprueba primero el JSON del idioma solicitado y, si no lo encuentra, busca la clave como clave en formato PHP. No recorre en orden el JSON del idioma de respaldo como hace con las traducciones PHP. Si usas frases en inglés como claves JSON, distingue este caso del comportamiento estándar en el que, si no hay traducción, se muestra la clave original.
El espacio de nombres de las traducciones PHP aísla las claves PHP de otros paquetes. Sin embargo, como Translator::get() busca primero una coincidencia exacta de clave en JSON, si defines en JSON una clave como courier::messages.delivery.queued, tendrá prioridad sobre la de PHP. Por lo general, adopta la política de no mezclar claves de texto con claves en formato PHP.

Actualizar sin romper las traducciones publicadas

A los usuarios que quieran publicar todas las traducciones PHP de una vez puedes indicarles un comando con el objetivo acotado.
Sin embargo, si se copian todos los valores predeterminados, esa copia pasa a ser también un valor de sobrescritura. Aunque corrijas una errata en el paquete, si la misma clave sigue en el archivo publicado, el nuevo valor no se verá. En cambio, las claves nuevas que no estén en la copia se completan desde el paquete.
Si solo cambias unos pocos textos, es más fácil incorporar las actualizaciones colocando únicamente las claves necesarias en el archivo de sobrescritura en lugar de publicar todos los archivos. Esta forma de trabajar aprovecha la sobrescritura parcial de las traducciones PHP.
Para el mantenimiento a largo plazo, diseña las actualizaciones en el siguiente orden.
  1. Mantén las claves y el espacio de nombres — Eliminar o mover una clave afecta a las llamadas a __() del usuario y a sus sobrescrituras. Considera añadir claves nuevas y conservar las antiguas durante un periodo de transición.
  2. Mantén los marcadores de posición — Cambiar :name por :recipient obliga a modificar también el array de reemplazo del código que llama. No lo consideres una corrección que afecta solo a los archivos de traducción.
  3. Compara las diferencias de los archivos publicados — Compara las sobrescrituras del usuario con los nuevos valores predeterminados. Si eliminas las claves de sobrescritura que ya no son necesarias, se vuelve a usar el valor del paquete.
  4. Evita la republicación incondicional — Republicar con --force sobrescribe las personalizaciones del usuario. En un diseño que copia el JSON en el archivo de la aplicación, incluso se pueden perder otras traducciones.
  5. Verifica en procesos de larga duración — Translator::load() guarda en la instancia los arrays por espacio de nombres, grupo e idioma. En un proceso donde permanece un Translator que ya ha cargado traducciones, cambiar los archivos no garantiza que se vuelvan a leer. Según tu operación, reinicia los workers u otros procesos.
La selección del objetivo de publicación y las opciones de sobrescritura se complementan en Assets públicos de paquetes y su actualización, y la evaluación de compatibilidad al actualizar versiones en Gestión de la compatibilidad de versiones de paquetes.

Elementos a verificar en la aplicación que usa el paquete

En una aplicación de verificación con el service provider registrado, comprueba las siguientes combinaciones. Para preparar el entorno de pruebas dentro del paquete, consulta Probar paquetes Laravel con Orchestra Testbench. En las pruebas que crean archivos de sobrescritura después de la carga, evita que influyan los resultados ya cargados por el Translator. Prepara los archivos antes de obtener las traducciones o usa una nueva instancia de la aplicación en cada caso.

Fuentes primarias consultadas

Para la documentación oficial se ha revisado la rama predeterminada más reciente, 13.x, y para la implementación interna, la última versión publicada en el momento de la consulta, v13.35.0.
Última modificación el 8 de octubre de 2026