Categorías: Flutter

Flutter: Do you speak English?, Parles-tu français? Hablas español?

Flutter, por defecto, sólo proporciona localizaciones para inglés de Estados Unidos. Por lo tanto, si queremos que nuestra aplicación esté localizada en castellano, vamos a tener que indicárselo. Veamos cómo.

Configurando nuestra aplicación

Lo primero que debemos hacer es añadir en nuestro fichero pubspec.yaml el paquete flutter_localizations. Lo correcto es que esté justo debajo del sdk:flutter o también podemos instalarlo desde la consola con la siguiente línea de comando: flutter pub add flutter_localizations --sdk=flutter

Nuestro fichero pubspec.yaml debería quedar así:

dependencies:
flutter:
  sdk: flutter
flutter_localizations:
  sdk: flutter

Esto nos dará acceso a todo lo necesario para continuar internacionalizando nuestra aplicación. Entre estas cosas, el paquete nos da acceso a los delegados que controlan las traducciones necesarias para los widgets de Android o de iOS que utilicemos, así cómo las traducciones de otros widgets genéricos de Flutter.

Estos delegados respectivamente son:

GlobalMaterialLocalizations.delegate
GlobalCupertinoLocalizations.delegate
GlobalWidgetsLocalizations.delegate

Para usarlos en nuestra aplicación, deberemos añadirlos en el constructor de nuestra MaterialApp como localizationsDelegates

return const MaterialApp(
   localizationsDelegates: [
     GlobalMaterialLocalizations.delegate,
     GlobalWidgetsLocalizations.delegate,
     GlobalCupertinoLocalizations.delegate
         
   ]);

Mas adelante veremos cómo crear nuestro propio delegado para traducir  cadenas de textos, pero por ahora, sigamos configurando la aplicación.

Lo siguiente que debemos hacer es indicarle qué idiomas vamos a soportar. Para ello debemos seguir modificando el constructor de nuestra MaterialApp. En el ejemplo, vamos a soportar el español de España e inglés genérico, sin código de país.

return const MaterialApp(
    localizationsDelegates: [
      GlobalMaterialLocalizations.delegate,
      GlobalWidgetsLocalizations.delegate,
      GlobalCupertinoLocalizations.delegate
         
    ],
    supportedLocales: const [
      Locale('es', 'ES'), //Español de españa
      Locale('en'),       //Inglés, cualquier país
    ],);

Una vez añadidos los idiomas que vamos a soportar, ya podríamos arrancar nuestra aplicación y, por ejemplo, si colocamos un CalendarDatePicker en nuestra página principal y cambiamos el idioma de nuestro teléfono de Español a Inglés, veremos cómo el primer día de la semana del calendario cambia de lunes a domingo y viceversa.

class _MyHomePageState extends State<MyHomePage> {
 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: Text(widget.title),
     ),
     body: Column(
       mainAxisAlignment: MainAxisAlignment.start,
       children: <Widget>[
          CalendarDatePicker(
               initialDate: DateTime.now(),
               firstDate: DateTime(1900),
               lastDate: DateTime(2100),
               onDateChanged: (value) {}),
       ],
     ),
   );
 }
}

Construyendo nuestro propio delegado

Ahora veamos cómo hacer para traducir nuestras propias cadenas de texto. Como ya hemos dicho, vamos a necesitar crear un delegado. Lo bueno es que, de la parte de «crear el delegado» se va encargar el generador de código de Flutter. Nosotros sólo tenemos que crear un fichero de configuración con formato .yaml, los ficheros de recursos con formato .arb y habilitar el generador de código de Flutter

Comencemos por el fichero de configuración. Este fichero lo colocamos en la raíz del proyecto y, como estamos hablando de localizar nuestra aplicación, lo podemos llamar l10n.yaml.
El contenido del fichero será el siguiente:

l10n.yaml

arb-dir: lib/l10n
template-arb-file: strings_es.arb
output-localization-file: app_localizations.dart
untranslated-messages-file: untranslated.txt
  • arb-dir: Indica la carpeta donde vamos a colocar los ficheros con las traducciones.
  • template-arb-file: Indica el fichero de traducciones por defecto de nuestra aplicación. Este fichero deberá estar incluido en la carpeta que hemos escrito en la opción anterior ( arb-dir ) y como ya sabemos, tendrá el formato .arb que básicamente es muy parecido a un fichero .json y en su contenido tendremos una serie de identificadores de las cadenas a traducir, su traducción y una breve descripción. Más adelante veremos esto con detalle. En este ejemplo, el fichero lo he llamado strings_es.arb, pero podría llamarse papa_es.arb. Lo importante es entender que este será el fichero plantilla para la generación del código, es decir, los identificadores de las cadenas de texto que no estén en este fichero, pero sí puedan estar en otros, no se tendrán en cuenta para la generación.
  • output-localization-file: Indica el nombre del fichero que Flutter debe generar con el delegado para soportar los diferentes lenguajes que utilicemos. Lo podemos llamar como queramos, pero la clase que generará se llamará AppLocalizations con lo que por convención el archivo lo llamamos app_localizations.dart
  • untranslated-messages-file: Este apartado no es obligatorio, pero, en mi opinión, es realmente útil al indicarlo y poner un nombre de fichero con extensión .txt. El proceso de generación nos escribirá en él los posibles errores durante el proceso de generación, identificadores de cadenas que no existen en un fichero u otro por ejemplo, con lo que facilita el mantenimiento de nuestras traducciones.

