Centro de Ayuda

Localización en Flutter: Archivos ARB, Intl y Automatización

El sistema de localización integrado de Flutter usa archivos Application Resource Bundle (ARB) y el paquete intl para ofrecer experiencias totalmente nativas en cualquier idioma. Esta guía cubre desde la configuración del proyecto y detalles del formato ARB hasta el cambio de idioma, pluralización y automatización de traducciones con l10n.dev.

¿Qué es la localización en Flutter?

La localización en Flutter es el enfoque oficial para adaptar tu app a múltiples idiomas y regiones. Se basa en archivos ARB para almacenar cadenas traducidas y en el generador de código flutter_gen para producir accesores Dart con tipos seguros. En tiempo de ejecución, Flutter selecciona el archivo ARB correcto según la configuración regional del dispositivo, sin necesidad de reiniciar al cambiar el idioma programáticamente.

Configuración del Proyecto

La canalización de localización de Flutter se controla con dos archivos de configuración: pubspec.yaml y l10n.yaml. Activa la generación de código en pubspec.yaml y apunta Flutter al directorio de tus archivos ARB.

1. Actualiza pubspec.yaml

Agrega flutter_localizations e intl como dependencias, luego activa la bandera generate para que Flutter genere automáticamente las clases Dart de localización a partir de tus archivos ARB.

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any

flutter:
  generate: true

2. Crea l10n.yaml

Coloca un archivo l10n.yaml en la raíz de tu proyecto para configurar el directorio ARB, el archivo plantilla y el nombre del archivo de salida generado.

arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart

El Formato de Archivo ARB

ARB (Application Resource Bundle) es un formato basado en JSON diseñado específicamente para la internacionalización en Flutter. Cada clave corresponde a una cadena traducible, y las claves de metadatos opcionales (con prefijo @) contienen descripciones, definiciones de marcadores y contexto para traductores.

  • @@locale: Declara la configuración regional del archivo (por ejemplo, "en", "fr", "zh_CN"). l10n.dev actualiza automáticamente esto al código del idioma destino.
  • @@last_modified: Marca temporal de la última modificación. l10n.dev establece automáticamente este valor con la fecha y hora UTC actual al generar archivos traducidos.
  • Metadatos @key: Entradas de metadatos como descripción, ejemplo y marcadores NO se traducen por defecto; permanecen sin cambios para preservar el contexto para los traductores. Activa la opción translateMetadata si deseas que se traduzcan.
  • Marcadores y mensajes ICU: Las cadenas pueden contener marcadores nombrados ({name}) y sintaxis de mensajes ICU para pluralización y selección, los cuales se preservan correctamente durante la traducción.

Archivo ARB fuente (inglés)

{
  "@@locale": "en",
  "@@last_modified": "2026-01-15T10:30:00Z",

  "appTitle": "My App",
  "@appTitle": {
    "description": "The title of the application"
  },

  "welcome": "Welcome, {name}!",
  "@welcome": {
    "description": "Welcome message shown on the home screen",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "Alice"
      }
    }
  },

  "unreadMessages": "{count, plural, =0{No unread messages} =1{1 unread message} other{{count} unread messages}}",
  "@unreadMessages": {
    "description": "Number of unread messages",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}

Archivo ARB traducido (francés)

Tras la traducción, las cadenas de la interfaz se localizan mientras la estructura de metadatos permanece intacta. l10n.dev actualiza @@locale y @@last_modified automáticamente.

{
  "@@locale": "fr",
  "@@last_modified": "2026-01-15T10:30:01Z",

  "appTitle": "Mon Application",
  "@appTitle": {
    "description": "The title of the application"
  },

  "welcome": "Bienvenue, {name} !",
  "@welcome": {
    "description": "Welcome message shown on the home screen",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "Alice"
      }
    }
  },

  "unreadMessages": "{count, plural, =0{Aucun message non lu} =1{1 message non lu} other{{count} messages non lus}}",
  "@unreadMessages": {
    "description": "Number of unread messages",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}

Convenciones de Nomenclatura de Archivos

Los archivos ARB siguen un patrón sencillo: un prefijo (por defecto app_) seguido del código de la configuración regional y la extensión .arb. Flutter y l10n.dev usan guiones bajos para separar los códigos de idioma y región.

Los archivos ARB usan guiones bajos, no guiones medios: escribe app_en_US.arb y app_zh_CN.arb, no app_en-US.arb ni app_zh-CN.arb.
# Default pattern (recommended)
app_en.arb
app_fr.arb
app_en_US.arb          # Locale with region (underscore format)
app_zh_CN.arb          # Chinese Simplified

