flutter中常用的國際化是Intl,通常會(huì)生成這樣的目錄結(jié)構(gòu)

image.png
然后在代碼中的使用方式為
MaterialApp(
localizationsDelegates: [S.delegate],
),
S.of(context).test;
看到of想必大家能聯(lián)想起InheritedWidget,其實(shí)國際化本質(zhì)就是依托于InheritedWidget
下面我們從后往前推,先看下S.of(context)
static S of(BuildContext context) {
final instance = S.maybeOf(context);
assert(instance != null,
'No instance of S present in the widget tree. Did you add S.delegate in localizationsDelegates?');
return instance!;
}
static S? maybeOf(BuildContext context) {
return Localizations.of<S>(context, S);
}
這里出現(xiàn)了Localizations
static T? of<T>(BuildContext context, Type type) {
assert(context != null);
assert(type != null);
final _LocalizationsScope? scope = context.dependOnInheritedWidgetOfExactType<_LocalizationsScope>();
return scope?.localizationsState.resourcesFor<T?>(type);
}
然后是_LocalizationsScope,他是我們要找的InheritedWidget

image.png
所以,可想而知,我們的國家化的內(nèi)容用該是通過這里獲取
然后我們看看
_LocalizationsScope是在哪里創(chuàng)建的
image.png

image.png
最終
WidgetsApp就是在MaterialApp中創(chuàng)建的通過上邊的源代碼發(fā)現(xiàn),我們最初傳入的
[S.delegate]給到了Localizations的delegates屬性,而Localizations的state,是賦值給了_LocalizationsScope的localizationsState屬性所以此時(shí)思路應(yīng)該清晰,Localizations負(fù)責(zé)管理所有的國際化,而
_LocalizationsScope是負(fù)責(zé)國際化上下文的管理這個(gè)時(shí)候我們返回頭再看
Localizations.of<S>(context, S)干了什么
image.png

image.png
繼續(xù)尋找
_typeToResources的來源
image.png

image.png
這里可以看到Localizations的delegates最終轉(zhuǎn)化成了_LocalizationsState的_typeToResources,而_typeToResources是以國際化的類型與國際化的實(shí)例作為鍵值對(duì)的形式存儲(chǔ)了起來
到此項(xiàng)目中使用國際化的詳細(xì)流程就結(jié)束了
這里我們可以優(yōu)化的一點(diǎn)是:如果是如果我們不想在使用的時(shí)候依托于上下文,來使用國際化,我們可以尋找一個(gè)恰當(dāng)?shù)臅r(shí)機(jī)來保存一個(gè)_LocalizationsScope創(chuàng)建之后的一個(gè)BuildContext,因?yàn)檫@個(gè)BuildContext足以通過上下文獲取到國際化的內(nèi)容,這就有很多種方式了,這列舉一種:onGenerateTitle中的context
因?yàn)橥ㄟ^上下文

image.png

image.png

image.png
這里的title最終會(huì)到
_LocalizationsScope下游,所以我們可以保存onGenerateTitle中的BuildContext
MaterialApp(
onGenerateTitle: (BuildContext context) {
globalContext = context;
return "title";
},
localizationsDelegates: [S.delegate],
)
T getLanguage<T>() {
final instance = Localizations.of<T>(globalContext, T);
assert(instance != null, '沒有找到${T}');
return instance!;
}
在使用的時(shí)候,直接提供Type就可以了,實(shí)現(xiàn)了國際化與BuildContext樹的解耦
getLanguage<S>().test;