Este sería el contenido básico del fichero de configuración para la generación de nuestro delegado. Hay muchas mas opciones que puedes consultar aquí.

Añadiendo nuestras traducciones

Nuestro siguiente paso es generar los ficheros con las traducciones, como ya hemos visto. Estos ficheros deberán estar en la carpeta lib/l10n. Recordemos que tendremos tantos ficheros como idiomas queramos soportar.

En el fichero de configuración hemos decidido que los ficheros se van a llamar strings<código de idiona>.arb, por lo que en nuestro ejemplo, deberíamos terminar con dos ficheros:

En su forma mas sencilla, el contenido de los ficheros será el siguiente:

strings_en.arb

{
"titleApp": "Traducciones",
"@titleApp": {
"description": "El título de la aplicación"
},
"helloWorld": "Hola Mundo!",
"@helloWorld": {
"description": "El saludo convencional del programador novato."
}
}

Y por lo tanto el contenido del fichero strings_en.arb deberá ser:

{
"titleApp": "Translations!",
"@titleApp": {
"description": "The title of the app"
},
"helloWorld": "Hello World!",
"@helloWorld": {
"description": "The conventional newborn programmer greeting"
}
}

  • Identificador de la cadena: El identificador de la cadena debe ser único y estará acompañado del valor traducido. En el ejemplo estamos viendo el fichero en español. Este identificativo deberá existir igual en el fichero strings_en.arb, pero con la traducción de la palabra Traducciones al idioma inglés.
  • Referencia al indicador: La generación del código podemos controlarla gracias al formato .arb. Con este formato podemos añadir descripciones para la cadena e incluso operaciones más complejas, como configurar placeholders, la pluralización o sustitución de valores dentro de la cadena traducida, etc. Para más información sobre cómo controlar la generación puedes consultarla aquí.

Activando la generación de código

Ya por último, sólo nos queda habilitar la generación de código de Flutter. Para ello, volvemos al fichero pubspec.yaml y buscamos la parte de Flutter, ahí añadimos generate: true.

El fichero debería quedar de la siguiente manera:

flutter:
 generate: true

Ahora, desde el terminal, debemos realizar un flutter clean y un flutter pub get. Si todo ha ido bien, que sí, Flutter nos habrá generado en nuestra carpeta de proyecto la siguiente estructura:

Vemos que tenemos los ficheros app_localizations_en.dart, app_localizations_**_es**.dart y app_localizations.dart. Este último es el delegado que controlará nuestras traducciones, y si lo abrimos, ya nos explica los siguientes pasos que debemos seguir para añadir el delegado en la aplicación.

Añadiendo nuestro delegado

Como último paso, debemos añadir nuestro delegado en la lista de delegados para la localización. Esta lista la añadimos en MaterialApp casi al principio de este tutorial.

Para poder configurarlo, primero debemos importar el fichero en nuestro main.dart o donde estemos inicializando MaterialApp

import 'package:flutter_gen/gen_l10n/app_localizations.dart';

Y luego ya podemos añadir el delegado

return const MaterialApp(
   localizationsDelegates: [
     AppLocalizations.delegate,
     GlobalMaterialLocalizations.delegate,
     GlobalWidgetsLocalizations.delegate,
     GlobalCupertinoLocalizations.delegate
         
   ],
   supportedLocales: const [
     Locale('es', 'ES'), //Español de españa
     Locale('en'),       //Inglés, cualquier país
   ],);

Ya podemos usar nuestras cadenas de texto y ver cómo son traducidas, para ello basta con invocarlas de la siguiente manera:

AppLocalizations.of(context)!.helloWorld

Podemos hacerlo dentro de cualquier widget, por ejemplo, añadamos un widget de texto debajo del calendario

class _MyHomePageState extends State&lt;MyHomePage&gt; {
 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: Text(widget.title),
     ),
     body: Column(
       mainAxisAlignment: MainAxisAlignment.start,
       children: &lt;Widget&gt;[
          CalendarDatePicker(
               initialDate: DateTime.now(),
               firstDate: DateTime(1900),
               lastDate: DateTime(2100),
               onDateChanged: (value) {}),
         Text(AppLocalizations.of(context)!.helloWorld),
       ],
     ),
   );
 }
}

Ahora,  si ejecutamos la aplicación y cambiamos el idioma, veremos cómo nuestro widget de texto, con el texto Hola Mundo! será traducido al idioma seleccionado.

Y voilà, hemos terminado de localizar nuestra aplicación de Flutter, por lo menos en cuanto a las cadenas de texto y los controles por defecto… porque, existe otro paquete que nos ayudará también a localizar nuestra aplicación dándonos herramientas para el formato numérico, el formato de las fechas e incluso para trabajar mejor con nuestros ficheros .arb. Ese paquete es intl, pero ese, será otro post 😉

Tienes el código de ejemplo en este enlace.

Compartir
Publicado por
Ciani Afonso Díaz

Este sitio web utiliza cookies para que tengas la mejor experiencia de usuario. Si continuas navegando, estás dando tu consentimiento para aceptar las cookies y también nuestra política de cookies (esperemos que no te empaches con tanta cookie 😊)