feat(admin-*,dashboard): i18n labels for menu item extensions (#13843)

* i18n menu item labels

* changeset

* changeset
This commit is contained in:
Leonardo Benini
2025-11-06 13:42:32 +01:00
committed by GitHub
parent 3095b63784
commit 3852efbcff
8 changed files with 104 additions and 9 deletions

View File

@@ -69,19 +69,22 @@ const expectedMenuItems = `
label: RouteConfig0.label,
icon: RouteConfig0.icon,
path: "/one",
nested: undefined
nested: undefined,
translationNs: undefined
},
{
label: RouteConfig1.label,
icon: undefined,
path: "/two",
nested: undefined
nested: undefined,
translationNs: undefined
},
{
label: RouteConfig2.label,
icon: RouteConfig2.icon,
path: "/three",
nested: "/products"
nested: "/products",
translationNs: undefined
}
]
`
@@ -137,4 +140,49 @@ describe("generateMenuItems", () => {
utils.normalizeString(expectedMenuItems)
)
})
it("should handle translationNs field", async () => {
const mockFileWithTranslation = `
import { defineRouteConfig } from "@medusajs/admin-sdk"
const Page = () => {
return <div>Custom Page</div>
}
export const config = defineRouteConfig({
label: "menuItems.customFeature",
translationNs: "my-plugin",
})
export default Page
`
const mockFiles = ["Users/user/medusa/src/admin/routes/custom/page.tsx"]
vi.mocked(utils.crawl).mockResolvedValue(mockFiles)
vi.mocked(fs.readFile).mockResolvedValue(mockFileWithTranslation)
const result = await generateMenuItems(
new Set(["Users/user/medusa/src/admin"])
)
expect(result.imports).toEqual([
`import { config as RouteConfig0 } from "Users/user/medusa/src/admin/routes/custom/page.tsx"`,
])
const expectedOutput = `
menuItems: [
{
label: RouteConfig0.label,
icon: undefined,
path: "/custom",
nested: undefined,
translationNs: RouteConfig0.translationNs
}
]
`
expect(utils.normalizeString(result.code)).toEqual(
utils.normalizeString(expectedOutput)
)
})
})

View File

@@ -28,6 +28,7 @@ type RouteConfig = {
label: boolean
icon: boolean
nested?: string
translationNs?: string
}
type MenuItem = {
@@ -35,6 +36,7 @@ type MenuItem = {
label: string
path: string
nested?: string
translationNs?: string
}
type MenuItemResult = {
@@ -64,12 +66,13 @@ function generateCode(results: MenuItemResult[]): string {
}
function formatMenuItem(route: MenuItem): string {
const { label, icon, path, nested } = route
const { label, icon, path, nested, translationNs } = route
return `{
label: ${label},
icon: ${icon || "undefined"},
path: "${path}",
nested: ${nested ? `"${nested}"` : "undefined"}
nested: ${nested ? `"${nested}"` : "undefined"},
translationNs: ${translationNs ? `${translationNs}` : "undefined"}
}`
}
@@ -130,6 +133,7 @@ function generateMenuItem(
icon: config.icon ? `${configName}.icon` : undefined,
path: getRoute(file),
nested: config.nested,
translationNs: config.translationNs ? `${configName}.translationNs` : undefined,
}
}
@@ -240,10 +244,22 @@ function processConfigProperties(
return null
}
const translationNs = properties.find(
(prop) =>
isObjectProperty(prop) && isIdentifier(prop.key, { name: "translationNs" })
) as ObjectProperty | undefined
let translationNsValue: string | undefined = undefined
if (isStringLiteral(translationNs?.value)) {
translationNsValue = translationNs.value.value
}
return {
label: hasLabel,
icon: hasProperty("icon"),
nested: nestedValue,
translationNs: translationNsValue,
}
}