From 27d43b2b419b5940e3b217acf871aeaf858592b1 Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Tue, 16 Mar 2021 18:42:39 +0800 Subject: [PATCH] Simplify language lists - SUPPORTED_SUB_LANGUAGE_CODES[] that I introduced was pretty redundant when SUPPORTED_LANGUAGES[] already hold the information. The logic to ignore sub-languages (i.e. reduce the locale's "en-GB" to "en" is now located in getDefaultLanguage()). - SUPPORTED_BROWSER_LANGUAGES[] and SUPPORTED_LANGUAGES[] look so similar and hard to tell what the former is for at first glance. The functionality to map 'zh-CN' to 'zh-Hans' is now handled by resolveLanguageAlias(), which makes the intention clearer. This leaves us with a single list -- SUPPORTED_LANGUAGES[], whose key also tells us the desired language code to use. Also, clients now need to call `resolveLanguageAlias` to map any language code aliases, as they differ depending on how it is queried (e.g. `navigator.language` vs. `app.getLocal()` uses different standards). I think we no longer need to explicitly migrate existing user's 'zh-CN' into 'zh-Hans' because the rest of the system will always use the desired language code as long as 'resolveLanguageAlias' is called appropriately. e.g. the system uses `selectLanguage` and `selectLanguage` calls `resolveLanguageAlias`. --- ui/component/app/view.jsx | 8 ---- ui/constants/language-migrations.js | 6 --- ui/constants/supported_browser_languages.js | 39 ------------------ ui/constants/supported_languages.js | 2 +- ui/constants/supported_sub_languages.js | 8 ---- ui/i18n.js | 13 +++--- ui/redux/selectors/settings.js | 5 ++- ui/util/default-languages.js | 45 +++++++++++++++++++-- 8 files changed, 54 insertions(+), 72 deletions(-) delete mode 100644 ui/constants/language-migrations.js delete mode 100644 ui/constants/supported_browser_languages.js delete mode 100644 ui/constants/supported_sub_languages.js diff --git a/ui/component/app/view.jsx b/ui/component/app/view.jsx index d6150edf2..7a56887a8 100644 --- a/ui/component/app/view.jsx +++ b/ui/component/app/view.jsx @@ -37,7 +37,6 @@ import { STATUS_DOWN, } from 'web/effects/use-degraded-performance'; // @endif -import LANGUAGE_MIGRATIONS from 'constants/language-migrations'; export const MAIN_WRAPPER_CLASS = 'main-wrapper'; export const IS_MAC = navigator.userAgent.indexOf('Mac OS X') !== -1; @@ -145,7 +144,6 @@ function App(props: Props) { const useCustomScrollbar = !IS_MAC; const hasMyChannels = myChannelUrls && myChannelUrls.length > 0; const hasNoChannels = myChannelUrls && myChannelUrls.length === 0; - const shouldMigrateLanguage = LANGUAGE_MIGRATIONS[language]; const hasActiveChannelClaim = activeChannelClaim !== undefined; let uri; @@ -259,12 +257,6 @@ function App(props: Props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [language, languages]); - useEffect(() => { - if (shouldMigrateLanguage) { - setLanguage(shouldMigrateLanguage); - } - }, [shouldMigrateLanguage, setLanguage]); - useEffect(() => { // Check that previousHasVerifiedEmail was not undefined instead of just not truthy // This ensures we don't fire the emailVerified event on the initial user fetch diff --git a/ui/constants/language-migrations.js b/ui/constants/language-migrations.js deleted file mode 100644 index d400cbcf3..000000000 --- a/ui/constants/language-migrations.js +++ /dev/null @@ -1,6 +0,0 @@ -const LANGUAGE_MIGRATIONS = { - 'zh-CN': 'zh-Hans', - 'zh-TW': 'zh-Hant', -}; - -export default LANGUAGE_MIGRATIONS; diff --git a/ui/constants/supported_browser_languages.js b/ui/constants/supported_browser_languages.js deleted file mode 100644 index c672e6100..000000000 --- a/ui/constants/supported_browser_languages.js +++ /dev/null @@ -1,39 +0,0 @@ -const SUPPORTED_BROWSER_LANGUAGES = { - en: 'en', - da: 'da', - 'zh-CN': 'zh-Hans', - 'zh-TW': 'zh-Hant', - 'zh-Hans': 'zh-Hans', - 'zh-Hant': 'zh-Hant', - hr: 'hr', - nl: 'nl', - no: 'no', - fi: 'fi', - fr: 'fr', - de: 'de', - gu: 'gu', - hi: 'hi', - id: 'id', - jv: 'jv', - it: 'it', - ms: 'ms', - ml: 'ml', - mr: 'mr', - pa: 'pa', - pl: 'pl', - pt: 'pt', - ro: 'ro', - ru: 'ru', - sr: 'sr', - sk: 'sk', - ur: 'ur', - ca: 'ca', - es: 'es', - sv: 'sv', - tr: 'tr', - cs: 'cs', - kn: 'kn', - uk: 'uk', -}; - -export default SUPPORTED_BROWSER_LANGUAGES; diff --git a/ui/constants/supported_languages.js b/ui/constants/supported_languages.js index b6bc3f5cb..ee2ea57ed 100644 --- a/ui/constants/supported_languages.js +++ b/ui/constants/supported_languages.js @@ -1,5 +1,5 @@ import LANGUAGES from './languages'; -// supported_browser_languages + const SUPPORTED_LANGUAGES = { en: LANGUAGES.en[1], da: LANGUAGES.da[1], diff --git a/ui/constants/supported_sub_languages.js b/ui/constants/supported_sub_languages.js deleted file mode 100644 index 98d5f59ee..000000000 --- a/ui/constants/supported_sub_languages.js +++ /dev/null @@ -1,8 +0,0 @@ -// https://www.electronjs.org/docs/api/locales - -export const SUB_LANG_CODE_LEN = 5; - -export const SUPPORTED_SUB_LANGUAGE_CODES = [ - 'zh-CN', - 'zh-TW', -]; diff --git a/ui/i18n.js b/ui/i18n.js index 6b66bfe62..31cfbf60f 100644 --- a/ui/i18n.js +++ b/ui/i18n.js @@ -1,3 +1,5 @@ +import { getDefaultLanguage, resolveLanguageAlias } from './util/default-languages'; + // @if TARGET='app' let fs = require('fs'); // @endif @@ -31,7 +33,7 @@ function saveMessageDesktop(message) { knownMessages[message] = removeContextMetadata(message); knownMessages[END] = END; - fs.writeFile(messagesFilePath, JSON.stringify(knownMessages, null, 2) + '\n', 'utf-8', err => { + fs.writeFile(messagesFilePath, JSON.stringify(knownMessages, null, 2) + '\n', 'utf-8', (err) => { if (err) { throw err; } @@ -83,9 +85,10 @@ export function __(message, tokens) { return ''; } - const language = localStorageAvailable - ? window.localStorage.getItem('language') || 'en' - : window.navigator.language.slice(0, 2) || 'en'; + const language = resolveLanguageAlias( + localStorageAvailable ? window.localStorage.getItem('language') || 'en' : getDefaultLanguage() || 'en' + ); + if (!isProduction) { IS_WEB ? saveMessageWeb(message) : saveMessageDesktop(message); } @@ -97,7 +100,7 @@ export function __(message, tokens) { return translatedMessage; } - return translatedMessage.replace(/%([^%]+)%/g, function($1, $2) { + return translatedMessage.replace(/%([^%]+)%/g, ($1, $2) => { return tokens.hasOwnProperty($2) ? tokens[$2] : $2; }); } diff --git a/ui/redux/selectors/settings.js b/ui/redux/selectors/settings.js index 6b48bab97..4d21b60d6 100644 --- a/ui/redux/selectors/settings.js +++ b/ui/redux/selectors/settings.js @@ -2,7 +2,7 @@ import { SETTINGS, DAEMON_SETTINGS } from 'lbry-redux'; import { createSelector } from 'reselect'; import homepages from 'homepages'; import { SIMPLE_SITE } from 'config'; -import { getDefaultHomepageKey, getDefaultLanguage } from 'util/default-languages'; +import { resolveLanguageAlias, getDefaultHomepageKey, getDefaultLanguage } from 'util/default-languages'; const selectState = (state) => state.settings || {}; @@ -60,7 +60,8 @@ export const selectHomepageCode = createSelector(makeSelectClientSetting(SETTING }); export const selectLanguage = createSelector(makeSelectClientSetting(SETTINGS.LANGUAGE), (setting) => { - return setting || getDefaultLanguage(); + const lang = resolveLanguageAlias(setting) || getDefaultLanguage(); + return lang; }); export const selectHomepageData = createSelector( diff --git a/ui/util/default-languages.js b/ui/util/default-languages.js index fd5cd4b6b..3a6838dc3 100644 --- a/ui/util/default-languages.js +++ b/ui/util/default-languages.js @@ -1,10 +1,49 @@ import homepages from 'homepages'; -import SUPPORTED_BROWSER_LANGUAGES from 'constants/supported_browser_languages'; +import SUPPORTED_LANGUAGES from 'constants/supported_languages'; const DEFAULT_LANG = 'en'; +/** + * Checks if the given language is an alias of a language that we support, and + * returns the version that the rest of the application (lbry-sdk, Transifex) + * expects. If the given language is not an expected alias, the original value + * is returned. + * + * @param lang + * @returns {*} + */ +export function resolveLanguageAlias(lang) { + const KNOWN_LANG_ALIASES = { + 'zh-CN': 'zh-Hans', + 'zh-TW': 'zh-Hant', + }; + return KNOWN_LANG_ALIASES[lang] ? KNOWN_LANG_ALIASES[lang] : lang; +} + +/** + * Returns the native language of the system, filtered/resolved + * to the language code format that the application expects. + * + * @returns {string|*} + */ export const getDefaultLanguage = () => { - const browserLanguage = window.navigator.language; - return SUPPORTED_BROWSER_LANGUAGES[browserLanguage] || DEFAULT_LANG; + const browserLanguage = resolveLanguageAlias(window.navigator.language); + + if (SUPPORTED_LANGUAGES[browserLanguage]) { + return browserLanguage; + } else { + if (browserLanguage.includes('-')) { + // Perhaps it is a sub-lang that we are currently not supporting. + // See if we support the main one. + const mainLang = browserLanguage.substring(0, browserLanguage.indexOf('-')); + if (SUPPORTED_LANGUAGES[mainLang]) { + return mainLang; + } else { + return DEFAULT_LANG; + } + } else { + return DEFAULT_LANG; + } + } }; // If homepages has a key "zh-Hant" return that, otherwise return "zh", otherwise "en"