@saasicat/ui-vue 0.15.1 → 0.17.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 +13 -10
- package/dist/{messages-BIYw32u1.d.ts → catalog-C4Gv2_KM.d.cts} +126 -39
- package/dist/{messages-BIYw32u1.d.cts → catalog-C4Gv2_KM.d.ts} +126 -39
- package/dist/{chunk-TY2WYKME.js → chunk-247RJPU4.js} +38 -11
- package/dist/{chunk-TBLXKSTR.js → chunk-IZGFS5RS.js} +90 -21
- package/dist/{chunk-66BUSVC5.js → chunk-XPSD5HKG.js} +30 -4
- package/dist/client/index.cjs +122 -22
- package/dist/client/index.d.cts +51 -5
- package/dist/client/index.d.ts +51 -5
- package/dist/client/index.js +14 -2
- package/dist/index.cjs +152 -30
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +17 -3
- package/dist/quasar/index.cjs +110 -14
- 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-DL_qI1BY.d.cts → use-super-admin-i18n-BdPqeTHl.d.cts} +51 -5
- package/dist/{use-super-admin-i18n-CWNu_W3u.d.ts → use-super-admin-i18n-uteRCL9q.d.ts} +51 -5
- package/package.json +8 -3
- package/src/client/i18n/catalog.ts +120 -0
- package/src/client/i18n/currency.ts +7 -2
- package/src/client/i18n/define.ts +2 -2
- package/src/client/i18n/index.ts +1 -0
- package/src/client/i18n/locale.ts +52 -8
- package/src/client/i18n/messages/bundles.ts +2 -3
- package/src/client/i18n/messages/marketing.ts +2 -2
- package/src/client/i18n/messages/nav.ts +3 -3
- package/src/client/i18n/messages/shell.ts +2 -0
- package/src/client/i18n/messages.ts +7 -4
- package/src/client/index.ts +1 -0
- package/src/client/login-branding.ts +61 -0
- package/src/client/nav-builder.ts +33 -6
- package/src/client/types.ts +51 -14
- package/src/components/LocaleSwitcher.vue +77 -0
- package/src/components/bundle-editor/bundle-version-status.ts +16 -8
- package/src/pages-standard/AdminLayout.vue +9 -3
- package/src/pages-standard/SuperAdminLoginPage.vue +17 -9
- package/src/pages-standard/SuperAdminSetupWizard.vue +7 -0
- package/src/pages-standard/discovery-page/discovery-ui.ts +8 -8
- package/src/pages-standard/plan-versions/format.ts +2 -2
- package/src/vue/use-super-admin-i18n.ts +116 -19
package/README.md
CHANGED
|
@@ -15,12 +15,12 @@ The package is layered so that each entry only loads what it names.
|
|
|
15
15
|
Lower layers never import upward; ESLint (`no-restricted-imports`, repo
|
|
16
16
|
root config) enforces the boundaries in CI.
|
|
17
17
|
|
|
18
|
-
| Entry
|
|
19
|
-
|
|
|
20
|
-
| `@saasicat/ui-vue/client`
|
|
21
|
-
| `@saasicat/ui-vue` (main)
|
|
22
|
-
| `@saasicat/ui-vue/quasar`
|
|
23
|
-
| `@saasicat/ui-vue/pages-standard/*`, `/pages-tenant/*`, `/components/*` | SFC directories
|
|
18
|
+
| Entry | Source | May import | Contents |
|
|
19
|
+
| ----------------------------------------------------------------------- | -------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
20
|
+
| `@saasicat/ui-vue/client` | `src/client/` | `@saasicat/types` only | Framework-free core: `BootLoader`, `ManifestLoader` (ETag cache), nav builder, action registry, batch column fetcher, `HttpClient`/`KvStore` contract. Usable from any framework or plain Node/TypeScript. |
|
|
21
|
+
| `@saasicat/ui-vue` (main) | `src/vue/` (+ client re-exports) | Vue, `vue-router`, Pinia — **no Quasar** | Composables (`useTenants`, `usePlanEditor`, …), router guards, injection keys + shell contract, notify-port type, optional Pinia store factory. |
|
|
22
|
+
| `@saasicat/ui-vue/quasar` | `src/quasar/` | everything above + Quasar | `createSuperAdminApp()` bootstrap and the Quasar notify-port implementation. |
|
|
23
|
+
| `@saasicat/ui-vue/pages-standard/*`, `/pages-tenant/*`, `/components/*` | SFC directories | everything | The Quasar reference UI, shipped as raw `.vue` from `src/` (compiled by the consumer's Vite). |
|
|
24
24
|
|
|
25
25
|
Rules of thumb when contributing:
|
|
26
26
|
|
|
@@ -49,7 +49,7 @@ createSuperAdminApp({
|
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
Confirm dialogs inside the reference pages intentionally keep using Quasar's
|
|
52
|
-
`Dialog` — the pages
|
|
52
|
+
`Dialog` — the pages _are_ the Quasar layer.
|
|
53
53
|
|
|
54
54
|
## Usage
|
|
55
55
|
|
|
@@ -92,9 +92,12 @@ createSuperAdminApp({
|
|
|
92
92
|
});
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
Users switch languages themselves through the shell's `LocaleSwitcher` (header
|
|
96
|
+
and login page); the pick is remembered. Which languages an app offers is its
|
|
97
|
+
own call: `i18n.locales` narrows the set, `i18n.additionalLocales` adds
|
|
98
|
+
languages the platform does not ship, `i18n.overrides` replaces individual
|
|
99
|
+
strings, and `i18n.switcher: false` drops the control entirely. Components read
|
|
100
|
+
the catalog via `useSaMessages('<namespace>')` / `useSuperAdminI18n()`.
|
|
98
101
|
See [handbook §8.6](https://github.com/uelker70/saasicat/blob/main/docs/handbook.md#86-ui-language-i18n).
|
|
99
102
|
|
|
100
103
|
## Build
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdminManifest, TenantActionDef
|
|
1
|
+
import { StandardPageKey, AdminManifest, TenantActionDef } from '@saasicat/types';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Minimal abstraction over `fetch`. Consumers may pass their own
|
|
@@ -25,8 +25,11 @@ interface KvStore {
|
|
|
25
25
|
remove(key: string): void;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
* Returns a `KvStore` wrapper around `localStorage
|
|
29
|
-
* Tests may pass an in-memory stub.
|
|
28
|
+
* Returns a `KvStore` wrapper around `localStorage`, or a no-op store when the
|
|
29
|
+
* environment has none or refuses access. Tests may pass an in-memory stub.
|
|
30
|
+
*
|
|
31
|
+
* Every persistence built on this is a convenience — losing it must never take
|
|
32
|
+
* the app down, so no failure mode is allowed to escape.
|
|
30
33
|
*/
|
|
31
34
|
declare function defaultKvStore(): KvStore;
|
|
32
35
|
/**
|
|
@@ -35,11 +38,49 @@ declare function defaultKvStore(): KvStore;
|
|
|
35
38
|
*/
|
|
36
39
|
declare function defaultHttpClient(): HttpClient;
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
/** Locales the platform itself ships a catalog for. */
|
|
42
|
+
type SaBuiltinLocale = 'de' | 'en';
|
|
43
|
+
/**
|
|
44
|
+
* Any locale the shell can run in: the built-ins plus whatever an app adds via
|
|
45
|
+
* `i18n.additionalLocales`. The `string & {}` arm keeps autocompletion for the
|
|
46
|
+
* built-ins while leaving the set open.
|
|
47
|
+
*/
|
|
48
|
+
type SaLocale = SaBuiltinLocale | (string & {});
|
|
49
|
+
/** The locales the platform ships. Apps narrow or extend this, see `i18n`. */
|
|
50
|
+
declare const SA_LOCALES: readonly SaBuiltinLocale[];
|
|
51
|
+
declare const DEFAULT_SA_LOCALE: SaBuiltinLocale;
|
|
52
|
+
/** BCP-47 tags used for `Intl`/`toLocaleString` formatting per built-in locale. */
|
|
53
|
+
declare const SA_INTL_LOCALES: Record<SaBuiltinLocale, string>;
|
|
54
|
+
/**
|
|
55
|
+
* Names for the language switcher. Endonyms — a language is listed in its own
|
|
56
|
+
* language, so the entries stay readable no matter which locale is active and
|
|
57
|
+
* never need translating.
|
|
58
|
+
*/
|
|
59
|
+
declare const SA_LOCALE_LABELS: Record<SaBuiltinLocale, string>;
|
|
60
|
+
/** Narrows untrusted input to a locale the platform ships a catalog for. */
|
|
61
|
+
declare function isSaBuiltinLocale(value: unknown): value is SaBuiltinLocale;
|
|
62
|
+
/**
|
|
63
|
+
* The built-in catalog a locale reads from. Helper modules that index the raw
|
|
64
|
+
* catalogs (rather than the resolved one from `useSaMessages`) need this: a
|
|
65
|
+
* language an app added has no entry there, and indexing it would yield
|
|
66
|
+
* `undefined` and take the page down.
|
|
67
|
+
*
|
|
68
|
+
* Strings resolved this way stay in the fallback language for an app-supplied
|
|
69
|
+
* locale — migrating those helpers to the resolved catalog is tracked
|
|
70
|
+
* separately.
|
|
71
|
+
*/
|
|
72
|
+
declare function builtinLocaleOf(locale: SaLocale | undefined, fallback?: SaBuiltinLocale): SaBuiltinLocale;
|
|
73
|
+
|
|
74
|
+
type SaNavMessages = {
|
|
75
|
+
readonly pages: Record<StandardPageKey, string>;
|
|
76
|
+
readonly sections: {
|
|
77
|
+
readonly overview: string;
|
|
78
|
+
readonly catalog: string;
|
|
79
|
+
readonly customers: string;
|
|
80
|
+
readonly system: string;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
declare const navMessages: Record<SaBuiltinLocale, SaNavMessages>;
|
|
43
84
|
|
|
44
85
|
/** Consumer implementation; receives the action inputs as a generic object. */
|
|
45
86
|
type ActionHandler<TInput = unknown, TResult = unknown> = (input: TInput) => Promise<TResult>;
|
|
@@ -104,7 +145,7 @@ type PartialMessages<T> = {
|
|
|
104
145
|
* Couples the German reference catalog with its English translation. Missing
|
|
105
146
|
* or extra keys in the English object are compile errors.
|
|
106
147
|
*/
|
|
107
|
-
declare function defineMessages<T extends MessageTree>(de: T, en: TranslationOf<T>): Record<
|
|
148
|
+
declare function defineMessages<T extends MessageTree>(de: T, en: TranslationOf<T>): Record<SaBuiltinLocale, T>;
|
|
108
149
|
/**
|
|
109
150
|
* Recursively overlays `overrides` onto `base` without mutating either side.
|
|
110
151
|
* Only string leaves are replaced; keys not present in `base` are ignored —
|
|
@@ -112,7 +153,7 @@ declare function defineMessages<T extends MessageTree>(de: T, en: TranslationOf<
|
|
|
112
153
|
*/
|
|
113
154
|
declare function mergeMessages<T extends MessageTree>(base: T, overrides: PartialMessages<T> | undefined): T;
|
|
114
155
|
|
|
115
|
-
declare const auditMessages: Record<
|
|
156
|
+
declare const auditMessages: Record<SaBuiltinLocale, {
|
|
116
157
|
title: string;
|
|
117
158
|
subtitle: string;
|
|
118
159
|
filterButton: string;
|
|
@@ -132,7 +173,7 @@ declare const auditMessages: Record<SaLocale, {
|
|
|
132
173
|
};
|
|
133
174
|
}>;
|
|
134
175
|
|
|
135
|
-
declare const bundlesMessages: Record<
|
|
176
|
+
declare const bundlesMessages: Record<SaBuiltinLocale, {
|
|
136
177
|
fields: {
|
|
137
178
|
masterData: string;
|
|
138
179
|
label: string;
|
|
@@ -338,7 +379,7 @@ declare const bundlesMessages: Record<SaLocale, {
|
|
|
338
379
|
};
|
|
339
380
|
}>;
|
|
340
381
|
|
|
341
|
-
declare const commonMessages: Record<
|
|
382
|
+
declare const commonMessages: Record<SaBuiltinLocale, {
|
|
342
383
|
save: string;
|
|
343
384
|
cancel: string;
|
|
344
385
|
close: string;
|
|
@@ -409,14 +450,14 @@ declare const commonMessages: Record<SaLocale, {
|
|
|
409
450
|
noChanges: string;
|
|
410
451
|
}>;
|
|
411
452
|
|
|
412
|
-
declare const dashboardMessages: Record<
|
|
453
|
+
declare const dashboardMessages: Record<SaBuiltinLocale, {
|
|
413
454
|
title: string;
|
|
414
455
|
emptyKpiCards: string;
|
|
415
456
|
shortcutsTitle: string;
|
|
416
457
|
deltaVsPreviousPeriod: string;
|
|
417
458
|
}>;
|
|
418
459
|
|
|
419
|
-
declare const discoveryMessages: Record<
|
|
460
|
+
declare const discoveryMessages: Record<SaBuiltinLocale, {
|
|
420
461
|
title: string;
|
|
421
462
|
subtitleLead: string;
|
|
422
463
|
subtitleEmphasis: string;
|
|
@@ -521,7 +562,7 @@ declare const discoveryMessages: Record<SaLocale, {
|
|
|
521
562
|
};
|
|
522
563
|
}>;
|
|
523
564
|
|
|
524
|
-
declare const emailMessages: Record<
|
|
565
|
+
declare const emailMessages: Record<SaBuiltinLocale, {
|
|
525
566
|
sender: string;
|
|
526
567
|
recipient: string;
|
|
527
568
|
errorAction: string;
|
|
@@ -581,7 +622,7 @@ declare const emailMessages: Record<SaLocale, {
|
|
|
581
622
|
};
|
|
582
623
|
}>;
|
|
583
624
|
|
|
584
|
-
declare const marketingMessages: Record<
|
|
625
|
+
declare const marketingMessages: Record<SaBuiltinLocale, {
|
|
585
626
|
topFeatures: string;
|
|
586
627
|
tabs: {
|
|
587
628
|
preview: string;
|
|
@@ -710,18 +751,7 @@ declare const marketingMessages: Record<SaLocale, {
|
|
|
710
751
|
};
|
|
711
752
|
}>;
|
|
712
753
|
|
|
713
|
-
|
|
714
|
-
readonly pages: Record<StandardPageKey, string>;
|
|
715
|
-
readonly sections: {
|
|
716
|
-
readonly overview: string;
|
|
717
|
-
readonly catalog: string;
|
|
718
|
-
readonly customers: string;
|
|
719
|
-
readonly system: string;
|
|
720
|
-
};
|
|
721
|
-
};
|
|
722
|
-
declare const navMessages: Record<SaLocale, NavNamespace>;
|
|
723
|
-
|
|
724
|
-
declare const pilotsMessages: Record<SaLocale, {
|
|
754
|
+
declare const pilotsMessages: Record<SaBuiltinLocale, {
|
|
725
755
|
title: string;
|
|
726
756
|
subtitleCount: string;
|
|
727
757
|
createAction: string;
|
|
@@ -815,7 +845,7 @@ declare const pilotsMessages: Record<SaLocale, {
|
|
|
815
845
|
};
|
|
816
846
|
}>;
|
|
817
847
|
|
|
818
|
-
declare const planDetailMessages: Record<
|
|
848
|
+
declare const planDetailMessages: Record<SaBuiltinLocale, {
|
|
819
849
|
header: {
|
|
820
850
|
noDescription: string;
|
|
821
851
|
nameEditHint: string;
|
|
@@ -943,7 +973,7 @@ declare const planDetailMessages: Record<SaLocale, {
|
|
|
943
973
|
};
|
|
944
974
|
}>;
|
|
945
975
|
|
|
946
|
-
declare const planEditorMessages: Record<
|
|
976
|
+
declare const planEditorMessages: Record<SaBuiltinLocale, {
|
|
947
977
|
perMonthShort: string;
|
|
948
978
|
perYearShort: string;
|
|
949
979
|
sections: {
|
|
@@ -1028,7 +1058,7 @@ declare const planEditorMessages: Record<SaLocale, {
|
|
|
1028
1058
|
};
|
|
1029
1059
|
}>;
|
|
1030
1060
|
|
|
1031
|
-
declare const planVersionsMessages: Record<
|
|
1061
|
+
declare const planVersionsMessages: Record<SaBuiltinLocale, {
|
|
1032
1062
|
compareEnd: string;
|
|
1033
1063
|
status: {
|
|
1034
1064
|
draft: string;
|
|
@@ -1081,7 +1111,7 @@ declare const planVersionsMessages: Record<SaLocale, {
|
|
|
1081
1111
|
};
|
|
1082
1112
|
}>;
|
|
1083
1113
|
|
|
1084
|
-
declare const plansMessages: Record<
|
|
1114
|
+
declare const plansMessages: Record<SaBuiltinLocale, {
|
|
1085
1115
|
page: {
|
|
1086
1116
|
loading: string;
|
|
1087
1117
|
toastPlanCreated: string;
|
|
@@ -1297,7 +1327,7 @@ declare const plansMessages: Record<SaLocale, {
|
|
|
1297
1327
|
};
|
|
1298
1328
|
}>;
|
|
1299
1329
|
|
|
1300
|
-
declare const promosMessages: Record<
|
|
1330
|
+
declare const promosMessages: Record<SaBuiltinLocale, {
|
|
1301
1331
|
title: string;
|
|
1302
1332
|
createAction: string;
|
|
1303
1333
|
apiErrorHttpStatus: string;
|
|
@@ -1396,7 +1426,7 @@ declare const promosMessages: Record<SaLocale, {
|
|
|
1396
1426
|
};
|
|
1397
1427
|
}>;
|
|
1398
1428
|
|
|
1399
|
-
declare const shellMessages: Record<
|
|
1429
|
+
declare const shellMessages: Record<SaBuiltinLocale, {
|
|
1400
1430
|
emailLabel: string;
|
|
1401
1431
|
passwordLabel: string;
|
|
1402
1432
|
invalidEmail: string;
|
|
@@ -1405,6 +1435,7 @@ declare const shellMessages: Record<SaLocale, {
|
|
|
1405
1435
|
subtitle: string;
|
|
1406
1436
|
roleBadge: string;
|
|
1407
1437
|
logout: string;
|
|
1438
|
+
language: string;
|
|
1408
1439
|
};
|
|
1409
1440
|
drawer: {
|
|
1410
1441
|
docs: string;
|
|
@@ -1464,7 +1495,7 @@ declare const shellMessages: Record<SaLocale, {
|
|
|
1464
1495
|
};
|
|
1465
1496
|
}>;
|
|
1466
1497
|
|
|
1467
|
-
declare const tenantsMessages: Record<
|
|
1498
|
+
declare const tenantsMessages: Record<SaBuiltinLocale, {
|
|
1468
1499
|
tenant: string;
|
|
1469
1500
|
plan: string;
|
|
1470
1501
|
list: {
|
|
@@ -1514,7 +1545,7 @@ declare const tenantsMessages: Record<SaLocale, {
|
|
|
1514
1545
|
};
|
|
1515
1546
|
}>;
|
|
1516
1547
|
|
|
1517
|
-
declare const usersMessages: Record<
|
|
1548
|
+
declare const usersMessages: Record<SaBuiltinLocale, {
|
|
1518
1549
|
title: string;
|
|
1519
1550
|
filterQuery: string;
|
|
1520
1551
|
filterTenant: string;
|
|
@@ -1575,11 +1606,67 @@ type SaMessages = {
|
|
|
1575
1606
|
/** Shape of app-side string overrides (deep partial of the catalog). */
|
|
1576
1607
|
type SaMessagesOverrides = PartialMessages<SaMessages>;
|
|
1577
1608
|
/** Complete, immutable message catalogs per locale. */
|
|
1578
|
-
declare const SA_MESSAGES: Record<
|
|
1609
|
+
declare const SA_MESSAGES: Record<SaBuiltinLocale, SaMessages>;
|
|
1579
1610
|
/**
|
|
1580
1611
|
* Returns the platform catalog for `locale`, optionally overlaid with
|
|
1581
1612
|
* app-side overrides.
|
|
1582
1613
|
*/
|
|
1583
|
-
declare function resolveMessages(locale:
|
|
1614
|
+
declare function resolveMessages(locale: SaBuiltinLocale, overrides?: SaMessagesOverrides): SaMessages;
|
|
1615
|
+
|
|
1616
|
+
/** A language an app brings along, on top of the two the platform ships. */
|
|
1617
|
+
interface SaLocaleDefinition {
|
|
1618
|
+
/**
|
|
1619
|
+
* Name for the switcher, written in the language itself (`'Français'`) —
|
|
1620
|
+
* that way the entry stays readable whatever locale is currently active.
|
|
1621
|
+
*/
|
|
1622
|
+
label: string;
|
|
1623
|
+
/** BCP-47 tag for `Intl`/`toLocaleString`, e.g. `'fr-FR'`. */
|
|
1624
|
+
intlLocale: string;
|
|
1625
|
+
/**
|
|
1626
|
+
* Built-in catalog that fills whatever `messages` leaves out, default
|
|
1627
|
+
* `'en'`. A partial translation therefore renders — untranslated keys fall
|
|
1628
|
+
* back instead of showing blanks.
|
|
1629
|
+
*/
|
|
1630
|
+
basedOn?: SaBuiltinLocale;
|
|
1631
|
+
/** The translation. Every key is optional; see `basedOn`. */
|
|
1632
|
+
messages: SaMessagesOverrides;
|
|
1633
|
+
}
|
|
1634
|
+
interface SaCatalogOptions {
|
|
1635
|
+
/**
|
|
1636
|
+
* Locales offered in the switcher, in the order given. Default: the
|
|
1637
|
+
* built-ins plus everything in `additionalLocales`. Narrow it to ship a
|
|
1638
|
+
* single language; entries without a catalog are ignored.
|
|
1639
|
+
*/
|
|
1640
|
+
locales?: readonly SaLocale[];
|
|
1641
|
+
/** Languages the app adds, keyed by locale code (`'fr'`, `'pt-BR'`, …). */
|
|
1642
|
+
additionalLocales?: Readonly<Record<string, SaLocaleDefinition>>;
|
|
1643
|
+
/** Per-locale wording changes layered on top of whatever catalog applies. */
|
|
1644
|
+
overrides?: Readonly<Partial<Record<SaLocale, SaMessagesOverrides>>>;
|
|
1645
|
+
}
|
|
1646
|
+
/** One entry of the switcher. */
|
|
1647
|
+
interface SaLocaleOption {
|
|
1648
|
+
code: SaLocale;
|
|
1649
|
+
label: string;
|
|
1650
|
+
}
|
|
1651
|
+
interface SaCatalog {
|
|
1652
|
+
/** Locales to offer, in switcher order. Never empty. */
|
|
1653
|
+
readonly locales: readonly SaLocaleOption[];
|
|
1654
|
+
/**
|
|
1655
|
+
* Whether the app offers this locale. Deliberately not "can it be
|
|
1656
|
+
* rendered": an app that narrowed to English must not be pushed back into
|
|
1657
|
+
* German by a stored pick from before, even though German is still shipped.
|
|
1658
|
+
*/
|
|
1659
|
+
has(locale: SaLocale): boolean;
|
|
1660
|
+
/** Locale to start from when nothing else is known. */
|
|
1661
|
+
readonly defaultLocale: SaLocale;
|
|
1662
|
+
messagesFor(locale: SaLocale): SaMessages;
|
|
1663
|
+
intlLocaleFor(locale: SaLocale): string;
|
|
1664
|
+
labelFor(locale: SaLocale): string;
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Builds the catalog an app runs on. Resolution is cached per locale, so
|
|
1668
|
+
* switching back and forth does not re-merge the message tree.
|
|
1669
|
+
*/
|
|
1670
|
+
declare function createSaCatalog(options?: SaCatalogOptions): SaCatalog;
|
|
1584
1671
|
|
|
1585
|
-
export { type ActionHandler as A, DEFAULT_SA_LOCALE as D, type HttpClient as H, type KvStore as K, type MessageTree as M, type PartialMessages as P, type ResolvedAction as R, type SaLocale as S, type TranslationOf as T, type SaMessages as a, type
|
|
1672
|
+
export { type ActionHandler as A, DEFAULT_SA_LOCALE as D, type HttpClient as H, type KvStore as K, type MessageTree as M, type PartialMessages as P, type ResolvedAction as R, type SaLocale as S, type TranslationOf as T, type SaMessages as a, type SaLocaleOption as b, type SaLocaleDefinition as c, type SaMessagesOverrides as d, ActionRegistry as e, ActionDefNotInManifestError as f, type HttpResponse as g, MissingHandlerError as h, SA_INTL_LOCALES as i, SA_LOCALES as j, SA_LOCALE_LABELS as k, SA_MESSAGES as l, type SaBuiltinLocale as m, type SaCatalog as n, type SaCatalogOptions as o, builtinLocaleOf as p, createSaCatalog as q, defaultHttpClient as r, defaultKvStore as s, defineMessages as t, isSaBuiltinLocale as u, mergeMessages as v, resolveMessages as w, type SaNavMessages as x };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdminManifest, TenantActionDef
|
|
1
|
+
import { StandardPageKey, AdminManifest, TenantActionDef } from '@saasicat/types';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Minimal abstraction over `fetch`. Consumers may pass their own
|
|
@@ -25,8 +25,11 @@ interface KvStore {
|
|
|
25
25
|
remove(key: string): void;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
* Returns a `KvStore` wrapper around `localStorage
|
|
29
|
-
* Tests may pass an in-memory stub.
|
|
28
|
+
* Returns a `KvStore` wrapper around `localStorage`, or a no-op store when the
|
|
29
|
+
* environment has none or refuses access. Tests may pass an in-memory stub.
|
|
30
|
+
*
|
|
31
|
+
* Every persistence built on this is a convenience — losing it must never take
|
|
32
|
+
* the app down, so no failure mode is allowed to escape.
|
|
30
33
|
*/
|
|
31
34
|
declare function defaultKvStore(): KvStore;
|
|
32
35
|
/**
|
|
@@ -35,11 +38,49 @@ declare function defaultKvStore(): KvStore;
|
|
|
35
38
|
*/
|
|
36
39
|
declare function defaultHttpClient(): HttpClient;
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
/** Locales the platform itself ships a catalog for. */
|
|
42
|
+
type SaBuiltinLocale = 'de' | 'en';
|
|
43
|
+
/**
|
|
44
|
+
* Any locale the shell can run in: the built-ins plus whatever an app adds via
|
|
45
|
+
* `i18n.additionalLocales`. The `string & {}` arm keeps autocompletion for the
|
|
46
|
+
* built-ins while leaving the set open.
|
|
47
|
+
*/
|
|
48
|
+
type SaLocale = SaBuiltinLocale | (string & {});
|
|
49
|
+
/** The locales the platform ships. Apps narrow or extend this, see `i18n`. */
|
|
50
|
+
declare const SA_LOCALES: readonly SaBuiltinLocale[];
|
|
51
|
+
declare const DEFAULT_SA_LOCALE: SaBuiltinLocale;
|
|
52
|
+
/** BCP-47 tags used for `Intl`/`toLocaleString` formatting per built-in locale. */
|
|
53
|
+
declare const SA_INTL_LOCALES: Record<SaBuiltinLocale, string>;
|
|
54
|
+
/**
|
|
55
|
+
* Names for the language switcher. Endonyms — a language is listed in its own
|
|
56
|
+
* language, so the entries stay readable no matter which locale is active and
|
|
57
|
+
* never need translating.
|
|
58
|
+
*/
|
|
59
|
+
declare const SA_LOCALE_LABELS: Record<SaBuiltinLocale, string>;
|
|
60
|
+
/** Narrows untrusted input to a locale the platform ships a catalog for. */
|
|
61
|
+
declare function isSaBuiltinLocale(value: unknown): value is SaBuiltinLocale;
|
|
62
|
+
/**
|
|
63
|
+
* The built-in catalog a locale reads from. Helper modules that index the raw
|
|
64
|
+
* catalogs (rather than the resolved one from `useSaMessages`) need this: a
|
|
65
|
+
* language an app added has no entry there, and indexing it would yield
|
|
66
|
+
* `undefined` and take the page down.
|
|
67
|
+
*
|
|
68
|
+
* Strings resolved this way stay in the fallback language for an app-supplied
|
|
69
|
+
* locale — migrating those helpers to the resolved catalog is tracked
|
|
70
|
+
* separately.
|
|
71
|
+
*/
|
|
72
|
+
declare function builtinLocaleOf(locale: SaLocale | undefined, fallback?: SaBuiltinLocale): SaBuiltinLocale;
|
|
73
|
+
|
|
74
|
+
type SaNavMessages = {
|
|
75
|
+
readonly pages: Record<StandardPageKey, string>;
|
|
76
|
+
readonly sections: {
|
|
77
|
+
readonly overview: string;
|
|
78
|
+
readonly catalog: string;
|
|
79
|
+
readonly customers: string;
|
|
80
|
+
readonly system: string;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
declare const navMessages: Record<SaBuiltinLocale, SaNavMessages>;
|
|
43
84
|
|
|
44
85
|
/** Consumer implementation; receives the action inputs as a generic object. */
|
|
45
86
|
type ActionHandler<TInput = unknown, TResult = unknown> = (input: TInput) => Promise<TResult>;
|
|
@@ -104,7 +145,7 @@ type PartialMessages<T> = {
|
|
|
104
145
|
* Couples the German reference catalog with its English translation. Missing
|
|
105
146
|
* or extra keys in the English object are compile errors.
|
|
106
147
|
*/
|
|
107
|
-
declare function defineMessages<T extends MessageTree>(de: T, en: TranslationOf<T>): Record<
|
|
148
|
+
declare function defineMessages<T extends MessageTree>(de: T, en: TranslationOf<T>): Record<SaBuiltinLocale, T>;
|
|
108
149
|
/**
|
|
109
150
|
* Recursively overlays `overrides` onto `base` without mutating either side.
|
|
110
151
|
* Only string leaves are replaced; keys not present in `base` are ignored —
|
|
@@ -112,7 +153,7 @@ declare function defineMessages<T extends MessageTree>(de: T, en: TranslationOf<
|
|
|
112
153
|
*/
|
|
113
154
|
declare function mergeMessages<T extends MessageTree>(base: T, overrides: PartialMessages<T> | undefined): T;
|
|
114
155
|
|
|
115
|
-
declare const auditMessages: Record<
|
|
156
|
+
declare const auditMessages: Record<SaBuiltinLocale, {
|
|
116
157
|
title: string;
|
|
117
158
|
subtitle: string;
|
|
118
159
|
filterButton: string;
|
|
@@ -132,7 +173,7 @@ declare const auditMessages: Record<SaLocale, {
|
|
|
132
173
|
};
|
|
133
174
|
}>;
|
|
134
175
|
|
|
135
|
-
declare const bundlesMessages: Record<
|
|
176
|
+
declare const bundlesMessages: Record<SaBuiltinLocale, {
|
|
136
177
|
fields: {
|
|
137
178
|
masterData: string;
|
|
138
179
|
label: string;
|
|
@@ -338,7 +379,7 @@ declare const bundlesMessages: Record<SaLocale, {
|
|
|
338
379
|
};
|
|
339
380
|
}>;
|
|
340
381
|
|
|
341
|
-
declare const commonMessages: Record<
|
|
382
|
+
declare const commonMessages: Record<SaBuiltinLocale, {
|
|
342
383
|
save: string;
|
|
343
384
|
cancel: string;
|
|
344
385
|
close: string;
|
|
@@ -409,14 +450,14 @@ declare const commonMessages: Record<SaLocale, {
|
|
|
409
450
|
noChanges: string;
|
|
410
451
|
}>;
|
|
411
452
|
|
|
412
|
-
declare const dashboardMessages: Record<
|
|
453
|
+
declare const dashboardMessages: Record<SaBuiltinLocale, {
|
|
413
454
|
title: string;
|
|
414
455
|
emptyKpiCards: string;
|
|
415
456
|
shortcutsTitle: string;
|
|
416
457
|
deltaVsPreviousPeriod: string;
|
|
417
458
|
}>;
|
|
418
459
|
|
|
419
|
-
declare const discoveryMessages: Record<
|
|
460
|
+
declare const discoveryMessages: Record<SaBuiltinLocale, {
|
|
420
461
|
title: string;
|
|
421
462
|
subtitleLead: string;
|
|
422
463
|
subtitleEmphasis: string;
|
|
@@ -521,7 +562,7 @@ declare const discoveryMessages: Record<SaLocale, {
|
|
|
521
562
|
};
|
|
522
563
|
}>;
|
|
523
564
|
|
|
524
|
-
declare const emailMessages: Record<
|
|
565
|
+
declare const emailMessages: Record<SaBuiltinLocale, {
|
|
525
566
|
sender: string;
|
|
526
567
|
recipient: string;
|
|
527
568
|
errorAction: string;
|
|
@@ -581,7 +622,7 @@ declare const emailMessages: Record<SaLocale, {
|
|
|
581
622
|
};
|
|
582
623
|
}>;
|
|
583
624
|
|
|
584
|
-
declare const marketingMessages: Record<
|
|
625
|
+
declare const marketingMessages: Record<SaBuiltinLocale, {
|
|
585
626
|
topFeatures: string;
|
|
586
627
|
tabs: {
|
|
587
628
|
preview: string;
|
|
@@ -710,18 +751,7 @@ declare const marketingMessages: Record<SaLocale, {
|
|
|
710
751
|
};
|
|
711
752
|
}>;
|
|
712
753
|
|
|
713
|
-
|
|
714
|
-
readonly pages: Record<StandardPageKey, string>;
|
|
715
|
-
readonly sections: {
|
|
716
|
-
readonly overview: string;
|
|
717
|
-
readonly catalog: string;
|
|
718
|
-
readonly customers: string;
|
|
719
|
-
readonly system: string;
|
|
720
|
-
};
|
|
721
|
-
};
|
|
722
|
-
declare const navMessages: Record<SaLocale, NavNamespace>;
|
|
723
|
-
|
|
724
|
-
declare const pilotsMessages: Record<SaLocale, {
|
|
754
|
+
declare const pilotsMessages: Record<SaBuiltinLocale, {
|
|
725
755
|
title: string;
|
|
726
756
|
subtitleCount: string;
|
|
727
757
|
createAction: string;
|
|
@@ -815,7 +845,7 @@ declare const pilotsMessages: Record<SaLocale, {
|
|
|
815
845
|
};
|
|
816
846
|
}>;
|
|
817
847
|
|
|
818
|
-
declare const planDetailMessages: Record<
|
|
848
|
+
declare const planDetailMessages: Record<SaBuiltinLocale, {
|
|
819
849
|
header: {
|
|
820
850
|
noDescription: string;
|
|
821
851
|
nameEditHint: string;
|
|
@@ -943,7 +973,7 @@ declare const planDetailMessages: Record<SaLocale, {
|
|
|
943
973
|
};
|
|
944
974
|
}>;
|
|
945
975
|
|
|
946
|
-
declare const planEditorMessages: Record<
|
|
976
|
+
declare const planEditorMessages: Record<SaBuiltinLocale, {
|
|
947
977
|
perMonthShort: string;
|
|
948
978
|
perYearShort: string;
|
|
949
979
|
sections: {
|
|
@@ -1028,7 +1058,7 @@ declare const planEditorMessages: Record<SaLocale, {
|
|
|
1028
1058
|
};
|
|
1029
1059
|
}>;
|
|
1030
1060
|
|
|
1031
|
-
declare const planVersionsMessages: Record<
|
|
1061
|
+
declare const planVersionsMessages: Record<SaBuiltinLocale, {
|
|
1032
1062
|
compareEnd: string;
|
|
1033
1063
|
status: {
|
|
1034
1064
|
draft: string;
|
|
@@ -1081,7 +1111,7 @@ declare const planVersionsMessages: Record<SaLocale, {
|
|
|
1081
1111
|
};
|
|
1082
1112
|
}>;
|
|
1083
1113
|
|
|
1084
|
-
declare const plansMessages: Record<
|
|
1114
|
+
declare const plansMessages: Record<SaBuiltinLocale, {
|
|
1085
1115
|
page: {
|
|
1086
1116
|
loading: string;
|
|
1087
1117
|
toastPlanCreated: string;
|
|
@@ -1297,7 +1327,7 @@ declare const plansMessages: Record<SaLocale, {
|
|
|
1297
1327
|
};
|
|
1298
1328
|
}>;
|
|
1299
1329
|
|
|
1300
|
-
declare const promosMessages: Record<
|
|
1330
|
+
declare const promosMessages: Record<SaBuiltinLocale, {
|
|
1301
1331
|
title: string;
|
|
1302
1332
|
createAction: string;
|
|
1303
1333
|
apiErrorHttpStatus: string;
|
|
@@ -1396,7 +1426,7 @@ declare const promosMessages: Record<SaLocale, {
|
|
|
1396
1426
|
};
|
|
1397
1427
|
}>;
|
|
1398
1428
|
|
|
1399
|
-
declare const shellMessages: Record<
|
|
1429
|
+
declare const shellMessages: Record<SaBuiltinLocale, {
|
|
1400
1430
|
emailLabel: string;
|
|
1401
1431
|
passwordLabel: string;
|
|
1402
1432
|
invalidEmail: string;
|
|
@@ -1405,6 +1435,7 @@ declare const shellMessages: Record<SaLocale, {
|
|
|
1405
1435
|
subtitle: string;
|
|
1406
1436
|
roleBadge: string;
|
|
1407
1437
|
logout: string;
|
|
1438
|
+
language: string;
|
|
1408
1439
|
};
|
|
1409
1440
|
drawer: {
|
|
1410
1441
|
docs: string;
|
|
@@ -1464,7 +1495,7 @@ declare const shellMessages: Record<SaLocale, {
|
|
|
1464
1495
|
};
|
|
1465
1496
|
}>;
|
|
1466
1497
|
|
|
1467
|
-
declare const tenantsMessages: Record<
|
|
1498
|
+
declare const tenantsMessages: Record<SaBuiltinLocale, {
|
|
1468
1499
|
tenant: string;
|
|
1469
1500
|
plan: string;
|
|
1470
1501
|
list: {
|
|
@@ -1514,7 +1545,7 @@ declare const tenantsMessages: Record<SaLocale, {
|
|
|
1514
1545
|
};
|
|
1515
1546
|
}>;
|
|
1516
1547
|
|
|
1517
|
-
declare const usersMessages: Record<
|
|
1548
|
+
declare const usersMessages: Record<SaBuiltinLocale, {
|
|
1518
1549
|
title: string;
|
|
1519
1550
|
filterQuery: string;
|
|
1520
1551
|
filterTenant: string;
|
|
@@ -1575,11 +1606,67 @@ type SaMessages = {
|
|
|
1575
1606
|
/** Shape of app-side string overrides (deep partial of the catalog). */
|
|
1576
1607
|
type SaMessagesOverrides = PartialMessages<SaMessages>;
|
|
1577
1608
|
/** Complete, immutable message catalogs per locale. */
|
|
1578
|
-
declare const SA_MESSAGES: Record<
|
|
1609
|
+
declare const SA_MESSAGES: Record<SaBuiltinLocale, SaMessages>;
|
|
1579
1610
|
/**
|
|
1580
1611
|
* Returns the platform catalog for `locale`, optionally overlaid with
|
|
1581
1612
|
* app-side overrides.
|
|
1582
1613
|
*/
|
|
1583
|
-
declare function resolveMessages(locale:
|
|
1614
|
+
declare function resolveMessages(locale: SaBuiltinLocale, overrides?: SaMessagesOverrides): SaMessages;
|
|
1615
|
+
|
|
1616
|
+
/** A language an app brings along, on top of the two the platform ships. */
|
|
1617
|
+
interface SaLocaleDefinition {
|
|
1618
|
+
/**
|
|
1619
|
+
* Name for the switcher, written in the language itself (`'Français'`) —
|
|
1620
|
+
* that way the entry stays readable whatever locale is currently active.
|
|
1621
|
+
*/
|
|
1622
|
+
label: string;
|
|
1623
|
+
/** BCP-47 tag for `Intl`/`toLocaleString`, e.g. `'fr-FR'`. */
|
|
1624
|
+
intlLocale: string;
|
|
1625
|
+
/**
|
|
1626
|
+
* Built-in catalog that fills whatever `messages` leaves out, default
|
|
1627
|
+
* `'en'`. A partial translation therefore renders — untranslated keys fall
|
|
1628
|
+
* back instead of showing blanks.
|
|
1629
|
+
*/
|
|
1630
|
+
basedOn?: SaBuiltinLocale;
|
|
1631
|
+
/** The translation. Every key is optional; see `basedOn`. */
|
|
1632
|
+
messages: SaMessagesOverrides;
|
|
1633
|
+
}
|
|
1634
|
+
interface SaCatalogOptions {
|
|
1635
|
+
/**
|
|
1636
|
+
* Locales offered in the switcher, in the order given. Default: the
|
|
1637
|
+
* built-ins plus everything in `additionalLocales`. Narrow it to ship a
|
|
1638
|
+
* single language; entries without a catalog are ignored.
|
|
1639
|
+
*/
|
|
1640
|
+
locales?: readonly SaLocale[];
|
|
1641
|
+
/** Languages the app adds, keyed by locale code (`'fr'`, `'pt-BR'`, …). */
|
|
1642
|
+
additionalLocales?: Readonly<Record<string, SaLocaleDefinition>>;
|
|
1643
|
+
/** Per-locale wording changes layered on top of whatever catalog applies. */
|
|
1644
|
+
overrides?: Readonly<Partial<Record<SaLocale, SaMessagesOverrides>>>;
|
|
1645
|
+
}
|
|
1646
|
+
/** One entry of the switcher. */
|
|
1647
|
+
interface SaLocaleOption {
|
|
1648
|
+
code: SaLocale;
|
|
1649
|
+
label: string;
|
|
1650
|
+
}
|
|
1651
|
+
interface SaCatalog {
|
|
1652
|
+
/** Locales to offer, in switcher order. Never empty. */
|
|
1653
|
+
readonly locales: readonly SaLocaleOption[];
|
|
1654
|
+
/**
|
|
1655
|
+
* Whether the app offers this locale. Deliberately not "can it be
|
|
1656
|
+
* rendered": an app that narrowed to English must not be pushed back into
|
|
1657
|
+
* German by a stored pick from before, even though German is still shipped.
|
|
1658
|
+
*/
|
|
1659
|
+
has(locale: SaLocale): boolean;
|
|
1660
|
+
/** Locale to start from when nothing else is known. */
|
|
1661
|
+
readonly defaultLocale: SaLocale;
|
|
1662
|
+
messagesFor(locale: SaLocale): SaMessages;
|
|
1663
|
+
intlLocaleFor(locale: SaLocale): string;
|
|
1664
|
+
labelFor(locale: SaLocale): string;
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Builds the catalog an app runs on. Resolution is cached per locale, so
|
|
1668
|
+
* switching back and forth does not re-merge the message tree.
|
|
1669
|
+
*/
|
|
1670
|
+
declare function createSaCatalog(options?: SaCatalogOptions): SaCatalog;
|
|
1584
1671
|
|
|
1585
|
-
export { type ActionHandler as A, DEFAULT_SA_LOCALE as D, type HttpClient as H, type KvStore as K, type MessageTree as M, type PartialMessages as P, type ResolvedAction as R, type SaLocale as S, type TranslationOf as T, type SaMessages as a, type
|
|
1672
|
+
export { type ActionHandler as A, DEFAULT_SA_LOCALE as D, type HttpClient as H, type KvStore as K, type MessageTree as M, type PartialMessages as P, type ResolvedAction as R, type SaLocale as S, type TranslationOf as T, type SaMessages as a, type SaLocaleOption as b, type SaLocaleDefinition as c, type SaMessagesOverrides as d, ActionRegistry as e, ActionDefNotInManifestError as f, type HttpResponse as g, MissingHandlerError as h, SA_INTL_LOCALES as i, SA_LOCALES as j, SA_LOCALE_LABELS as k, SA_MESSAGES as l, type SaBuiltinLocale as m, type SaCatalog as n, type SaCatalogOptions as o, builtinLocaleOf as p, createSaCatalog as q, defaultHttpClient as r, defaultKvStore as s, defineMessages as t, isSaBuiltinLocale as u, mergeMessages as v, resolveMessages as w, type SaNavMessages as x };
|