Skip to content

Commit 916ee74

Browse files
Soultermurphys7017
authored andcommitted
feat: enhance plugin page internationalization (AstrBotDevs#7998)
* feat: enhance plugin page internationalization - Updated PluginRoute to read initial context from JWT and set it in the bridge SDK. - Added methods to retrieve locale and plugin metadata for better i18n support. - Enhanced pluginI18n utility to resolve page-specific translations and added new functions for page titles and descriptions. - Modified PluginPagePage and PluginDetailPage to utilize new i18n features for dynamic content rendering. - Improved documentation for plugin page i18n structure and usage. - Added tests to verify the correct integration of i18n in plugin pages and context handling. * fix test
1 parent cd82b8d commit 916ee74

12 files changed

Lines changed: 1772 additions & 73 deletions

File tree

astrbot/dashboard/plugin_page_bridge.js

Lines changed: 91 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const SELF_ORIGIN = window.location.origin;
44
const pendingRequests = new Map();
55
const sseHandlers = new Map();
6+
const contextHandlers = new Set();
67
let requestCounter = 0;
78
let subscriptionCounter = 0;
89
let context = null;
@@ -13,7 +14,11 @@
1314
});
1415

1516
function getTargetOrigin() {
16-
if (typeof parentOrigin === "string" && parentOrigin && parentOrigin !== "null") {
17+
if (
18+
typeof parentOrigin === "string" &&
19+
parentOrigin &&
20+
parentOrigin !== "null"
21+
) {
1722
return parentOrigin;
1823
}
1924
if (SELF_ORIGIN !== "null") {
@@ -70,6 +75,63 @@
7075
}
7176
}
7277

78+
function getByPath(source, key) {
79+
if (!source || typeof source !== "object" || !key) {
80+
return undefined;
81+
}
82+
83+
return String(key)
84+
.split(".")
85+
.reduce((current, part) => {
86+
if (!current || typeof current !== "object" || !(part in current)) {
87+
return undefined;
88+
}
89+
return current[part];
90+
}, source);
91+
}
92+
93+
function translate(key, fallback) {
94+
const locale = context?.locale;
95+
const messages = context?.i18n;
96+
const locales = [locale, "zh-CN", "en-US"].filter(Boolean);
97+
let value;
98+
for (const candidateLocale of locales) {
99+
value = getByPath(messages?.[candidateLocale], key);
100+
if (value !== undefined && value !== null) {
101+
break;
102+
}
103+
}
104+
if (value === undefined || value === null) {
105+
return fallback || "";
106+
}
107+
return typeof value === "string" ? value : String(value);
108+
}
109+
110+
function notifyContextHandlers() {
111+
contextHandlers.forEach((handler) => {
112+
try {
113+
handler(context);
114+
} catch (error) {
115+
console.error("AstrBotPluginPage context handler failed:", error);
116+
}
117+
});
118+
}
119+
120+
function applyContext(nextContext) {
121+
if (!nextContext || typeof nextContext !== "object") {
122+
return;
123+
}
124+
context = {
125+
...(context || {}),
126+
...nextContext,
127+
};
128+
if (resolveReady) {
129+
resolveReady(context);
130+
resolveReady = null;
131+
}
132+
notifyContextHandlers();
133+
}
134+
73135
window.addEventListener("message", (event) => {
74136
if (event.source !== window.parent) {
75137
return;
@@ -87,11 +149,7 @@
87149
}
88150

89151
if (message.kind === "context") {
90-
context = message.context || null;
91-
if (resolveReady) {
92-
resolveReady(context);
93-
resolveReady = null;
94-
}
152+
applyContext(message.context);
95153
return;
96154
}
97155

@@ -104,7 +162,9 @@
104162
if (message.ok) {
105163
pending.resolve(message.data);
106164
} else {
107-
pending.reject(new Error(message.error || "Plugin bridge request failed."));
165+
pending.reject(
166+
new Error(message.error || "Plugin bridge request failed."),
167+
);
108168
}
109169
return;
110170
}
@@ -139,6 +199,30 @@
139199
getContext() {
140200
return context;
141201
},
202+
getLocale() {
203+
return context?.locale || "zh-CN";
204+
},
205+
getI18n() {
206+
return context?.i18n || {};
207+
},
208+
t(key, fallback) {
209+
return translate(key, fallback);
210+
},
211+
onContext(handler) {
212+
if (typeof handler !== "function") {
213+
return () => {};
214+
}
215+
contextHandlers.add(handler);
216+
if (context) {
217+
handler(context);
218+
}
219+
return () => {
220+
contextHandlers.delete(handler);
221+
};
222+
},
223+
__setInitialContext(nextContext) {
224+
applyContext(nextContext);
225+
},
142226
apiGet(endpoint, params) {
143227
return makeRequest("api:get", { endpoint, params });
144228
},

0 commit comments

Comments
 (0)