Flutter-國(guó)際化適配終結(jié)者

大家好,很久不見(jiàn),甚是想念,今天,我們來(lái)學(xué)習(xí)以下如何使用國(guó)際化神器Flutter i18n,該神器為一位叫Razvan Lung的外國(guó)大佬開(kāi)發(fā)的!完美解決Flutter在開(kāi)發(fā)應(yīng)用時(shí),字符串資源統(tǒng)一存放的問(wèn)題,好的,我們現(xiàn)在開(kāi)始學(xué)習(xí)吧!

Flutter i18n官網(wǎng) 插件已經(jīng)棄用,以下安裝將會(huì)找不到插件,最新使用方法見(jiàn)文章

安裝插件

該神器為idea的一款插件,名為Flutter i18n,大家可以到開(kāi)發(fā)工具的設(shè)置中找得到。我這里使用的是Android Studio工具開(kāi)發(fā),idea工具也是可以找到的,vscode就不知道了,哈哈。

image.png

如圖,先打開(kāi)到上面的Plugins這一欄,然后點(diǎn)擊插件列表下面的Browe repositories,然后在彈出的界面中輸入Flutter i18n。
image.png

然后點(diǎn)擊右邊的綠色按鈕install,下載安裝完之后會(huì)要求重啟開(kāi)發(fā)工具,重啟就可以了
image.png

使用

如果你已經(jīng)成功安裝插件,打開(kāi)項(xiàng)目后,會(huì)發(fā)現(xiàn)自動(dòng)添加以下兩個(gè)文件:

  • lib/generated/i18n.dart 主要的國(guó)際化文件,主要使用的類(lèi)為S
  • res/values/string_en.arb 該文件主要適配英文語(yǔ)言,內(nèi)容為json格式
    到這里我們會(huì)出現(xiàn)疑惑,.arb是什么格式的文件,下面我們來(lái)了解以下.arb格式

ARB文件

arb文件.png

ARB文件擴(kuò)展名為:Application Resource Bundle 意為應(yīng)用程序資源包,并得到Google的支持,每個(gè).arb文件都包含一個(gè)JSON表,該表從資源ID映射到本地化值,文件名包含已為其轉(zhuǎn)換值的語(yǔ)言環(huán)境,你可以選中res/values點(diǎn)擊右鍵-New-Arb File,在彈出的界面中選擇你要的語(yǔ)言環(huán)境
image.png

如圖上:

  • 第一欄為語(yǔ)言
  • 第二欄為特定的區(qū)域
    為了方便理解我們?cè)?code>Language一欄中拉到底部找到zh:Chinese,在右邊可以很明確的知道特定區(qū)域表示什么
    image.png
  • Any Region 表示所有地區(qū),優(yōu)先級(jí)為:特定地區(qū)>所有地區(qū)
  • CN:China 中國(guó)(大陸)
  • HK:Hong Kong SAR China 香港特別行政區(qū)
  • MO:Macau SAR China 澳門(mén)特別行政區(qū)
  • SG:Singapore 新加波
  • TW:Taiwan 臺(tái)灣
    看到這里,是不是清晰了很多

添加國(guó)際化支持

在使用該插件支持,我們還是要知道,該插件依賴(lài)插件包flutter_localizations,否則會(huì)出現(xiàn)某些地區(qū)支持會(huì)出錯(cuò)

在我們的項(xiàng)目的pubspec.yaml下添加flutter_localizations

....
dependencies:
  flutter_localizations:
    sdk: flutter
....

然后在命令行運(yùn)行下Flutter packages get
回到我們有MaterialApp或者MaterialApp或者CupertinoApp的文件下,導(dǎo)入以下包,我的是main.dart文件

import 'generated/i18n.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

我使用的是剛新建的Flutter項(xiàng)目,添加下面的內(nèi)容

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
//   new
      localizationsDelegates: const [
        S.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: S.delegate.supportedLocales,
// new
      home: MyHomePage(title: '本地化'),
    );
  }
}

來(lái)一個(gè)一個(gè)的解釋以下:

  • localizationsDelegates本地化委托參數(shù)
  • S.delegate 我們項(xiàng)目的本地化委托類(lèi),這個(gè)你不用管,他會(huì)根據(jù)你的arb文件自動(dòng)生成對(duì)應(yīng)的函數(shù)
  • GlobalMaterialLocalizations.delegateGlobalWidgetsLocalizations.delegateflutter_localizations插件包提供的委托,如果你使用MaterialApp這個(gè)部件的GlobalMaterialLocalizations.delegate這個(gè)可以用不
  • supportedLocales支持的本地化
  • S.delegate.supportedLocales我們項(xiàng)目支持的本地化,這個(gè)你不用管,它會(huì)在你添加arb文件時(shí)自動(dòng)更新你的支持的本地化

聲明資源

現(xiàn)在我們可以在.arb文件下添加JSON內(nèi)容了
string_en.arb添加如下:

