From 5985d53625d6936b2500ccdedabf47cbd44865b6 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:31:48 +0800 Subject: [PATCH 1/7] fix: request url --- libs/datasource/i18n/src/scripts/request.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/datasource/i18n/src/scripts/request.ts b/libs/datasource/i18n/src/scripts/request.ts index 64e18bd9bd..3368feb634 100644 --- a/libs/datasource/i18n/src/scripts/request.ts +++ b/libs/datasource/i18n/src/scripts/request.ts @@ -36,7 +36,7 @@ const withTolgee = ( } else { // URL or URLLike + ?RequestInit if (typeof argArray[0] === 'string') { - argArray[0] = TOLGEE_API_URL + argArray[0]; + argArray[0] = `${TOLGEE_API_URL}/v2/projects${argArray[0]}`; } if (!argArray[1]) { argArray[1] = {}; From 2faa87213d253c3e6660a29271a795a3c3389000 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:32:04 +0800 Subject: [PATCH 2/7] feat(i18n): add check mode --- libs/datasource/i18n/src/scripts/sync.ts | 51 +++++++++++++++++++----- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/libs/datasource/i18n/src/scripts/sync.ts b/libs/datasource/i18n/src/scripts/sync.ts index 5b264bf329..c19da6c4ae 100644 --- a/libs/datasource/i18n/src/scripts/sync.ts +++ b/libs/datasource/i18n/src/scripts/sync.ts @@ -78,6 +78,42 @@ const differenceObject = ( return { add, remove, modify }; }; +function warnDiff(diff: { add: string[]; remove: string[]; modify: string[] }) { + if (!diff.add.length) { + } else { + console.log('New keys found:', diff.add.join(', ')); + //See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-notice-message + process.env['CI'] && + console.log( + `::notice file=${BASE_JSON_PATH},line=1,title=New keys::${diff.add.join( + ', ' + )}` + ); + } + if (diff.remove.length) { + console.warn('[WARN]', 'Unused keys found:', diff.remove.join(', ')); + process.env['CI'] && + console.warn( + `::notice file=${BASE_JSON_PATH},line=1,title=Unused keys::${diff.remove.join( + ', ' + )}` + ); + } + if (diff.modify.length) { + console.warn( + '[WARN]', + 'Inconsistent keys found:', + diff.modify.join(', ') + ); + process.env['CI'] && + console.warn( + `::warning file=${BASE_JSON_PATH},line=1,title=Inconsistent keys::${diff.modify.join( + ', ' + )}` + ); + } +} + const main = async () => { console.log('Loading local base translations...'); const baseLocalTranslations = JSON.parse( @@ -107,17 +143,14 @@ const main = async () => { ); console.log(''); // new line - diff.add.length && console.log('New keys found:', diff.add.join(', ')); - diff.remove.length && - console.warn('[WARN]', 'Unused keys found:', diff.remove.join(', ')); - diff.modify.length && - console.warn( - '[WARN]', - 'Inconsistent keys found:', - diff.modify.join(', ') - ); + warnDiff(diff); console.log(''); // new line + if (process.argv.slice(2).includes('--check')) { + // check mode + return; + } + diff.add.forEach(async key => { const val = flatLocalTranslations[key]; console.log(`Creating new key: ${key} -> ${val}`); From 54f1db6fdccb17de8d5a7823b8a01f134a7e7e04 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:33:35 +0800 Subject: [PATCH 3/7] feat(i18n): add sync workflows --- .github/workflows/languages-sync.yml | 56 ++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 .github/workflows/languages-sync.yml diff --git a/.github/workflows/languages-sync.yml b/.github/workflows/languages-sync.yml new file mode 100644 index 0000000000..871307ebf4 --- /dev/null +++ b/.github/workflows/languages-sync.yml @@ -0,0 +1,56 @@ +name: Languages Sync + +on: + push: + branches: [ "develop", "master" ] + paths: + - 'libs/datasource/i18n/**' + - '.github/workflows/languages-sync.yml' + pull_request: + branches: [ "develop", "master" ] + paths: + - 'libs/datasource/i18n/**' + - '.github/workflows/languages-sync.yml' + +# Cancels all previous workflow runs for pull requests that have not completed. +# See https://docs.github.com/en/actions/using-jobs/using-concurrency +concurrency: + # The concurrency group contains the workflow name and the branch name for + # pull requests or the commit hash for any other events. + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} + cancel-in-progress: true + +jobs: + main: + strategy: + matrix: + node-version: [18] + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Use pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 + + - name: Use Node.js ${{ matrix.node-version }} + # https://github.com/actions/setup-node + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'pnpm' + + - name: Install node modules + run: pnpm install + + - name: Check Language Key + if: github.ref != 'refs/heads/develop' && github.ref != 'refs/heads/master' + run: pnpm run --recursive sync-languages:check + + - name: Sync Languages + if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master' + run: pnpm run --recursive sync-languages From 1018149ca4f0382f077aaeb73fde3dd100ee9801 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:33:58 +0800 Subject: [PATCH 4/7] chore(i18n): update package --- libs/datasource/i18n/README.md | 8 +++++--- libs/datasource/i18n/package.json | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libs/datasource/i18n/README.md b/libs/datasource/i18n/README.md index ff902b333c..c454be380a 100644 --- a/libs/datasource/i18n/README.md +++ b/libs/datasource/i18n/README.md @@ -8,7 +8,7 @@ import { useTranslation } from '@toeverything/datasource/i18n'; // base.json // { // 'Text': 'some text', -// 'Switch to language': 'Switch to {language}', +// 'Switch to language': 'Switch to {{language}}', // <- you can interpolation by curly brackets // }; const App = () => { @@ -41,10 +41,12 @@ const App = () => { export TOLGEE_API_KEY=tgpak_XXXXXXX ``` -- Run the `sync` script from package script +- Run the `sync-languages:check` to check all languages +- Run the `sync-languages` script to add new keys to the tolgee platform ## References +- [AFFiNE | Tolgee](https://i18n.affine.pro/) +- [Tolgee Documentation](https://tolgee.io/docs/) - [i18next](https://www.i18next.com/) - [react-i18next](https://react.i18next.com/) -- [Tolgee](https://tolgee.io/docs/) diff --git a/libs/datasource/i18n/package.json b/libs/datasource/i18n/package.json index 8f6afe9b85..cabc0a36b6 100644 --- a/libs/datasource/i18n/package.json +++ b/libs/datasource/i18n/package.json @@ -2,7 +2,8 @@ "name": "@toeverything/datasource/i18n", "version": "0.0.1", "scripts": { - "sync": "NODE_OPTIONS=--experimental-fetch ts-node src/scripts/sync.ts" + "sync-languages": "NODE_OPTIONS=--experimental-fetch ts-node src/scripts/sync.ts", + "sync-languages:check": "pnpm run sync-languages --check" }, "dependencies": { "i18next": "^21.9.1", From cbe508664d83b9c0c8775706ceeebcd1c7725212 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:34:27 +0800 Subject: [PATCH 5/7] chore(i18n): sunset lint workflows --- .github/workflows/lint.yml | 62 -------------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 8efce5cbd4..0000000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Lint - -on: - push: - branches: [master] - # pull_request: - # branches: [master] - -# Cancels all previous workflow runs for pull requests that have not completed. -# See https://docs.github.com/en/actions/using-jobs/using-concurrency -concurrency: - # The concurrency group contains the workflow name and the branch name for - # pull requests or the commit hash for any other events. - group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} - cancel-in-progress: true - -jobs: - main: - strategy: - matrix: - node-version: [16] - os: [ubuntu-latest] - runs-on: ${{ matrix.os }} - # TODO Remove the next line after cleaning all errors - continue-on-error: true - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Use pnpm - uses: pnpm/action-setup@v2 - with: - version: 7 - - - name: Use Node.js ${{ matrix.node-version }} - # https://github.com/actions/setup-node - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - cache: 'pnpm' - - - name: Install node modules - run: pnpm install - - - name: Lint - if: always() - run: pnpm run lint:with-cache - - # - name: Check - # if: always() - # run: pnpm run check - - # - name: Format Check - # if: always() - # run: pnpm run format:ci - - # - name: Build - # run: pnpm run build - - # - name: Test - # run: pnpm run test From ff1cb4da845b9e31cb1fc509ed8a009b8ef383d7 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Fri, 9 Sep 2022 15:14:44 +0800 Subject: [PATCH 6/7] feat(i18n): storage lng --- libs/datasource/i18n/src/index.ts | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/libs/datasource/i18n/src/index.ts b/libs/datasource/i18n/src/index.ts index 187ed40aae..a421494bf8 100644 --- a/libs/datasource/i18n/src/index.ts +++ b/libs/datasource/i18n/src/index.ts @@ -19,6 +19,8 @@ declare module 'react-i18next' { } } +const STORAGE_KEY = 'i18n_lng'; + const LOCALES = [ { value: 'en', text: 'English', res: en_US }, { value: 'zh', text: '简体中文', res: zh_CN }, @@ -29,11 +31,26 @@ const resources = LOCALES.reduce( {} ); +const fallbackLng = LOCALES[0].value; +const standardizeLocale = (language: string) => { + if (LOCALES.find(locale => locale.value === language)) return language; + if ( + LOCALES.find( + locale => locale.value === language.slice(0, 2).toLowerCase() + ) + ) + return language; + return fallbackLng; +}; + +const language = standardizeLocale( + localStorage.getItem(STORAGE_KEY) ?? navigator.language +); + const i18n = i18next.createInstance(); i18n.use(initReactI18next).init({ - // TODO auto detect - lng: LOCALES[0].value, - fallbackLng: LOCALES[0].value, + lng: language, + fallbackLng, debug: process.env['NODE_ENV'] === 'development', resources, @@ -42,6 +59,10 @@ i18n.use(initReactI18next).init({ }, }); +i18n.on('languageChanged', lng => { + localStorage.setItem(STORAGE_KEY, lng); +}); + const I18nProvider = I18nextProvider; export { i18n, useTranslation, I18nProvider, LOCALES }; From d6e408a4be712149ea8674799080aafb873f6614 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Fri, 9 Sep 2022 15:27:03 +0800 Subject: [PATCH 7/7] chore(i18n): clean code --- .github/workflows/languages-sync.yml | 11 +++++++++-- libs/datasource/i18n/package.json | 1 - libs/datasource/i18n/src/scripts/request.ts | 5 +++-- libs/datasource/i18n/src/scripts/sync.ts | 3 +-- pnpm-lock.yaml | 2 -- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/languages-sync.yml b/.github/workflows/languages-sync.yml index 871307ebf4..33b0b79e93 100644 --- a/.github/workflows/languages-sync.yml +++ b/.github/workflows/languages-sync.yml @@ -11,6 +11,7 @@ on: paths: - 'libs/datasource/i18n/**' - '.github/workflows/languages-sync.yml' + workflow_dispatch: # Cancels all previous workflow runs for pull requests that have not completed. # See https://docs.github.com/en/actions/using-jobs/using-concurrency @@ -49,8 +50,14 @@ jobs: - name: Check Language Key if: github.ref != 'refs/heads/develop' && github.ref != 'refs/heads/master' - run: pnpm run --recursive sync-languages:check + working-directory: ./libs/datasource/i18n + run: pnpm run sync-languages:check + env: + TOLGEE_API_KEY: ${{ secrets.TOLGEE_API_KEY }} - name: Sync Languages if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master' - run: pnpm run --recursive sync-languages + working-directory: ./libs/datasource/i18n + run: pnpm run sync-languages + env: + TOLGEE_API_KEY: ${{ secrets.TOLGEE_API_KEY }} diff --git a/libs/datasource/i18n/package.json b/libs/datasource/i18n/package.json index cabc0a36b6..eb1657865e 100644 --- a/libs/datasource/i18n/package.json +++ b/libs/datasource/i18n/package.json @@ -7,7 +7,6 @@ }, "dependencies": { "i18next": "^21.9.1", - "jotai": "^1.8.1", "react-i18next": "^11.18.4" } } diff --git a/libs/datasource/i18n/src/scripts/request.ts b/libs/datasource/i18n/src/scripts/request.ts index 3368feb634..c016909a24 100644 --- a/libs/datasource/i18n/src/scripts/request.ts +++ b/libs/datasource/i18n/src/scripts/request.ts @@ -9,6 +9,7 @@ if (!TOLGEE_API_KEY) { const withTolgee = ( fetch: typeof globalThis.fetch ): typeof globalThis.fetch => { + const baseUrl = `${TOLGEE_API_URL}/v2/projects`; const headers = new Headers({ 'X-API-Key': TOLGEE_API_KEY, 'Content-Type': 'application/json', @@ -29,14 +30,14 @@ const withTolgee = ( if (!argArray[0].headers) { argArray[0] = { ...argArray[0], - url: `${TOLGEE_API_URL}/v2/projects${argArray[0].url}`, + url: `${baseUrl}${argArray[0].url}`, headers, }; } } else { // URL or URLLike + ?RequestInit if (typeof argArray[0] === 'string') { - argArray[0] = `${TOLGEE_API_URL}/v2/projects${argArray[0]}`; + argArray[0] = `${baseUrl}${argArray[0]}`; } if (!argArray[1]) { argArray[1] = {}; diff --git a/libs/datasource/i18n/src/scripts/sync.ts b/libs/datasource/i18n/src/scripts/sync.ts index c19da6c4ae..a71a0de61f 100644 --- a/libs/datasource/i18n/src/scripts/sync.ts +++ b/libs/datasource/i18n/src/scripts/sync.ts @@ -79,8 +79,7 @@ const differenceObject = ( }; function warnDiff(diff: { add: string[]; remove: string[]; modify: string[] }) { - if (!diff.add.length) { - } else { + if (diff.add.length) { console.log('New keys found:', diff.add.join(', ')); //See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-notice-message process.env['CI'] && diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52c187aa40..164e93cf73 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -580,11 +580,9 @@ importers: libs/datasource/i18n: specifiers: i18next: ^21.9.1 - jotai: ^1.8.1 react-i18next: ^11.18.4 dependencies: i18next: 21.9.1 - jotai: 1.8.1 react-i18next: 11.18.4_i18next@21.9.1 libs/datasource/jwt: