Skip to content

Commit

Permalink
Merge pull request #4134 from dklymenk/3770-multi-language-improvements
Browse files Browse the repository at this point in the history
3770 multi language improvements
  • Loading branch information
madmax330 authored Jul 27, 2021
2 parents cd663c7 + c9cfd0c commit 0e5e46a
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 58 deletions.
1 change: 1 addition & 0 deletions src/CONST.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

88 changes: 88 additions & 0 deletions src/components/LocalePicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React from 'react';
import {withOnyx} from 'react-native-onyx';
import PropTypes from 'prop-types';
import styles from '../styles/styles';
import Picker from './Picker';
import Text from './Text';
import compose from '../libs/compose';
import {setLocale} from '../libs/actions/App';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
import ONYXKEYS from '../ONYXKEYS';
import CONST from '../CONST';
import Permissions from '../libs/Permissions';
import {translate} from '../libs/translate';

const propTypes = {
/** Indicates which locale the user currently has selected */
preferredLocale: PropTypes.string,

/** Indicates size of a picker component and whether to render the label or not */
size: PropTypes.oneOf(['normal', 'small']),

/** Beta features list */
betas: PropTypes.arrayOf(PropTypes.string),

...withLocalizePropTypes,
};

const defaultProps = {
preferredLocale: CONST.DEFAULT_LOCALE,
size: 'normal',
betas: [],
};

const localesToLanguages = {
default: {
value: 'en',
label: translate('en', 'preferencesPage.languages.english'),
},
es: {
value: 'es',
label: translate('es', 'preferencesPage.languages.spanish'),
},
};

const LocalePicker = ({
// eslint-disable-next-line no-shadow
preferredLocale, translate, betas, size,
}) => {
if (!Permissions.canUseInternationalization(betas)) {
return null;
}

return (
<>
{size === 'normal' && (
<Text style={[styles.formLabel]} numberOfLines={1}>
{translate('preferencesPage.language')}
</Text>
)}
<Picker
onChange={(locale) => {
if (locale !== preferredLocale) {
setLocale(locale);
}
}}
items={Object.values(localesToLanguages)}
size={size}
value={preferredLocale}
/>
</>
);
};

LocalePicker.defaultProps = defaultProps;
LocalePicker.propTypes = propTypes;
LocalePicker.displayName = 'LocalePicker';

export default compose(
withLocalize,
withOnyx({
preferredLocale: {
key: ONYXKEYS.PREFERRED_LOCALE,
},
betas: {
key: ONYXKEYS.BETAS,
},
}),
)(LocalePicker);
22 changes: 21 additions & 1 deletion src/components/Picker/PickerPropTypes.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import Icon from '../Icon';
import styles from '../../styles/styles';
import {DownArrow} from '../Icon/Expensicons';

const propTypes = {
Expand Down Expand Up @@ -36,13 +37,32 @@ const propTypes = {

/** An icon to display with the picker */
icon: PropTypes.func,

/** Size of a picker component */
size: PropTypes.oneOf(['normal', 'small']),
};
const defaultProps = {
useDisabledStyles: false,
disabled: false,
placeholder: {},
value: null,
icon: () => <Icon src={DownArrow} />,
icon: size => (
<>
{size === 'small'
? (
<Icon
width={styles.pickerSmall.icon.width}
height={styles.pickerSmall.icon.height}
src={DownArrow}
/>
)
: (
<Icon
src={DownArrow}
/>
)}
</>
),
};

export {
Expand Down
36 changes: 23 additions & 13 deletions src/components/Picker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,29 @@ const Picker = ({
value,
icon,
disabled,
}) => (
<RNPickerSelect
onValueChange={onChange}
items={items}
style={useDisabledStyles ? pickerDisabledStyles : styles.picker}
useNativeAndroidPickerStyle={false}
placeholder={placeholder}
value={value}
Icon={icon}
disabled={disabled}
fixAndroidTouchableBug
/>
);
size,
}) => {
let pickerStyles;
if (size === 'small') {
pickerStyles = styles.pickerSmall;
} else {
pickerStyles = useDisabledStyles ? pickerDisabledStyles : styles.picker;
}

return (
<RNPickerSelect
onValueChange={onChange}
items={items}
style={pickerStyles}
useNativeAndroidPickerStyle={false}
placeholder={placeholder}
value={value}
Icon={() => icon(size)}
disabled={disabled}
fixAndroidTouchableBug
/>
);
};

Picker.propTypes = pickerPropTypes.propTypes;
Picker.defaultProps = pickerPropTypes.defaultProps;
Expand Down
9 changes: 9 additions & 0 deletions src/libs/Permissions.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,19 @@ function canUseDefaultRooms(betas) {
return _.contains(betas, CONST.BETAS.DEFAULT_ROOMS) || canUseAllBetas(betas);
}

/**
* @param {Array<String>} betas
* @returns {Boolean}
*/
function canUseInternationalization(betas) {
return _.contains(betas, CONST.BETAS.INTERNATIONALIZATION) || canUseAllBetas(betas);
}

export default {
canUseChronos,
canUseIOU,
canUsePayWithExpensify,
canUseFreePlan,
canUseDefaultRooms,
canUseInternationalization,
};
10 changes: 10 additions & 0 deletions src/libs/actions/SignInRedirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ Onyx.connect({
},
});

let currentPreferredLocale;
Onyx.connect({
key: ONYXKEYS.PREFERRED_LOCALE,
callback: val => currentPreferredLocale = val,
});

