@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.
Files changed (210) hide show
  1. package/README.md +83 -4
  2. package/dist/chart.d.ts +13 -1
  3. package/dist/components/account-chips.d.ts +153 -0
  4. package/dist/components/account-chips.js +135 -0
  5. package/dist/components/account-chips.js.map +1 -0
  6. package/dist/components/account-settings-labels.d.ts +10 -2
  7. package/dist/components/account-settings-labels.js +3 -0
  8. package/dist/components/account-settings-labels.js.map +1 -1
  9. package/dist/components/amount-input.d.ts +13 -1
  10. package/dist/components/button-group.d.ts +13 -1
  11. package/dist/components/calculator.d.ts +13 -1
  12. package/dist/components/chip.d.ts +25 -1
  13. package/dist/components/chip.js +143 -6
  14. package/dist/components/chip.js.map +1 -1
  15. package/dist/components/confirm-dialog.d.ts +42 -1
  16. package/dist/components/confirm-dialog.js +36 -5
  17. package/dist/components/confirm-dialog.js.map +1 -1
  18. package/dist/components/copy-button.d.ts +13 -1
  19. package/dist/components/danger-confirm.d.ts +55 -4
  20. package/dist/components/danger-confirm.js +67 -30
  21. package/dist/components/danger-confirm.js.map +1 -1
  22. package/dist/components/data-table-cells.d.ts +1 -1
  23. package/dist/components/data-table-filter-popover.d.ts +1 -1
  24. package/dist/components/data-table-filters.d.ts +1 -1
  25. package/dist/components/data-table.d.ts +1 -1
  26. package/dist/components/data-table.js +2 -0
  27. package/dist/components/data-table.js.map +1 -1
  28. package/dist/components/facing-pair.d.ts +13 -1
  29. package/dist/components/file-button.d.ts +13 -1
  30. package/dist/components/file-dropzone.d.ts +13 -1
  31. package/dist/components/floating-panel.d.ts +4 -1
  32. package/dist/components/floating-panel.js +15 -1
  33. package/dist/components/floating-panel.js.map +1 -1
  34. package/dist/components/form-actions.d.ts +13 -1
  35. package/dist/components/form-actions.js +3 -0
  36. package/dist/components/form-actions.js.map +1 -1
  37. package/dist/components/legal.d.ts +84 -0
  38. package/dist/components/legal.js +55 -0
  39. package/dist/components/legal.js.map +1 -0
  40. package/dist/components/money-field.d.ts +13 -1
  41. package/dist/components/number-field.d.ts +14 -2
  42. package/dist/components/number-field.js +23 -22
  43. package/dist/components/number-field.js.map +1 -1
  44. package/dist/components/number-input.d.ts +13 -1
  45. package/dist/components/numpad-sheet.d.ts +13 -1
  46. package/dist/components/passkeys-setting.d.ts +27 -1
  47. package/dist/components/passkeys-setting.js +31 -5
  48. package/dist/components/passkeys-setting.js.map +1 -1
  49. package/dist/components/progress-bar.d.ts +15 -1
  50. package/dist/components/progress-bar.js +8 -1
  51. package/dist/components/progress-bar.js.map +1 -1
  52. package/dist/components/reauth-dialog.d.ts +90 -0
  53. package/dist/components/reauth-dialog.js +158 -0
  54. package/dist/components/reauth-dialog.js.map +1 -0
  55. package/dist/components/series-chart.d.ts +13 -1
  56. package/dist/components/server-wake.d.ts +60 -0
  57. package/dist/components/server-wake.js +79 -0
  58. package/dist/components/server-wake.js.map +1 -0
  59. package/dist/components/settings-fields.d.ts +13 -1
  60. package/dist/components/share-card.d.ts +64 -0
  61. package/dist/components/share-card.js +350 -0
  62. package/dist/components/share-card.js.map +1 -0
  63. package/dist/components/status-dot.d.ts +2 -0
  64. package/dist/components/text-link.d.ts +13 -1
  65. package/dist/components/time-input.d.ts +13 -1
  66. package/dist/components/toast.d.ts +10 -1
  67. package/dist/components/toast.js +42 -2
  68. package/dist/components/toast.js.map +1 -1
  69. package/dist/components/toggle-group.js +5 -2
  70. package/dist/components/toggle-group.js.map +1 -1
  71. package/dist/components/translation-review-editor.d.ts +56 -0
  72. package/dist/components/translation-review-editor.js +159 -0
  73. package/dist/components/translation-review-editor.js.map +1 -0
  74. package/dist/components/translation-review-labels.d.ts +92 -0
  75. package/dist/components/translation-review-labels.js +67 -0
  76. package/dist/components/translation-review-labels.js.map +1 -0
  77. package/dist/components/translation-review-parts.d.ts +97 -0
  78. package/dist/components/translation-review-parts.js +163 -0
  79. package/dist/components/translation-review-parts.js.map +1 -0
  80. package/dist/components/translation-review.d.ts +94 -0
  81. package/dist/components/translation-review.js +344 -0
  82. package/dist/components/translation-review.js.map +1 -0
  83. package/dist/components/ui.d.ts +13 -1
  84. package/dist/components/ui.js +43 -28
  85. package/dist/components/ui.js.map +1 -1
  86. package/dist/components/use-table-state.d.ts +1 -1
  87. package/dist/components/user-avatar.d.ts +2 -0
  88. package/dist/components/write-lock.d.ts +68 -0
  89. package/dist/components/write-lock.js +33 -0
  90. package/dist/components/write-lock.js.map +1 -0
  91. package/dist/{data-table-CpkWUJBY.d.ts → data-table-3mi2R3so.d.ts} +19 -1
  92. package/dist/data-table.d.ts +1 -1
  93. package/dist/hooks/use-file-drop.d.ts +13 -1
  94. package/dist/hooks/use-overlay-history.js +16 -0
  95. package/dist/hooks/use-overlay-history.js.map +1 -1
  96. package/dist/i18n/defaults.d.ts +13 -1
  97. package/dist/i18n/defaults.js +15 -1
  98. package/dist/i18n/defaults.js.map +1 -1
  99. package/dist/i18n/german.d.ts +81 -0
  100. package/dist/i18n/{locales/de.js → german.js} +110 -9
  101. package/dist/i18n/german.js.map +1 -0
  102. package/dist/i18n/kit-labels.d.ts +13 -1
  103. package/dist/i18n/kit-labels.js +5 -0
  104. package/dist/i18n/kit-labels.js.map +1 -1
  105. package/dist/i18n/languages.d.ts +243 -0
  106. package/dist/i18n/languages.js +70 -0
  107. package/dist/i18n/languages.js.map +1 -0
  108. package/dist/i18n/locales/de-CH.d.ts +26 -8
  109. package/dist/i18n/locales/de-CH.js +7 -3
  110. package/dist/i18n/locales/de-CH.js.map +1 -1
  111. package/dist/i18n/locales/en.d.ts +13 -1
  112. package/dist/i18n/locales/en.js +8 -0
  113. package/dist/i18n/locales/en.js.map +1 -1
  114. package/dist/i18n/locales/es.d.ts +13 -1
  115. package/dist/i18n/locales/es.js +127 -27
  116. package/dist/i18n/locales/es.js.map +1 -1
  117. package/dist/i18n/locales/fr.d.ts +13 -1
  118. package/dist/i18n/locales/fr.js +101 -1
  119. package/dist/i18n/locales/fr.js.map +1 -1
  120. package/dist/i18n/locales/hu.d.ts +13 -1
  121. package/dist/i18n/locales/hu.js +105 -1
  122. package/dist/i18n/locales/hu.js.map +1 -1
  123. package/dist/i18n/locales/it.d.ts +13 -1
  124. package/dist/i18n/locales/it.js +134 -34
  125. package/dist/i18n/locales/it.js.map +1 -1
  126. package/dist/i18n/locales/zh.d.ts +13 -1
  127. package/dist/i18n/locales/zh.js +101 -1
  128. package/dist/i18n/locales/zh.js.map +1 -1
  129. package/dist/i18n/review.d.ts +102 -0
  130. package/dist/i18n/review.js +158 -0
  131. package/dist/i18n/review.js.map +1 -0
  132. package/dist/i18n/swiss.d.ts +3 -3
  133. package/dist/i18n/swiss.js.map +1 -1
  134. package/dist/index.d.ts +17 -4
  135. package/dist/index.js +97 -1
  136. package/dist/index.js.map +1 -1
  137. package/dist/{kit-labels-C4uB_zmg.d.ts → kit-labels-D1J2_jyD.d.ts} +236 -9
  138. package/dist/lib/floating-stack.d.ts +31 -0
  139. package/dist/lib/floating-stack.js +42 -0
  140. package/dist/lib/floating-stack.js.map +1 -0
  141. package/dist/lib/server-wake.d.ts +146 -0
  142. package/dist/lib/server-wake.js +122 -0
  143. package/dist/lib/server-wake.js.map +1 -0
  144. package/dist/lib/translation-review.d.ts +232 -0
  145. package/dist/lib/translation-review.js +194 -0
  146. package/dist/lib/translation-review.js.map +1 -0
  147. package/dist/rhf/fields.d.ts +13 -1
  148. package/dist/rhf/form.d.ts +13 -1
  149. package/dist/rhf.d.ts +13 -1
  150. package/dist/search/global-search.d.ts +3 -1
  151. package/dist/search/global-search.js.map +1 -1
  152. package/dist/shell/app-shell.d.ts +13 -1
  153. package/dist/shell/top-bar-brand.d.ts +13 -1
  154. package/dist/shell/topbar-action-menu.d.ts +2 -0
  155. package/dist/shell.d.ts +13 -1
  156. package/dist/wizard/stepper-nav.d.ts +13 -1
  157. package/dist/wizard.d.ts +13 -1
  158. package/package.json +1 -1
  159. package/src/components/account-chips.tsx +302 -0
  160. package/src/components/account-settings-labels.ts +16 -2
  161. package/src/components/chip.tsx +239 -6
  162. package/src/components/confirm-dialog.tsx +82 -7
  163. package/src/components/danger-confirm.tsx +118 -33
  164. package/src/components/data-table.tsx +20 -0
  165. package/src/components/floating-panel.tsx +19 -1
  166. package/src/components/form-actions.tsx +22 -3
  167. package/src/components/legal.tsx +159 -0
  168. package/src/components/number-field.tsx +32 -26
  169. package/src/components/passkeys-setting.tsx +68 -7
  170. package/src/components/progress-bar.tsx +21 -1
  171. package/src/components/reauth-dialog.tsx +273 -0
  172. package/src/components/server-wake.tsx +156 -0
  173. package/src/components/share-card.tsx +615 -0
  174. package/src/components/toast.tsx +72 -2
  175. package/src/components/toggle-group.tsx +5 -2
  176. package/src/components/translation-review-editor.tsx +261 -0
  177. package/src/components/translation-review-labels.ts +152 -0
  178. package/src/components/translation-review-parts.tsx +269 -0
  179. package/src/components/translation-review.tsx +502 -0
  180. package/src/components/ui.tsx +89 -32
  181. package/src/components/write-lock.tsx +96 -0
  182. package/src/hooks/use-overlay-history.ts +51 -0
  183. package/src/i18n/defaults.ts +14 -0
  184. package/src/i18n/{locales/de.ts → german.ts} +120 -13
  185. package/src/i18n/kit-labels.tsx +29 -2
  186. package/src/i18n/languages.ts +285 -0
  187. package/src/i18n/locales/de-CH.ts +17 -8
  188. package/src/i18n/locales/en.ts +8 -0
  189. package/src/i18n/locales/es.ts +128 -26
  190. package/src/i18n/locales/fr.ts +103 -0
  191. package/src/i18n/locales/hu.ts +107 -0
  192. package/src/i18n/locales/it.ts +135 -33
  193. package/src/i18n/locales/zh.ts +102 -0
  194. package/src/i18n/review.ts +193 -0
  195. package/src/i18n/swiss.ts +3 -3
  196. package/src/index.ts +86 -1
  197. package/src/lib/floating-stack.ts +66 -0
  198. package/src/lib/server-wake.ts +291 -0
  199. package/src/lib/translation-review.ts +465 -0
  200. package/src/search/global-search.tsx +3 -1
  201. package/dist/i18n/locales/de-CH-informal.d.ts +0 -61
  202. package/dist/i18n/locales/de-CH-informal.js +0 -8
  203. package/dist/i18n/locales/de-CH-informal.js.map +0 -1
  204. package/dist/i18n/locales/de-informal.d.ts +0 -82
  205. package/dist/i18n/locales/de-informal.js +0 -37
  206. package/dist/i18n/locales/de-informal.js.map +0 -1
  207. package/dist/i18n/locales/de.d.ts +0 -66
  208. package/dist/i18n/locales/de.js.map +0 -1
  209. package/src/i18n/locales/de-CH-informal.ts +0 -10
  210. package/src/i18n/locales/de-informal.ts +0 -61
@@ -0,0 +1,243 @@
1
+ import { bc as UiKitLabels } from '../kit-labels-D1J2_jyD.js';
2
+ import { LanguageOption } from '../shell/topbar-controls.js';
3
+ import 'react';
4
+ import '../components/data-table-labels.js';
5
+ import '../components/mini-calendar.js';
6
+ import '../components/calendar-heatmap.js';
7
+ import '../components/popover.js';
8
+ import '../components/chip.js';
9
+ import 'lucide-react';
10
+ import '../components/field-sync.js';
11
+ import '../components/tooltip.js';
12
+ import '../hooks/use-anchored-rect.js';
13
+ import '../lib/clipping.js';
14
+ import '../wizard/types.js';
15
+ import '../tour/tour.js';
16
+ import '../search/command-palette.js';
17
+ import '../search/global-search.js';
18
+ import '../search/search-index.js';
19
+ import '../components/month-picker.js';
20
+ import '../components/page-contents.js';
21
+ import '../components/series-chart-labels.js';
22
+ import '../components/pie-chart-labels.js';
23
+ import '../components/sparkline.js';
24
+ import '../components/stat-tile.js';
25
+ import '../components/signature-pad.js';
26
+ import '../components/password-strength.js';
27
+ import '../components/danger-confirm.js';
28
+ import '../components/swatch-picker.js';
29
+ import '../components/tile-radio.js';
30
+ import '../components/icon-picker.js';
31
+ import '../components/dialog-frame.js';
32
+ import '../components/modal.js';
33
+ import '../hooks/use-search-param-state.js';
34
+ import '../components/measured-grid.js';
35
+ import '../feedback-attachment-WFiXJ8We.js';
36
+ import '../feedback/feedback-thread.js';
37
+ import '../feedback/feedback-inbox.js';
38
+ import '../components/account-settings-labels.js';
39
+ import '../components/confirm-dialog.js';
40
+ import '../components/floating-panel.js';
41
+ import '../components/bulk-action-bar.js';
42
+ import '../components/list.js';
43
+ import '../components/signed-amount.js';
44
+ import '../components/breadcrumbs.js';
45
+ import '../components/toast.js';
46
+ import '../components/description-list.js';
47
+ import '../components/line-items.js';
48
+ import '../components/progress-bar.js';
49
+ import '../components/error-boundary.js';
50
+ import '../components/authed-image.js';
51
+ import '../hooks/use-authed-src.js';
52
+ import '../components/image-grid.js';
53
+ import '../components/lightbox.js';
54
+ import '../components/write-lock.js';
55
+ import '../components/legal.js';
56
+ import '../components/account-chips.js';
57
+ import '../lib/format.js';
58
+ import '../data-table-3mi2R3so.js';
59
+ import '../components/data-table-sort.js';
60
+ import '../components/swipeable-row.js';
61
+ import '../components/reauth-dialog.js';
62
+ import '../components/server-wake.js';
63
+ import '../lib/server-wake.js';
64
+ import '../components/translation-review-labels.js';
65
+ import '../lib/translation-review.js';
66
+ import '../theme/palette-presets.js';
67
+ import '../theme/chart-palette.js';
68
+ import '../theme/theme-store.js';
69
+ import 'zustand/middleware';
70
+ import 'zustand';
71
+
72
+ /**
73
+ * "Which language is this reader in, and what does the kit say in it?" — the one
74
+ * answer the three apps each wrote for themselves (docs/i18n-harmonization.md, H2).
75
+ *
76
+ * kastlan, keksdose and Kurvenschmiede all ship a subset of the same seven languages,
77
+ * and every one of them hand-rolled the same three things: a list of languages with
78
+ * their names and flags, a rule for turning what a browser asks for (`de-AT`, `zh-TW`,
79
+ * `en-AU`) into a code the app ships, and a bridge from that code to the kit's label
80
+ * catalogue. The three disagreed where nobody was looking: a reader asking for `zh-TW`
81
+ * got German in kastlan and Chinese in Kurvenschmiede; keksdose's English got the raw
82
+ * defaults, so its counts read "12345" where the other two wrote "12,345"; kastlan
83
+ * formatted French as `fr-CH` and Kurvenschmiede as `fr-FR`. None of it was a decision.
84
+ * This module makes it one, in one place, tested once.
85
+ *
86
+ * WHAT IT IS NOT: an i18n library. It resolves no app strings, carries no detector and
87
+ * depends on nothing — the app keeps i18next (or whatever it uses) for its own words and
88
+ * asks this module only the questions the kit can answer for all three apps alike:
89
+ * - {@link KIT_LANGUAGES}: the seven codes, each with its own name, its English name,
90
+ * the flag it flies and the locale it formats in;
91
+ * - {@link resolveLanguage}: which of the codes an app offers answers a reader;
92
+ * - {@link formatLocaleOf}: the `Intl` tag for a code (the provider's `locale`,
93
+ * `<html lang>`, every `toLocaleString` in the app);
94
+ * - {@link loadUiKitLabels}: the kit's catalogue for a code, fetched on demand;
95
+ * - {@link languageOptions}: the rows `LanguageMenu` and `LanguageSetting` take.
96
+ *
97
+ * THE CODE AND THE FORMATTING LOCALE ARE TWO THINGS (Kurvenschmiede's insight, made
98
+ * the rule). The code names a catalogue — what the account stores, what i18next
99
+ * resolves, what a mail is chosen by — and a bare `en` says nothing about how a date is
100
+ * written. Each language formats like its home (Marcel, 2026-10-02, H6): `de-CH`,
101
+ * `en-GB` (British, like the spelling), `es-ES`, `fr-FR`, `it-IT`, `hu-HU`, `zh-CN`. An
102
+ * app that must format otherwise — kastlan's QR bill follows the SIX spec, not the
103
+ * reader — passes its own locale where it needs it; the registry is the default.
104
+ *
105
+ * THERE IS ONE GERMAN, `de-CH`: Swiss Standard German, formal (0.18). Every other
106
+ * German a browser or an old localStorage can hand over — `de`, `de-DE`, `de-AT`,
107
+ * `de-LI`, the briefly offered `de-informal` / `de-CH-informal` — is read as it.
108
+ * Its name is plain "Deutsch": it is the only German, so there is nothing to tell it
109
+ * apart from, and the Swiss flag beside it is what says where the spelling comes from.
110
+ *
111
+ * AND ONE CHINESE, `zh`, WHICH IS SIMPLIFIED. `zh-TW`, `zh-HK` and `zh-Hant` resolve to
112
+ * it: there is no Traditional catalogue, and a reader of Traditional characters reads
113
+ * Simplified far more readily than whichever second language a fallback would guess
114
+ * at (Kurvenschmiede's reasoning, now everyone's). Its name says "简体中文" so that
115
+ * reader sees what they are getting before they pick it.
116
+ */
117
+ /** The seven languages the kit ships a catalogue for. An app offers a subset. */
118
+ type KitLanguageCode = "de-CH" | "en" | "es" | "fr" | "it" | "hu" | "zh";
119
+ /** One language the kit ships: what it is called, which flag it flies and which
120
+ * BCP 47 tag it formats in. */
121
+ interface KitLanguage {
122
+ /** The catalogue code — what an app stores, sends and hands i18next. */
123
+ readonly code: KitLanguageCode;
124
+ /** The language's name in itself, for a switcher: the reader looking for theirs may
125
+ * not read the language the page is currently in. */
126
+ readonly nativeName: string;
127
+ /** The name in English, for places that list languages to a team rather than to a
128
+ * reader (a translation review's locale column, an admin's reviewer grant). */
129
+ readonly englishName: string;
130
+ /** The BCP 47 tag the language formats numbers and dates in, and declares itself in
131
+ * on `<html lang>`. See {@link formatLocaleOf}. */
132
+ readonly formatLocale: string;
133
+ /** ISO 3166-1 alpha-2 country (lowercase) for flag-icons' `fi fi-<flag>` class —
134
+ * NOT the language code: English flies the UK flag, German the Swiss one, Chinese
135
+ * the PRC's (the catalogue is Simplified). The kit renders the class name only; the
136
+ * app supplies the flag stylesheet (README, "What you install alongside it"). */
137
+ readonly flag: string;
138
+ }
139
+ /**
140
+ * Every language the kit ships, in the order a switcher lists them: alphabetical by
141
+ * native name (Deutsch, English, Español … 简体中文), which is what a reader scanning for
142
+ * their own language's name expects.
143
+ *
144
+ * An app offering four of them passes those four codes to {@link resolveLanguage} and
145
+ * {@link languageOptions}; it does not copy this list. A language added here is one the
146
+ * kit has a catalogue for (the loader map below is typed by {@link KitLanguageCode}, so
147
+ * a code without one does not compile).
148
+ */
149
+ declare const KIT_LANGUAGES: readonly KitLanguage[];
150
+ /**
151
+ * Which of the codes an app offers answers this reader.
152
+ *
153
+ * `candidates` are the reader's preferences **in precedence order**, and the first
154
+ * one that matches wins — so the order is the policy. The one the harmonisation plan
155
+ * gives every app (H5):
156
+ *
157
+ * resolveLanguage(
158
+ * [localStorage.getItem("<app>-lang"), user?.locale, ...navigator.languages],
159
+ * OFFERED,
160
+ * );
161
+ *
162
+ * the choice stored on this device (the reader picked it, here) → the account's
163
+ * language (read back on sign-in, so a new device starts in it) → the browser's list,
164
+ * in its own order → the fallback. Missing sources are simply `null` / `undefined`;
165
+ * they are skipped, as is an empty string.
166
+ *
167
+ * Each candidate is matched exactly (case-insensitively), then by language — every
168
+ * German variant to `de-CH`, every Chinese to `zh` (Simplified), any other regional
169
+ * form to its base language (`fr-CA` → `fr`, `en-AU` → `en`) — and only within
170
+ * `offered`: a reader whose browser says `es-MX` first and `en` second, in an app that
171
+ * offers no Spanish, gets English rather than the fallback. That is the difference
172
+ * from a single-tag lookup, and why the browser's whole list is passed, not its first
173
+ * entry.
174
+ *
175
+ * `fallback` is what a reader nothing matches gets: by default `de-CH` when the app
176
+ * offers it — the kit's and the three apps' home language — else the app's first
177
+ * offered code. It is returned as given, offered or not; the app chose it.
178
+ *
179
+ * Why not i18next's own matcher (`getBestMatchFromCodes`, which Kurvenschmiede calls):
180
+ * it needs an i18next instance, it reduces `de-AT` to a `de` none of the apps ships
181
+ * unless every caller remembers a converter first, and its answer to a list depends on
182
+ * `supportedLngs` and `nonExplicitSupportedLngs` being set exactly so. This is a pure
183
+ * function of its arguments, so the switcher, the account form, a server-rendered
184
+ * guess and a test all get the same answer without one.
185
+ */
186
+ declare function resolveLanguage(candidates: readonly (string | null | undefined)[], offered: readonly KitLanguageCode[], fallback?: KitLanguageCode): KitLanguageCode;
187
+ /**
188
+ * The BCP 47 tag a language formats in — `formatLocaleOf("en")` is `"en-GB"`.
189
+ *
190
+ * For `<UiKitProvider locale>`, for `<html lang>` (a screen reader pronounces by it,
191
+ * and `en` alone does not say which English) and for the app's own `Intl` calls, so
192
+ * the kit's counts and the app's amounts group their digits the same way.
193
+ *
194
+ * Takes any tag, not only a {@link KitLanguageCode}, and resolves it the way
195
+ * {@link resolveLanguage} does against all seven: `de-AT` formats as `de-CH`, `en-AU`
196
+ * as `en-GB` (the language's home, by decision — not the reader's region), and a
197
+ * language the kit does not ship as the home language, `de-CH`. So an app can hand it
198
+ * i18next's `resolvedLanguage` as it comes.
199
+ */
200
+ declare function formatLocaleOf(code: string): string;
201
+ /**
202
+ * The kit's catalogue for a language, fetched on demand and formatted in
203
+ * `formatLocale` — for `<UiKitProvider labels={…}>`.
204
+ *
205
+ * Every language goes through its catalogue's factory, English included:
206
+ * `uiKitLabelsEn("en-GB")` writes "12,345 rows" where the bare
207
+ * `DEFAULT_UI_KIT_LABELS` print "12345" (and keksdose's English did, by passing no
208
+ * labels at all). `formatLocale` defaults to the language's own
209
+ * ({@link formatLocaleOf}); pass another only for a reason, as the factories' own
210
+ * docs describe (`"de-DE"` keeps the Swiss words and writes German digits).
211
+ *
212
+ * `code` may be any tag and is resolved like {@link formatLocaleOf}'s, so `de` loads
213
+ * the one German and a language the kit does not ship loads `de-CH` — the same answer
214
+ * the app's own fallback gives, rather than English beside the app's German.
215
+ *
216
+ * Asynchronous on purpose, and there is no synchronous twin: one would have to import
217
+ * all seven catalogues statically, which puts every language in every app's entry
218
+ * chunk — exactly what one subpath per language exists to prevent. Await it before the
219
+ * first render, beside the app's own catalogue (the apps already await i18next's init
220
+ * for the same reason: no frame in the wrong language), and keep the result in state.
221
+ * To change a few words, spread over what it returns rather than copying a catalogue:
222
+ * a copy misses every key a later release adds.
223
+ *
224
+ * A rejected fetch (a deploy replaced the chunk, the device went offline) is not
225
+ * remembered, so the next call tries again.
226
+ */
227
+ declare function loadUiKitLabels(code: string, formatLocale?: string): Promise<UiKitLabels>;
228
+ /**
229
+ * The rows `LanguageMenu` and `LanguageSetting` take, for the codes an app offers, in
230
+ * the order given: `{ code, label: nativeName, country: flag }`.
231
+ *
232
+ * `LanguageMenu` draws `country` as a flag-icons class (`fi fi-ch`) and nothing more —
233
+ * the kit ships no flag artwork and no flag CSS, the app loads the stylesheet (or just
234
+ * the rules for its flags, as Kurvenschmiede and keksdose do). `LanguageSetting` is a
235
+ * native `<select>`, whose options can hold text only, so it shows the names and
236
+ * ignores `country`; the same array serves both.
237
+ *
238
+ * A label of the app's own (keksdose's "Deutsch (Schweiz)") is a `.map` over the
239
+ * result.
240
+ */
241
+ declare function languageOptions(codes?: readonly KitLanguageCode[]): LanguageOption[];
242
+
243
+ export { KIT_LANGUAGES, type KitLanguage, type KitLanguageCode, formatLocaleOf, languageOptions, loadUiKitLabels, resolveLanguage };
@@ -0,0 +1,70 @@
1
+ "use client";
2
+ const KIT_LANGUAGES = [
3
+ { code: "de-CH", nativeName: "Deutsch", englishName: "German", formatLocale: "de-CH", flag: "ch" },
4
+ { code: "en", nativeName: "English", englishName: "English", formatLocale: "en-GB", flag: "gb" },
5
+ { code: "es", nativeName: "Espa\xF1ol", englishName: "Spanish", formatLocale: "es-ES", flag: "es" },
6
+ { code: "fr", nativeName: "Fran\xE7ais", englishName: "French", formatLocale: "fr-FR", flag: "fr" },
7
+ { code: "it", nativeName: "Italiano", englishName: "Italian", formatLocale: "it-IT", flag: "it" },
8
+ { code: "hu", nativeName: "Magyar", englishName: "Hungarian", formatLocale: "hu-HU", flag: "hu" },
9
+ { code: "zh", nativeName: "\u7B80\u4F53\u4E2D\u6587", englishName: "Chinese (Simplified)", formatLocale: "zh-CN", flag: "cn" }
10
+ ];
11
+ const ALL_CODES = KIT_LANGUAGES.map((language) => language.code);
12
+ const HOME = "de-CH";
13
+ const languagePart = (tag) => tag.split("-")[0].toLowerCase();
14
+ function answer(candidate, offered) {
15
+ if (typeof candidate !== "string") return void 0;
16
+ const tag = candidate.trim().replace(/_/g, "-");
17
+ if (!tag) return void 0;
18
+ const lower = tag.toLowerCase();
19
+ const exact = offered.find((code) => code.toLowerCase() === lower);
20
+ if (exact) return exact;
21
+ const language = languagePart(tag);
22
+ return offered.find((code) => languagePart(code) === language);
23
+ }
24
+ function resolveLanguage(candidates, offered, fallback) {
25
+ for (const candidate of candidates) {
26
+ const found = answer(candidate, offered);
27
+ if (found) return found;
28
+ }
29
+ return fallback ?? (offered.includes(HOME) ? HOME : offered[0] ?? HOME);
30
+ }
31
+ function formatLocaleOf(code) {
32
+ const resolved = resolveLanguage([code], ALL_CODES);
33
+ return KIT_LANGUAGES.find((language) => language.code === resolved).formatLocale;
34
+ }
35
+ const LOADERS = {
36
+ "de-CH": async (locale) => (await import("./locales/de-CH.js")).uiKitLabelsDeCh(locale),
37
+ en: async (locale) => (await import("./locales/en.js")).uiKitLabelsEn(locale),
38
+ es: async (locale) => (await import("./locales/es.js")).uiKitLabelsEs(locale),
39
+ fr: async (locale) => (await import("./locales/fr.js")).uiKitLabelsFr(locale),
40
+ it: async (locale) => (await import("./locales/it.js")).uiKitLabelsIt(locale),
41
+ hu: async (locale) => (await import("./locales/hu.js")).uiKitLabelsHu(locale),
42
+ zh: async (locale) => (await import("./locales/zh.js")).uiKitLabelsZh(locale)
43
+ };
44
+ const loaded = /* @__PURE__ */ new Map();
45
+ function loadUiKitLabels(code, formatLocale = formatLocaleOf(code)) {
46
+ const language = resolveLanguage([code], ALL_CODES);
47
+ const key = `${language}\0${formatLocale}`;
48
+ let labels = loaded.get(key);
49
+ if (!labels) {
50
+ labels = LOADERS[language](formatLocale);
51
+ loaded.set(key, labels);
52
+ labels.catch(() => loaded.delete(key));
53
+ }
54
+ return labels;
55
+ }
56
+ function languageOptions(codes = ALL_CODES) {
57
+ return codes.flatMap((code) => {
58
+ const language = KIT_LANGUAGES.find((entry) => entry.code === code);
59
+ if (!language) return [];
60
+ return [{ code: language.code, label: language.nativeName, country: language.flag }];
61
+ });
62
+ }
63
+ export {
64
+ KIT_LANGUAGES,
65
+ formatLocaleOf,
66
+ languageOptions,
67
+ loadUiKitLabels,
68
+ resolveLanguage
69
+ };
70
+ //# sourceMappingURL=languages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/i18n/languages.ts"],"sourcesContent":["import type { UiKitLabels } from \"./kit-labels\";\nimport type { LanguageOption } from \"../shell/topbar-controls\";\n\n/**\n * \"Which language is this reader in, and what does the kit say in it?\" — the one\n * answer the three apps each wrote for themselves (docs/i18n-harmonization.md, H2).\n *\n * kastlan, keksdose and Kurvenschmiede all ship a subset of the same seven languages,\n * and every one of them hand-rolled the same three things: a list of languages with\n * their names and flags, a rule for turning what a browser asks for (`de-AT`, `zh-TW`,\n * `en-AU`) into a code the app ships, and a bridge from that code to the kit's label\n * catalogue. The three disagreed where nobody was looking: a reader asking for `zh-TW`\n * got German in kastlan and Chinese in Kurvenschmiede; keksdose's English got the raw\n * defaults, so its counts read \"12345\" where the other two wrote \"12,345\"; kastlan\n * formatted French as `fr-CH` and Kurvenschmiede as `fr-FR`. None of it was a decision.\n * This module makes it one, in one place, tested once.\n *\n * WHAT IT IS NOT: an i18n library. It resolves no app strings, carries no detector and\n * depends on nothing — the app keeps i18next (or whatever it uses) for its own words and\n * asks this module only the questions the kit can answer for all three apps alike:\n * - {@link KIT_LANGUAGES}: the seven codes, each with its own name, its English name,\n * the flag it flies and the locale it formats in;\n * - {@link resolveLanguage}: which of the codes an app offers answers a reader;\n * - {@link formatLocaleOf}: the `Intl` tag for a code (the provider's `locale`,\n * `<html lang>`, every `toLocaleString` in the app);\n * - {@link loadUiKitLabels}: the kit's catalogue for a code, fetched on demand;\n * - {@link languageOptions}: the rows `LanguageMenu` and `LanguageSetting` take.\n *\n * THE CODE AND THE FORMATTING LOCALE ARE TWO THINGS (Kurvenschmiede's insight, made\n * the rule). The code names a catalogue — what the account stores, what i18next\n * resolves, what a mail is chosen by — and a bare `en` says nothing about how a date is\n * written. Each language formats like its home (Marcel, 2026-10-02, H6): `de-CH`,\n * `en-GB` (British, like the spelling), `es-ES`, `fr-FR`, `it-IT`, `hu-HU`, `zh-CN`. An\n * app that must format otherwise — kastlan's QR bill follows the SIX spec, not the\n * reader — passes its own locale where it needs it; the registry is the default.\n *\n * THERE IS ONE GERMAN, `de-CH`: Swiss Standard German, formal (0.18). Every other\n * German a browser or an old localStorage can hand over — `de`, `de-DE`, `de-AT`,\n * `de-LI`, the briefly offered `de-informal` / `de-CH-informal` — is read as it.\n * Its name is plain \"Deutsch\": it is the only German, so there is nothing to tell it\n * apart from, and the Swiss flag beside it is what says where the spelling comes from.\n *\n * AND ONE CHINESE, `zh`, WHICH IS SIMPLIFIED. `zh-TW`, `zh-HK` and `zh-Hant` resolve to\n * it: there is no Traditional catalogue, and a reader of Traditional characters reads\n * Simplified far more readily than whichever second language a fallback would guess\n * at (Kurvenschmiede's reasoning, now everyone's). Its name says \"简体中文\" so that\n * reader sees what they are getting before they pick it.\n */\n\n/** The seven languages the kit ships a catalogue for. An app offers a subset. */\nexport type KitLanguageCode = \"de-CH\" | \"en\" | \"es\" | \"fr\" | \"it\" | \"hu\" | \"zh\";\n\n/** One language the kit ships: what it is called, which flag it flies and which\n * BCP 47 tag it formats in. */\nexport interface KitLanguage {\n /** The catalogue code — what an app stores, sends and hands i18next. */\n readonly code: KitLanguageCode;\n /** The language's name in itself, for a switcher: the reader looking for theirs may\n * not read the language the page is currently in. */\n readonly nativeName: string;\n /** The name in English, for places that list languages to a team rather than to a\n * reader (a translation review's locale column, an admin's reviewer grant). */\n readonly englishName: string;\n /** The BCP 47 tag the language formats numbers and dates in, and declares itself in\n * on `<html lang>`. See {@link formatLocaleOf}. */\n readonly formatLocale: string;\n /** ISO 3166-1 alpha-2 country (lowercase) for flag-icons' `fi fi-<flag>` class —\n * NOT the language code: English flies the UK flag, German the Swiss one, Chinese\n * the PRC's (the catalogue is Simplified). The kit renders the class name only; the\n * app supplies the flag stylesheet (README, \"What you install alongside it\"). */\n readonly flag: string;\n}\n\n/**\n * Every language the kit ships, in the order a switcher lists them: alphabetical by\n * native name (Deutsch, English, Español … 简体中文), which is what a reader scanning for\n * their own language's name expects.\n *\n * An app offering four of them passes those four codes to {@link resolveLanguage} and\n * {@link languageOptions}; it does not copy this list. A language added here is one the\n * kit has a catalogue for (the loader map below is typed by {@link KitLanguageCode}, so\n * a code without one does not compile).\n */\nexport const KIT_LANGUAGES: readonly KitLanguage[] = [\n { code: \"de-CH\", nativeName: \"Deutsch\", englishName: \"German\", formatLocale: \"de-CH\", flag: \"ch\" },\n { code: \"en\", nativeName: \"English\", englishName: \"English\", formatLocale: \"en-GB\", flag: \"gb\" },\n { code: \"es\", nativeName: \"Español\", englishName: \"Spanish\", formatLocale: \"es-ES\", flag: \"es\" },\n { code: \"fr\", nativeName: \"Français\", englishName: \"French\", formatLocale: \"fr-FR\", flag: \"fr\" },\n { code: \"it\", nativeName: \"Italiano\", englishName: \"Italian\", formatLocale: \"it-IT\", flag: \"it\" },\n { code: \"hu\", nativeName: \"Magyar\", englishName: \"Hungarian\", formatLocale: \"hu-HU\", flag: \"hu\" },\n { code: \"zh\", nativeName: \"简体中文\", englishName: \"Chinese (Simplified)\", formatLocale: \"zh-CN\", flag: \"cn\" },\n];\n\nconst ALL_CODES: readonly KitLanguageCode[] = KIT_LANGUAGES.map((language) => language.code);\n\n/** The kit's home language: what a reader nothing else matches gets, when it is offered. */\nconst HOME: KitLanguageCode = \"de-CH\";\n\n/** The language part of a tag, lower-cased: `de-CH-informal` → `de`, `zh_Hant` → `zh`. */\nconst languagePart = (tag: string) => tag.split(\"-\")[0].toLowerCase();\n\n/**\n * The offered code that answers ONE requested tag, or `undefined`.\n *\n * Exact first, ignoring case (`DE-ch` → `de-CH`), then by language part: since the kit\n * has exactly one code per language, \"the offered code whose language is the tag's\n * language\" is the whole of the rule, and it is what takes every German to `de-CH`\n * (`de-AT`, `de-informal`), every Chinese to `zh` (`zh-TW`, `zh-Hant-HK`) and every\n * regional form to its base (`fr-CA` → `fr`, `en-AU` → `en`). A language the app does\n * not offer answers nothing, so the caller moves on to the reader's next preference\n * rather than landing on a guess. Underscores are read as hyphens (`de_CH`), the way a\n * Java or Python backend may have stored the account's locale.\n */\nfunction answer(\n candidate: unknown,\n offered: readonly KitLanguageCode[],\n): KitLanguageCode | undefined {\n if (typeof candidate !== \"string\") return undefined;\n const tag = candidate.trim().replace(/_/g, \"-\");\n if (!tag) return undefined;\n const lower = tag.toLowerCase();\n const exact = offered.find((code) => code.toLowerCase() === lower);\n if (exact) return exact;\n const language = languagePart(tag);\n return offered.find((code) => languagePart(code) === language);\n}\n\n/**\n * Which of the codes an app offers answers this reader.\n *\n * `candidates` are the reader's preferences **in precedence order**, and the first\n * one that matches wins — so the order is the policy. The one the harmonisation plan\n * gives every app (H5):\n *\n * resolveLanguage(\n * [localStorage.getItem(\"<app>-lang\"), user?.locale, ...navigator.languages],\n * OFFERED,\n * );\n *\n * the choice stored on this device (the reader picked it, here) → the account's\n * language (read back on sign-in, so a new device starts in it) → the browser's list,\n * in its own order → the fallback. Missing sources are simply `null` / `undefined`;\n * they are skipped, as is an empty string.\n *\n * Each candidate is matched exactly (case-insensitively), then by language — every\n * German variant to `de-CH`, every Chinese to `zh` (Simplified), any other regional\n * form to its base language (`fr-CA` → `fr`, `en-AU` → `en`) — and only within\n * `offered`: a reader whose browser says `es-MX` first and `en` second, in an app that\n * offers no Spanish, gets English rather than the fallback. That is the difference\n * from a single-tag lookup, and why the browser's whole list is passed, not its first\n * entry.\n *\n * `fallback` is what a reader nothing matches gets: by default `de-CH` when the app\n * offers it — the kit's and the three apps' home language — else the app's first\n * offered code. It is returned as given, offered or not; the app chose it.\n *\n * Why not i18next's own matcher (`getBestMatchFromCodes`, which Kurvenschmiede calls):\n * it needs an i18next instance, it reduces `de-AT` to a `de` none of the apps ships\n * unless every caller remembers a converter first, and its answer to a list depends on\n * `supportedLngs` and `nonExplicitSupportedLngs` being set exactly so. This is a pure\n * function of its arguments, so the switcher, the account form, a server-rendered\n * guess and a test all get the same answer without one.\n */\nexport function resolveLanguage(\n candidates: readonly (string | null | undefined)[],\n offered: readonly KitLanguageCode[],\n fallback?: KitLanguageCode,\n): KitLanguageCode {\n for (const candidate of candidates) {\n const found = answer(candidate, offered);\n if (found) return found;\n }\n return fallback ?? (offered.includes(HOME) ? HOME : (offered[0] ?? HOME));\n}\n\n/**\n * The BCP 47 tag a language formats in — `formatLocaleOf(\"en\")` is `\"en-GB\"`.\n *\n * For `<UiKitProvider locale>`, for `<html lang>` (a screen reader pronounces by it,\n * and `en` alone does not say which English) and for the app's own `Intl` calls, so\n * the kit's counts and the app's amounts group their digits the same way.\n *\n * Takes any tag, not only a {@link KitLanguageCode}, and resolves it the way\n * {@link resolveLanguage} does against all seven: `de-AT` formats as `de-CH`, `en-AU`\n * as `en-GB` (the language's home, by decision — not the reader's region), and a\n * language the kit does not ship as the home language, `de-CH`. So an app can hand it\n * i18next's `resolvedLanguage` as it comes.\n */\nexport function formatLocaleOf(code: string): string {\n const resolved = resolveLanguage([code], ALL_CODES);\n return KIT_LANGUAGES.find((language) => language.code === resolved)!.formatLocale;\n}\n\n/**\n * One loader per catalogue, each a LITERAL relative `import()`.\n *\n * The literal is load-bearing twice. The library is built one file per module\n * (`bundle: false`, tsup.config.ts), so `./locales/fr` stays a module of its own in\n * dist/ and `scripts/fix-esm-extensions.mjs` gives the specifier its `.js`. And an\n * app's bundler can only split what it can read: a path assembled from a code is a\n * chunk rollup cannot make, and the failure is at runtime. With literals, each\n * language is a chunk of its own and a reader downloads exactly theirs — about 25 kB of\n * JavaScript a catalogue, so an entry chunk holding all of them would carry six that\n * the reader never uses.\n *\n * Relative, not `@eifi1/ui-kit/i18n/fr`: a package importing itself by name resolves\n * through the consumer's node_modules, which a linked checkout or a test of this repo\n * does not have.\n */\nconst LOADERS: Record<KitLanguageCode, (formatLocale: string) => Promise<UiKitLabels>> = {\n \"de-CH\": async (locale) => (await import(\"./locales/de-CH\")).uiKitLabelsDeCh(locale),\n en: async (locale) => (await import(\"./locales/en\")).uiKitLabelsEn(locale),\n es: async (locale) => (await import(\"./locales/es\")).uiKitLabelsEs(locale),\n fr: async (locale) => (await import(\"./locales/fr\")).uiKitLabelsFr(locale),\n it: async (locale) => (await import(\"./locales/it\")).uiKitLabelsIt(locale),\n hu: async (locale) => (await import(\"./locales/hu\")).uiKitLabelsHu(locale),\n zh: async (locale) => (await import(\"./locales/zh\")).uiKitLabelsZh(locale),\n};\n\n/** One promise per (language, format locale), so asking twice is one fetch and one\n * object: the provider's context value keeps its identity, and every kit component\n * reading it is spared a re-render on a switch back. */\nconst loaded = new Map<string, Promise<UiKitLabels>>();\n\n/**\n * The kit's catalogue for a language, fetched on demand and formatted in\n * `formatLocale` — for `<UiKitProvider labels={…}>`.\n *\n * Every language goes through its catalogue's factory, English included:\n * `uiKitLabelsEn(\"en-GB\")` writes \"12,345 rows\" where the bare\n * `DEFAULT_UI_KIT_LABELS` print \"12345\" (and keksdose's English did, by passing no\n * labels at all). `formatLocale` defaults to the language's own\n * ({@link formatLocaleOf}); pass another only for a reason, as the factories' own\n * docs describe (`\"de-DE\"` keeps the Swiss words and writes German digits).\n *\n * `code` may be any tag and is resolved like {@link formatLocaleOf}'s, so `de` loads\n * the one German and a language the kit does not ship loads `de-CH` — the same answer\n * the app's own fallback gives, rather than English beside the app's German.\n *\n * Asynchronous on purpose, and there is no synchronous twin: one would have to import\n * all seven catalogues statically, which puts every language in every app's entry\n * chunk — exactly what one subpath per language exists to prevent. Await it before the\n * first render, beside the app's own catalogue (the apps already await i18next's init\n * for the same reason: no frame in the wrong language), and keep the result in state.\n * To change a few words, spread over what it returns rather than copying a catalogue:\n * a copy misses every key a later release adds.\n *\n * A rejected fetch (a deploy replaced the chunk, the device went offline) is not\n * remembered, so the next call tries again.\n */\nexport function loadUiKitLabels(\n code: string,\n formatLocale: string = formatLocaleOf(code),\n): Promise<UiKitLabels> {\n const language = resolveLanguage([code], ALL_CODES);\n const key = `${language}\\u0000${formatLocale}`;\n let labels = loaded.get(key);\n if (!labels) {\n labels = LOADERS[language](formatLocale);\n loaded.set(key, labels);\n labels.catch(() => loaded.delete(key));\n }\n return labels;\n}\n\n/**\n * The rows `LanguageMenu` and `LanguageSetting` take, for the codes an app offers, in\n * the order given: `{ code, label: nativeName, country: flag }`.\n *\n * `LanguageMenu` draws `country` as a flag-icons class (`fi fi-ch`) and nothing more —\n * the kit ships no flag artwork and no flag CSS, the app loads the stylesheet (or just\n * the rules for its flags, as Kurvenschmiede and keksdose do). `LanguageSetting` is a\n * native `<select>`, whose options can hold text only, so it shows the names and\n * ignores `country`; the same array serves both.\n *\n * A label of the app's own (keksdose's \"Deutsch (Schweiz)\") is a `.map` over the\n * result.\n */\nexport function languageOptions(codes: readonly KitLanguageCode[] = ALL_CODES): LanguageOption[] {\n return codes.flatMap((code) => {\n const language = KIT_LANGUAGES.find((entry) => entry.code === code);\n if (!language) return [];\n return [{ code: language.code, label: language.nativeName, country: language.flag }];\n });\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,4 @@
1
- import { a$ as UiKitLabels } from '../../kit-labels-C4uB_zmg.js';
1
+ import { bc as UiKitLabels } from '../../kit-labels-D1J2_jyD.js';
2
2
  import 'react';
3
3
  import '../../components/data-table-labels.js';
4
4
  import '../../components/mini-calendar.js';
@@ -50,17 +50,35 @@ import '../../components/authed-image.js';
50
50
  import '../../hooks/use-authed-src.js';
51
51
  import '../../components/image-grid.js';
52
52
  import '../../components/lightbox.js';
53
+ import '../../components/write-lock.js';
54
+ import '../../components/legal.js';
55
+ import '../../components/account-chips.js';
56
+ import '../../lib/format.js';
57
+ import '../../data-table-3mi2R3so.js';
58
+ import '../../components/data-table-sort.js';
59
+ import '../../components/swipeable-row.js';
60
+ import '../../components/reauth-dialog.js';
61
+ import '../../components/server-wake.js';
62
+ import '../../lib/server-wake.js';
63
+ import '../../components/translation-review-labels.js';
64
+ import '../../lib/translation-review.js';
53
65
 
54
66
  /**
55
- * Swiss Standard German: the German labels with Swiss spelling — "ss" for every "ß"
56
- * (Schliessen, Grösse), which is the one systematic difference in UI text — and
67
+ * The kit's words in German — Swiss Standard German, formal ("Sie"), the kit's ONE German
68
+ * catalogue: `<UiKitProvider labels={UI_KIT_LABELS_DE_CH}>`. Swiss spelling — "ss" for
69
+ * every "ß" (Schliessen, Grösse), which is the one systematic difference in UI text — and
57
70
  * `de-CH` number formatting (1’234.5).
58
71
  *
59
- * Derived rather than duplicated, so a key added to the German labels is Swiss the
60
- * moment it lands. Function labels are wrapped: their RESULT is respelled, so an
61
- * argument the app passes in (a file name, a phrase to type) is respelled too — which
62
- * is what a Swiss app writing "ss" everywhere wants.
72
+ * Derived from the internal German source (`../german`) rather than written out, so a
73
+ * key added there is Swiss the moment it lands. Function labels are wrapped: their
74
+ * RESULT is respelled, so an argument the app passes in (a file name, a phrase to type)
75
+ * is respelled too — which is what a Swiss app writing "ss" everywhere wants.
76
+ *
77
+ * {@link uiKitLabelsDeCh} takes another number locale (e.g. `"de-DE"` for 1.234,5, or
78
+ * `"de-AT"`) without touching the words — the spelling stays Swiss, as the factories of
79
+ * the other catalogues keep their words.
63
80
  */
