Cómo Traducir una App Flutter: Guía Completa

Aprende cómo localizar tu app Flutter usando Dart y el paquete intl. Esta guía completa cubre la localización de cadenas, pluralización, formato de fechas y mejores prácticas para la traducc

  • date icon

    Friday, Nov 14, 2025

Cómo Traducir una App Flutter: Guía Completa

Traducir tu app Flutter es esencial para llegar a una audiencia global. Flutter proporciona excelente soporte integrado para la localización a través del paquete intl y archivos ARB (Application Resource Bundle). Esta guía te guiará a través del proceso de traducir una app Flutter usando Dart.

Entendiendo la Localización en Flutter

Flutter utiliza archivos ARB (Application Resource Bundle) para almacenar traducciones. Estos archivos similares a JSON contienen pares clave-valor para cada idioma. El paquete intl de Flutter maneja la localización automáticamente basándose en la configuración de idioma del dispositivo del usuario.

Paso 1: Añadir Dependencias

Primero, añade los paquetes necesarios a tu pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: ^0.19.0

flutter:
  generate: true

Ejecuta flutter pub get para instalar los paquetes.

Paso 2: Configurar l10n.yaml

Crea un archivo l10n.yaml en la raíz de tu proyecto para configurar la localización:

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

Paso 3: Crear Archivos ARB

Crea un directorio lib/l10n y añade archivos ARB para cada idioma:

lib/l10n/app_en.arb (Inglés - por defecto):

{
  "@@locale": "en",
  "appName": "My App",
  "@appName": {
    "description": "The application name"
  },
  "welcomeMessage": "Welcome to our app!",
  "@welcomeMessage": {
    "description": "Welcome message displayed on home screen"
  },
  "buttonSubmit": "Submit",
  "@buttonSubmit": {
    "description": "Submit button label"
  },
  "errorNetwork": "Network error. Please try again.",
  "@errorNetwork": {
    "description": "Network error message"
  },
  "itemsCount": "{count, plural, =0{No items} one{1 item} other{{count} items}}",
  "@itemsCount": {
    "description": "Number of items",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  },
  "userGreeting": "Hello, {name}! You have {messageCount, plural, =0{no messages} one{1 message} other{{messageCount} messages}}.",
  "@userGreeting": {
    "description": "Greeting with user name and message count",
    "placeholders": {
      "name": {
        "type": "String"
      },
      "messageCount": {
        "type": "int"
      }
    }
  }
}

lib/l10n/app_es.arb (Español):

{
  "@@locale": "es",
  "appName": "Mi Aplicación",
  "welcomeMessage": "¡Bienvenido a nuestra aplicación!",
  "buttonSubmit": "Enviar",
  "errorNetwork": "Error de red. Por favor, inténtalo de nuevo.",
  "itemsCount": "{count, plural, =0{No hay elementos} one{1 elemento} other{{count} elementos}}",
  "userGreeting": "¡Hola, {name}! Tienes {messageCount, plural, =0{no hay mensajes} one{1 mensaje} other{{messageCount} mensajes}}."
}

lib/l10n/app_fr.arb (Francés):

{
  "@@locale": "fr",
  "appName": "Mon Application",
  "welcomeMessage": "Bienvenue dans notre application!",
  "buttonSubmit": "Soumettre",
  "errorNetwork": "Erreur réseau. Veuillez réessayer.",
  "itemsCount": "{count, plural, =0{Aucun élément} one{1 élément} other{{count} éléments}}",
  "userGreeting": "Bonjour, {name}! Vous avez {messageCount, plural, =0{aucun message} one{1 message} other{{messageCount} messages}}."
}

Paso 4: Generar Archivos de Localización

Ejecuta el generador de código:

flutter gen-l10n

O usa:

flutter pub run intl_utils:generate

Esto genera app_localizations.dart y archivos específicos de idioma en .dart_tool/flutter_gen/gen_l10n/.

Paso 5: Configurar MaterialApp

Actualiza tu main.dart para habilitar la localización:

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

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Localization Demo',
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: const [
        Locale('en'), // English
        Locale('es'), // Spanish
        Locale('fr'), // French
      ],
      home: const HomePage(),
    );
  }
}

Paso 6: Usar Cadenas Localizadas

Accede a las cadenas localizadas usando AppLocalizations.of(context):

Antes:

Text('Welcome to our app!')

Después:

Text(AppLocalizations.of(context)!.welcomeMessage)

O con un enfoque null-safe:

final l10n = AppLocalizations.of(context);
if (l10n != null) {
  Text(l10n.welcomeMessage)
}

Paso 7: Manejar Formato de Cadenas con Variables

Usa placeholders en archivos ARB y Flutter maneja el formato:

Archivo ARB:

{
  "userGreeting": "Hello, {name}!",
  "@userGreeting": {
    "placeholders": {
      "name": {
        "type": "String"
      }
    }
  }
}

Dart:

Text(AppLocalizations.of(context)!.userGreeting('John'))
// Inglés: "Hello, John!"
// Español: "¡Hola, John!"

Paso 8: Pluralización

Flutter soporta pluralización usando el formato de mensaje ICU:

Archivo ARB:

{
  "itemsCount": "{count, plural, =0{No items} one{1 item} other{{count} items}}"
}

Dart:

Text(AppLocalizations.of(context)!.itemsCount(5))
// Inglés: "5 items"
// Español: "5 elementos"

Text(AppLocalizations.of(context)!.itemsCount(1))
// Inglés: "1 item"
// Español: "1 elemento"

Text(AppLocalizations.of(context)!.itemsCount(0))
// Inglés: "No items"
// Español: "No hay elementos"

Paso 9: Formatear Fechas y Números

Usa el paquete intl para el formato localizado:

Fechas:

import 'package:intl/intl.dart';

final date = DateTime.now();
final formatter = DateFormat.yMMMMEEEEd(Intl.getCurrentLocale());
final localizedDate = formatter.format(date);
// Inglés: "Wednesday, March 20, 2025"
// Español: "miércoles, 20 de marzo de 2025"

Números:

import 'package:intl/intl.dart';

final number = 1234.56;
final formatter = NumberFormat.decimalPattern(Intl.getCurrentLocale());
final localizedNumber = formatter.format(number);
// Inglés: "1,234.56"
// Español: "1.234,56"

Moneda:

import 'package:intl/intl.dart';

final amount = 1234.56;
final formatter = NumberFormat.currency(locale: Intl.getCurrentLocale());
final localizedCurrency = formatter.format(amount);
// Inglés (US): "$1,234.56"
// Español (ES): "1.234,56 €"

Paso 10: Manejar Idiomas de Derecha a Izquierda (RTL)

Flutter maneja automáticamente los diseños RTL. Usa el widget Directionality si es necesario:

Directionality(
  textDirection: TextDirection.rtl, // o TextDirection.ltr
  child: YourWidget(),
)

O detecta automáticamente:

final locale = Localizations.localeOf(context);
final isRTL = locale.languageCode == 'ar' || locale.languageCode == 'he';

Paso 11: Probar tu Localización

Usando Flutter DevTools:

  1. Ejecuta tu app
  2. Abre DevTools
  3. Ve a la pestaña Inspector
  4. Cambia el locale en la configuración del dispositivo

Usando Configuración del Dispositivo:

  1. Ve a Settings > Language & Region del dispositivo
  2. Cambia el idioma del dispositivo
  3. Reinicia tu app

Programáticamente (para pruebas):

import 'package:flutter/material.dart';

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

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

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

  void _changeLanguage(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: const [
        Locale('en'),
        Locale('es'),
        Locale('fr'),
      ],
      home: LanguageSelector(
        onLanguageChanged: _changeLanguage,
      ),
    );
  }
}

Mejores Prácticas

1. Usar Claves Descriptivas

Malo:

{
  "msg1": "Submit"
}

Bueno:

{
  "buttonSubmit": "Submit",
  "@buttonSubmit": {
    "description": "Submit button label"
  }
}

2. Proporcionar Contexto en Archivos ARB

Siempre incluye entradas de metadatos @ para ayudar a los traductores:

{
  "deleteButton": "Delete",
  "@deleteButton": {
    "description": "Button to delete an item. Shown in the item detail view."
  }
}

3. Evitar Concatenación de Cadenas

Malo:

Text(AppLocalizations.of(context)!.hello + ' ' + name)

Bueno:

{
  "helloUser": "Hello, {name}!",
  "@helloUser": {
    "placeholders": {
      "name": {"type": "String"}
    }
  }
}
Text(AppLocalizations.of(context)!.helloUser(name))

4. Usar Pluralización Correctamente

Siempre usa el formato plural ICU para elementos contables:

{
  "messagesCount": "{count, plural, =0{No messages} one{1 message} other{{count} messages}}"
}

5. Probar Longitudes de Cadenas

Algunos idiomas son más largos que otros. Diseña tu UI para acomodar:

  • Alemán y finlandés: 30-50% más largos que el inglés
  • Idiomas asiáticos: Pueden necesitar más espacio vertical
  • Árabe y hebreo: Consideraciones de diseño RTL

6. Manejar Traducciones Faltantes

Flutter recurre al locale por defecto si falta una traducción. Siempre proporciona un fallback:

final l10n = AppLocalizations.of(context);
final text = l10n?.welcomeMessage ?? 'Welcome'; // Fallback

Errores Comunes

1. Olvidar Ejecutar la Generación de Código

Después de actualizar archivos ARB, siempre ejecuta:

flutter gen-l10n

2. No Incluir Todos los Delegados Requeridos

Asegúrate de incluir los cuatro delegados:

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

3. Codificar Cadenas de Formato

Malo:

Text('\$${amount.toStringAsFixed(2)}')

Bueno:

final formatter = NumberFormat.currency(locale: Intl.getCurrentLocale());
Text(formatter.format(amount))

4. No Probar Casos Extremos

Prueba con:

  • Cadenas muy largas
  • Caracteres especiales
  • Números y fechas
  • Formas plurales (0, 1, muchos)
  • Idiomas RTL

Avanzado: Cambio Dinámico de Idioma

Para permitir a los usuarios cambiar el idioma dentro de la app:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class LocaleProvider extends ChangeNotifier {
  Locale _locale = const Locale('en');
  
  Locale get locale => _locale;
  
  Future<void> loadLocale() async {
    final prefs = await SharedPreferences.getInstance();
    final languageCode = prefs.getString('language_code') ?? 'en';
    _locale = Locale(languageCode);
    notifyListeners();
  }
  
  Future<void> setLocale(Locale locale) async {
    if (_locale == locale) return;
    
    _locale = locale;
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString('language_code', locale.languageCode);
    notifyListeners();
  }
}

Uso:

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

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => LocaleProvider()..loadLocale(),
      child: Consumer<LocaleProvider>(
        builder: (context, localeProvider, _) {
          return MaterialApp(
            locale: localeProvider.locale,
            localizationsDelegates: const [
              AppLocalizations.delegate,
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              GlobalCupertinoLocalizations.delegate,
            ],
            supportedLocales: const [
              Locale('en'),
              Locale('es'),
              Locale('fr'),
            ],
            home: const HomePage(),
          );
        },
      ),
    );
  }
}

Usando con GetX (Alternativa)

Si estás usando GetX para gestión de estado:

import 'package:get/get.dart';

class LocaleController extends GetxController {
  var locale = const Locale('en').obs;
  
  void changeLocale(Locale newLocale) {
    locale.value = newLocale;
    Get.updateLocale(newLocale);
  }
}

Conclusión

Localizar tu app Flutter es sencillo cuando sigues estos pasos:

  1. Añade los paquetes flutter_localizations e intl
  2. Crea archivos ARB para cada idioma en lib/l10n/
  3. Configura l10n.yaml y ejecuta la generación de código
  4. Configura localizationsDelegates en MaterialApp
  5. Usa AppLocalizations.of(context) en toda tu app
  6. Maneja la pluralización con el formato de mensaje ICU
  7. Formatea fechas y números usando el paquete intl
  8. Prueba exhaustivamente en todos los idiomas soportados

Siguiendo estas prácticas, crearás una app que proporciona una experiencia nativa para usuarios de todo el mundo, expandiendo significativamente tu base de usuarios potencial.

Optimiza tu Flujo de Trabajo de Localización Flutter

Gestionar traducciones para múltiples idiomas puede volverse complejo a medida que tu app crece. Considera usar una plataforma de gestión de traducciones para:

  • Colaborar con traductores
  • Mantener las traducciones sincronizadas con tu código base
  • Automatizar el flujo de trabajo de traducción
  • Mantener la consistencia en todos los idiomas
  • Generar archivos ARB automáticamente
  • Integrar con tu pipeline CI/CD

¿Listo para llevar tu app Flutter a nivel global? Explora la plataforma de localización de AZbox y optimiza tu flujo de trabajo de traducción:

Ver Planes y Precios de AZbox

Blog

Latest Posts

Discover our latest articles and updates.

Why Translations Have Always Been a Problem in Software Development
date icon

Sunday, Dec 21, 2025

Why Translations Have Always Been a Problem in Software Development

For decades, software developers have struggled with translations and localization. What should be a straightforward pro

Read More
Cómo Traducir una App Flutter con Azbox: Guía Completa
date icon

Saturday, Dec 20, 2025

Cómo Traducir una App Flutter con Azbox: Guía Completa

Traducir tu app Flutter es esencial para llegar a una audiencia global. Azbox proporciona un potente SDK de Flutter que

Read More
How to Translate a Flutter App with Azbox: Complete Guide
date icon

Saturday, Dec 20, 2025

How to Translate a Flutter App with Azbox: Complete Guide

Translating your Flutter app is essential for reaching a global audience. Azbox provides a powerful Flutter SDK that sim

Read More
cta-image

Start Global Growth Today

Join hundreds of successful companies already using AZbox to reach customers worldwide. Start with a free trial, no credit card required.

Get Started - It's Free