Skip to content
Mehdi Achour edited this page Apr 26, 2018 · 1 revision

Also known as internationalization.

Implementation

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.

The translation process

  1. 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>;
  }
}
  1. Our extraction utility (yarn i18n:extract) scans our source code, and extract all strings wrapped in t() 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.
  1. Translators do their magic
// src/locale/languages/fr.js
module.exports = {
  "This will be transalted.": "Ceci sera traduit."
};

Placeholders

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
});

How to properly write English strings

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.

Obsolete strings

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.

Adding a new language

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.

  1. Declare the new language in package.json, under the i18n key, using its ISO 639-1 code.
  2. Run the extraction utility: yarn i18n:extract.
  3. Edit the newly create file in src/locale/languages/ and translate its messages.
  4. Add a new entry in src/auth/screens/language-settings.js
  5. Test the application using your new translation and if it all looks good, submit that PR in! 😄