Flutter: ¿Cómo agregar soporte para múltiples idiomas en tu aplicación?

Hugo Grados
Comunidad Flutter
Published in
5 min readFeb 8, 2024

En un mundo globalizado, las aplicaciones móviles necesitan romper las barreras del idioma para llegar a una audiencia más amplia. Flutter, con su enfoque multiplataforma, facilita la internacionalización y la localización de tu app, permitiéndote ofrecer una experiencia personalizada a usuarios de diferentes idiomas.

1. Configuración del Proyecto Flutter

Para comenzar a utilizar flutter_localizations, necesitas agregar el paquete como una dependencia en tu archivo pubspec.yaml, junto con el paquete intl. Para hacerlo, ejecuta los siguientes comandos en tu terminal:

flutter pub add flutter_localizations --sdk=flutter
flutter pub add intl:any

Esto agregará las siguientes entradas a tu archivo pubspec.yaml :

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

2. Crear Archivo de Recursos de Localización

Dentro de la carpeta lib, crea una subcarpeta llamada l10n. Dentro de esta carpeta, crea un archivo llamado app_en.arb para almacenar tus recursos de localización en inglés.

3. Configurar Archivo de Configuración de Localización

Agrega un nuevo archivo YAML al directorio raíz del proyecto Flutter y nómbralo l10n.yaml. Dentro de este archivo, incluye el siguiente contenido para configurar la generación de archivos de localización:

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

4. Habilitar Generación Automática

Abre el archivo pubspec.yaml y habilita el indicador de generación para permitir la generación automática de archivos de localización:

flutter:
generate: true # Agrega esta línea

5. Agregar Contenido al Archivo de Recursos en Inglés

Dentro de ${FLUTTER_PROJECT}/lib/l10n, agrega el siguiente contenido al archivo app_en.arb:

{
"testMedium": "Test for Medium"
}

6. Agregar Archivo de Recursos en Español

Agrega otro archivo llamado app_es.arb en el mismo directorio. En este archivo, añade la traducción al español del mismo mensaje:

{
"testMedium": "Prueba para Medium"
}

7. Generar Archivos Automáticamente

Luego, ejecuta flutter pub get o flutter run en tu terminal. El generador de código realizará automáticamente la generación de archivos de localización. Puedes encontrar los archivos generados en ${FLUTTER_PROJECT}/.dart_tool/flutter_gen/gen_l10n.

8. Integrar la Localización en el Archivo Main

Dentro del archivo main.dart, asegúrate de importar las bibliotecas necesarias y de configurar la localización en el constructor de MaterialApp:

import 'package:flutter/material.dart';
import 'package:multilang_app/screens/my_app.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

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

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

@override
Widget build(BuildContext context) {
return const MaterialApp(
locale: Locale("EN"), //// Establece el idioma predeterminado a inglés
supportedLocales: AppLocalizations.supportedLocales,
localizationsDelegates: AppLocalizations.localizationsDelegates,
home: MyApp(),
);
}
}

9. Integración de Flutter Bloc para Manejar el Estado del Locale

Comencemos instalando las dependencias necesarias:

flutter pub add flutter_bloc
flutter pub add equatable

10. Definición del Archivo de Idiomas

Antes de crear el bloc, crearemos un archivo language.dart en una carpeta utils con la siguiente estructura:

import 'dart:ui';

enum Language { english, spanish }

extension LanguageExtension on Language {
String get locale {
switch (this) {
case Language.english:
return 'en';
case Language.spanish:
return 'es';
default:
return 'en';
}
}

String get name {
switch (this) {
case Language.english:
return 'English';
case Language.spanish:
return 'Español';
default:
return 'English';
}
}

String get flag {
switch (this) {
case Language.english:
return '🇺🇸';
case Language.spanish:
return '🇪🇸';
default:
return '🇺🇸';
}
}

Locale get localeValue {
switch (this) {
case Language.english:
return const Locale('en', "US");
case Language.spanish:
return const Locale('es', "ES");
default:
return const Locale('en', "US");
}
}
}

11. Estructura del Bloc de Localización

Crea la carpeta locale_bloc y dentro de ella los siguientes archivos:

  • locale_bloc.dart
  • locale_event.dart
  • locale_state.dart

12. Definición de Estados del Bloc de Localización

Dentro del archivo locale_state.dart, añade el siguiente contenido para definir los estados del bloque de localización. Inicializamos el idioma como inglés por defecto:

part of 'locale_bloc.dart';

sealed class LocaleState extends Equatable {
final Language selectedLanguage;
const LocaleState({Language? language})
: selectedLanguage = language ?? Language.english;

@override
List<Object> get props => [selectedLanguage];
}

