3.4 KiB
Internationalization
We want the official Bluesky app to be supported in as many languages as possible. If you want to help us translate the app, please open a PR or issue on the Bluesky app repo on GitHub
Tools
We are using Lingui to manage translations. You can find the documentation here.
Adding new strings
When adding a new string, do it as follows:
// Before
import { Text } from "react-native";
<Text>Hello World</Text>
// After
import { Text } from "react-native";
import { Trans } from "@lingui/macro";
<Text><Trans>Hello World</Trans></Text>
The <Trans>
macro will extract the string and add it to the catalog. It is not really a component, but a macro. Further reading here
However sometimes you will run into this case:
// Before
import { Text } from "react-native";
const text = "Hello World";
<Text accessibilityLabel="Label is here">{text}</Text>
In this case, you cannot use the useLingui()
hook:
import { msg } from "@lingui/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):
import { t } from "@lingui/macro";
const text = t`Hello World`;
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.
We can then run yarn intl:compile
to update the translation files in src/locale/locales/{locale}/messages.js
. This will add the new string to the translation files.
The configuration for translations is defined in lingui.config.js
So the workflow is as follows:
- Wrap messages in Trans macro
- Run
yarn intl:extract
command to generate message catalogs - Translate message catalogs (send them to translators usually)
- Run
yarn intl:compile
to create runtime catalogs - Load runtime catalog
- Enjoy translated app!
Common pitfalls
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.
import { msg } from "@lingui/macro";
import { i18n } from "@lingui/core";
const welcomeMessage = msg`Welcome!`;
// ❌ Bad! This code won't work
export function Welcome() {
const buggyWelcome = useMemo(() => {
return i18n._(welcomeMessage);
}, []);
return <div>{buggyWelcome}</div>;
}
// ❌ Bad! This code won't work either because the reference to i18n does not change
export function Welcome() {
const { i18n } = useLingui();
const buggyWelcome = useMemo(() => {
return i18n._(welcomeMessage);
}, [i18n]);
return <div>{buggyWelcome}</div>;
}
// ✅ Good! `useMemo` has i18n context in the dependency
export function Welcome() {
const linguiCtx = useLingui();
const welcome = useMemo(() => {
return linguiCtx.i18n._(welcomeMessage);
}, [linguiCtx]);
return <div>{welcome}</div>;
}
// 🤩 Better! `useMemo` consumes the `_` function from the Lingui context
export function Welcome() {
const { _ } = useLingui();
const welcome = useMemo(() => {
return _(welcomeMessage);
}, [_]);
return <div>{welcome}</div>;
}