perf: merge all namespace of i18n resource in prod
Signed-off-by: Innei <i@innei.in>
This commit is contained in:
parent
304cb7f59f
commit
92bfce0f7e
|
|
@ -1,5 +1,5 @@
|
|||
import { readFileSync } from "node:fs"
|
||||
import { resolve } from "node:path"
|
||||
import fs, { readFileSync } from "node:fs"
|
||||
import path, { resolve } from "node:path"
|
||||
|
||||
import * as babel from "@babel/core"
|
||||
import generate from "@babel/generator"
|
||||
|
|
@ -14,6 +14,51 @@ import { getGitHash } from "../scripts/lib"
|
|||
|
||||
const pkg = JSON.parse(readFileSync("package.json", "utf8"))
|
||||
const isCI = process.env.CI === "true" || process.env.CI === "1"
|
||||
function localesPlugin(): Plugin {
|
||||
return {
|
||||
name: "locales-merge",
|
||||
enforce: "post",
|
||||
generateBundle(options, bundle) {
|
||||
const localesDir = path.resolve(__dirname, "locales")
|
||||
const namespaces = fs.readdirSync(localesDir)
|
||||
const languageResources = {}
|
||||
|
||||
namespaces.forEach((namespace) => {
|
||||
const namespacePath = path.join(localesDir, namespace)
|
||||
const files = fs.readdirSync(namespacePath).filter((file) => file.endsWith(".json"))
|
||||
|
||||
files.forEach((file) => {
|
||||
const lang = path.basename(file, ".json")
|
||||
const filePath = path.join(namespacePath, file)
|
||||
const content = JSON.parse(fs.readFileSync(filePath, "utf-8"))
|
||||
|
||||
if (!languageResources[lang]) {
|
||||
languageResources[lang] = {}
|
||||
}
|
||||
languageResources[lang][namespace] = content
|
||||
})
|
||||
})
|
||||
|
||||
Object.entries(languageResources).forEach(([lang, resources]) => {
|
||||
const fileName = `locales/${lang}.js`
|
||||
const content = `export default ${JSON.stringify(resources)};`
|
||||
|
||||
this.emitFile({
|
||||
type: "asset",
|
||||
fileName,
|
||||
source: content,
|
||||
})
|
||||
})
|
||||
|
||||
// Remove original JSON chunks
|
||||
Object.keys(bundle).forEach((key) => {
|
||||
if (key.startsWith("locales/") && key.endsWith(".json")) {
|
||||
delete bundle[key]
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const viteRenderBaseConfig = {
|
||||
resolve: {
|
||||
|
|
@ -52,6 +97,7 @@ export const viteRenderBaseConfig = {
|
|||
},
|
||||
}),
|
||||
|
||||
localesPlugin(),
|
||||
viteTwToRawString(),
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,16 +29,7 @@ if (import.meta.hot) {
|
|||
async ({ file, content }: { file: string; content: string }) => {
|
||||
const resources = JSON.parse(content)
|
||||
const i18next = jotaiStore.get(i18nAtom)
|
||||
// `file` is absolute path e.g. /Users/innei/git/follow/locales/en.json
|
||||
// Absolute path e.g. /Users/innei/git/follow/locales/<module-name>/en.json
|
||||
|
||||
// 1. parse root language
|
||||
// if (!file.includes("locales/namespaces")) {
|
||||
// const lang = file.split("/").pop()?.replace(".json", "")
|
||||
// if (!lang) return
|
||||
// i18next.addResourceBundle(lang, defaultNS, resources, true, true)
|
||||
// i18next.reloadResources(lang, defaultNS)
|
||||
// } else {
|
||||
const nsName = file.match(/locales\/(.+?)\//)?.[1]
|
||||
|
||||
if (!nsName) return
|
||||
|
|
@ -48,7 +39,6 @@ if (import.meta.hot) {
|
|||
|
||||
console.info("reload", lang, nsName)
|
||||
await i18next.reloadResources(lang, nsName)
|
||||
// }
|
||||
|
||||
import.meta.env.DEV && EventBus.dispatch("I18N_UPDATE", "")
|
||||
},
|
||||
|
|
|
|||
|
|
@ -42,37 +42,35 @@ const langChangedHandler = async (lang: string) => {
|
|||
|
||||
loadingLangLock.add(lang)
|
||||
|
||||
const nsGlobbyMap = import.meta.glob("@locales/*/*.json")
|
||||
if (import.meta.env.DEV) {
|
||||
const nsGlobbyMap = import.meta.glob("@locales/*/*.json")
|
||||
|
||||
// const rootGlobbyMap = import.meta.glob("@locales/*.json")
|
||||
// const rootResources = await rootGlobbyMap[`../../locales/${lang}.json`]()
|
||||
// .then((m: any) => m.default)
|
||||
// .catch(() => {
|
||||
// toast.error(`${t("common:tips.load-lng-error")}: ${lang}`)
|
||||
// })
|
||||
// i18next.addResourceBundle(lang, defaultNS, rootResources, true, true)
|
||||
const namespaces = Object.keys(defaultResources.en)
|
||||
|
||||
const namespaces = Object.keys(defaultResources.en)
|
||||
const res = await Promise.allSettled(
|
||||
namespaces.map(async (ns) => {
|
||||
const loader = nsGlobbyMap[`../../locales/${ns}/${lang}.json`]
|
||||
|
||||
const res = await Promise.allSettled(
|
||||
namespaces.map(async (ns) => {
|
||||
// if (ns === defaultNS) return
|
||||
if (!loader) return
|
||||
const nsResources = await loader().then((m: any) => m.default)
|
||||
|
||||
const loader = nsGlobbyMap[`../../locales/${ns}/${lang}.json`]
|
||||
i18next.addResourceBundle(lang, ns, nsResources, true, true)
|
||||
}),
|
||||
)
|
||||
|
||||
if (!loader) return
|
||||
const nsResources = await loader().then((m: any) => m.default)
|
||||
for (const r of res) {
|
||||
if (r.status === "rejected") {
|
||||
toast.error(`${t("common:tips.load-lng-error")}: ${lang}`)
|
||||
loadingLangLock.delete(lang)
|
||||
|
||||
i18next.addResourceBundle(lang, ns, nsResources, true, true)
|
||||
}),
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const res = await eval(`import('/locales/${lang}.js').then((res) => res?.default || res)`)
|
||||
|
||||
for (const r of res) {
|
||||
if (r.status === "rejected") {
|
||||
toast.error(`${t("common:tips.load-lng-error")}: ${lang}`)
|
||||
loadingLangLock.delete(lang)
|
||||
|
||||
return
|
||||
for (const namespace in res) {
|
||||
i18next.addResourceBundle(lang, namespace, res[namespace], true, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ export default ({ mode }) => {
|
|||
__debug_proxy: resolve(ROOT, "/__debug_proxy.html"),
|
||||
},
|
||||
output: {
|
||||
experimentalMinChunkSize: 500_000,
|
||||
// experimentalMinChunkSize: 500_000,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -97,7 +97,6 @@ export default ({ mode }) => {
|
|||
}),
|
||||
htmlPlugin(typedEnv),
|
||||
mkcert(),
|
||||
|
||||
devPrint(),
|
||||
|
||||
process.env.ANALYZER && analyzer(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue