diff --git a/assets/linux/betaflight-configurator-english.desktop b/assets/linux/betaflight-configurator-english.desktop deleted file mode 100644 index 05fd15ec..00000000 --- a/assets/linux/betaflight-configurator-english.desktop +++ /dev/null @@ -1,7 +0,0 @@ -[Desktop Entry] -Name=Betaflight Configurator (English) -Comment=Crossplatform configuration tool for the Betaflight flight control system -Exec=bash -c "LANGUAGE=en /opt/betaflight/betaflight-configurator/betaflight-configurator" -Icon=/opt/betaflight/betaflight-configurator/icon/bf_icon_english_128.png -Terminal=false -Type=Application diff --git a/assets/windows/installer.nsi b/assets/windows/installer.nsi index 1a6c874f..4f736e5e 100644 --- a/assets/windows/installer.nsi +++ b/assets/windows/installer.nsi @@ -119,6 +119,9 @@ Section ${EndIf} ${EndIf} + # the english shortcut is not installed in actual versions, remove the deletion in a future release + Delete "$SMPROGRAMS\${GROUP_NAME}\${FOLDER_NAME}\${APP_NAME} (English).lnk" + # if the registry entries did not exist, we ignore the errors ClearErrors @@ -140,7 +143,6 @@ Section # create shortcuts in the start menu and on the desktop CreateDirectory "$SMPROGRAMS\${GROUP_NAME}\${FOLDER_NAME}" CreateShortCut "$SMPROGRAMS\${GROUP_NAME}\${FOLDER_NAME}\${APP_NAME}.lnk" "$INSTDIR\${FILE_NAME_EXECUTABLE}" - CreateShortCut "$SMPROGRAMS\${GROUP_NAME}\${FOLDER_NAME}\${APP_NAME} (English).lnk" "$INSTDIR\${FILE_NAME_EXECUTABLE}" "--lang=en" CreateShortCut "$SMPROGRAMS\${GROUP_NAME}\${FOLDER_NAME}\Uninstall ${APP_NAME}.lnk" "$INSTDIR\${FILE_NAME_UNINSTALLER}" CreateShortCut "$DESKTOP\${APP_NAME}.lnk" "$INSTDIR\${FILE_NAME_EXECUTABLE}" @@ -184,6 +186,7 @@ Section "Uninstall" RMDir "$INSTDIR" # delete the shortcuts + # the english shortcut is not installed in actual versions, remove the deletion in a future release Delete "$SMPROGRAMS\${GROUP_NAME}\${FOLDER_NAME}\${APP_NAME}.lnk" Delete "$SMPROGRAMS\${GROUP_NAME}\${FOLDER_NAME}\${APP_NAME} (English).lnk" Delete "$SMPROGRAMS\${GROUP_NAME}\${FOLDER_NAME}\Uninstall ${APP_NAME}.lnk" diff --git a/gulpfile.js b/gulpfile.js index a25d65c5..10d97939 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -482,8 +482,8 @@ function release_deb(arch) { architecture: debArch, maintainer: pkg.author, description: pkg.description, - postinst: ['xdg-desktop-menu install /opt/betaflight/betaflight-configurator/betaflight-configurator.desktop /opt/betaflight/betaflight-configurator/betaflight-configurator-english.desktop'], - prerm: ['xdg-desktop-menu uninstall betaflight-configurator.desktop betaflight-configurator-english.desktop'], + postinst: ['xdg-desktop-menu install /opt/betaflight/betaflight-configurator/betaflight-configurator.desktop'], + prerm: ['xdg-desktop-menu uninstall betaflight-configurator.desktop'], depends: 'libgconf-2-4', changelog: [], _target: 'opt/betaflight/betaflight-configurator', diff --git a/locales/en/messages.json b/locales/en/messages.json index b6619be9..9ecb4a93 100644 --- a/locales/en/messages.json +++ b/locales/en/messages.json @@ -48,6 +48,31 @@ "permanentExpertMode": { "message": "Permanently enable Expert Mode" }, + "userLanguageSelect": { + "message": "Language (need to restart the application for the changes to take effect)" + }, + "language_default": { + "message": "Default" + }, + "language_ca": { + "message": "Catalan" + }, + "language_de": { + "message": "German" + }, + "language_en": { + "message": "English" + }, + "language_es": { + "message": "Spanish" + }, + "language_fr": { + "message": "French" + }, + "language_ko": { + "message": "Korean" + }, + "sensorStatusGyro": { "message": "Gyroscope" }, diff --git a/src/css/main.css b/src/css/main.css index aff01ce2..eb1f0d4c 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -406,6 +406,21 @@ input[type="number"]::-webkit-inner-spin-button { margin-right: 5px; } +#options-window .separator { + padding-bottom: 10px; + margin-bottom: 10px; + border-bottom: 2px solid silver; +} +#options-window .dropdown { + float: left; + width: auto; + margin-right: 5px; +} + +#options-window select { + margin-right: 3em; +} + /* Log setup*/ #log { margin-bottom: 0px; diff --git a/src/js/localization.js b/src/js/localization.js index 8d9ddbfb..037edafd 100644 --- a/src/js/localization.js +++ b/src/js/localization.js @@ -6,33 +6,36 @@ var i18n = {} +const languagesAvailables = ['ca', 'de', 'en', 'es', 'fr', 'ko']; + /** * Functions that depend on the i18n framework */ i18n.init = function(cb) { - var defaultLocale = window.navigator.userLanguage || window.navigator.language; + getStoredUserLocale(function(userLanguage){ - i18next - .use(i18nextXHRBackend) - .init({ - lng: defaultLocale, - getAsync: false, - debug: true, - ns: ['messages'], - defaultNS:['messages'], - fallbackLng: 'en', - backend: { loadPath: '/_locales/{{lng}}/{{ns}}.json' } - }, function(err, t) { - if (err !== undefined) { - console.error('Error loading i18n ' + err); - } else { - console.log('i18n system loaded'); - } - if (cb !== undefined) { - cb(); - } - }); + i18next + .use(i18nextXHRBackend) + .init({ + lng: userLanguage, + getAsync: false, + debug: true, + ns: ['messages'], + defaultNS:['messages'], + fallbackLng: 'en', + backend: { loadPath: '/_locales/{{lng}}/{{ns}}.json' } + }, function(err, t) { + if (err !== undefined) { + console.error('Error loading i18n ' + err); + } else { + console.log('i18n system loaded'); + } + if (cb !== undefined) { + cb(); + } + }); + }); } i18n.getMessage = function(messageID, parameters) { @@ -43,10 +46,12 @@ i18n.getMessage = function(messageID, parameters) { translatedString = translatedString.replace('$' + (index + 1), element); }); } - - return translatedString; - + return translatedString; +} + +i18n.getLanguagesAvailables = function() { + return languagesAvailables; } /** @@ -93,3 +98,28 @@ i18n.localizePage = function() { return localized; } + +/* + * Reads the chrome config, if DEFAULT or there is no config stored, + * returns the current locale to the callback + */ +function getStoredUserLocale(cb) { + chrome.storage.local.get('userLanguageSelect', function (result) { + var userLanguage = 'DEFAULT'; + if (result.userLanguageSelect) { + userLanguage = result.userLanguageSelect + } + + userLanguage = getValidLocale(userLanguage); + + cb(userLanguage); + }) +} + +function getValidLocale(userLocale) { + + if (userLocale == 'DEFAULT') { + userLocale = window.navigator.userLanguage || window.navigator.language; + } + return userLocale; +} diff --git a/src/js/main.js b/src/js/main.js index 2c3c03d9..7aef5094 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -13,6 +13,7 @@ $(document).ready(function () { //Process to execute to real start the app function startProcess() { + // translate to user-selected language i18n.localizePage(); @@ -232,6 +233,29 @@ function startProcess() { $('div.checkForConfiguratorUnstableVersions').hide(); } + chrome.storage.local.get('userLanguageSelect', function (result) { + + var userLanguage_e = $('div.userLanguage select'); + var languagesAvailables = i18n.getLanguagesAvailables(); + userLanguage_e.append(''); + userLanguage_e.append(''); + languagesAvailables.forEach(function(element) { + var languageName = i18n.getMessage('language_' + element); + userLanguage_e.append(''); + }); + + if (result.userLanguageSelect) { + userLanguage_e.val(result.userLanguageSelect); + } + + userLanguage_e.change(function () { + var languageSelected = $(this).val(); + + // Select the new language, a restart is required + chrome.storage.local.set({'userLanguageSelect': languageSelected}); + }); + }); + function close_and_cleanup(e) { if (e.type == 'click' && !$.contains($('div#options-window')[0], e.target) || e.type == 'keyup' && e.keyCode == 27) { $(document).unbind('click keyup', close_and_cleanup); @@ -364,7 +388,7 @@ function startProcess() { } }).change(); }); -} +}; function checkForConfiguratorUpdates() { var releaseChecker = new ReleaseChecker('configurator', 'https://api.github.com/repos/betaflight/betaflight-configurator/releases'); @@ -602,7 +626,6 @@ function getManifestVersion(manifest) { } function openNewWindowsInExternalBrowser() { - // Open new windows in external browser try { var gui = require('nw.gui'); @@ -615,6 +638,6 @@ function openNewWindowsInExternalBrowser() { policy.ignore(); }); } catch (ex) { - console.warn("require does not exist, maybe inside chrome"); + console.log("require does not exist, maybe inside chrome"); } } \ No newline at end of file diff --git a/src/tabs/options.html b/src/tabs/options.html index 2a926365..d79dca35 100644 --- a/src/tabs/options.html +++ b/src/tabs/options.html @@ -4,3 +4,14 @@