81
+ declare function uiKitLabelsDeCh(numberLocale?: string): UiKitLabels;
64
82
  declare const UI_KIT_LABELS_DE_CH: UiKitLabels;
65
83
 
66
- export { UI_KIT_LABELS_DE_CH };
84
+ export { UI_KIT_LABELS_DE_CH, uiKitLabelsDeCh };
@@ -1,8 +1,12 @@
1
1
  "use client";
2
+ import { germanLabels } from "../german.js";
2
3
  import { swiss } from "../swiss.js";
3
- import { uiKitLabelsDe } from "./de.js";
4
- const UI_KIT_LABELS_DE_CH = swiss(uiKitLabelsDe("de-CH"));
4
+ function uiKitLabelsDeCh(numberLocale = "de-CH") {
5
+ return swiss(germanLabels(numberLocale));
6
+ }
7
+ const UI_KIT_LABELS_DE_CH = uiKitLabelsDeCh();
5
8
  export {
6
- UI_KIT_LABELS_DE_CH
9
+ UI_KIT_LABELS_DE_CH,
10
+ uiKitLabelsDeCh
7
11
  };
8
12
  //# sourceMappingURL=de-CH.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/i18n/locales/de-CH.ts"],"sourcesContent":["import type { UiKitLabels } from \"../kit-labels\";\nimport { swiss } from \"../swiss\";\nimport { uiKitLabelsDe } from \"./de\";\n\n/**\n * Swiss Standard German: the German labels with Swiss spelling — \"ss\" for every \"ß\"\n * (Schliessen, Grösse), which is the one systematic difference in UI text — and\n * `de-CH` number formatting (1’234.5).\n *\n * Derived rather than duplicated, so a key added to the German labels is Swiss the\n * moment it lands. Function labels are wrapped: their RESULT is respelled, so an\n * argument the app passes in (a file name, a phrase to type) is respelled too — which\n * is what a Swiss app writing \"ss\" everywhere wants.\n */\nexport const UI_KIT_LABELS_DE_CH: UiKitLabels = swiss(uiKitLabelsDe(\"de-CH\"));\n"],"mappings":";AACA,SAAS,aAAa;AACtB,SAAS,qBAAqB;AAYvB,MAAM,sBAAmC,MAAM,cAAc,OAAO,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/i18n/locales/de-CH.ts"],"sourcesContent":["import type { UiKitLabels } from \"../kit-labels\";\nimport { germanLabels } from \"../german\";\nimport { swiss } from \"../swiss\";\n\n/**\n * The kit's words in German — Swiss Standard German, formal (\"Sie\"), the kit's ONE German\n * catalogue: `<UiKitProvider labels={UI_KIT_LABELS_DE_CH}>`. Swiss spelling — \"ss\" for\n * every \"ß\" (Schliessen, Grösse), which is the one systematic difference in UI text — and\n * `de-CH` number formatting (1’234.5).\n *\n * Derived from the internal German source (`../german`) rather than written out, so a\n * key added there is Swiss the moment it lands. Function labels are wrapped: their\n * RESULT is respelled, so an argument the app passes in (a file name, a phrase to type)\n * is respelled too — which is what a Swiss app writing \"ss\" everywhere wants.\n *\n * {@link uiKitLabelsDeCh} takes another number locale (e.g. `\"de-DE\"` for 1.234,5, or\n * `\"de-AT\"`) without touching the words — the spelling stays Swiss, as the factories of\n * the other catalogues keep their words.\n */\nexport function uiKitLabelsDeCh(numberLocale = \"de-CH\"): UiKitLabels {\n return swiss(germanLabels(numberLocale));\n}\n\nexport const UI_KIT_LABELS_DE_CH: UiKitLabels = uiKitLabelsDeCh();\n"],"mappings":";AACA,SAAS,oBAAoB;AAC7B,SAAS,aAAa;AAiBf,SAAS,gBAAgB,eAAe,SAAsB;AACnE,SAAO,MAAM,aAAa,YAAY,CAAC;AACzC;AAEO,MAAM,sBAAmC,gBAAgB;","names":[]}
