From df4efb3645f6e4e046b365b0fb8bf2b4ed75580a Mon Sep 17 00:00:00 2001 From: Christiaan Scheermeijer Date: Wed, 3 Apr 2024 17:38:55 +0200 Subject: [PATCH] feat(project): implement i18next-parser-workspaces cli --- ...elease-create-release-candidate-branch.yml | 2 +- i18next-parser.config.js | 28 ---------------- knip.config.ts | 1 + package.json | 5 ++- platforms/web/i18next-parser.config.js | 30 +++++++++++++++++ platforms/web/package.json | 18 +++++------ platforms/web/public/locales/en/common.json | 1 - platforms/web/public/locales/en/country.json | 2 +- platforms/web/public/locales/en/us_state.json | 2 +- platforms/web/public/locales/en/user.json | 18 ++--------- platforms/web/public/locales/es/common.json | 1 - platforms/web/public/locales/es/country.json | 2 +- platforms/web/public/locales/es/us_state.json | 2 +- platforms/web/public/locales/es/user.json | 18 ++--------- platforms/web/src/i18n/resources.ts | 4 +-- scripts/i18next/generate.js | 32 ------------------- yarn.lock | 25 +++++++++++++-- 17 files changed, 78 insertions(+), 113 deletions(-) delete mode 100644 i18next-parser.config.js create mode 100644 platforms/web/i18next-parser.config.js delete mode 100644 scripts/i18next/generate.js diff --git a/.github/workflows/release-create-release-candidate-branch.yml b/.github/workflows/release-create-release-candidate-branch.yml index 964292fdb..e5f084f44 100644 --- a/.github/workflows/release-create-release-candidate-branch.yml +++ b/.github/workflows/release-create-release-candidate-branch.yml @@ -23,7 +23,7 @@ jobs: git config --global user.email 'ott-release-script@jwplayer.com' git fetch origin ${{ github.ref_name }} git merge origin/${{ github.ref_name }} - yarn && yarn i18next + yarn && yarn workspace @jwp/ott-web run i18next env: GITHUB_TOKEN: ${{ secrets.ACTION_TOKEN }} diff --git a/i18next-parser.config.js b/i18next-parser.config.js deleted file mode 100644 index 5164c5eaf..000000000 --- a/i18next-parser.config.js +++ /dev/null @@ -1,28 +0,0 @@ -const fs = require('fs'); - -// @TODO: make it work with all packages and the web platform -const localesEntries = fs.readdirSync('./platforms/web/public/locales'); -const locales = localesEntries.filter((entry) => entry !== '..' && entry !== '.'); - -module.exports = { - contextSeparator: '_', - createOldCatalogs: true, - defaultNamespace: 'common', - defaultValue: '', - indentation: 2, - keepRemoved: false, - keySeparator: '.', - lexers: { - mjs: ['JavascriptLexer'], - js: ['JavascriptLexer'], - ts: ['JavascriptLexer'], - jsx: ['JsxLexer'], - tsx: ['JsxLexer'], - default: ['JavascriptLexer'], - }, - lineEnding: 'auto', - locales, - namespaceSeparator: ':', - output: 'platforms/web/public/locales/$LOCALE/$NAMESPACE.json', - sort: true, -}; diff --git a/knip.config.ts b/knip.config.ts index 285d4b3ee..9faf68d30 100644 --- a/knip.config.ts +++ b/knip.config.ts @@ -39,6 +39,7 @@ const config: KnipConfig = { 'babel-plugin-transform-typescript-metadata', // Used to build with decorators for ioc resolution 'core-js', // Conditionally imported at build time 'eslint-plugin-codeceptjs', // Used by apps/web/test-e2e/.eslintrc.cjs + 'i18next-parser', 'luxon', // Used in tests 'playwright', // Used in test configs 'sharp', // Requirement for @vite-pwa/assets-generator diff --git a/package.json b/package.json index 4fb840f26..c35953a12 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,8 @@ "format:eslint": "eslint \"{**/*,*}.{js,ts,jsx,tsx}\" --fix", "format:prettier": "prettier --write \"{**/*,*}.{js,ts,jsx,tsx}\"", "format:stylelint": "stylelint --fix '**/*.{css,scss}'", - "i18next": "i18next 'platforms/*/src/**/*.{ts,tsx}' 'packages/*/src/**/*.{ts,tsx}' && node ./scripts/i18next/generate.js", "i18next-diff": "npx ts-node ./scripts/i18next/diff-translations", - "i18next-update": "npx ts-node ./scripts/i18next/update-translations.ts && yarn i18next", + "i18next-update": "npx ts-node ./scripts/i18next/update-translations.ts && yarn workspace @jwp/ott-web run i18next", "lint": "run-p -c lint:*", "lint:eslint": "eslint \"{**/*,*}.{js,ts,jsx,tsx}\"", "lint:prettier": "prettier --check \"{**/*,*}.{js,ts,jsx,tsx}\"", @@ -43,7 +42,7 @@ "csv-parse": "^5.4.0", "eslint": "^8.57.0", "husky": "^6.0.0", - "i18next-parser": "^8.0.0", + "i18next-parser-workspaces": "^0.2.0", "knip": "^5.0.3", "lint-staged": "^15.1.0", "npm-run-all": "^4.1.5", diff --git a/platforms/web/i18next-parser.config.js b/platforms/web/i18next-parser.config.js new file mode 100644 index 000000000..2f356ef4b --- /dev/null +++ b/platforms/web/i18next-parser.config.js @@ -0,0 +1,30 @@ +const { readdirSync } = require('fs'); +const { join } = require('path'); + +// i18next runs in the workspace root, so we need to make sure the locales path is correct +const localesPath = join(__dirname, '/public/locales'); +const localesEntries = readdirSync(localesPath, { withFileTypes: true }); +const locales = localesEntries.filter((entry) => entry.isDirectory()).map((entry) => entry.name); + +module.exports = { + contextSeparator: '_', + createOldCatalogs: true, + defaultNamespace: 'common', + defaultValue: '', + indentation: 2, + keepRemoved: false, + keySeparator: '.', + lexers: { + mjs: ['JavascriptLexer'], + js: ['JavascriptLexer'], + ts: ['JavascriptLexer'], + jsx: ['JsxLexer'], + tsx: ['JsxLexer'], + default: ['JavascriptLexer'], + }, + lineEnding: 'auto', + locales, + namespaceSeparator: ':', + output: join(localesPath, '$LOCALE/$NAMESPACE.json'), + sort: true, +}; diff --git a/platforms/web/package.json b/platforms/web/package.json index f689bf26d..a74c24e9f 100644 --- a/platforms/web/package.json +++ b/platforms/web/package.json @@ -14,6 +14,7 @@ "codecept:desktop": "cd test-e2e && rm -rf \"./output/desktop\" && codeceptjs run-workers --suites ${WORKER_COUNT:=8} --config ./codecept.desktop.cjs", "codecept:mobile": "cd test-e2e && rm -rf \"./output/mobile\" && codeceptjs run-workers --suites ${WORKER_COUNT:=8} --config ./codecept.mobile.cjs", "generate-pwa-assets": "pwa-assets-generator", + "i18next": "i18next-workspaces parse ./ && i18next-workspaces namespaces ./ src/i18n/resources.ts", "lint:ts": "tsc --pretty --noEmit -p ./ && tsc --pretty --noEmit -p ./test-e2e", "serve-report:desktop": "cd test-e2e && allure serve \"./output/desktop\"", "serve-report:mobile": "cd test-e2e && allure serve \"./output/mobile\"", @@ -26,6 +27,11 @@ }, "dependencies": { "@codeceptjs/allure-legacy": "^1.0.2", + "@jwp/ott-common": "*", + "@jwp/ott-hooks-react": "*", + "@jwp/ott-testing": "*", + "@jwp/ott-theme": "*", + "@jwp/ott-ui-react": "*", "i18next": "^22.4.15", "i18next-browser-languagedetector": "^6.1.1", "i18next-http-backend": "^2.2.0", @@ -56,11 +62,14 @@ "babel-plugin-transform-typescript-metadata": "^0.3.2", "codeceptjs": "3.5.5", "core-js": "^3.37.0", + "eslint-config-jwp": "*", "eslint-plugin-codeceptjs": "^1.3.0", + "i18next-parser": "^8.13.0", "jsdom": "^22.1.0", "luxon": "^3.2.1", "playwright": "^1.38.1", "postcss": "^8.4.31", + "postcss-config-jwp": "*", "react-app-polyfill": "^3.0.0", "reflect-metadata": "^0.1.13", "sass": "^1.49.10", @@ -85,14 +94,5 @@ "gh-pages": "^3.2.3", "lighthouse": "^9.6.7", "sharp": "^0.33.2" - }, - "peerDependencies": { - "@jwp/ott-common": "*", - "@jwp/ott-hooks-react": "*", - "@jwp/ott-testing": "*", - "@jwp/ott-theme": "*", - "@jwp/ott-ui-react": "*", - "eslint-config-jwp": "*", - "postcss-config-jwp": "*" } } diff --git a/platforms/web/public/locales/en/common.json b/platforms/web/public/locales/en/common.json index acc115d5e..e63929b0e 100644 --- a/platforms/web/public/locales/en/common.json +++ b/platforms/web/public/locales/en/common.json @@ -18,7 +18,6 @@ "home": "Home", "live": "LIVE", "now": "Now", - "optional": "(Optional)", "play_item": "Play {{title}}", "scheduled": "Scheduled", "sign_in": "Sign in", diff --git a/platforms/web/public/locales/en/country.json b/platforms/web/public/locales/en/country.json index e10ac2742..f4a38ce6d 100644 --- a/platforms/web/public/locales/en/country.json +++ b/platforms/web/public/locales/en/country.json @@ -247,4 +247,4 @@ "ye": "Yemen", "zm": "Zambia", "zw": "Zimbabwe" -} \ No newline at end of file +} diff --git a/platforms/web/public/locales/en/us_state.json b/platforms/web/public/locales/en/us_state.json index 3fffc9328..e32fc4733 100644 --- a/platforms/web/public/locales/en/us_state.json +++ b/platforms/web/public/locales/en/us_state.json @@ -50,4 +50,4 @@ "wv": "West Virginia", "wi": "Wisconsin", "wy": "Wyoming" -} \ No newline at end of file +} diff --git a/platforms/web/public/locales/en/user.json b/platforms/web/public/locales/en/user.json index 694c142d6..3873713ad 100644 --- a/platforms/web/public/locales/en/user.json +++ b/platforms/web/public/locales/en/user.json @@ -4,7 +4,6 @@ "add_password": "Add password", "add_password_error": "Failed to proceed to the Add Password screen. Please try again.", "add_password_modal_text": "We sent instructions to {{email}} on how to add a password. If you don’t receive the email within a few minutes, check your spam folder or", - "add_profile": "Add profile", "cancel": "Cancel", "confirm_password": "Confirm password", "continue": "Continue", @@ -51,7 +50,6 @@ "export_data_title": "Export account data", "firstname": "First name", "lastname": "Last name", - "manage_profiles": "Manage profiles", "other_registration_details": "Other registration details", "password": "Password", "proceed_to_adding_a_password": "Proceed to adding a password", @@ -62,8 +60,7 @@ "terms_and_tracking": "Legal & Marketing", "update_consents": "Update consents", "update_success": "Your {{section}} has been successfully updated.", - "view_password": "View password", - "who_is_watching": "Who’s watching?" + "view_password": "View password" }, "favorites": { "clear": "Clear favorites", @@ -77,13 +74,11 @@ }, "nav": { "account": "Account", - "add_profile": "Add new profile", "favorites": "Favorites", "logout": "Log out", "payments": "Payments", "profile": "Profile", - "settings": "Settings", - "switch_profiles": "Switch profiles" + "settings": "Settings" }, "payment": { "access_granted": "access granted", @@ -132,23 +127,17 @@ "profile": { "adult": "Adult", "avatar": "Avatar", - "back_to_profiles": "Back to profiles", "content_rating": "Content rating", - "create_message": "Create your profile", - "created_message": "You successfully created your profile. Now go and watch some awesome content and assemble your own personal collection of favorites.", - "created_title": "You’ve created your profile", "delete": "Delete profile", "delete_confirmation": "Are you sure you want to delete your profile? You will lose all you watch history and settings connected to this profile.", "delete_description": "Permanently delete your profile along with all of your watch history and favorites.", "delete_main": "The main profile cannot be deleted because it’s linked to your account's watch history and favorites.", "description": "Profiles allow you to watch content and assemble your own personal collection of favorites.", - "done": "Done", "edit": "Edit profile", "form_error": "Something went wrong. Please try again later.", "info": "Profile info", "kids": "Kids", "name": "User name", - "no_one_watching": "There’s no one watching.", "validation": { "name": { "already_exists": "This profile name is already taken. Please choose another one.", @@ -157,7 +146,6 @@ "too_long": "Please limit your profile name to {{charactersCount}} characters or fewer.", "too_short": "Please enter at least {{charactersCount}} characters." } - }, - "watch_now": "Watch now" + } } } diff --git a/platforms/web/public/locales/es/common.json b/platforms/web/public/locales/es/common.json index e5baa3040..067c3b4d2 100644 --- a/platforms/web/public/locales/es/common.json +++ b/platforms/web/public/locales/es/common.json @@ -18,7 +18,6 @@ "home": "Inicio", "live": "EN VIVO", "now": "Ahora", - "optional": "(Opcional)", "play_item": "Reproducir {{title}}", "scheduled": "Programada", "sign_in": "Iniciar sesión", diff --git a/platforms/web/public/locales/es/country.json b/platforms/web/public/locales/es/country.json index 023006f8a..bbd009387 100644 --- a/platforms/web/public/locales/es/country.json +++ b/platforms/web/public/locales/es/country.json @@ -247,4 +247,4 @@ "ye": "Yemen", "zm": "Zambia", "zw": "Zimbabue" -} \ No newline at end of file +} diff --git a/platforms/web/public/locales/es/us_state.json b/platforms/web/public/locales/es/us_state.json index 82ef691e6..502b70511 100644 --- a/platforms/web/public/locales/es/us_state.json +++ b/platforms/web/public/locales/es/us_state.json @@ -50,4 +50,4 @@ "wv": "Virginia Occidental", "wi": "Wisconsin", "wy": "Wyoming" -} \ No newline at end of file +} diff --git a/platforms/web/public/locales/es/user.json b/platforms/web/public/locales/es/user.json index 66331fb65..1d21dee39 100644 --- a/platforms/web/public/locales/es/user.json +++ b/platforms/web/public/locales/es/user.json @@ -4,7 +4,6 @@ "add_password": "Agregar contraseña", "add_password_error": "No se pudo pasar a la pantalla Agregar contraseña. Inténtalo de nuevo.", "add_password_modal_text": "Enviamos instrucciones a {{email}} sobre cómo agregar una contraseña. Si no recibes el correo electrónico en unos minutos, revisa tu carpeta de spam o", - "add_profile": "Añadir perfil", "cancel": "Cancelar", "confirm_password": "Confirmar contraseña", "continue": "Continuar", @@ -51,7 +50,6 @@ "export_data_title": "Por favor revise su correo electrónico.", "firstname": "Nombre", "lastname": "Apellido", - "manage_profiles": "Administrar perfiles", "other_registration_details": "Otros detalles de registro", "password": "Contraseña", "proceed_to_adding_a_password": "Proceda a agregar una contraseña", @@ -62,8 +60,7 @@ "terms_and_tracking": "Jurídico y marketing", "update_consents": "Actualizar consentimientos", "update_success": "Tu {{section}} ha sido actualizado con éxito.", - "view_password": "Ver contraseña", - "who_is_watching": "¿Quién está mirando?" + "view_password": "Ver contraseña" }, "favorites": { "clear": "Borrar favoritos", @@ -77,13 +74,11 @@ }, "nav": { "account": "Cuenta", - "add_profile": "Añade un nuevo perfil", "favorites": "Favoritos", "logout": "Cerrar sesión", "payments": "Pagos", "profile": "Perfil", - "settings": "Ajustes", - "switch_profiles": "Cambiar de perfil" + "settings": "Ajustes" }, "payment": { "access_granted": "acceso concedido", @@ -133,23 +128,17 @@ "profile": { "adult": "Adultos", "avatar": "Avatar", - "back_to_profiles": "Volver a perfiles", "content_rating": "Puntuación del contenido", - "create_message": "Crea tu perfil", - "created_message": "Creaste exitosamente tu perfil. Ahora ve y mira contenido increíble y reúne tu propia colección personal de favoritos.", - "created_title": "Has creado tu perfil", "delete": "Eliminar perfil", "delete_confirmation": "¿Estás seguro que quieres eliminar tu perfil? Perderás todo tu historial y ajustes en este perfil.", "delete_description": "Borrar permentemente el perfil junto con el contenido de tu historial y favoritos.", "delete_main": "El perfil principal no puede ser borrado debido a que está ligado al historial de tu cuenta y tus favoritos.", "description": "Los perfiles te permiten ver el contenido y organizar tu colección de favoritos.", - "done": "Hecho", "edit": "Editar perfil", "form_error": "Algo salió mal. Intenta de nuevo más tarde", "info": "Información del perfil", "kids": "Niños", "name": "Nombre del usuario", - "no_one_watching": "No hay nadie mirando.", "validation": { "name": { "already_exists": "Este nombre de perfil ya está en uso. Por favor elije otro.", @@ -158,7 +147,6 @@ "too_long": "Por favor, limite el nombre de su perfil a {{charactersCount}} caracteres o menos.", "too_short": "Por favor introduzca al menos {{charactersCount}} caracteres." } - }, - "watch_now": "Ver ahora" + } } } diff --git a/platforms/web/src/i18n/resources.ts b/platforms/web/src/i18n/resources.ts index e0e6c1b90..30732b323 100644 --- a/platforms/web/src/i18n/resources.ts +++ b/platforms/web/src/i18n/resources.ts @@ -1,4 +1,4 @@ -// This file is generated, do not modify manually. -// Run `$ yarn i18next` to update this file +// This file is generated by i18next-parser-workspaces, do not modify manually. +// Run `$ npx i18next-workspaces` to update this file export const NAMESPACES = ['account', 'common', 'country', 'demo', 'epg', 'error', 'menu', 'search', 'us_state', 'user', 'video']; diff --git a/scripts/i18next/generate.js b/scripts/i18next/generate.js deleted file mode 100644 index 2b769977e..000000000 --- a/scripts/i18next/generate.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * This script generates all i18next resource entries. - */ -const fs = require('fs'); -const path = require('path'); - -const prettier = require('prettier'); - -const localesPath = './platforms/web/public/locales'; -const defaultLocale = 'en'; -const resourcesPath = './platforms/web/src/i18n/resources.ts'; - -// filter *_old namespaces generated by i18next-parser -const namespaces = fs - .readdirSync(path.join(localesPath, defaultLocale)) - .filter((namespace) => !/_old\.json/.test(namespace)) - .map((namespace) => namespace.replace('.json', '')); - -let configContents = `// This file is generated, do not modify manually. -// Run \`$ yarn i18next\` to update this file - -export const NAMESPACES = ${JSON.stringify(namespaces)};`; - -prettier.resolveConfig('./prettierrc').then((options) => { - const formatted = prettier.format(configContents, { ...options, filepath: resourcesPath }); - - fs.writeFileSync(resourcesPath, formatted, { encoding: 'utf-8' }); - - console.info(''); - console.info(`Generated i18next resources for all namespaces`); - console.info(''); -}); diff --git a/yarn.lock b/yarn.lock index e70e3d07d..339cba482 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4053,7 +4053,7 @@ colorette@^2.0.16, colorette@^2.0.20: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== -colors@1.4.0: +colors@1.4.0, colors@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== @@ -4075,6 +4075,11 @@ commander@11.1.0, commander@~11.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== +commander@^12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.0.0.tgz#b929db6df8546080adfd004ab215ed48cf6f2592" + integrity sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA== + commander@^2.18.0, commander@^2.19.0, commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -6175,7 +6180,18 @@ i18next-http-backend@^2.2.0: dependencies: cross-fetch "4.0.0" -i18next-parser@^8.0.0: +i18next-parser-workspaces@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/i18next-parser-workspaces/-/i18next-parser-workspaces-0.2.0.tgz#ada2d11e39d247f5396692e65f18aac5e9f3cdad" + integrity sha512-5e1Bhbqflm+FNL0zpvf8Vb1BDJ9aRSKFB7WIjcn1ioVl+W8OmEpSNEQxWBE7mcNR1jCPQnMO48XRNRkZByhTxQ== + dependencies: + colors "^1.4.0" + commander "^12.0.0" + vinyl-fs "^4.0.0" + optionalDependencies: + prettier "^3.2.5" + +i18next-parser@^8.13.0: version "8.13.0" resolved "https://registry.yarnpkg.com/i18next-parser/-/i18next-parser-8.13.0.tgz#3d0774f1659d691b451c105cc1eaf8c444e11740" integrity sha512-XU7resoeNcpJazh29OncQQUH6HsgCxk06RqBBDAmLHldafxopfCHY1vElyG/o3EY0Sn7XjelAmPTV0SgddJEww== @@ -8654,6 +8670,11 @@ prettier@^2.8.8: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== +prettier@^3.2.5: + version "3.2.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" + integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== + pretty-bytes@^5.3.0: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"