Centro de ayuda

Localización en Flutter: archivos ARB, Intl y automatización

El sistema de localización integrado de Flutter utiliza archivos ARB (Application Resource Bundle) y el paquete intl para ofrecer experiencias totalmente nativas en cualquier idioma. Esta guía cubre todo, desde la configuración del proyecto y los detalles del formato ARB hasta el cambio de idioma, la pluralización y la 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 aplicación 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 descriptores de acceso Dart con seguridad de tipos. En tiempo de ejecución, Flutter selecciona el archivo ARB correcto según la configuración regional del dispositivo; no es necesario reiniciar al cambiar la configuración regional mediante programación.

Configuración del proyecto

La canalización de localización de Flutter se rige por dos archivos de configuración: pubspec.yaml y l10n.yaml. Habilita la generación de código en pubspec.yaml y apunta Flutter a tu directorio ARB.

1. Actualiza pubspec.yaml

Añade flutter_localizations e intl como dependencias, luego habilita la bandera generate para que Flutter genere automáticamente las clases de localización de Dart 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 de 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 de Flutter. Cada clave se asigna a una cadena traducible, y las claves de metadatos opcionales (con el prefijo @) contienen descripciones, definiciones de marcadores de posición y contexto para los traductores.

  • @@locale: Declara la configuración regional del archivo (por ejemplo, "en", "fr", "zh_CN"). l10n.dev actualiza esto automáticamente al código de idioma de destino.
  • @@last_modified: Marca de tiempo de la última modificación. l10n.dev establece esto automáticamente en la marca de tiempo UTC actual al generar archivos traducidos.
  • @key metadata: Las entradas de metadatos como la descripción, el ejemplo y los marcadores de posición NO se traducen de forma predeterminada; permanecen sin cambios para preservar el contexto para los traductores. Habilita el ajuste translateMetadata si deseas que se traduzcan.
  • Marcadores de posición y mensajes ICU: Las cadenas pueden contener marcadores de posición con nombre ({name}) y sintaxis de mensajes ICU para la pluralización y selección, todo lo cual se conserva correctamente durante la traducción.

Archivo ARB de origen (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)

Después de la traducción, las cadenas de la interfaz de usuario 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 de nomenclatura sencillo: un prefijo (por defecto app_) seguido del código de configuración regional y la extensión .arb. Flutter y l10n.dev utilizan 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 o 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 l10n dedicada 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 de Dart generada con MaterialApp proporcionando localizationsDelegates y supportedLocales. Flutter resolverá entonces 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 enumera cada configuración regional que admite tu aplicación. 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 te permite cambiar la configuración regional de la aplicación en tiempo de ejecución actualizando la propiedad locale en MaterialApp. Un patrón común es mantener una Locale en un StatefulWidget o una solución de gestión de estado y exponer una devolución de llamada para cambiarla. 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 utiliza la sintaxis de mensajes ICU para la pluralización dentro de los archivos ARB. El paquete intl maneja todas las categorías de plurales CLDR, aplicando automáticamente la forma correcta según las reglas del idioma de destino.

  • Usa la sintaxis {count, plural, =0{...} =1{...} other{...}} dentro de los valores de cadena ARB.
  • Declara el marcador de posición count con tipo int en los metadatos @key.
  • l10n.dev genera todas las formas plurales requeridas para cada idioma de destino, incluidos idiomas complejos como el árabe, el ruso y el 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 específicamente para funcionar a la perfección con el flujo de trabajo ARB de Flutter. Sube tu archivo ARB de origen y recibe traducciones precisas y correctamente estructuradas:

  • Actualizaciones automáticas de metadatos: @@locale se actualiza al código de idioma de destino y @@last_modified se establece automáticamente en la marca de tiempo UTC actual.
  • Control de traducción de metadatos: De forma predeterminada, las entradas de metadatos @key (descripción, ejemplo, contexto) NO se traducen y permanecen sin cambios, manteniendo intactas las notas del traductor. Habilita el ajuste translateMetadata para traducirlos junto con las cadenas de la interfaz de usuario.
  • Prefijos de archivo personalizados: Se admite cualquier patrón de nomenclatura: 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 maneja esto correctamente para que los archivos generados se integren directamente en tu proyecto de Flutter.
  • Consciente de la pluralización: Las formas plurales ICU se generan para cada idioma de destino de acuerdo con las reglas CLDR, por lo que no es necesaria la edición manual de plurales después de la traducción.

Automatiza traducciones con npm

Usa el paquete npm ai-l10n para traducir tu archivo ARB de origen desde la línea de comandos o como parte de una canalización CI/CD. Instálalo una vez y luego 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 conectar ai-l10n directamente en tu proceso de compilación de Flutter para que las traducciones estén siempre actualizadas antes de compilar la aplicación. Dos enfoques comunes son un script package.json o un Makefile.

A través de scripts de package.json

Añade un script de traducción y usa el gancho 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, 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"
  }
}

A través de Makefile

Si tu equipo usa Make, declara un objetivo 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 obtener información sobre la integración CI/CD, actualizaciones incrementales, traducción por lotes en varios archivos y ejemplos de flujo de trabajo de GitHub Actions, consulta la Guía de automatización de localización.

Extensión de VS Code

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

Cómo funciona en VS Code:

  1. Abre tu archivo ARB de origen (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 de destino (por ejemplo, francés, japonés, alemán).
  4. La extensión crea archivos ARB localizados junto a tu origen, con @@locale y @@last_modified actualizados automáticamente.

Véalo en acción

Aquí tienes un ejemplo en vivo de cómo traducir un archivo ARB de Flutter al uzbeko dentro de VS Code:

Flutter ARB localization in VS Code

Empieza a localizar tu aplicación Flutter

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