@saasicat/ui-vue 0.15.0 → 0.16.0
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.
- package/README.md +4 -2
- package/dist/{chunk-66BUSVC5.js → chunk-CRUUZMMN.js} +1 -1
- package/dist/{chunk-TY2WYKME.js → chunk-MGKJCVDU.js} +32 -5
- package/dist/{chunk-TBLXKSTR.js → chunk-TZ2NGQXK.js} +48 -15
- package/dist/client/index.cjs +50 -15
- package/dist/client/index.d.cts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +6 -2
- package/dist/index.cjs +74 -20
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +9 -3
- package/dist/{messages-BIYw32u1.d.ts → messages-DetB75lX.d.cts} +15 -3
- package/dist/{messages-BIYw32u1.d.cts → messages-DetB75lX.d.ts} +15 -3
- package/dist/quasar/index.cjs +66 -4
- package/dist/quasar/index.d.cts +2 -2
- package/dist/quasar/index.d.ts +2 -2
- package/dist/quasar/index.js +2 -2
- package/dist/{use-super-admin-i18n-CWNu_W3u.d.ts → use-super-admin-i18n-BPC-H9jz.d.ts} +30 -4
- package/dist/{use-super-admin-i18n-DL_qI1BY.d.cts → use-super-admin-i18n-DokHhkS_.d.cts} +30 -4
- package/package.json +2 -2
- package/src/client/i18n/locale.ts +15 -0
- package/src/client/i18n/messages/shell.ts +2 -0
- package/src/client/types.ts +51 -14
- package/src/components/LocaleSwitcher.vue +68 -0
- package/src/pages-standard/AdminLayout.vue +2 -0
- package/src/pages-standard/SuperAdminLoginPage.vue +9 -0
- package/src/pages-standard/SuperAdminSetupWizard.vue +7 -0
- package/src/vue/use-super-admin-i18n.ts +74 -8
|
@@ -8,16 +8,28 @@
|
|
|
8
8
|
// Without a provider the composables fall back to a shared German instance, so
|
|
9
9
|
// isolated mounts and unit tests need no setup.
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
computed,
|
|
13
|
+
inject,
|
|
14
|
+
isReadonly,
|
|
15
|
+
isRef,
|
|
16
|
+
ref,
|
|
17
|
+
watch,
|
|
18
|
+
type ComputedRef,
|
|
19
|
+
type InjectionKey,
|
|
20
|
+
type Ref,
|
|
21
|
+
} from 'vue';
|
|
12
22
|
|
|
13
23
|
import {
|
|
14
24
|
DEFAULT_SA_LOCALE,
|
|
15
25
|
SA_INTL_LOCALES,
|
|
26
|
+
isSaLocale,
|
|
16
27
|
resolveMessages,
|
|
17
28
|
type SaLocale,
|
|
18
29
|
type SaMessages,
|
|
19
30
|
type SaMessagesOverrides,
|
|
20
31
|
} from '../client/i18n/index.js';
|
|
32
|
+
import { defaultKvStore, type KvStore } from '../client/types.js';
|
|
21
33
|
|
|
22
34
|
export interface SuperAdminI18n {
|
|
23
35
|
/** Active UI locale — mutable; switching re-renders all catalog texts. */
|
|
@@ -26,18 +38,45 @@ export interface SuperAdminI18n {
|
|
|
26
38
|
messages: ComputedRef<SaMessages>;
|
|
27
39
|
/** BCP-47 tag for `Intl`/`toLocaleString` formatting in the active locale. */
|
|
28
40
|
intlLocale: ComputedRef<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the shell renders its language switcher. `false` when the app
|
|
43
|
+
* opted out or when `locale` cannot be written to — a switcher that cannot
|
|
44
|
+
* change anything is worse than none.
|
|
45
|
+
*/
|
|
46
|
+
switcherEnabled: boolean;
|
|
29
47
|
}
|
|
30
48
|
|
|
31
49
|
export interface SuperAdminI18nOptions {
|
|
32
50
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
51
|
+
* Starting UI locale, default `'de'` — the shell's switcher lets the user
|
|
52
|
+
* pick another one, and a stored pick outranks this. Pass a `Ref` when the
|
|
53
|
+
* app wants to keep control (e.g. a user-profile setting).
|
|
35
54
|
*/
|
|
36
55
|
locale?: SaLocale | Ref<SaLocale>;
|
|
37
56
|
/** Per-locale string overrides layered over the platform catalog. */
|
|
38
57
|
overrides?: Partial<Record<SaLocale, SaMessagesOverrides>>;
|
|
58
|
+
/**
|
|
59
|
+
* Remembers the locale picked in the header switcher across reloads,
|
|
60
|
+
* default `true`. Ignored when `locale` is a `Ref`: the app owns that value
|
|
61
|
+
* and persists it wherever it belongs (user profile, its own store).
|
|
62
|
+
*/
|
|
63
|
+
persist?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Storage adapter for `persist`. Defaults to `defaultKvStore()`. Pass a
|
|
66
|
+
* key-prefixing wrapper when several apps share one origin.
|
|
67
|
+
*/
|
|
68
|
+
storage?: KvStore;
|
|
69
|
+
/**
|
|
70
|
+
* Renders the language switcher in the shell chrome, default `true`. Set
|
|
71
|
+
* `false` for a deployment that ships one language. A readonly `locale`
|
|
72
|
+
* ref disables it on its own — no need to set this as well.
|
|
73
|
+
*/
|
|
74
|
+
switcher?: boolean;
|
|
39
75
|
}
|
|
40
76
|
|
|
77
|
+
/** `KvStore` key holding the locale the user picked in the switcher. */
|
|
78
|
+
export const SA_LOCALE_STORAGE_KEY = 'sa:locale';
|
|
79
|
+
|
|
41
80
|
// `Symbol.for` — see super-admin-context.ts: dist- and src-imported module
|
|
42
81
|
// instances must resolve to the same injection key.
|
|
43
82
|
export const SUPER_ADMIN_I18N_KEY: InjectionKey<SuperAdminI18n> = Symbol.for(
|
|
@@ -45,14 +84,38 @@ export const SUPER_ADMIN_I18N_KEY: InjectionKey<SuperAdminI18n> = Symbol.for(
|
|
|
45
84
|
);
|
|
46
85
|
|
|
47
86
|
export function createSuperAdminI18n(options: SuperAdminI18nOptions = {}): SuperAdminI18n {
|
|
48
|
-
const locale = isRef(options.locale)
|
|
49
|
-
? options.locale
|
|
50
|
-
: ref(options.locale ?? DEFAULT_SA_LOCALE);
|
|
87
|
+
const locale = isRef(options.locale) ? options.locale : createOwnedLocale(options);
|
|
51
88
|
const messages = computed(() =>
|
|
52
89
|
resolveMessages(locale.value, options.overrides?.[locale.value]),
|
|
53
90
|
);
|
|
54
91
|
const intlLocale = computed(() => SA_INTL_LOCALES[locale.value]);
|
|
55
|
-
|
|
92
|
+
// A readonly ref (typically a `computed` derived from a profile setting)
|
|
93
|
+
// silently swallows writes, so the switcher would be a dead control. The
|
|
94
|
+
// type system permits it — TypeScript ignores `readonly` when checking
|
|
95
|
+
// assignability — so the guard has to be a runtime one.
|
|
96
|
+
const writable = !isReadonly(locale);
|
|
97
|
+
return {
|
|
98
|
+
locale,
|
|
99
|
+
messages,
|
|
100
|
+
intlLocale,
|
|
101
|
+
switcherEnabled: (options.switcher ?? true) && writable,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Builds the locale ref the platform owns. A stored choice outranks the
|
|
107
|
+
* `locale` option, because that option is the app's default while the stored
|
|
108
|
+
* value is the user's explicit pick in the switcher.
|
|
109
|
+
*/
|
|
110
|
+
function createOwnedLocale(options: SuperAdminI18nOptions): Ref<SaLocale> {
|
|
111
|
+
if (options.persist === false) {
|
|
112
|
+
return ref(options.locale ?? DEFAULT_SA_LOCALE);
|
|
113
|
+
}
|
|
114
|
+
const storage = options.storage ?? defaultKvStore();
|
|
115
|
+
const stored = storage.get(SA_LOCALE_STORAGE_KEY);
|
|
116
|
+
const locale = ref(isSaLocale(stored) ? stored : (options.locale ?? DEFAULT_SA_LOCALE));
|
|
117
|
+
watch(locale, (next) => storage.set(SA_LOCALE_STORAGE_KEY, next));
|
|
118
|
+
return locale;
|
|
56
119
|
}
|
|
57
120
|
|
|
58
121
|
let fallbackI18n: SuperAdminI18n | null = null;
|
|
@@ -65,7 +128,10 @@ let fallbackI18n: SuperAdminI18n | null = null;
|
|
|
65
128
|
export function useSuperAdminI18n(): SuperAdminI18n {
|
|
66
129
|
const injected = inject(SUPER_ADMIN_I18N_KEY, null);
|
|
67
130
|
if (injected) return injected;
|
|
68
|
-
|
|
131
|
+
// Deliberately not persisted: this instance exists for mounts outside a
|
|
132
|
+
// shell, and a shared singleton that reads and writes real storage would
|
|
133
|
+
// make test outcomes depend on their order.
|
|
134
|
+
fallbackI18n ??= createSuperAdminI18n({ persist: false });
|
|
69
135
|
return fallbackI18n;
|
|
70
136
|
}
|
|
71
137
|
|