Files
agent-desk-ng/web/lib/notification-i18n.test.mjs

118 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import assert from "node:assert/strict"
import test from "node:test"
import ts from "typescript"
import { readFile } from "node:fs/promises"
import vm from "node:vm"
const messageBundles = {}
async function loadBundle(locale) {
if (!messageBundles[locale]) {
const source = await readFile(new URL(`../messages/${locale}.json`, import.meta.url), "utf8")
messageBundles[locale] = JSON.parse(source)
}
return messageBundles[locale]
}
function lookupMessage(bundle, key) {
return key.split(".").reduce((value, segment) => (value == null ? undefined : value[segment]), bundle)
}
function translateMessage(locale, key, values) {
const message = lookupMessage(messageBundles[locale], key)
if (typeof message !== "string") {
return key
}
if (!values) {
return message
}
return message.replace(/\{(\w+)\}/g, (match, name) => String(values[name] ?? match))
}
async function loadModule() {
await loadBundle("en-US")
await loadBundle("ru-RU")
const source = await readFile(new URL("./notification-i18n.ts", import.meta.url), "utf8")
const compiled = ts.transpileModule(source, {
compilerOptions: {
target: ts.ScriptTarget.ES2017,
module: ts.ModuleKind.CommonJS,
},
fileName: "notification-i18n.ts",
})
const sandbox = {
exports: {},
module: { exports: {} },
require: (id) => {
if (id === "@/i18n/config") {
return { DEFAULT_LOCALE: "zh-CN", normalizeLocale: normalizeLocaleStub }
}
if (id === "@/i18n/messages") {
return { translateMessage }
}
throw new Error(`unexpected import ${id}`)
},
}
sandbox.exports = sandbox.module.exports
vm.runInNewContext(compiled.outputText, sandbox)
return sandbox.module.exports
}
function normalizeLocaleStub(value) {
const key = String(value ?? "").trim().toLowerCase()
if (key === "zh-cn" || key === "zh_cn" || key === "zh") {
return "zh-CN"
}
if (key === "en-us" || key === "en_us" || key === "en") {
return "en-US"
}
if (key === "ru-ru" || key === "ru_ru" || key === "ru") {
return "ru-RU"
}
return "zh-CN"
}
const ticketAssignedNotification = {
id: 1,
recipientUserId: 2,
title: "工单指派提醒",
content: "工单 TK-100 已指派给你\nCannot sign in\n指派原因: urgent",
notificationType: "ticket_assigned",
bizType: "ticket",
bizId: 100,
actionUrl: "/dashboard/tickets?ticketId=100",
}
test("localizes realtime ticket assignment notification to English", async () => {
const { localizeNotificationItem } = await loadModule()
const result = localizeNotificationItem(ticketAssignedNotification, "en-US")
assert.equal(result.title, "Ticket assigned")
assert.equal(
result.content,
"Ticket TK-100 has been assigned to you.\nCannot sign in\nAssignment reason: urgent"
)
})
test("localizes realtime ticket assignment notification to Russian", async () => {
await loadBundle("ru-RU")
const { localizeNotificationItem } = await loadModule()
const result = localizeNotificationItem(ticketAssignedNotification, "ru-RU")
assert.equal(result.title, "Обращение назначено")
assert.equal(
result.content,
"Обращение TK-100 назначено на вас.\nCannot sign in\nПричина назначения: urgent"
)
})
test("leaves Chinese notifications untouched for the Chinese locale", async () => {
const { localizeNotificationItem } = await loadModule()
const result = localizeNotificationItem(ticketAssignedNotification, "zh-CN")
assert.equal(result.title, ticketAssignedNotification.title)
assert.equal(result.content, ticketAssignedNotification.content)
})