Skip to content

Commit

Permalink
Merge pull request #684 from zyf722/i18next-integration-draft
Browse files Browse the repository at this point in the history
feat(ci): update .lokalise.json after pulling from Lokalise
  • Loading branch information
hatemhosny authored Dec 11, 2024
2 parents ed6208b + 52f9f31 commit 310cd77
Show file tree
Hide file tree
Showing 25 changed files with 26,319 additions and 8,276 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/i18n-update-pull.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ jobs:
mkdir -p $LOKALISE_TEMP && touch $LOKALISE_TEMP/locales.zip && npm run i18n-update-pull -- $PR_BRANCH && rm -rf $LOKALISE_TEMP
env:
LOKALISE_TEMP: lokalise_tmp

- name: Generate Lokalise JSON files
run: npm run i18n-lokalise-json all

- name: Linting and fixing
run: npm run fix
Expand Down
14 changes: 13 additions & 1 deletion docs/docs/contribution/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,9 @@ Several npm scripts are available to facilitate the i18n workflow:
- The `<phase>` argument is required to specify whether the script is to exclude files or revert the exclusion. Valid values are `pre` and `post`.
- This script only works when environment variable `BUILD_INCLUDE_LOCALES` is **NOT** set to `true`.
- [`i18n-lokalise-json`](../../../scripts/i18n-lokalise-json.mjs): Generates `.lokalise.json` files from codebase for manually authoring translations on Lokalise.
- The `<lang>` argument is required to specify the language that the `.lokalise.json` files are generated from.
- Arguments to the script are required to specify the languages that the `.lokalise.json` files are generated from.
- You can also use `all` to generate `.lokalise.json` files for all languages.
- This script **should not** be used for the source language English. Use `i18n-export` instead.

Please run `i18n-export` before pushing changes to the codebase to ensure that the source texts are up-to-date.

Expand Down Expand Up @@ -204,6 +206,16 @@ This means new changes are made to the source code/texts. In this case, maintain
7. Once the translation is complete, maintainers can comment `.i18n-update-pull` to trigger the `i18n-update-pull` workflow. The workflow will pull the translated texts from Lokalise, update the `.ts` files under `src/livecodes/i18n/locales`, and commit the changes to the `i18n/<owner>/<head-branch>` branch. Then, it will create a PR to merge the changes back to the default branch `develop`.
8. Maintainers should perform a final review on the i18n PR and merge it if everything is fine. Meanwhile, a merging from the `i18n/<owner>/<head-branch>` to `master` should also be done to keep the `master` branch on Lokalise up-to-date.

#### Minor Fixes / Updates
Sometimes there is already an ongoing main prerelease branch with many features being developed and translated on Lokalise, and a minor fix or update to the prerelease branch is needed. In this case, maintainers should follow the steps below:

1. Switch to `develop` branch.
2. Do `i18n-export` and upload corresponding `.lokalise.json` to the prerelease branch of the Lokalise project through web UI.
3. Affected entries will be updated and [marked as `unverified`](https://docs.lokalise.com/en/articles/3684557-translation-statuses-translated-verified-reviewed-and-completed#verified-and-unverified).
4. Provide correct translations in other languages on Lokalise.

Here we do not want an extra i18n branch for simplicity, nor need to pull from Lokalise as we always consider English source strings from codebase as the latest version and do not recommend modifying them on Lokalise directly.

### Github Actions (CI)

Four i18n-related workflows are set up in the repository:
Expand Down
50 changes: 37 additions & 13 deletions scripts/i18n-lokalise-json.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,42 @@ const parseObject = (node) => {
result[key] = parseValue(prop.value);
});
return result;
}
};

const parseValue = (node) => {
switch (node.type) {
case "ObjectExpression":
case 'ObjectExpression':
return parseObject(node);
case "ArrayExpression":
case 'ArrayExpression':
return node.elements.map(parseValue);
case "StringLiteral":
case "NumericLiteral":
case "BooleanLiteral":
case 'StringLiteral':
case 'NumericLiteral':
case 'BooleanLiteral':
return node.value;
case "NullLiteral":
case 'NullLiteral':
return null;
default:
throw new Error(`Unsupported node type: ${node.type}`);
}
}
};

const generateLokaliseJSON = async () => {
const lang = process.argv[2];
/** @param {string} lang */
const generateLokaliseJSON = async (lang) => {
const srcDir = path.resolve('src/livecodes/i18n/locales/' + lang);
if (!fs.existsSync(srcDir)) {
console.error(`Language ${srcDir} does not exist.`);
return;
} else if (lang === 'en') {
console.warn('This script is not intended to be run for English language.\nPlease use `npm run i18n-export` instead.');
return
}

const files = fs
.readdirSync(srcDir)
.filter((file) => file.endsWith('.ts'))
.map((file) => path.resolve(srcDir, file));

await Promise.all(
return Promise.all(
files.map(async (file) => {
try {
console.log(`Generating Lokalise JSON for ${file} in language ${lang}...`);
Expand All @@ -83,12 +86,33 @@ const generateLokaliseJSON = async () => {
}

const outFile = path.resolve(srcDir, file.replace('.ts', '.lokalise.json'));
await fs.promises.writeFile(outFile, sortedJSONify(result).replace(/<(\/?)(\d+)>/g, '<$1tag-$2>'));
await fs.promises.writeFile(
outFile,
sortedJSONify(result).replace(/<(\/?)(\d+)>/g, '<$1tag-$2>'),
);
} catch (err) {
console.error(err);
}
}),
);
};

generateLokaliseJSON();
const main = async () => {
const langs = new Set(process.argv.slice(2));

if (langs.has('all')) {
langs.delete('all');
const srcDir = path.resolve('src/livecodes/i18n/locales');
const files = fs
.readdirSync(srcDir)
.filter(
(file) =>
fs.statSync(path.resolve(srcDir, file)).isDirectory() && file !== 'en' && file !== 'tmp',
);
files.forEach((file) => langs.add(file));
}

await Promise.all([...langs].map(generateLokaliseJSON));
};

main();
20 changes: 19 additions & 1 deletion src/livecodes/i18n/locales/ar/language-info.lokalise.json
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@
"translation": "يتم ترجمة JSX إلى جافا سكريبت في LiveCodes باستخدام مترجم TypeScript. افتراضيًا، يستخدم React كبيئة تشغيل JSX."
},
"jsx.link": {
"translation": "<tag-1> <tag-2>الموقع الرسمي لـ React</tag-2> </tag-1> <tag-3> <tag-4>وثائق JSX في React</tag-4> </tag-3> <tag-5> <tag-6>وثائق LiveCodes</tag-6> </tag-5> <tag-7> <tag-8>تحميل قالب البداية</tag-8> </tag-7>"
"translation": "<tag-1> <tag-2>الموقع الرسمي لـ React</tag-2> </tag-1> <tag-3> <tag-4>وثائق JSX في React</tag-4> </tag-3> <tag-5> <tag-6>وثائق LiveCodes</tag-6> </tag-5>"
},
"jsx.name": {
"translation": "JSX"
Expand Down Expand Up @@ -456,6 +456,15 @@
"r.name": {
"translation": "R"
},
"react.desc": {
"translation": "React Compiler هو أداة تعمل في وقت البناء فقط وتقوم تلقائياً بتحسين تطبيقات React."
},
"react.link": {
"translation": "<tag-1> <tag-2>موقع React الرسمي</tag-2> </tag-1> <tag-3> <tag-4>مُترجم React</tag-4> </tag-3> <tag-5> <tag-6>وثائق LiveCodes</tag-6> </tag-5> <tag-7> <tag-8>تحميل القالب المبدئي</tag-8> </tag-7>"
},
"react.name": {
"translation": "مترجم React"
},
"reactNative.desc": {
"translation": "React Native للويب هو تنفيذ سهل الوصول لمكونات وواجهات برمجة تطبيقات React Native التي تتوافق مع React DOM."
},
Expand All @@ -474,6 +483,15 @@
"reactNativeTsx.name": {
"translation": "React Native للويب (مع TypeScript)"
},
"reactTsx.desc": {
"translation": "React Compiler هو أداة تعمل في وقت البناء فقط وتقوم تلقائياً بتحسين تطبيقات React."
},
"reactTsx.link": {
"translation": "<tag-1> <tag-2>موقع React الرسمي</tag-2> </tag-1> <tag-3> <tag-4>مُترجم React</tag-4> </tag-3> <tag-5> <tag-6>موقع TypeScript</tag-6> </tag-5> <tag-7> <tag-8>وثائق TypeScript</tag-8> </tag-7> <tag-9> <tag-10>وثائق LiveCodes</tag-10> </tag-9> <tag-11> <tag-12>تحميل القالب المبدئي (JSX)</tag-12> </tag-11>"
},
"reactTsx.name": {
"translation": "مترجم React (مع TypeScript)"
},
"reason.desc1": {
"translation": "تتيح لك Reason كتابة كود بسيط وسريع وعالي الجودة وآمن الأنواع مع الاستفادة من النظم البيئية لكل من JavaScript و OCaml."
},
Expand Down
Loading

0 comments on commit 310cd77

Please sign in to comment.