Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ google-services.json

# i18n
src/locale/locales/_build/
src/locale/locales/**/*.js
src/locale/locales/**/messages.js
src/locale/locales/**/messages.mjs
src/locale/locales/**/messages.ts

# local builds
*.apk
Expand Down
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,8 @@ import * as TextField from '#/components/forms/TextField'
All user-facing strings must be wrapped for translation using Lingui.

```tsx
import {msg, Trans, plural} from '@lingui/macro'
import {msg, plural} from '@lingui/core/macro'
import {Trans} from '@lingui/react/macro'
import {useLingui} from '@lingui/react'

function MyComponent() {
Expand Down
6 changes: 6 additions & 0 deletions __tests__/lib/string.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {RichText} from '@atproto/api'
import {i18n} from '@lingui/core'

import {parseEmbedPlayerFromUrl} from '#/lib/strings/embed-player'
import {
createStarterPackGooglePlayUri,
createStarterPackLinkFromAndroidReferrer,
parseStarterPackUri,
} from '#/lib/strings/starter-pack'
import {messages} from '#/locale/locales/en/messages'
import {tenorUrlToBskyGifUrl} from '#/state/queries/tenor'
import {cleanError} from '../../src/lib/strings/errors'
import {createFullHandle, makeValidHandle} from '../../src/lib/strings/handles'
Expand Down Expand Up @@ -202,6 +204,9 @@ describe('enforceLen', () => {
})

describe('cleanError', () => {
// cleanError uses lingui
i18n.loadAndActivate({locale: 'en', messages})

const inputs = [
'TypeError: Network request failed',
'Error: Aborted',
Expand Down Expand Up @@ -327,6 +332,7 @@ describe('shortenLinks', () => {
expect(outputRT.text).toEqual(outputs[i][0])
expect(outputRT.facets?.length).toEqual(outputs[i][1].length)
for (let j = 0; j < outputs[i][1].length; j++) {
// @ts-expect-error whatever
expect(outputRT.facets![j].features[0].uri).toEqual(outputs[i][1][j])
}
}
Expand Down
2 changes: 1 addition & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = function (api) {
],
],
plugins: [
'macros',
'@lingui/babel-plugin-lingui-macro',
['babel-plugin-react-compiler', {target: '19'}],
[
'module:react-native-dotenv',
Expand Down
25 changes: 20 additions & 5 deletions docs/localization.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ import { Text } from "react-native";
```jsx
// After
import { Text } from "react-native";
import { Trans } from "@lingui/macro";
import { Trans } from "@lingui/react/macro";

<Text><Trans>Hello World</Trans></Text>
```
Expand All @@ -90,18 +90,33 @@ const text = "Hello World";
```
In this case, you can use the `useLingui()` hook:
```jsx
import { msg } from "@lingui/macro";
import { msg } from "@lingui/core/macro";
import { useLingui } from "@lingui/react";

const { _ } = useLingui();
return <Text accessibilityLabel={_(msg`Label is here`)}>{text}</Text>
```

If you want to do this outside of a React component, you can use the `t` macro instead (note: this won't react to changes if the locale is switched dynamically within the app):
NEW: the latest Lingui version introduced a new macro version of the `useLingui` hook which lets you do this:

```jsx
import { t } from "@lingui/macro";
import { useLingui } from "@lingui/react/macro";

const { t } = useLingui();
return <Text accessibilityLabel={t`Label is here`}>{text}</Text>
```

If you want to do this outside of a React component, you can use the global `t` macro instead (note: this won't react to changes if the locale is switched dynamically within the app):
```jsx
import { t } from "@lingui/core/macro";

// not ideal - t only gets called once at module evaluation time
const text = t`Hello World`;

// however, this is suitable for strings that are ephemeral:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great docs 👍

function sayHello() {
Toast.show(t`Hello World`); // Each time the toast shows, the current locale at that moment is used
}
```

We can then run `yarn intl:extract` to update the catalog in `src/locale/locales/{locale}/messages.po`. This will add the new string to the catalog.
Expand All @@ -121,7 +136,7 @@ So the workflow is as follows:
These pitfalls are memoization pitfalls that will cause the components to not re-render when the locale is changed -- causing stale translations to be shown.

```jsx
import { msg } from "@lingui/macro";
import { msg } from "@lingui/core/macro";
import { i18n } from "@lingui/core";

const welcomeMessage = msg`Welcome!`;
Expand Down
10 changes: 6 additions & 4 deletions lingui.config.js → lingui.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/** @type {import('@lingui/conf').LinguiConfig} */
module.exports = {
import {defineConfig} from '@lingui/cli'

export default defineConfig({
sourceLocale: 'en',
locales: [
'en',
'an',
Expand Down Expand Up @@ -49,5 +51,5 @@ module.exports = {
include: ['src'],
},
],
format: 'po',
}
compileNamespace: 'ts',
})
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"intl:extract": "lingui extract --clean --locale en",
"intl:extract:all": "lingui extract --clean",
"intl:compile": "lingui compile",
"intl:compile-if-needed": "is-ci || [ -f src/locale/locales/en/messages.js ] || yarn intl:compile",
"intl:compile-if-needed": "is-ci || [ -f src/locale/locales/en/messages.ts ] || yarn intl:compile",
"intl:pull": "crowdin download translations --verbose -b main",
"intl:push": "crowdin push translations --verbose -b main",
"intl:push-sources": "crowdin push sources --verbose -b main",
Expand Down Expand Up @@ -97,7 +97,8 @@
"@growthbook/growthbook-react": "^1.6.5",
"@haileyok/bluesky-video": "0.3.2",
"@ipld/dag-cbor": "^9.2.0",
"@lingui/react": "^4.14.1",
"@lingui/core": "^5.9.2",
"@lingui/react": "^5.9.2",
"@mattermost/react-native-paste-input": "mattermost/react-native-paste-input",
"@miblanchard/react-native-slider": "^2.6.0",
"@mozzius/expo-dynamic-app-icon": "^1.8.0",
Expand Down Expand Up @@ -236,8 +237,8 @@
"@babel/runtime": "^7.26.0",
"@eslint/js": "^9.39.2",
"@expo/config-plugins": "~54.0.1",
"@lingui/cli": "^4.14.1",
"@lingui/macro": "^4.14.1",
"@lingui/babel-plugin-lingui-macro": "^5.9.2",
"@lingui/cli": "^5.9.2",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
"@react-native/babel-preset": "0.81.5",
"@react-native/eslint-config": "^0.81.5",
Expand All @@ -252,7 +253,6 @@
"@types/react": "^19.1.12",
"@types/react-dom": "^19.1.9",
"babel-jest": "^29.7.0",
"babel-plugin-macros": "^3.1.0",
"babel-plugin-module-resolver": "^5.0.2",
"babel-plugin-react-compiler": "^19.1.0-rc.3",
"babel-preset-expo": "~54.0.0",
Expand Down
10 changes: 0 additions & 10 deletions patches/@lingui+core+4.14.1.patch

This file was deleted.

2 changes: 1 addition & 1 deletion src/App.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import * as ScreenOrientation from 'expo-screen-orientation'
import * as SplashScreen from 'expo-splash-screen'
import * as SystemUI from 'expo-system-ui'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import * as Sentry from '@sentry/react-native'

Expand Down
2 changes: 1 addition & 1 deletion src/App.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import './style.css'

import {Fragment, useEffect, useState} from 'react'
import {SafeAreaProvider} from 'react-native-safe-area-context'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import * as Sentry from '@sentry/react-native'

Expand Down
2 changes: 1 addition & 1 deletion src/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {type JSX, useCallback, useRef} from 'react'
import * as Linking from 'expo-linking'
import * as Notifications from 'expo-notifications'
import {i18n, type MessageDescriptor} from '@lingui/core'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {
type BottomTabBarProps,
createBottomTabNavigator,
Expand Down
3 changes: 2 additions & 1 deletion src/ageAssurance/components/NoAccessScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {useCallback, useEffect} from 'react'
import {ScrollView, View} from 'react-native'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {msg, Trans} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'

import {
SupportCode,
Expand Down
3 changes: 2 additions & 1 deletion src/ageAssurance/components/RedirectOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import {
} from 'react'
import {Dimensions, View} from 'react-native'
import * as Linking from 'expo-linking'
import {msg, Trans} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'

import {retry} from '#/lib/async/retry'
import {wait} from '#/lib/async/wait'
Expand Down
3 changes: 2 additions & 1 deletion src/components/AccountList.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React, {useCallback} from 'react'
import {View} from 'react-native'
import {type AppBskyActorDefs} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'

import {isJwtExpired} from '#/lib/jwt'
import {sanitizeDisplayName} from '#/lib/strings/display-names'
Expand Down
2 changes: 1 addition & 1 deletion src/components/AppLanguageDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query'

Expand Down
2 changes: 1 addition & 1 deletion src/components/ContextMenu/Backdrop.ios.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Animated, {
useAnimatedStyle,
} from 'react-native-reanimated'
import {BlurView} from 'expo-blur'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'

import {atoms as a, useTheme} from '#/alf'
Expand Down
2 changes: 1 addition & 1 deletion src/components/ContextMenu/Backdrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Animated, {
type SharedValue,
useAnimatedStyle,
} from 'react-native-reanimated'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'

import {atoms as a, useTheme} from '#/alf'
Expand Down
2 changes: 1 addition & 1 deletion src/components/ContextMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
} from 'react-native-safe-area-context'
import {captureRef} from 'react-native-view-shot'
import {Image, type ImageErrorEventData} from 'expo-image'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {useIsFocused} from '@react-navigation/native'
import flattenReactChildren from 'react-keyed-flatten-children'
Expand Down
2 changes: 1 addition & 1 deletion src/components/Dialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import Animated, {
useAnimatedStyle,
} from 'react-native-reanimated'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'

import {ScrollProvider} from '#/lib/ScrollContext'
Expand Down
2 changes: 1 addition & 1 deletion src/components/Dialog/index.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
View,
type ViewStyle,
} from 'react-native'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {DismissableLayer, FocusGuards, FocusScope} from 'radix-ui/internal'
import {RemoveScrollBar} from 'react-remove-scroll-bar'
Expand Down
3 changes: 2 additions & 1 deletion src/components/Error.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'

import {useGoBack} from '#/lib/hooks/useGoBack'
import {CenteredView} from '#/view/com/util/Views'
Expand Down
3 changes: 2 additions & 1 deletion src/components/FeedCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {
AtUri,
RichText as RichTextApi,
} from '@atproto/api'
import {msg, Plural, Trans} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Plural, Trans} from '@lingui/react/macro'
import {useQueryClient} from '@tanstack/react-query'

import {sanitizeHandle} from '#/lib/strings/handles'
Expand Down
3 changes: 2 additions & 1 deletion src/components/FeedInterstitials.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import Animated, {
LinearTransition,
} from 'react-native-reanimated'
import {type AppBskyFeedDefs, AtUri} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useNavigation} from '@react-navigation/native'

import {type NavigationProp} from '#/lib/routes/types'
Expand Down
2 changes: 1 addition & 1 deletion src/components/FocusScope/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
Text,
View,
} from 'react-native'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'

import {useA11y} from '#/state/a11y'
Expand Down
2 changes: 1 addition & 1 deletion src/components/InterestTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
View,
type ViewStyle,
} from 'react-native'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'

import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
Expand Down
2 changes: 1 addition & 1 deletion src/components/InternationalPhoneCodeSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Fragment, useMemo} from 'react'
import {Text as RNText} from 'react-native'
import {Image} from 'expo-image'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'

import {
Expand Down
6 changes: 3 additions & 3 deletions src/components/KnownFollowers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import {
moderateProfile,
type ModerationOpts,
} from '@atproto/api'
import {msg, Plural, Trans} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Plural, Trans} from '@lingui/react/macro'

import {makeProfileLink} from '#/lib/routes/links'
import {sanitizeDisplayName} from '#/lib/strings/display-names'
Expand Down Expand Up @@ -205,9 +206,8 @@ function KnownFollowersInner({
one="# other"
other="# others"
/>
</Trans>
</Trans> // only 2
) : (
// only 2
<Trans>
Followed by{' '}
<Text emoji key={slice[0].profile.did} style={textStyle}>
Expand Down
3 changes: 2 additions & 1 deletion src/components/LabelingServiceCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {View} from 'react-native'
import {type AppBskyLabelerDefs} from '@atproto/api'
import {msg, Plural, Trans} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Plural, Trans} from '@lingui/react/macro'
import type React from 'react'

import {getLabelingServiceTitle} from '#/lib/moderation'
Expand Down
2 changes: 1 addition & 1 deletion src/components/LanguageSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import {msg} from '@lingui/macro'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'

import {sanitizeAppLanguageSetting} from '#/locale/helpers'
Expand Down
Loading
Loading