@voxendar/shared 0.2.0 → 0.4.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/dist/capture/audio.d.ts +16 -0
- package/dist/capture/audio.d.ts.map +1 -0
- package/dist/capture/audio.js +22 -0
- package/dist/capture/audio.js.map +1 -0
- package/dist/capture/fields.d.ts +87 -0
- package/dist/capture/fields.d.ts.map +1 -0
- package/dist/capture/fields.js +171 -0
- package/dist/capture/fields.js.map +1 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/i18n/copy/ar-SA.d.ts +176 -0
- package/dist/i18n/copy/ar-SA.d.ts.map +1 -0
- package/dist/i18n/copy/ar-SA.js +194 -0
- package/dist/i18n/copy/ar-SA.js.map +1 -0
- package/dist/i18n/copy/de-DE.d.ts +176 -0
- package/dist/i18n/copy/de-DE.d.ts.map +1 -0
- package/dist/i18n/copy/de-DE.js +196 -0
- package/dist/i18n/copy/de-DE.js.map +1 -0
- package/dist/i18n/copy/en-US.d.ts +190 -0
- package/dist/i18n/copy/en-US.d.ts.map +1 -0
- package/dist/i18n/copy/en-US.js +223 -0
- package/dist/i18n/copy/en-US.js.map +1 -0
- package/dist/i18n/copy/es-MX.d.ts +176 -0
- package/dist/i18n/copy/es-MX.d.ts.map +1 -0
- package/dist/i18n/copy/es-MX.js +189 -0
- package/dist/i18n/copy/es-MX.js.map +1 -0
- package/dist/i18n/copy/fr-FR.d.ts +176 -0
- package/dist/i18n/copy/fr-FR.d.ts.map +1 -0
- package/dist/i18n/copy/fr-FR.js +190 -0
- package/dist/i18n/copy/fr-FR.js.map +1 -0
- package/dist/i18n/copy/he-IL.d.ts +176 -0
- package/dist/i18n/copy/he-IL.d.ts.map +1 -0
- package/dist/i18n/copy/he-IL.js +190 -0
- package/dist/i18n/copy/he-IL.js.map +1 -0
- package/dist/i18n/copy/hi-IN.d.ts +176 -0
- package/dist/i18n/copy/hi-IN.d.ts.map +1 -0
- package/dist/i18n/copy/hi-IN.js +191 -0
- package/dist/i18n/copy/hi-IN.js.map +1 -0
- package/dist/i18n/copy/ja-JP.d.ts +176 -0
- package/dist/i18n/copy/ja-JP.d.ts.map +1 -0
- package/dist/i18n/copy/ja-JP.js +192 -0
- package/dist/i18n/copy/ja-JP.js.map +1 -0
- package/dist/i18n/copy/ko-KR.d.ts +176 -0
- package/dist/i18n/copy/ko-KR.d.ts.map +1 -0
- package/dist/i18n/copy/ko-KR.js +192 -0
- package/dist/i18n/copy/ko-KR.js.map +1 -0
- package/dist/i18n/copy/pt-BR.d.ts +176 -0
- package/dist/i18n/copy/pt-BR.d.ts.map +1 -0
- package/dist/i18n/copy/pt-BR.js +187 -0
- package/dist/i18n/copy/pt-BR.js.map +1 -0
- package/dist/i18n/copy/ru-RU.d.ts +176 -0
- package/dist/i18n/copy/ru-RU.d.ts.map +1 -0
- package/dist/i18n/copy/ru-RU.js +191 -0
- package/dist/i18n/copy/ru-RU.js.map +1 -0
- package/dist/i18n/copy/zh-CN.d.ts +176 -0
- package/dist/i18n/copy/zh-CN.d.ts.map +1 -0
- package/dist/i18n/copy/zh-CN.js +189 -0
- package/dist/i18n/copy/zh-CN.js.map +1 -0
- package/dist/i18n/copy/zh-TW.d.ts +176 -0
- package/dist/i18n/copy/zh-TW.d.ts.map +1 -0
- package/dist/i18n/copy/zh-TW.js +196 -0
- package/dist/i18n/copy/zh-TW.js.map +1 -0
- package/dist/i18n/rtl.d.ts +27 -0
- package/dist/i18n/rtl.d.ts.map +1 -0
- package/dist/i18n/rtl.js +47 -0
- package/dist/i18n/rtl.js.map +1 -0
- package/dist/i18n/server-messages.d.ts +56 -0
- package/dist/i18n/server-messages.d.ts.map +1 -0
- package/dist/i18n/server-messages.js +163 -0
- package/dist/i18n/server-messages.js.map +1 -0
- package/dist/i18n/templates.d.ts +5 -0
- package/dist/i18n/templates.d.ts.map +1 -1
- package/dist/i18n/templates.js +5 -0
- package/dist/i18n/templates.js.map +1 -1
- package/dist/i18n/ui.d.ts +85 -0
- package/dist/i18n/ui.d.ts.map +1 -0
- package/dist/i18n/ui.js +151 -0
- package/dist/i18n/ui.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/schemas/capture.d.ts +8 -0
- package/dist/schemas/capture.d.ts.map +1 -1
- package/dist/schemas/capture.js +6 -0
- package/dist/schemas/capture.js.map +1 -1
- package/dist/schemas/enums.d.ts +2 -0
- package/dist/schemas/enums.d.ts.map +1 -1
- package/package.json +8 -3
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UI copy (Milestone 1.9.7) — the mechanism behind the app's own words.
|
|
3
|
+
*
|
|
4
|
+
* Until this existed, `language` drove ASR, the LLM's output language, the spoken
|
|
5
|
+
* confirmation, the reminder templates and the voice ranking — and **nothing about the
|
|
6
|
+
* interface**. The M1.5 walkthrough showed the seam on screen: the confirmation was
|
|
7
|
+
* spoken in French (*"Demain, à quatorze heures… C'est bien ça ?"*) while the card's
|
|
8
|
+
* labels and its red `400` were English. This is that seam.
|
|
9
|
+
*
|
|
10
|
+
* Three properties are deliberate:
|
|
11
|
+
*
|
|
12
|
+
* 1. **The English table is the key set.** `UiKey` is derived from it (`./copy/en-US.ts`)
|
|
13
|
+
* and every other language is typed `Record<UiKey, string>`, so a missing key is a
|
|
14
|
+
* **compile error**, not a sentence that quietly turns English — the same rule the
|
|
15
|
+
* reminder templates enforce with a test, applied here by the type system.
|
|
16
|
+
* 2. **One file per language** in `./copy/`; this module is only the mechanism
|
|
17
|
+
* (resolution, lookup, interpolation, the two allowlists). A language is therefore
|
|
18
|
+
* added, reviewed, or handed to a translator on its own — and the tables live in
|
|
19
|
+
* `shared` rather than in the app because the server also writes sentences that reach
|
|
20
|
+
* the screen (`./server-messages.ts`, next door).
|
|
21
|
+
* 3. **Every string the member reads is in those tables**, including the labels that feel
|
|
22
|
+
* like data — card field names, the Today/Tomorrow chips, colour names, avatar names.
|
|
23
|
+
* A person should not read the app's sentence about their own event in a language they
|
|
24
|
+
* did not choose, and "Lavender — light periwinkle" is such a sentence.
|
|
25
|
+
*
|
|
26
|
+
* And nothing here falls back to English silently for a language we ship: see
|
|
27
|
+
* `PENDING_UI_LANGUAGES`, which names the ones still missing, and `ui.test.ts`, which
|
|
28
|
+
* asserts that list is exactly the gap between `SUPPORTED_LANGUAGES` and `UI_COPY`.
|
|
29
|
+
*/
|
|
30
|
+
import { SUPPORTED_LANGUAGES } from "../constants";
|
|
31
|
+
import { type CopyTable, type UiKey } from "./copy/en-US";
|
|
32
|
+
export type Language = (typeof SUPPORTED_LANGUAGES)[number];
|
|
33
|
+
export type { CopyTable, UiKey };
|
|
34
|
+
export type UiParams = Record<string, string | number>;
|
|
35
|
+
/**
|
|
36
|
+
* Keys where English is the right answer in *every* language: brand names, an example
|
|
37
|
+
* invite code, and a developer diagnostic. The guard both skips these and asserts they
|
|
38
|
+
* really do match English everywhere — which is why the list must stay short.
|
|
39
|
+
*/
|
|
40
|
+
export declare const UNTRANSLATED_BY_DESIGN: readonly UiKey[];
|
|
41
|
+
/**
|
|
42
|
+
* Keys where a *specific* language may legitimately coincide with English: French says
|
|
43
|
+
* *Date* and *Notes* exactly as English does, German says *Neutral* and *Person*. Keyed by
|
|
44
|
+
* language on purpose — a global allowlist would excuse a copy-paste in Spanish or Korean
|
|
45
|
+
* too, and the point of the guard is to catch exactly that.
|
|
46
|
+
*
|
|
47
|
+
* Adding an entry is a claim about that language, so it is reviewed like the copy is.
|
|
48
|
+
*/
|
|
49
|
+
export declare const MAY_READ_AS_ENGLISH: Readonly<Partial<Record<Language, readonly UiKey[]>>>;
|
|
50
|
+
/** The English table: the copy of record, and what every lookup falls back to. */
|
|
51
|
+
export declare const UI_COPY_EN: CopyTable;
|
|
52
|
+
/** Which language has which table. `en-US` is the floor; see `PENDING_UI_LANGUAGES`. */
|
|
53
|
+
export declare const UI_COPY: Partial<Record<Language, CopyTable>>;
|
|
54
|
+
/**
|
|
55
|
+
* Launch languages whose UI copy is not written yet. They fall back to English until their
|
|
56
|
+
* tables land — a decision the diff shows rather than a silent fallback, because the guard
|
|
57
|
+
* test asserts this list is exactly the gap between `SUPPORTED_LANGUAGES` and `UI_COPY`.
|
|
58
|
+
*
|
|
59
|
+
* **Empty since 2026-09-29**, when wave 2 filled the last nine tables. It stays exported,
|
|
60
|
+
* and the guard stays switched on, because the *thirteenth* language is the one this list
|
|
61
|
+
* exists for — and on **2026-10-21 that happened**: `zh-TW` arrived with its table in the
|
|
62
|
+
* same commit, so this list stayed empty. The mechanism was never needed; the guard still
|
|
63
|
+
* proved the gap was zero rather than assumed it.
|
|
64
|
+
*/
|
|
65
|
+
export declare const PENDING_UI_LANGUAGES: readonly Language[];
|
|
66
|
+
/**
|
|
67
|
+
* The mechanism. `resolveUiLanguage` deliberately mirrors `resolveTemplateKey` in
|
|
68
|
+
* `templates.ts`: exact tag → base language → `en-US`. Two tables with two different
|
|
69
|
+
* fallback policies would be a bug waiting for the first `pt-PT` member.
|
|
70
|
+
*/
|
|
71
|
+
export declare function resolveUiLanguage(language: string | null | undefined): Language | null;
|
|
72
|
+
/**
|
|
73
|
+
* The copy table for a language, complete or English. A language listed in
|
|
74
|
+
* `PENDING_UI_LANGUAGES` has no table yet and lands on English — the guard test asserts
|
|
75
|
+
* that list is explicit, so this can never be the silent path it looks like.
|
|
76
|
+
*/
|
|
77
|
+
export declare function uiCopyFor(language: string | null | undefined): CopyTable;
|
|
78
|
+
/** One sentence, in one language. */
|
|
79
|
+
export declare function translate(language: string | null | undefined, key: UiKey, params?: UiParams): string;
|
|
80
|
+
/**
|
|
81
|
+
* Bind a language once and reuse it — what the app's `useT()` wraps, so a screen writes
|
|
82
|
+
* `t("card.confirm")` and never threads the language through every call.
|
|
83
|
+
*/
|
|
84
|
+
export declare function createTranslator(language: string | null | undefined): (key: UiKey, params?: UiParams) => string;
|
|
85
|
+
//# sourceMappingURL=ui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/i18n/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAM,KAAK,SAAS,EAAE,KAAK,KAAK,EAAE,MAAM,cAAc,CAAC;AAgB9D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAC5D,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AACjC,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,KAAK,EAMlD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,KAAK,EAAE,CAAC,CAAC,CAGrF,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,UAAU,EAAE,SAAc,CAAC;AAExC,wFAAwF;AACxF,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAcxD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,QAAQ,EAAO,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,GAAG,IAAI,CAStF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,CAGxE;AAUD,qCAAqC;AACrC,wBAAgB,SAAS,CACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACnC,GAAG,EAAE,KAAK,EACV,MAAM,CAAC,EAAE,QAAQ,GAChB,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAClC,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,QAAQ,KAAK,MAAM,CAG3C"}
|
package/dist/i18n/ui.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PENDING_UI_LANGUAGES = exports.UI_COPY = exports.UI_COPY_EN = exports.MAY_READ_AS_ENGLISH = exports.UNTRANSLATED_BY_DESIGN = void 0;
|
|
4
|
+
exports.resolveUiLanguage = resolveUiLanguage;
|
|
5
|
+
exports.uiCopyFor = uiCopyFor;
|
|
6
|
+
exports.translate = translate;
|
|
7
|
+
exports.createTranslator = createTranslator;
|
|
8
|
+
/**
|
|
9
|
+
* UI copy (Milestone 1.9.7) — the mechanism behind the app's own words.
|
|
10
|
+
*
|
|
11
|
+
* Until this existed, `language` drove ASR, the LLM's output language, the spoken
|
|
12
|
+
* confirmation, the reminder templates and the voice ranking — and **nothing about the
|
|
13
|
+
* interface**. The M1.5 walkthrough showed the seam on screen: the confirmation was
|
|
14
|
+
* spoken in French (*"Demain, à quatorze heures… C'est bien ça ?"*) while the card's
|
|
15
|
+
* labels and its red `400` were English. This is that seam.
|
|
16
|
+
*
|
|
17
|
+
* Three properties are deliberate:
|
|
18
|
+
*
|
|
19
|
+
* 1. **The English table is the key set.** `UiKey` is derived from it (`./copy/en-US.ts`)
|
|
20
|
+
* and every other language is typed `Record<UiKey, string>`, so a missing key is a
|
|
21
|
+
* **compile error**, not a sentence that quietly turns English — the same rule the
|
|
22
|
+
* reminder templates enforce with a test, applied here by the type system.
|
|
23
|
+
* 2. **One file per language** in `./copy/`; this module is only the mechanism
|
|
24
|
+
* (resolution, lookup, interpolation, the two allowlists). A language is therefore
|
|
25
|
+
* added, reviewed, or handed to a translator on its own — and the tables live in
|
|
26
|
+
* `shared` rather than in the app because the server also writes sentences that reach
|
|
27
|
+
* the screen (`./server-messages.ts`, next door).
|
|
28
|
+
* 3. **Every string the member reads is in those tables**, including the labels that feel
|
|
29
|
+
* like data — card field names, the Today/Tomorrow chips, colour names, avatar names.
|
|
30
|
+
* A person should not read the app's sentence about their own event in a language they
|
|
31
|
+
* did not choose, and "Lavender — light periwinkle" is such a sentence.
|
|
32
|
+
*
|
|
33
|
+
* And nothing here falls back to English silently for a language we ship: see
|
|
34
|
+
* `PENDING_UI_LANGUAGES`, which names the ones still missing, and `ui.test.ts`, which
|
|
35
|
+
* asserts that list is exactly the gap between `SUPPORTED_LANGUAGES` and `UI_COPY`.
|
|
36
|
+
*/
|
|
37
|
+
const constants_1 = require("../constants");
|
|
38
|
+
const en_US_1 = require("./copy/en-US");
|
|
39
|
+
const fr_FR_1 = require("./copy/fr-FR");
|
|
40
|
+
const zh_CN_1 = require("./copy/zh-CN");
|
|
41
|
+
// zh-TW sits after zh-CN everywhere for the same reason: `resolveUiLanguage("zh")` picks the
|
|
42
|
+
// *first* `zh-` entry, and a bare `zh` has always meant Simplified. Order is the fallback.
|
|
43
|
+
const zh_TW_1 = require("./copy/zh-TW");
|
|
44
|
+
const es_MX_1 = require("./copy/es-MX");
|
|
45
|
+
const de_DE_1 = require("./copy/de-DE");
|
|
46
|
+
const pt_BR_1 = require("./copy/pt-BR");
|
|
47
|
+
const ru_RU_1 = require("./copy/ru-RU");
|
|
48
|
+
const ar_SA_1 = require("./copy/ar-SA");
|
|
49
|
+
const hi_IN_1 = require("./copy/hi-IN");
|
|
50
|
+
const he_IL_1 = require("./copy/he-IL");
|
|
51
|
+
const ja_JP_1 = require("./copy/ja-JP");
|
|
52
|
+
const ko_KR_1 = require("./copy/ko-KR");
|
|
53
|
+
/**
|
|
54
|
+
* Keys where English is the right answer in *every* language: brand names, an example
|
|
55
|
+
* invite code, and a developer diagnostic. The guard both skips these and asserts they
|
|
56
|
+
* really do match English everywhere — which is why the list must stay short.
|
|
57
|
+
*/
|
|
58
|
+
exports.UNTRANSLATED_BY_DESIGN = [
|
|
59
|
+
"login.configWarning",
|
|
60
|
+
"setup.invitePlaceholder",
|
|
61
|
+
"channel.sms",
|
|
62
|
+
"channel.whatsapp",
|
|
63
|
+
"channel.telegram",
|
|
64
|
+
];
|
|
65
|
+
/**
|
|
66
|
+
* Keys where a *specific* language may legitimately coincide with English: French says
|
|
67
|
+
* *Date* and *Notes* exactly as English does, German says *Neutral* and *Person*. Keyed by
|
|
68
|
+
* language on purpose — a global allowlist would excuse a copy-paste in Spanish or Korean
|
|
69
|
+
* too, and the point of the guard is to catch exactly that.
|
|
70
|
+
*
|
|
71
|
+
* Adding an entry is a claim about that language, so it is reviewed like the copy is.
|
|
72
|
+
*/
|
|
73
|
+
exports.MAY_READ_AS_ENGLISH = {
|
|
74
|
+
"fr-FR": ["card.date", "card.notes"],
|
|
75
|
+
"de-DE": ["avatar.generic_01", "avatar.generic_02"],
|
|
76
|
+
};
|
|
77
|
+
/** The English table: the copy of record, and what every lookup falls back to. */
|
|
78
|
+
exports.UI_COPY_EN = en_US_1.EN;
|
|
79
|
+
/** Which language has which table. `en-US` is the floor; see `PENDING_UI_LANGUAGES`. */
|
|
80
|
+
exports.UI_COPY = {
|
|
81
|
+
"en-US": en_US_1.EN,
|
|
82
|
+
"zh-CN": zh_CN_1.ZH,
|
|
83
|
+
"zh-TW": zh_TW_1.TW,
|
|
84
|
+
"es-MX": es_MX_1.ES,
|
|
85
|
+
"fr-FR": fr_FR_1.FR,
|
|
86
|
+
"de-DE": de_DE_1.DE,
|
|
87
|
+
"pt-BR": pt_BR_1.PT,
|
|
88
|
+
"ru-RU": ru_RU_1.RU,
|
|
89
|
+
"ar-SA": ar_SA_1.AR,
|
|
90
|
+
"hi-IN": hi_IN_1.HI,
|
|
91
|
+
"he-IL": he_IL_1.HE,
|
|
92
|
+
"ja-JP": ja_JP_1.JA,
|
|
93
|
+
"ko-KR": ko_KR_1.KO,
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Launch languages whose UI copy is not written yet. They fall back to English until their
|
|
97
|
+
* tables land — a decision the diff shows rather than a silent fallback, because the guard
|
|
98
|
+
* test asserts this list is exactly the gap between `SUPPORTED_LANGUAGES` and `UI_COPY`.
|
|
99
|
+
*
|
|
100
|
+
* **Empty since 2026-09-29**, when wave 2 filled the last nine tables. It stays exported,
|
|
101
|
+
* and the guard stays switched on, because the *thirteenth* language is the one this list
|
|
102
|
+
* exists for — and on **2026-10-21 that happened**: `zh-TW` arrived with its table in the
|
|
103
|
+
* same commit, so this list stayed empty. The mechanism was never needed; the guard still
|
|
104
|
+
* proved the gap was zero rather than assumed it.
|
|
105
|
+
*/
|
|
106
|
+
exports.PENDING_UI_LANGUAGES = [];
|
|
107
|
+
/**
|
|
108
|
+
* The mechanism. `resolveUiLanguage` deliberately mirrors `resolveTemplateKey` in
|
|
109
|
+
* `templates.ts`: exact tag → base language → `en-US`. Two tables with two different
|
|
110
|
+
* fallback policies would be a bug waiting for the first `pt-PT` member.
|
|
111
|
+
*/
|
|
112
|
+
function resolveUiLanguage(language) {
|
|
113
|
+
if (!language)
|
|
114
|
+
return null;
|
|
115
|
+
const exact = constants_1.SUPPORTED_LANGUAGES.find((candidate) => candidate === language);
|
|
116
|
+
if (exact)
|
|
117
|
+
return exact;
|
|
118
|
+
const base = language.split("-")[0] ?? "";
|
|
119
|
+
if (base.length >= 2) {
|
|
120
|
+
return constants_1.SUPPORTED_LANGUAGES.find((candidate) => candidate.startsWith(`${base}-`)) ?? null;
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The copy table for a language, complete or English. A language listed in
|
|
126
|
+
* `PENDING_UI_LANGUAGES` has no table yet and lands on English — the guard test asserts
|
|
127
|
+
* that list is explicit, so this can never be the silent path it looks like.
|
|
128
|
+
*/
|
|
129
|
+
function uiCopyFor(language) {
|
|
130
|
+
const resolved = resolveUiLanguage(language);
|
|
131
|
+
return (resolved ? exports.UI_COPY[resolved] : undefined) ?? exports.UI_COPY_EN;
|
|
132
|
+
}
|
|
133
|
+
/** `{name}` → the value. A placeholder with no value is left visible, not blanked. */
|
|
134
|
+
function interpolate(text, params) {
|
|
135
|
+
if (!params)
|
|
136
|
+
return text;
|
|
137
|
+
return text.replace(/\{(\w+)\}/g, (whole, key) => key in params ? String(params[key]) : whole);
|
|
138
|
+
}
|
|
139
|
+
/** One sentence, in one language. */
|
|
140
|
+
function translate(language, key, params) {
|
|
141
|
+
return interpolate(uiCopyFor(language)[key], params);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Bind a language once and reuse it — what the app's `useT()` wraps, so a screen writes
|
|
145
|
+
* `t("card.confirm")` and never threads the language through every call.
|
|
146
|
+
*/
|
|
147
|
+
function createTranslator(language) {
|
|
148
|
+
const copy = uiCopyFor(language);
|
|
149
|
+
return (key, params) => interpolate(copy[key], params);
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/i18n/ui.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,12 @@ export * from "./schemas/event";
|
|
|
6
6
|
export * from "./schemas/circle";
|
|
7
7
|
export * from "./schemas/member";
|
|
8
8
|
export * from "./schemas/capture";
|
|
9
|
+
export * from "./capture/fields";
|
|
10
|
+
export * from "./capture/audio";
|
|
9
11
|
export * from "./schemas/reminder";
|
|
10
12
|
export * from "./reminders/math";
|
|
11
13
|
export * from "./i18n/templates";
|
|
14
|
+
export * from "./i18n/ui";
|
|
15
|
+
export * from "./i18n/rtl";
|
|
16
|
+
export * from "./i18n/server-messages";
|
|
12
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -22,7 +22,12 @@ __exportStar(require("./schemas/event"), exports);
|
|
|
22
22
|
__exportStar(require("./schemas/circle"), exports);
|
|
23
23
|
__exportStar(require("./schemas/member"), exports);
|
|
24
24
|
__exportStar(require("./schemas/capture"), exports);
|
|
25
|
+
__exportStar(require("./capture/fields"), exports);
|
|
26
|
+
__exportStar(require("./capture/audio"), exports);
|
|
25
27
|
__exportStar(require("./schemas/reminder"), exports);
|
|
26
28
|
__exportStar(require("./reminders/math"), exports);
|
|
27
29
|
__exportStar(require("./i18n/templates"), exports);
|
|
30
|
+
__exportStar(require("./i18n/ui"), exports);
|
|
31
|
+
__exportStar(require("./i18n/rtl"), exports);
|
|
32
|
+
__exportStar(require("./i18n/server-messages"), exports);
|
|
28
33
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,kDAAgC;AAChC,uDAAqC;AACrC,kDAAgC;AAChC,kDAAgC;AAChC,mDAAiC;AACjC,mDAAiC;AACjC,oDAAkC;AAClC,qDAAmC;AACnC,mDAAiC;AACjC,mDAAiC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,kDAAgC;AAChC,uDAAqC;AACrC,kDAAgC;AAChC,kDAAgC;AAChC,mDAAiC;AACjC,mDAAiC;AACjC,oDAAkC;AAClC,mDAAiC;AACjC,kDAAgC;AAChC,qDAAmC;AACnC,mDAAiC;AACjC,mDAAiC;AACjC,4CAA0B;AAC1B,6CAA2B;AAC3B,yDAAuC"}
|
|
@@ -47,6 +47,12 @@ export declare const CaptureSchema: z.ZodObject<{
|
|
|
47
47
|
editedFields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
48
48
|
googleEventId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
49
49
|
createdAt: z.ZodAny;
|
|
50
|
+
/**
|
|
51
|
+
* When the member confirmed or discarded it (M1.5). Optional because captures
|
|
52
|
+
* written before this existed have no such instant, and because a capture sitting
|
|
53
|
+
* in `pending_confirmation` has not been decided at all.
|
|
54
|
+
*/
|
|
55
|
+
decidedAt: z.ZodOptional<z.ZodAny>;
|
|
50
56
|
}, "strip", z.ZodTypeAny, {
|
|
51
57
|
status: "pending_confirmation" | "confirmed" | "discarded";
|
|
52
58
|
memberId: string;
|
|
@@ -67,6 +73,7 @@ export declare const CaptureSchema: z.ZodObject<{
|
|
|
67
73
|
editedFields: string[];
|
|
68
74
|
createdAt?: any;
|
|
69
75
|
googleEventId?: string | null | undefined;
|
|
76
|
+
decidedAt?: any;
|
|
70
77
|
}, {
|
|
71
78
|
status: "pending_confirmation" | "confirmed" | "discarded";
|
|
72
79
|
memberId: string;
|
|
@@ -87,6 +94,7 @@ export declare const CaptureSchema: z.ZodObject<{
|
|
|
87
94
|
createdAt?: any;
|
|
88
95
|
editedFields?: string[] | undefined;
|
|
89
96
|
googleEventId?: string | null | undefined;
|
|
97
|
+
decidedAt?: any;
|
|
90
98
|
}>;
|
|
91
99
|
export type Capture = z.infer<typeof CaptureSchema>;
|
|
92
100
|
//# sourceMappingURL=capture.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/schemas/capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAMxB,0DAA0D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/schemas/capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAMxB,0DAA0D;;;;IAI1D;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEH,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
package/dist/schemas/capture.js
CHANGED
|
@@ -20,5 +20,11 @@ exports.CaptureSchema = zod_1.z.object({
|
|
|
20
20
|
editedFields: zod_1.z.array(zod_1.z.string()).default([]),
|
|
21
21
|
googleEventId: zod_1.z.string().nullish(),
|
|
22
22
|
createdAt: primitives_1.firestoreTimestamp,
|
|
23
|
+
/**
|
|
24
|
+
* When the member confirmed or discarded it (M1.5). Optional because captures
|
|
25
|
+
* written before this existed have no such instant, and because a capture sitting
|
|
26
|
+
* in `pending_confirmation` has not been decided at all.
|
|
27
|
+
*/
|
|
28
|
+
decidedAt: primitives_1.firestoreTimestamp.optional(),
|
|
23
29
|
});
|
|
24
30
|
//# sourceMappingURL=capture.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/schemas/capture.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,mCAA4D;AAC5D,6CAAkD;AAClD,mCAA2C;AAE3C;;;;GAIG;AACU,QAAA,aAAa,GAAG,OAAC,CAAC,MAAM,CAAC;IACpC,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,uBAAe,CAAC;IAC/B,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,cAAc,EAAE,wBAAgB,CAAC,QAAQ,EAAE;IAC3C,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,wBAAgB,CAAC;IAChC,0DAA0D;IAC1D,YAAY,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7C,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACnC,SAAS,EAAE,+BAAkB;
|
|
1
|
+
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/schemas/capture.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,mCAA4D;AAC5D,6CAAkD;AAClD,mCAA2C;AAE3C;;;;GAIG;AACU,QAAA,aAAa,GAAG,OAAC,CAAC,MAAM,CAAC;IACpC,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,uBAAe,CAAC;IAC/B,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,cAAc,EAAE,wBAAgB,CAAC,QAAQ,EAAE;IAC3C,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,wBAAgB,CAAC;IAChC,0DAA0D;IAC1D,YAAY,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7C,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACnC,SAAS,EAAE,+BAAkB;IAC7B;;;;OAIG;IACH,SAAS,EAAE,+BAAkB,CAAC,QAAQ,EAAE;CACzC,CAAC,CAAC"}
|
package/dist/schemas/enums.d.ts
CHANGED
|
@@ -8,4 +8,6 @@ export declare const CONFIDENCE_LEVELS: readonly ["high", "medium", "low"];
|
|
|
8
8
|
export declare const NOTIFY_CHANNELS: readonly ["sms", "whatsapp", "telegram"];
|
|
9
9
|
export declare const REMINDER_STATUSES: readonly ["sent", "failed", "skipped"];
|
|
10
10
|
export declare const VOICE_STYLE_PRESETS: readonly ["professional", "warm_casual", "friendly_brief"];
|
|
11
|
+
/** The preset a member chose; `member.ts` validates against the list above. */
|
|
12
|
+
export type VoiceStylePreset = (typeof VOICE_STYLE_PRESETS)[number];
|
|
11
13
|
//# sourceMappingURL=enums.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../../src/schemas/enums.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,eAAO,MAAM,UAAU,gCAAiC,CAAC;AACzD,eAAO,MAAM,eAAe,qCAAsC,CAAC;AACnE,eAAO,MAAM,gBAAgB,6DAA8D,CAAC;AAC5F,eAAO,MAAM,gBAAgB,4CAA6C,CAAC;AAC3E,eAAO,MAAM,YAAY,qCAAsC,CAAC;AAChE,eAAO,MAAM,iBAAiB,oCAAqC,CAAC;AACpE,eAAO,MAAM,eAAe,0CAA2C,CAAC;AACxE,eAAO,MAAM,iBAAiB,wCAAyC,CAAC;AACxE,eAAO,MAAM,mBAAmB,4DAA6D,CAAC"}
|
|
1
|
+
{"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../../src/schemas/enums.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,eAAO,MAAM,UAAU,gCAAiC,CAAC;AACzD,eAAO,MAAM,eAAe,qCAAsC,CAAC;AACnE,eAAO,MAAM,gBAAgB,6DAA8D,CAAC;AAC5F,eAAO,MAAM,gBAAgB,4CAA6C,CAAC;AAC3E,eAAO,MAAM,YAAY,qCAAsC,CAAC;AAChE,eAAO,MAAM,iBAAiB,oCAAqC,CAAC;AACpE,eAAO,MAAM,eAAe,0CAA2C,CAAC;AACxE,eAAO,MAAM,iBAAiB,wCAAyC,CAAC;AACxE,eAAO,MAAM,mBAAmB,4DAA6D,CAAC;AAC9F,+EAA+E;AAC/E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voxendar/shared",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"private": false,
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
5
8
|
"description": "Shared contracts, schemas, constants and pure logic for Voxendar/Tellie (consumed by functions/ and app/)",
|
|
6
9
|
"main": "dist/index.js",
|
|
7
10
|
"types": "dist/index.d.ts",
|
|
@@ -11,13 +14,15 @@
|
|
|
11
14
|
"scripts": {
|
|
12
15
|
"build": "tsc -p tsconfig.json",
|
|
13
16
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
14
|
-
"test": "vitest run"
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"prepare": "npm run build",
|
|
19
|
+
"prepublishOnly": "npm test"
|
|
15
20
|
},
|
|
16
21
|
"dependencies": {
|
|
17
22
|
"zod": "^3.23.8"
|
|
18
23
|
},
|
|
19
24
|
"devDependencies": {
|
|
20
|
-
"@types/node": "^20.
|
|
25
|
+
"@types/node": "^22.20.5",
|
|
21
26
|
"typescript": "^5.5.4",
|
|
22
27
|
"vitest": "^2.1.9"
|
|
23
28
|
}
|