From 32e53ee1ad66a02b7d7839d8763471706c6eba5b Mon Sep 17 00:00:00 2001 From: Neil Date: Tue, 28 Feb 2023 13:38:57 +0800 Subject: [PATCH] I18n crowdin (#242) * #241 init crowdin usage * #241 convert all convertible copy into i18n value --------- Co-authored-by: neil --- .gitignore | 3 +- README.md | 1 + modules/desktop/electron-builder.config.cjs | 12 +--- modules/desktop/package.json | 2 + .../scripts/prepare-crowdin-import.cjs | 36 ++++++++++ .../desktop/scripts/update-translations.cjs | 39 +++++++++++ .../essential-workshops.svelte | 3 +- .../featured-courses/featured-courses.svelte | 3 +- .../footer-links/footer-links.svelte | 13 ++-- .../installed-packages.svelte | 5 +- .../desktop/src/components/news/news.svelte | 3 +- .../src/components/packages/packages.svelte | 11 ++-- .../search-packages/search-packages.svelte | 11 ++-- .../search-packages/sorting-buttons.svelte | 10 ++- .../search-popup-results.svelte | 9 +-- .../suggested-packages.svelte | 9 +-- .../src/components/top-bar/top-bar.svelte | 7 +- .../top-packages/top-packages.svelte | 7 +- .../components/top-scripts/top-scripts.svelte | 16 +++-- .../desktop/src/libs/translations/index.ts | 3 +- .../desktop/src/libs/translations/lang.json | 4 -- .../src/libs/translations/translations.json | 65 +++++++++++++++++++ .../src/libs/translations/translations.ts | 16 ----- modules/desktop/src/routes/+page.svelte | 29 +++++---- .../src/routes/documentation/+page.svelte | 8 ++- modules/ui/src/posts/posts.svelte | 3 +- package.json | 2 + pnpm-lock.yaml | 23 +++++++ 28 files changed, 260 insertions(+), 93 deletions(-) create mode 100644 modules/desktop/scripts/prepare-crowdin-import.cjs create mode 100644 modules/desktop/scripts/update-translations.cjs delete mode 100644 modules/desktop/src/libs/translations/lang.json create mode 100644 modules/desktop/src/libs/translations/translations.json delete mode 100644 modules/desktop/src/libs/translations/translations.ts diff --git a/.gitignore b/.gitignore index eeab4fb..8bfc580 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules yarn-error.log .DS_Store .pnpm-store -target \ No newline at end of file +target +copy.json \ No newline at end of file diff --git a/README.md b/README.md index decb9cb..fc93616 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ pnpm dev ```sh pnpm install +pnpm --filter desktop exec pnpm predist pnpm --filter desktop exec pnpm dist ``` diff --git a/modules/desktop/electron-builder.config.cjs b/modules/desktop/electron-builder.config.cjs index a738e67..8498bbe 100644 --- a/modules/desktop/electron-builder.config.cjs +++ b/modules/desktop/electron-builder.config.cjs @@ -1,6 +1,8 @@ const { notarize } = require("@electron/notarize"); const fs = require("fs"); const path = require("path"); +const otaClient = require("@crowdin/ota-client"); +const _ = require("lodash"); module.exports = { appId: "xyz.tea.gui", @@ -17,8 +19,6 @@ module.exports = { arch: ["x64", "arm64"] } }, - // TODO: if xcrun altool exists eventually in our self-hosted macos - // SOLUTION: is notarize separately in next pipeline step afterSign: async (params) => { if (process.platform !== "darwin") { return; @@ -51,14 +51,6 @@ module.exports = { console.log(`Done notarizing`); }, - - // publish: { - // provider: "github", - // repo: "gui", - // owner: "teaxyz", - // releaseType: "release" - // }, - // this determines the configuration of the auto-update feature publish: { provider: "generic", diff --git a/modules/desktop/package.json b/modules/desktop/package.json index 286465b..d49da1e 100644 --- a/modules/desktop/package.json +++ b/modules/desktop/package.json @@ -14,6 +14,7 @@ "dev:main": "cd ./electron && vite build --config ./vite.config.js --watch", "build:main": "cp package.json electron && cd ./electron && vite --config ./vite.config.js build --base . && rm package.json", "pack": "electron-builder --dir --config electron-builder.config.cjs", + "predist": "node ./scripts/update-translations.cjs", "dist": "pnpm build && electron-builder --config electron-builder.config.cjs", "package": "pnpm build && electron-builder --config electron-builder.config.cjs", "dev:package": "pnpm build && electron-builder --config electron-builder.config.cjs --dir", @@ -72,6 +73,7 @@ }, "type": "module", "dependencies": { + "@crowdin/ota-client": "^0.7.0", "@electron/asar": "^3.2.3", "@sentry/electron": "^4.3.0", "@sentry/svelte": "^7.38.0", diff --git a/modules/desktop/scripts/prepare-crowdin-import.cjs b/modules/desktop/scripts/prepare-crowdin-import.cjs new file mode 100644 index 0000000..204e4b9 --- /dev/null +++ b/modules/desktop/scripts/prepare-crowdin-import.cjs @@ -0,0 +1,36 @@ +const fs = require("fs"); +const _ = require("lodash"); +const translations = require("../src/libs/translations/translations.json"); + +const englishRaw = translations["en"]; + +delete englishRaw.lang; + +function flattenObject(o, prefix = "", result = {}, keepNull = true) { + if (_.isString(o) || _.isNumber(o) || _.isBoolean(o) || (keepNull && _.isNull(o))) { + result[prefix] = o; + return result; + } + + if (_.isArray(o) || _.isPlainObject(o)) { + for (let i in o) { + let pref = prefix; + if (_.isArray(o)) { + pref = pref + `[${i}]`; + } else { + if (_.isEmpty(prefix)) { + pref = i; + } else { + pref = prefix + "." + i; + } + } + flattenObject(o[i], pref, result, keepNull); + } + return result; + } + return result; +} + +const flattenedEnglish = flattenObject(englishRaw); + +fs.writeFileSync("./copy.json", JSON.stringify(flattenedEnglish, null, 2), "utf-8"); diff --git a/modules/desktop/scripts/update-translations.cjs b/modules/desktop/scripts/update-translations.cjs new file mode 100644 index 0000000..5facb14 --- /dev/null +++ b/modules/desktop/scripts/update-translations.cjs @@ -0,0 +1,39 @@ +const otaClient = require("@crowdin/ota-client"); +const _ = require("lodash"); +const fs = require("fs"); +const path = require("path"); + +// this read only hash is from crowdin +const hash = "cf849610ca66250f0954379ct4t"; + +const client = new otaClient.default(hash); + +async function main() { + console.log("getting latest translation!"); + const [languagesList, translationsRaw] = await Promise.all([ + client.getLanguageObjects(), + client.getStrings() + ]); + + const lang = languagesList.reduce((map, lang) => { + map[lang.id] = lang.name; + return map; + }, {}); + + const translations = languagesList.reduce((map, langRaw) => { + map[langRaw.id] = { + lang + }; + const translation = translationsRaw[langRaw.id]; + for (const k in translation) { + const key = [langRaw.id, k].join("."); + _.set(map, key, translation[k]); + } + return map; + }, {}); + + const translationsPath = path.join(__dirname, "../src/libs/translations/translations.json"); + await fs.writeFileSync(translationsPath, JSON.stringify(translations, null, 2), "utf-8"); +} + +main(); diff --git a/modules/desktop/src/components/essential-workshops/essential-workshops.svelte b/modules/desktop/src/components/essential-workshops/essential-workshops.svelte index 3121210..3ac28a4 100644 --- a/modules/desktop/src/components/essential-workshops/essential-workshops.svelte +++ b/modules/desktop/src/components/essential-workshops/essential-workshops.svelte @@ -1,5 +1,6 @@ ({ title: course.title, subTitle: course.sub_title, diff --git a/modules/desktop/src/components/footer-links/footer-links.svelte b/modules/desktop/src/components/footer-links/footer-links.svelte index 71cdc7a..d32a219 100644 --- a/modules/desktop/src/components/footer-links/footer-links.svelte +++ b/modules/desktop/src/components/footer-links/footer-links.svelte @@ -1,17 +1,18 @@