create and use namespace-i18n-plugin.ts

This commit is contained in:
Adrian 2024-10-09 03:52:44 -04:00
parent 57a967890a
commit 7cb39bd539
3 changed files with 91 additions and 90 deletions

View File

@ -116,6 +116,8 @@ function i18nMoneyFormatter(amount: any): string {
return `@[MONEY]{${i18next.t("common:money", { amount })}}`;
}
const nsEn = [];
//#region Exports
/**
@ -166,95 +168,7 @@ export async function initI18n(): Promise<void> {
},
},
defaultNS: "menu",
ns: [
"ability",
"abilityTriggers",
"arenaFlyout",
"arenaTag",
"battle",
"battleScene",
"battleInfo",
"battleMessageUiHandler",
"battlePokemonForm",
"battlerTags",
"berry",
"bgmName",
"biome",
"challenges",
"commandUiHandler",
"common",
"achv",
"dialogue",
"battleSpecDialogue",
"miscDialogue",
"doubleBattleDialogue",
"egg",
"fightUiHandler",
"filterBar",
"gameMode",
"gameStatsUiHandler",
"growth",
"menu",
"menuUiHandler",
"modifier",
"modifierType",
"move",
"nature",
"pokeball",
"pokemon",
"pokemonForm",
"pokemonInfo",
"pokemonInfoContainer",
"pokemonSummary",
"saveSlotSelectUiHandler",
"settings",
"splashMessages",
"starterSelectUiHandler",
"statusEffect",
"terrain",
"titles",
"trainerClasses",
"trainerNames",
"tutorial",
"voucher",
"weather",
"partyUiHandler",
"modifierSelectUiHandler",
"moveTriggers",
"runHistory",
"mysteryEncounters/mysteriousChallengers",
"mysteryEncounters/mysteriousChest",
"mysteryEncounters/darkDeal",
"mysteryEncounters/fightOrFlight",
"mysteryEncounters/slumberingSnorlax",
"mysteryEncounters/trainingSession",
"mysteryEncounters/departmentStoreSale",
"mysteryEncounters/shadyVitaminDealer",
"mysteryEncounters/fieldTrip",
"mysteryEncounters/safariZone",
"mysteryEncounters/lostAtSea",
"mysteryEncounters/fieryFallout",
"mysteryEncounters/theStrongStuff",
"mysteryEncounters/thePokemonSalesman",
"mysteryEncounters/anOfferYouCantRefuse",
"mysteryEncounters/delibirdy",
"mysteryEncounters/absoluteAvarice",
"mysteryEncounters/aTrainersTest",
"mysteryEncounters/trashToTreasure",
"mysteryEncounters/berriesAbound",
"mysteryEncounters/clowningAround",
"mysteryEncounters/partTimer",
"mysteryEncounters/dancingLessons",
"mysteryEncounters/weirdDream",
"mysteryEncounters/theWinstrateChallenge",
"mysteryEncounters/teleportingHijinks",
"mysteryEncounters/bugTypeSuperfan",
"mysteryEncounters/funAndGames",
"mysteryEncounters/uncommonBreed",
"mysteryEncounters/globalTradeSystem",
"mysteryEncounters/theExpertPokemonBreeder",
"mysteryEncounterMessages",
],
ns: nsEn, // assign with namespaces-i18n-plugin.ts
detection: {
lookupLocalStorage: "prLang"
},

View File

@ -0,0 +1,85 @@
import { normalizePath, type Plugin as VitePlugin } from "vite";
import fs from "fs";
import path from "path";
function kebabCaseToCamelCase(str: string): string {
return str.split("-").map((text, index) => {
if (index > 0) {
return text.split("").map((char, i) => i === 0 ? char.toUpperCase() : char).join("");
}
return text;
}).join("");
}
function getNameSpaces(dir: string) {
const namespace: string[] = [];
const files = fs.readdirSync(dir);
for (const file of files) {
const filePath = path.join(dir, file);
const stat = fs.lstatSync(filePath);
if (stat.isDirectory()) {
const subnamespace = getNameSpaces(filePath);
for (let i = 0; i < subnamespace.length; i++) {
let ns = subnamespace[i];
if (kebabCaseToCamelCase(file).replace(".json", "").startsWith("mysteryEncounters")) {
ns = subnamespace[i].replace(/Dialogue$/, "");
}
namespace.push(`${kebabCaseToCamelCase(file).replace(".json", "")}/${ns}`);
}
} else if (path.extname(file) === ".json") {
namespace.push(kebabCaseToCamelCase(file).replace(".json", ""));
}
}
return namespace;
}
function isFileInsideDir(file, dir) {
const filePath = path.normalize(file);
const dirPath = path.normalize(dir);
return filePath.startsWith(dirPath);
}
export function LocaleNamespace(): VitePlugin {
const nsLocation = "./public/locales";
const nsEn = `${nsLocation}/en`; // Default namespace
let namespaces = getNameSpaces(nsEn);
// const nsEnRegex = new RegExp(`^${nsEn.replace(/\//g, "\\/")}.*\\.json$`);
const nsAbsolutePath = path.resolve(process.cwd(), nsLocation); // Convert to absolute path
return {
name: "namespaces-i18next",
buildStart() {
if (process.env.NODE_ENV === "production") {
console.log("Assign namespace to constant nsEn");
}
},
configureServer(server) {
const restartHandler = async (file, action: string) => {
if (isFileInsideDir(file, nsAbsolutePath) && file.endsWith(".json")) {
console.log(`\x1b[34m${normalizePath(file.replace(nsAbsolutePath, ""))}\x1b[0m ${action}, reloading page...`);
namespaces = await getNameSpaces(nsEn);
await server.moduleGraph.invalidateAll();
await server.ws.send({
type: "full-reload",
});
}
};
server.watcher.on("change", (file) => restartHandler(file, "updated"));
server.watcher.on("add", (file) => restartHandler(file, "added"));
server.watcher.on("unlink", (file) => restartHandler(file, "removed"));
},
transform: {
handler(code, id) {
if (id.endsWith("i18n.ts")) {
return code.replace("const nsEn = [];", `const nsEn = ${JSON.stringify(namespaces)};`);
}
return code;
},
},
};
}

View File

@ -1,11 +1,13 @@
import { defineConfig, loadEnv, Rollup, UserConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
import { minifyJsonPlugin } from "./src/plugins/vite/vite-minify-json-plugin";
import { LocaleNamespace } from "./src/plugins/vite/namespaces-i18n-plugin";
export const defaultConfig: UserConfig = {
plugins: [
tsconfigPaths(),
minifyJsonPlugin(["images", "battle-anims"], true)
minifyJsonPlugin(["images", "battle-anims"], true),
LocaleNamespace()
],
clearScreen: false,
appType: "mpa",