-
Notifications
You must be signed in to change notification settings - Fork 787
I18N
Also known as internationalization.
GitPoint source language is English, and any missing (empty) translation will default to that language.
We're currently using a home-made translation mechanism, built on top of react-native-i18n
.
- We write plain English strings in our source code, wrapped in
t()
:
// file: mycomponent.js
// ...
import { t } from "utils";
// ...
export class MyComponent extends React.Component {
props: {
locale: string
};
render() {
return <Text>${t("This will be transalted.", this.props.locale)}</Text>;
}
}
- Our extraction utility (
yarn i18n:extract
) scans our source code, and extract all strings wrapped int()
into the translations files.
New strings are inserted into every language file with an empty value.
$ yarn i18n:extract
Extracting messages in ./src/ using t()
- parsing ./src/components/mycomponent.js .. 1 string found!
Done parsing
Generating translations:
- merged /Users/me/js/react-native/git-point/src/locale/languages/de.js
- merged /Users/me/js/react-native/git-point/src/locale/languages/en.js
- merged /Users/me/js/react-native/git-point/src/locale/languages/fr.js
Done, have fun translating!
✨ Done in 0.21s.
- Translators do their magic
// src/locale/languages/fr.js
module.exports = {
"This will be transalted.": "Ceci sera traduit."
};
We support Strings, Numbers, and Components is placeholders values:
t("You have {count} open issues", this.props.locale, {
count: 42
});
const repoLink = <RepoLink repoId="gitpoint/git-point" />;
t("Visit our {repository}", this.props.locale, {
repository: repoLink
});
Our current implementation is a result of several discussions (See #273).
Not every language use the same strings construction as English, so concatenating translated chunks is always a bad idea.
Don't do
t("This is a {type}", locale, {
type: isPR ? t("Pull Request", locale) : t("Issue", locale)
});
This would result in the following translatable strings (with FR translation):
- This is a {type}: Ceci est un {type}
- Issue: Ticket
- Pull Request: Pull Request
And would result in:
- Ceci est un Ticket
- Ceci est un Pull Request // <- This a wrong, as Pull Request is "feminine" so it should be "une Pull Request"
Do
isPR ? t("This is an Issue", locale) : t("This is a Pull Request");
Now both complete strings will be extracted, and the translator will be able to correctly internationalize them.
Sometimes, you may want to edit or remove a source string from the app. For example, there's a typo in "translated" in the usage sample above.
After fixing the typo in mycomponent.js
and running the extraction again, here's how the French translation file will look like:
// src/locale/languages/fr.js
module.exports = {
"This will be translated.": "", // <- The new and corrected string
"This will be transalted.": "@Ceci sera traduit.@" // <- The now obsolete string
};
As you may see from the above sample, the new string was extracted with an empty counter part. Translators will need to fill in the blanks.
Notice how the old string, even though it's now obsolete, is kept in the translation file and wrapped between @
marks.
This is meant as a courtesy for translators, as they may want to just copy/paste their old translation before manually deleting the obsolete string.
Before you start translating the application into a new language, make sure to open an issue or reach out on Gitter to see if no one is currently working on it. We'd hate to see your efforts go to waste.
- Declare the new language in
package.json
, under thei18n
key, using its ISO 639-1 code. - Run the extraction utility:
yarn i18n:extract
. - Edit the newly create file in
src/locale/languages/
and translate its messages. - Add a new entry in
src/auth/screens/language-settings.js
- Test the application using your new translation and if it all looks good, submit that PR in! 😄
Our team is usually available on gitter should you face any trouble - join us, we ❤️ questions!