@@ -1,4 +1,4 @@
1
- import { a$ as UiKitLabels } from '../../kit-labels-C4uB_zmg.js';
1
+ import { bc as UiKitLabels } from '../../kit-labels-D1J2_jyD.js';
2
2
  import 'react';
3
3
  import '../../components/data-table-labels.js';
4
4
  import '../../components/mini-calendar.js';
@@ -50,6 +50,18 @@ import '../../components/authed-image.js';
50
50
  import '../../hooks/use-authed-src.js';
51
51
  import '../../components/image-grid.js';
52
52
  import '../../components/lightbox.js';
53
+ import '../../components/write-lock.js';
54
+ import '../../components/legal.js';
55
+ import '../../components/account-chips.js';
56
+ import '../../lib/format.js';
57
+ import '../../data-table-3mi2R3so.js';
58
+ import '../../components/data-table-sort.js';
59
+ import '../../components/swipeable-row.js';
60
+ import '../../components/reauth-dialog.js';
61
+ import '../../components/server-wake.js';
62
+ import '../../lib/server-wake.js';
63
+ import '../../components/translation-review-labels.js';
64
+ import '../../lib/translation-review.js';
53
65
 
54
66
  /**
55
67
  * The kit's English words with every count and file size formatted for
@@ -86,6 +86,14 @@ function uiKitLabelsEn(numberLocale = "en-US") {
86
86
  ...d.lightbox,
87
87
  counter: (index, count) => `${n(index)} / ${n(count)}`,
88
88
  position: (index, count) => `Image ${n(index)} of ${n(count)}`
89
+ },
90
+ translationReview: {
91
+ ...d.translationReview,
92
+ filterCount: (label, count) => `${label} \xB7 ${n(count)}`,
93
+ placeholdersOnly: (count) => `Only placeholder problems (${n(count)})`,
94
+ progress: (approved, total) => `${n(approved)} of ${n(total)} approved`,
95
+ localeProgress: (approved, total) => `${n(approved)}/${n(total)}`,
96
+ exportCorrections: (count) => `Export corrections (${n(count)})`
89
97
  }
90
98
  };
91
99
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/i18n/locales/en.ts"],"sourcesContent":["import { DEFAULT_UI_KIT_LABELS } from \"../defaults\";\nimport { formatFileSize } from \"../kit-labels\";\nimport type { UiKitLabels } from \"../kit-labels\";\n\n/**\n * The kit's English words with every count and file size formatted for\n * `numberLocale` — `uiKitLabelsEn(\"en-CH\")` reads \"12’345 rows\", where the defaults\n * print \"12345\". For `<UiKitProvider labels={uiKitLabelsEn(\"en-CH\")}>`.\n *\n * A factory and not a constant on purpose: {@link DEFAULT_UI_KIT_LABELS} prints counts\n * raw and has since 0.1, so an app that passes nothing must keep seeing exactly that.\n * Formatting is something an app asks for, by calling this.\n *\n * Derived rather than copied: every word is the default's own, spread in, and only the\n * labels that print a number are restated — with the same wording and the same\n * singular/plural split — so a key added to the defaults is here the moment it lands.\n * Row and line numbers (`lineItems.row`, `measuredGrid.cell`) are positions, not\n * counts, and stay as the defaults print them, as in the other catalogues.\n */\nexport function uiKitLabelsEn(numberLocale = \"en-US\"): UiKitLabels {\n const num = new Intl.NumberFormat(numberLocale);\n const n = (value: number) => num.format(value);\n const d = DEFAULT_UI_KIT_LABELS;\n\n return {\n ...d,\n feedbackAttachment: {\n ...d.feedbackAttachment,\n attachmentLimit: (max) =>\n `Up to ${n(max)} ${max === 1 ? \"attachment\" : \"attachments\"} — remove one to add another.`,\n },\n measuredGrid: {\n ...d.measuredGrid,\n points: (count) => (count === 1 ? \"1 point\" : `${n(count)} points`),\n problems: (count) =>\n count === 1 ? \"1 cell is not a number\" : `${n(count)} cells are not numbers`,\n },\n dataTable: {\n ...d.dataTable,\n filterResults: (shown, total) => `${n(shown)} of ${n(total)} rows`,\n pageChanged: (page, totalPages) => `Page ${n(page)} of ${n(totalPages)}`,\n pageRange: (from, to, total) => `${n(from)}–${n(to)} / ${n(total)}`,\n rowCount: (total) => n(total),\n columnsCount: (visible, total) => `Columns (${n(visible)}/${n(total)})`,\n },\n calendarHeatmap: {\n ...d.calendarHeatmap,\n truncated: (count) =>\n `Showing the most recent days; ${n(count)} earlier ${count === 1 ? \"day is\" : \"days are\"} not shown.`,\n },\n combobox: {\n ...d.combobox,\n selectedCount: (count) => `${n(count)} selected`,\n resultCount: (count) => (count === 1 ? \"1 result\" : `${n(count)} results`),\n minChars: (count) =>\n count === 1 ? \"Type at least 1 character\" : `Type at least ${n(count)} characters`,\n },\n multiSelect: {\n ...d.multiSelect,\n selectedCount: (count) => n(count),\n },\n chipInput: {\n ...d.chipInput,\n atLimit: (max) => `Limit of ${n(max)} reached`,\n },\n iconPicker: {\n ...d.iconPicker,\n resultCount: (count) => (count === 1 ? \"1 icon\" : `${n(count)} icons`),\n },\n bulkActionBar: {\n ...d.bulkActionBar,\n selected: (count) => `${n(count)} selected`,\n },\n file: {\n // The kit's own `Intl` unit formatting, pinned to this locale (\"3.4 MB\").\n size: (bytes) => formatFileSize(bytes, numberLocale),\n },\n filePicker: {\n ...d.filePicker,\n rejectedCount: (name, maxFiles) =>\n `“${name}” was not added: at most ${n(maxFiles)} ${maxFiles === 1 ? \"file\" : \"files\"}`,\n rejectedMany: (count) => `${n(count)} files were not added`,\n rejectedPick: (count) =>\n count === 1 ? \"The file was not added\" : `None of the ${n(count)} files were added`,\n selected: (count, firstName) =>\n count === 1 ? `“${firstName}” selected` : `${n(count)} files selected`,\n },\n wizard: {\n ...d.wizard,\n step: (current, total) => `Step ${n(current)} of ${n(total)}`,\n },\n tour: {\n ...d.tour,\n step: (current, total) => `${n(current)} / ${n(total)}`,\n },\n passwordStrength: {\n ...d.passwordStrength,\n ruleLength: (minLength) => `At least ${n(minLength)} characters`,\n tooLong: (maxBytes) =>\n `At most ${n(maxBytes)} characters (accents and emoji count for more than one).`,\n },\n floatingPanel: {\n ...d.floatingPanel,\n badge: (count) => `${n(count)} new`,\n },\n imageGrid: {\n ...d.imageGrid,\n item: (index, count) => `Image ${n(index)} of ${n(count)}`,\n },\n lightbox: {\n ...d.lightbox,\n counter: (index, count) => `${n(index)} / ${n(count)}`,\n position: (index, count) => `Image ${n(index)} of ${n(count)}`,\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/i18n/locales/en.ts"],"sourcesContent":["import { DEFAULT_UI_KIT_LABELS } from \"../defaults\";\nimport { formatFileSize } from \"../kit-labels\";\nimport type { UiKitLabels } from \"../kit-labels\";\n\n/**\n * The kit's English words with every count and file size formatted for\n * `numberLocale` — `uiKitLabelsEn(\"en-CH\")` reads \"12’345 rows\", where the defaults\n * print \"12345\". For `<UiKitProvider labels={uiKitLabelsEn(\"en-CH\")}>`.\n *\n * A factory and not a constant on purpose: {@link DEFAULT_UI_KIT_LABELS} prints counts\n * raw and has since 0.1, so an app that passes nothing must keep seeing exactly that.\n * Formatting is something an app asks for, by calling this.\n *\n * Derived rather than copied: every word is the default's own, spread in, and only the\n * labels that print a number are restated — with the same wording and the same\n * singular/plural split — so a key added to the defaults is here the moment it lands.\n * Row and line numbers (`lineItems.row`, `measuredGrid.cell`) are positions, not\n * counts, and stay as the defaults print them, as in the other catalogues.\n */\nexport function uiKitLabelsEn(numberLocale = \"en-US\"): UiKitLabels {\n const num = new Intl.NumberFormat(numberLocale);\n const n = (value: number) => num.format(value);\n const d = DEFAULT_UI_KIT_LABELS;\n\n return {\n ...d,\n feedbackAttachment: {\n ...d.feedbackAttachment,\n attachmentLimit: (max) =>\n `Up to ${n(max)} ${max === 1 ? \"attachment\" : \"attachments\"} — remove one to add another.`,\n },\n measuredGrid: {\n ...d.measuredGrid,\n points: (count) => (count === 1 ? \"1 point\" : `${n(count)} points`),\n problems: (count) =>\n count === 1 ? \"1 cell is not a number\" : `${n(count)} cells are not numbers`,\n },\n dataTable: {\n ...d.dataTable,\n filterResults: (shown, total) => `${n(shown)} of ${n(total)} rows`,\n pageChanged: (page, totalPages) => `Page ${n(page)} of ${n(totalPages)}`,\n pageRange: (from, to, total) => `${n(from)}–${n(to)} / ${n(total)}`,\n rowCount: (total) => n(total),\n columnsCount: (visible, total) => `Columns (${n(visible)}/${n(total)})`,\n },\n calendarHeatmap: {\n ...d.calendarHeatmap,\n truncated: (count) =>\n `Showing the most recent days; ${n(count)} earlier ${count === 1 ? \"day is\" : \"days are\"} not shown.`,\n },\n combobox: {\n ...d.combobox,\n selectedCount: (count) => `${n(count)} selected`,\n resultCount: (count) => (count === 1 ? \"1 result\" : `${n(count)} results`),\n minChars: (count) =>\n count === 1 ? \"Type at least 1 character\" : `Type at least ${n(count)} characters`,\n },\n multiSelect: {\n ...d.multiSelect,\n selectedCount: (count) => n(count),\n },\n chipInput: {\n ...d.chipInput,\n atLimit: (max) => `Limit of ${n(max)} reached`,\n },\n iconPicker: {\n ...d.iconPicker,\n resultCount: (count) => (count === 1 ? \"1 icon\" : `${n(count)} icons`),\n },\n bulkActionBar: {\n ...d.bulkActionBar,\n selected: (count) => `${n(count)} selected`,\n },\n file: {\n // The kit's own `Intl` unit formatting, pinned to this locale (\"3.4 MB\").\n size: (bytes) => formatFileSize(bytes, numberLocale),\n },\n filePicker: {\n ...d.filePicker,\n rejectedCount: (name, maxFiles) =>\n `“${name}” was not added: at most ${n(maxFiles)} ${maxFiles === 1 ? \"file\" : \"files\"}`,\n rejectedMany: (count) => `${n(count)} files were not added`,\n rejectedPick: (count) =>\n count === 1 ? \"The file was not added\" : `None of the ${n(count)} files were added`,\n selected: (count, firstName) =>\n count === 1 ? `“${firstName}” selected` : `${n(count)} files selected`,\n },\n wizard: {\n ...d.wizard,\n step: (current, total) => `Step ${n(current)} of ${n(total)}`,\n },\n tour: {\n ...d.tour,\n step: (current, total) => `${n(current)} / ${n(total)}`,\n },\n passwordStrength: {\n ...d.passwordStrength,\n ruleLength: (minLength) => `At least ${n(minLength)} characters`,\n tooLong: (maxBytes) =>\n `At most ${n(maxBytes)} characters (accents and emoji count for more than one).`,\n },\n floatingPanel: {\n ...d.floatingPanel,\n badge: (count) => `${n(count)} new`,\n },\n imageGrid: {\n ...d.imageGrid,\n item: (index, count) => `Image ${n(index)} of ${n(count)}`,\n },\n lightbox: {\n ...d.lightbox,\n counter: (index, count) => `${n(index)} / ${n(count)}`,\n position: (index, count) => `Image ${n(index)} of ${n(count)}`,\n },\n translationReview: {\n ...d.translationReview,\n filterCount: (label, count) => `${label} · ${n(count)}`,\n placeholdersOnly: (count) => `Only placeholder problems (${n(count)})`,\n progress: (approved, total) => `${n(approved)} of ${n(total)} approved`,\n localeProgress: (approved, total) => `${n(approved)}/${n(total)}`,\n exportCorrections: (count) => `Export corrections (${n(count)})`,\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,4 @@
1
- import { a$ as UiKitLabels } from '../../kit-labels-C4uB_zmg.js';
1
+ import { bc as UiKitLabels } from '../../kit-labels-D1J2_jyD.js';
2
2
  import 'react';
3
3
  import '../../components/data-table-labels.js';
4
4
  import '../../components/mini-calendar.js';
@@ -50,6 +50,18 @@ import '../../components/authed-image.js';
50
50
  import '../../hooks/use-authed-src.js';
51
51
  import '../../components/image-grid.js';
52
52
  import '../../components/lightbox.js';
53
+ import '../../components/write-lock.js';
54
+ import '../../components/legal.js';
55
+ import '../../components/account-chips.js';
56
+ import '../../lib/format.js';
57
+ import '../../data-table-3mi2R3so.js';
58
+ import '../../components/data-table-sort.js';
59
+ import '../../components/swipeable-row.js';
60
+ import '../../components/reauth-dialog.js';
61
+ import '../../components/server-wake.js';
62
+ import '../../lib/server-wake.js';
63
+ import '../../components/translation-review-labels.js';
64
+ import '../../lib/translation-review.js';
53
65
 
54
66
  /**
55
67
  * The kit's words in Spanish: every namespace of {@link UiKitLabels}, for