diff --git a/electron/createWindow.js b/electron/createWindow.js index f1f0a649c..253c7b9f2 100644 --- a/electron/createWindow.js +++ b/electron/createWindow.js @@ -4,21 +4,23 @@ import isDev from 'electron-is-dev'; import windowStateKeeper from 'electron-window-state'; import SUPPORTED_LANGUAGES from 'constants/supported_languages'; import { SUPPORTED_SUB_LANGUAGE_CODES, SUB_LANG_CODE_LEN } from 'constants/supported_sub_languages'; +import { SUPPORTED_BROWSER_LANGUAGES } from 'constants/supported_browser_languages'; import { TO_TRAY_WHEN_CLOSED } from 'constants/settings'; import setupBarMenu from './menu/setupBarMenu'; import * as PAGES from 'constants/pages'; function GetAppLangCode() { + // https://www.electronjs.org/docs/api/locales // 1. Gets the user locale. // 2. Converts unsupported sub-languages to its primary (e.g. "en-GB" -> "en"). // Note that the primary itself may or may not be a supported language // (up to clients to verify against SUPPORTED_LANGUAGES). const langCode = app.getLocale(); if (langCode.length === SUB_LANG_CODE_LEN && !SUPPORTED_SUB_LANGUAGE_CODES.includes(langCode)) { - return langCode.slice(0, 2); + return SUPPORTED_BROWSER_LANGUAGES[langCode.slice(0, 2)]; } - return langCode; + return SUPPORTED_BROWSER_LANGUAGES[langCode]; } export default appState => { diff --git a/ui/component/app/view.jsx b/ui/component/app/view.jsx index 8908c9f0f..9a8a17d74 100644 --- a/ui/component/app/view.jsx +++ b/ui/component/app/view.jsx @@ -36,6 +36,7 @@ import { STATUS_FAILING, STATUS_DOWN, } from 'web/effects/use-degraded-performance'; +import LANGUAGE_MIGRATIONS from 'constants/language-migrations'; // @endif export const MAIN_WRAPPER_CLASS = 'main-wrapper'; export const IS_MAC = navigator.userAgent.indexOf('Mac OS X') !== -1; @@ -134,6 +135,8 @@ function App(props: Props) { const userId = user && user.id; const useCustomScrollbar = !IS_MAC; + const shouldMigrateLanguage = LANGUAGE_MIGRATIONS[language]; + let uri; try { const newpath = buildURI(parseURI(pathname.slice(1).replace(/:/g, '#'))); @@ -232,6 +235,13 @@ function App(props: Props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [language, languages]); + useEffect(() => { + if (shouldMigrateLanguage) { + setLanguage(shouldMigrateLanguage); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [shouldMigrateLanguage]); + 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/component/homepageSelector/view.jsx b/ui/component/homepageSelector/view.jsx index d58524f66..514cb2f94 100644 --- a/ui/component/homepageSelector/view.jsx +++ b/ui/component/homepageSelector/view.jsx @@ -4,7 +4,7 @@ import React from 'react'; import homepages from 'homepages'; import LANGUAGES from 'constants/languages'; import { FormField } from 'component/common/form'; -import { getDefaultHomepage } from 'util/default-languages'; +import { getDefaultHomepageKey } from 'util/default-languages'; type Props = { homepage: string, @@ -28,7 +28,7 @@ function SelectHomepage(props: Props) { type="select" label={__('Homepage')} onChange={handleSetHomepage} - value={homepage || getDefaultHomepage()} + value={homepage || getDefaultHomepageKey()} helper={__('Tailor your experience.')} > {Object.keys(homepages).map(hp => ( diff --git a/ui/component/publishAdditionalOptions/view.jsx b/ui/component/publishAdditionalOptions/view.jsx index 220042582..b4ae97105 100644 --- a/ui/component/publishAdditionalOptions/view.jsx +++ b/ui/component/publishAdditionalOptions/view.jsx @@ -6,6 +6,8 @@ import { FormField } from 'component/common/form'; import Button from 'component/button'; import LicenseType from './license-type'; import Card from 'component/common/card'; +import SUPPORTED_LANGUAGES from 'constants/supported_languages'; + // @if TARGET='app' // import ErrorText from 'component/common/error-text'; // import { LbryFirst } from 'lbry-redux'; @@ -156,34 +158,12 @@ function PublishAdditionalOptions(props: Props) { value={language} onChange={event => updatePublishForm({ language: event.target.value })} > - - - - - - - - - - - - - - - - - - - - - - - - - - - - + {Object.entries(SUPPORTED_LANGUAGES).map(([langkey, langName]) => ( + // $FlowFixMe + + ))} { let languageCode; - if (code === window.navigator.language.slice(0, 2)) { + if (code === getDefaultLanguage()) { languageCode = null; } else { languageCode = code; @@ -311,7 +312,7 @@ export function doSetLanguage(language) { const { share_usage_data: shareSetting } = daemonSettings; const isSharingData = shareSetting || IS_WEB; let languageSetting; - if (language === window.navigator.language.slice(0, 2)) { + if (language === getDefaultLanguage()) { languageSetting = null; } else { languageSetting = language; diff --git a/ui/redux/actions/user.js b/ui/redux/actions/user.js index 7bcf46cf8..9c85074fc 100644 --- a/ui/redux/actions/user.js +++ b/ui/redux/actions/user.js @@ -6,6 +6,7 @@ import { doToast } from 'redux/actions/notifications'; import rewards from 'rewards'; import { Lbryio } from 'lbryinc'; import { DOMAIN } from 'config'; +import { getDefaultLanguage } from 'util/default-languages'; const AUTH_IN_PROGRESS = 'authInProgress'; export let sessionStorageAvailable = false; @@ -131,7 +132,7 @@ export function doAuthenticate( }); checkAuthBusy() .then(() => { - return Lbryio.authenticate(DOMAIN, window.navigator.language.slice(0, 2) || 'en'); + return Lbryio.authenticate(DOMAIN, getDefaultLanguage()); }) .then(user => { if (sessionStorageAvailable) window.sessionStorage.removeItem(AUTH_IN_PROGRESS); diff --git a/ui/redux/reducers/settings.js b/ui/redux/reducers/settings.js index bd6dd11b5..9a1f11d11 100644 --- a/ui/redux/reducers/settings.js +++ b/ui/redux/reducers/settings.js @@ -2,6 +2,7 @@ import * as ACTIONS from 'constants/action_types'; import moment from 'moment'; import { ACTIONS as LBRY_REDUX_ACTIONS, SETTINGS, SHARED_PREFERENCES } from 'lbry-redux'; import { getSubsetFromKeysArray } from 'util/sync-settings'; +import { getDefaultLanguage } from 'util/default-languages'; import { UNSYNCED_SETTINGS } from 'config'; const { CLIENT_SYNC_KEYS } = SHARED_PREFERENCES; @@ -16,7 +17,7 @@ try { let appLanguage = window.localStorage.getItem(SETTINGS.LANGUAGE); settingLanguage.push(appLanguage); } catch (e) {} -settingLanguage.push(window.navigator.language.slice(0, 2)); +settingLanguage.push(getDefaultLanguage()); settingLanguage.push('en'); const defaultState = { diff --git a/ui/redux/selectors/settings.js b/ui/redux/selectors/settings.js index fe9657048..1febe623a 100644 --- a/ui/redux/selectors/settings.js +++ b/ui/redux/selectors/settings.js @@ -1,7 +1,7 @@ import { SETTINGS, DAEMON_SETTINGS } from 'lbry-redux'; import { createSelector } from 'reselect'; import homepages from 'homepages'; -import { getDefaultHomepage, getDefaultLanguage } from 'util/default-languages'; +import { getDefaultHomepageKey, getDefaultLanguage } from 'util/default-languages'; const selectState = state => state.settings || {}; @@ -55,7 +55,7 @@ export const selectThemePath = createSelector( ); export const selectHomepageCode = createSelector(makeSelectClientSetting(SETTINGS.HOMEPAGE), setting => { - return homepages[setting] ? setting : getDefaultHomepage(); + return homepages[setting] ? setting : getDefaultHomepageKey(); }); export const selectLanguage = createSelector(makeSelectClientSetting(SETTINGS.LANGUAGE), setting => { diff --git a/ui/util/default-languages.js b/ui/util/default-languages.js index d840b2f81..fd5cd4b6b 100644 --- a/ui/util/default-languages.js +++ b/ui/util/default-languages.js @@ -1,13 +1,14 @@ import homepages from 'homepages'; -import SUPPORTED_LANGUAGES from 'constants/supported_languages'; +import SUPPORTED_BROWSER_LANGUAGES from 'constants/supported_browser_languages'; const DEFAULT_LANG = 'en'; -export const getDefaultHomepage = () => { - return homepages[window.navigator.language.slice(0, 2)] ? window.navigator.language.slice(0, 2) : DEFAULT_LANG; +export const getDefaultLanguage = () => { + const browserLanguage = window.navigator.language; + return SUPPORTED_BROWSER_LANGUAGES[browserLanguage] || DEFAULT_LANG; }; -export const getDefaultLanguage = () => { - return SUPPORTED_LANGUAGES[window.navigator.language.slice(0, 2)] - ? window.navigator.language.slice(0, 2) - : DEFAULT_LANG; +// If homepages has a key "zh-Hant" return that, otherwise return "zh", otherwise "en" +export const getDefaultHomepageKey = () => { + const language = getDefaultLanguage(); + return (homepages[language] && language) || (homepages[language.slice(0, 2)] && language.slice(0, 2)) || DEFAULT_LANG; };