From 69784959637f6a53458e15d9a42d48de751c72f3 Mon Sep 17 00:00:00 2001 From: Andres Date: Fri, 20 Oct 2023 11:10:45 +0200 Subject: [PATCH 1/7] feat: dynamic import on build time --- frontend/public/locales/en/common.json | 3 +- frontend/public/locales/es-ES/common.json | 3 +- frontend/src/components/Settings/Settings.jsx | 14 +++---- frontend/src/i18n.js | 5 ++- frontend/src/utils/localesList.json | 10 +++++ frontend/tsconfig.json | 3 +- generateLocalesList.js | 40 +++++++++++++++++++ package.json | 4 +- 8 files changed, 67 insertions(+), 15 deletions(-) create mode 100644 frontend/src/utils/localesList.json create mode 100644 generateLocalesList.js diff --git a/frontend/public/locales/en/common.json b/frontend/public/locales/en/common.json index 3dc0905..f23ee21 100644 --- a/frontend/public/locales/en/common.json +++ b/frontend/public/locales/en/common.json @@ -63,5 +63,6 @@ "optional": "Optional", "destination": "Destination", "username": "Username", - "password": "Password" + "password": "Password", + "yourLanguage": "English" } diff --git a/frontend/public/locales/es-ES/common.json b/frontend/public/locales/es-ES/common.json index f314e3c..2bf8ef6 100644 --- a/frontend/public/locales/es-ES/common.json +++ b/frontend/public/locales/es-ES/common.json @@ -63,5 +63,6 @@ "optional": "Opcional", "destination": "Destino", "username": "Nombre de usuario", - "password": "Contraseña" + "password": "Contraseña", + "yourLanguage": "Español" } diff --git a/frontend/src/components/Settings/Settings.jsx b/frontend/src/components/Settings/Settings.jsx index 0ee47aa..08774ad 100644 --- a/frontend/src/components/Settings/Settings.jsx +++ b/frontend/src/components/Settings/Settings.jsx @@ -2,19 +2,14 @@ import { Accordion, AccordionSummary, AccordionDetails, - Checkbox, - Divider, Grid, Typography, - TextField, Select, } from "@material-ui/core"; import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; -import API from "utils/API"; -import { parseValue, replaceValue, setValue } from "utils/ChangeHelper"; - import { useTranslation } from "react-i18next"; +import localesList from "../../utils/localesList.json"; function Settings() { const { t, i18n } = useTranslation(); @@ -31,8 +26,11 @@ function Settings() { diff --git a/frontend/src/i18n.js b/frontend/src/i18n.js index fd27dd5..8d5d959 100644 --- a/frontend/src/i18n.js +++ b/frontend/src/i18n.js @@ -3,7 +3,8 @@ import languageDetector from "i18next-browser-languagedetector"; import { initReactI18next } from "react-i18next"; import Backend from "i18next-http-backend"; -const userLanguage = window.navigator.language; +import localesList from "./utils/localesList.json"; +const supportedLngs = localesList.map((locale) => locale.code); i18n .use(languageDetector) @@ -23,7 +24,7 @@ i18n react: { useSuspense: true, }, - supportedLngs: ["en", "es-ES"], + supportedLngs, backend: { loadPath: "/locales/{{lng}}/{{ns}}.json", }, diff --git a/frontend/src/utils/localesList.json b/frontend/src/utils/localesList.json new file mode 100644 index 0000000..35f6fb1 --- /dev/null +++ b/frontend/src/utils/localesList.json @@ -0,0 +1,10 @@ +[ + { + "code": "en", + "name": "English" + }, + { + "code": "es-ES", + "name": "Español" + } +] diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 2c8bc1d..39c41ba 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -5,7 +5,8 @@ "baseUrl": "src", "module": "NodeNext", "moduleResolution": "NodeNext", - "jsx": "preserve" + "jsx": "preserve", + "resolveJsonModule": true }, "include": ["src"] } diff --git a/generateLocalesList.js b/generateLocalesList.js new file mode 100644 index 0000000..63a4fda --- /dev/null +++ b/generateLocalesList.js @@ -0,0 +1,40 @@ +const fs = require("fs"); +const path = require("path"); + +const localesDir = path.join(__dirname, "frontend", "public", "locales"); // Adjust the path if necessary + +if (fs.existsSync(localesDir)) { + const localesList = fs + .readdirSync(localesDir) + .filter((file) => { + return fs.statSync(path.join(localesDir, file)).isDirectory(); + }) + .map((locale) => { + const commonFilePath = path.join(localesDir, locale, "common.json"); + if (fs.existsSync(commonFilePath)) { + const commonFile = require(commonFilePath); + return { + code: locale, + name: commonFile.yourLanguage || locale, + }; + } + return { + code: locale, + name: locale, + }; + }); + + // Save the array to a JSON file + const outputPath = path.join( + __dirname, + "frontend", + "src", + "utils", + "localesList.json" + ); + fs.writeFileSync(outputPath, JSON.stringify(localesList, null, 2)); + + console.log(`Locales list saved to ${outputPath}`); +} else { + console.error("Locales directory not found."); +} diff --git a/package.json b/package.json index 679dc8a..d789026 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ "format": "yarn prettier", "format:fix": "yarn prettier --write .", "lint": "yarn workspaces foreach --all --parallel run lint", - "dev": "concurrently \"cd frontend && cross-env FAST_REFRESH=true yarn start\" \"cd backend && cross-env NODE_ENV=development ZU_DEFAULT_USERNAME=admin ZU_DEFAULT_PASSWORD=zero-ui nodemon ./bin/www --ignore data/db.json\"", - "build": "cd frontend && cross-env GENERATE_SOURCEMAP=false yarn build", + "dev": "concurrently \"node generateLocalesList.js && cd frontend && cross-env FAST_REFRESH=true yarn start\" \"cd backend && cross-env NODE_ENV=development ZU_DEFAULT_USERNAME=admin ZU_DEFAULT_PASSWORD=zero-ui nodemon ./bin/www --ignore data/db.json\"", + "build": "node generateLocalesList.js && cd frontend && cross-env GENERATE_SOURCEMAP=false yarn build", "prod": "cd backend && cross-env NODE_ENV=production ZU_SECURE_HEADERS=false yarn start", "release": "standard-version && git push --follow-tags origin main && git add CHANGELOG.md", "commit": "yarn git-cz" From 7db15c26abd38eb6a2571c11ab7203736fa6e666 Mon Sep 17 00:00:00 2001 From: Andres Date: Sat, 21 Oct 2023 07:32:15 +0200 Subject: [PATCH 2/7] feat: i18n - vite plugin --- frontend/vite-plugin-generate-locales.js.js | 48 +++++++++++++++++++++ frontend/vite.config.js | 3 +- generateLocalesList.js | 40 ----------------- 3 files changed, 50 insertions(+), 41 deletions(-) create mode 100644 frontend/vite-plugin-generate-locales.js.js delete mode 100644 generateLocalesList.js diff --git a/frontend/vite-plugin-generate-locales.js.js b/frontend/vite-plugin-generate-locales.js.js new file mode 100644 index 0000000..e03bee6 --- /dev/null +++ b/frontend/vite-plugin-generate-locales.js.js @@ -0,0 +1,48 @@ +import fs from "fs"; +import path from "path"; + +export default function GenerateLocalesPlugin() { + return { + name: "generate-locales", + buildStart() { + const localesDir = path.resolve(__dirname, "public", "locales"); + + if (fs.existsSync(localesDir)) { + const localesList = fs + .readdirSync(localesDir) + .filter((file) => { + return fs.statSync(path.join(localesDir, file)).isDirectory(); + }) + .map((locale) => { + const commonFilePath = path.join(localesDir, locale, "common.json"); + if (fs.existsSync(commonFilePath)) { + const commonFile = JSON.parse( + fs.readFileSync(commonFilePath, "utf-8") + ); + return { + code: locale, + name: commonFile.yourLanguage || locale, + }; + } + return { + code: locale, + name: locale, + }; + }); + + // Save the array to a JSON file + const outputPath = path.resolve( + __dirname, + "src", + "utils", + "localesList.json" + ); + fs.writeFileSync(outputPath, JSON.stringify(localesList, null, 2)); + + console.log(`Locales list saved to ${outputPath}`); + } else { + console.error("Locales directory not found."); + } + }, + }; +} diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 3709e65..a8265c1 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -1,6 +1,7 @@ import process from "node:process"; import { defineConfig, searchForWorkspaceRoot } from "vite"; import react from "@vitejs/plugin-react"; +import GenerateLocalesPlugin from "./vite-plugin-generate-locales.js"; export default defineConfig({ base: "/app", @@ -27,5 +28,5 @@ export default defineConfig({ outDir: "build", chunkSizeWarningLimit: 1000, }, - plugins: [react()], + plugins: [react(), GenerateLocalesPlugin()], }); diff --git a/generateLocalesList.js b/generateLocalesList.js deleted file mode 100644 index 63a4fda..0000000 --- a/generateLocalesList.js +++ /dev/null @@ -1,40 +0,0 @@ -const fs = require("fs"); -const path = require("path"); - -const localesDir = path.join(__dirname, "frontend", "public", "locales"); // Adjust the path if necessary - -if (fs.existsSync(localesDir)) { - const localesList = fs - .readdirSync(localesDir) - .filter((file) => { - return fs.statSync(path.join(localesDir, file)).isDirectory(); - }) - .map((locale) => { - const commonFilePath = path.join(localesDir, locale, "common.json"); - if (fs.existsSync(commonFilePath)) { - const commonFile = require(commonFilePath); - return { - code: locale, - name: commonFile.yourLanguage || locale, - }; - } - return { - code: locale, - name: locale, - }; - }); - - // Save the array to a JSON file - const outputPath = path.join( - __dirname, - "frontend", - "src", - "utils", - "localesList.json" - ); - fs.writeFileSync(outputPath, JSON.stringify(localesList, null, 2)); - - console.log(`Locales list saved to ${outputPath}`); -} else { - console.error("Locales directory not found."); -} From f5e257e9c8470bc717e4692ddcdd3dbd40e4d20c Mon Sep 17 00:00:00 2001 From: Andres Date: Sat, 21 Oct 2023 07:34:02 +0200 Subject: [PATCH 3/7] feat: i18n package.json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d789026..679dc8a 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ "format": "yarn prettier", "format:fix": "yarn prettier --write .", "lint": "yarn workspaces foreach --all --parallel run lint", - "dev": "concurrently \"node generateLocalesList.js && cd frontend && cross-env FAST_REFRESH=true yarn start\" \"cd backend && cross-env NODE_ENV=development ZU_DEFAULT_USERNAME=admin ZU_DEFAULT_PASSWORD=zero-ui nodemon ./bin/www --ignore data/db.json\"", - "build": "node generateLocalesList.js && cd frontend && cross-env GENERATE_SOURCEMAP=false yarn build", + "dev": "concurrently \"cd frontend && cross-env FAST_REFRESH=true yarn start\" \"cd backend && cross-env NODE_ENV=development ZU_DEFAULT_USERNAME=admin ZU_DEFAULT_PASSWORD=zero-ui nodemon ./bin/www --ignore data/db.json\"", + "build": "cd frontend && cross-env GENERATE_SOURCEMAP=false yarn build", "prod": "cd backend && cross-env NODE_ENV=production ZU_SECURE_HEADERS=false yarn start", "release": "standard-version && git push --follow-tags origin main && git add CHANGELOG.md", "commit": "yarn git-cz" From beec9d7d78c62998fffe5c83b6a7f115f71cda1a Mon Sep 17 00:00:00 2001 From: Andres Date: Sat, 21 Oct 2023 07:38:18 +0200 Subject: [PATCH 4/7] feat: i18n - yourLanguage - languageName --- frontend/public/locales/en/common.json | 2 +- frontend/public/locales/es-ES/common.json | 2 +- frontend/vite-plugin-generate-locales.js.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/public/locales/en/common.json b/frontend/public/locales/en/common.json index f23ee21..50471ea 100644 --- a/frontend/public/locales/en/common.json +++ b/frontend/public/locales/en/common.json @@ -64,5 +64,5 @@ "destination": "Destination", "username": "Username", "password": "Password", - "yourLanguage": "English" + "languageName": "English" } diff --git a/frontend/public/locales/es-ES/common.json b/frontend/public/locales/es-ES/common.json index 2bf8ef6..0592994 100644 --- a/frontend/public/locales/es-ES/common.json +++ b/frontend/public/locales/es-ES/common.json @@ -64,5 +64,5 @@ "destination": "Destino", "username": "Nombre de usuario", "password": "Contraseña", - "yourLanguage": "Español" + "languageName": "Español" } diff --git a/frontend/vite-plugin-generate-locales.js.js b/frontend/vite-plugin-generate-locales.js.js index e03bee6..7b8d3b7 100644 --- a/frontend/vite-plugin-generate-locales.js.js +++ b/frontend/vite-plugin-generate-locales.js.js @@ -21,7 +21,7 @@ export default function GenerateLocalesPlugin() { ); return { code: locale, - name: commonFile.yourLanguage || locale, + name: commonFile.languageName || locale, }; } return { From ba4e5f2001a9e40b675018b98c56126de2ff2def Mon Sep 17 00:00:00 2001 From: dec0dOS Date: Sat, 21 Oct 2023 14:48:53 +0100 Subject: [PATCH 5/7] fix: vite-plugin-generate-locales.js --- ...-generate-locales.js.js => vite-plugin-generate-locales.js} | 3 +++ 1 file changed, 3 insertions(+) rename frontend/{vite-plugin-generate-locales.js.js => vite-plugin-generate-locales.js} (93%) diff --git a/frontend/vite-plugin-generate-locales.js.js b/frontend/vite-plugin-generate-locales.js similarity index 93% rename from frontend/vite-plugin-generate-locales.js.js rename to frontend/vite-plugin-generate-locales.js index 7b8d3b7..27e4141 100644 --- a/frontend/vite-plugin-generate-locales.js.js +++ b/frontend/vite-plugin-generate-locales.js @@ -1,5 +1,8 @@ import fs from "fs"; import path from "path"; +import * as url from "url"; + +const __dirname = url.fileURLToPath(new URL(".", import.meta.url)); export default function GenerateLocalesPlugin() { return { From 5b1ad30e98abb58075796a5eb3cac9c535f5ecaa Mon Sep 17 00:00:00 2001 From: dec0dOS Date: Wed, 1 May 2024 14:05:58 +0100 Subject: [PATCH 6/7] chore: fix path to localesList --- frontend/src/components/Settings/Settings.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/Settings/Settings.jsx b/frontend/src/components/Settings/Settings.jsx index 08774ad..801ef1b 100644 --- a/frontend/src/components/Settings/Settings.jsx +++ b/frontend/src/components/Settings/Settings.jsx @@ -9,7 +9,7 @@ import { import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; import { useTranslation } from "react-i18next"; -import localesList from "../../utils/localesList.json"; +import localesList from "utils/localesList.json"; function Settings() { const { t, i18n } = useTranslation(); From d826cda2a0c6d3e128f7021cb2922b986b00ca53 Mon Sep 17 00:00:00 2001 From: dec0dOS Date: Wed, 1 May 2024 14:11:05 +0100 Subject: [PATCH 7/7] chore: move localesList to generated folder --- frontend/src/components/Settings/Settings.jsx | 2 +- frontend/src/generated/localesList.json | 10 ++++++++++ frontend/vite-plugin-generate-locales.js | 2 +- frontend/vite.config.js | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 frontend/src/generated/localesList.json diff --git a/frontend/src/components/Settings/Settings.jsx b/frontend/src/components/Settings/Settings.jsx index 801ef1b..a81a1d8 100644 --- a/frontend/src/components/Settings/Settings.jsx +++ b/frontend/src/components/Settings/Settings.jsx @@ -9,7 +9,7 @@ import { import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; import { useTranslation } from "react-i18next"; -import localesList from "utils/localesList.json"; +import localesList from "generated/localesList.json"; function Settings() { const { t, i18n } = useTranslation(); diff --git a/frontend/src/generated/localesList.json b/frontend/src/generated/localesList.json new file mode 100644 index 0000000..35f6fb1 --- /dev/null +++ b/frontend/src/generated/localesList.json @@ -0,0 +1,10 @@ +[ + { + "code": "en", + "name": "English" + }, + { + "code": "es-ES", + "name": "Español" + } +] diff --git a/frontend/vite-plugin-generate-locales.js b/frontend/vite-plugin-generate-locales.js index 27e4141..a2f4289 100644 --- a/frontend/vite-plugin-generate-locales.js +++ b/frontend/vite-plugin-generate-locales.js @@ -37,7 +37,7 @@ export default function GenerateLocalesPlugin() { const outputPath = path.resolve( __dirname, "src", - "utils", + "generated", "localesList.json" ); fs.writeFileSync(outputPath, JSON.stringify(localesList, null, 2)); diff --git a/frontend/vite.config.js b/frontend/vite.config.js index a8265c1..d7fcd87 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -22,6 +22,7 @@ export default defineConfig({ components: "/src/components", utils: "/src/utils", external: "/src/external", + generated: "/src/generated", }, }, build: {