How to create a Offline Internationalization App:Support multiple languages
Tags: flutter, sqlite, offline, strapi
Published: 2021-10-11 08:29:06

There is a column of `locale` in the Sqlite database that supports multiple languages, so you only need to change the Sql query conditions to find out the data in different languages.

![image-20211010174334-jvp95ah](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqoek2ytyd3uyfl8c8t4.png)

Modify `VegetableDao` to add language query conditions 

`[project_root]/lib/app/data/dao/vegetalbe_dao.dart`

```dart
import 'package:floor/floor.dart';
import 'package:strapi_flutter_internation_poc/app/data/entity/vegetable.dart';

@dao
abstract class VegetableDao {
  @Query('SELECT * FROM vegetables_v WHERE  locale = :locale')
  Future<List<VegetableV>> findAll(String locale);
}

```

Re-run the Floor code generator after modification


```dart
flutter packages pub run build_runner build
```

`HomeController`

`[project_root]/lib/app/modules/home/controllers/home_controller.dart`

```dart
  Future<void> getAllVegetables() async {
    final result = await DbService.to.db.vegetableDao.findAll('en');
    vegetables.value = result;
  }
```

The data displayed in this way is all in English

![image-20211010175216-r3ixc2x](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ocbrso7emd5n9dogoh6.png)

Next, integrate the internationalization features of GetX

Create a new language_service

`[project_root]/lib/app/common/services/language_service.dart`
 
Here, `get_storage` is used as a cache for the default language. Remember to increase the dependency of this library in the Flutter project. Use the command `get install get_storage` to quickly complete the installation.


```dart
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';

class LanguageService extends GetxService {
  static LanguageService get to => Get.find();

  var box = GetStorage();
  var locale = Locale('en', 'US');
  var localeKey = 'en';

  Future<LanguageService> init() async {
    if (box.read('language') != null) {
      if (box.read('language') == 'zh-CN') {
        locale = Locale('zh', 'CN');
        localeKey = 'zh-CN';
      } else {
        locale = Locale('en', 'US');
        localeKey = 'en';
      }
    } else {
      if (ui.window.locale.languageCode == 'zh') {
        locale = Locale('zh', 'CN');
        localeKey = 'zh-CN';
      } else {
        locale = Locale('en', 'US');
        localeKey = 'en';
      }
    }

    return this;
  }

  void changeLocale(l) {
    if (l == Locale('zh', 'CN')) {
      localeKey = 'zh-CN';
      updateLocale(Locale('zh', 'CN'));
    } else if (l == Locale('en', 'US')) {
      localeKey = 'en';
      updateLocale(Locale('en', 'US'));
    }
    box.write('language', localeKey);
  }

  void updateLocale(_l) {
    locale = _l;
    Get.updateLocale(_l);
  }
}

```

GetX Cli can quickly generate the multi-language configuration required by the GetX framework from a JSON file.

Create two new JSON files under `[project_root]/assets/locales`


`en_US.json`

```json
{
  "app": {
    "name": "VAF"
  },
  "locale": {
    "title": "Language",
    "zh": "中文",
    "en": "English"
  }
}
```

`zh_CN.json`

```json
{
  "app": {
    "name": "蔬果"
  },
  "locale": {
    "title": "语言",
    "zh": "中文",
    "en": "English"
  }
}
```

run


```json
get generate locales assets/locales
```

out`[project_root]/lib/generated/locales.g.dart`


```dart
class AppTranslation {
  static Map<String, Map<String, String>> translations = {
    'zh_CN': Locales.zh_CN,
    'en_US': Locales.en_US,
  };
}

class LocaleKeys {
  LocaleKeys._();
  static const app_name = 'app_name';
  static const locale_title = 'locale_title';
  static const locale_zh = 'locale_zh';
  static const locale_en = 'locale_en';
}

class Locales {
  static const zh_CN = {
    'app_name': '蔬果',
    'locale_title': '语言',
    'locale_zh': '中文',
    'locale_en': 'English',
  };
  static const en_US = {
    'app_name': 'VAF',
    'locale_title': 'Language',
    'locale_zh': '中文',
    'locale_en': 'English',
  };
}

```

Add the initialization of LanguageService in main.dart


```dart
Future<void> initServices() async {
  print('starting services ...');
  await Get.putAsync(() => DbService().init());
  await Get.putAsync(() => LanguageService().init());
  print('All services started...');
}
```

Modify `runApp` to add multi-language configuration


```dart
  runApp(
    GetMaterialApp(
      title: "Application",
      initialRoute: AppPages.INITIAL,
      getPages: AppPages.routes,
      translationsKeys: AppTranslation.translations,
      locale: LanguageService.to.locale,
      fallbackLocale: Locale('zh', 'CN'),
    ),
  );
```

Adjust the query conditions in the Controller


```dart
final result = await DbService.to.db.vegetableDao.findAll('en');
```

To


```dart
    final result = await DbService.to.db.vegetableDao
        .findAll(LanguageService.to.localeKey);
```

Modify the text in the interface to reference multilingual resources


```dart
      appBar: AppBar(
        title: Text('Vegetables'),
        centerTitle: true,
      ),
```

To

```dart
      appBar: AppBar(
        title: Text(LocaleKeys.app_name.tr),
        centerTitle: true,
      ),
```

Run it again to see the interface that defaults to Chinese

![image-20211010182410-m6ayfcq](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jelovo7hgxu001dm4lg0.png)

Make a little improvement and add a button to switch languages


```dart
appBar: AppBar(
        title: Text(LocaleKeys.app_name.tr),
        centerTitle: true,
        actions: [
          IconButton(
              onPressed: () {
                Get.dialog(SimpleDialog(
                  title: Text(LocaleKeys.locale_title.tr),
                  children: <Widget>[
                    SimpleDialogOption(
                      onPressed: () {
                        LanguageService.to.changeLocale(Locale('en', 'US'));
                      },
                      child: Padding(
                        padding: const EdgeInsets.symmetric(vertical: 6),
                        child: Text(LocaleKeys.locale_en.tr),
                      ),
                    ),
                    SimpleDialogOption(
                      onPressed: () {
                        LanguageService.to.changeLocale(Locale('zh', 'CN'));
                      },
                      child: Padding(
                        padding: const EdgeInsets.symmetric(vertical: 6),
                        child: Text(LocaleKeys.locale_zh.tr),
                      ),
                    ),
                  ],
                ));
              },
              icon: Icon(Icons.language))
        ],
      ),
```

Very convenient and fast to complete the language switch

![image-20211010183432-nqf0vo3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uok2bq5sg63vf7sm009b.png)
 
 
---

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lfajbsflhz9t8zpfm7ap.png)
 

[![Play Store](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ocrcqncrb8uyhym5m2so.png)](https://play.google.com/store/apps/details?id=com.nasawz.diet_therap)


[![Apple Store](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6gwvms69chncj8lf5qe.png)](https://apps.apple.com/us/app/%E8%94%AC%E6%9E%9C%E9%A3%9F%E7%96%97/id1588683566)