mirror of
https://github.com/dec0dOS/zero-ui.git
synced 2025-07-05 20:41:43 -07:00
Merge pull request #188 from aruznieto/i18n
feat: i18n - dynamic import on build time
This commit is contained in:
commit
0fb92649df
9 changed files with 89 additions and 14 deletions
|
@ -63,5 +63,6 @@
|
||||||
"optional": "Optional",
|
"optional": "Optional",
|
||||||
"destination": "Destination",
|
"destination": "Destination",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
"password": "Password"
|
"password": "Password",
|
||||||
|
"languageName": "English"
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,5 +63,6 @@
|
||||||
"optional": "Opcional",
|
"optional": "Opcional",
|
||||||
"destination": "Destino",
|
"destination": "Destino",
|
||||||
"username": "Nombre de usuario",
|
"username": "Nombre de usuario",
|
||||||
"password": "Contraseña"
|
"password": "Contraseña",
|
||||||
|
"languageName": "Español"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,14 @@ import {
|
||||||
Accordion,
|
Accordion,
|
||||||
AccordionSummary,
|
AccordionSummary,
|
||||||
AccordionDetails,
|
AccordionDetails,
|
||||||
Checkbox,
|
|
||||||
Divider,
|
|
||||||
Grid,
|
Grid,
|
||||||
Typography,
|
Typography,
|
||||||
TextField,
|
|
||||||
Select,
|
Select,
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
|
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 { useTranslation } from "react-i18next";
|
||||||
|
import localesList from "generated/localesList.json";
|
||||||
|
|
||||||
function Settings() {
|
function Settings() {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
@ -31,8 +26,11 @@ function Settings() {
|
||||||
<AccordionDetails>
|
<AccordionDetails>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<Select native value={i18n.language} onChange={handleChange()}>
|
<Select native value={i18n.language} onChange={handleChange()}>
|
||||||
<option value={"en"}>English</option>
|
{localesList.map((locale) => (
|
||||||
<option value={"es-ES"}>Español</option>
|
<option key={locale.code} value={locale.code}>
|
||||||
|
{locale.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Grid>
|
</Grid>
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
|
|
10
frontend/src/generated/localesList.json
Normal file
10
frontend/src/generated/localesList.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"code": "en",
|
||||||
|
"name": "English"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "es-ES",
|
||||||
|
"name": "Español"
|
||||||
|
}
|
||||||
|
]
|
|
@ -3,7 +3,8 @@ import languageDetector from "i18next-browser-languagedetector";
|
||||||
import { initReactI18next } from "react-i18next";
|
import { initReactI18next } from "react-i18next";
|
||||||
import Backend from "i18next-http-backend";
|
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
|
i18n
|
||||||
.use(languageDetector)
|
.use(languageDetector)
|
||||||
|
@ -23,7 +24,7 @@ i18n
|
||||||
react: {
|
react: {
|
||||||
useSuspense: true,
|
useSuspense: true,
|
||||||
},
|
},
|
||||||
supportedLngs: ["en", "es-ES"],
|
supportedLngs,
|
||||||
backend: {
|
backend: {
|
||||||
loadPath: "/locales/{{lng}}/{{ns}}.json",
|
loadPath: "/locales/{{lng}}/{{ns}}.json",
|
||||||
},
|
},
|
||||||
|
|
10
frontend/src/utils/localesList.json
Normal file
10
frontend/src/utils/localesList.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"code": "en",
|
||||||
|
"name": "English"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "es-ES",
|
||||||
|
"name": "Español"
|
||||||
|
}
|
||||||
|
]
|
|
@ -5,7 +5,8 @@
|
||||||
"baseUrl": "src",
|
"baseUrl": "src",
|
||||||
"module": "NodeNext",
|
"module": "NodeNext",
|
||||||
"moduleResolution": "NodeNext",
|
"moduleResolution": "NodeNext",
|
||||||
"jsx": "preserve"
|
"jsx": "preserve",
|
||||||
|
"resolveJsonModule": true
|
||||||
},
|
},
|
||||||
"include": ["src"]
|
"include": ["src"]
|
||||||
}
|
}
|
||||||
|
|
51
frontend/vite-plugin-generate-locales.js
Normal file
51
frontend/vite-plugin-generate-locales.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
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 {
|
||||||
|
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.languageName || locale,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
code: locale,
|
||||||
|
name: locale,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save the array to a JSON file
|
||||||
|
const outputPath = path.resolve(
|
||||||
|
__dirname,
|
||||||
|
"src",
|
||||||
|
"generated",
|
||||||
|
"localesList.json"
|
||||||
|
);
|
||||||
|
fs.writeFileSync(outputPath, JSON.stringify(localesList, null, 2));
|
||||||
|
|
||||||
|
console.log(`Locales list saved to ${outputPath}`);
|
||||||
|
} else {
|
||||||
|
console.error("Locales directory not found.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import process from "node:process";
|
import process from "node:process";
|
||||||
import { defineConfig, searchForWorkspaceRoot } from "vite";
|
import { defineConfig, searchForWorkspaceRoot } from "vite";
|
||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
|
import GenerateLocalesPlugin from "./vite-plugin-generate-locales.js";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
base: "/app",
|
base: "/app",
|
||||||
|
@ -21,11 +22,12 @@ export default defineConfig({
|
||||||
components: "/src/components",
|
components: "/src/components",
|
||||||
utils: "/src/utils",
|
utils: "/src/utils",
|
||||||
external: "/src/external",
|
external: "/src/external",
|
||||||
|
generated: "/src/generated",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
outDir: "build",
|
outDir: "build",
|
||||||
chunkSizeWarningLimit: 1000,
|
chunkSizeWarningLimit: 1000,
|
||||||
},
|
},
|
||||||
plugins: [react()],
|
plugins: [react(), GenerateLocalesPlugin()],
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue