# 實現Localizations
前面講了Material組件庫如何支持國際化,本節我們將介紹一下我們自己的UI中如何支持多語言。根據上節所述,我們需要實現兩個類:一個Delegate類一個Localizations類,下面我們通過一個實例說明。
### 實現Localizations類
我們已經知道Localizations類中主要實現提供了本地化值,如文本:
```
//Locale資源類
class DemoLocalizations {
DemoLocalizations(this.isZh);
//是否為中文
bool isZh = false;
//為了使用方便,我們定義一個靜態方法
static DemoLocalizations of(BuildContext context) {
return Localizations.of<DemoLocalizations>(context, DemoLocalizations);
}
//Locale相關值,title為應用標題
String get title {
return isZh ? "Flutter應用" : "Flutter APP";
}
//... 其它的值
}
```
DemoLocalizations中會根據當前的語言來返回不同的文本,如`title`,我們可以將所有需要支持多語言的文本都在此類中定義。DemoLocalizations的實例將會在Delegate類的`load`方法中創建。
### 實現Delegate類
Delegate類的職責是在Locale改變時加載新的Locale資源,所以它有一個`load`方法,Delegate類需要繼承自LocalizationsDelegate類,實現相應的接口,示例如下:
```
//Locale代理類
class DemoLocalizationsDelegate extends LocalizationsDelegate<DemoLocalizations> {
const DemoLocalizationsDelegate();
//是否支持某個Local
@override
bool isSupported(Locale locale) => ['en', 'zh'].contains(locale.languageCode);
// Flutter會調用此類加載相應的Locale資源類
@override
Future<DemoLocalizations> load(Locale locale) {
print("xxxx$locale");
return SynchronousFuture<DemoLocalizations>(
DemoLocalizations(locale.languageCode == "zh")
);
}
@override
bool shouldReload(DemoLocalizationsDelegate old) => false;
}
```
`shouldReload`的返回值決定當Localizations Widget重新build時,是否調用`load`方法重新加載Locale資源。一般情況下,Locale資源只應該在Locale切換時加載一次,不需要每次在Localizations 重新build時都加載,所以返回`false`即可。可能有些人會擔心返回`false`的話在APP啟動后用戶再改變系統語言時`load`方法將不會被調用,所以Locale資源將不會被加載。事實上,每當Locale改變時Flutter都會再調用`load`方法加載新的Locale,無論`shouldReload`返回`true`還是`false`。
### 最后一步:添加多語言支持
和上一節中介紹的相同,我們現在需要先注冊DemoLocalizationsDelegate類,然后再通過`DemoLocalizations.of(context)`來動態獲取當前Locale文本。
只需要在MaterialApp或WidgetsApp的`localizationsDelegates`列表中添加我們的Delegate實例即可完成注冊:
```
localizationsDelegates: [
// 本地化的代理類
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
// 注冊我們的Delegate
DemoLocalizationsDelegate()
],
```
接下來我們可以在Widget中使用Locale值:
```
return Scaffold(
appBar: AppBar(
//使用Locale title
title: Text(DemoLocalizations.of(context).title),
),
... //省略無關代碼
)
```
這樣,當在美國英語和中文簡體之間切換系統語言時,APP的標題將會分別為“Flutter APP”和“Flutter應用”。
## 總結
本節我們通過一個簡單的示例說明了Flutter應用國際化的基本過程及原理。但是上面的實例還有一個嚴重的不足就是我們需要在DemoLocalizations類中獲取`title`時手動的判斷當前語言Locale,然后返回合適的文本。試想一下,當我們要支持的語言不是兩種而是8種甚至20幾種時,如果為每個文本屬性都要分別去判斷到底是哪種Locale從而獲取相應語言的文本將會是一件非常復雜的事。還有,通常情況下翻譯人員并不是開發人員,能不能像i18n或i10n標準那樣可以將翻譯單獨保存為一個arb文件交由翻譯人員去翻譯,翻譯好之后開發人員再通過工具將arb文件轉為代碼。答案是肯定的!我們將在下一節介紹如何通過Dart intl包來實現這些。
- 緣起
- 起步
- 移動開發技術簡介
- Flutter簡介
- 搭建Flutter開發環境
- 常見配置問題
- Dart語言簡介
- 第一個Flutter應用
- 計數器示例
- 路由管理
- 包管理
- 資源管理
- 調試Flutter APP
- Dart線程模型及異常捕獲
- 基礎Widgets
- Widget簡介
- 文本、字體樣式
- 按鈕
- 圖片和Icon
- 單選框和復選框
- 輸入框和表單
- 布局類Widgets
- 布局類Widgets簡介
- 線性布局Row、Column
- 彈性布局Flex
- 流式布局Wrap、Flow
- 層疊布局Stack、Positioned
- 容器類Widgets
- Padding
- 布局限制類容器ConstrainedBox、SizeBox
- 裝飾容器DecoratedBox
- 變換Transform
- Container容器
- Scaffold、TabBar、底部導航
- 可滾動Widgets
- 可滾動Widgets簡介
- SingleChildScrollView
- ListView
- GridView
- CustomScrollView
- 滾動監聽及控制ScrollController
- 功能型Widgets
- 導航返回攔截-WillPopScope
- 數據共享-InheritedWidget
- 主題-Theme
- 事件處理與通知
- 原始指針事件處理
- 手勢識別
- 全局事件總線
- 通知Notification
- 動畫
- Flutter動畫簡介
- 動畫結構
- 自定義路由過渡動畫
- Hero動畫
- 交錯動畫
- 自定義Widget
- 自定義Widget方法簡介
- 通過組合現有Widget實現
- 實例:TurnBox
- CustomPaint與Canvas
- 實例:圓形漸變進度條(自繪)
- 文件操作與網絡請求
- 文件操作
- Http請求-HttpClient
- Http請求-Dio package
- 實例:Http分塊下載
- WebSocket
- 使用Socket API
- Json轉Model
- 包與插件
- 開發package
- 插件開發:平臺通道簡介
- 插件開發:實現Android端API
- 插件開發:實現IOS端API
- 系統能力調用
- 國際化
- 讓App支持多語言
- 實現Localizations
- 使用Intl包
- Flutter核心原理
- Flutter UI系統
- Element和BuildContext
- RenderObject與RenderBox
- Flutter從啟動到顯示