@iveri/contracts 0.17.0 → 0.18.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 +25 -1
- package/dist/cjs/api/localization/bundle.type.d.ts +41 -0
- package/dist/cjs/api/localization/bundle.type.d.ts.map +1 -0
- package/dist/cjs/api/localization/bundle.type.js +3 -0
- package/dist/cjs/api/localization/bundle.type.js.map +1 -0
- package/dist/cjs/api/localization/index.d.ts +10 -0
- package/dist/cjs/api/localization/index.d.ts.map +1 -0
- package/dist/cjs/api/localization/index.js +26 -0
- package/dist/cjs/api/localization/index.js.map +1 -0
- package/dist/cjs/api/localization/locale.type.d.ts +67 -0
- package/dist/cjs/api/localization/locale.type.d.ts.map +1 -0
- package/dist/cjs/api/localization/locale.type.js +3 -0
- package/dist/cjs/api/localization/locale.type.js.map +1 -0
- package/dist/cjs/api/localization/message.type.d.ts +90 -0
- package/dist/cjs/api/localization/message.type.d.ts.map +1 -0
- package/dist/cjs/api/localization/message.type.js +3 -0
- package/dist/cjs/api/localization/message.type.js.map +1 -0
- package/dist/cjs/api/localization/namespace.type.d.ts +67 -0
- package/dist/cjs/api/localization/namespace.type.d.ts.map +1 -0
- package/dist/cjs/api/localization/namespace.type.js +3 -0
- package/dist/cjs/api/localization/namespace.type.js.map +1 -0
- package/dist/cjs/api/localization/release.type.d.ts +74 -0
- package/dist/cjs/api/localization/release.type.d.ts.map +1 -0
- package/dist/cjs/api/localization/release.type.js +3 -0
- package/dist/cjs/api/localization/release.type.js.map +1 -0
- package/dist/cjs/api/localization/render.type.d.ts +50 -0
- package/dist/cjs/api/localization/render.type.d.ts.map +1 -0
- package/dist/cjs/api/localization/render.type.js +3 -0
- package/dist/cjs/api/localization/render.type.js.map +1 -0
- package/dist/cjs/api/localization/translation-status.enum.d.ts +29 -0
- package/dist/cjs/api/localization/translation-status.enum.d.ts.map +1 -0
- package/dist/cjs/api/localization/translation-status.enum.js +33 -0
- package/dist/cjs/api/localization/translation-status.enum.js.map +1 -0
- package/dist/cjs/api/localization/translation.type.d.ts +74 -0
- package/dist/cjs/api/localization/translation.type.d.ts.map +1 -0
- package/dist/cjs/api/localization/translation.type.js +3 -0
- package/dist/cjs/api/localization/translation.type.js.map +1 -0
- package/dist/cjs/api/localization/variable-type.enum.d.ts +39 -0
- package/dist/cjs/api/localization/variable-type.enum.d.ts.map +1 -0
- package/dist/cjs/api/localization/variable-type.enum.js +43 -0
- package/dist/cjs/api/localization/variable-type.enum.js.map +1 -0
- package/dist/cjs/enum/user-permission.enum.d.ts +44 -1
- package/dist/cjs/enum/user-permission.enum.d.ts.map +1 -1
- package/dist/cjs/enum/user-permission.enum.js +50 -0
- package/dist/cjs/enum/user-permission.enum.js.map +1 -1
- package/dist/esm/api/localization/bundle.type.d.ts +41 -0
- package/dist/esm/api/localization/bundle.type.d.ts.map +1 -0
- package/dist/esm/api/localization/bundle.type.js +2 -0
- package/dist/esm/api/localization/bundle.type.js.map +1 -0
- package/dist/esm/api/localization/index.d.ts +10 -0
- package/dist/esm/api/localization/index.d.ts.map +1 -0
- package/dist/esm/api/localization/index.js +10 -0
- package/dist/esm/api/localization/index.js.map +1 -0
- package/dist/esm/api/localization/locale.type.d.ts +67 -0
- package/dist/esm/api/localization/locale.type.d.ts.map +1 -0
- package/dist/esm/api/localization/locale.type.js +2 -0
- package/dist/esm/api/localization/locale.type.js.map +1 -0
- package/dist/esm/api/localization/message.type.d.ts +90 -0
- package/dist/esm/api/localization/message.type.d.ts.map +1 -0
- package/dist/esm/api/localization/message.type.js +2 -0
- package/dist/esm/api/localization/message.type.js.map +1 -0
- package/dist/esm/api/localization/namespace.type.d.ts +67 -0
- package/dist/esm/api/localization/namespace.type.d.ts.map +1 -0
- package/dist/esm/api/localization/namespace.type.js +2 -0
- package/dist/esm/api/localization/namespace.type.js.map +1 -0
- package/dist/esm/api/localization/release.type.d.ts +74 -0
- package/dist/esm/api/localization/release.type.d.ts.map +1 -0
- package/dist/esm/api/localization/release.type.js +2 -0
- package/dist/esm/api/localization/release.type.js.map +1 -0
- package/dist/esm/api/localization/render.type.d.ts +50 -0
- package/dist/esm/api/localization/render.type.d.ts.map +1 -0
- package/dist/esm/api/localization/render.type.js +2 -0
- package/dist/esm/api/localization/render.type.js.map +1 -0
- package/dist/esm/api/localization/translation-status.enum.d.ts +29 -0
- package/dist/esm/api/localization/translation-status.enum.d.ts.map +1 -0
- package/dist/esm/api/localization/translation-status.enum.js +30 -0
- package/dist/esm/api/localization/translation-status.enum.js.map +1 -0
- package/dist/esm/api/localization/translation.type.d.ts +74 -0
- package/dist/esm/api/localization/translation.type.d.ts.map +1 -0
- package/dist/esm/api/localization/translation.type.js +2 -0
- package/dist/esm/api/localization/translation.type.js.map +1 -0
- package/dist/esm/api/localization/variable-type.enum.d.ts +39 -0
- package/dist/esm/api/localization/variable-type.enum.d.ts.map +1 -0
- package/dist/esm/api/localization/variable-type.enum.js +40 -0
- package/dist/esm/api/localization/variable-type.enum.js.map +1 -0
- package/dist/esm/enum/user-permission.enum.d.ts +44 -1
- package/dist/esm/enum/user-permission.enum.d.ts.map +1 -1
- package/dist/esm/enum/user-permission.enum.js +50 -0
- package/dist/esm/enum/user-permission.enum.js.map +1 -1
- package/package.json +9 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { IsoDateTime } from '../../type/iso-date-time.type.js';
|
|
2
|
+
import type { Nullable } from '../../type/nil.type.js';
|
|
3
|
+
import type { Paginated } from '../../type/paginated.type.js';
|
|
4
|
+
import type { UUID } from '../../type/uuid.type.js';
|
|
5
|
+
/**
|
|
6
|
+
* A bounded set of keys owned by one consumer — `unibox-web`, `billing.invoice`, `messaging.otp`.
|
|
7
|
+
*
|
|
8
|
+
* **The unit of publish and the unit of fetch, and it has to be both.** Without namespaces every
|
|
9
|
+
* consumer downloads every string the tenant has ever written, and a translator fixing one word in
|
|
10
|
+
* an invoice template republishes the entire admin panel's UI at the same time. Those are the two
|
|
11
|
+
* failures a flat key space produces, and neither is visible until the key count is in the
|
|
12
|
+
* thousands and it is expensive to fix.
|
|
13
|
+
*
|
|
14
|
+
* A namespace maps roughly to a deployable: one app, or one family of server-rendered messages.
|
|
15
|
+
*/
|
|
16
|
+
export interface Namespace {
|
|
17
|
+
id: UUID;
|
|
18
|
+
/** Lowercase `[a-z0-9.-]`, e.g. `unibox-web`. Unique within the tenant. */
|
|
19
|
+
key: string;
|
|
20
|
+
/** What lives in here, for whoever has to decide where a new key belongs. */
|
|
21
|
+
description: Nullable<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Whether a release may include translations still in `draft`.
|
|
24
|
+
*
|
|
25
|
+
* Off by default. On for a namespace nobody reads in production yet, where requiring approval
|
|
26
|
+
* on every key means a translator cannot see their own work in the app.
|
|
27
|
+
*/
|
|
28
|
+
allowsDraftRelease: boolean;
|
|
29
|
+
messageCount: number;
|
|
30
|
+
/** Null until the namespace has been published once. */
|
|
31
|
+
latestReleaseVersion: Nullable<number>;
|
|
32
|
+
latestReleaseAt: Nullable<IsoDateTime>;
|
|
33
|
+
createdAt: IsoDateTime;
|
|
34
|
+
updatedAt: IsoDateTime;
|
|
35
|
+
}
|
|
36
|
+
/** `GET /api/v1/namespaces`. */
|
|
37
|
+
export type NamespacesPage = Paginated<Namespace>;
|
|
38
|
+
/** `POST /api/v1/namespaces`. */
|
|
39
|
+
export interface CreateNamespaceBody {
|
|
40
|
+
key: string;
|
|
41
|
+
description?: Nullable<string>;
|
|
42
|
+
allowsDraftRelease?: boolean;
|
|
43
|
+
}
|
|
44
|
+
/** `PATCH /api/v1/namespaces/:key`. The key itself is immutable — consumers pin it. */
|
|
45
|
+
export interface UpdateNamespaceBody {
|
|
46
|
+
description?: Nullable<string>;
|
|
47
|
+
allowsDraftRelease?: boolean;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* `GET /api/v1/namespaces/:key/progress` — how much is left to do, per locale.
|
|
51
|
+
*
|
|
52
|
+
* The one screen a translation project actually runs on. Answering it from the message listing
|
|
53
|
+
* would mean paging through every key to count what is missing.
|
|
54
|
+
*/
|
|
55
|
+
export interface NamespaceProgress {
|
|
56
|
+
namespaceKey: string;
|
|
57
|
+
messageCount: number;
|
|
58
|
+
locales: LocaleProgress[];
|
|
59
|
+
}
|
|
60
|
+
export interface LocaleProgress {
|
|
61
|
+
localeCode: string;
|
|
62
|
+
approved: number;
|
|
63
|
+
needsReview: number;
|
|
64
|
+
draft: number;
|
|
65
|
+
missing: number;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=namespace.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace.type.d.ts","sourceRoot":"","sources":["../../../../src/api/localization/namespace.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,IAAI,CAAC;IAET,2EAA2E;IAC3E,GAAG,EAAE,MAAM,CAAC;IAEZ,6EAA6E;IAC7E,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE9B;;;;;OAKG;IACH,kBAAkB,EAAE,OAAO,CAAC;IAE5B,YAAY,EAAE,MAAM,CAAC;IAErB,wDAAwD;IACxD,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,eAAe,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IAEvC,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,EAAE,WAAW,CAAC;CAC1B;AAED,gCAAgC;AAChC,MAAM,MAAM,cAAc,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;AAElD,iCAAiC;AACjC,MAAM,WAAW,mBAAmB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,uFAAuF;AACvF,MAAM,WAAW,mBAAmB;IAChC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace.type.js","sourceRoot":"","sources":["../../../../src/api/localization/namespace.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { IsoDateTime } from '../../type/iso-date-time.type.js';
|
|
2
|
+
import type { Nullable } from '../../type/nil.type.js';
|
|
3
|
+
import type { Paginated } from '../../type/paginated.type.js';
|
|
4
|
+
import type { UUID } from '../../type/uuid.type.js';
|
|
5
|
+
/**
|
|
6
|
+
* An immutable snapshot of one namespace, at every active locale, at one moment.
|
|
7
|
+
*
|
|
8
|
+
* **This is what makes the service safe to depend on.** Without it, editing a translation changes
|
|
9
|
+
* production text the instant it is saved — so a translator experimenting at 2am is a deploy, an
|
|
10
|
+
* unfinished sentence is an outage, and there is no way to answer "what did this say last
|
|
11
|
+
* Tuesday". With it, editing is free and publishing is the decision, gated by its own permission.
|
|
12
|
+
*
|
|
13
|
+
* The snapshot is stored in full rather than reconstructed from the translation rows by
|
|
14
|
+
* timestamp. Reconstruction sounds cheaper and is wrong: a message archived after the release, or
|
|
15
|
+
* a variable renamed, changes what the reconstruction produces, so a consumer pinned to version 3
|
|
16
|
+
* would silently get different bytes next month.
|
|
17
|
+
*/
|
|
18
|
+
export interface Release {
|
|
19
|
+
id: UUID;
|
|
20
|
+
namespaceId: UUID;
|
|
21
|
+
namespaceKey: string;
|
|
22
|
+
/** Monotonic per namespace, starting at 1. What a consumer pins. */
|
|
23
|
+
version: number;
|
|
24
|
+
/** What changed and why, for whoever reads the history. */
|
|
25
|
+
notes: Nullable<string>;
|
|
26
|
+
/** Locales the snapshot contains — the active ones at publish time, not necessarily now. */
|
|
27
|
+
localeCodes: string[];
|
|
28
|
+
messageCount: number;
|
|
29
|
+
/** Null when published by a service principal. */
|
|
30
|
+
publishedByUserId: Nullable<UUID>;
|
|
31
|
+
publishedAt: IsoDateTime;
|
|
32
|
+
}
|
|
33
|
+
/** `GET /api/v1/namespaces/:key/releases`. Newest first. */
|
|
34
|
+
export type ReleasesPage = Paginated<Release>;
|
|
35
|
+
/** `POST /api/v1/namespaces/:key/releases`. */
|
|
36
|
+
export interface PublishReleaseBody {
|
|
37
|
+
notes?: Nullable<string>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* `GET /api/v1/namespaces/:key/releases/preview` — what publishing right now would change.
|
|
41
|
+
*
|
|
42
|
+
* Shown before the button is pressed. A publish is irreversible in the sense that matters — the
|
|
43
|
+
* consumers pull it — so the operator gets to see the diff first rather than discovering it in
|
|
44
|
+
* production.
|
|
45
|
+
*/
|
|
46
|
+
export interface ReleaseDiff {
|
|
47
|
+
namespaceKey: string;
|
|
48
|
+
/** The version this would become. */
|
|
49
|
+
nextVersion: number;
|
|
50
|
+
/** Null when nothing has been published yet, in which case everything reads as added. */
|
|
51
|
+
previousVersion: Nullable<number>;
|
|
52
|
+
entries: ReleaseDiffEntry[];
|
|
53
|
+
/**
|
|
54
|
+
* Messages with no publishable translation in a locale that is active.
|
|
55
|
+
*
|
|
56
|
+
* Not an error — a release ships with gaps and the consumer falls back. It is surfaced
|
|
57
|
+
* because shipping a gap should be a choice someone made, not one they made by not looking.
|
|
58
|
+
*/
|
|
59
|
+
untranslated: UntranslatedEntry[];
|
|
60
|
+
}
|
|
61
|
+
export interface ReleaseDiffEntry {
|
|
62
|
+
messageKey: string;
|
|
63
|
+
localeCode: string;
|
|
64
|
+
change: 'added' | 'changed' | 'removed';
|
|
65
|
+
previousValue: Nullable<string>;
|
|
66
|
+
nextValue: Nullable<string>;
|
|
67
|
+
}
|
|
68
|
+
export interface UntranslatedEntry {
|
|
69
|
+
messageKey: string;
|
|
70
|
+
localeCode: string;
|
|
71
|
+
/** Where the fallback chain lands, or null if it falls off the end and the key renders raw. */
|
|
72
|
+
fallsBackTo: Nullable<string>;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=release.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release.type.d.ts","sourceRoot":"","sources":["../../../../src/api/localization/release.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,OAAO;IACpB,EAAE,EAAE,IAAI,CAAC;IAET,WAAW,EAAE,IAAI,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IAErB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAEhB,2DAA2D;IAC3D,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAExB,4FAA4F;IAC5F,WAAW,EAAE,MAAM,EAAE,CAAC;IAEtB,YAAY,EAAE,MAAM,CAAC;IAErB,kDAAkD;IAClD,iBAAiB,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,WAAW,EAAE,WAAW,CAAC;CAC5B;AAED,4DAA4D;AAC5D,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;AAE9C,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IAC/B,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IACxB,YAAY,EAAE,MAAM,CAAC;IAErB,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IAEpB,yFAAyF;IACzF,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAElC,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAE5B;;;;;OAKG;IACH,YAAY,EAAE,iBAAiB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,gBAAgB;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACxC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,+FAA+F;IAC/F,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release.type.js","sourceRoot":"","sources":["../../../../src/api/localization/release.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Nullable } from '../../type/nil.type.js';
|
|
2
|
+
/**
|
|
3
|
+
* `POST /api/v1/render` — resolve and format messages server-side.
|
|
4
|
+
*
|
|
5
|
+
* The counterpart to {@link TranslationBundle}, for the case a bundle cannot serve: text produced
|
|
6
|
+
* on a server, where there is no compiled app to bake strings into and the target locale belongs
|
|
7
|
+
* to whoever will read the message rather than whoever is making the request. An OTP body, an
|
|
8
|
+
* invoice line, an order confirmation.
|
|
9
|
+
*
|
|
10
|
+
* **Batched, because the caller almost always needs several.** An invoice email is a subject, a
|
|
11
|
+
* greeting, six line labels and a footer, and one HTTP round trip per string would put this
|
|
12
|
+
* service on the latency path of every email the platform sends.
|
|
13
|
+
*/
|
|
14
|
+
export interface RenderBody {
|
|
15
|
+
/** BCP-47. Falls back through the locale chain when this one has no translation. */
|
|
16
|
+
localeCode: string;
|
|
17
|
+
items: RenderItem[];
|
|
18
|
+
}
|
|
19
|
+
export interface RenderItem {
|
|
20
|
+
namespaceKey: string;
|
|
21
|
+
messageKey: string;
|
|
22
|
+
/**
|
|
23
|
+
* Values for the message's declared placeholders.
|
|
24
|
+
*
|
|
25
|
+
* A missing one is an error rather than an empty substitution: an OTP that renders as
|
|
26
|
+
* "Your code is " is worse than an error, because it is sent.
|
|
27
|
+
*/
|
|
28
|
+
variables?: Record<string, string | number>;
|
|
29
|
+
}
|
|
30
|
+
export interface RenderResult {
|
|
31
|
+
items: RenderedMessage[];
|
|
32
|
+
}
|
|
33
|
+
export interface RenderedMessage {
|
|
34
|
+
namespaceKey: string;
|
|
35
|
+
messageKey: string;
|
|
36
|
+
/** The locale actually used, which is not necessarily the one asked for. */
|
|
37
|
+
localeCode: string;
|
|
38
|
+
/** Formatted for {@link localeCode} — plural branches taken, numbers and dates localised. */
|
|
39
|
+
value: string;
|
|
40
|
+
/**
|
|
41
|
+
* True when the requested locale had nothing and the chain supplied this.
|
|
42
|
+
*
|
|
43
|
+
* Returned rather than hidden so a caller that must not send a half-localised message — an
|
|
44
|
+
* OTP, a legal notice — can decide for itself rather than discovering it from a customer.
|
|
45
|
+
*/
|
|
46
|
+
isFallback: boolean;
|
|
47
|
+
/** The release the value came from. Null for a message that has never been published. */
|
|
48
|
+
version: Nullable<number>;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=render.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.type.d.ts","sourceRoot":"","sources":["../../../../src/api/localization/render.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,UAAU;IACvB,oFAAoF;IACpF,UAAU,EAAE,MAAM,CAAC;IAEnB,KAAK,EAAE,UAAU,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IAEnB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IAEnB,6FAA6F;IAC7F,KAAK,EAAE,MAAM,CAAC;IAEd;;;;;OAKG;IACH,UAAU,EAAE,OAAO,CAAC;IAEpB,yFAAyF;IACzF,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.type.js","sourceRoot":"","sources":["../../../../src/api/localization/render.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a single translation stands, for one message in one locale.
|
|
3
|
+
*
|
|
4
|
+
* The states exist to answer one question a translator asks constantly — *what is left to do* —
|
|
5
|
+
* and they are ordered by how much trust a reader may put in the value.
|
|
6
|
+
*
|
|
7
|
+
* `MISSING` is **not stored**. A translation row exists only once someone has written something,
|
|
8
|
+
* so "missing" is the absence of a row projected into this enum by the read side. Storing it
|
|
9
|
+
* would mean writing a row per message per locale the moment a key is created, which turns
|
|
10
|
+
* adding one key into N writes and makes "has anyone touched this?" unanswerable.
|
|
11
|
+
*/
|
|
12
|
+
export declare enum TranslationStatus {
|
|
13
|
+
/** No row exists. Synthesised by the read side so a listing can be filtered on it. */
|
|
14
|
+
MISSING = "missing",
|
|
15
|
+
/** Someone is working on it. Excluded from a release unless the namespace allows drafts. */
|
|
16
|
+
DRAFT = "draft",
|
|
17
|
+
/**
|
|
18
|
+
* Written, but the source text changed underneath it.
|
|
19
|
+
*
|
|
20
|
+
* Set automatically when the source-locale value of the same message is edited — an English
|
|
21
|
+
* label reworded from `Archive` to `Delete` leaves a Georgian translation that is
|
|
22
|
+
* grammatically fine and now says the wrong thing. Nothing else in the system can catch that,
|
|
23
|
+
* because the translation is still valid text.
|
|
24
|
+
*/
|
|
25
|
+
NEEDS_REVIEW = "needs-review",
|
|
26
|
+
/** Reviewed and publishable. */
|
|
27
|
+
APPROVED = "approved"
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=translation-status.enum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation-status.enum.d.ts","sourceRoot":"","sources":["../../../../src/api/localization/translation-status.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,oBAAY,iBAAiB;IACzB,sFAAsF;IACtF,OAAO,YAAY;IAEnB,4FAA4F;IAC5F,KAAK,UAAU;IAEf;;;;;;;OAOG;IACH,YAAY,iBAAiB;IAE7B,gCAAgC;IAChC,QAAQ,aAAa;CACxB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a single translation stands, for one message in one locale.
|
|
3
|
+
*
|
|
4
|
+
* The states exist to answer one question a translator asks constantly — *what is left to do* —
|
|
5
|
+
* and they are ordered by how much trust a reader may put in the value.
|
|
6
|
+
*
|
|
7
|
+
* `MISSING` is **not stored**. A translation row exists only once someone has written something,
|
|
8
|
+
* so "missing" is the absence of a row projected into this enum by the read side. Storing it
|
|
9
|
+
* would mean writing a row per message per locale the moment a key is created, which turns
|
|
10
|
+
* adding one key into N writes and makes "has anyone touched this?" unanswerable.
|
|
11
|
+
*/
|
|
12
|
+
export var TranslationStatus;
|
|
13
|
+
(function (TranslationStatus) {
|
|
14
|
+
/** No row exists. Synthesised by the read side so a listing can be filtered on it. */
|
|
15
|
+
TranslationStatus["MISSING"] = "missing";
|
|
16
|
+
/** Someone is working on it. Excluded from a release unless the namespace allows drafts. */
|
|
17
|
+
TranslationStatus["DRAFT"] = "draft";
|
|
18
|
+
/**
|
|
19
|
+
* Written, but the source text changed underneath it.
|
|
20
|
+
*
|
|
21
|
+
* Set automatically when the source-locale value of the same message is edited — an English
|
|
22
|
+
* label reworded from `Archive` to `Delete` leaves a Georgian translation that is
|
|
23
|
+
* grammatically fine and now says the wrong thing. Nothing else in the system can catch that,
|
|
24
|
+
* because the translation is still valid text.
|
|
25
|
+
*/
|
|
26
|
+
TranslationStatus["NEEDS_REVIEW"] = "needs-review";
|
|
27
|
+
/** Reviewed and publishable. */
|
|
28
|
+
TranslationStatus["APPROVED"] = "approved";
|
|
29
|
+
})(TranslationStatus || (TranslationStatus = {}));
|
|
30
|
+
//# sourceMappingURL=translation-status.enum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation-status.enum.js","sourceRoot":"","sources":["../../../../src/api/localization/translation-status.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAN,IAAY,iBAmBX;AAnBD,WAAY,iBAAiB;IACzB,sFAAsF;IACtF,wCAAmB,CAAA;IAEnB,4FAA4F;IAC5F,oCAAe,CAAA;IAEf;;;;;;;OAOG;IACH,kDAA6B,CAAA;IAE7B,gCAAgC;IAChC,0CAAqB,CAAA;AACzB,CAAC,EAnBW,iBAAiB,KAAjB,iBAAiB,QAmB5B"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { IsoDateTime } from '../../type/iso-date-time.type.js';
|
|
2
|
+
import type { Nullable } from '../../type/nil.type.js';
|
|
3
|
+
import type { UUID } from '../../type/uuid.type.js';
|
|
4
|
+
import type { TranslationStatus } from './translation-status.enum.js';
|
|
5
|
+
/**
|
|
6
|
+
* One message, in one locale.
|
|
7
|
+
*
|
|
8
|
+
* `value` is **ICU MessageFormat**, not a template string with our own placeholder syntax. That
|
|
9
|
+
* choice is the reason this service can be correct in Russian: Russian selects between `one`,
|
|
10
|
+
* `few`, `many` and `other` on the *numeric* value, and a hand-rolled `count === 1 ? a : b` is
|
|
11
|
+
* wrong for 2, 5 and 21 in ways an English-speaking reviewer cannot see. ICU already encodes
|
|
12
|
+
* every locale's plural rules, so the translation carries the branch and the code carries none.
|
|
13
|
+
*/
|
|
14
|
+
export interface Translation {
|
|
15
|
+
id: UUID;
|
|
16
|
+
messageId: UUID;
|
|
17
|
+
messageKey: string;
|
|
18
|
+
namespaceKey: string;
|
|
19
|
+
localeCode: string;
|
|
20
|
+
/** ICU MessageFormat. Validated against the message's declared variables on every write. */
|
|
21
|
+
value: string;
|
|
22
|
+
status: TranslationStatus;
|
|
23
|
+
/** Null when written by a service principal rather than a person. */
|
|
24
|
+
updatedByUserId: Nullable<UUID>;
|
|
25
|
+
createdAt: IsoDateTime;
|
|
26
|
+
updatedAt: IsoDateTime;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* `PUT /api/v1/namespaces/:key/messages/:messageKey/translations/:localeCode`.
|
|
30
|
+
*
|
|
31
|
+
* An upsert rather than create/update, because a translator does not know or care whether a row
|
|
32
|
+
* exists — `MISSING` is the absence of one, and making them discover that through a 404 would be
|
|
33
|
+
* exposing our storage decision as a workflow step.
|
|
34
|
+
*/
|
|
35
|
+
export interface UpsertTranslationBody {
|
|
36
|
+
value: string;
|
|
37
|
+
/**
|
|
38
|
+
* Defaults to `DRAFT`. Setting `APPROVED` requires the same permission as any other write —
|
|
39
|
+
* approving is not separately gated, because the gate that matters is publishing.
|
|
40
|
+
*/
|
|
41
|
+
status?: TranslationStatus;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* `POST /api/v1/namespaces/:key/translations/bulk` — one locale, many messages.
|
|
45
|
+
*
|
|
46
|
+
* The entries that validate are written together in one transaction; the ones that do not are
|
|
47
|
+
* reported back. See {@link BulkUpsertTranslationsResult} for why it is not all-or-nothing.
|
|
48
|
+
*/
|
|
49
|
+
export interface BulkUpsertTranslationsBody {
|
|
50
|
+
localeCode: string;
|
|
51
|
+
entries: BulkTranslationEntry[];
|
|
52
|
+
}
|
|
53
|
+
export interface BulkTranslationEntry {
|
|
54
|
+
messageKey: string;
|
|
55
|
+
value: string;
|
|
56
|
+
status?: TranslationStatus;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The result of a bulk write.
|
|
60
|
+
*
|
|
61
|
+
* Rejections are returned per entry instead of failing the whole batch, because the usual caller
|
|
62
|
+
* is an import of a file a translator produced elsewhere: refusing 400 good rows over one bad
|
|
63
|
+
* placeholder means they have no way to make progress, and the failure they must fix is
|
|
64
|
+
* precisely the one this names.
|
|
65
|
+
*/
|
|
66
|
+
export interface BulkUpsertTranslationsResult {
|
|
67
|
+
written: number;
|
|
68
|
+
rejected: RejectedTranslation[];
|
|
69
|
+
}
|
|
70
|
+
export interface RejectedTranslation {
|
|
71
|
+
messageKey: string;
|
|
72
|
+
reason: string;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=translation.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation.type.d.ts","sourceRoot":"","sources":["../../../../src/api/localization/translation.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,IAAI,CAAC;IAET,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IAEnB,4FAA4F;IAC5F,KAAK,EAAE,MAAM,CAAC;IAEd,MAAM,EAAE,iBAAiB,CAAC;IAE1B,qEAAqE;IACrE,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEhC,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,EAAE,WAAW,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,oBAAoB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,oBAAoB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,4BAA4B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,mBAAmB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation.type.js","sourceRoot":"","sources":["../../../../src/api/localization/translation.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kind of value a message placeholder expects.
|
|
3
|
+
*
|
|
4
|
+
* **Declared on the message, not inferred from the text.** A translation is rejected at write
|
|
5
|
+
* time if its placeholders do not match the message's declared set, which is the single check
|
|
6
|
+
* that stops a Russian string shipping with a literal `{orderNumber}` in front of a customer.
|
|
7
|
+
* Inferring the set from whichever locale happened to be written first would make the check
|
|
8
|
+
* circular — the first typo becomes the specification.
|
|
9
|
+
*
|
|
10
|
+
* The type is what tells a renderer how to format the value and what an editor should show as an
|
|
11
|
+
* example. It also tells a translator what they are allowed to do with it: `PLURAL` may be
|
|
12
|
+
* branched on, `STRING` may not.
|
|
13
|
+
*/
|
|
14
|
+
export declare enum VariableType {
|
|
15
|
+
/** Substituted verbatim. `{name}` */
|
|
16
|
+
STRING = "string",
|
|
17
|
+
/** Formatted with `Intl.NumberFormat` for the target locale. `{count, number}` */
|
|
18
|
+
NUMBER = "number",
|
|
19
|
+
/** Formatted with `Intl.DateTimeFormat` for the target locale. `{dueAt, date, medium}` */
|
|
20
|
+
DATE = "date",
|
|
21
|
+
/**
|
|
22
|
+
* A count the translation branches on: `{n, plural, one {...} few {...} other {...}}`.
|
|
23
|
+
*
|
|
24
|
+
* Distinct from `NUMBER` because the plural categories a locale needs are not a formatting
|
|
25
|
+
* choice. Russian has `one`/`few`/`many`/`other` and English has `one`/`other`, so a
|
|
26
|
+
* translation written by substituting a number and appending an "s" is wrong in Russian in a
|
|
27
|
+
* way no reviewer of the English can see.
|
|
28
|
+
*/
|
|
29
|
+
PLURAL = "plural",
|
|
30
|
+
/**
|
|
31
|
+
* A closed set the translation branches on: `{gender, select, female {...} other {...}}`.
|
|
32
|
+
*
|
|
33
|
+
* Georgian and Russian inflect around the subject where English does not, so a sentence that
|
|
34
|
+
* needs no branch in the source locale needs one in the target. The declared options are the
|
|
35
|
+
* contract — a translation branching on an option the message never declared is rejected.
|
|
36
|
+
*/
|
|
37
|
+
SELECT = "select"
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=variable-type.enum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variable-type.enum.d.ts","sourceRoot":"","sources":["../../../../src/api/localization/variable-type.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,oBAAY,YAAY;IACpB,qCAAqC;IACrC,MAAM,WAAW;IAEjB,kFAAkF;IAClF,MAAM,WAAW;IAEjB,0FAA0F;IAC1F,IAAI,SAAS;IAEb;;;;;;;OAOG;IACH,MAAM,WAAW;IAEjB;;;;;;OAMG;IACH,MAAM,WAAW;CACpB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kind of value a message placeholder expects.
|
|
3
|
+
*
|
|
4
|
+
* **Declared on the message, not inferred from the text.** A translation is rejected at write
|
|
5
|
+
* time if its placeholders do not match the message's declared set, which is the single check
|
|
6
|
+
* that stops a Russian string shipping with a literal `{orderNumber}` in front of a customer.
|
|
7
|
+
* Inferring the set from whichever locale happened to be written first would make the check
|
|
8
|
+
* circular — the first typo becomes the specification.
|
|
9
|
+
*
|
|
10
|
+
* The type is what tells a renderer how to format the value and what an editor should show as an
|
|
11
|
+
* example. It also tells a translator what they are allowed to do with it: `PLURAL` may be
|
|
12
|
+
* branched on, `STRING` may not.
|
|
13
|
+
*/
|
|
14
|
+
export var VariableType;
|
|
15
|
+
(function (VariableType) {
|
|
16
|
+
/** Substituted verbatim. `{name}` */
|
|
17
|
+
VariableType["STRING"] = "string";
|
|
18
|
+
/** Formatted with `Intl.NumberFormat` for the target locale. `{count, number}` */
|
|
19
|
+
VariableType["NUMBER"] = "number";
|
|
20
|
+
/** Formatted with `Intl.DateTimeFormat` for the target locale. `{dueAt, date, medium}` */
|
|
21
|
+
VariableType["DATE"] = "date";
|
|
22
|
+
/**
|
|
23
|
+
* A count the translation branches on: `{n, plural, one {...} few {...} other {...}}`.
|
|
24
|
+
*
|
|
25
|
+
* Distinct from `NUMBER` because the plural categories a locale needs are not a formatting
|
|
26
|
+
* choice. Russian has `one`/`few`/`many`/`other` and English has `one`/`other`, so a
|
|
27
|
+
* translation written by substituting a number and appending an "s" is wrong in Russian in a
|
|
28
|
+
* way no reviewer of the English can see.
|
|
29
|
+
*/
|
|
30
|
+
VariableType["PLURAL"] = "plural";
|
|
31
|
+
/**
|
|
32
|
+
* A closed set the translation branches on: `{gender, select, female {...} other {...}}`.
|
|
33
|
+
*
|
|
34
|
+
* Georgian and Russian inflect around the subject where English does not, so a sentence that
|
|
35
|
+
* needs no branch in the source locale needs one in the target. The declared options are the
|
|
36
|
+
* contract — a translation branching on an option the message never declared is rejected.
|
|
37
|
+
*/
|
|
38
|
+
VariableType["SELECT"] = "select";
|
|
39
|
+
})(VariableType || (VariableType = {}));
|
|
40
|
+
//# sourceMappingURL=variable-type.enum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variable-type.enum.js","sourceRoot":"","sources":["../../../../src/api/localization/variable-type.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAN,IAAY,YA4BX;AA5BD,WAAY,YAAY;IACpB,qCAAqC;IACrC,iCAAiB,CAAA;IAEjB,kFAAkF;IAClF,iCAAiB,CAAA;IAEjB,0FAA0F;IAC1F,6BAAa,CAAA;IAEb;;;;;;;OAOG;IACH,iCAAiB,CAAA;IAEjB;;;;;;OAMG;IACH,iCAAiB,CAAA;AACrB,CAAC,EA5BW,YAAY,KAAZ,YAAY,QA4BvB"}
|
|
@@ -228,7 +228,50 @@ export declare enum UserPermission {
|
|
|
228
228
|
/** Read tenant invoices and their immutable line items. */
|
|
229
229
|
BILLING_INVOICE_READ = "billing:invoice:read",
|
|
230
230
|
/** Create, finalize or void tenant invoices. */
|
|
231
|
-
BILLING_INVOICE_MANAGE = "billing:invoice:manage"
|
|
231
|
+
BILLING_INVOICE_MANAGE = "billing:invoice:manage",
|
|
232
|
+
/**
|
|
233
|
+
* Read locales, namespaces, keys, translations and release history — and pull a published
|
|
234
|
+
* bundle, which is how a build gets its strings.
|
|
235
|
+
*
|
|
236
|
+
* One read permission over all of it rather than one per aggregate: none of it is secret. It
|
|
237
|
+
* is text written to be shown to users, and a key list with the values hidden is unusable
|
|
238
|
+
* for the review this permission exists to enable.
|
|
239
|
+
*/
|
|
240
|
+
LOCALIZATION_READ = "localization:read",
|
|
241
|
+
/**
|
|
242
|
+
* Define the structure — locales, namespaces, message keys and their declared variables.
|
|
243
|
+
*
|
|
244
|
+
* The engineer's half, and the sharper one despite sounding like configuration. A message key
|
|
245
|
+
* is compiled into an app (`t('inbox.title')`), so archiving one breaks a screen that already
|
|
246
|
+
* shipped; and editing a message's declared variables invalidates every translation of it in
|
|
247
|
+
* every language at once. A translator must not be able to do either by accident.
|
|
248
|
+
*/
|
|
249
|
+
LOCALIZATION_MESSAGE_MANAGE = "localization:message:manage",
|
|
250
|
+
/**
|
|
251
|
+
* Write translation values.
|
|
252
|
+
*
|
|
253
|
+
* The translator's whole job, and deliberately the *only* thing it grants. This is the
|
|
254
|
+
* permission handed to an outside contractor or an agency, so it must be safe to hand to
|
|
255
|
+
* someone with no stake in the codebase: they can rewrite every string in the product and
|
|
256
|
+
* cannot add a key, remove one, or put a word of it in front of a customer.
|
|
257
|
+
*/
|
|
258
|
+
LOCALIZATION_TRANSLATE = "localization:translate",
|
|
259
|
+
/**
|
|
260
|
+
* Cut a release — the act that actually changes what users read.
|
|
261
|
+
*
|
|
262
|
+
* Separate from `LOCALIZATION_TRANSLATE` for the reason the release aggregate exists at all:
|
|
263
|
+
* editing has to be free so a translator can work in the tool instead of in a spreadsheet,
|
|
264
|
+
* which is only tolerable if editing is not shipping. This is the gate between the two.
|
|
265
|
+
*/
|
|
266
|
+
LOCALIZATION_PUBLISH = "localization:publish",
|
|
267
|
+
/**
|
|
268
|
+
* Resolve and format messages at runtime through `POST /render`.
|
|
269
|
+
*
|
|
270
|
+
* A service permission. `iveri-messaging-api` rendering an OTP body and `iveri-billing-api`
|
|
271
|
+
* rendering an invoice line hold this and nothing else here — they have no reason to read the
|
|
272
|
+
* key catalogue, and separating it keeps a compromised worker from enumerating it.
|
|
273
|
+
*/
|
|
274
|
+
LOCALIZATION_RENDER = "localization:render"
|
|
232
275
|
}
|
|
233
276
|
/**
|
|
234
277
|
* Every member, for seeding the owner role and validating custom-role input.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-permission.enum.d.ts","sourceRoot":"","sources":["../../../src/enum/user-permission.enum.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"user-permission.enum.d.ts","sourceRoot":"","sources":["../../../src/enum/user-permission.enum.ts"],"names":[],"mappings":"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"}
|
|
@@ -266,6 +266,56 @@ export var UserPermission;
|
|
|
266
266
|
UserPermission["BILLING_INVOICE_READ"] = "billing:invoice:read";
|
|
267
267
|
/** Create, finalize or void tenant invoices. */
|
|
268
268
|
UserPermission["BILLING_INVOICE_MANAGE"] = "billing:invoice:manage";
|
|
269
|
+
// ══ iveri-localization-api ══════════════════════════════════════════════
|
|
270
|
+
//
|
|
271
|
+
// Four permissions for what looks like one job, because translation has four distinct
|
|
272
|
+
// audiences and the whole point of the service is that they are not the same person. An
|
|
273
|
+
// engineer defines keys, a translator writes values, a reviewer decides a language is ready,
|
|
274
|
+
// and a service reads the result. Collapsing them means a contractor hired to translate a
|
|
275
|
+
// panel into Georgian can delete the keys the panel is built from.
|
|
276
|
+
/**
|
|
277
|
+
* Read locales, namespaces, keys, translations and release history — and pull a published
|
|
278
|
+
* bundle, which is how a build gets its strings.
|
|
279
|
+
*
|
|
280
|
+
* One read permission over all of it rather than one per aggregate: none of it is secret. It
|
|
281
|
+
* is text written to be shown to users, and a key list with the values hidden is unusable
|
|
282
|
+
* for the review this permission exists to enable.
|
|
283
|
+
*/
|
|
284
|
+
UserPermission["LOCALIZATION_READ"] = "localization:read";
|
|
285
|
+
/**
|
|
286
|
+
* Define the structure — locales, namespaces, message keys and their declared variables.
|
|
287
|
+
*
|
|
288
|
+
* The engineer's half, and the sharper one despite sounding like configuration. A message key
|
|
289
|
+
* is compiled into an app (`t('inbox.title')`), so archiving one breaks a screen that already
|
|
290
|
+
* shipped; and editing a message's declared variables invalidates every translation of it in
|
|
291
|
+
* every language at once. A translator must not be able to do either by accident.
|
|
292
|
+
*/
|
|
293
|
+
UserPermission["LOCALIZATION_MESSAGE_MANAGE"] = "localization:message:manage";
|
|
294
|
+
/**
|
|
295
|
+
* Write translation values.
|
|
296
|
+
*
|
|
297
|
+
* The translator's whole job, and deliberately the *only* thing it grants. This is the
|
|
298
|
+
* permission handed to an outside contractor or an agency, so it must be safe to hand to
|
|
299
|
+
* someone with no stake in the codebase: they can rewrite every string in the product and
|
|
300
|
+
* cannot add a key, remove one, or put a word of it in front of a customer.
|
|
301
|
+
*/
|
|
302
|
+
UserPermission["LOCALIZATION_TRANSLATE"] = "localization:translate";
|
|
303
|
+
/**
|
|
304
|
+
* Cut a release — the act that actually changes what users read.
|
|
305
|
+
*
|
|
306
|
+
* Separate from `LOCALIZATION_TRANSLATE` for the reason the release aggregate exists at all:
|
|
307
|
+
* editing has to be free so a translator can work in the tool instead of in a spreadsheet,
|
|
308
|
+
* which is only tolerable if editing is not shipping. This is the gate between the two.
|
|
309
|
+
*/
|
|
310
|
+
UserPermission["LOCALIZATION_PUBLISH"] = "localization:publish";
|
|
311
|
+
/**
|
|
312
|
+
* Resolve and format messages at runtime through `POST /render`.
|
|
313
|
+
*
|
|
314
|
+
* A service permission. `iveri-messaging-api` rendering an OTP body and `iveri-billing-api`
|
|
315
|
+
* rendering an invoice line hold this and nothing else here — they have no reason to read the
|
|
316
|
+
* key catalogue, and separating it keeps a compromised worker from enumerating it.
|
|
317
|
+
*/
|
|
318
|
+
UserPermission["LOCALIZATION_RENDER"] = "localization:render";
|
|
269
319
|
})(UserPermission || (UserPermission = {}));
|
|
270
320
|
/**
|
|
271
321
|
* Every member, for seeding the owner role and validating custom-role input.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-permission.enum.js","sourceRoot":"","sources":["../../../src/enum/user-permission.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"user-permission.enum.js","sourceRoot":"","sources":["../../../src/enum/user-permission.enum.ts"],"names":[],"mappings":"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"}
|