{
  "appName":"Carpe Diem"
}

如果你想支持中文,可以按上面的Ard文件操作步驟進(jìn)行創(chuàng)建
string_zn_CN.arb內(nèi)容如下:

{
  "appName":"及時(shí)行樂(lè)"
}

支持香港
string_zn_HK.arb內(nèi)容如下:

{
  "appName":"及時(shí)行樂(lè)"
}

使用資源

使用資源,我們只需要一行代碼

S.of(context).appName

why?這樣就可以了?嗯,是的,插件會(huì)在你寫(xiě)json的時(shí)候會(huì)自動(dòng)生成函數(shù)
S類(lèi)自動(dòng)添加:

  String get appName => "Carpe Diem";

$zh_CN類(lèi)自動(dòng)添加

  @override
  String get appName => "及時(shí)行樂(lè)";

$zh_HK類(lèi)自動(dòng)添加

  @override
  String get appName => "及時(shí)行樂(lè)";

Arb文件更多語(yǔ)法

  • 1.占位符
{
  "dialogTip":"Hello $name"
}

使用:

S.of(context).dialogTip("Rhyme");
  • 2.復(fù)數(shù)
    支持語(yǔ)法為:key+zero/one/many/other
{
  "selectZero":"沒(méi)有了",
  "selectOne":"一個(gè)",
  "selectMany":"很多",
  "selectOther":"其它"
}

使用:

    S.of(context).select(0);//零個(gè)
    S.of(context).select(1);//一個(gè)
    S.of(context).select("many");//多個(gè)
    S.of(context).select(null);//其它
  • 3.忽略$符號(hào)
    如果你要忽略該符號(hào),請(qǐng)?jiān)谇懊婕?code>\反斜杠

提取字符串

很多時(shí)候,我們需要像Android一樣,將光標(biāo)放到字符串中,使用快捷鍵alt+enter對(duì)字符串進(jìn)行快速提取,該插件也同樣適應(yīng)

將編輯光標(biāo)放在所要提取的字符串后,使用快捷鍵alt+enter,可以看到如圖所示:

image.png

選中Extract the string resource,會(huì)出現(xiàn)如下界面:
image.png

  • String id 對(duì)應(yīng)為json表中的key
  • String value 對(duì)應(yīng)為json表中的value
  • Create the string for languages 為需要添加到的語(yǔ)言文件,可以多選
  • 下面的四個(gè)按鈕分別為:添加一種語(yǔ)言、刪除一種語(yǔ)言、全選、全不選

點(diǎn)擊ok之后,就會(huì)自動(dòng)替換


image.png

指定一種語(yǔ)言

有時(shí)候,我們需要指定一種語(yǔ)言,那么我們?cè)撛趺床僮髂兀@里直接上代碼

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: S.of(context).flutter_demo,
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      localizationsDelegates: const [
        S.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: S.delegate.supportedLocales,
// new 
      localeResolutionCallback:
          S.delegate.resolution(fallback: const Locale('en', '')),
// new
      home: MyHomePage(title: '本地化'),
    );
  }
}

或者

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: S.of(context).flutter_demo,
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      localizationsDelegates: const [
        S.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: S.delegate.supportedLocales,
// new 
      localeListResolutionCallback: S.delegate.listResolution(
        fallback: const Locale('en', ''),),
// new
      home: MyHomePage(title: '本地化'),
    );
  }
}

兩種方式也是同樣可以的,設(shè)置之后就會(huì)忽略你當(dāng)前設(shè)備的語(yǔ)言,直接指定為英文語(yǔ)言環(huán)境!

切換語(yǔ)言

如果你有切換語(yǔ)言的需求,可以這樣實(shí)現(xiàn)

// new
ValueChanged<Locale> localeChange;
// new
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
// new 
  Locale _locale = const Locale('en', '');

  @override
  void initState() {
    super.initState();
    localeChange = (locale) {
      setState(() {
        _locale = locale;
      });
    };
  }
// new 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      localizationsDelegates: const [
        S.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: S.delegate.supportedLocales,
// remove localeListResolutionCallback
// edit
      home: Builder(
        builder: (BuildContext context) {
          return Localizations.override(
            context: context,
            locale: _locale,
            child: MyHomePage(title: 'Flutter Demo Home Page'),
          );
        },
      ),
    );
  }
}
// edit
// 在其他地方調(diào)用
localeChange(Locale('zh', ''));//zh為中文

以上就是這篇文章的全部?jī)?nèi)容,閱讀完后就會(huì)發(fā)現(xiàn),跟Android中的R文件有異曲同工的效果!如果你學(xué)會(huì)了,希望能收到你的大禮包(****** 點(diǎn)亮紅心 ****** 關(guān)注 ****** 轉(zhuǎn)發(fā) ******) 你的支持,是我創(chuàng)作和分享的動(dòng)力!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容