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:
Ansh 2023-11-09 10:04:16 -08:00 committed by GitHub
parent 82059b7ee1
commit 4c7850f8c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
108 changed files with 10334 additions and 1365 deletions

View file

@ -10,6 +10,8 @@ import {Text} from 'view/com/util/text/Text'
import {Dimensions} from 'lib/media/types'
import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useModalControls} from '#/state/modals'
import {isNative} from 'platform/detection'
@ -48,6 +50,7 @@ const GalleryInner = observer(function GalleryImpl({
containerInfo,
}: GalleryInnerProps) {
const pal = usePalette('default')
const {_} = useLingui()
const {isMobile} = useWebMediaQueries()
const {openModal} = useModalControls()
@ -113,7 +116,7 @@ const GalleryInner = observer(function GalleryImpl({
<TouchableOpacity
testID="altTextButton"
accessibilityRole="button"
accessibilityLabel="Add alt text"
accessibilityLabel={_(msg`Add alt text`)}
accessibilityHint=""
onPress={() => {
Keyboard.dismiss()
@ -124,7 +127,7 @@ const GalleryInner = observer(function GalleryImpl({
}}
style={[styles.altTextControl, altTextControlStyle]}>
<Text style={styles.altTextControlLabel} accessible={false}>
ALT
<Trans>ALT</Trans>
</Text>
{image.altText.length > 0 ? (
<FontAwesomeIcon
@ -138,7 +141,7 @@ const GalleryInner = observer(function GalleryImpl({
<TouchableOpacity
testID="editPhotoButton"
accessibilityRole="button"
accessibilityLabel="Edit image"
accessibilityLabel={_(msg`Edit image`)}
accessibilityHint=""
onPress={() => {
if (isNative) {
@ -161,7 +164,7 @@ const GalleryInner = observer(function GalleryImpl({
<TouchableOpacity
testID="removePhotoButton"
accessibilityRole="button"
accessibilityLabel="Remove image"
accessibilityLabel={_(msg`Remove image`)}
accessibilityHint=""
onPress={() => gallery.remove(image)}
style={styles.imageControl}>
@ -174,7 +177,7 @@ const GalleryInner = observer(function GalleryImpl({
</View>
<TouchableOpacity
accessibilityRole="button"
accessibilityLabel="Add alt text"
accessibilityLabel={_(msg`Add alt text`)}
accessibilityHint=""
onPress={() => {
Keyboard.dismiss()
@ -203,8 +206,10 @@ const GalleryInner = observer(function GalleryImpl({
<FontAwesomeIcon icon="info" size={12} color={pal.colors.text} />
</View>
<Text type="sm" style={[pal.textLight, s.flex1]}>
Alt text describes images for blind and low-vision users, and helps
give context to everyone.
<Trans>
Alt text describes images for blind and low-vision users, and helps
give context to everyone.
</Trans>
</Text>
</View>
</>

View file

@ -13,6 +13,8 @@ import {HITSLOP_10, POST_IMG_MAX} from 'lib/constants'
import {GalleryModel} from 'state/models/media/gallery'
import {isMobileWeb, isNative} from 'platform/detection'
import {logger} from '#/logger'
import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
type Props = {
gallery: GalleryModel
@ -22,6 +24,7 @@ export function OpenCameraBtn({gallery}: Props) {
const pal = usePalette('default')
const {track} = useAnalytics()
const store = useStores()
const {_} = useLingui()
const {requestCameraAccessIfNeeded} = useCameraPermission()
const onPressTakePicture = useCallback(async () => {
@ -56,7 +59,7 @@ export function OpenCameraBtn({gallery}: Props) {
style={styles.button}
hitSlop={HITSLOP_10}
accessibilityRole="button"
accessibilityLabel="Camera"
accessibilityLabel={_(msg`Camera`)}
accessibilityHint="Opens camera on device">
<FontAwesomeIcon
icon="camera"

View file

@ -10,6 +10,8 @@ import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions'
import {GalleryModel} from 'state/models/media/gallery'
import {HITSLOP_10} from 'lib/constants'
import {isNative} from 'platform/detection'
import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
type Props = {
gallery: GalleryModel
@ -18,6 +20,7 @@ type Props = {
export function SelectPhotoBtn({gallery}: Props) {
const pal = usePalette('default')
const {track} = useAnalytics()
const {_} = useLingui()
const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
const onPressSelectPhotos = useCallback(async () => {
@ -37,7 +40,7 @@ export function SelectPhotoBtn({gallery}: Props) {
style={styles.button}
hitSlop={HITSLOP_10}
accessibilityRole="button"
accessibilityLabel="Gallery"
accessibilityLabel={_(msg`Gallery`)}
accessibilityHint="Opens device photo gallery">
<FontAwesomeIcon
icon={['far', 'image']}