final class LocaleInitial extends LocaleState {}

final class LocaleChanged extends LocaleState {
const LocaleChanged({super.language});
}

13. Definición de Eventos del Bloc de Localización

Dentro del archivo locale_event.dart, añade el siguiente contenido para definir los eventos del bloque de localización, específicamente el evento para cambiar el idioma:

part of 'locale_bloc.dart';

sealed class LocaleEvent extends Equatable {
const LocaleEvent();

@override
List<Object> get props => [];
}

class ChangeLanguage extends LocaleEvent {
final Language selectedLanguage;

const ChangeLanguage(this.selectedLanguage);

@override
List<Object> get props => [selectedLanguage];
}

14. Implementación del Bloc de Localización

En el archivo locale_bloc.dart, agrega el siguiente contenido para implementar el bloque de localización, incluyendo la lógica para manejar el evento de cambio de idioma:

import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:multilang_app/infrastructure/utils/language.dart';

part 'locale_event.dart';
part 'locale_state.dart';

class LocaleBloc extends Bloc<LocaleEvent, LocaleState> {
LocaleBloc() : super(LocaleInitial()) {
on<ChangeLanguage>(_onChangeLanguage);
}

_onChangeLanguage(ChangeLanguage event, Emitter<LocaleState> emit) {
emit(LocaleChanged(language: event.selectedLanguage));
}
}

15. Integración del LocaleBloc en main.dart

En el archivo main.dart, utilizamos MultiBlocProvider para proporcionar el LocaleBloc a toda la aplicación. Luego, en el BlocBuilder, configuramos el idioma de la aplicación según el estado inicial del LocaleBloc, que es inglés:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'presentation/blocs/locale_bloc/locale_bloc.dart';
import 'package:multilang_app/infrastructure/utils/language.dart';
import 'package:multilang_app/presentation/screens/my_app.dart';

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

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

@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<LocaleBloc>(create: (_) => LocaleBloc()),
],
child: BlocBuilder<LocaleBloc, LocaleState>(
builder: (context, state) {
return MaterialApp(
debugShowCheckedModeBanner: false,
locale: state.selectedLanguage.localeValue,
supportedLocales: AppLocalizations.supportedLocales,
localizationsDelegates: AppLocalizations.localizationsDelegates,
home: const MyApp(),
);
},
),
);
}
}

16. Utilización de AppLocalizations en MyApp

En la clase MyApp, importamos AppLocalizations y creamos la variable l10n para acceder a los textos localizados. Luego, utilizamos esta variable para mostrar el texto localizado en la interfaz de usuario:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:multilang_app/infrastructure/utils/language.dart';
import 'package:multilang_app/presentation/blocs/locale_bloc/locale_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

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

@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(
title: const Text('Multilang App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
BlocBuilder<LocaleBloc, LocaleState>(
builder: (context, state) {
return _buildLanguageSwitch(
context,
Theme.of(context),
state,
);
},
),
Text(
l10n.testMedium,
style: const TextStyle(fontSize: 25),
),
],
),
),
);
}
}

17. Creación del Widget buildLanguageSwitch

Creamos el widget buildLanguageSwitch que nos permite alternar entre los idiomas español e inglés en nuestra aplicación:

Widget _buildLanguageSwitch(
BuildContext context,
ThemeData theme,
LocaleState state,
) {
return TextButton(
onPressed: () {
context.read<LocaleBloc>().add(
ChangeLanguage(
state.selectedLanguage == Language.english
? Language.spanish
: Language.english,
),
);
},
child: RichText(
text: TextSpan(children: [
TextSpan(
text: "EN",
style: TextStyle(
fontSize: 18,
color: state.selectedLanguage == Language.english
? Colors.blue
: Colors.black,
),
),
const TextSpan(
text: " | ",
style: TextStyle(
fontSize: 18,
color: Colors.black,
),
),
TextSpan(
text: "ES",
style: TextStyle(
fontSize: 18,
color: state.selectedLanguage == Language.spanish
? Colors.blue
: Colors.black,
),
),
]),
),
);
}

En este proceso, hemos explorado paso a paso cómo implementar la internacionalización y localización en una aplicación Flutter de manera eficiente y organizada. Desde la configuración inicial del proyecto hasta la integración de Flutter Bloc para gestionar el estado del locale y la implementación de la alternancia entre idiomas en la interfaz de usuario, hemos demostrado cómo crear una aplicación multilingüe con facilidad.

Recursos:

El código fuente del proyecto está disponible en GitHub:

hdgch1106/multilang-app: Aplicación en flutter para altenar idiomas, utilizando flutter_localizations (github.com)

Gracias por leer!

--

--