feat(admin-*,dashboard): add dashboard i18n extensions (#13763)

* virtual i18n module

* changeset

* fallback ns

fallback to the default "translation" ns if the key isnt found. Allows to use a single "useTranslation("customNs")" hook for both custom and medusa-provided keys

* simplify merges

* optional for backward compat

* fix HMR

* fix generated deepMerge

* test
This commit is contained in:
Leonardo Benini
2025-10-23 21:16:43 +02:00
committed by GitHub
parent 012e30801e
commit 226984cf0f
25 changed files with 314 additions and 9 deletions

View File

@@ -3,12 +3,14 @@ import { rm, writeFile } from "node:fs/promises"
import path from "node:path"
import type * as Vite from "vite"
import { generateCustomFieldHashes } from "./custom-fields"
import { generateI18nHash } from "./i18n"
import { generateRouteHashes } from "./routes"
import { MedusaVitePlugin } from "./types"
import { AdminSubdirectory, isFileInAdminSubdirectory } from "./utils"
import {
generateVirtualDisplayModule,
generateVirtualFormModule,
generateVirtualI18nModule,
generateVirtualLinkModule,
generateVirtualMenuItemModule,
generateVirtualRouteModule,
@@ -84,6 +86,7 @@ export const medusaVitePlugin: MedusaVitePlugin = (options) => {
const menuItemModule = await generateVirtualMenuItemModule(sources, true)
const formModule = await generateVirtualFormModule(sources, true)
const displayModule = await generateVirtualDisplayModule(sources, true)
const i18nModule = await generateVirtualI18nModule(sources, true)
// Create the index.js content that re-exports everything
return `
@@ -93,13 +96,15 @@ export const medusaVitePlugin: MedusaVitePlugin = (options) => {
${menuItemModule.code}
${formModule.code}
${displayModule.code}
${i18nModule.code}
const plugin = {
widgetModule,
routeModule,
menuItemModule,
formModule,
displayModule
displayModule,
i18nModule
}
export default plugin
@@ -229,6 +234,11 @@ const loadConfigs: Record<string, ModuleConfig> = {
moduleGenerator: async (sources) => generateVirtualMenuItemModule(sources),
hashKey: vmod.virtual.menuItem,
},
[vmod.resolved.i18n]: {
hashGenerator: async (sources) => generateI18nHash(sources),
moduleGenerator: async (sources) => generateVirtualI18nModule(sources),
hashKey: vmod.virtual.i18n,
},
}
type WatcherConfig = {
@@ -292,4 +302,17 @@ const watcherConfigs: WatcherConfig[] = [
},
],
},
{
subdirectory: "i18n",
hashGenerator: async (sources) => ({
i18nHash: await generateI18nHash(sources),
}),
modules: [
{
virtualModule: vmod.virtual.i18n,
resolvedModule: vmod.resolved.i18n,
hashKey: "i18nHash",
},
],
},
]