Cambiar el locale de un contenedor (CT) a es_AR

El procedimiento depende del tipo de contenedor: LXC/LXD o Docker. En ambos casos, el locale debe generarse dentro del contenedor antes de establecer las variables de entorno.

⚠️ Nota específica para Debian 13 (trixie): locale-gen no acepta parámetros. Debe ejecutarse sin argumentos para que lea /etc/locale.gen y genere todos los locales habilitados. Además, localectl no es confiable en Debian; se debe usar update-locale.

Contenedores LXC/LXD (Debian/Ubuntu)

1. Instalar el paquete de locales (si no está)

apt update && apt install -y locales

2. Habilitar el locale es_AR en /etc/locale.gen

Editar el archivo y descomentar la línea:

es_AR.UTF-8 UTF-8

Se puede hacer con sed:

sed -i 's/^# *es_AR.UTF-8 UTF-8/es_AR.UTF-8 UTF-8/' /etc/locale.gen

Verificar que quedó bien:

grep es_AR /etc/locale.gen

Debe mostrar es_AR.UTF-8 UTF-8 sin #.

3. Generar el locale (SIN parámetros)

locale-gen

Debe aparecer Generating locales... es_AR.UTF-8... done.

⚠️ NO ejecutar locale-gen es_AR.UTF-8 ni locale-gen es_AR.UTF-8 UTF-8. En Debian 13 eso no genera el locale y falla silenciosamente.

4. Verificar que el locale quedó generado

locale -a | grep es_AR

Debe devolver es_AR.utf8.

Si aparecen advertencias tipo locale: Cannot set LC_CTYPE to default locale..., es porque la sesión actual arrastra variables de entorno apuntando a locales inexistentes. No impiden que el locale esté generado (ver sección Contingencias más abajo).

5. Configurar el locale del sistema con update-locale

update-locale LANG=es_AR.UTF-8

Si aparece una advertencia de Perl (perl: warning: Setting locale failed...), es esperable cuando la sesión actual tiene variables rotas. update-locale igual escribe /etc/default/locale correctamente. Verificar con cat /etc/default/locale.

6. Verificar

Salir del contenedor y volver a entrar para que la sesión cargue el nuevo /etc/default/locale:

locale

Salida esperada (sin advertencias):

LANG=es_AR.UTF-8
LC_CTYPE="es_AR.UTF-8"
LC_NUMERIC="es_AR.UTF-8"
LC_TIME="es_AR.UTF-8"
LC_COLLATE="es_AR.UTF-8"
LC_MONETARY="es_AR.UTF-8"
LC_MESSAGES="es_AR.UTF-8"
LC_PAPER="es_AR.UTF-8"
LC_NAME="es_AR.UTF-8"
LC_ADDRESS="es_AR.UTF-8"
LC_TELEPHONE="es_AR.UTF-8"
LC_MEASUREMENT="es_AR.UTF-8"
LC_IDENTIFICATION="es_AR.UTF-8"
LC_ALL=

Contenedores Docker

Los cambios en caliente se pierden al recrear el contenedor, existen dos opciones.

Opción A: En el Dockerfile (recomendado)

Para imágenes basadas en Debian/Ubuntu:

RUN apt-get update && apt-get install -y locales \
    && sed -i '/es_AR.UTF-8/s/^# //g' /etc/locale.gen \
    && locale-gen

ENV LANG=es_AR.UTF-8

⚠️ Nótese locale-gen sin parámetros. También se omite LC_ALL a propósito (ver Consideraciones).

Opción B: Al ejecutar el contenedor

Si la imagen ya tiene el locale generado, sobrescribe las variables:

docker run -e LANG=es_AR.UTF-8 -it <imagen> bash

Verificar

locale -a | grep es_AR
locale

Contingencias

Caso 1: locale: Cannot set LC_* to default locale: No such file or directory

Síntoma: al ejecutar locale, locale -a o update-locale, aparecen advertencias como:

locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory

Causa: la sesión actual tiene variables de entorno (LANG, LC_*) apuntando a locales que no existen en el contenedor. Esto ocurre típicamente porque:

  • El cliente SSH o el host envía variables LANG/LC_* heredadas.

  • Se exportaron variables LC_* manualmente en pasos anteriores y quedaron apuntando a locales que nunca se generaron.

Solución:

Las advertencias no impiden que locale-gen funcione. Verificar con locale -a | grep es_AR que el locale sí esté generado.

Limpiar el entorno de la sesión actual:

unset LC_ALL LC_CTYPE LC_MESSAGES LC_COLLATE LC_NUMERIC LC_TIME LC_MONETARY \
      LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION LANGUAGE
export LANG=es_AR.UTF-8
locale

Si las advertencias reaparecen en sesiones nuevas, el culpable es el cliente SSH (ver Caso 3).

Caso 2: perl: warning: Setting locale failed… Falling back to the standard locale («C»)

Síntoma: al ejecutar update-locale, Perl emite advertencias y menciona LANG = "en_US.UTF-8".

Causa: el proceso Perl heredó un entorno con locales inexistentes. Es la misma causa que el Caso 1.

Solución:

Es esperable en la primera ejecución si la sesión está rota. update-locale igual escribe /etc/default/locale.

Verifica con:

cat /etc/default/locale

Debe contener LANG=es_AR.UTF-8.

Salir y volver a entrar al contenedor para que la nueva sesión cargue la configuración correcta.

Caso 3: Las advertencias reaparecen en cada sesión nueva

Causa: el cliente (SSH o el host) envía variables LANG/LC_* que no existen en el contenedor.

Soluciones:

Para SSH: editar /etc/ssh/sshd_config en el contenedor y ajustar AcceptEnv para no aceptar LANG/LC_*:

AcceptEnv LANG LC_*      # ← comentar o eliminar esta línea

O bien, en el cliente, editar ~/.ssh/config:

Host <contenedor>
    SendEnv -LANG -LC_*

Caso 4: locale-gen no genera el locale aunque esté descomentado

Causa: en Debian 13, locale-gen con argumentos no funciona como en Ubuntu.

Solución: ejecutar siempre locale-gen sin parámetros. Verificar que /etc/locale.gen tenga la línea es_AR.UTF-8 UTF-8 sin #. Si el problema persiste, revisar que el paquete locales esté instalado (dpkg -l locales).

Caso 5: El locale se genera pero las aplicaciones siguen en inglés

Causa: aplicaciones específicas (PHP, Java, PostgreSQL, etc.) pueden tener su propia configuración de locale independiente del sistema.

Solución: revisar la configuración de locale de cada aplicación. Por ejemplo, en PostgreSQL se configura con lc_messages, lc_monetary, etc. en postgresql.conf.

Consideraciones

Imágenes minimalistas: En imágenes como Alpine o variantes -slim, el locale es_AR puede no estar disponible. En Alpine se requiere musl-locales y configurar LANG/LC_ALL manualmente.

Persistencia en Docker: los cambios hechos en un contenedor en ejecución se pierden al recrearlo. Usar siempre el Dockerfile o variables de entorno en docker run / docker-compose.yml.

  • LC_ALL vs LANG: LC_ALL sobrescribe todas las categorías y es difícil de sobrescribir. La wiki de Debian recomienda no configurarlo permanentemente. Usar solo LANG para el idioma predeterminado; si se necesita ajustar categorías específicas, usar LC_TIME, LC_NUMERIC, etc.

  • localectl en Debian: a diferencia de otras distros, en Debian localectl puede no estar disponible o no funcionar como se espera. Usa siempre update-locale.

  • No editar /etc/default/locale a mano: usar update-locale para mantenerlo consistente.