Internationalization & localization (#1822)
* install and setup lingui * setup dynamic locale activation and async loading * first pass of automated replacement of text messages * add some more documentaton * fix nits * add `es` and `hi`locales for testing purposes * make accessibilityLabel localized * compile and extract new messages * fix merge conflicts * fix eslint warning * change instructions from sending email to opening PR * fix comments
This commit is contained in:
parent
82059b7ee1
commit
4c7850f8c4
108 changed files with 10334 additions and 1365 deletions
|
@ -63,6 +63,8 @@ import {
|
|||
// -prf
|
||||
import {useDebugHeaderSetting} from 'lib/api/debug-appview-proxy-header'
|
||||
import {STATUS_PAGE_URL} from 'lib/constants'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'>
|
||||
export const SettingsScreen = withAuthRequired(
|
||||
|
@ -71,6 +73,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
const setColorMode = useSetColorMode()
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {_} = useLingui()
|
||||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
const requireAltTextEnabled = useRequireAltTextEnabled()
|
||||
const setRequireAltTextEnabled = useSetRequireAltTextEnabled()
|
||||
|
@ -213,7 +216,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
{store.session.currentSession !== undefined ? (
|
||||
<>
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Account
|
||||
<Trans>Account</Trans>
|
||||
</Text>
|
||||
<View style={[styles.infoLine]}>
|
||||
<Text type="lg-medium" style={pal.text}>
|
||||
|
@ -233,17 +236,17 @@ export const SettingsScreen = withAuthRequired(
|
|||
</Text>
|
||||
<Link onPress={() => openModal({name: 'change-email'})}>
|
||||
<Text type="lg" style={pal.link}>
|
||||
Change
|
||||
<Trans>Change</Trans>
|
||||
</Text>
|
||||
</Link>
|
||||
</View>
|
||||
<View style={[styles.infoLine]}>
|
||||
<Text type="lg-medium" style={pal.text}>
|
||||
Birthday:{' '}
|
||||
<Trans>Birthday: </Trans>
|
||||
</Text>
|
||||
<Link onPress={() => openModal({name: 'birth-date-settings'})}>
|
||||
<Text type="lg" style={pal.link}>
|
||||
Show
|
||||
<Trans>Show</Trans>
|
||||
</Text>
|
||||
</Link>
|
||||
</View>
|
||||
|
@ -253,7 +256,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
) : null}
|
||||
<View style={[s.flexRow, styles.heading]}>
|
||||
<Text type="xl-bold" style={pal.text}>
|
||||
Signed in as
|
||||
<Trans>Signed in as</Trans>
|
||||
</Text>
|
||||
<View style={s.flex1} />
|
||||
</View>
|
||||
|
@ -282,10 +285,10 @@ export const SettingsScreen = withAuthRequired(
|
|||
testID="signOutBtn"
|
||||
onPress={isSwitching ? undefined : onPressSignout}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Sign out"
|
||||
accessibilityLabel={_(msg`Sign out`)}
|
||||
accessibilityHint={`Signs ${store.me.displayName} out of Bluesky`}>
|
||||
<Text type="lg" style={pal.link}>
|
||||
Sign out
|
||||
<Trans>Sign out</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
@ -321,7 +324,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
|
||||
onPress={isSwitching ? undefined : onPressAddAccount}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Add account"
|
||||
accessibilityLabel={_(msg`Add account`)}
|
||||
accessibilityHint="Create a new Bluesky account">
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
|
@ -330,21 +333,21 @@ export const SettingsScreen = withAuthRequired(
|
|||
/>
|
||||
</View>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Add account
|
||||
<Trans>Add account</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Invite a Friend
|
||||
<Trans>Invite a Friend</Trans>
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
testID="inviteFriendBtn"
|
||||
style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
|
||||
onPress={isSwitching ? undefined : onPressInviteCodes}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Invite"
|
||||
accessibilityLabel={_(msg`Invite`)}
|
||||
accessibilityHint="Opens invite code list">
|
||||
<View
|
||||
style={[
|
||||
|
@ -371,7 +374,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Accessibility
|
||||
<Trans>Accessibility</Trans>
|
||||
</Text>
|
||||
<View style={[pal.view, styles.toggleCard]}>
|
||||
<ToggleButton
|
||||
|
@ -386,7 +389,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Appearance
|
||||
<Trans>Appearance</Trans>
|
||||
</Text>
|
||||
<View>
|
||||
<View style={[styles.linkCard, pal.view, styles.selectableBtns]}>
|
||||
|
@ -415,7 +418,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Basics
|
||||
<Trans>Basics</Trans>
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
testID="preferencesHomeFeedButton"
|
||||
|
@ -423,7 +426,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
onPress={openHomeFeedPreferences}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint=""
|
||||
accessibilityLabel="Opens the home feed preferences">
|
||||
accessibilityLabel={_(msg`Opens the home feed preferences`)}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
icon="sliders"
|
||||
|
@ -431,7 +434,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
/>
|
||||
</View>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Home Feed Preferences
|
||||
<Trans>Home Feed Preferences</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
|
@ -440,7 +443,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
onPress={openThreadsPreferences}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint=""
|
||||
accessibilityLabel="Opens the threads preferences">
|
||||
accessibilityLabel={_(msg`Opens the threads preferences`)}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
icon={['far', 'comments']}
|
||||
|
@ -449,20 +452,20 @@ export const SettingsScreen = withAuthRequired(
|
|||
/>
|
||||
</View>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Thread Preferences
|
||||
<Trans>Thread Preferences</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
testID="savedFeedsBtn"
|
||||
style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
|
||||
accessibilityHint="My Saved Feeds"
|
||||
accessibilityLabel="Opens screen with all saved feeds"
|
||||
accessibilityLabel={_(msg`Opens screen with all saved feeds`)}
|
||||
onPress={onPressSavedFeeds}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<HashtagIcon style={pal.text} size={18} strokeWidth={3} />
|
||||
</View>
|
||||
<Text type="lg" style={pal.text}>
|
||||
My Saved Feeds
|
||||
<Trans>My Saved Feeds</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
|
@ -471,7 +474,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
onPress={isSwitching ? undefined : onPressLanguageSettings}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint="Language settings"
|
||||
accessibilityLabel="Opens configurable language settings">
|
||||
accessibilityLabel={_(msg`Opens configurable language settings`)}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
icon="language"
|
||||
|
@ -479,7 +482,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
/>
|
||||
</View>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Languages
|
||||
<Trans>Languages</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
|
@ -490,18 +493,18 @@ export const SettingsScreen = withAuthRequired(
|
|||
}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint=""
|
||||
accessibilityLabel="Opens moderation settings">
|
||||
accessibilityLabel={_(msg`Opens moderation settings`)}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<HandIcon style={pal.text} size={18} strokeWidth={6} />
|
||||
</View>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Moderation
|
||||
<Trans>Moderation</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Advanced
|
||||
<Trans>Advanced</Trans>
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
testID="appPasswordBtn"
|
||||
|
@ -509,7 +512,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
onPress={onPressAppPasswords}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint="Open app password settings"
|
||||
accessibilityLabel="Opens the app password settings page">
|
||||
accessibilityLabel={_(msg`Opens the app password settings page`)}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
icon="lock"
|
||||
|
@ -517,7 +520,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
/>
|
||||
</View>
|
||||
<Text type="lg" style={pal.text}>
|
||||
App passwords
|
||||
<Trans>App passwords</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
|
@ -525,7 +528,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
|
||||
onPress={isSwitching ? undefined : onPressChangeHandle}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Change handle"
|
||||
accessibilityLabel={_(msg`Change handle`)}
|
||||
accessibilityHint="Choose a new Bluesky username or create">
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
|
@ -534,19 +537,19 @@ export const SettingsScreen = withAuthRequired(
|
|||
/>
|
||||
</View>
|
||||
<Text type="lg" style={pal.text} numberOfLines={1}>
|
||||
Change handle
|
||||
<Trans>Change handle</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<View style={styles.spacer20} />
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Danger Zone
|
||||
<Trans>Danger Zone</Trans>
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={[pal.view, styles.linkCard]}
|
||||
onPress={onPressDeleteAccount}
|
||||
accessible={true}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Delete account"
|
||||
accessibilityLabel={_(msg`Delete account`)}
|
||||
accessibilityHint="Opens modal for account deletion confirmation. Requires email code.">
|
||||
<View style={[styles.iconContainer, dangerBg]}>
|
||||
<FontAwesomeIcon
|
||||
|
@ -556,21 +559,21 @@ export const SettingsScreen = withAuthRequired(
|
|||
/>
|
||||
</View>
|
||||
<Text type="lg" style={dangerText}>
|
||||
Delete my account…
|
||||
<Trans>Delete my account…</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<View style={styles.spacer20} />
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Developer Tools
|
||||
<Trans>Developer Tools</Trans>
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={[pal.view, styles.linkCardNoIcon]}
|
||||
onPress={onPressSystemLog}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint="Open system log"
|
||||
accessibilityLabel="Opens the system log page">
|
||||
accessibilityLabel={_(msg`Opens the system log page`)}>
|
||||
<Text type="lg" style={pal.text}>
|
||||
System log
|
||||
<Trans>System log</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
{__DEV__ ? (
|
||||
|
@ -588,9 +591,9 @@ export const SettingsScreen = withAuthRequired(
|
|||
onPress={onPressStorybook}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint="Open storybook page"
|
||||
accessibilityLabel="Opens the storybook page">
|
||||
accessibilityLabel={_(msg`Opens the storybook page`)}>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Storybook
|
||||
<Trans>Storybook</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
|
@ -598,9 +601,9 @@ export const SettingsScreen = withAuthRequired(
|
|||
onPress={onPressResetPreferences}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint="Reset preferences"
|
||||
accessibilityLabel="Resets the preferences state">
|
||||
accessibilityLabel={_(msg`Resets the preferences state`)}>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Reset preferences state
|
||||
<Trans>Reset preferences state</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
|
@ -608,9 +611,9 @@ export const SettingsScreen = withAuthRequired(
|
|||
onPress={onPressResetOnboarding}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint="Reset onboarding"
|
||||
accessibilityLabel="Resets the onboarding state">
|
||||
accessibilityLabel={_(msg`Resets the onboarding state`)}>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Reset onboarding state
|
||||
<Trans>Reset onboarding state</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
|
@ -620,7 +623,9 @@ export const SettingsScreen = withAuthRequired(
|
|||
accessibilityRole="button"
|
||||
onPress={onPressBuildInfo}>
|
||||
<Text type="sm" style={[styles.buildInfo, pal.textLight]}>
|
||||
Build version {AppInfo.appVersion} {AppInfo.updateChannel}
|
||||
<Trans>
|
||||
Build version {AppInfo.appVersion} {AppInfo.updateChannel}
|
||||
</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Text type="sm" style={[pal.textLight]}>
|
||||
|
@ -630,7 +635,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
accessibilityRole="button"
|
||||
onPress={onPressStatusPage}>
|
||||
<Text type="sm" style={[styles.buildInfo, pal.textLight]}>
|
||||
Status page
|
||||
<Trans>Status page</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
@ -646,6 +651,7 @@ const EmailConfirmationNotice = observer(
|
|||
const pal = usePalette('default')
|
||||
const palInverted = usePalette('inverted')
|
||||
const store = useStores()
|
||||
const {_} = useLingui()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const {openModal} = useModalControls()
|
||||
|
||||
|
@ -656,7 +662,7 @@ const EmailConfirmationNotice = observer(
|
|||
return (
|
||||
<View style={{marginBottom: 20}}>
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Verify email
|
||||
<Trans>Verify email</Trans>
|
||||
</Text>
|
||||
<View
|
||||
style={[
|
||||
|
@ -681,7 +687,7 @@ const EmailConfirmationNotice = observer(
|
|||
isMobile && {flex: 1},
|
||||
]}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Verify my email"
|
||||
accessibilityLabel={_(msg`Verify my email`)}
|
||||
accessibilityHint=""
|
||||
onPress={() => openModal({name: 'verify-email'})}>
|
||||
<FontAwesomeIcon
|
||||
|
@ -690,12 +696,12 @@ const EmailConfirmationNotice = observer(
|
|||
size={16}
|
||||
/>
|
||||
<Text type="button" style={palInverted.text}>
|
||||
Verify My Email
|
||||
<Trans>Verify My Email</Trans>
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
<Text style={pal.textLight}>
|
||||
Protect your account by verifying your email.
|
||||
<Trans>Protect your account by verifying your email.</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue