> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Sobrescritura y actualización de traducciones de paquetes

> Analiza el cargador de traducciones de Laravel 13 y explica la sobrescritura parcial de traducciones PHP, las claves compartidas de las traducciones JSON y cómo actualizar sin romper las traducciones ya publicadas.

## 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](/es/localization) cubre las operaciones básicas en una aplicación y [Desarrollo de paquetes para Laravel](/es/advanced/package-development) 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.

<Info>
  `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`.
</Info>

## 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`.

```text theme={null}
courier/
├── src/
│   └── CourierServiceProvider.php
└── lang/
    ├── en/
    │   └── messages.php
    └── ja/
        └── messages.php
```

Prepara los valores predeterminados en japonés en `lang/ja/messages.php`.

```php theme={null}
<?php

return [
    'delivery' => [
        'queued' => ':nameさんへの配送を受け付けました。',
        'failed' => '配送できませんでした。',
    ],
];
```

Prepara también el inglés como respaldo en `lang/en/messages.php`.

```php theme={null}
<?php

return [
    'delivery' => [
        'queued' => 'Delivery to :name has been queued.',
        'failed' => 'Delivery failed.',
    ],
];
```

Registra la carga y, opcionalmente, la publicación en el método `boot()` del service provider.

```php theme={null}
<?php

namespace Acme\Courier;

use Illuminate\Support\ServiceProvider;

class CourierServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');

        $this->publishes([
            __DIR__.'/../lang' => $this->app->langPath('vendor/courier'),
        ], 'courier-translations');
    }
}
```

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.

```php theme={null}
echo __('courier::messages.delivery.queued', ['name' => '山田'], 'ja');
```

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')`.

```php theme={null}
<?php

return [
    'delivery' => [
        'queued' => ':name様への配送予約が完了しました。',
    ],
];
```

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()`.

```mermaid theme={null}
flowchart TD
    A["courier::messages.delivery.queued<br>locale: ja"] --> B["lang/ja/messages.php<br>del paquete"]
    B --> C["lang/vendor/courier/ja/messages.php<br>de la aplicación"]
    C --> D["Reemplazo de las claves indicadas<br>con array_replace_recursive"]
    D --> E["Obtención de la cadena traducida<br>y reemplazo de marcadores"]
```

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.

| Situación | Resultado |
| - | - |
| La clave existe en la aplicación | Ese valor sobrescribe el del paquete |
| Existe el mismo archivo, pero no la clave | Se mantiene el valor del paquete para el mismo idioma |
| No se encuentra la clave en el idioma solicitado | Normalmente se busca la traducción PHP de `fallback_locale` |
| La clave tampoco existe en el idioma de respaldo | Por defecto se devuelve la clave solicitada |

<Warning>
  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.
</Warning>

## 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.

```php theme={null}
public function boot(): void
{
    $this->loadJsonTranslationsFrom(__DIR__.'/../lang');
}
```

Ejemplo de `lang/ja.json` del paquete:

```json theme={null}
{
  "Courier delivery queued": "配送を受け付けました。"
}
```

```php theme={null}
echo __('Courier delivery queued', [], 'ja');
```

`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.

```json theme={null}
{
  "Courier delivery queued": "配送予約が完了しました。"
}
```

* 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.

<Warning>
  `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.
</Warning>

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.

```bash theme={null}
php artisan vendor:publish --provider="Acme\Courier\CourierServiceProvider" --tag=courier-translations
```

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.

<Tip>
  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.
</Tip>

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](/es/advanced/package-assets), y la evaluación de compatibilidad al actualizar versiones en [Gestión de la compatibilidad de versiones de paquetes](/es/advanced/package-versioning).

## 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](/es/advanced/package-testing).

| Caso | Qué comprobar |
| - | - |
| No se han publicado las traducciones PHP | Se obtienen el japonés y el inglés del paquete |
| Solo se sobrescribe `queued` en japonés | `queued` cambia y `failed` mantiene el valor predeterminado |
| Se añade una clave al actualizar el paquete | También se obtienen las claves que no están en el archivo de sobrescritura existente |
| La clave no existe en el idioma solicitado | Las traducciones PHP se obtienen del idioma de respaldo configurado |
| Se define la misma clave en JSON | En la configuración estándar prevalece el JSON de la aplicación |
| El JSON se coloca solo en `lang/vendor/courier` | En la configuración estándar no actúa como sobrescritura del JSON |
| Traducción que contiene `:name` | Coincide con el array de reemplazo del código que llama y no quedan cadenas sin reemplazar |

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`.

* [Documentación oficial de Laravel: archivos de idioma de paquetes](https://github.com/laravel/docs/blob/13.x/packages.md#language-files)
* [Documentación oficial de Laravel: sobrescritura de traducciones de paquetes](https://github.com/laravel/docs/blob/13.x/localization.md#overriding-package-language-files)
* [ServiceProvider: registro de traducciones](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Support/ServiceProvider.php)
* [TranslationServiceProvider: rutas de idioma estándar](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Translation/TranslationServiceProvider.php)
* [FileLoader: reemplazo recursivo de PHP y orden de carga de JSON](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Translation/FileLoader.php)
* [Translator: obtención con prioridad de JSON y arrays ya cargados](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Translation/Translator.php)
* [Pruebas oficiales: cargador de traducciones](https://github.com/laravel/framework/blob/v13.35.0/tests/Translation/TranslationFileLoaderTest.php)


## Related topics

- [Desarrollo de paquetes para Laravel](/es/advanced/package-development.md)
- [Temas avanzados](/es/advanced/index.md)
- [Sobrescritura y actualización de vistas de paquetes](/es/advanced/package-views.md)
- [Assets públicos de paquetes y su actualización](/es/advanced/package-assets.md)
- [Publicación y actualización de migraciones de paquetes](/es/advanced/package-migrations.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.