讓 Flutter App 支援多國語系的開發流程

zonble
7 min readJul 24, 2018

--

在使用 Flutter 開發應用程式,要加入多國語系的時候,可以發現,Flutter 的多國語系字串並不是獨自的字串檔案,不是某種 XML 或是 JSON 格式的設定檔,而是專案程式碼的一部分。

你要自己先產生一個實作了 WidgetsLocalizations 的物件(這邊姑且先稱為「翻譯物件」),在這個物件中建立對應的 property,然後在建立整個 app 的 root widget(屬於 MaterialApp class),在 MetarialApp 的 localizationsDelegates 屬性中,包含你的翻譯物件的 delegate…光講到這邊我就覺得你應該不知道我在講什麼,官方這篇文件 — Internationalizing Flutter Apps — 寫得也不清不楚。

如果用手動的方式維護這個「翻譯物件」的內容,新增或刪除某個語系,增加或減少某個字串,都要自行修改程式碼,也十分麻煩。所以,要開始製作 Flutter 的多國語系,我們不妨先把官方文件丟到一邊,直接從安裝 Android Studio 裡頭的 Flutter i18n plug-in 開始。這個 plug-in 的用途,在於幫你自動從你的翻譯字串檔中產生對應的 Dart 程式碼。

安裝 Flutter i18n Plug-in

雖然在 Android Studio 以及 Visual Studio Code 裡頭,官方都提供了 Flutter 的開發環境,但是實際寫了一陣子之後,個人還是覺得 Android Studio 的整合程度比較高些。在 Android Studio 中,我們先去設定的 Plug-in 分頁中,按下 Browse Repository 按鈕。

然後搜尋 Flutter i18n

點下去就可以完成安裝,系統會要求您重新啟動 Android Studio。

pubspec.yaml 設定

要讓你的應用程式開始支援多國語系,首先得安裝 flutter_localizations 套件,方法是在你的 Futter 專案的 pubspec.yaml 裡頭,多加上幾行。找一下 dependencies 的段落,改成:

dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
cupertino_icons: ^0.1.2

接著執行 flutter packages get 更新相依套件。你也可以讓 IDE 幫你更新。

在 Android Studio 裡頭,編輯 pubspec.yaml 檔案時,畫面上方有套件管理的相關命令可以直接使用。

arb 檔案以及 generated/i18n.dart

用裝了 Flutter i18n 的 Android Studio 打開你的 Flutter 專案後,你可以發現在 res 資料夾下,有個叫做 values/strings_en.arb 的檔案。這個檔案是 JSON 格式的文字檔,只要改動 res/values 底下的 arb 檔案,Android Studio 就會幫你產生對應的程式碼。

空白的 arb 檔案

增加一個繁體中文設定檔 strings_zh_TW.arb ,隨便修改一下 arb 檔案裡頭的內容。

就會看到 IDE 在 lib 資料夾底下,產生了 generated/i18n.dart。

generated/i18n.dart 是程式自動產生的,每次改動 arb 檔案,都會自動產生一份新的檔案,所以不要手動編輯這個檔案。

設定 MaterialApp

回到 main.dart ,import 必要的檔案,並且調整 MaterialApp 的設定。

這邊我們做了幾件事情:

加入 Google 官方定義好的多國語系翻譯

Google 在 Flutter 環境中本身提供的 Widget,其實不少本身就已經翻譯好了多國語文,我們就沒有必要再自己翻譯一次。我們剛剛透過 pubspec.yaml 裡頭安裝的 flutter_localizations,就是 Google 提供的翻譯字串套件。

這段程式碼中,我們首先 import 了 package:flutter_localizations/flutter_localizations.dart,然後在 localizationsDelegates 中,加入了 GlobalMaterialLocalizations 與 GlobalWidgetsLocalizations 的 delegate,就是在做這件事情。

加入我們自己的翻譯語系

由於我們的翻譯字串是在 generated/i18n.dart 中,所以要 import 這個檔案。在 generated/i18n.dart 定義了一個叫做 S 的物件,所以,S 的 delegate 也要加入到 MaterialApp 的 localizationsDelegates 中。

S 的 delegate 包含了這個翻譯物件支援哪些語系的資訊,所以我們將 MaterialApp 的 supportedLocales 設為 S 的 delegate 的 supportedLocales,指定這個 App 支援哪些語系。localeResolutionCallback 則在指定如果某個語系字串不完整時,改用哪的語系,例如中文字串設定少了某個字串時,這邊就指定成改用英文語系。

使用翻譯字串

我們剛剛定義了 login、logout 這兩個字串,使用時,就是寫成

S.of(context).login

比方說,我們寫個非常簡單的,只有一個按鈕的 Widget

就可以看到執行的結果

iOS 的額外設定

要讓 Flutter App 在 iOS 上可以使用多國語系,我們還需要在 Xcode 裡頭做一些額外的設定。打開 Xcode 裡頭,打開 Flutter 專案目錄下的 Runner 專案,然後在 Localization 段落的地方按下加號按鈕,新增語系。

不過,在 iOS 上想讓 Flutter App 支援繁體中文還有問題。我們可能設定的語系檔是 zh_TW,而在 Xcode 增加的繁體中文語系是 zh-Hant,兩者可能就對應不起來。而在 iOS 上,Flutter 似乎只能辨認 Language Code,無法辨認 Country Code。

我們把 Localizations.localeOf(context).toString( ) 在不同平台上印出來看一下,在 Android 上可以印出 zh_TW,但是在 iOS 上只能印出 zh_。

也就是說,目前在 iOS 上想要支援中文,只能告訴系統我們用的是 zh,但這樣會無法區分是簡體中文還是繁體中文…。這應該是一個官方需要修正的 bug。

--

--

zonble
zonble

Written by zonble

XDDDD - eXtreme Due Date Driven Development

Responses (1)