# Custom prefix patterns also supported
my_app_en.arb
my_app_fr.arb

# Note: ARB files use underscores, not hyphens
# ✓  app_en_US.arb
# ✗  app_en-US.arb

Estructura del Proyecto

Organiza todos tus archivos ARB dentro de una carpeta dedicada l10n dentro de lib/. El generador de código de Flutter los detecta automáticamente según la configuración arb-dir en l10n.yaml y genera clases Dart listas para usar.

lib/
├── l10n/
│   ├── app_en.arb        ← Source (English)
│   ├── app_fr.arb        ← French
│   ├── app_de.arb        ← German
│   ├── app_ja.arb        ← Japanese
│   ├── app_zh_CN.arb     ← Chinese Simplified
│   └── app_es.arb        ← Spanish
├── main.dart
└── ...

# Generated output (do not edit manually)
.dart_tool/
└── flutter_gen/
    └── gen_l10n/
        └── app_localizations.dart

Inicialización

Conecta la clase de localización Dart generada con MaterialApp proporcionando localizationsDelegates y supportedLocales. Flutter resolverá los datos ARB correctos para la configuración regional del dispositivo.

Configuración de MaterialApp

Pasa los cuatro delegados requeridos: tu AppLocalizations.delegate generado más los tres delegados del SDK de Flutter, y lista todas las configuraciones regionales que tu app soporta. Usa AppLocalizations.of(context)! en cualquier parte del árbol de widgets para acceder a las cadenas traducidas.

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',

      // Required delegates
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],

      // Supported locales
      supportedLocales: AppLocalizations.supportedLocales,

      home: const HomePage(),
    );
  }
}

// Use in a widget
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;

    return Scaffold(
      appBar: AppBar(title: Text(l10n.appTitle)),
      body: Center(child: Text(l10n.welcome('Alice'))),
    );
  }
}

Cambio de Idioma en Tiempo de Ejecución

Flutter permite cambiar la configuración regional de la app en tiempo de ejecución actualizando la propiedad locale en MaterialApp. Un patrón común es mantener un Locale en un StatefulWidget o en una solución de gestión de estado y exponer un callback para cambiarlo. El árbol de widgets se reconstruye automáticamente con la nueva configuración regional.

// Manage locale state at the app level
class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Locale _locale = const Locale('en');

  void _changeLocale(Locale locale) {
    setState(() => _locale = locale);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      locale: _locale,
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: AppLocalizations.supportedLocales,
      home: SettingsPage(onLocaleChange: _changeLocale),
    );
  }
}

// Language selector widget
class LanguageSelector extends StatelessWidget {
  final void Function(Locale) onLocaleChange;

  const LanguageSelector({super.key, required this.onLocaleChange});

  @override
  Widget build(BuildContext context) {
    return DropdownButton<Locale>(
      value: Localizations.localeOf(context),
      items: AppLocalizations.supportedLocales
          .map((locale) => DropdownMenuItem(
                value: locale,
                child: Text(locale.toLanguageTag()),
              ))
          .toList(),
      onChanged: (locale) {
        if (locale != null) onLocaleChange(locale);
      },
    );
  }
}

Pluralización

Flutter usa la sintaxis de mensajes ICU para la pluralización dentro de los archivos ARB. El paquete intl maneja todas las categorías plurales CLDR, aplicando automáticamente la forma correcta según las reglas del idioma destino.

  • Usa la sintaxis {count, plural, =0{...} =1{...} other{...}} dentro de los valores de cadena ARB.
  • Declara el marcador count con tipo int en los metadatos @key.
  • l10n.dev genera todas las formas plurales necesarias para cada idioma destino, incluyendo idiomas complejos como árabe, ruso y polaco, sin intervención manual.
{
  "cartItems": "{count, plural, =0{Your cart is empty} =1{1 item in your cart} other{{count} items in your cart}}",
  "@cartItems": {
    "description": "Cart item count",
    "placeholders": {
      "count": { "type": "int" }
    }
  },

  "daysLeft": "{days, plural, =1{1 day left} other{{days} days left}}",
  "@daysLeft": {
    "description": "Days remaining",
    "placeholders": {
      "days": { "type": "int" }
    }
  }
}

Soporte Completo de ARB en l10n.dev

