Flutter配置國際化骡送,多語言步驟優(yōu)化
請(qǐng)先參考國際化 · 《Flutter實(shí)戰(zhàn)》中的intl章節(jié)完成國際化配置至能夠使用
其中intl.sh
文件的部分注釋
# lib/i10n/localization_intl.dart 要進(jìn)行翻譯的(其中包含有Intl相關(guān)方法)文件
# i10n-arb/intl_*.arb 轉(zhuǎn)換后的.arb文件 2
# i10n-arb 存放1轉(zhuǎn)換后的相應(yīng).arb文件的目錄 3
# lib/i10n 存放2再轉(zhuǎn)換成相應(yīng)dart文件的目錄 4
# 轉(zhuǎn)換成arb。傳入3和1
flutter pub pub run intl_translation:extract_to_arb --output-dir=i10n-arb lib/i10n/localization_intl.dart
# 將arb轉(zhuǎn)化成相關(guān)dart文件喷众。傳入4,1和2
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/i10n --no-use-deferred-loading lib/i10n/localization_intl.dart i10n-arb/intl_*.arb
1. 抽離要翻譯字段
- 刪除掉
lib/i10n/localization_intl.dart
中以下部分
String get title {
return Intl.message(
'Flutter APP',
name: 'title',
desc: 'Title for the Demo application',
);
}
新建
lib/i10n/mixins
文件夾mixins
文件夾中新建commom.dart
文件并寫入
// ignore_for_file: non_constant_identifier_names
import 'package:intl/intl.dart';
mixin Commom {
// 加上前綴方便在.arb文件中區(qū)分
String get commom_title => Intl.message(
'Flutter APP',
name: 'commom_title', // 在.arb文件中顯示的字段名
desc: 'Title for the Demo application');
}
- 在
lib/i10n/localization_intl.dart
引用
// ...
import './mixins/commom.dart';
// ...
class DemoLocalizations with Common {
// ...
- 修改
intl.sh
文件- 只修改了1相應(yīng)的路徑
# lib/i10n/mixins/** 要進(jìn)行翻譯的(其中包含有Intl相關(guān)方法)文件 1
# i10n-arb/intl_*.arb 轉(zhuǎn)換后的.arb文件 2
# i10n-arb 存放1轉(zhuǎn)換后的相應(yīng).arb文件的目錄 3
# lib/i10n 存放2再轉(zhuǎn)換成相應(yīng)dart文件的目錄 4
# 轉(zhuǎn)換成arb各谚。傳入3和1
flutter pub pub run intl_translation:extract_to_arb --output-dir=i10n-arb lib/i10n/mixins/**
# 將arb轉(zhuǎn)化成相關(guān)dart文件。傳入4,1和2
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/i10n --no-use-deferred-loading lib/i10n/mixins/** i10n-arb/intl_*.arb
- 完成
2. 簡化翻譯步驟(需要安裝Node.js)
參考使用Intl包 · 《Flutter實(shí)戰(zhàn)》當(dāng)前的翻譯步驟為
-
lib/i10n/mixins/
下相關(guān)文件添加要翻譯的字段 - 執(zhí)行
./intl.sh
-
i10n-arb/
下相關(guān)文件進(jìn)行相應(yīng)的翻譯 - 執(zhí)行
./intl.sh
缺點(diǎn)
- 需要在多處相關(guān)文件進(jìn)行相關(guān)改動(dòng)
- 翻譯時(shí)的.arb文件需要和
i10n-arb/intl_messages.arb
進(jìn)行對(duì)比到千,并進(jìn)行手動(dòng)更改 - 若是修改之前的翻譯字段昌渤,可能需要對(duì)部分.arb文件進(jìn)行相關(guān)的手動(dòng)修改
- 需要多次執(zhí)行
./intl.sh
優(yōu)化思路
- 原步驟中第一次執(zhí)行
./intl.sh
是為了執(zhí)行其中第一條命令。 - 第二次執(zhí)行
./intl.sh
是為了執(zhí)行其中第二條命令憔四。 - 因此只要將對(duì).arb文件進(jìn)行相關(guān)翻譯通過命令行執(zhí)行即可
優(yōu)化后的步驟
-
lib/i10n/mixins/
下相關(guān)文件添加要翻譯的字段 - 執(zhí)行
./intl.sh
如何優(yōu)化
- 根目錄下添加
node_intl.js
文件
const fs = require("fs");
const path = require("path");
// 要轉(zhuǎn)換的語言(默認(rèn)語言不填)
const localeList = ["en", "ja"];
// 獲取命令行參數(shù)
const params = process.argv.splice(2);
// 判斷是否為Object-JSON格式
function canParse(str) {
try {
return (
str !== "" &&
typeof str == "string" &&
Object.prototype.toString.call(JSON.parse(str)) === "[object Object]"
);
} catch (error) {
return false;
}
}
// 對(duì)文件 根據(jù)locale 進(jìn)行修改
// locale = "en";
// 原來:
// "commom_tab_home": "首頁",
// "@commom_tab_home": {
// "description": "{\"desc\":\"底部tab中的首頁\",\"en\":\"Home\"}",
// "type": "text",
// "placeholders": {}
// },
// 修改后:
// "commom_tab_home": "Home",
// "@commom_tab_home": {
// "description": "{\"desc\":\"底部tab中的首頁\",\"en\":\"Home\"}",
// "type": "text",
// "placeholders": {}
// },
function translateAccordingToLocale(fileContent) {
const newFileContentObj = {};
// 復(fù)制原文件內(nèi)容膀息,僅修改locale
localeList.forEach((locale) => {
let data = JSON.parse(fileContent);
data["@@locale"] = locale;
newFileContentObj[locale] = data;
});
// 遍歷原文件內(nèi)容,根據(jù)description進(jìn)行相應(yīng)轉(zhuǎn)換
const data = JSON.parse(fileContent);
for (const key in data) {
if (data.hasOwnProperty(key) && /^@[^@]/.test(key)) {
const element = data[key]["description"];
if (canParse(element)) {
const desc = JSON.parse(element);
// 根據(jù)description進(jìn)行相應(yīng)轉(zhuǎn)換
localeList.forEach((locale) => {
const translateToLocale = desc[locale];
translateToLocale &&
(newFileContentObj[locale][
key.replace(/^@/, "")
] = translateToLocale);
});
}
}
}
return Promise.resolve(newFileContentObj);
}
// 寫入arb文件
function writeArb(fileContentObj) {
return new Promise((resolve, reject) => {
for (const locale in fileContentObj) {
if (fileContentObj.hasOwnProperty(locale)) {
fs.writeFile(
path.join(__dirname, `${params[0]}/intl_${locale}.arb`),
// 寫入格式化后的文件內(nèi)容
JSON.stringify(fileContentObj[locale], null, 2),
(err) => err && reject(err)
);
}
}
});
}
// 讀取源arb文件
function readArb() {
return new Promise((resolve, reject) => {
if (params.length == 0) return reject("請(qǐng)傳入相關(guān).arb文件所在目錄");
fs.readFile(
path.join(__dirname, `${params[0]}/intl_messages.arb`),
(err, data) => (err ? reject(err) : resolve(data))
);
});
}
readArb()
.then(translateAccordingToLocale)
.then(writeArb)
.catch((e) => {
console.error(`Node_Intl Error: ${e}`);
});
- 修改
./intl.sh
文件- 原來兩條命令中新增一條命令
# lib/i10n/mixins/** 要進(jìn)行翻譯的(其中包含有Intl相關(guān)方法)文件 1
# i10n-arb/intl_*.arb 轉(zhuǎn)換后的.arb文件 2
# i10n-arb 存放1轉(zhuǎn)換后的相應(yīng).arb文件的目錄 3
# lib/i10n 存放2再轉(zhuǎn)換成相應(yīng)dart文件的目錄 4
# 轉(zhuǎn)換成arb了赵。傳入3和1
flutter pub pub run intl_translation:extract_to_arb --output-dir=i10n-arb lib/i10n/mixins/**
# 優(yōu)化翻譯步驟 傳入3
node node_intl.js i10n-arb
# 將arb轉(zhuǎn)化成相關(guān)dart文件潜支。傳入4,1和2
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/i10n --no-use-deferred-loading lib/i10n/mixins/** i10n-arb/intl_*.arb
- 翻譯格式
-
lib/i10n/mixins/commom.dart
中 -
desc
格式需要為Object-JSON格式
-
// ignore_for_file: non_constant_identifier_names
import 'package:intl/intl.dart';
mixin Commom {
// 加上前綴方便在.arb文件中區(qū)分
String get commom_title => Intl.message(
'Flutter APP',
name: 'commom_title', // 在.arb文件中顯示的字段名
desc: '{"desc":"Title for the Demo application","en":"英文翻譯在這","ja":"日語翻譯在這"}');
}
- 完成