@konce-pt/i18n 0.8.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 konce.pt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,48 @@
1
+ <p align="center">
2
+ <img src="https://ui.konce.pt/images/koncept_ui_lib.png" alt="Koncept UI — Angular component library" width="100%" />
3
+ </p>
4
+
5
+ # @konce-pt/i18n
6
+
7
+ Kontrakt tłumaczeń i słowniki bazowe (EN, PL) dla [Koncept UI](https://gitlab.com/konce-pt/koncept-ui).
8
+ Czysty TypeScript, **zero zależności runtime**, bez wiązania z frameworkiem — jedno źródło prawdy
9
+ dla `@konce-pt/angular` i `@konce-pt/react`.
10
+
11
+ Zwykle nie instalujesz tego pakietu samodzielnie: biblioteki komponentów re-eksportują jego API
12
+ (`provideKptI18n` / `KptI18n` w Angularze, `KptI18nProvider` / `useKptI18n` w Reakcie).
13
+ Sięgnij po niego wprost, gdy piszesz własny słownik albo własne wiązanie frameworkowe.
14
+
15
+ ```bash
16
+ npm i @konce-pt/i18n
17
+ ```
18
+
19
+ ```ts
20
+ import { KPT_MESSAGES_PL, translate } from '@konce-pt/i18n';
21
+
22
+ translate(KPT_MESSAGES_PL, 'paginator.range', { start: 1, end: 10, total: 42 });
23
+ // '1–10 z 42'
24
+
25
+ translate(KPT_MESSAGES_PL, 'nope.missing');
26
+ // 'nope.missing' — brak klucza spada na EN, a potem na sam klucz
27
+ ```
28
+
29
+ ## API
30
+
31
+ | Eksport | Typ | Opis |
32
+ |---|---|---|
33
+ | `KptMessages` | `interface` | Kontrakt wszystkich etykiet UI biblioteki |
34
+ | `KptLocale` | `type` | `'en' \| 'pl' \| (string & {})` — otwarty kod języka |
35
+ | `KPT_MESSAGES_EN` / `KPT_MESSAGES_PL` | `KptMessages` | Słowniki bazowe |
36
+ | `translate(dict, key, params?)` | `string` | Klucz kropkowy + interpolacja `{name}`, fallback → EN → klucz |
37
+ | `lookup(dict, key)` | `string \| undefined` | Surowa wartość spod klucza kropkowego |
38
+ | `deepMerge(base, patch)` | `T` | Nakłada częściowy słownik na pełny |
39
+ | `weekdayNames(locale)` | `string[]` | Skrócone nazwy dni, od poniedziałku |
40
+ | `monthNames(locale)` | `string[]` | Pełne nazwy miesięcy |
41
+ | `DeepPartial<T>`, `KptI18nConfig` | `type` | Typy używane przez wiązania frameworkowe |
42
+
43
+ Nazw dni i miesięcy nie ma w słowniku — wyliczają się z `Intl` dla aktywnego locale, więc
44
+ kalendarze działają także w języku, którego nikt nie tłumaczył ręcznie.
45
+
46
+ ## Licencja
47
+
48
+ MIT © konce.pt
@@ -0,0 +1,5 @@
1
+ export { KPT_MESSAGES_EN, KPT_MESSAGES_PL } from './messages.ts';
2
+ export type { KptLocale, KptMessages } from './messages.ts';
3
+ export { deepMerge, lookup, translate } from './translate.ts';
4
+ export type { DeepPartial, KptI18nConfig } from './types.ts';
5
+ export { monthNames, weekdayNames } from './intl.ts';
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /*
2
+ * @konce-pt/i18n — kontrakt tłumaczeń i słowniki bazowe Koncept UI.
3
+ *
4
+ * Czysty TypeScript, zero zależności runtime. Współdzielony przez
5
+ * `@konce-pt/angular` (serwis na sygnałach) i `@konce-pt/react` (Context + hook),
6
+ * żeby oba porty miały jedno źródło prawdy dla etykiet EN/PL.
7
+ */
8
+ export { KPT_MESSAGES_EN, KPT_MESSAGES_PL } from "./messages.js";
9
+ export { deepMerge, lookup, translate } from "./translate.js";
10
+ export { monthNames, weekdayNames } from "./intl.js";
package/dist/intl.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ /** Krótkie nazwy dni tygodnia, zaczynając od poniedziałku (Pn…Nd). */
2
+ export declare function weekdayNames(locale: string): string[];
3
+ /** Pełne nazwy miesięcy (styczeń…grudzień / January…December). */
4
+ export declare function monthNames(locale: string): string[];
package/dist/intl.js ADDED
@@ -0,0 +1,16 @@
1
+ /*
2
+ * Pomocniki nazw dni/miesięcy wyliczane z `Intl` — sterowane bieżącym locale i18n.
3
+ * Dzięki temu kalendarze (`kpt-datepicker`, `kpt-date-range`) nie trzymają
4
+ * zaszytych tablic nazw i działają dla dowolnego języka.
5
+ */
6
+ /** Krótkie nazwy dni tygodnia, zaczynając od poniedziałku (Pn…Nd). */
7
+ export function weekdayNames(locale) {
8
+ const fmt = new Intl.DateTimeFormat(locale, { weekday: 'short' });
9
+ // 2024-01-01 (UTC) to poniedziałek.
10
+ return Array.from({ length: 7 }, (_, i) => fmt.format(new Date(Date.UTC(2024, 0, 1 + i))));
11
+ }
12
+ /** Pełne nazwy miesięcy (styczeń…grudzień / January…December). */
13
+ export function monthNames(locale) {
14
+ const fmt = new Intl.DateTimeFormat(locale, { month: 'long' });
15
+ return Array.from({ length: 12 }, (_, i) => fmt.format(new Date(Date.UTC(2024, i, 1))));
16
+ }
@@ -0,0 +1,367 @@
1
+ /** Kod języka. Otwarty string — EN/PL mają podpowiedzi, ale dozwolony dowolny. */
2
+ export type KptLocale = 'en' | 'pl' | (string & {});
3
+ /** Pełny słownik etykiet UI używanych przez komponenty biblioteki. */
4
+ export interface KptMessages {
5
+ /** Etykiety współdzielone przez wiele komponentów (przyciski ikonowe itp.). */
6
+ common: {
7
+ close: string;
8
+ remove: string;
9
+ previous: string;
10
+ next: string;
11
+ clear: string;
12
+ done: string;
13
+ all: string;
14
+ };
15
+ paginator: {
16
+ rowsPerPage: string;
17
+ /** Interpolacja: {start}, {end}, {total}. */
18
+ range: string;
19
+ prevPage: string;
20
+ nextPage: string;
21
+ };
22
+ select: {
23
+ search: string;
24
+ noResults: string;
25
+ removeChip: string;
26
+ };
27
+ listbox: {
28
+ search: string;
29
+ empty: string;
30
+ };
31
+ dataView: {
32
+ list: string;
33
+ grid: string;
34
+ empty: string;
35
+ /** Interpolacja: {count}. */
36
+ count: string;
37
+ };
38
+ roadmap: {
39
+ empty: string;
40
+ /** Prefiks numeru tygodnia na osi, np. „W" w „W35". */
41
+ week: string;
42
+ today: string;
43
+ milestone: string;
44
+ expandGroup: string;
45
+ collapseGroup: string;
46
+ };
47
+ map: {
48
+ /** Pozycja menu po kliknięciu mapy prawym przyciskiem. */
49
+ addLocation: string;
50
+ chooseCategory: string;
51
+ myLocation: string;
52
+ locateMe: string;
53
+ locationDenied: string;
54
+ locationUnavailable: string;
55
+ zoomIn: string;
56
+ zoomOut: string;
57
+ legend: string;
58
+ /** Interpolacja: {category}. */
59
+ showCategory: string;
60
+ /** Interpolacja: {category}. */
61
+ hideCategory: string;
62
+ /** Etykieta grupy znaczników dla czytnika ekranu. Interpolacja: {count}. */
63
+ cluster: string;
64
+ /** Nagłówek listy pokazywanej, gdy grupy nie da się rozbić zoomem. */
65
+ clusterItems: string;
66
+ /** Interpolacja: {label}. */
67
+ fieldRequired: string;
68
+ /** Notka w formularzu, gdy trwa geokodowanie wsteczne. */
69
+ lookingUpAddress: string;
70
+ /** Notka, gdy geokoder nie ustalił adresu dla klikniętego punktu. */
71
+ addressNotFound: string;
72
+ latitude: string;
73
+ longitude: string;
74
+ empty: string;
75
+ save: string;
76
+ cancel: string;
77
+ /** Karta miejsca (`kpt-map-poi-card`). */
78
+ poi: {
79
+ /** Interpolacja: {distance}. */
80
+ distanceAway: string;
81
+ openNow: string;
82
+ closedNow: string;
83
+ /** Interpolacja: {time}. */
84
+ opensAt: string;
85
+ /** Interpolacja: {time}. */
86
+ closesAt: string;
87
+ alwaysOpen: string;
88
+ openingHours: string;
89
+ closedDay: string;
90
+ call: string;
91
+ sendEmail: string;
92
+ openWebsite: string;
93
+ coordinates: string;
94
+ copy: string;
95
+ copied: string;
96
+ share: string;
97
+ addFavourite: string;
98
+ removeFavourite: string;
99
+ noPhoto: string;
100
+ };
101
+ /** Wyszukiwarka adresów (`kpt-map-search`). */
102
+ search: {
103
+ /** Podpowiedź w pustym polu. */
104
+ placeholder: string;
105
+ /** Nazwa dostępna pola — nie ma przy nim widocznej etykiety. */
106
+ label: string;
107
+ /** Etykieta listy podpowiedzi dla czytnika ekranu. */
108
+ results: string;
109
+ clear: string;
110
+ noResults: string;
111
+ /** Fraza za krótka. Interpolacja: {count}. */
112
+ minLength: string;
113
+ searching: string;
114
+ /** Liczba znalezionych podpowiedzi dla czytnika. Interpolacja: {count}. */
115
+ found: string;
116
+ };
117
+ /** Pola formularza „dodaj lokalizację" poza wspólnymi komunikatami. */
118
+ field: {
119
+ invalidEmail: string;
120
+ invalidUrl: string;
121
+ /** Interpolacja: {max}. */
122
+ imageTooLarge: string;
123
+ pickImage: string;
124
+ orPasteUrl: string;
125
+ removeImage: string;
126
+ imagePreview: string;
127
+ hoursClosed: string;
128
+ hoursFrom: string;
129
+ hoursTo: string;
130
+ hoursSameAllWeek: string;
131
+ hoursAddRange: string;
132
+ hoursRemoveRange: string;
133
+ /** Interpolacja: {day}. */
134
+ hoursIncomplete: string;
135
+ };
136
+ };
137
+ dataTable: {
138
+ search: string;
139
+ exportCsv: string;
140
+ loading: string;
141
+ empty: string;
142
+ selectAll: string;
143
+ selectRow: string;
144
+ expandRow: string;
145
+ /** Interpolacja: {column}. */
146
+ filter: string;
147
+ /** Interpolacja: {column}. */
148
+ filterMin: string;
149
+ /** Interpolacja: {column}. */
150
+ filterMax: string;
151
+ all: string;
152
+ dateRange: string;
153
+ min: string;
154
+ max: string;
155
+ /** Interpolacja: {column}. Aria-label edytowalnej komórki. */
156
+ editCell: string;
157
+ /** Domyślna etykieta wiersza podsumowania (input `summaryLabel` ma priorytet). */
158
+ total: string;
159
+ };
160
+ confirm: {
161
+ header: string;
162
+ accept: string;
163
+ reject: string;
164
+ };
165
+ fileUpload: {
166
+ /** Może zawierać `<strong>…</strong>`. */
167
+ hint: string;
168
+ remove: string;
169
+ };
170
+ chipsInput: {
171
+ placeholder: string;
172
+ };
173
+ dateRange: {
174
+ placeholder: string;
175
+ from: string;
176
+ to: string;
177
+ fromTime: string;
178
+ toTime: string;
179
+ };
180
+ datepicker: {
181
+ prevMonth: string;
182
+ nextMonth: string;
183
+ prevYear: string;
184
+ nextYear: string;
185
+ prevYears: string;
186
+ nextYears: string;
187
+ prevDecades: string;
188
+ nextDecades: string;
189
+ chooseMonth: string;
190
+ chooseYear: string;
191
+ chooseDecade: string;
192
+ calendar: string;
193
+ month: string;
194
+ time: string;
195
+ };
196
+ pickList: {
197
+ available: string;
198
+ selected: string;
199
+ moveAllRight: string;
200
+ moveRight: string;
201
+ moveLeft: string;
202
+ moveAllLeft: string;
203
+ };
204
+ orderList: {
205
+ up: string;
206
+ down: string;
207
+ };
208
+ inputNumber: {
209
+ decrement: string;
210
+ increment: string;
211
+ };
212
+ password: {
213
+ show: string;
214
+ hide: string;
215
+ /** Etykiety miernika siły (indeksy 0–4). */
216
+ strength: [string, string, string, string, string];
217
+ };
218
+ rating: {
219
+ /** Etykieta gwiazdki; interpolacja `{value}` i `{max}`. */
220
+ star: string;
221
+ };
222
+ tree: {
223
+ expand: string;
224
+ collapse: string;
225
+ };
226
+ spinner: {
227
+ label: string;
228
+ };
229
+ speedDial: {
230
+ actions: string;
231
+ };
232
+ scrollTop: {
233
+ label: string;
234
+ };
235
+ splitButton: {
236
+ more: string;
237
+ };
238
+ panel: {
239
+ toggle: string;
240
+ };
241
+ appShell: {
242
+ /** Etykieta przycisku otwierającego i zamykającego panel boczny. */
243
+ toggleNavigation: string;
244
+ /** Etykieta dostępności panelu bocznego. */
245
+ navigation: string;
246
+ };
247
+ breadcrumb: {
248
+ label: string;
249
+ };
250
+ galleria: {
251
+ /** Interpolacja: {index}. */
252
+ image: string;
253
+ };
254
+ carousel: {
255
+ /** Interpolacja: {index}. */
256
+ slide: string;
257
+ };
258
+ richText: {
259
+ copy: string;
260
+ paste: string;
261
+ pasteText: string;
262
+ heading: string;
263
+ bold: string;
264
+ italic: string;
265
+ underline: string;
266
+ strike: string;
267
+ ul: string;
268
+ ol: string;
269
+ indent: string;
270
+ outdent: string;
271
+ foreColor: string;
272
+ backColor: string;
273
+ alignLeft: string;
274
+ alignCenter: string;
275
+ alignRight: string;
276
+ alignJustify: string;
277
+ link: string;
278
+ table: string;
279
+ clear: string;
280
+ html: string;
281
+ /** Styl bloku „Normalny" (select). */
282
+ styleNormal: string;
283
+ /** Interpolacja: {level}. */
284
+ styleHeading: string;
285
+ linkPrompt: string;
286
+ htmlSource: string;
287
+ /** Etykieta „Własny…" przy pickerze koloru. */
288
+ paletteCustom: string;
289
+ /** Menu kontekstowe tabeli. */
290
+ menu: {
291
+ column: string;
292
+ row: string;
293
+ cell: string;
294
+ insertLeft: string;
295
+ insertRight: string;
296
+ headerColumn: string;
297
+ deleteColumn: string;
298
+ insertAbove: string;
299
+ insertBelow: string;
300
+ headerRow: string;
301
+ deleteRow: string;
302
+ cellBackground: string;
303
+ alignLeft: string;
304
+ alignCenter: string;
305
+ alignRight: string;
306
+ mergeCells: string;
307
+ splitCell: string;
308
+ border: string;
309
+ deleteTable: string;
310
+ };
311
+ /** Popover obramowania. */
312
+ border: {
313
+ table: string;
314
+ cell: string;
315
+ none: string;
316
+ thin: string;
317
+ medium: string;
318
+ thick: string;
319
+ customColor: string;
320
+ };
321
+ };
322
+ /** Ekran uwierzytelniania (kpt-auth). */
323
+ auth: {
324
+ signInTitle: string;
325
+ signInSubtitle: string;
326
+ signUpTitle: string;
327
+ signUpSubtitle: string;
328
+ forgotTitle: string;
329
+ forgotSubtitle: string;
330
+ name: string;
331
+ email: string;
332
+ emailPlaceholder: string;
333
+ password: string;
334
+ /** Interpolacja: {min} — minimalna długość hasła. */
335
+ passwordHint: string;
336
+ confirmPassword: string;
337
+ remember: string;
338
+ terms: string;
339
+ forgotLink: string;
340
+ backToSignIn: string;
341
+ signInSubmit: string;
342
+ signUpSubmit: string;
343
+ resetSubmit: string;
344
+ orContinueWith: string;
345
+ /** Interpolacja: {provider} — nazwa dostawcy (etykieta przycisku). */
346
+ continueWith: string;
347
+ noAccount: string;
348
+ haveAccount: string;
349
+ signInSwitch: string;
350
+ signUpSwitch: string;
351
+ errorRequired: string;
352
+ errorEmail: string;
353
+ /** Interpolacja: {min}. */
354
+ errorMinLength: string;
355
+ errorMismatch: string;
356
+ errorInvalid: string;
357
+ /** Treść panelu promocyjnego — zachęca do trybu przeciwnego niż bieżący. */
358
+ promo: {
359
+ signInTitle: string;
360
+ signInText: string;
361
+ signUpTitle: string;
362
+ signUpText: string;
363
+ };
364
+ };
365
+ }
366
+ export declare const KPT_MESSAGES_EN: KptMessages;
367
+ export declare const KPT_MESSAGES_PL: KptMessages;
@@ -0,0 +1,642 @@
1
+ /*
2
+ * Kontrakt tłumaczeń Koncept UI + słowniki bazowe (EN, PL).
3
+ *
4
+ * Plik jest celowo wolny od zależności frameworka — to czysty TypeScript/JSON.
5
+ * Dzięki temu ten sam kontrakt (`KptMessages`) i te same słowniki obsługują
6
+ * `@konce-pt/angular` (serwis na sygnałach) i `@konce-pt/react` (Context + hook).
7
+ *
8
+ * Autor nowego języka wypełnia strukturę `KptMessages` (np. `de.json`) i podaje
9
+ * ją przez `provideKptI18n({ locale: 'de', messages: { de } })` w Angularze albo
10
+ * `<KptI18nProvider locale="de" messages={{ de }}>` w Reakcie. Brakujące klucze
11
+ * spadają na fallback EN.
12
+ */
13
+ export const KPT_MESSAGES_EN = {
14
+ common: {
15
+ close: 'Close',
16
+ remove: 'Remove',
17
+ previous: 'Previous',
18
+ next: 'Next',
19
+ clear: 'Clear',
20
+ done: 'Done',
21
+ all: 'All',
22
+ },
23
+ paginator: {
24
+ rowsPerPage: 'Rows:',
25
+ range: '{start}–{end} of {total}',
26
+ prevPage: 'Previous page',
27
+ nextPage: 'Next page',
28
+ },
29
+ select: {
30
+ search: 'Search…',
31
+ noResults: 'No results',
32
+ removeChip: 'Remove',
33
+ },
34
+ listbox: {
35
+ search: 'Search…',
36
+ empty: 'No items',
37
+ },
38
+ dataView: {
39
+ list: 'List',
40
+ grid: 'Grid',
41
+ empty: 'No items',
42
+ count: '{count} items',
43
+ },
44
+ roadmap: {
45
+ empty: 'No items on the roadmap',
46
+ week: 'W',
47
+ today: 'Today',
48
+ milestone: 'Milestone',
49
+ expandGroup: 'Expand group',
50
+ collapseGroup: 'Collapse group',
51
+ },
52
+ map: {
53
+ addLocation: 'Add location',
54
+ chooseCategory: 'Choose a category',
55
+ myLocation: 'My location',
56
+ locateMe: 'Centre on my location',
57
+ locationDenied: 'Location access denied',
58
+ locationUnavailable: 'Location unavailable',
59
+ zoomIn: 'Zoom in',
60
+ zoomOut: 'Zoom out',
61
+ legend: 'Legend',
62
+ showCategory: 'Show {category}',
63
+ hideCategory: 'Hide {category}',
64
+ cluster: 'Group of {count} locations',
65
+ clusterItems: 'Locations in this group',
66
+ fieldRequired: '{label} is required',
67
+ lookingUpAddress: 'Looking up the address…',
68
+ addressNotFound: 'No address found for this point',
69
+ latitude: 'Latitude',
70
+ longitude: 'Longitude',
71
+ empty: 'No locations',
72
+ save: 'Save',
73
+ cancel: 'Cancel',
74
+ poi: {
75
+ distanceAway: '{distance} away',
76
+ openNow: 'Open',
77
+ closedNow: 'Closed',
78
+ opensAt: 'opens at {time}',
79
+ closesAt: 'closes at {time}',
80
+ alwaysOpen: 'Open 24/7',
81
+ openingHours: 'Opening hours',
82
+ closedDay: 'Closed',
83
+ call: 'Call',
84
+ sendEmail: 'Send an e-mail',
85
+ openWebsite: 'Open the website',
86
+ coordinates: 'Coordinates',
87
+ copy: 'Copy',
88
+ copied: 'Copied',
89
+ share: 'Share',
90
+ addFavourite: 'Add to favourites',
91
+ removeFavourite: 'Remove from favourites',
92
+ noPhoto: 'No photo',
93
+ },
94
+ search: {
95
+ placeholder: 'Search for an address…',
96
+ label: 'Search for an address',
97
+ results: 'Address suggestions',
98
+ clear: 'Clear the search',
99
+ noResults: 'No matching places',
100
+ minLength: 'Type at least {count} characters',
101
+ searching: 'Searching…',
102
+ found: '{count} suggestions',
103
+ },
104
+ field: {
105
+ invalidEmail: 'Enter a valid e-mail address',
106
+ invalidUrl: 'Enter an address starting with http:// or https://',
107
+ imageTooLarge: 'The picture must be no larger than {max}',
108
+ pickImage: 'Pick a picture',
109
+ orPasteUrl: 'or paste a picture address',
110
+ removeImage: 'Remove the picture',
111
+ imagePreview: 'Picture preview',
112
+ hoursClosed: 'Closed',
113
+ hoursFrom: 'From',
114
+ hoursTo: 'To',
115
+ hoursSameAllWeek: 'Same all week',
116
+ hoursAddRange: 'Add a second range',
117
+ hoursRemoveRange: 'Remove the range',
118
+ hoursIncomplete: 'Set both times for {day} or mark the day as closed',
119
+ },
120
+ },
121
+ dataTable: {
122
+ search: 'Search…',
123
+ exportCsv: 'Export CSV',
124
+ loading: 'Loading…',
125
+ empty: 'No data',
126
+ selectAll: 'Select all',
127
+ selectRow: 'Select row',
128
+ expandRow: 'Expand row',
129
+ filter: 'Filter: {column}',
130
+ filterMin: 'Filter min: {column}',
131
+ filterMax: 'Filter max: {column}',
132
+ all: 'All',
133
+ dateRange: 'Date range',
134
+ min: 'min',
135
+ max: 'max',
136
+ editCell: 'Edit: {column}',
137
+ total: 'Total',
138
+ },
139
+ confirm: {
140
+ header: 'Confirmation',
141
+ accept: 'Confirm',
142
+ reject: 'Cancel',
143
+ },
144
+ fileUpload: {
145
+ hint: '<strong>Click</strong> or drag files here',
146
+ remove: 'Remove',
147
+ },
148
+ chipsInput: {
149
+ placeholder: 'Add and press Enter…',
150
+ },
151
+ dateRange: {
152
+ placeholder: 'Select range',
153
+ from: 'From',
154
+ to: 'To',
155
+ fromTime: 'From (time)',
156
+ toTime: 'To (time)',
157
+ },
158
+ datepicker: {
159
+ prevMonth: 'Previous month',
160
+ nextMonth: 'Next month',
161
+ prevYear: 'Previous year',
162
+ nextYear: 'Next year',
163
+ prevYears: 'Previous years',
164
+ nextYears: 'Next years',
165
+ prevDecades: 'Previous decades',
166
+ nextDecades: 'Next decades',
167
+ chooseMonth: 'Choose month',
168
+ chooseYear: 'Choose year',
169
+ chooseDecade: 'Choose decade',
170
+ calendar: 'Calendar',
171
+ month: 'Month',
172
+ time: 'Time',
173
+ },
174
+ pickList: {
175
+ available: 'Available',
176
+ selected: 'Selected',
177
+ moveAllRight: 'Move all right',
178
+ moveRight: 'Move right',
179
+ moveLeft: 'Move left',
180
+ moveAllLeft: 'Move all left',
181
+ },
182
+ orderList: {
183
+ up: 'Up',
184
+ down: 'Down',
185
+ },
186
+ inputNumber: {
187
+ decrement: 'Decrease',
188
+ increment: 'Increase',
189
+ },
190
+ password: {
191
+ show: 'Show password',
192
+ hide: 'Hide password',
193
+ strength: ['Very weak', 'Weak', 'Medium', 'Good', 'Strong'],
194
+ },
195
+ rating: {
196
+ star: '{value} of {max}',
197
+ },
198
+ tree: {
199
+ expand: 'Expand',
200
+ collapse: 'Collapse',
201
+ },
202
+ spinner: {
203
+ label: 'Loading',
204
+ },
205
+ speedDial: {
206
+ actions: 'Actions',
207
+ },
208
+ scrollTop: {
209
+ label: 'Scroll to top',
210
+ },
211
+ splitButton: {
212
+ more: 'More actions',
213
+ },
214
+ panel: {
215
+ toggle: 'Collapse / expand',
216
+ },
217
+ appShell: {
218
+ toggleNavigation: 'Toggle navigation',
219
+ navigation: 'Main navigation',
220
+ },
221
+ breadcrumb: {
222
+ label: 'breadcrumb',
223
+ },
224
+ galleria: {
225
+ image: 'Image {index}',
226
+ },
227
+ carousel: {
228
+ slide: 'Slide {index}',
229
+ },
230
+ richText: {
231
+ copy: 'Copy',
232
+ paste: 'Paste with formatting',
233
+ pasteText: 'Paste without formatting',
234
+ heading: 'Style',
235
+ bold: 'Bold',
236
+ italic: 'Italic',
237
+ underline: 'Underline',
238
+ strike: 'Strikethrough',
239
+ ul: 'Bulleted list',
240
+ ol: 'Numbered list',
241
+ indent: 'Increase indent',
242
+ outdent: 'Decrease indent',
243
+ foreColor: 'Text color',
244
+ backColor: 'Text background color',
245
+ alignLeft: 'Align left',
246
+ alignCenter: 'Center',
247
+ alignRight: 'Align right',
248
+ alignJustify: 'Justify',
249
+ link: 'Insert link',
250
+ table: 'Table',
251
+ clear: 'Clear formatting',
252
+ html: 'HTML preview',
253
+ styleNormal: 'Normal',
254
+ styleHeading: 'Heading {level}',
255
+ linkPrompt: 'URL:',
256
+ htmlSource: 'HTML source',
257
+ paletteCustom: 'Custom…',
258
+ menu: {
259
+ column: 'Column',
260
+ row: 'Row',
261
+ cell: 'Cell',
262
+ insertLeft: 'Insert left',
263
+ insertRight: 'Insert right',
264
+ headerColumn: 'Header column',
265
+ deleteColumn: 'Delete column',
266
+ insertAbove: 'Insert above',
267
+ insertBelow: 'Insert below',
268
+ headerRow: 'Header row',
269
+ deleteRow: 'Delete row',
270
+ cellBackground: 'Background color',
271
+ alignLeft: 'Left',
272
+ alignCenter: 'Center',
273
+ alignRight: 'Right',
274
+ mergeCells: 'Merge cells',
275
+ splitCell: 'Split cell',
276
+ border: 'Border…',
277
+ deleteTable: 'Delete table',
278
+ },
279
+ border: {
280
+ table: 'Table',
281
+ cell: 'Cell',
282
+ none: 'None',
283
+ thin: 'Thin',
284
+ medium: 'Medium',
285
+ thick: 'Thick',
286
+ customColor: 'Color…',
287
+ },
288
+ },
289
+ auth: {
290
+ signInTitle: 'Sign in',
291
+ signInSubtitle: 'Use your e-mail and password.',
292
+ signUpTitle: 'Create account',
293
+ signUpSubtitle: 'It takes less than a minute.',
294
+ forgotTitle: 'Reset password',
295
+ forgotSubtitle: 'We will send a reset link to your e-mail.',
296
+ name: 'Full name',
297
+ email: 'E-mail',
298
+ emailPlaceholder: 'you@company.com',
299
+ password: 'Password',
300
+ passwordHint: 'At least {min} characters.',
301
+ confirmPassword: 'Repeat password',
302
+ remember: 'Remember me',
303
+ terms: 'I accept the terms of service',
304
+ forgotLink: 'Forgot password?',
305
+ backToSignIn: 'Back to sign in',
306
+ signInSubmit: 'Sign in',
307
+ signUpSubmit: 'Create account',
308
+ resetSubmit: 'Send reset link',
309
+ orContinueWith: 'or continue with',
310
+ continueWith: 'Continue with {provider}',
311
+ noAccount: 'No account yet?',
312
+ haveAccount: 'Already have an account?',
313
+ signInSwitch: 'Sign in',
314
+ signUpSwitch: 'Sign up',
315
+ errorRequired: 'This field is required',
316
+ errorEmail: 'Enter a valid e-mail address',
317
+ errorMinLength: 'Use at least {min} characters',
318
+ errorMismatch: 'Passwords do not match',
319
+ errorInvalid: 'Invalid value',
320
+ promo: {
321
+ signInTitle: 'Welcome back',
322
+ signInText: 'Sign in to pick up where you left off.',
323
+ signUpTitle: 'New here?',
324
+ signUpText: 'Create an account and start in a minute.',
325
+ },
326
+ },
327
+ };
328
+ export const KPT_MESSAGES_PL = {
329
+ common: {
330
+ close: 'Zamknij',
331
+ remove: 'Usuń',
332
+ previous: 'Poprzedni',
333
+ next: 'Następny',
334
+ clear: 'Wyczyść',
335
+ done: 'Gotowe',
336
+ all: 'Wszystkie',
337
+ },
338
+ paginator: {
339
+ rowsPerPage: 'Wierszy:',
340
+ range: '{start}–{end} z {total}',
341
+ prevPage: 'Poprzednia strona',
342
+ nextPage: 'Następna strona',
343
+ },
344
+ select: {
345
+ search: 'Szukaj…',
346
+ noResults: 'Brak wyników',
347
+ removeChip: 'Usuń',
348
+ },
349
+ listbox: {
350
+ search: 'Szukaj…',
351
+ empty: 'Brak pozycji',
352
+ },
353
+ dataView: {
354
+ list: 'Lista',
355
+ grid: 'Siatka',
356
+ empty: 'Brak elementów',
357
+ count: '{count} elementów',
358
+ },
359
+ roadmap: {
360
+ empty: 'Brak elementów na roadmapie',
361
+ week: 'T',
362
+ today: 'Dziś',
363
+ milestone: 'Kamień milowy',
364
+ expandGroup: 'Rozwiń grupę',
365
+ collapseGroup: 'Zwiń grupę',
366
+ },
367
+ map: {
368
+ addLocation: 'Dodaj lokalizację',
369
+ chooseCategory: 'Wybierz kategorię',
370
+ myLocation: 'Moje położenie',
371
+ locateMe: 'Wyśrodkuj na moim położeniu',
372
+ locationDenied: 'Brak zgody na dostęp do lokalizacji',
373
+ locationUnavailable: 'Położenie niedostępne',
374
+ zoomIn: 'Przybliż',
375
+ zoomOut: 'Oddal',
376
+ legend: 'Legenda',
377
+ showCategory: 'Pokaż: {category}',
378
+ hideCategory: 'Ukryj: {category}',
379
+ cluster: 'Grupa {count} lokalizacji',
380
+ clusterItems: 'Lokalizacje w tej grupie',
381
+ fieldRequired: 'Pole „{label}" jest wymagane',
382
+ lookingUpAddress: 'Szukam adresu…',
383
+ addressNotFound: 'Nie znaleziono adresu dla tego punktu',
384
+ latitude: 'Szerokość',
385
+ longitude: 'Długość',
386
+ empty: 'Brak lokalizacji',
387
+ save: 'Zapisz',
388
+ cancel: 'Anuluj',
389
+ poi: {
390
+ distanceAway: '{distance} od Ciebie',
391
+ openNow: 'Otwarte',
392
+ closedNow: 'Zamknięte',
393
+ opensAt: 'otwarcie o {time}',
394
+ closesAt: 'zamknięcie o {time}',
395
+ alwaysOpen: 'Czynne całą dobę',
396
+ openingHours: 'Godziny otwarcia',
397
+ closedDay: 'Zamknięte',
398
+ call: 'Zadzwoń',
399
+ sendEmail: 'Napisz wiadomość',
400
+ openWebsite: 'Otwórz stronę',
401
+ coordinates: 'Współrzędne',
402
+ copy: 'Kopiuj',
403
+ copied: 'Skopiowano',
404
+ share: 'Udostępnij',
405
+ addFavourite: 'Dodaj do ulubionych',
406
+ removeFavourite: 'Usuń z ulubionych',
407
+ noPhoto: 'Brak zdjęcia',
408
+ },
409
+ search: {
410
+ placeholder: 'Szukaj adresu…',
411
+ label: 'Szukaj adresu',
412
+ results: 'Podpowiedzi adresów',
413
+ clear: 'Wyczyść wyszukiwanie',
414
+ noResults: 'Brak pasujących miejsc',
415
+ minLength: 'Wpisz więcej znaków (minimum: {count})',
416
+ searching: 'Szukam…',
417
+ found: 'Podpowiedzi: {count}',
418
+ },
419
+ field: {
420
+ invalidEmail: 'Podaj poprawny adres e-mail',
421
+ invalidUrl: 'Podaj adres zaczynający się od http:// albo https://',
422
+ imageTooLarge: 'Zdjęcie może mieć najwyżej {max}',
423
+ pickImage: 'Wybierz zdjęcie',
424
+ orPasteUrl: 'albo wklej adres zdjęcia',
425
+ removeImage: 'Usuń zdjęcie',
426
+ imagePreview: 'Podgląd zdjęcia',
427
+ hoursClosed: 'Zamknięte',
428
+ hoursFrom: 'Od',
429
+ hoursTo: 'Do',
430
+ hoursSameAllWeek: 'Tak samo przez cały tydzień',
431
+ hoursAddRange: 'Dodaj drugi przedział',
432
+ hoursRemoveRange: 'Usuń przedział',
433
+ hoursIncomplete: 'Podaj obie godziny dla dnia {day} albo oznacz go jako zamknięty',
434
+ },
435
+ },
436
+ dataTable: {
437
+ search: 'Szukaj…',
438
+ exportCsv: 'Eksport CSV',
439
+ loading: 'Ładowanie…',
440
+ empty: 'Brak danych',
441
+ selectAll: 'Zaznacz wszystkie',
442
+ selectRow: 'Zaznacz wiersz',
443
+ expandRow: 'Rozwiń wiersz',
444
+ filter: 'Filtr: {column}',
445
+ filterMin: 'Filtr min: {column}',
446
+ filterMax: 'Filtr max: {column}',
447
+ all: 'Wszystkie',
448
+ dateRange: 'Zakres dat',
449
+ min: 'min',
450
+ max: 'max',
451
+ editCell: 'Edytuj: {column}',
452
+ total: 'Razem',
453
+ },
454
+ confirm: {
455
+ header: 'Potwierdzenie',
456
+ accept: 'Potwierdź',
457
+ reject: 'Anuluj',
458
+ },
459
+ fileUpload: {
460
+ hint: '<strong>Kliknij</strong> lub przeciągnij pliki tutaj',
461
+ remove: 'Usuń',
462
+ },
463
+ chipsInput: {
464
+ placeholder: 'Dodaj i naciśnij Enter…',
465
+ },
466
+ dateRange: {
467
+ placeholder: 'Wybierz zakres',
468
+ from: 'Od',
469
+ to: 'Koniec',
470
+ fromTime: 'Od (godzina)',
471
+ toTime: 'Koniec (godzina)',
472
+ },
473
+ datepicker: {
474
+ prevMonth: 'Poprzedni miesiąc',
475
+ nextMonth: 'Następny miesiąc',
476
+ prevYear: 'Poprzedni rok',
477
+ nextYear: 'Następny rok',
478
+ prevYears: 'Poprzednie lata',
479
+ nextYears: 'Następne lata',
480
+ prevDecades: 'Poprzednie dekady',
481
+ nextDecades: 'Następne dekady',
482
+ chooseMonth: 'Wybierz miesiąc',
483
+ chooseYear: 'Wybierz rok',
484
+ chooseDecade: 'Wybierz dekadę',
485
+ calendar: 'Kalendarz',
486
+ month: 'Miesiąc',
487
+ time: 'Godzina',
488
+ },
489
+ pickList: {
490
+ available: 'Dostępne',
491
+ selected: 'Wybrane',
492
+ moveAllRight: 'Przenieś wszystko w prawo',
493
+ moveRight: 'Przenieś w prawo',
494
+ moveLeft: 'Przenieś w lewo',
495
+ moveAllLeft: 'Przenieś wszystko w lewo',
496
+ },
497
+ orderList: {
498
+ up: 'W górę',
499
+ down: 'W dół',
500
+ },
501
+ inputNumber: {
502
+ decrement: 'Zmniejsz',
503
+ increment: 'Zwiększ',
504
+ },
505
+ password: {
506
+ show: 'Pokaż hasło',
507
+ hide: 'Ukryj hasło',
508
+ strength: ['Bardzo słabe', 'Słabe', 'Średnie', 'Dobre', 'Silne'],
509
+ },
510
+ rating: {
511
+ star: '{value} z {max}',
512
+ },
513
+ tree: {
514
+ expand: 'Rozwiń',
515
+ collapse: 'Zwiń',
516
+ },
517
+ spinner: {
518
+ label: 'Ładowanie',
519
+ },
520
+ speedDial: {
521
+ actions: 'Akcje',
522
+ },
523
+ scrollTop: {
524
+ label: 'Przewiń do góry',
525
+ },
526
+ splitButton: {
527
+ more: 'Więcej akcji',
528
+ },
529
+ panel: {
530
+ toggle: 'Zwiń / rozwiń',
531
+ },
532
+ appShell: {
533
+ toggleNavigation: 'Przełącz nawigację',
534
+ navigation: 'Nawigacja główna',
535
+ },
536
+ breadcrumb: {
537
+ label: 'breadcrumb',
538
+ },
539
+ galleria: {
540
+ image: 'Obraz {index}',
541
+ },
542
+ carousel: {
543
+ slide: 'Slajd {index}',
544
+ },
545
+ richText: {
546
+ copy: 'Kopiuj',
547
+ paste: 'Wklej z formatowaniem',
548
+ pasteText: 'Wklej bez formatowania',
549
+ heading: 'Styl',
550
+ bold: 'Pogrubienie',
551
+ italic: 'Kursywa',
552
+ underline: 'Podkreślenie',
553
+ strike: 'Przekreślenie',
554
+ ul: 'Lista punktowana',
555
+ ol: 'Lista numerowana',
556
+ indent: 'Dodaj wcięcie',
557
+ outdent: 'Usuń wcięcie',
558
+ foreColor: 'Kolor tekstu',
559
+ backColor: 'Kolor tła tekstu',
560
+ alignLeft: 'Wyrównaj do lewej',
561
+ alignCenter: 'Wyśrodkuj',
562
+ alignRight: 'Wyrównaj do prawej',
563
+ alignJustify: 'Wyjustuj',
564
+ link: 'Wstaw link',
565
+ table: 'Tabela',
566
+ clear: 'Usuń formatowanie',
567
+ html: 'Podgląd HTML',
568
+ styleNormal: 'Normalny',
569
+ styleHeading: 'Nagłówek {level}',
570
+ linkPrompt: 'Adres URL:',
571
+ htmlSource: 'Źródło HTML',
572
+ paletteCustom: 'Własny…',
573
+ menu: {
574
+ column: 'Kolumna',
575
+ row: 'Wiersz',
576
+ cell: 'Komórka',
577
+ insertLeft: 'Wstaw z lewej',
578
+ insertRight: 'Wstaw z prawej',
579
+ headerColumn: 'Nagłówek kolumny',
580
+ deleteColumn: 'Usuń kolumnę',
581
+ insertAbove: 'Wstaw powyżej',
582
+ insertBelow: 'Wstaw poniżej',
583
+ headerRow: 'Nagłówek wiersza',
584
+ deleteRow: 'Usuń wiersz',
585
+ cellBackground: 'Kolor tła',
586
+ alignLeft: 'Do lewej',
587
+ alignCenter: 'Wyśrodkuj',
588
+ alignRight: 'Do prawej',
589
+ mergeCells: 'Scal komórki',
590
+ splitCell: 'Podziel komórkę',
591
+ border: 'Obramowanie…',
592
+ deleteTable: 'Usuń tabelę',
593
+ },
594
+ border: {
595
+ table: 'Tabela',
596
+ cell: 'Komórka',
597
+ none: 'Bez',
598
+ thin: 'Cienkie',
599
+ medium: 'Średnie',
600
+ thick: 'Grube',
601
+ customColor: 'Kolor…',
602
+ },
603
+ },
604
+ auth: {
605
+ signInTitle: 'Zaloguj się',
606
+ signInSubtitle: 'Użyj adresu e-mail i hasła.',
607
+ signUpTitle: 'Załóż konto',
608
+ signUpSubtitle: 'Zajmie mniej niż minutę.',
609
+ forgotTitle: 'Zresetuj hasło',
610
+ forgotSubtitle: 'Wyślemy link do zmiany hasła na podany adres.',
611
+ name: 'Imię i nazwisko',
612
+ email: 'E-mail',
613
+ emailPlaceholder: 'jan@firma.pl',
614
+ password: 'Hasło',
615
+ passwordHint: 'Co najmniej {min} znaków.',
616
+ confirmPassword: 'Powtórz hasło',
617
+ remember: 'Zapamiętaj mnie',
618
+ terms: 'Akceptuję regulamin',
619
+ forgotLink: 'Nie pamiętasz hasła?',
620
+ backToSignIn: 'Wróć do logowania',
621
+ signInSubmit: 'Zaloguj się',
622
+ signUpSubmit: 'Załóż konto',
623
+ resetSubmit: 'Wyślij link',
624
+ orContinueWith: 'lub kontynuuj przez',
625
+ continueWith: 'Kontynuuj przez {provider}',
626
+ noAccount: 'Nie masz jeszcze konta?',
627
+ haveAccount: 'Masz już konto?',
628
+ signInSwitch: 'Zaloguj się',
629
+ signUpSwitch: 'Załóż konto',
630
+ errorRequired: 'To pole jest wymagane',
631
+ errorEmail: 'Podaj poprawny adres e-mail',
632
+ errorMinLength: 'Użyj co najmniej {min} znaków',
633
+ errorMismatch: 'Hasła nie są takie same',
634
+ errorInvalid: 'Nieprawidłowa wartość',
635
+ promo: {
636
+ signInTitle: 'Witaj ponownie',
637
+ signInText: 'Zaloguj się, by wrócić do pracy.',
638
+ signUpTitle: 'Pierwszy raz u nas?',
639
+ signUpText: 'Załóż konto i zacznij w minutę.',
640
+ },
641
+ },
642
+ };
@@ -0,0 +1,11 @@
1
+ import { type KptMessages } from './messages.ts';
2
+ import type { DeepPartial } from './types.ts';
3
+ /** Deep-merge `patch` na kopię `base` (łączy tylko obiekty, wartości nadpisuje). */
4
+ export declare function deepMerge<T>(base: T, patch: DeepPartial<T>): T;
5
+ /** Zwraca string spod klucza w notacji kropkowej albo `undefined`, gdy go nie ma. */
6
+ export declare function lookup(dict: KptMessages, key: string): string | undefined;
7
+ /**
8
+ * Tłumaczy klucz w notacji kropkowej (np. `'paginator.range'`), z opcjonalną
9
+ * interpolacją `{name}`. Brakujący klucz spada na EN, a w ostateczności zwraca sam klucz.
10
+ */
11
+ export declare function translate(dict: KptMessages, key: string, params?: Record<string, string | number>): string;
@@ -0,0 +1,45 @@
1
+ /*
2
+ * Rdzeń tłumaczeń — czysty TypeScript, bez zależności od frameworka.
3
+ *
4
+ * Angular owija te funkcje w serwis na sygnałach (`KptI18n`), React w Context
5
+ * i hook (`useKptI18n`). Semantyka wyszukiwania, fallbacku i interpolacji żyje
6
+ * tutaj, żeby oba porty zachowywały się identycznie.
7
+ */
8
+ import { KPT_MESSAGES_EN } from "./messages.js";
9
+ /** Deep-merge `patch` na kopię `base` (łączy tylko obiekty, wartości nadpisuje). */
10
+ export function deepMerge(base, patch) {
11
+ const out = { ...base };
12
+ for (const [key, value] of Object.entries(patch)) {
13
+ const current = out[key];
14
+ if (value && typeof value === 'object' && !Array.isArray(value) && current && typeof current === 'object') {
15
+ out[key] = deepMerge(current, value);
16
+ }
17
+ else if (value !== undefined) {
18
+ out[key] = value;
19
+ }
20
+ }
21
+ return out;
22
+ }
23
+ /** Zwraca string spod klucza w notacji kropkowej albo `undefined`, gdy go nie ma. */
24
+ export function lookup(dict, key) {
25
+ let node = dict;
26
+ for (const part of key.split('.')) {
27
+ if (node && typeof node === 'object' && part in node) {
28
+ node = node[part];
29
+ }
30
+ else {
31
+ return undefined;
32
+ }
33
+ }
34
+ return typeof node === 'string' ? node : undefined;
35
+ }
36
+ /**
37
+ * Tłumaczy klucz w notacji kropkowej (np. `'paginator.range'`), z opcjonalną
38
+ * interpolacją `{name}`. Brakujący klucz spada na EN, a w ostateczności zwraca sam klucz.
39
+ */
40
+ export function translate(dict, key, params) {
41
+ const raw = lookup(dict, key) ?? lookup(KPT_MESSAGES_EN, key) ?? key;
42
+ if (!params)
43
+ return raw;
44
+ return raw.replace(/\{(\w+)\}/g, (_, name) => String(params[name] ?? `{${name}}`));
45
+ }
@@ -0,0 +1,16 @@
1
+ import type { KptLocale, KptMessages } from './messages.ts';
2
+ /** Głęboko-opcjonalna wersja typu — dla nadpisań/częściowych słowników. */
3
+ export type DeepPartial<T> = {
4
+ [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
5
+ };
6
+ /** Konfiguracja i18n — wspólna dla portu Angulara i Reacta. */
7
+ export interface KptI18nConfig {
8
+ /** Język początkowy (domyślnie 'en'). */
9
+ locale?: KptLocale;
10
+ /**
11
+ * Słowniki do zarejestrowania lub nadpisania, kluczowane kodem języka.
12
+ * Może dodać nowy język (`{ de: {...} }`) lub nadpisać istniejący
13
+ * (`{ en: { paginator: { rowsPerPage: 'Rows:' } } }`). Deep-merge z bazą EN/PL.
14
+ */
15
+ messages?: Record<string, DeepPartial<KptMessages>>;
16
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@konce-pt/i18n",
3
+ "version": "0.8.0",
4
+ "description": "Translation contract and base dictionaries (EN, PL) for Koncept UI — shared by the Angular and React ports. Pure TypeScript, zero runtime dependencies.",
5
+ "license": "MIT",
6
+ "author": "konce.pt",
7
+ "homepage": "https://ui.konce.pt/",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://gitlab.com/konce-pt/koncept-ui.git",
11
+ "directory": "packages/i18n"
12
+ },
13
+ "bugs": {
14
+ "url": "https://gitlab.com/konce-pt/koncept-ui/-/issues"
15
+ },
16
+ "keywords": [
17
+ "i18n",
18
+ "internationalization",
19
+ "translations",
20
+ "design-system",
21
+ "koncept-ui",
22
+ "kpt"
23
+ ],
24
+ "type": "module",
25
+ "sideEffects": false,
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "module": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/index.d.ts",
34
+ "default": "./dist/index.js"
35
+ }
36
+ },
37
+ "devDependencies": {
38
+ "typescript": "~6.0.3"
39
+ },
40
+ "scripts": {
41
+ "build": "tsc -p tsconfig.build.json",
42
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\""
43
+ }
44
+ }