DEV Community

Odinachi David
Odinachi David

Posted on

Localization in Flutter with ChatGPT

What is an App if everybody can’t get to use it or even more because of language barriers?

Here’s how you can bridge that gap in your Flutter app.

Before we start we need to ensure all our strings are in a single class and accessed using getters.

1. Install Packages

we need to first install flutter_translate and flutter_localization packages

flutter_translate: ^4.0.4 
flutter_localization: ^0.2.1
Enter fullscreen mode Exit fullscreen mode

2. Initializing Localization

This is where we set the languages we want to support and we do this by initializing our delegate and providing LocalizedApp on the topmost widget.

Future<void> main() async {
  var delegate = await LocalizationDelegate.create(
      fallbackLocale: 'en', supportedLocales: ['en', 'es', 'fr', 'de']);

  runApp(LocalizedApp(delegate, const MyApp()));
}
Enter fullscreen mode Exit fullscreen mode

What we did here was initialize our app with the delegate and the delegate supports Spanish, French and German, also note that the locale code has to be correct so you can check here and pick the first characters before the underscore(two or three).

3. Add Delegate to MaterialApp

We need to set the supported locale for the app.

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

  @override
  Widget build(BuildContext context) {
    var localizationDelegate = LocalizedApp.of(context).delegate;
    return MaterialApp(
      title: AppString.flutterDemo,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        localizationDelegate
      ],
      supportedLocales: localizationDelegate.supportedLocales,
      locale: localizationDelegate.currentLocale,
      home: const MyHomePage(),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Set up iOS

We need to provide iOS with our supported locale.

   <key>CFBundleLocalizations</key>
        <array>
            <string>en</string>
            <string>es</string>
            <string>fr</string>
            <string>de</string>
        </array>
Enter fullscreen mode Exit fullscreen mode

5. Setup Assets

Firstly we need to create an i18n folder in the assets folder, so this folder will contain all our json translations that were set in our supported locale and add it to our pubspec.

assets:
  - assets/i18n/
Enter fullscreen mode Exit fullscreen mode

Then we need to ask chatGPT to generate the json translations for each of the words in our AppString class, here’s a sample prompt

generate the translation for this class using this example

class AppString { static String get keyName => translate(key) }

and the json should be

{ key: translated_text }

generate for english, spanish, french and german

this is the class

class AppString { static String get selectLanguage => 'Select Language';

static String get flutterDemo => 'Flutter Demo';

static String get interestingStories => 'Interesting Stories';

static String get story1 => "Once upon a time, in a faraway land, a young prince was cursed to live as a beast until he learned to love.";

static String get story2 => "A group of explorers discovered an ancient city hidden beneath the ice of Antarctica.";

static String get story3 => "A boy found a mysterious key that opened a door to another dimension.";

static String get story4 => "A scientist accidentally created a potion that made him invisible, but the effects were irreversible.";

static String get story5 => "During a space mission, an astronaut encountered a strange, glowing object that gave him superpowers.";

static String get story6 => "A small village in Japan has a forest where it is said people can communicate with spirits.";

static String get story7 => "In a world where time stops for everyone except for one person, that person becomes the guardian of time.";

static String get story8 => "A magical library exists where the books write themselves, containing stories of people’s dreams.";

static String get story9 => "A pirate ship sailing through the Caribbean found a map leading to the legendary lost city of gold.";

static String get story10 => "A woman wakes up every day with no memory of her past, but she leaves herself clues hidden around the house.";

}

now copy and past the respective json in into the file on asset

  1. Change your locale Changing your locale will automatically change the language automatically
  Widget _languageOption(String language) {
    return RadioListTile<String>(
      title: Text(language),
      value: language,
      groupValue: langNotifier.value,
      onChanged: (String? value) {
        langNotifier.value = value!;
        changeLocale(context, getLangString(value)); // Chnage the locale
        Navigator.of(context).pop(); // Close the modal after selection
      },
    );
  }
Enter fullscreen mode Exit fullscreen mode

here’s the complete code

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_translate/flutter_translate.dart';
import 'package:language_app/app/app_string.dart';

Future<void> main() async {
  var delegate = await LocalizationDelegate.create(
      fallbackLocale: 'en', supportedLocales: ['en', 'es', 'fr', 'de']);

  runApp(LocalizedApp(delegate, const MyApp()));
}

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

  @override
  Widget build(BuildContext context) {
    var localizationDelegate = LocalizedApp.of(context).delegate;
    return MaterialApp(
      title: AppString.flutterDemo,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        localizationDelegate
      ],
      supportedLocales: localizationDelegate.supportedLocales,
      locale: localizationDelegate.currentLocale,
      home: const MyHomePage(),
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ValueNotifier<String> langNotifier = ValueNotifier('en');

  @override
  void initState() {
    super.initState();
  }

  void _showLanguageModal() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text(AppString.selectLanguage),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              _languageOption('English'),
              _languageOption('Español'),
              _languageOption('Français'),
              _languageOption('Deutsch'),
            ],
          ),
        );
      },
    );
  }

  Widget _languageOption(String language) {
    return RadioListTile<String>(
      title: Text(language),
      value: language,
      groupValue: langNotifier.value,
      onChanged: (String? value) {
        langNotifier.value = value!;
        changeLocale(context, getLangString(value));
        Navigator.of(context).pop(); // Close the modal after selection
      },
    );
  }

  String getLangString(String value) {
    switch (value) {
      case "English":
        return 'en';
      case 'Español':
        return 'es';

      case 'Français':
        return 'fr';

      case 'Deutsch':
        return 'de';
      default:
        return 'en';
    }
  }

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder(
      valueListenable: langNotifier,
      builder: (_, value, child) {
        List<String> allStories = [
          AppString.story1,
          AppString.story2,
          AppString.story3,
          AppString.story4,
          AppString.story5,
          AppString.story6,
          AppString.story7,
          AppString.story8,
          AppString.story9,
          AppString.story10,
        ];
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(AppString.interestingStories),
            actions: [
              IconButton(
                icon: const Icon(Icons.language),
                onPressed: _showLanguageModal,
              ),
            ],
          ),
          body: Column(
            children: [
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(
                  '${AppString.selectLanguage}: ${langNotifier.value}',
                  style: Theme.of(context).textTheme.headlineSmall,
                ),
              ),
              Expanded(
                child: ListView.builder(
                  itemCount: allStories.length,
                  itemBuilder: (context, index) {
                    String story = allStories[index];
                    return ListTile(
                      title: Text(story),
                    );
                  },
                ),
              ),
            ],
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _showLanguageModal,
            tooltip: AppString.selectLanguage,
            child: const Icon(Icons.language),
          ),
        );
      },
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Here’s the repo: https://github.com/Odinachi/flutter-localization

Here’s the video explaining it better: https://www.youtube.com/watch?v=xerUWn_s-xs

Happy coding!!

Top comments (0)