/**
* Clears the Onyx store and redirects to the sign in page.
* Normally this method would live in Session.js, but that would cause a circular dependency with Network.js.
Expand All @@ -37,12 +43,16 @@ function redirectToSignIn(errorMessage) {
}

const activeClients = currentActiveClients;
const preferredLocale = currentPreferredLocale;

// We must set the authToken to null so we can navigate to "signin" it's not possible to navigate to the route as
// it only exists when the authToken is null.
Onyx.set(ONYXKEYS.SESSION, {authToken: null})
.then(() => {
Onyx.clear().then(() => {
if (preferredLocale) {
Onyx.set(ONYXKEYS.PREFERRED_LOCALE, preferredLocale);
}
if (errorMessage) {
Onyx.set(ONYXKEYS.SESSION, {error: errorMessage});
}
Expand Down
35 changes: 3 additions & 32 deletions src/pages/settings/PreferencesPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {withOnyx} from 'react-native-onyx';
import PropTypes from 'prop-types';

import HeaderWithCloseButton from '../../components/HeaderWithCloseButton';
import LocalePicker from '../../components/LocalePicker';
import Navigation from '../../libs/Navigation/Navigation';
import ROUTES from '../../ROUTES';
import ONYXKEYS from '../../ONYXKEYS';
Expand All @@ -17,7 +18,6 @@ import Switch from '../../components/Switch';
import Picker from '../../components/Picker';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
import compose from '../../libs/compose';
import {setLocale} from '../../libs/actions/App';

const propTypes = {
/** The chat priority mode */
Expand All @@ -29,20 +29,16 @@ const propTypes = {
expensifyNewsStatus: PropTypes.bool,
}),

/** Indicates which locale the user currently has selected */
preferredLocale: PropTypes.string,

...withLocalizePropTypes,
};

const defaultProps = {
priorityMode: CONST.PRIORITY_MODE.DEFAULT,
user: {},
preferredLocale: CONST.DEFAULT_LOCALE,
};

const PreferencesPage = ({
priorityMode, user, translate, preferredLocale,
priorityMode, user, translate,
}) => {
const priorityModes = {
default: {
Expand All @@ -57,17 +53,6 @@ const PreferencesPage = ({
},
};

const localesToLanguages = {
default: {
value: 'en',
label: translate('preferencesPage.languages.english'),
},
es: {
value: 'es',
label: translate('preferencesPage.languages.spanish'),
},
};

return (
<ScreenWrapper>
<HeaderWithCloseButton
Expand Down Expand Up @@ -109,19 +94,8 @@ const PreferencesPage = ({
<Text style={[styles.textLabel, styles.colorMuted, styles.mb6]}>
{priorityModes[priorityMode].description}
</Text>
<Text style={[styles.formLabel]} numberOfLines={1}>
{translate('preferencesPage.language')}
</Text>
<View style={[styles.mb2]}>
<Picker
onChange={(locale) => {
if (locale !== preferredLocale) {
setLocale(locale);
}
}}
items={Object.values(localesToLanguages)}
value={preferredLocale}
/>
<LocalePicker />
</View>
</View>
</View>
Expand All @@ -142,8 +116,5 @@ export default compose(
user: {
key: ONYXKEYS.USER,
},
preferredLocale: {
key: ONYXKEYS.NVP_PREFERRED_LOCALE,
},
}),
)(PreferencesPage);
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,17 @@ import withLocalize, {
withLocalizePropTypes,
} from '../../../../components/withLocalize';
import LogoWordmark from '../../../../../assets/images/expensify-wordmark.svg';
import LocalePicker from '../../../../components/LocalePicker';

const TermsWithLicenses = ({translate}) => (
<View>
<View style={[styles.mt1, styles.alignItemsCenter, styles.mb3]}>
<LogoWordmark height={30} width={80} />
</View>
<View
style={[
styles.dFlex,
styles.flexRow,
styles.flexWrap,
styles.textAlignCenter,
styles.alignItemsCenter,
styles.justifyContentCenter,
]}
>
<Text style={[styles.textAlignCenter, styles.loginTermsText]}>
Expand Down Expand Up @@ -61,6 +58,12 @@ const TermsWithLicenses = ({translate}) => (
</TextLink>
<Text style={[styles.textAlignCenter, styles.loginTermsText]}>.</Text>
</View>
<View style={[
styles.mt4, styles.alignItemsCenter, styles.mb2, styles.flexRow, styles.justifyContentBetween]}
>
<LogoWordmark height={30} width={80} />
<LocalePicker size="small" />
</View>
</View>
);

Expand Down
11 changes: 7 additions & 4 deletions src/pages/signin/TermsAndLicenses/TermsWithLicenses/index.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,16 @@ import withLocalize, {
withLocalizePropTypes,
} from '../../../../components/withLocalize';
import LogoWordmark from '../../../../../assets/images/expensify-wordmark.svg';
import LocalePicker from '../../../../components/LocalePicker';

const TermsWithLicenses = ({translate}) => (
<View>
<View style={[styles.mt1, styles.alignItemsCenter, styles.mb3]}>
<LogoWordmark height={30} width={80} />
</View>
<View
style={[
styles.dFlex,
styles.flexColumn,
styles.flexWrap,
styles.textAlignCenter,
styles.alignItemsCenter,
styles.justifyContentCenter,
]}
>
Expand Down Expand Up @@ -67,6 +64,12 @@ const TermsWithLicenses = ({translate}) => (
<Text style={[styles.textAlignCenter, styles.loginTermsText]}>.</Text>
</View>
</View>
<View style={[
styles.mt4, styles.alignItemsCenter, styles.mb2, styles.flexRow, styles.justifyContentBetween]}
>
<LogoWordmark height={30} width={80} />
<LocalePicker size="small" />
</View>
</View>
);

Expand Down
Loading

0 comments on commit 0e5e46a

Please sign in to comment.