Flutter : Créer une application mutlilingues

Vous avez besoin que votre application Flutter soit disponible en plusieurs langues mais vous ne savez pas comment vous y prendre ?
Ne vous inquiétez pas, EL TIGRE vous propose une solution simple et efficace !

 

Au préalable

  • Avoir installé Flutter
  • Avoir des notions de base de Dart et Flutter

 

Mettre en place son application pour supporter plusieurs langues

L’application que nous allons faire est très simple. Elle affichera simplement un texte à l’écran et nous allons changer la langue du téléphone. Nous allons alors voir en temps réel l’application se mettre à jour.

Cette solution se basera sur la librairie « flutter_localizations » native à flutter. Il faudra tout de même la spécifier dans notre fichier pubspec.yaml afin de pouvoir l’utiliser.

name: flutter_multilingues
description: Miltilingues application.

version: 1.0.0+1

environment:
  sdk: ">=2.1.0 <3.0.0"

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

  cupertino_icons: ^0.1.2

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

Pour commencer nous allons créer le fichier app_local.dart. Celui-ci comportera la classe qui regroupe tous les champs textes qui devront être traduits.

import 'package:meta/meta.dart';

class HomeLocal {
  String question;
  String ctaYes;
  String ctaNo;
  HomeLocal({
    @required this.question,
    @required this.ctaYes,
    @required this.ctaNo,
  });
}

abstract class AppLocal {
  HomeLocal get home;
}

AppLocal est une classe abstraite qui déclare un get du type HomeLocal. La classe HomeLocal définie tous les champs nécessaires au widget Home que nous allons créer plus tard.

Maintenant nous pouvons créer un dossier lib/locales qui contiendra deux fichiers : fr.dart et en.dart

lib/locales/fr.dart

import 'package:flutter_multilingues/app_locale.dart';

class FrLocal extends AppLocal {
  @override
  HomeLocal get home => HomeLocal(
        question: 'Aimez vous cette application ?',
        ctaYes: 'Oui',
        ctaNo: 'Non',
      );
}

 

lib/locales/en.dart

import 'package:flutter_multilingues/app_locale.dart';

class EnLocal extends AppLocal {
  @override
  HomeLocal get home => HomeLocal(
        question: 'Do you like this application ?',
        ctaYes: 'Yes',
        ctaNo: 'No',
      );
}

 

Nous pouvons voir que les deux classes FrLocal et EnLocal étendent la classe abstraite AppLocal. Il est donc nécessaire d’implémenter les surcouches de celles-ci.

Ici notre fameuse fonction get « home » qui retourne une instanciation de HomeLocal.

Créez maintenant un fichier lib/app_localizations.dart

import 'package:flutter/material.dart';
import 'package:flutter_multilingues/app_locale.dart';
import 'package:flutter_multilingues/locales/en.dart';
import 'package:flutter_multilingues/locales/fr.dart';

class AppLocalizations {
  final Locale locale;

  Map<String, AppLocal> _localizedValues = {
    'fr': FrLocal(),
    'en': EnLocal(),
  };

  AppLocalizations(this.locale);

  static AppLocalizations of(BuildContext context) =>
      Localizations.of<AppLocalizations>(context, AppLocalizations);

  AppLocal get lang => _localizedValues[locale.languageCode];
}

 

Nous créons ici :

  • Une classe AppLocalizations où l’on définit _localizedValues comme étant un Map ayant ses clés du type String et ses valeurs du type AppLocal.
  • La fonction get « lang » qui renvoie l’AppLocal en fonction de la clé du paramètre du type Local passé à la construction de la classe AppLocalizations
  • Et une fonction « of » qui permet de récupérer le widget du type AppLocalizations le plus proche du contexte avec lequel la fonction est appelée.

 

Ajoutons-y la classe AppLocalizationsDelegate qui étant LocalizationsDelegate<AppLocalizations>

class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
  const AppLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => true;

  @override
  Future<AppLocalizations> load(Locale locale) =>
      SynchronousFuture<AppLocalizations>(AppLocalizations(locale));

  @override
  bool shouldReload(AppLocalizationsDelegate old) => false;
}

N’oubliez pas d’importer :

import 'package:flutter/foundation.dart' show SynchronousFuture;

 

Cette classe est nécessaire lors de la création du widget MaterialApp afin de gérer les langues.

 

Créez maintenant le fichier lib/multilingues.dart qui définira le widget père de l’application

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

import './screens/home.dart';

class Multilingues extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Multilingues',
      localizationsDelegates: [
        const AppLocalizationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [
        const Locale('fr', ''),
        const Locale('en', ''),
      ],
      home: Home(),
    );
  }
}

Précisez bien les langues supportées avec le paramètre « supportedLocales » et les langues déléguées. Pour plus d’informations, référez-vous à la documentation officielle.

 

Enfin, créez le fichier lib/screens/home.dart

import 'package:flutter/material.dart';
import 'package:flutter_multilingues/app_locale.dart';

import '../app_localizations.dart';

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    AppLocal _local = AppLocalizations.of(context).lang;
    return Scaffold(
      body: Center(
        child: Text(_local.home.question),
      ),
    );
  }
}

Ici on récupère les données grâce à la fonction static « of » de notre classe AppLocal et nous les affichons.

Lancez l’application et vous devriez voir la question en français si votre téléphone est en français.

 

Comportement

Avec cette solution le comportement est naturel.

  • Si vous n’avez qu’une seule langue définie
    • Si elle est supportée par l’application, celle-ci sera utilisée.
    • Si elle n’est pas supportée, la première langue définie dans le tableau « supportedLocales » sera utilisée.
  • Si vous avez plusieurs langues définies
    • Si qu’une seule langue est supportée par l’application, celles-ci sera utilisée.
    • Si plusieurs langues sont supportées par l’application, elle utilisera la première langue supportée et classée la plus haute dans vos préférences.
    • Si aucunes n’est supportée, la première langue définie dans le tableau « supportedLocales » sera utilisée.

 

Voir le repo Bitbucket