# wttj-config <!-- omit in toc -->

- [Introduction](#introduction)
- [Important considerations](#important-considerations)
- [Automatic Id generation](#automatic-id-generation)
  - [Benefits](#benefits)
  - [Limitation](#limitation)
- [Contextualization](#contextualization)
- [Installation](#installation)
- [Usage](#usage)

## Introduction

i18n translations for wttj projects are based on react-intl / formatjs

Many choices have been made hand in hand with our product writer to make translations as easy as possible to use and maintain.

A core concept of this process is the automatic id generation which has its own section below. Please read it carefully.

## Important considerations

- Source locales should be in english in every projects.
- Developers are responsible for source translations (ie: `en-US.json`).
- Lokalise is responsible for target translations (ie: `fr-FR.json`, `es-ES.json`, …).
- As the source locale is generated by formatjs, updates on the file will be overriden at the next extraction.
- As the target locales are proposed through pr's by lokalise, updates on these files will be overriden at the next target locale pr approval.
- Every update to the source locales is followed by an update of the contextualized source locales on lokalise with the `lokalise2` cli command.

## Automatic Id generation

As said before, a core feature on this i18n process is based on automatic id generation. It comes with benefits as well as a limitation that you should be aware of:

### Benefits

- No need to think about choosing an id for a translation, it's automatically generated by your editor on save thanks to an eslint rule (see the [installation](#installation) section on eslintrc rule)!
- Locales are as DRY as possible, since the id is generated from the `defaultMessage` itself. Same `defaultMessage`, same id, simple as that. No common id to maintain!

### Limitation

- Product writers can't use the id to get context on the translation as it doesn't mean anything (but we have a solution for that, see [Contextualization](#contextualization) section).

## Contextualization

To help product writers have more context on the translation they are working on, we generate a `contextualized-en-US.json` file that contains a github link to the file where the translation is used in the code.

This file is then used by lokalise to provide context to the translators.

## Update last source locales to lokalise

CircleCI is responsible for updating the last source locales to lokalise. It uses the `lokalise2` cli command to do so.

It will run on every push on the `main` branch so that our product writers always have the last source locales to work on.

Actually, it is not possible to work on branches other than `main`, but it could be possible if we need it by upgrading our plan on lokalise and change some CircleCI configuration accordingly.

Add the following code to your circleci configuration file and adapt it to your circleci configuration:

```yaml
    jobs:
      check_translations:
        <<: *defaults
        machine:
          image: default
        steps:
          - *restore_repo
          - *restore_node_modules
          - run:
              name: Check i18n translations between code and generated source locales (en-US by default)
              command: |
                node ~/CHANGE_ME_FOR_YOUR_APP_NAME/node_modules/wttj-config/lib/i18n/check.mjs

      update_translations:
        <<: *defaults
        machine:
          image: default
        steps:
          - *restore_repo
          - *restore_node_modules
          - run:
              name: Download and install lokalise-cli v2
              command: |
                curl -sfL https://raw.githubusercontent.com/lokalise/lokalise-cli-2-go/master/install.sh | sh
                # Make it executable
                chmod +x ./bin/lokalise2
                sudo mv ./bin/lokalise2 /usr/local/bin/
                # Verify installation
                lokalise2 --version
          - run:
              name: Update source locales to lokalise via lokalise2
              command: |
                lokalise2 --token $LOKALISE_TOKEN --project-id $LOKALISE_PROJECT_ID file upload --file REPLACE_ME_WITH_LOCALES_DIR_PATH_VALUE/contextualized-en-US.json --lang-iso en-US --cleanup-mode --convert-placeholders=false --replace-modified
    […]

    workflows:
      test_and_build:
        jobs:
          - check_translations:
              context: i18n
              requires:
                - checkout
          - update_translations:
              context: i18n
              requires:
                - check_translations
              filters:
                branches:
                  only: main

```

Please note that we filter the branches to only `main` to avoid updating the source locales on lokalise with every push on every branch.

## Installation

```bash
yarn add react-intl
yarn add -D wttj-config @formatjs/cli eslint-plugin-formatjs
```

## Usage

First, add the following scripts in the `package.json` of your app:

1. under a `config` key:

```json
    "config": {
      "i18n": {
        "app_name": "your-app-name",
        "locales_dir_path": "src/locales",
        "extract_from_pattern": "src/**/*.ts*",
        "default_language_filename": "en-US",
        "path_to_ignore": ""
      }
    }
```

- `app_name` is the name of your app_name
- `locales_dir_path` is the folder where you want your locales to be generated in
- `extract_from_pattern` is the global pattern where you want the scripts to look for translations
- `default_language_filename` is the default language filename
- `path_to_ignore` is a path where you don't want the scripts to look for translations ( if it is inside the `extract_from_pattern` global pattern ). Set to '' if you don't want to ignore any path.

2. under the `scripts` key:

```json
    "scripts": {
      "i18n:extract": "formatjs extract \"$npm_package_config_i18n_extract_from_pattern\" --ignore=\"{**/*.d.ts,$npm_package_config_i18n_path_to_ignore}\" --out-file $npm_package_config_i18n_locales_dir_path/temp.json --flatten --format simple",
      "i18n:contextualize": "node node_modules/wttj-config/lib/i18n/contextualize.mjs",
      "i18n:sync": "node node_modules/wttj-config/lib/i18n/sync.mjs",
      "i18n:translate": "yarn --silent i18n:extract && yarn --silent i18n:sync && yarn --silent i18n:contextualize",// remove --silent if you are using yarn v4
    }
```

Update your `.eslintrc.cjs` configuration to include the following:

- `formatjs` in your plugins:

```javascript
  plugins: ['testing-library', 'formatjs', '@vitest'],
```

- under the `rules` key:

```javascript
    'formatjs/enforce-id': [
      'error',
      {
        idInterpolationPattern: '[sha512:contenthash:base64:6]',
      },
    ],
```

If you use husky, add the following line in a precommit hook `./husky/pre-commit` to automatize the translation process:

```shell
node ./node_modules/wttj-config/lib/i18n/precommit.mjs
```

If you don't use husky, you will be responsible for running the `i18n:translate` script before pushing your code (not recommended as many automation are made in the precommit hook).

This should be it, enjoy and don't hesitate to reach out if you have any questions / issues!
