mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-16 12:55:14 +03:00
Parse messages file and use i18next vue plugin
This commit is contained in:
parent
f87c0f5461
commit
dba61bc652
10 changed files with 89 additions and 65 deletions
|
@ -622,25 +622,32 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
"statusbar_port_utilization": {
|
"statusbar_port_utilization": {
|
||||||
"message": "Port utilization:"
|
"message": "Port utilization:",
|
||||||
|
"description": "Port utilization text shown in the status bar"
|
||||||
},
|
},
|
||||||
"statusbar_usage_download": {
|
"statusbar_usage_download": {
|
||||||
"message": "D: $1%"
|
"message": "D:",
|
||||||
|
"description": "References 'Download' in the status bar, port utilization. Keep one character long if possible"
|
||||||
},
|
},
|
||||||
"statusbar_usage_upload": {
|
"statusbar_usage_upload": {
|
||||||
"message": "U: $1%"
|
"message": "U:",
|
||||||
|
"description": "References 'Upload' in the status bar, port utilization. Keep one character long if possible"
|
||||||
},
|
},
|
||||||
"statusbar_packet_error": {
|
"statusbar_packet_error": {
|
||||||
"message": "Packet error:"
|
"message": "Packet error:",
|
||||||
|
"description": "Packet error text shown in the status bar"
|
||||||
},
|
},
|
||||||
"statusbar_i2c_error": {
|
"statusbar_i2c_error": {
|
||||||
"message": "I2C error:"
|
"message": "I2C error:",
|
||||||
|
"description": "CPU load text shown in the status bar"
|
||||||
},
|
},
|
||||||
"statusbar_cycle_time": {
|
"statusbar_cycle_time": {
|
||||||
"message": "Cycle Time:"
|
"message": "Cycle Time:",
|
||||||
|
"description": "Cycle time text shown in the status bar"
|
||||||
},
|
},
|
||||||
"statusbar_cpu_load": {
|
"statusbar_cpu_load": {
|
||||||
"message": "CPU Load: $1%"
|
"message": "CPU Load:",
|
||||||
|
"description": "CPU load text shown in the status bar"
|
||||||
},
|
},
|
||||||
|
|
||||||
"dfu_connect_message": {
|
"dfu_connect_message": {
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^5.13.0",
|
"@fortawesome/fontawesome-free": "^5.13.0",
|
||||||
|
"@panter/vue-i18next": "^0.15.2",
|
||||||
"bluebird": "^3.7.2",
|
"bluebird": "^3.7.2",
|
||||||
"djv": "^2.1.3-alpha.0",
|
"djv": "^2.1.3-alpha.0",
|
||||||
"i18next": "^19.0.0",
|
"i18next": "^19.0.0",
|
||||||
|
@ -67,8 +68,7 @@
|
||||||
"short-unique-id": "^1.1.1",
|
"short-unique-id": "^1.1.1",
|
||||||
"three": "~0.97.0",
|
"three": "~0.97.0",
|
||||||
"universal-ga": "^1.2.0",
|
"universal-ga": "^1.2.0",
|
||||||
"vue": "2.6.12",
|
"vue": "2.6.12"
|
||||||
"vue-i18n": "8.21.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@quanle94/innosetup": "^6.0.2",
|
"@quanle94/innosetup": "^6.0.2",
|
||||||
|
|
|
@ -72,15 +72,15 @@
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<div class="logo_text">
|
<div class="logo_text">
|
||||||
<span>
|
<span>
|
||||||
{{ $t("versionLabelConfigurator.message") }}: {{ configuratorVersion }}
|
{{ $t("versionLabelConfigurator") }}: {{ configuratorVersion }}
|
||||||
<br />
|
<br />
|
||||||
<span v-if="firmwareVersion && firmwareId">
|
<span v-if="firmwareVersion && firmwareId">
|
||||||
{{ $t("versionLabelFirmware.message") }}: {{ firmwareVersion }}
|
{{ $t("versionLabelFirmware") }}: {{ firmwareVersion }}
|
||||||
{{ firmwareId }}
|
{{ firmwareId }}
|
||||||
</span>
|
</span>
|
||||||
<br />
|
<br />
|
||||||
<span v-if="hardwareId">
|
<span v-if="hardwareId">
|
||||||
{{ $t("versionLabelTarget.message") }}: {{ hardwareId }}
|
{{ $t("versionLabelTarget") }}: {{ hardwareId }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,14 +4,6 @@ import BatteryLegend from "./quad-status/BatteryLegend.vue";
|
||||||
import BetaflightLogo from "./betaflight-logo/BetaflightLogo.vue";
|
import BetaflightLogo from "./betaflight-logo/BetaflightLogo.vue";
|
||||||
import StatusBar from "./status-bar/StatusBar.vue";
|
import StatusBar from "./status-bar/StatusBar.vue";
|
||||||
|
|
||||||
// a bit of a hack here to get around the current translations.
|
|
||||||
// vue i18n provides slightly different api for this. But
|
|
||||||
// it's also possible to provide custom formatter
|
|
||||||
Vue.filter(
|
|
||||||
"stripEnd",
|
|
||||||
(value) => value.replace(/\$1%/, "")
|
|
||||||
);
|
|
||||||
|
|
||||||
// Most of the global objects can go here at first.
|
// Most of the global objects can go here at first.
|
||||||
// It's a bit of overkill for simple components,
|
// It's a bit of overkill for simple components,
|
||||||
// but these instance would eventually have more children
|
// but these instance would eventually have more children
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<span>{{ $t("statusbar_port_utilization.message") }}</span>
|
<span>{{ $t("statusbar_port_utilization") }}</span>
|
||||||
<ReadingStat
|
<ReadingStat
|
||||||
message="statusbar_usage_download"
|
message="statusbar_usage_download"
|
||||||
:value="usageDown"
|
:value="usageDown"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<span>
|
<span>
|
||||||
<span>{{ $t(message + ".message") | stripEnd }}</span>
|
<span>{{ $t(message) }}</span>
|
||||||
<span>{{ value }}</span>
|
<span>{{ value }}</span>
|
||||||
<span v-if="unit">{{ unit }}</span>
|
<span v-if="unit">{{ unit }}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="version">
|
<div class="version">
|
||||||
{{ $t("versionLabelConfigurator.message") }}: {{ configuratorVersion }}
|
{{ $t("versionLabelConfigurator") }}: {{ configuratorVersion }}
|
||||||
<span v-if="firmwareVersion && firmwareId">
|
<span v-if="firmwareVersion && firmwareId">
|
||||||
, {{ $t("versionLabelFirmware.message") }}: {{ firmwareVersion }}
|
, {{ $t("versionLabelFirmware") }}: {{ firmwareVersion }}
|
||||||
{{ firmwareId }}
|
{{ firmwareId }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="hardwareId">
|
<span v-if="hardwareId">
|
||||||
, {{ $t("versionLabelTarget.message") }}: {{ hardwareId }}
|
, {{ $t("versionLabelTarget") }}: {{ hardwareId }}
|
||||||
</span>
|
</span>
|
||||||
({{ gitChangesetId }})
|
({{ gitChangesetId }})
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import VueI18n from "vue-i18n";
|
import VueI18Next from "@panter/vue-i18next";
|
||||||
|
|
||||||
Vue.use(VueI18n);
|
Vue.use(VueI18Next);
|
||||||
|
|
||||||
const vueI18n = new VueI18n(i18next);
|
const vueI18n = new VueI18Next(i18next);
|
||||||
|
|
||||||
i18next.on("initialized", () => {
|
|
||||||
vueI18n.setLocaleMessage("en", i18next.getDataByLanguage("en").messages);
|
|
||||||
});
|
|
||||||
|
|
||||||
i18next.on("languageChanged", (lang) => {
|
|
||||||
vueI18n.setLocaleMessage(lang, i18next.getDataByLanguage(lang).messages);
|
|
||||||
vueI18n.locale = lang;
|
|
||||||
document.querySelector("html").setAttribute("lang", lang);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default vueI18n;
|
export default vueI18n;
|
||||||
|
|
|
@ -29,8 +29,12 @@ i18n.init = function(cb) {
|
||||||
ns: ['messages'],
|
ns: ['messages'],
|
||||||
defaultNS:['messages'],
|
defaultNS:['messages'],
|
||||||
fallbackLng: languageFallback,
|
fallbackLng: languageFallback,
|
||||||
backend: { loadPath: '/_locales/{{lng}}/{{ns}}.json' },
|
backend: {
|
||||||
}, function(err) {
|
loadPath: '/_locales/{{lng}}/{{ns}}.json',
|
||||||
|
parse: i18n.parseInputFile,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
if (err !== undefined) {
|
if (err !== undefined) {
|
||||||
console.error(`Error loading i18n: ${err}`);
|
console.error(`Error loading i18n: ${err}`);
|
||||||
} else {
|
} else {
|
||||||
|
@ -49,6 +53,29 @@ i18n.init = function(cb) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We have different interpolate methods in the input messages file,
|
||||||
|
* we unify all of them here to the i18next style and simplify it
|
||||||
|
*/
|
||||||
|
i18n.parseInputFile = function(data) {
|
||||||
|
|
||||||
|
// Remove the $n interpolate of Chrome $1, $2, ... -> {{1}}, {{2}}, ...
|
||||||
|
const REGEXP_CHROME = /\$([1-9])/g;
|
||||||
|
const dataChrome = data.replace(REGEXP_CHROME, '{{$1}}');
|
||||||
|
|
||||||
|
// Remove the .message of the nesting $t(xxxxx.message) -> $t(xxxxx)
|
||||||
|
const REGEXP_NESTING = /\$t\(([^\)]*).message\)/g;
|
||||||
|
const dataNesting = dataChrome.replace(REGEXP_NESTING, '$t($1)');
|
||||||
|
|
||||||
|
// Move the .message of the json object to root xxxxx.message -> xxxxx
|
||||||
|
const jsonData = JSON.parse(dataNesting);
|
||||||
|
Object.entries(jsonData).forEach(([key, value]) => {
|
||||||
|
jsonData[key] = value.message;
|
||||||
|
});
|
||||||
|
|
||||||
|
return jsonData;
|
||||||
|
};
|
||||||
|
|
||||||
i18n.changeLanguage = function(languageSelected) {
|
i18n.changeLanguage = function(languageSelected) {
|
||||||
if (typeof ConfigStorage !== 'undefined') {
|
if (typeof ConfigStorage !== 'undefined') {
|
||||||
ConfigStorage.set({'userLanguageSelect': languageSelected});
|
ConfigStorage.set({'userLanguageSelect': languageSelected});
|
||||||
|
@ -60,28 +87,29 @@ i18n.changeLanguage = function(languageSelected) {
|
||||||
|
|
||||||
i18n.getMessage = function(messageID, parameters) {
|
i18n.getMessage = function(messageID, parameters) {
|
||||||
|
|
||||||
let translatedString;
|
let parametersObject;
|
||||||
|
|
||||||
// Option 1, no parameters or Object as parameters (i18Next type parameters)
|
// Option 1, no parameters or Object as parameters (i18Next type parameters)
|
||||||
if ((parameters === undefined) || ((parameters.constructor !== Array) && (parameters instanceof Object))) {
|
if ((parameters === undefined) || ((parameters.constructor !== Array) && (parameters instanceof Object))) {
|
||||||
translatedString = i18next.t(`${messageID}.message`, parameters);
|
parametersObject = parameters;
|
||||||
|
|
||||||
// Option 2: parameters as $1, $2, etc.
|
// Option 2: parameters as $1, $2, etc.
|
||||||
// (deprecated, from the old Chrome i18n
|
// (deprecated, from the old Chrome i18n
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
translatedString = i18next.t(`${messageID}.message`);
|
// Convert the input to an array
|
||||||
|
|
||||||
let parametersArray = parameters;
|
let parametersArray = parameters;
|
||||||
if (parametersArray.constructor !== Array) {
|
if (parametersArray.constructor !== Array) {
|
||||||
parametersArray = [parameters];
|
parametersArray = [parameters];
|
||||||
}
|
}
|
||||||
parametersArray.forEach(function(element, index) {
|
|
||||||
translatedString = translatedString.replace(`$${(index + 1)}`, element);
|
parametersObject = {};
|
||||||
|
parametersArray.forEach(function(parameter, index) {
|
||||||
|
parametersObject[index + 1] = parameter;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return translatedString;
|
return i18next.t(messageID, parametersObject);
|
||||||
};
|
};
|
||||||
|
|
||||||
i18n.getLanguagesAvailables = function() {
|
i18n.getLanguagesAvailables = function() {
|
||||||
|
|
17
yarn.lock
17
yarn.lock
|
@ -53,6 +53,13 @@
|
||||||
"@nodelib/fs.scandir" "2.1.3"
|
"@nodelib/fs.scandir" "2.1.3"
|
||||||
fastq "^1.6.0"
|
fastq "^1.6.0"
|
||||||
|
|
||||||
|
"@panter/vue-i18next@^0.15.2":
|
||||||
|
version "0.15.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@panter/vue-i18next/-/vue-i18next-0.15.2.tgz#814f6774237e444eb9b69156e9c507d41b7fbd32"
|
||||||
|
integrity sha512-7VX9GyxHJNEJKa2CRzC294Oz5EEbzVDZ1o3O/P8gL/PWBmcFOFsuivRbP/1a9ga2ihv/NBzoCWMCNIEEeCcONQ==
|
||||||
|
dependencies:
|
||||||
|
deepmerge "^2.0.0"
|
||||||
|
|
||||||
"@quanle94/innosetup@^6.0.2":
|
"@quanle94/innosetup@^6.0.2":
|
||||||
version "6.0.2"
|
version "6.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/@quanle94/innosetup/-/innosetup-6.0.2.tgz#b678b67240486302a08e3469151faca2c29f80ab"
|
resolved "https://registry.yarnpkg.com/@quanle94/innosetup/-/innosetup-6.0.2.tgz#b678b67240486302a08e3469151faca2c29f80ab"
|
||||||
|
@ -1787,6 +1794,11 @@ deep-extend@^0.6.0:
|
||||||
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
|
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
|
||||||
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
|
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
|
||||||
|
|
||||||
|
deepmerge@^2.0.0:
|
||||||
|
version "2.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
||||||
|
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
|
||||||
|
|
||||||
deepmerge@^4.2.1, deepmerge@^4.2.2:
|
deepmerge@^4.2.1, deepmerge@^4.2.2:
|
||||||
version "4.2.2"
|
version "4.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
|
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
|
||||||
|
@ -7470,11 +7482,6 @@ void-elements@^2.0.0, void-elements@^2.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
|
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
|
||||||
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
|
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
|
||||||
|
|
||||||
vue-i18n@8.21.1:
|
|
||||||
version "8.21.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-8.21.1.tgz#afa8e6390a5de3b65bd17533c4269181f86f1d61"
|
|
||||||
integrity sha512-KEakJLI7R6+UCmhJOMZ0K7C+Zf5FcMh7QDkBRaEq39V7d9JgSrTDBf/9HuHU3TaxQYXx4fUi5PTIPdwLXq+iow==
|
|
||||||
|
|
||||||
vue-runtime-helpers@^1.1.2:
|
vue-runtime-helpers@^1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/vue-runtime-helpers/-/vue-runtime-helpers-1.1.2.tgz#446b7b820888ab0c5264d2c3a32468e72e4100f3"
|
resolved "https://registry.yarnpkg.com/vue-runtime-helpers/-/vue-runtime-helpers-1.1.2.tgz#446b7b820888ab0c5264d2c3a32468e72e4100f3"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue