diff --git a/ui/component/app/index.js b/ui/component/app/index.js index 29594fdf3..7e72ad791 100644 --- a/ui/component/app/index.js +++ b/ui/component/app/index.js @@ -6,7 +6,12 @@ import { doFetchAccessToken, doUserSetReferrer } from 'redux/actions/user'; import { selectUser, selectAccessToken, selectUserVerifiedEmail } from 'redux/selectors/user'; import { selectUnclaimedRewards } from 'redux/selectors/rewards'; import { doFetchChannelListMine, SETTINGS } from 'lbry-redux'; -import { makeSelectClientSetting, selectLoadedLanguages, selectThemePath } from 'redux/selectors/settings'; +import { + makeSelectClientSetting, + selectLanguage, + selectLoadedLanguages, + selectThemePath, +} from 'redux/selectors/settings'; import { selectIsUpgradeAvailable, selectAutoUpdateDownloaded, selectModal } from 'redux/selectors/app'; import { doGetWalletSyncPreference, doSetLanguage } from 'redux/actions/settings'; import { doSyncSubscribe } from 'redux/actions/sync'; @@ -22,7 +27,7 @@ const select = state => ({ user: selectUser(state), accessToken: selectAccessToken(state), theme: selectThemePath(state), - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), + language: selectLanguage(state), syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state), languages: selectLoadedLanguages(state), autoUpdateDownloaded: selectAutoUpdateDownloaded(state), diff --git a/ui/component/claimListDiscover/index.js b/ui/component/claimListDiscover/index.js index 988947a8b..e483f37ff 100644 --- a/ui/component/claimListDiscover/index.js +++ b/ui/component/claimListDiscover/index.js @@ -9,7 +9,7 @@ import { import { selectFollowedTags } from 'redux/selectors/tags'; import { selectBlockedChannels } from 'redux/selectors/blocked'; import { doToggleTagFollowDesktop } from 'redux/actions/tags'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { makeSelectClientSetting, selectLanguage } from 'redux/selectors/settings'; import ClaimListDiscover from './view'; const select = state => ({ @@ -19,7 +19,7 @@ const select = state => ({ loading: selectFetchingClaimSearch(state), showNsfw: makeSelectClientSetting(SETTINGS.SHOW_MATURE)(state), hideReposts: makeSelectClientSetting(SETTINGS.HIDE_REPOSTS)(state), - languageSetting: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), + language: selectLanguage(state), hiddenUris: selectBlockedChannels(state), searchInLanguage: makeSelectClientSetting(SETTINGS.SEARCH_IN_LANGUAGE)(state), }); diff --git a/ui/component/claimListHeader/index.js b/ui/component/claimListHeader/index.js index b894b6f66..b8e221a0d 100644 --- a/ui/component/claimListHeader/index.js +++ b/ui/component/claimListHeader/index.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux'; import { selectFetchingClaimSearch, SETTINGS } from 'lbry-redux'; import { selectFollowedTags } from 'redux/selectors/tags'; import { doToggleTagFollowDesktop } from 'redux/actions/tags'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { makeSelectClientSetting, selectLanguage } from 'redux/selectors/settings'; import { doSetClientSetting } from 'redux/actions/settings'; import ClaimListHeader from './view'; @@ -11,7 +11,7 @@ const select = state => ({ loading: selectFetchingClaimSearch(state), showNsfw: makeSelectClientSetting(SETTINGS.SHOW_MATURE)(state), searchInLanguage: makeSelectClientSetting(SETTINGS.SEARCH_IN_LANGUAGE)(state), - languageSetting: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), + languageSetting: selectLanguage(state), }); const perform = { diff --git a/ui/component/header/index.js b/ui/component/header/index.js index 2becebaa8..f18581bd8 100644 --- a/ui/component/header/index.js +++ b/ui/component/header/index.js @@ -6,14 +6,14 @@ import { selectUserVerifiedEmail, selectUserEmail, selectEmailToVerify, selectUs import { doClearEmailEntry, doClearPasswordEntry } from 'redux/actions/user'; import { doSetClientSetting } from 'redux/actions/settings'; import { doSignOut, doOpenModal } from 'redux/actions/app'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { makeSelectClientSetting, selectLanguage } from 'redux/selectors/settings'; import { selectCommentChannel } from 'redux/selectors/comments'; import Header from './view'; import { selectHasNavigated } from 'redux/selectors/app'; const select = state => ({ balance: selectBalance(state), - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), // trigger redraw on language change + language: selectLanguage(state), roundedBalance: formatCredits(selectBalance(state), 2, true), currentTheme: makeSelectClientSetting(SETTINGS.THEME)(state), automaticDarkModeEnabled: makeSelectClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED)(state), diff --git a/ui/component/homepageSelector/index.js b/ui/component/homepageSelector/index.js index 3d96812c4..751f71287 100644 --- a/ui/component/homepageSelector/index.js +++ b/ui/component/homepageSelector/index.js @@ -1,7 +1,6 @@ import { connect } from 'react-redux'; import SelectHomepage from './view'; -import { SETTINGS } from 'lbry-redux'; -import { doSetClientSetting } from 'redux/actions/settings'; +import { doSetHomepage } from 'redux/actions/settings'; import { selectHomepageCode } from 'redux/selectors/settings'; const select = state => ({ @@ -9,7 +8,7 @@ const select = state => ({ }); const perform = dispatch => ({ - setHomepage: value => dispatch(doSetClientSetting(SETTINGS.HOMEPAGE, value)), + setHomepage: value => dispatch(doSetHomepage(value)), }); export default connect(select, perform)(SelectHomepage); diff --git a/ui/component/homepageSelector/view.jsx b/ui/component/homepageSelector/view.jsx index 8a7ef8bec..d58524f66 100644 --- a/ui/component/homepageSelector/view.jsx +++ b/ui/component/homepageSelector/view.jsx @@ -4,6 +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'; type Props = { homepage: string, @@ -27,7 +28,7 @@ function SelectHomepage(props: Props) { type="select" label={__('Homepage')} onChange={handleSetHomepage} - value={homepage} + value={homepage || getDefaultHomepage()} helper={__('Tailor your experience.')} > {Object.keys(homepages).map(hp => ( diff --git a/ui/component/settingAccountPassword/index.js b/ui/component/settingAccountPassword/index.js index 29393c734..44dc35f4b 100644 --- a/ui/component/settingAccountPassword/index.js +++ b/ui/component/settingAccountPassword/index.js @@ -1,16 +1,15 @@ import { connect } from 'react-redux'; import { selectUser, selectPasswordSetSuccess, selectPasswordSetError } from 'redux/selectors/user'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { selectLanguage } from 'redux/selectors/settings'; import { doUserPasswordSet, doClearPasswordEntry } from 'redux/actions/user'; import { doToast } from 'redux/actions/notifications'; import UserSignIn from './view'; -import { SETTINGS } from 'lbry-redux'; const select = state => ({ user: selectUser(state), passwordSetSuccess: selectPasswordSetSuccess(state), passwordSetError: selectPasswordSetError(state), - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), + language: selectLanguage(state), }); export default connect(select, { diff --git a/ui/component/settingAutoLaunch/index.js b/ui/component/settingAutoLaunch/index.js index a45096f61..d295fcf7f 100644 --- a/ui/component/settingAutoLaunch/index.js +++ b/ui/component/settingAutoLaunch/index.js @@ -1,13 +1,13 @@ import { connect } from 'react-redux'; import { SETTINGS } from 'lbry-redux'; import { doSetAutoLaunch } from 'redux/actions/settings'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { makeSelectClientSetting, selectLanguage } from 'redux/selectors/settings'; import { doToast } from 'redux/actions/notifications'; import SettingAutoLaunch from './view'; const select = state => ({ autoLaunch: makeSelectClientSetting(SETTINGS.AUTO_LAUNCH)(state), - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), + language: selectLanguage(state), }); const perform = dispatch => ({ diff --git a/ui/component/settingLanguage/index.js b/ui/component/settingLanguage/index.js index 7fee4e9c8..5a3d60abe 100644 --- a/ui/component/settingLanguage/index.js +++ b/ui/component/settingLanguage/index.js @@ -1,11 +1,11 @@ import { connect } from 'react-redux'; import { SETTINGS } from 'lbry-redux'; import { doSetLanguage, doSetClientSetting } from 'redux/actions/settings'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { makeSelectClientSetting, selectLanguage } from 'redux/selectors/settings'; import SettingLanguage from './view'; const select = state => ({ - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), + language: selectLanguage(state), searchInLanguage: makeSelectClientSetting(SETTINGS.SEARCH_IN_LANGUAGE)(state), }); diff --git a/ui/component/settingLanguage/view.jsx b/ui/component/settingLanguage/view.jsx index e1f651326..2d31ebe39 100644 --- a/ui/component/settingLanguage/view.jsx +++ b/ui/component/settingLanguage/view.jsx @@ -4,6 +4,7 @@ import React, { useState } from 'react'; import { FormField } from 'component/common/form'; import Spinner from 'component/spinner'; import SUPPORTED_LANGUAGES from 'constants/supported_languages'; +import { getDefaultLanguage } from 'util/default-languages'; type Props = { language: string, @@ -24,7 +25,7 @@ function SettingLanguage(props: Props) { function onLanguageChange(e) { const { value } = e.target; - setPreviousLanguage(language); + setPreviousLanguage(language || getDefaultLanguage()); setLanguage(value); } @@ -35,7 +36,7 @@ function SettingLanguage(props: Props) { type="select" label={__('Language')} onChange={onLanguageChange} - value={language} + value={language || getDefaultLanguage()} helper={__( 'Multi-language support is brand new and incomplete. Switching your language may have unintended consequences, like glossolalia.' )} diff --git a/ui/component/sideNavigation/index.js b/ui/component/sideNavigation/index.js index 1d6d04ef7..820fc33b4 100644 --- a/ui/component/sideNavigation/index.js +++ b/ui/component/sideNavigation/index.js @@ -1,9 +1,9 @@ import { connect } from 'react-redux'; import { selectSubscriptions } from 'redux/selectors/subscriptions'; -import { selectPurchaseUriSuccess, doClearPurchasedUriSuccess, SETTINGS } from 'lbry-redux'; +import { selectPurchaseUriSuccess, doClearPurchasedUriSuccess } from 'lbry-redux'; import { selectFollowedTags } from 'redux/selectors/tags'; import { selectUserVerifiedEmail, selectUser } from 'redux/selectors/user'; -import { makeSelectClientSetting, selectHomepageData } from 'redux/selectors/settings'; +import { selectHomepageData, selectLanguage } from 'redux/selectors/settings'; import { doSignOut } from 'redux/actions/app'; import { selectUnreadNotificationCount } from 'redux/selectors/notifications'; @@ -12,7 +12,7 @@ import SideNavigation from './view'; const select = state => ({ subscriptions: selectSubscriptions(state), followedTags: selectFollowedTags(state), - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), // trigger redraw on language change + language: selectLanguage(state), // trigger redraw on language change email: selectUserVerifiedEmail(state), purchaseSuccess: selectPurchaseUriSuccess(state), unreadCount: selectUnreadNotificationCount(state), diff --git a/ui/component/syncEnableFlow/index.js b/ui/component/syncEnableFlow/index.js index 2a083f653..7ebfbcf45 100644 --- a/ui/component/syncEnableFlow/index.js +++ b/ui/component/syncEnableFlow/index.js @@ -8,7 +8,7 @@ import { selectHashChanged, } from 'redux/selectors/sync'; import { doCheckSync, doGetSync } from 'redux/actions/sync'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { makeSelectClientSetting, selectLanguage } from 'redux/selectors/settings'; import { doSetWalletSyncPreference } from 'redux/actions/settings'; import SyncToggle from './view'; import { doGetAndPopulatePreferences } from 'redux/actions/app'; @@ -20,7 +20,7 @@ const select = state => ({ verifiedEmail: selectUserVerifiedEmail(state), getSyncError: selectGetSyncErrorMessage(state), getSyncPending: selectGetSyncIsPending(state), - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), + language: selectLanguage(state), }); const perform = dispatch => ({ diff --git a/ui/component/syncToggle/index.js b/ui/component/syncToggle/index.js index 151d7cd7a..84580a3dd 100644 --- a/ui/component/syncToggle/index.js +++ b/ui/component/syncToggle/index.js @@ -2,7 +2,7 @@ import { SETTINGS } from 'lbry-redux'; import { connect } from 'react-redux'; import { selectUserVerifiedEmail } from 'redux/selectors/user'; import { selectGetSyncErrorMessage } from 'redux/selectors/sync'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { makeSelectClientSetting, selectLanguage } from 'redux/selectors/settings'; import { doSetWalletSyncPreference } from 'redux/actions/settings'; import { doOpenModal } from 'redux/actions/app'; import SyncToggle from './view'; @@ -11,7 +11,7 @@ const select = state => ({ syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state), verifiedEmail: selectUserVerifiedEmail(state), getSyncError: selectGetSyncErrorMessage(state), - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), + language: selectLanguage(state), }); const perform = dispatch => ({ diff --git a/ui/component/wunderbar/index.js b/ui/component/wunderbar/index.js index dd3c33f06..99f0b8ae1 100644 --- a/ui/component/wunderbar/index.js +++ b/ui/component/wunderbar/index.js @@ -1,8 +1,7 @@ import { connect } from 'react-redux'; -import { SETTINGS } from 'lbry-redux'; import { doFocusSearchInput, doBlurSearchInput, doUpdateSearchQuery } from 'redux/actions/search'; import { selectSearchValue, selectSearchSuggestions, selectSearchBarFocused } from 'redux/selectors/search'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { selectLanguage } from 'redux/selectors/settings'; import { doToast } from 'redux/actions/notifications'; import analytics from 'analytics'; import Wunderbar from './view'; @@ -12,7 +11,7 @@ const select = state => ({ suggestions: selectSearchSuggestions(state), searchQuery: selectSearchValue(state), isFocused: selectSearchBarFocused(state), - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), + language: selectLanguage(state), }); const perform = (dispatch, ownProps) => ({ diff --git a/ui/page/settings/index.js b/ui/page/settings/index.js index b02283af6..b1280579d 100644 --- a/ui/page/settings/index.js +++ b/ui/page/settings/index.js @@ -10,7 +10,7 @@ import { doExitSettingsPage, } from 'redux/actions/settings'; import { doSetPlayingUri } from 'redux/actions/content'; -import { makeSelectClientSetting, selectDaemonSettings } from 'redux/selectors/settings'; +import { makeSelectClientSetting, selectDaemonSettings, selectLanguage } from 'redux/selectors/settings'; import { doWalletStatus, selectWalletIsEncrypted, SETTINGS } from 'lbry-redux'; import { selectBlockedChannelsCount } from 'redux/selectors/blocked'; import SettingsPage from './view'; @@ -32,7 +32,7 @@ const select = state => ({ floatingPlayer: makeSelectClientSetting(SETTINGS.FLOATING_PLAYER)(state), hideReposts: makeSelectClientSetting(SETTINGS.HIDE_REPOSTS)(state), darkModeTimes: makeSelectClientSetting(SETTINGS.DARK_MODE_TIMES)(state), - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), + language: selectLanguage(state), }); const perform = dispatch => ({ diff --git a/ui/page/settingsAdvanced/index.js b/ui/page/settingsAdvanced/index.js index 1e8d3336e..1997160cf 100644 --- a/ui/page/settingsAdvanced/index.js +++ b/ui/page/settingsAdvanced/index.js @@ -11,6 +11,7 @@ import { } from 'redux/actions/settings'; import { makeSelectClientSetting, + selectLanguage, selectDaemonSettings, selectFfmpegStatus, selectFindingFFmpeg, @@ -29,7 +30,7 @@ const select = state => ({ hideBalance: makeSelectClientSetting(SETTINGS.HIDE_BALANCE)(state), ffmpegStatus: selectFfmpegStatus(state), findingFFmpeg: selectFindingFFmpeg(state), - language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), + language: selectLanguage(state), syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state), }); diff --git a/ui/redux/actions/settings.js b/ui/redux/actions/settings.js index d13107288..a204e0d34 100644 --- a/ui/redux/actions/settings.js +++ b/ui/redux/actions/settings.js @@ -292,14 +292,35 @@ export function doFetchLanguage(language) { }; } +export function doSetHomepage(code) { + return (dispatch, getState) => { + let languageCode; + if (code === window.navigator.language.slice(0, 2)) { + languageCode = null; + } else { + languageCode = code; + } + dispatch(doSetClientSetting(SETTINGS.HOMEPAGE, languageCode)); + }; +} + export function doSetLanguage(language) { return (dispatch, getState) => { const { settings } = getState(); const { daemonSettings } = settings; const { share_usage_data: shareSetting } = daemonSettings; const isSharingData = shareSetting || IS_WEB; + let languageSetting; + if (language === window.navigator.language.slice(0, 2)) { + languageSetting = null; + } else { + languageSetting = language; + } - if (settings.language !== language || (settings.loadedLanguages && !settings.loadedLanguages.includes(language))) { + if ( + settings.language !== languageSetting || + (settings.loadedLanguages && !settings.loadedLanguages.includes(language)) + ) { // this should match the behavior/logic in index-web.html fetch('https://lbry.com/i18n/get/lbry-desktop/app-strings/' + language + '.json') .then(r => r.json()) @@ -315,7 +336,7 @@ export function doSetLanguage(language) { .then(() => { // set on localStorage so it can be read outside of redux window.localStorage.setItem(SETTINGS.LANGUAGE, language); - dispatch(doSetClientSetting(SETTINGS.LANGUAGE, language)); + dispatch(doSetClientSetting(SETTINGS.LANGUAGE, languageSetting)); if (isSharingData) { Lbryio.call('user', 'language', { language: language, diff --git a/ui/redux/reducers/settings.js b/ui/redux/reducers/settings.js index 0db9afce4..aea778ef4 100644 --- a/ui/redux/reducers/settings.js +++ b/ui/redux/reducers/settings.js @@ -1,12 +1,9 @@ import * as ACTIONS from 'constants/action_types'; import moment from 'moment'; -import SUPPORTED_LANGUAGES from 'constants/supported_languages'; import { ACTIONS as LBRY_REDUX_ACTIONS, SETTINGS, SHARED_PREFERENCES } from 'lbry-redux'; import { getSubsetFromKeysArray } from 'util/sync-settings'; import { UNSYNCED_SETTINGS } from 'config'; -import homepages from 'homepages'; -const homepageKeys = Object.keys(homepages); const { CLIENT_SYNC_KEYS } = SHARED_PREFERENCES; const settingsToIgnore = (UNSYNCED_SETTINGS && UNSYNCED_SETTINGS.trim().split(' ')) || []; const clientSyncKeys = settingsToIgnore.length @@ -39,11 +36,11 @@ const defaultState = { [SETTINGS.ENABLE_PUBLISH_PREVIEW]: true, // UI - [SETTINGS.LANGUAGE]: settingLanguage.find(language => SUPPORTED_LANGUAGES[language]), + [SETTINGS.LANGUAGE]: null, [SETTINGS.SEARCH_IN_LANGUAGE]: false, [SETTINGS.THEME]: __('light'), [SETTINGS.THEMES]: [__('light'), __('dark')], - [SETTINGS.HOMEPAGE]: settingLanguage.find(language => homepageKeys.includes(language)) || 'en', + [SETTINGS.HOMEPAGE]: null, [SETTINGS.HIDE_SPLASH_ANIMATION]: false, [SETTINGS.HIDE_BALANCE]: false, [SETTINGS.OS_NOTIFICATIONS_ENABLED]: true, diff --git a/ui/redux/selectors/settings.js b/ui/redux/selectors/settings.js index a56660b1e..204756ded 100644 --- a/ui/redux/selectors/settings.js +++ b/ui/redux/selectors/settings.js @@ -1,6 +1,7 @@ import { SETTINGS, DAEMON_SETTINGS } from 'lbry-redux'; import { createSelector } from 'reselect'; import homepages from 'homepages'; +import { getDefaultHomepage, getDefaultLanguage } from 'util/default-languages'; const selectState = state => state.settings || {}; @@ -54,7 +55,11 @@ export const selectThemePath = createSelector( ); export const selectHomepageCode = createSelector(makeSelectClientSetting(SETTINGS.HOMEPAGE), setting => { - return setting || 'en'; + return setting || getDefaultHomepage(); +}); + +export const selectLanguage = createSelector(makeSelectClientSetting(SETTINGS.LANGUAGE), setting => { + return setting || getDefaultLanguage(); }); export const selectHomepageData = createSelector( @@ -63,7 +68,7 @@ export const selectHomepageData = createSelector( homepageCode => { // homepages = { 'en': homepageFile, ... } if (!homepageCode || !homepages[homepageCode]) { - return homepages['en']; + return getDefaultHomepage(); } else { return homepages[homepageCode]; } diff --git a/ui/util/default-languages.js b/ui/util/default-languages.js new file mode 100644 index 000000000..d840b2f81 --- /dev/null +++ b/ui/util/default-languages.js @@ -0,0 +1,13 @@ +import homepages from 'homepages'; +import SUPPORTED_LANGUAGES from 'constants/supported_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 = () => { + return SUPPORTED_LANGUAGES[window.navigator.language.slice(0, 2)] + ? window.navigator.language.slice(0, 2) + : DEFAULT_LANG; +};