@eifi1/ui-kit 0.17.0 → 0.19.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 +83 -4
- package/dist/chart.d.ts +13 -1
- package/dist/components/account-chips.d.ts +153 -0
- package/dist/components/account-chips.js +135 -0
- package/dist/components/account-chips.js.map +1 -0
- package/dist/components/account-settings-labels.d.ts +10 -2
- package/dist/components/account-settings-labels.js +3 -0
- package/dist/components/account-settings-labels.js.map +1 -1
- package/dist/components/amount-input.d.ts +13 -1
- package/dist/components/button-group.d.ts +13 -1
- package/dist/components/calculator.d.ts +13 -1
- package/dist/components/chip.d.ts +25 -1
- package/dist/components/chip.js +143 -6
- package/dist/components/chip.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +42 -1
- package/dist/components/confirm-dialog.js +36 -5
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/copy-button.d.ts +13 -1
- package/dist/components/danger-confirm.d.ts +55 -4
- package/dist/components/danger-confirm.js +67 -30
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-cells.d.ts +1 -1
- package/dist/components/data-table-filter-popover.d.ts +1 -1
- package/dist/components/data-table-filters.d.ts +1 -1
- package/dist/components/data-table.d.ts +1 -1
- package/dist/components/data-table.js +2 -0
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/facing-pair.d.ts +13 -1
- package/dist/components/file-button.d.ts +13 -1
- package/dist/components/file-dropzone.d.ts +13 -1
- package/dist/components/floating-panel.d.ts +4 -1
- package/dist/components/floating-panel.js +15 -1
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/form-actions.d.ts +13 -1
- package/dist/components/form-actions.js +3 -0
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/legal.d.ts +84 -0
- package/dist/components/legal.js +55 -0
- package/dist/components/legal.js.map +1 -0
- package/dist/components/money-field.d.ts +13 -1
- package/dist/components/number-field.d.ts +14 -2
- package/dist/components/number-field.js +23 -22
- package/dist/components/number-field.js.map +1 -1
- package/dist/components/number-input.d.ts +13 -1
- package/dist/components/numpad-sheet.d.ts +13 -1
- package/dist/components/passkeys-setting.d.ts +27 -1
- package/dist/components/passkeys-setting.js +31 -5
- package/dist/components/passkeys-setting.js.map +1 -1
- package/dist/components/progress-bar.d.ts +15 -1
- package/dist/components/progress-bar.js +8 -1
- package/dist/components/progress-bar.js.map +1 -1
- package/dist/components/reauth-dialog.d.ts +90 -0
- package/dist/components/reauth-dialog.js +158 -0
- package/dist/components/reauth-dialog.js.map +1 -0
- package/dist/components/series-chart.d.ts +13 -1
- package/dist/components/server-wake.d.ts +60 -0
- package/dist/components/server-wake.js +79 -0
- package/dist/components/server-wake.js.map +1 -0
- package/dist/components/settings-fields.d.ts +13 -1
- package/dist/components/share-card.d.ts +64 -0
- package/dist/components/share-card.js +350 -0
- package/dist/components/share-card.js.map +1 -0
- package/dist/components/status-dot.d.ts +2 -0
- package/dist/components/text-link.d.ts +13 -1
- package/dist/components/time-input.d.ts +13 -1
- package/dist/components/toast.d.ts +10 -1
- package/dist/components/toast.js +42 -2
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toggle-group.js +5 -2
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/translation-review-editor.d.ts +56 -0
- package/dist/components/translation-review-editor.js +159 -0
- package/dist/components/translation-review-editor.js.map +1 -0
- package/dist/components/translation-review-labels.d.ts +92 -0
- package/dist/components/translation-review-labels.js +67 -0
- package/dist/components/translation-review-labels.js.map +1 -0
- package/dist/components/translation-review-parts.d.ts +97 -0
- package/dist/components/translation-review-parts.js +163 -0
- package/dist/components/translation-review-parts.js.map +1 -0
- package/dist/components/translation-review.d.ts +94 -0
- package/dist/components/translation-review.js +344 -0
- package/dist/components/translation-review.js.map +1 -0
- package/dist/components/ui.d.ts +13 -1
- package/dist/components/ui.js +43 -28
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-table-state.d.ts +1 -1
- package/dist/components/user-avatar.d.ts +2 -0
- package/dist/components/write-lock.d.ts +68 -0
- package/dist/components/write-lock.js +33 -0
- package/dist/components/write-lock.js.map +1 -0
- package/dist/{data-table-CpkWUJBY.d.ts → data-table-3mi2R3so.d.ts} +19 -1
- package/dist/data-table.d.ts +1 -1
- package/dist/hooks/use-file-drop.d.ts +13 -1
- package/dist/hooks/use-overlay-history.js +16 -0
- package/dist/hooks/use-overlay-history.js.map +1 -1
- package/dist/i18n/defaults.d.ts +13 -1
- package/dist/i18n/defaults.js +15 -1
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.d.ts +81 -0
- package/dist/i18n/{locales/de.js → german.js} +110 -9
- package/dist/i18n/german.js.map +1 -0
- package/dist/i18n/kit-labels.d.ts +13 -1
- package/dist/i18n/kit-labels.js +5 -0
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.d.ts +243 -0
- package/dist/i18n/languages.js +70 -0
- package/dist/i18n/languages.js.map +1 -0
- package/dist/i18n/locales/de-CH.d.ts +26 -8
- package/dist/i18n/locales/de-CH.js +7 -3
- package/dist/i18n/locales/de-CH.js.map +1 -1
- package/dist/i18n/locales/en.d.ts +13 -1
- package/dist/i18n/locales/en.js +8 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +13 -1
- package/dist/i18n/locales/es.js +127 -27
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +13 -1
- package/dist/i18n/locales/fr.js +101 -1
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +13 -1
- package/dist/i18n/locales/hu.js +105 -1
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +13 -1
- package/dist/i18n/locales/it.js +134 -34
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +13 -1
- package/dist/i18n/locales/zh.js +101 -1
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +102 -0
- package/dist/i18n/review.js +158 -0
- package/dist/i18n/review.js.map +1 -0
- package/dist/i18n/swiss.d.ts +3 -3
- package/dist/i18n/swiss.js.map +1 -1
- package/dist/index.d.ts +17 -4
- package/dist/index.js +97 -1
- package/dist/index.js.map +1 -1
- package/dist/{kit-labels-C4uB_zmg.d.ts → kit-labels-D1J2_jyD.d.ts} +236 -9
- package/dist/lib/floating-stack.d.ts +31 -0
- package/dist/lib/floating-stack.js +42 -0
- package/dist/lib/floating-stack.js.map +1 -0
- package/dist/lib/server-wake.d.ts +146 -0
- package/dist/lib/server-wake.js +122 -0
- package/dist/lib/server-wake.js.map +1 -0
- package/dist/lib/translation-review.d.ts +232 -0
- package/dist/lib/translation-review.js +194 -0
- package/dist/lib/translation-review.js.map +1 -0
- package/dist/rhf/fields.d.ts +13 -1
- package/dist/rhf/form.d.ts +13 -1
- package/dist/rhf.d.ts +13 -1
- package/dist/search/global-search.d.ts +3 -1
- package/dist/search/global-search.js.map +1 -1
- package/dist/shell/app-shell.d.ts +13 -1
- package/dist/shell/top-bar-brand.d.ts +13 -1
- package/dist/shell/topbar-action-menu.d.ts +2 -0
- package/dist/shell.d.ts +13 -1
- package/dist/wizard/stepper-nav.d.ts +13 -1
- package/dist/wizard.d.ts +13 -1
- package/package.json +1 -1
- package/src/components/account-chips.tsx +302 -0
- package/src/components/account-settings-labels.ts +16 -2
- package/src/components/chip.tsx +239 -6
- package/src/components/confirm-dialog.tsx +82 -7
- package/src/components/danger-confirm.tsx +118 -33
- package/src/components/data-table.tsx +20 -0
- package/src/components/floating-panel.tsx +19 -1
- package/src/components/form-actions.tsx +22 -3
- package/src/components/legal.tsx +159 -0
- package/src/components/number-field.tsx +32 -26
- package/src/components/passkeys-setting.tsx +68 -7
- package/src/components/progress-bar.tsx +21 -1
- package/src/components/reauth-dialog.tsx +273 -0
- package/src/components/server-wake.tsx +156 -0
- package/src/components/share-card.tsx +615 -0
- package/src/components/toast.tsx +72 -2
- package/src/components/toggle-group.tsx +5 -2
- package/src/components/translation-review-editor.tsx +261 -0
- package/src/components/translation-review-labels.ts +152 -0
- package/src/components/translation-review-parts.tsx +269 -0
- package/src/components/translation-review.tsx +502 -0
- package/src/components/ui.tsx +89 -32
- package/src/components/write-lock.tsx +96 -0
- package/src/hooks/use-overlay-history.ts +51 -0
- package/src/i18n/defaults.ts +14 -0
- package/src/i18n/{locales/de.ts → german.ts} +120 -13
- package/src/i18n/kit-labels.tsx +29 -2
- package/src/i18n/languages.ts +285 -0
- package/src/i18n/locales/de-CH.ts +17 -8
- package/src/i18n/locales/en.ts +8 -0
- package/src/i18n/locales/es.ts +128 -26
- package/src/i18n/locales/fr.ts +103 -0
- package/src/i18n/locales/hu.ts +107 -0
- package/src/i18n/locales/it.ts +135 -33
- package/src/i18n/locales/zh.ts +102 -0
- package/src/i18n/review.ts +193 -0
- package/src/i18n/swiss.ts +3 -3
- package/src/index.ts +86 -1
- package/src/lib/floating-stack.ts +66 -0
- package/src/lib/server-wake.ts +291 -0
- package/src/lib/translation-review.ts +465 -0
- package/src/search/global-search.tsx +3 -1
- package/dist/i18n/locales/de-CH-informal.d.ts +0 -61
- package/dist/i18n/locales/de-CH-informal.js +0 -8
- package/dist/i18n/locales/de-CH-informal.js.map +0 -1
- package/dist/i18n/locales/de-informal.d.ts +0 -82
- package/dist/i18n/locales/de-informal.js +0 -37
- package/dist/i18n/locales/de-informal.js.map +0 -1
- package/dist/i18n/locales/de.d.ts +0 -66
- package/dist/i18n/locales/de.js.map +0 -1
- package/src/i18n/locales/de-CH-informal.ts +0 -10
- package/src/i18n/locales/de-informal.ts +0 -61
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure half of an app's translation review (H1 in docs/i18n-harmonization.md): from
|
|
3
|
+
* the strings the app ships and the verdicts its server stores to one row per (locale,
|
|
4
|
+
* key) with a status — keksdose's `features/translations/translation-catalogue.ts` and
|
|
5
|
+
* kastlan's copy of it, which had grown apart by a fifth status and a second kind of key.
|
|
6
|
+
*
|
|
7
|
+
* WHY THE STRINGS ARE THE CATALOGUE. Nothing on the server lists which strings exist: a
|
|
8
|
+
* verdict only says what somebody thought of one. So the rows are built from what the app
|
|
9
|
+
* ships — its locale bundles, kastlan's document texts, the kit's own words
|
|
10
|
+
* (`kitLabelStrings`) — and the review can never offer a string users do not see. A
|
|
11
|
+
* verdict is stored WITH the wording it was given on, and a string that changed since is
|
|
12
|
+
* noticed by comparing the two: `changed`, read it again, whatever the verdict was.
|
|
13
|
+
*
|
|
14
|
+
* WHAT STAYS IN THE APP. Which locale is read against which (keksdose: everything against
|
|
15
|
+
* English, English against de-CH; kastlan: against German, German against English), where
|
|
16
|
+
* the strings come from, who may review what (the locales and areas its server answers
|
|
17
|
+
* with), and every request. The kit takes those as input and never derives them.
|
|
18
|
+
*
|
|
19
|
+
* camelCase, like the rest of the kit. The contract's wire shape is snake_case
|
|
20
|
+
* (`reference_text`, `reviewer_name`, `reviewed_at`); {@link fromApiReview} and
|
|
21
|
+
* {@link toApiWrite} are the two lines each app would otherwise write — both apps speak
|
|
22
|
+
* the same contract, so the mapping is written once, here.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// ── Shapes ──────────────────────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
export type TranslationVerdict = "APPROVED" | "NEEDS_CHANGE";
|
|
28
|
+
|
|
29
|
+
/** One stored verdict: what a reviewer said about one string in one locale. */
|
|
30
|
+
export interface TranslationReview {
|
|
31
|
+
locale: string;
|
|
32
|
+
key: string;
|
|
33
|
+
/** The wording that was judged — compared with today's to notice a change. Empty for
|
|
34
|
+
* a string the locale lacked (a suggested translation for a `missing` row). */
|
|
35
|
+
text: string;
|
|
36
|
+
/** The reference wording at the time. `null` from a server that did not store it. */
|
|
37
|
+
referenceText: string | null;
|
|
38
|
+
verdict: TranslationVerdict;
|
|
39
|
+
note: string | null;
|
|
40
|
+
/** The reviewer's wording — or, for a missing string, the translation to add. */
|
|
41
|
+
suggestion: string | null;
|
|
42
|
+
/** `null` once the reviewer's account has been erased. */
|
|
43
|
+
reviewerName: string | null;
|
|
44
|
+
/** ISO timestamp. */
|
|
45
|
+
reviewedAt: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** What a save sends: the verdict plus the wording it is given on. */
|
|
49
|
+
export interface TranslationReviewWrite {
|
|
50
|
+
locale: string;
|
|
51
|
+
key: string;
|
|
52
|
+
text: string;
|
|
53
|
+
referenceText: string | null;
|
|
54
|
+
verdict: TranslationVerdict;
|
|
55
|
+
note: string | null;
|
|
56
|
+
suggestion: string | null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** What a reset sends: back to "unreviewed". */
|
|
60
|
+
export interface TranslationReviewKey {
|
|
61
|
+
locale: string;
|
|
62
|
+
key: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Where a string stands, in the order a reviewer works through them: what is not there
|
|
67
|
+
* at all, what nobody has read, what changed after it was read, what was sent back, and
|
|
68
|
+
* what is done. `missing` never occurs for an app whose locales have every key
|
|
69
|
+
* (keksdose); kastlan's French lacks 172 screen texts.
|
|
70
|
+
*/
|
|
71
|
+
export type ReviewStatus = "missing" | "unreviewed" | "changed" | "needs_change" | "approved";
|
|
72
|
+
|
|
73
|
+
export const REVIEW_STATUSES: readonly ReviewStatus[] = [
|
|
74
|
+
"missing",
|
|
75
|
+
"unreviewed",
|
|
76
|
+
"changed",
|
|
77
|
+
"needs_change",
|
|
78
|
+
"approved",
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
export interface TranslationRow {
|
|
82
|
+
/** `${locale}|${key}` — unique across every locale on a page. A bar, not a colon:
|
|
83
|
+
* kastlan's keys contain colons (`common:actions.save`). */
|
|
84
|
+
id: string;
|
|
85
|
+
key: string;
|
|
86
|
+
/** The key's group: `budget` for `budget.rta`, `common` for `common:actions.save`,
|
|
87
|
+
* `kit` for the kit's own words. See {@link keyNamespace}. */
|
|
88
|
+
namespace: string;
|
|
89
|
+
/** Where the string comes from, in the app's own words — kastlan's `screen` and
|
|
90
|
+
* `documents`, keksdose's one source. `""` when the app does not say. */
|
|
91
|
+
source: string;
|
|
92
|
+
locale: string;
|
|
93
|
+
/** The wording users see today; empty when the locale lacks the string. */
|
|
94
|
+
text: string;
|
|
95
|
+
/** The same key in the reference locale. */
|
|
96
|
+
reference: string;
|
|
97
|
+
status: ReviewStatus;
|
|
98
|
+
review: TranslationReview | null;
|
|
99
|
+
/** The interpolations and tags differ from the reference's — `{{count}}` dropped, a
|
|
100
|
+
* `<1>` link lost, a `{date}` renamed. A machine can check that much, so it does,
|
|
101
|
+
* before a person reads. Never set on a missing string: it has nothing to lose. */
|
|
102
|
+
placeholderMismatch: boolean;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ── The wire contract ───────────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
/** A verdict as `GET /translations/reviews` returns it (H1's shared contract). Typed
|
|
108
|
+
* structurally, so an app's generated OpenAPI type fits without a cast. */
|
|
109
|
+
export interface ApiTranslationReview {
|
|
110
|
+
locale: string;
|
|
111
|
+
key: string;
|
|
112
|
+
text: string;
|
|
113
|
+
reference_text: string | null;
|
|
114
|
+
verdict: TranslationVerdict;
|
|
115
|
+
note: string | null;
|
|
116
|
+
suggestion: string | null;
|
|
117
|
+
reviewer_name: string | null;
|
|
118
|
+
reviewed_at: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** One item of `PUT /translations/reviews`. */
|
|
122
|
+
export interface ApiTranslationReviewWrite {
|
|
123
|
+
locale: string;
|
|
124
|
+
key: string;
|
|
125
|
+
text: string;
|
|
126
|
+
reference_text: string | null;
|
|
127
|
+
verdict: TranslationVerdict;
|
|
128
|
+
note: string | null;
|
|
129
|
+
suggestion: string | null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** A verdict from the server, in the kit's spelling. */
|
|
133
|
+
export function fromApiReview(review: ApiTranslationReview): TranslationReview {
|
|
134
|
+
return {
|
|
135
|
+
locale: review.locale,
|
|
136
|
+
key: review.key,
|
|
137
|
+
text: review.text,
|
|
138
|
+
referenceText: review.reference_text,
|
|
139
|
+
verdict: review.verdict,
|
|
140
|
+
note: review.note,
|
|
141
|
+
suggestion: review.suggestion,
|
|
142
|
+
reviewerName: review.reviewer_name,
|
|
143
|
+
reviewedAt: review.reviewed_at,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** A save, in the server's spelling. `TranslationReviewKey` needs no mapping — it is
|
|
148
|
+
* `{ locale, key }` on both sides. */
|
|
149
|
+
export function toApiWrite(write: TranslationReviewWrite): ApiTranslationReviewWrite {
|
|
150
|
+
return {
|
|
151
|
+
locale: write.locale,
|
|
152
|
+
key: write.key,
|
|
153
|
+
text: write.text,
|
|
154
|
+
reference_text: write.referenceText,
|
|
155
|
+
verdict: write.verdict,
|
|
156
|
+
note: write.note,
|
|
157
|
+
suggestion: write.suggestion,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ── Strings ─────────────────────────────────────────────────────────────────────
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* A nested bundle as `key → string`, in the bundle's own order. Non-string leaves are
|
|
165
|
+
* skipped rather than stringified into something nobody wrote.
|
|
166
|
+
*
|
|
167
|
+
* `prefix` is put in front of every key AS IS, so it names the separator too:
|
|
168
|
+
* `flattenStrings(bundle)` is keksdose's `budget.rta`, `flattenStrings(tree, "common:")`
|
|
169
|
+
* kastlan's `common:actions.save`, and `flattenStrings(kitLabelStrings(labels), "kit.")`
|
|
170
|
+
* the kit's own words as `kit.combobox.resultCount(3)` — already flat, so only the prefix
|
|
171
|
+
* is added.
|
|
172
|
+
*/
|
|
173
|
+
export function flattenStrings(tree: Readonly<Record<string, unknown>>, prefix = ""): Record<string, string> {
|
|
174
|
+
const out: Record<string, string> = {};
|
|
175
|
+
for (const [key, value] of Object.entries(tree)) {
|
|
176
|
+
const path = `${prefix}${key}`;
|
|
177
|
+
if (typeof value === "string") out[path] = value;
|
|
178
|
+
else if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
179
|
+
Object.assign(out, flattenStrings(value as Record<string, unknown>, `${path}.`));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return out;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* The key's group, for the namespace filter: the part before a colon when there is one
|
|
187
|
+
* (kastlan's `common:actions.save` → `common`, `doc_text.invoice:due` →
|
|
188
|
+
* `doc_text.invoice`), else the first dotted segment (keksdose's `budget.rta` →
|
|
189
|
+
* `budget`, the kit's `kit.combobox.resultCount(3)` → `kit`). Only the part before a
|
|
190
|
+
* sample's `(` is looked at, so a colon inside one cannot move the split.
|
|
191
|
+
*/
|
|
192
|
+
export function keyNamespace(key: string): string {
|
|
193
|
+
const head = key.split("(", 1)[0];
|
|
194
|
+
const colon = head.indexOf(":");
|
|
195
|
+
return colon >= 0 ? head.slice(0, colon) : head.split(".", 1)[0];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// i18next `{{x}}` (formatting options ignored: `{{x, number}}` is `{{x}}`); a Python
|
|
199
|
+
// format field `{x}` / `{0}` / `{amount:.2f}` (kastlan's document texts), but not a
|
|
200
|
+
// LaTeX argument (`\textbf{x}` — a letter or backslash right before the brace); a
|
|
201
|
+
// numbered or named tag (`<1>`, `<strong>`), not prose in angle brackets ("<deleted
|
|
202
|
+
// user>"); and a nested `$t(key)`. `{{x}}` is tried first at its position and consumed
|
|
203
|
+
// whole, so it is never counted a second time as `{x}`.
|
|
204
|
+
const PLACEHOLDER_RE =
|
|
205
|
+
/\{\{\s*([^}\s,]+)[^}]*\}\}|(?<![\\A-Za-z])\{([a-z_][a-z0-9_]*|\d+)(?:[!:][^{}]*)?\}|<\/?(\d+|[a-z][a-z0-9]*)\s*\/?>|\$t\(([^)]+)\)/g;
|
|
206
|
+
|
|
207
|
+
/** The placeholders in a string, as a sorted multiset: `{{count}}`, `{date}`, `<1>`,
|
|
208
|
+
* `$t(common.save)`. */
|
|
209
|
+
export function placeholderTokens(text: string): string[] {
|
|
210
|
+
const found: string[] = [];
|
|
211
|
+
for (const m of text.matchAll(PLACEHOLDER_RE)) {
|
|
212
|
+
if (m[1]) found.push(`{{${m[1]}}}`);
|
|
213
|
+
else if (m[2]) found.push(`{${m[2]}}`);
|
|
214
|
+
else if (m[3]) found.push(`<${m[3]}>`);
|
|
215
|
+
else if (m[4]) found.push(`$t(${m[4]})`);
|
|
216
|
+
}
|
|
217
|
+
return found.sort();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** Whether `text` has other placeholders than `reference` — dropped, renamed or added.
|
|
221
|
+
* Moving one is fine: a translation reorders a sentence. */
|
|
222
|
+
export function placeholderMismatch(text: string, reference: string): boolean {
|
|
223
|
+
const a = placeholderTokens(text);
|
|
224
|
+
const b = placeholderTokens(reference);
|
|
225
|
+
return a.length !== b.length || a.some((p, i) => p !== b[i]);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ── Status ──────────────────────────────────────────────────────────────────────
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* A verdict counts only for the wording it was given on. If the string or its reference
|
|
232
|
+
* changed since, it is `changed` — read it again — whatever the verdict was. A string the
|
|
233
|
+
* locale lacks is `missing` until somebody suggests its translation (stored as
|
|
234
|
+
* NEEDS_CHANGE on the empty text, so it reads `needs_change`, and `changed` once a
|
|
235
|
+
* developer adds the string).
|
|
236
|
+
*/
|
|
237
|
+
export function reviewStatus(
|
|
238
|
+
review: TranslationReview | null | undefined,
|
|
239
|
+
text: string,
|
|
240
|
+
reference: string,
|
|
241
|
+
): ReviewStatus {
|
|
242
|
+
if (!review) return text === "" && reference !== "" ? "missing" : "unreviewed";
|
|
243
|
+
if (review.text !== text) return "changed";
|
|
244
|
+
if (review.referenceText != null && review.referenceText !== reference) return "changed";
|
|
245
|
+
return review.verdict === "APPROVED" ? "approved" : "needs_change";
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** Whether `key` lies in `area`: the key IS the area, or sits under it — `legal.terms`
|
|
249
|
+
* and kastlan's `legal:terms` are in `legal`, `legalese.title` is not. */
|
|
250
|
+
export function keyInArea(key: string, area: string): boolean {
|
|
251
|
+
return key === area || key.startsWith(`${area}.`) || key.startsWith(`${area}:`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Whether `key` lies in one of `areas` — the scope a reviewer may be limited to
|
|
256
|
+
* (keksdose: `["legal"]`, a lawyer who judges the Imprint, the Privacy Policy and the
|
|
257
|
+
* Terms and sees nothing else). `null`/`undefined` is every area. The server applies the
|
|
258
|
+
* same rule and refuses verdicts outside; this decides only what is listed.
|
|
259
|
+
*/
|
|
260
|
+
export function keyInAreas(
|
|
261
|
+
key: string,
|
|
262
|
+
areas: readonly string[] | null | undefined,
|
|
263
|
+
inArea: (key: string, area: string) => boolean = keyInArea,
|
|
264
|
+
): boolean {
|
|
265
|
+
return !areas || areas.some((area) => inArea(key, area));
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface TranslationRowsInput {
|
|
269
|
+
locale: string;
|
|
270
|
+
/** The locale's strings, `key → text` ({@link flattenStrings}). */
|
|
271
|
+
strings: Readonly<Record<string, string>>;
|
|
272
|
+
/** The reference locale's strings — whichever locale THIS app reads `locale` against. */
|
|
273
|
+
reference: Readonly<Record<string, string>>;
|
|
274
|
+
/** The verdicts: this locale's by key, or the whole list as the server sent it (other
|
|
275
|
+
* locales' verdicts are skipped). */
|
|
276
|
+
reviews?: ReadonlyMap<string, TranslationReview> | readonly TranslationReview[];
|
|
277
|
+
/** Default {@link keyNamespace}. */
|
|
278
|
+
namespaceOf?: (key: string) => string;
|
|
279
|
+
/** The row's source, an app-defined word (kastlan: `doc_text.` keys are `documents`,
|
|
280
|
+
* the rest `screen`). Default: none (`""`). */
|
|
281
|
+
sourceOf?: (key: string) => string;
|
|
282
|
+
/** Keep only keys inside these areas ({@link keyInAreas}); `null` keeps every key. */
|
|
283
|
+
areas?: readonly string[] | null;
|
|
284
|
+
/** Default {@link keyInArea}. */
|
|
285
|
+
inArea?: (key: string, area: string) => boolean;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Every key of one locale, with its status: the reference's keys first, in its order, so
|
|
290
|
+
* rows read the way the app's authors wrote them; a key only this locale has is appended
|
|
291
|
+
* rather than dropped (a parity test should forbid it, but the page should not lie if one
|
|
292
|
+
* slips through).
|
|
293
|
+
*/
|
|
294
|
+
export function translationRows({
|
|
295
|
+
locale,
|
|
296
|
+
strings,
|
|
297
|
+
reference,
|
|
298
|
+
reviews,
|
|
299
|
+
namespaceOf: groupOf = keyNamespace,
|
|
300
|
+
sourceOf,
|
|
301
|
+
areas,
|
|
302
|
+
inArea,
|
|
303
|
+
}: TranslationRowsInput): TranslationRow[] {
|
|
304
|
+
const byKey = new Map<string, TranslationReview>();
|
|
305
|
+
if (reviews instanceof Map) {
|
|
306
|
+
for (const [key, review] of reviews) byKey.set(key, review);
|
|
307
|
+
} else if (reviews) {
|
|
308
|
+
for (const review of reviews as readonly TranslationReview[]) {
|
|
309
|
+
if (review.locale === locale) byKey.set(review.key, review);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
const keys = Object.keys(reference);
|
|
313
|
+
for (const key of Object.keys(strings)) if (!(key in reference)) keys.push(key);
|
|
314
|
+
return keys
|
|
315
|
+
.filter((key) => keyInAreas(key, areas, inArea))
|
|
316
|
+
.map((key) => {
|
|
317
|
+
const text = strings[key] ?? "";
|
|
318
|
+
const ref = reference[key] ?? "";
|
|
319
|
+
const review = byKey.get(key) ?? null;
|
|
320
|
+
return {
|
|
321
|
+
id: `${locale}|${key}`,
|
|
322
|
+
key,
|
|
323
|
+
namespace: groupOf(key),
|
|
324
|
+
source: sourceOf?.(key) ?? "",
|
|
325
|
+
locale,
|
|
326
|
+
text,
|
|
327
|
+
reference: ref,
|
|
328
|
+
status: reviewStatus(review, text, ref),
|
|
329
|
+
review,
|
|
330
|
+
placeholderMismatch: text !== "" && placeholderMismatch(text, ref),
|
|
331
|
+
};
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/** How many rows stand where, and how many there are. */
|
|
336
|
+
export type TranslationSummary = Record<ReviewStatus, number> & { total: number };
|
|
337
|
+
|
|
338
|
+
export function summariseRows(rows: readonly TranslationRow[]): TranslationSummary {
|
|
339
|
+
const summary: TranslationSummary = {
|
|
340
|
+
missing: 0,
|
|
341
|
+
unreviewed: 0,
|
|
342
|
+
changed: 0,
|
|
343
|
+
needs_change: 0,
|
|
344
|
+
approved: 0,
|
|
345
|
+
total: rows.length,
|
|
346
|
+
};
|
|
347
|
+
for (const row of rows) summary[row.status] += 1;
|
|
348
|
+
return summary;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// ── Filtering ───────────────────────────────────────────────────────────────────
|
|
352
|
+
|
|
353
|
+
/** The panel's filters. `"all"` switches one off. */
|
|
354
|
+
export interface TranslationReviewFilter {
|
|
355
|
+
status: ReviewStatus | "all";
|
|
356
|
+
source: string;
|
|
357
|
+
namespace: string;
|
|
358
|
+
/** Searched in the key, the text and the reference, case-insensitively. */
|
|
359
|
+
query: string;
|
|
360
|
+
placeholdersOnly: boolean;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export const DEFAULT_TRANSLATION_REVIEW_FILTER: TranslationReviewFilter = {
|
|
364
|
+
status: "all",
|
|
365
|
+
source: "all",
|
|
366
|
+
namespace: "all",
|
|
367
|
+
query: "",
|
|
368
|
+
placeholdersOnly: false,
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
export function filterTranslationRows(
|
|
372
|
+
rows: readonly TranslationRow[],
|
|
373
|
+
filter: Partial<TranslationReviewFilter>,
|
|
374
|
+
): TranslationRow[] {
|
|
375
|
+
const f = { ...DEFAULT_TRANSLATION_REVIEW_FILTER, ...filter };
|
|
376
|
+
const q = f.query.trim().toLowerCase();
|
|
377
|
+
return rows.filter(
|
|
378
|
+
(row) =>
|
|
379
|
+
(f.status === "all" || row.status === f.status) &&
|
|
380
|
+
(f.source === "all" || row.source === f.source) &&
|
|
381
|
+
(f.namespace === "all" || row.namespace === f.namespace) &&
|
|
382
|
+
(!f.placeholdersOnly || row.placeholderMismatch) &&
|
|
383
|
+
(!q ||
|
|
384
|
+
row.key.toLowerCase().includes(q) ||
|
|
385
|
+
row.text.toLowerCase().includes(q) ||
|
|
386
|
+
row.reference.toLowerCase().includes(q)),
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// ── Writing ─────────────────────────────────────────────────────────────────────
|
|
391
|
+
|
|
392
|
+
/** What gets stored for a verdict: the wording it was given on, so a later change of the
|
|
393
|
+
* string (or of its reference) shows up as `changed`. */
|
|
394
|
+
export function reviewWrite(
|
|
395
|
+
row: TranslationRow,
|
|
396
|
+
verdict: TranslationVerdict,
|
|
397
|
+
note: string | null = null,
|
|
398
|
+
suggestion: string | null = null,
|
|
399
|
+
): TranslationReviewWrite {
|
|
400
|
+
return {
|
|
401
|
+
locale: row.locale,
|
|
402
|
+
key: row.key,
|
|
403
|
+
text: row.text,
|
|
404
|
+
referenceText: row.reference,
|
|
405
|
+
verdict,
|
|
406
|
+
note,
|
|
407
|
+
suggestion,
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/** The app's cached verdict list with `written` in place of what was said before — a
|
|
412
|
+
* save answers with the rows it wrote, so a page patches its copy instead of
|
|
413
|
+
* downloading every verdict again after each click. Any spelling with `locale` and
|
|
414
|
+
* `key` (the API's or the kit's). */
|
|
415
|
+
export function mergeReviews<T extends TranslationReviewKey>(prev: readonly T[], written: readonly T[]): T[] {
|
|
416
|
+
const id = (r: TranslationReviewKey) => `${r.locale}|${r.key}`;
|
|
417
|
+
const replaced = new Set(written.map(id));
|
|
418
|
+
return [...prev.filter((r) => !replaced.has(id(r))), ...written];
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/** The cached list without the verdicts on `cleared`. */
|
|
422
|
+
export function dropReviews<T extends TranslationReviewKey>(
|
|
423
|
+
prev: readonly T[],
|
|
424
|
+
cleared: readonly TranslationReviewKey[],
|
|
425
|
+
): T[] {
|
|
426
|
+
const gone = new Set(cleared.map((r) => `${r.locale}|${r.key}`));
|
|
427
|
+
return prev.filter((r) => !gone.has(`${r.locale}|${r.key}`));
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// ── Export ──────────────────────────────────────────────────────────────────────
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* One entry of the "Export corrections" file — enough for a developer to apply the change
|
|
434
|
+
* to the bundle without opening the page. snake_case `reviewed_at` on purpose: this is a
|
|
435
|
+
* FILE, the one keksdose and kastlan already write, beside an API spelled that way.
|
|
436
|
+
*/
|
|
437
|
+
export interface TranslationCorrection {
|
|
438
|
+
locale: string;
|
|
439
|
+
key: string;
|
|
440
|
+
status: ReviewStatus;
|
|
441
|
+
current: string;
|
|
442
|
+
reference: string;
|
|
443
|
+
suggestion: string | null;
|
|
444
|
+
note: string | null;
|
|
445
|
+
reviewer: string | null;
|
|
446
|
+
reviewed_at: string | null;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/** The rows sent back (verdict NEEDS_CHANGE — a suggested translation for a missing
|
|
450
|
+
* string included), as the export file lists them. */
|
|
451
|
+
export function translationCorrections(rows: readonly TranslationRow[]): TranslationCorrection[] {
|
|
452
|
+
return rows
|
|
453
|
+
.filter((row) => row.review?.verdict === "NEEDS_CHANGE")
|
|
454
|
+
.map((row) => ({
|
|
455
|
+
locale: row.locale,
|
|
456
|
+
key: row.key,
|
|
457
|
+
status: row.status,
|
|
458
|
+
current: row.text,
|
|
459
|
+
reference: row.reference,
|
|
460
|
+
suggestion: row.review?.suggestion ?? null,
|
|
461
|
+
note: row.review?.note ?? null,
|
|
462
|
+
reviewer: row.review?.reviewerName ?? null,
|
|
463
|
+
reviewed_at: row.review?.reviewedAt ?? null,
|
|
464
|
+
}));
|
|
465
|
+
}
|
|
@@ -43,7 +43,9 @@ export interface GlobalSearchSource {
|
|
|
43
43
|
/** Stable key — the effect that runs the source is keyed by it, not by identity. */
|
|
44
44
|
id: string;
|
|
45
45
|
/** The group its results are shown under (an entry's own `group` is ignored) — unless
|
|
46
|
-
* `groups` is set, where it is only the home of entries that name no declared group.
|
|
46
|
+
* `groups` is set, where it is only the home of entries that name no declared group.
|
|
47
|
+
* If every entry names a declared group, it is never shown: a catch-all heading such
|
|
48
|
+
* as "Other" is the honest value, so a stray type would still surface, labelled. */
|
|
47
49
|
group: string;
|
|
48
50
|
/**
|
|
49
51
|
* Split ONE request into several groups — kastlan's record search answers with
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { a$ as UiKitLabels } from '../../kit-labels-C4uB_zmg.js';
|
|
2
|
-
import 'react';
|
|
3
|
-
import '../../components/data-table-labels.js';
|
|
4
|
-
import '../../components/mini-calendar.js';
|
|
5
|
-
import '../../components/calendar-heatmap.js';
|
|
6
|
-
import '../../components/popover.js';
|
|
7
|
-
import '../../components/chip.js';
|
|
8
|
-
import 'lucide-react';
|
|
9
|
-
import '../../components/field-sync.js';
|
|
10
|
-
import '../../components/tooltip.js';
|
|
11
|
-
import '../../hooks/use-anchored-rect.js';
|
|
12
|
-
import '../../lib/clipping.js';
|
|
13
|
-
import '../../wizard/types.js';
|
|
14
|
-
import '../../tour/tour.js';
|
|
15
|
-
import '../../search/command-palette.js';
|
|
16
|
-
import '../../search/global-search.js';
|
|
17
|
-
import '../../search/search-index.js';
|
|
18
|
-
import '../../components/month-picker.js';
|
|
19
|
-
import '../../components/page-contents.js';
|
|
20
|
-
import '../../components/series-chart-labels.js';
|
|
21
|
-
import '../../components/pie-chart-labels.js';
|
|
22
|
-
import '../../components/sparkline.js';
|
|
23
|
-
import '../../components/stat-tile.js';
|
|
24
|
-
import '../../components/signature-pad.js';
|
|
25
|
-
import '../../components/password-strength.js';
|
|
26
|
-
import '../../components/danger-confirm.js';
|
|
27
|
-
import '../../components/swatch-picker.js';
|
|
28
|
-
import '../../components/tile-radio.js';
|
|
29
|
-
import '../../components/icon-picker.js';
|
|
30
|
-
import '../../components/dialog-frame.js';
|
|
31
|
-
import '../../components/modal.js';
|
|
32
|
-
import '../../hooks/use-search-param-state.js';
|
|
33
|
-
import '../../components/measured-grid.js';
|
|
34
|
-
import '../../feedback-attachment-WFiXJ8We.js';
|
|
35
|
-
import '../../feedback/feedback-thread.js';
|
|
36
|
-
import '../../feedback/feedback-inbox.js';
|
|
37
|
-
import '../../components/account-settings-labels.js';
|
|
38
|
-
import '../../components/confirm-dialog.js';
|
|
39
|
-
import '../../components/floating-panel.js';
|
|
40
|
-
import '../../components/bulk-action-bar.js';
|
|
41
|
-
import '../../components/list.js';
|
|
42
|
-
import '../../components/signed-amount.js';
|
|
43
|
-
import '../../components/breadcrumbs.js';
|
|
44
|
-
import '../../components/toast.js';
|
|
45
|
-
import '../../components/description-list.js';
|
|
46
|
-
import '../../components/line-items.js';
|
|
47
|
-
import '../../components/progress-bar.js';
|
|
48
|
-
import '../../components/error-boundary.js';
|
|
49
|
-
import '../../components/authed-image.js';
|
|
50
|
-
import '../../hooks/use-authed-src.js';
|
|
51
|
-
import '../../components/image-grid.js';
|
|
52
|
-
import '../../components/lightbox.js';
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Swiss Standard German, informal ("du"): the informal German labels with Swiss
|
|
56
|
-
* spelling ("ss" for every "ß") and `de-CH` number formatting (1’234.5) — derived the
|
|
57
|
-
* same way `de-CH` is from `de`, so both stay in sync with their source.
|
|
58
|
-
*/
|
|
59
|
-
declare const UI_KIT_LABELS_DE_CH_INFORMAL: UiKitLabels;
|
|
60
|
-
|
|
61
|
-
export { UI_KIT_LABELS_DE_CH_INFORMAL };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { swiss } from "../swiss.js";
|
|
3
|
-
import { uiKitLabelsDeInformal } from "./de-informal.js";
|
|
4
|
-
const UI_KIT_LABELS_DE_CH_INFORMAL = swiss(uiKitLabelsDeInformal("de-CH"));
|
|
5
|
-
export {
|
|
6
|
-
UI_KIT_LABELS_DE_CH_INFORMAL
|
|
7
|
-
};
|
|
8
|
-
//# sourceMappingURL=de-CH-informal.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/i18n/locales/de-CH-informal.ts"],"sourcesContent":["import type { UiKitLabels } from \"../kit-labels\";\nimport { swiss } from \"../swiss\";\nimport { uiKitLabelsDeInformal } from \"./de-informal\";\n\n/**\n * Swiss Standard German, informal (\"du\"): the informal German labels with Swiss\n * spelling (\"ss\" for every \"ß\") and `de-CH` number formatting (1’234.5) — derived the\n * same way `de-CH` is from `de`, so both stay in sync with their source.\n */\nexport const UI_KIT_LABELS_DE_CH_INFORMAL: UiKitLabels = swiss(uiKitLabelsDeInformal(\"de-CH\"));\n"],"mappings":";AACA,SAAS,aAAa;AACtB,SAAS,6BAA6B;AAO/B,MAAM,+BAA4C,MAAM,sBAAsB,OAAO,CAAC;","names":[]}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { a$ as UiKitLabels } from '../../kit-labels-C4uB_zmg.js';
|
|
2
|
-
import 'react';
|
|
3
|
-
import '../../components/data-table-labels.js';
|
|
4
|
-
import '../../components/mini-calendar.js';
|
|
5
|
-
import '../../components/calendar-heatmap.js';
|
|
6
|
-
import '../../components/popover.js';
|
|
7
|
-
import '../../components/chip.js';
|
|
8
|
-
import 'lucide-react';
|
|
9
|
-
import '../../components/field-sync.js';
|
|
10
|
-
import '../../components/tooltip.js';
|
|
11
|
-
import '../../hooks/use-anchored-rect.js';
|
|
12
|
-
import '../../lib/clipping.js';
|
|
13
|
-
import '../../wizard/types.js';
|
|
14
|
-
import '../../tour/tour.js';
|
|
15
|
-
import '../../search/command-palette.js';
|
|
16
|
-
import '../../search/global-search.js';
|
|
17
|
-
import '../../search/search-index.js';
|
|
18
|
-
import '../../components/month-picker.js';
|
|
19
|
-
import '../../components/page-contents.js';
|
|
20
|
-
import '../../components/series-chart-labels.js';
|
|
21
|
-
import '../../components/pie-chart-labels.js';
|
|
22
|
-
import '../../components/sparkline.js';
|
|
23
|
-
import '../../components/stat-tile.js';
|
|
24
|
-
import '../../components/signature-pad.js';
|
|
25
|
-
import '../../components/password-strength.js';
|
|
26
|
-
import '../../components/danger-confirm.js';
|
|
27
|
-
import '../../components/swatch-picker.js';
|
|
28
|
-
import '../../components/tile-radio.js';
|
|
29
|
-
import '../../components/icon-picker.js';
|
|
30
|
-
import '../../components/dialog-frame.js';
|
|
31
|
-
import '../../components/modal.js';
|
|
32
|
-
import '../../hooks/use-search-param-state.js';
|
|
33
|
-
import '../../components/measured-grid.js';
|
|
34
|
-
import '../../feedback-attachment-WFiXJ8We.js';
|
|
35
|
-
import '../../feedback/feedback-thread.js';
|
|
36
|
-
import '../../feedback/feedback-inbox.js';
|
|
37
|
-
import '../../components/account-settings-labels.js';
|
|
38
|
-
import '../../components/confirm-dialog.js';
|
|
39
|
-
import '../../components/floating-panel.js';
|
|
40
|
-
import '../../components/bulk-action-bar.js';
|
|
41
|
-
import '../../components/list.js';
|
|
42
|
-
import '../../components/signed-amount.js';
|
|
43
|
-
import '../../components/breadcrumbs.js';
|
|
44
|
-
import '../../components/toast.js';
|
|
45
|
-
import '../../components/description-list.js';
|
|
46
|
-
import '../../components/line-items.js';
|
|
47
|
-
import '../../components/progress-bar.js';
|
|
48
|
-
import '../../components/error-boundary.js';
|
|
49
|
-
import '../../components/authed-image.js';
|
|
50
|
-
import '../../hooks/use-authed-src.js';
|
|
51
|
-
import '../../components/image-grid.js';
|
|
52
|
-
import '../../components/lightbox.js';
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* The kit's words in informal German ("du"), for apps that address their users that way
|
|
56
|
-
* everywhere else: `<UiKitProvider labels={UI_KIT_LABELS_DE_INFORMAL}>`.
|
|
57
|
-
*
|
|
58
|
-
* Built on the formal catalogue ({@link uiKitLabelsDe}) rather than beside it: most of
|
|
59
|
-
* the kit's German never addresses anyone — buttons are infinitives ("Speichern"),
|
|
60
|
-
* status lines are impersonal ("Wird geladen…"), hints use the infinitive
|
|
61
|
-
* ("Mindestens 3 Zeichen eingeben", "Bitte erneut versuchen") — so it is the same text
|
|
62
|
-
* in both registers and stays in sync with `de.ts` by construction. Only the sentences
|
|
63
|
-
* that speak TO the user are rewritten here, by hand: du/Sie is grammar (verb forms,
|
|
64
|
-
* imperatives, possessives), not a substitution a regex could do.
|
|
65
|
-
*
|
|
66
|
-
* Every key of `de.ts` was reviewed. The overridden ones — the complete list of
|
|
67
|
-
* sentences that say "Sie" / "Ihr" / a Sie-imperative in the formal catalogue:
|
|
68
|
-
* - `miniCalendar.startSelected`, `miniCalendar.rangeSelected`
|
|
69
|
-
* - `dangerConfirm.phrase`
|
|
70
|
-
* - `wizard.confirmCancel`, `wizard.missingRequired`
|
|
71
|
-
* - `tour.awaitClickHint`
|
|
72
|
-
* - `signaturePad.instructions`, `signaturePad.typedFallbackHint`
|
|
73
|
-
*
|
|
74
|
-
* A key added to `de.ts` later is inherited as is; if it addresses the user, add its
|
|
75
|
-
* du form here (the "no formal address" test in locales.test.ts catches a "Sie").
|
|
76
|
-
* Conventions as in `de.ts`: „…“ quotes, `Intl` digits (via the `numberLocale`
|
|
77
|
-
* argument, e.g. `"de-AT"`), number agreement.
|
|
78
|
-
*/
|
|
79
|
-
declare function uiKitLabelsDeInformal(numberLocale?: string): UiKitLabels;
|
|
80
|
-
declare const UI_KIT_LABELS_DE_INFORMAL: UiKitLabels;
|
|
81
|
-
|
|
82
|
-
export { UI_KIT_LABELS_DE_INFORMAL, uiKitLabelsDeInformal };
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { uiKitLabelsDe } from "./de.js";
|
|
3
|
-
function uiKitLabelsDeInformal(numberLocale = "de-DE") {
|
|
4
|
-
const de = uiKitLabelsDe(numberLocale);
|
|
5
|
-
return {
|
|
6
|
-
...de,
|
|
7
|
-
miniCalendar: {
|
|
8
|
-
...de.miniCalendar,
|
|
9
|
-
startSelected: (date) => `${date} als Startdatum gew\xE4hlt. W\xE4hle jetzt ein Enddatum.`,
|
|
10
|
-
rangeSelected: (from, to) => `Zeitraum ${from} bis ${to} gew\xE4hlt. W\xE4hle ein Startdatum, um neu zu beginnen.`
|
|
11
|
-
},
|
|
12
|
-
dangerConfirm: {
|
|
13
|
-
...de.dangerConfirm,
|
|
14
|
-
phrase: (phrase) => `Gib zur Best\xE4tigung \u201E${phrase}\u201C ein`
|
|
15
|
-
},
|
|
16
|
-
wizard: {
|
|
17
|
-
...de.wizard,
|
|
18
|
-
confirmCancel: "Deine Eingaben gehen verloren.",
|
|
19
|
-
missingRequired: "Bitte f\xFClle alle Pflichtfelder aus."
|
|
20
|
-
},
|
|
21
|
-
tour: {
|
|
22
|
-
...de.tour,
|
|
23
|
-
awaitClickHint: "Klick auf das hervorgehobene Element, um fortzufahren"
|
|
24
|
-
},
|
|
25
|
-
signaturePad: {
|
|
26
|
-
...de.signaturePad,
|
|
27
|
-
instructions: "Unterschreibe im Feld mit der Maus, dem Finger oder einem Stift.",
|
|
28
|
-
typedFallbackHint: "Wenn du nicht zeichnen kannst, gib stattdessen deinen Namen ein."
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
const UI_KIT_LABELS_DE_INFORMAL = uiKitLabelsDeInformal();
|
|
33
|
-
export {
|
|
34
|
-
UI_KIT_LABELS_DE_INFORMAL,
|
|
35
|
-
uiKitLabelsDeInformal
|
|
36
|
-
};
|
|
37
|
-
//# sourceMappingURL=de-informal.js.map
|