l10n.dev está diseñado para integrarse perfectamente con el flujo de trabajo ARB de Flutter. Sube tu archivo ARB fuente y recibe traducciones precisas y correctamente estructuradas:

  • Actualizaciones Automáticas de Metadatos: @@locale se actualiza al código del idioma destino y @@last_modified se establece automáticamente con la fecha y hora UTC actual.
  • Control de Traducción de Metadatos: Por defecto, las entradas de metadatos @key (descripción, ejemplo, contexto) NO se traducen y permanecen sin cambios, manteniendo intactas las notas para traductores. Activa la opción translateMetadata para traducirlas junto con las cadenas de UI.
  • Prefijos de Archivo Personalizados: Se admite cualquier patrón de nombres: app_en.arb, my_app_en_US.arb, strings_fr.arb y más.
  • Formato de Configuración Regional con Guiones Bajos: Los códigos de configuración regional ARB usan guiones bajos (en_US, zh_CN) en lugar de guiones medios; l10n.dev gestiona esto correctamente para que los archivos generados se integren directamente en tu proyecto Flutter.
  • Consciente de la Pluralización: Se generan formas plurales ICU para cada idioma destino según las reglas CLDR, por lo que no es necesario editar manualmente los plurales tras la traducción.

Automatiza Traducciones con npm

Usa el paquete ai-l10n de npm para traducir tu archivo ARB fuente desde la línea de comandos o como parte de una canalización CI/CD. Instálalo una vez y traduce a cualquier número de idiomas con un solo comando.

# Install the CLI
npm install ai-l10n

# Translate your source ARB to multiple languages
npx ai-l10n translate lib/l10n/app_en.arb \
  --languages fr,de,ja,zh_CN,es,ko

Integración en una compilación de Flutter

Puedes integrar ai-l10n directamente en tu proceso de compilación de Flutter para que las traducciones estén siempre actualizadas antes de que se compile la aplicación. Dos enfoques comunes son un script de package.json o un Makefile.

Mediante scripts de package.json

Añade un script de traducción y utiliza el hook de ciclo de vida prebuild de npm para ejecutarlo automáticamente antes de cada compilación. Ejecuta npm run build:android (o build:ios / build:web) y ai-l10n traducirá primero, y luego pasará el control a Flutter.

{
  "scripts": {
    "translate": "ai-l10n translate lib/l10n/app_en.arb --languages fr,de,ja,zh_CN,es,ko --update",
    "prebuild": "npm run translate",
    "build:android": "flutter build apk",
    "build:ios": "flutter build ios",
    "build:web": "flutter build web"
  }
}

Mediante Makefile

Si tu equipo utiliza Make, declara un objetivo (target) de traducción y haz que cada objetivo de compilación dependa de él. Ejecutar make build-android (o build-ios / build-all) traducirá todos los idiomas de destino antes de invocar flutter build.

LANGUAGES = fr,de,ja,zh_CN,es,ko

translate:
	npx ai-l10n translate lib/l10n/app_en.arb --languages $(LANGUAGES) --update

build-android: translate
	flutter build apk

build-ios: translate
	flutter build ios

build-web: translate
	flutter build web

build-all: translate
	flutter build apk
	flutter build ios
	flutter build web

Para integración CI/CD, actualizaciones incrementales, traducción por lotes en múltiples archivos y ejemplos de flujos de trabajo en GitHub Actions, consulta la Guía de Automatización de Localización.

Extensión para VS Code

La extensión l10n.dev para VS Code trae la traducción de archivos ARB de Flutter directamente a tu editor. Haz clic derecho en cualquier archivo ARB y tradúcelo a tus idiomas objetivo sin salir de VS Code.

Cómo Funciona en VS Code:

  1. Abre tu archivo ARB fuente (por ejemplo, app_en.arb) en el editor.
  2. Haz clic derecho en el editor y selecciona "Translate JSON".
  3. Elige uno o más idiomas destino (por ejemplo, francés, japonés, alemán).
  4. La extensión crea archivos ARB localizados junto a tu fuente, con @@locale y @@last_modified actualizados automáticamente.

Míralo en Acción

Aquí tienes un ejemplo en vivo de la traducción de un archivo ARB de Flutter al uzbeko dentro de VS Code:

Flutter ARB localization in VS Code

Comienza a Localizar Tu App Flutter

¿Listo para llegar a usuarios globales? Puedes traducir archivos ARB directamente en el espacio de trabajo l10n.dev, automatizar con la CLI de npm o traducir directamente dentro de VS Code: