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
|
@ -43,6 +43,8 @@ import {NavigationProp} from 'lib/routes/types'
|
|||
import {useNavigationTabState} from 'lib/hooks/useNavigationTabState'
|
||||
import {isWeb} from 'platform/detection'
|
||||
import {formatCount, formatCountShortOnly} from 'view/com/util/numeric/format'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useSetDrawerOpen} from '#/state/shell'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
|
@ -50,6 +52,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
|
|||
const theme = useTheme()
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {_} = useLingui()
|
||||
const setDrawerOpen = useSetDrawerOpen()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {track} = useAnalytics()
|
||||
|
@ -158,7 +161,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
|
|||
<View style={{}}>
|
||||
<TouchableOpacity
|
||||
testID="profileCardButton"
|
||||
accessibilityLabel="Profile"
|
||||
accessibilityLabel={_(msg`Profile`)}
|
||||
accessibilityHint="Navigates to your profile"
|
||||
onPress={onPressProfile}>
|
||||
<UserAvatar
|
||||
|
@ -215,7 +218,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
|
|||
)
|
||||
}
|
||||
label="Search"
|
||||
accessibilityLabel="Search"
|
||||
accessibilityLabel={_(msg`Search`)}
|
||||
accessibilityHint=""
|
||||
bold={isAtSearch}
|
||||
onPress={onPressSearch}
|
||||
|
@ -237,7 +240,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
|
|||
)
|
||||
}
|
||||
label="Home"
|
||||
accessibilityLabel="Home"
|
||||
accessibilityLabel={_(msg`Home`)}
|
||||
accessibilityHint=""
|
||||
bold={isAtHome}
|
||||
onPress={onPressHome}
|
||||
|
@ -259,7 +262,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
|
|||
)
|
||||
}
|
||||
label="Notifications"
|
||||
accessibilityLabel="Notifications"
|
||||
accessibilityLabel={_(msg`Notifications`)}
|
||||
accessibilityHint={
|
||||
notifications.unreadCountLabel === ''
|
||||
? ''
|
||||
|
@ -286,7 +289,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
|
|||
)
|
||||
}
|
||||
label="Feeds"
|
||||
accessibilityLabel="Feeds"
|
||||
accessibilityLabel={_(msg`Feeds`)}
|
||||
accessibilityHint=""
|
||||
bold={isAtFeeds}
|
||||
onPress={onPressMyFeeds}
|
||||
|
@ -294,14 +297,14 @@ export const DrawerContent = observer(function DrawerContentImpl() {
|
|||
<MenuItem
|
||||
icon={<ListIcon strokeWidth={2} style={pal.text} size={26} />}
|
||||
label="Lists"
|
||||
accessibilityLabel="Lists"
|
||||
accessibilityLabel={_(msg`Lists`)}
|
||||
accessibilityHint=""
|
||||
onPress={onPressLists}
|
||||
/>
|
||||
<MenuItem
|
||||
icon={<HandIcon strokeWidth={5} style={pal.text} size={24} />}
|
||||
label="Moderation"
|
||||
accessibilityLabel="Moderation"
|
||||
accessibilityLabel={_(msg`Moderation`)}
|
||||
accessibilityHint=""
|
||||
onPress={onPressModeration}
|
||||
/>
|
||||
|
@ -322,7 +325,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
|
|||
)
|
||||
}
|
||||
label="Profile"
|
||||
accessibilityLabel="Profile"
|
||||
accessibilityLabel={_(msg`Profile`)}
|
||||
accessibilityHint=""
|
||||
onPress={onPressProfile}
|
||||
/>
|
||||
|
@ -335,7 +338,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
|
|||
/>
|
||||
}
|
||||
label="Settings"
|
||||
accessibilityLabel="Settings"
|
||||
accessibilityLabel={_(msg`Settings`)}
|
||||
accessibilityHint=""
|
||||
onPress={onPressSettings}
|
||||
/>
|
||||
|
@ -346,7 +349,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
|
|||
<View style={styles.footer}>
|
||||
<TouchableOpacity
|
||||
accessibilityRole="link"
|
||||
accessibilityLabel="Send feedback"
|
||||
accessibilityLabel={_(msg`Send feedback`)}
|
||||
accessibilityHint=""
|
||||
onPress={onPressFeedback}
|
||||
style={[
|
||||
|
@ -362,17 +365,17 @@ export const DrawerContent = observer(function DrawerContentImpl() {
|
|||
icon={['far', 'message']}
|
||||
/>
|
||||
<Text type="lg-medium" style={[pal.link, s.pl10]}>
|
||||
Feedback
|
||||
<Trans>Feedback</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
accessibilityRole="link"
|
||||
accessibilityLabel="Send feedback"
|
||||
accessibilityLabel={_(msg`Send feedback`)}
|
||||
accessibilityHint=""
|
||||
onPress={onPressHelp}
|
||||
style={[styles.footerBtn]}>
|
||||
<Text type="lg-medium" style={[pal.link, s.pl10]}>
|
||||
Help
|
||||
<Trans>Help</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
|
|
@ -24,6 +24,8 @@ import {styles} from './BottomBarStyles'
|
|||
import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
|
||||
import {useNavigationTabState} from 'lib/hooks/useNavigationTabState'
|
||||
import {UserAvatar} from 'view/com/util/UserAvatar'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds'
|
||||
|
@ -34,6 +36,7 @@ export const BottomBar = observer(function BottomBarImpl({
|
|||
const {openModal} = useModalControls()
|
||||
const store = useStores()
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const safeAreaInsets = useSafeAreaInsets()
|
||||
const {track} = useAnalytics()
|
||||
const {isAtHome, isAtSearch, isAtFeeds, isAtNotifications, isAtMyProfile} =
|
||||
|
@ -105,7 +108,7 @@ export const BottomBar = observer(function BottomBarImpl({
|
|||
}
|
||||
onPress={onPressHome}
|
||||
accessibilityRole="tab"
|
||||
accessibilityLabel="Home"
|
||||
accessibilityLabel={_(msg`Home`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
<Btn
|
||||
|
@ -127,7 +130,7 @@ export const BottomBar = observer(function BottomBarImpl({
|
|||
}
|
||||
onPress={onPressSearch}
|
||||
accessibilityRole="search"
|
||||
accessibilityLabel="Search"
|
||||
accessibilityLabel={_(msg`Search`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
<Btn
|
||||
|
@ -149,7 +152,7 @@ export const BottomBar = observer(function BottomBarImpl({
|
|||
}
|
||||
onPress={onPressFeeds}
|
||||
accessibilityRole="tab"
|
||||
accessibilityLabel="Feeds"
|
||||
accessibilityLabel={_(msg`Feeds`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
<Btn
|
||||
|
@ -173,7 +176,7 @@ export const BottomBar = observer(function BottomBarImpl({
|
|||
notificationCount={notifications.unreadCountLabel}
|
||||
accessible={true}
|
||||
accessibilityRole="tab"
|
||||
accessibilityLabel="Notifications"
|
||||
accessibilityLabel={_(msg`Notifications`)}
|
||||
accessibilityHint={
|
||||
notifications.unreadCountLabel === ''
|
||||
? ''
|
||||
|
@ -215,7 +218,7 @@ export const BottomBar = observer(function BottomBarImpl({
|
|||
onPress={onPressProfile}
|
||||
onLongPress={onLongPressProfile}
|
||||
accessibilityRole="tab"
|
||||
accessibilityLabel="Profile"
|
||||
accessibilityLabel={_(msg`Profile`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
</Animated.View>
|
||||
|
|
|
@ -39,6 +39,8 @@ import {getCurrentRoute, isTab, isStateAtTabRoot} from 'lib/routes/helpers'
|
|||
import {NavigationProp, CommonNavigatorParams} from 'lib/routes/types'
|
||||
import {router} from '../../../routes'
|
||||
import {makeProfileLink} from 'lib/routes/links'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
|
||||
const ProfileCard = observer(function ProfileCardImpl() {
|
||||
const store = useStores()
|
||||
|
@ -67,6 +69,7 @@ function BackBtn() {
|
|||
const {isTablet} = useWebMediaQueries()
|
||||
const pal = usePalette('default')
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {_} = useLingui()
|
||||
const shouldShow = useNavigationState(state => !isStateAtTabRoot(state))
|
||||
|
||||
const onPressBack = React.useCallback(() => {
|
||||
|
@ -86,7 +89,7 @@ function BackBtn() {
|
|||
onPress={onPressBack}
|
||||
style={styles.backBtn}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Go back"
|
||||
accessibilityLabel={_(msg`Go back`)}
|
||||
accessibilityHint="">
|
||||
<FontAwesomeIcon
|
||||
size={24}
|
||||
|
@ -184,6 +187,7 @@ const NavItem = observer(function NavItemImpl({
|
|||
function ComposeBtn() {
|
||||
const store = useStores()
|
||||
const {getState} = useNavigation()
|
||||
const {_} = useLingui()
|
||||
const {isTablet} = useWebMediaQueries()
|
||||
|
||||
const getProfileHandle = async () => {
|
||||
|
@ -222,7 +226,7 @@ function ComposeBtn() {
|
|||
style={[styles.newPostBtn]}
|
||||
onPress={onPressCompose}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="New post"
|
||||
accessibilityLabel={_(msg`New post`)}
|
||||
accessibilityHint="">
|
||||
<View style={styles.newPostBtnIconWrapper}>
|
||||
<ComposeIcon2
|
||||
|
@ -232,7 +236,7 @@ function ComposeBtn() {
|
|||
/>
|
||||
</View>
|
||||
<Text type="button" style={styles.newPostBtnLabel}>
|
||||
New Post
|
||||
<Trans>New Post</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
|
|
|
@ -9,10 +9,13 @@ import {MagnifyingGlassIcon2} from 'lib/icons'
|
|||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {ProfileCard} from 'view/com/profile/ProfileCard'
|
||||
import {Text} from 'view/com/util/text/Text'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
export const DesktopSearch = observer(function DesktopSearch() {
|
||||
const store = useStores()
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const textInput = React.useRef<TextInput>(null)
|
||||
const [isInputFocused, setIsInputFocused] = React.useState<boolean>(false)
|
||||
const [query, setQuery] = React.useState<string>('')
|
||||
|
@ -75,7 +78,7 @@ export const DesktopSearch = observer(function DesktopSearch() {
|
|||
onChangeText={onChangeQuery}
|
||||
onSubmitEditing={onSubmit}
|
||||
accessibilityRole="search"
|
||||
accessibilityLabel="Search"
|
||||
accessibilityLabel={_(msg`Search`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
{query ? (
|
||||
|
@ -83,11 +86,11 @@ export const DesktopSearch = observer(function DesktopSearch() {
|
|||
<TouchableOpacity
|
||||
onPress={onPressCancelSearch}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel search"
|
||||
accessibilityLabel={_(msg`Cancel search`)}
|
||||
accessibilityHint="Exits inputting search query"
|
||||
onAccessibilityEscape={onPressCancelSearch}>
|
||||
<Text type="lg" style={[pal.link]}>
|
||||
Cancel
|
||||
<Trans>Cancel</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
@ -106,7 +109,7 @@ export const DesktopSearch = observer(function DesktopSearch() {
|
|||
) : (
|
||||
<View>
|
||||
<Text style={[pal.textLight, styles.noResults]}>
|
||||
No results found for {autocompleteView.prefix}
|
||||
<Trans>No results found for {autocompleteView.prefix}</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
|
|
@ -17,6 +17,7 @@ import {BottomBarWeb} from './bottom-bar/BottomBarWeb'
|
|||
import {useNavigation} from '@react-navigation/native'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {useAuxClick} from 'lib/hooks/useAuxClick'
|
||||
import {t} from '@lingui/macro'
|
||||
import {
|
||||
useIsDrawerOpen,
|
||||
useSetDrawerOpen,
|
||||
|
@ -73,7 +74,7 @@ const ShellInner = observer(function ShellInnerImpl() {
|
|||
<TouchableOpacity
|
||||
onPress={() => setDrawerOpen(false)}
|
||||
style={styles.drawerMask}
|
||||
accessibilityLabel="Close navigation footer"
|
||||
accessibilityLabel={t`Close navigation footer`}
|
||||
accessibilityHint="Closes bottom navigation bar">
|
||||
<View style={styles.drawerContainer}>
|
||||
<DrawerContent />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue