@nocobase/portal-template-default 1.0.12 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/package.json +1 -1
  2. package/scripts/build-html.mjs +14 -0
  3. package/src/extensions/nocobase-auth-cas/README.md +6 -0
  4. package/src/extensions/nocobase-auth-cas/cas-sign-in-button.tsx +41 -0
  5. package/src/extensions/nocobase-auth-cas/demo.tsx +20 -0
  6. package/src/extensions/nocobase-auth-cas/extension.tsx +48 -0
  7. package/src/extensions/nocobase-auth-cas/index.ts +1 -0
  8. package/src/extensions/nocobase-auth-cas/use-cas-sign-in.ts +31 -0
  9. package/src/extensions/nocobase-auth-dingtalk/README.md +7 -0
  10. package/src/extensions/nocobase-auth-dingtalk/auto-login-provider.tsx +185 -0
  11. package/src/extensions/nocobase-auth-dingtalk/demo.tsx +23 -0
  12. package/src/extensions/nocobase-auth-dingtalk/dingtalk-sign-in-button.tsx +45 -0
  13. package/src/extensions/nocobase-auth-dingtalk/extension.tsx +53 -0
  14. package/src/extensions/nocobase-auth-dingtalk/index.ts +4 -0
  15. package/src/extensions/nocobase-auth-dingtalk/use-dingtalk-sign-in.ts +66 -0
  16. package/src/extensions/nocobase-auth-ldap/README.md +6 -0
  17. package/src/extensions/nocobase-auth-ldap/demo.tsx +21 -0
  18. package/src/extensions/nocobase-auth-ldap/extension.tsx +48 -0
  19. package/src/extensions/nocobase-auth-ldap/index.ts +1 -0
  20. package/src/extensions/nocobase-auth-ldap/ldap-sign-in-form.tsx +69 -0
  21. package/src/extensions/nocobase-auth-ldap/use-ldap-sign-in.ts +5 -0
  22. package/src/extensions/nocobase-auth-oidc/README.md +11 -0
  23. package/src/extensions/nocobase-auth-oidc/auto-redirect-provider.tsx +13 -0
  24. package/src/extensions/nocobase-auth-oidc/demo.tsx +20 -0
  25. package/src/extensions/nocobase-auth-oidc/extension.tsx +51 -0
  26. package/src/extensions/nocobase-auth-oidc/index.ts +1 -0
  27. package/src/extensions/nocobase-auth-oidc/oidc-sign-in-button.tsx +44 -0
  28. package/src/extensions/nocobase-auth-oidc/use-oidc-sign-in.ts +60 -0
  29. package/src/extensions/nocobase-auth-saml/README.md +6 -0
  30. package/src/extensions/nocobase-auth-saml/auto-redirect-provider.tsx +13 -0
  31. package/src/extensions/nocobase-auth-saml/demo.tsx +20 -0
  32. package/src/extensions/nocobase-auth-saml/extension.tsx +51 -0
  33. package/src/extensions/nocobase-auth-saml/index.ts +1 -0
  34. package/src/extensions/nocobase-auth-saml/saml-sign-in-button.tsx +43 -0
  35. package/src/extensions/nocobase-auth-saml/use-saml-sign-in.ts +53 -0
  36. package/src/extensions/nocobase-auth-sms/README.md +7 -0
  37. package/src/extensions/nocobase-auth-sms/demo.tsx +25 -0
  38. package/src/extensions/nocobase-auth-sms/extension.tsx +48 -0
  39. package/src/extensions/nocobase-auth-sms/index.ts +1 -0
  40. package/src/extensions/nocobase-auth-sms/sms-sign-in-form.tsx +107 -0
  41. package/src/extensions/nocobase-auth-sms/use-sms-sign-in.ts +88 -0
  42. package/src/extensions/nocobase-auth-wecom/README.md +6 -0
  43. package/src/extensions/nocobase-auth-wecom/auto-login-provider.tsx +21 -0
  44. package/src/extensions/nocobase-auth-wecom/demo.tsx +23 -0
  45. package/src/extensions/nocobase-auth-wecom/extension.tsx +51 -0
  46. package/src/extensions/nocobase-auth-wecom/index.ts +1 -0
  47. package/src/extensions/nocobase-auth-wecom/use-wecom-sign-in.ts +64 -0
  48. package/src/extensions/nocobase-auth-wecom/wecom-sign-in-button.tsx +70 -0
  49. package/src/extensions/nocobase-i18n/README.md +44 -0
  50. package/src/extensions/nocobase-i18n/components/index.ts +1 -0
  51. package/src/extensions/nocobase-i18n/components/language-switcher.tsx +138 -0
  52. package/src/extensions/nocobase-i18n/demo/index.tsx +209 -0
  53. package/src/extensions/nocobase-i18n/demo/prompt-generator.tsx +132 -0
  54. package/src/extensions/nocobase-i18n/extension.tsx +48 -0
  55. package/src/extensions/nocobase-i18n/index.ts +7 -0
  56. package/src/extensions/nocobase-i18n/locales/en-US.ts +39 -0
  57. package/src/extensions/nocobase-i18n/locales/index.ts +8 -0
  58. package/src/extensions/nocobase-i18n/locales/zh-CN.ts +35 -0
  59. package/src/extensions/nocobase-i18n/provider.tsx +44 -0
  60. package/src/extensions/nocobase-i18n/server-resources.ts +166 -0
  61. package/src/extensions/nocobase-i18n/tests/i18n-regression.mjs +51 -0
@@ -0,0 +1,166 @@
1
+ import { nocobaseClient } from "@/lib/nocobase/client";
2
+ import {
3
+ type LocaleSystemSettings,
4
+ applyDocumentLocale,
5
+ getCurrentLocale,
6
+ i18n,
7
+ registerLocale,
8
+ setEnabledLocales,
9
+ } from "@/providers/i18n";
10
+
11
+ type ServerLanguagePayload = {
12
+ lang?: string;
13
+ resources?: Record<string, Record<string, string>>;
14
+ };
15
+
16
+ const serverResourceNamespaces = new Set(["lm-collections"]);
17
+ const loadedServerResourceNamespaces = new Set<string>();
18
+ const namespaceLoadPromises = new Map<string, Promise<void>>();
19
+ let cachedServerResources: ServerLanguagePayload["resources"] = {};
20
+ let serverResourcesPromise: Promise<void> | undefined;
21
+ let bootstrapStarted = false;
22
+ let bootstrapComplete = false;
23
+
24
+ function mergeNamespace(namespace: string, locale?: string) {
25
+ const resource = cachedServerResources?.[namespace];
26
+ if (!locale || !resource) return false;
27
+ i18n.addResourceBundle(locale, namespace, resource, true, false);
28
+ loadedServerResourceNamespaces.add(namespace);
29
+ return true;
30
+ }
31
+
32
+ async function requestServerResources(
33
+ namespaces: string[],
34
+ requestedLocale?: string
35
+ ) {
36
+ const payload = await nocobaseClient.action<ServerLanguagePayload>(
37
+ "app",
38
+ "getLang",
39
+ {
40
+ method: "GET",
41
+ query: {
42
+ ...(requestedLocale ? { locale: requestedLocale } : {}),
43
+ ...(namespaces.length ? { ns: namespaces.join(",") } : {}),
44
+ },
45
+ includeRole: false,
46
+ withAclMeta: false,
47
+ }
48
+ );
49
+
50
+ cachedServerResources = {
51
+ ...cachedServerResources,
52
+ ...payload.resources,
53
+ };
54
+ for (const namespace of namespaces) {
55
+ mergeNamespace(namespace, payload.lang);
56
+ loadedServerResourceNamespaces.add(namespace);
57
+ }
58
+
59
+ return payload;
60
+ }
61
+
62
+ async function ensureServerResourceNamespaces(namespaces: string[]) {
63
+ const pending: Promise<void>[] = [];
64
+ const missing: string[] = [];
65
+
66
+ for (const namespace of namespaces) {
67
+ if (loadedServerResourceNamespaces.has(namespace)) continue;
68
+ if (mergeNamespace(namespace, getCurrentLocale())) continue;
69
+ const existing = namespaceLoadPromises.get(namespace);
70
+ if (existing) pending.push(existing);
71
+ else missing.push(namespace);
72
+ }
73
+
74
+ if (missing.length) {
75
+ const request = requestServerResources(
76
+ missing,
77
+ nocobaseClient.getStoredLocale() ?? getCurrentLocale()
78
+ ).then(() => undefined);
79
+ for (const namespace of missing) {
80
+ namespaceLoadPromises.set(namespace, request);
81
+ }
82
+ const cleanup = () => {
83
+ for (const namespace of missing) {
84
+ if (namespaceLoadPromises.get(namespace) === request) {
85
+ namespaceLoadPromises.delete(namespace);
86
+ }
87
+ }
88
+ };
89
+ void request.then(cleanup, cleanup);
90
+ pending.push(request);
91
+ }
92
+
93
+ await Promise.all(pending);
94
+ }
95
+
96
+ export function registerServerResourceNamespace(namespace: string) {
97
+ if (!namespace) return;
98
+ serverResourceNamespaces.add(namespace);
99
+
100
+ if (
101
+ mergeNamespace(namespace, getCurrentLocale()) ||
102
+ !bootstrapStarted ||
103
+ !bootstrapComplete
104
+ ) {
105
+ return;
106
+ }
107
+
108
+ void ensureServerResourceNamespaces([namespace]).catch((error) => {
109
+ console.warn(
110
+ `Unable to load NocoBase locale namespace ${namespace}`,
111
+ error
112
+ );
113
+ });
114
+ }
115
+
116
+ export function getServerResourceNamespaces() {
117
+ return [...serverResourceNamespaces];
118
+ }
119
+
120
+ export function loadServerLocaleResources(settings?: LocaleSystemSettings) {
121
+ if (serverResourcesPromise) return serverResourcesPromise;
122
+
123
+ bootstrapStarted = true;
124
+ const requestedLocale = nocobaseClient.getStoredLocale();
125
+ const initialNamespaces = [...serverResourceNamespaces];
126
+ const configuredLocales = Array.isArray(settings?.enabledLanguages)
127
+ ? settings.enabledLanguages
128
+ : [];
129
+ if (configuredLocales.length) setEnabledLocales(configuredLocales);
130
+ const languagePromise = requestServerResources(
131
+ initialNamespaces,
132
+ requestedLocale
133
+ );
134
+
135
+ serverResourcesPromise = languagePromise
136
+ .then(async (payload) => {
137
+ const serverLocale = payload.lang;
138
+
139
+ if (!configuredLocales.length && serverLocale) {
140
+ setEnabledLocales([serverLocale]);
141
+ }
142
+
143
+ if (serverLocale) {
144
+ registerLocale({ locale: serverLocale, label: serverLocale });
145
+ nocobaseClient.setLocale(serverLocale);
146
+ await i18n.changeLanguage(serverLocale);
147
+ applyDocumentLocale(serverLocale);
148
+ }
149
+
150
+ bootstrapComplete = true;
151
+ const lateNamespaces = [...serverResourceNamespaces].filter(
152
+ (namespace) => !loadedServerResourceNamespaces.has(namespace)
153
+ );
154
+ if (lateNamespaces.length) {
155
+ await ensureServerResourceNamespaces(lateNamespaces);
156
+ }
157
+ })
158
+ .catch((error) => {
159
+ bootstrapComplete = true;
160
+ if (!configuredLocales.length) setEnabledLocales([getCurrentLocale()]);
161
+ serverResourcesPromise = undefined;
162
+ throw error;
163
+ });
164
+
165
+ return serverResourcesPromise;
166
+ }
@@ -0,0 +1,51 @@
1
+ import assert from "node:assert/strict";
2
+ import { createServer } from "vite";
3
+
4
+ const server = await createServer({
5
+ appType: "custom",
6
+ logLevel: "silent",
7
+ server: { middlewareMode: true },
8
+ });
9
+
10
+ try {
11
+ await server.ssrLoadModule("/src/locales/index.ts");
12
+ const {
13
+ applySystemLocale,
14
+ getCurrentLocale,
15
+ i18n,
16
+ registerLocaleResources,
17
+ translate,
18
+ } = await server.ssrLoadModule("/src/providers/i18n/runtime.ts");
19
+ const { resolveTranslatableText } =
20
+ await server.ssrLoadModule("/src/lib/i18n.ts");
21
+
22
+ await i18n.changeLanguage("en-US");
23
+ assert.equal(translate("buttons.create", { ns: "starter" }, "Create"), "Create");
24
+
25
+ await i18n.changeLanguage("zh-CN");
26
+ assert.equal(translate("buttons.create", { ns: "starter" }, "Create"), "新建");
27
+ assert.equal(resolveTranslatableText('{{t("Admin")}}'), "管理员");
28
+ assert.equal(
29
+ resolveTranslatableText("Full permissions", { ns: "starter" }),
30
+ "全部权限"
31
+ );
32
+
33
+ registerLocaleResources("example-feature", {
34
+ "en-US": { title: "Example" },
35
+ "zh-CN": { title: "示例" },
36
+ });
37
+ assert.equal(
38
+ translate("title", { ns: "example-feature" }, "Example"),
39
+ "示例"
40
+ );
41
+
42
+ await applySystemLocale({
43
+ appLang: "en-US",
44
+ enabledLanguages: ["en-US", "zh-CN"],
45
+ });
46
+ assert.equal(getCurrentLocale(), "en-US");
47
+
48
+ console.log("NocoBase i18n regression tests passed");
49
+ } finally {
50
+ await server.close();
51
+ }