@vireocodedev/localization 0.2.0 → 0.2.1

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.
@@ -0,0 +1,41 @@
1
+ import { HISTORY_TRANSLATION_NAMESPACE, HistoryResources, HistoryResourcesOverride } from './history/createHistoryResources';
2
+ import { PLATFORM_TRANSLATION_NAMESPACE, PlatformResources, PlatformResourcesOverride } from './platform/createPlatformResources';
3
+ import { QUERYENGINE_TRANSLATION_NAMESPACE, QueryEngineResources, QueryEngineResourcesOverride } from './queryengine/createQueryEngineResources';
4
+ import { i18n as I18nInstance } from 'i18next';
5
+ /** Every i18next namespace shipped by the starter libraries. */
6
+ export declare const STARTER_TRANSLATION_NAMESPACES: readonly ["platform", "queryengine", "history"];
7
+ export type StarterTranslationNamespace = (typeof STARTER_TRANSLATION_NAMESPACES)[number];
8
+ /** Locales every starter namespace ships out of the box. */
9
+ export declare const STARTER_BASE_LOCALES: readonly ["en", "hr"];
10
+ export type StarterBaseLocale = (typeof STARTER_BASE_LOCALES)[number];
11
+ /** The resources contributed by the starter libraries, keyed by namespace. */
12
+ export type StarterNamespaceResources = {
13
+ [PLATFORM_TRANSLATION_NAMESPACE]: PlatformResources;
14
+ [QUERYENGINE_TRANSLATION_NAMESPACE]: QueryEngineResources;
15
+ [HISTORY_TRANSLATION_NAMESPACE]: HistoryResources;
16
+ };
17
+ /** Per-locale, per-namespace value overrides. */
18
+ export type StarterResourcesOverride = {
19
+ [PLATFORM_TRANSLATION_NAMESPACE]?: PlatformResourcesOverride;
20
+ [QUERYENGINE_TRANSLATION_NAMESPACE]?: QueryEngineResourcesOverride;
21
+ [HISTORY_TRANSLATION_NAMESPACE]?: HistoryResourcesOverride;
22
+ };
23
+ export type CreateStarterResourcesConfig<L extends string> = {
24
+ /** The full set of locales the consumer app wants to support. */
25
+ locales: readonly L[];
26
+ /** Base locale used to seed locales the starter does not ship. Defaults to `"en"`. */
27
+ seedFrom?: StarterBaseLocale;
28
+ /** Optional per-locale, per-namespace value overrides, deep-merged over the seeded base. */
29
+ overrides?: Partial<Record<L, StarterResourcesOverride>>;
30
+ };
31
+ /**
32
+ * Builds every starter-owned namespace for the requested locales in a single
33
+ * call, so apps spread one object per locale into their i18next resources and
34
+ * pick up new starter namespaces without touching their wiring.
35
+ */
36
+ export declare function createStarterResources<L extends string>(config: CreateStarterResourcesConfig<L>): Record<L, StarterNamespaceResources>;
37
+ /**
38
+ * Imperatively registers every starter namespace onto an existing i18next
39
+ * instance. Useful when resources are added after i18next has been initialized.
40
+ */
41
+ export declare function registerStarterResources<L extends string>(i18n: I18nInstance, config: CreateStarterResourcesConfig<L>): void;
@@ -0,0 +1,7 @@
1
+ export type IntlNumberFormatRequest = {
2
+ locale: string;
3
+ options?: Intl.NumberFormatOptions;
4
+ fallback?: (value: number) => string;
5
+ };
6
+ /** Locale-neutral formatting primitive; application locale/default policy stays at the call site. */
7
+ export declare function formatIntlNumber(value: number, request: IntlNumberFormatRequest): string;
@@ -0,0 +1,29 @@
1
+ import { default as HISTORY_EN } from './history.en';
2
+ import { HISTORY_TRANSLATION_NAMESPACE } from './namespace';
3
+ import { DeepPartial, WidenLeaves } from '../toolkit/createNamespaceResources';
4
+ export { HISTORY_TRANSLATION_NAMESPACE, type HistoryTranslationNamespace } from './namespace';
5
+ /** The canonical History resource shape. English is the key source of truth. */
6
+ export type HistoryResources = WidenLeaves<typeof HISTORY_EN>;
7
+ /**
8
+ * A recursively partial resource, used for per-locale value overrides. Leaves
9
+ * are widened, so an override may supply any string for a shipped key.
10
+ */
11
+ export type HistoryResourcesOverride = DeepPartial<HistoryResources>;
12
+ /** Locales the History namespace ships out of the box. */
13
+ export declare const HISTORY_BASE_LOCALES: readonly ["en", "hr"];
14
+ export type HistoryBaseLocale = (typeof HISTORY_BASE_LOCALES)[number];
15
+ export declare const historyBaseResources: Record<HistoryBaseLocale, HistoryResources>;
16
+ export type CreateHistoryResourcesConfig<L extends string> = {
17
+ /** The full set of locales the consumer app wants to support. */
18
+ locales: readonly L[];
19
+ /** Base locale used to seed locales the namespace does not ship. Defaults to `"en"`. */
20
+ seedFrom?: HistoryBaseLocale;
21
+ /** Optional per-locale value overrides, deep-merged over the seeded base. */
22
+ overrides?: Partial<Record<L, HistoryResourcesOverride>>;
23
+ };
24
+ /**
25
+ * Builds a fully-populated History resource map for every requested locale.
26
+ */
27
+ export declare function createHistoryResources<L extends string>(config: CreateHistoryResourcesConfig<L>): Record<L, {
28
+ [HISTORY_TRANSLATION_NAMESPACE]: HistoryResources;
29
+ }>;
@@ -0,0 +1,8 @@
1
+ declare const HISTORY_EN: {
2
+ readonly title: "History";
3
+ readonly empty: "No history yet.";
4
+ readonly showUnchanged: "Show unchanged";
5
+ readonly hideUnchanged: "Hide unchanged";
6
+ readonly viewHistory: "View history";
7
+ };
8
+ export default HISTORY_EN;
@@ -0,0 +1,8 @@
1
+ declare const HISTORY_HR: {
2
+ readonly title: "Povijest";
3
+ readonly empty: "Još nema povijesti.";
4
+ readonly showUnchanged: "Prikaži nepromijenjeno";
5
+ readonly hideUnchanged: "Sakrij nepromijenjeno";
6
+ readonly viewHistory: "Prikaži povijest";
7
+ };
8
+ export default HISTORY_HR;
@@ -0,0 +1,2 @@
1
+ export declare const HISTORY_TRANSLATION_NAMESPACE: "history";
2
+ export type HistoryTranslationNamespace = typeof HISTORY_TRANSLATION_NAMESPACE;
@@ -0,0 +1,7 @@
1
+ export { createStarterResources, registerStarterResources, STARTER_BASE_LOCALES, STARTER_TRANSLATION_NAMESPACES, type CreateStarterResourcesConfig, type StarterBaseLocale, type StarterNamespaceResources, type StarterResourcesOverride, type StarterTranslationNamespace, } from './createStarterResources';
2
+ export { createPlatformResources, platformBaseResources, PLATFORM_BASE_LOCALES, PLATFORM_TRANSLATION_NAMESPACE, type CreatePlatformResourcesConfig, type PlatformBaseLocale, type PlatformResources, type PlatformResourcesOverride, type PlatformTranslationNamespace, } from './platform/createPlatformResources';
3
+ export { createQueryEngineResources, queryEngineBaseResources, QUERYENGINE_BASE_LOCALES, QUERYENGINE_TRANSLATION_NAMESPACE, type CreateQueryEngineResourcesConfig, type QueryEngineBaseLocale, type QueryEngineResources, type QueryEngineResourcesOverride, type QueryEngineTranslationNamespace, } from './queryengine/createQueryEngineResources';
4
+ export { createHistoryResources, historyBaseResources, HISTORY_BASE_LOCALES, HISTORY_TRANSLATION_NAMESPACE, type CreateHistoryResourcesConfig, type HistoryBaseLocale, type HistoryResources, type HistoryResourcesOverride, type HistoryTranslationNamespace, } from './history/createHistoryResources';
5
+ export { createNamespaceResources, type DeepPartial, type WidenLeaves } from './toolkit/createNamespaceResources';
6
+ export { deepMerge } from './toolkit/deepMerge';
7
+ export { formatIntlNumber, type IntlNumberFormatRequest } from './formatters/intlNumberFormat';
package/dist/index.js ADDED
@@ -0,0 +1,513 @@
1
+ //#region src/history/history.en.ts
2
+ var e = {
3
+ title: "History",
4
+ empty: "No history yet.",
5
+ showUnchanged: "Show unchanged",
6
+ hideUnchanged: "Hide unchanged",
7
+ viewHistory: "View history"
8
+ }, t = {
9
+ title: "Povijest",
10
+ empty: "Još nema povijesti.",
11
+ showUnchanged: "Prikaži nepromijenjeno",
12
+ hideUnchanged: "Sakrij nepromijenjeno",
13
+ viewHistory: "Prikaži povijest"
14
+ }, n = "history", r = /* @__PURE__ */ new Set([
15
+ "__proto__",
16
+ "constructor",
17
+ "prototype"
18
+ ]);
19
+ function i(e) {
20
+ if (typeof e != "object" || !e || Array.isArray(e)) return !1;
21
+ let t = Object.getPrototypeOf(e);
22
+ return t === Object.prototype || t === null;
23
+ }
24
+ function a(e) {
25
+ if (Array.isArray(e)) return e.map((e) => a(e));
26
+ if (i(e)) {
27
+ let t = {};
28
+ for (let [n, i] of Object.entries(e)) r.has(n) || (t[n] = a(i));
29
+ return t;
30
+ }
31
+ return e;
32
+ }
33
+ function o(e, t) {
34
+ if (!i(e) || !i(t)) return a(t === void 0 ? e : t);
35
+ let n = a(e);
36
+ for (let e of Object.keys(t)) {
37
+ if (r.has(e)) continue;
38
+ let s = t[e];
39
+ if (s === void 0) continue;
40
+ let c = n[e];
41
+ n[e] = i(c) && i(s) ? o(c, s) : a(s);
42
+ }
43
+ return n;
44
+ }
45
+ //#endregion
46
+ //#region src/toolkit/validateResourceConfiguration.ts
47
+ function s(e, t, n) {
48
+ if (t.length === 0) throw Error(`${e} requires at least one locale identifier.`);
49
+ if (t.find((e) => e.trim().length === 0 || e !== e.trim()) !== void 0) throw Error(`${e} requires non-empty, trimmed locale identifiers.`);
50
+ if (new Set(t).size !== t.length) throw Error(`${e} requires unique locale identifiers.`);
51
+ if (!n) return;
52
+ let r = new Set(t), i = Object.keys(n).find((e) => !r.has(e));
53
+ if (i !== void 0) throw Error(`${e} received an override for unrequested locale "${i}".`);
54
+ }
55
+ //#endregion
56
+ //#region src/toolkit/createNamespaceResources.ts
57
+ function c(e) {
58
+ let { namespace: t, baseResources: n, seedFrom: r, locales: i, overrides: a } = e;
59
+ if (t.trim().length === 0) throw Error("createNamespaceResources requires a non-empty namespace.");
60
+ if (!Object.prototype.hasOwnProperty.call(n, r)) throw Error(`createNamespaceResources could not find seed locale "${r}".`);
61
+ s("createNamespaceResources", i, a);
62
+ let c = n[r], l = {};
63
+ for (let e of i) {
64
+ let r = n[e], i = a?.[e], s = o(c, void 0);
65
+ r && (s = o(s, r)), i && (s = o(s, i)), l[e] = { [t]: s };
66
+ }
67
+ return l;
68
+ }
69
+ //#endregion
70
+ //#region src/history/createHistoryResources.ts
71
+ var l = ["en", "hr"], u = {
72
+ en: e,
73
+ hr: t
74
+ };
75
+ function d(e) {
76
+ return c({
77
+ namespace: n,
78
+ baseResources: u,
79
+ seedFrom: e.seedFrom ?? "en",
80
+ locales: e.locales,
81
+ overrides: e.overrides
82
+ });
83
+ }
84
+ //#endregion
85
+ //#region src/platform/namespace.ts
86
+ var f = "platform", p = {
87
+ common: {
88
+ actions: "Actions",
89
+ ascending: "Ascending",
90
+ ascendingSortDirection: "Ascending sort direction",
91
+ back: "Back",
92
+ bottomNavigation: "Bottom navigation",
93
+ cancel: "Cancel",
94
+ clearAll: "Clear all",
95
+ clearSearch: "Clear search",
96
+ closeFilters: "Close filters",
97
+ closeNavigation: "Close navigation",
98
+ collapse: "Collapse",
99
+ column: "Sort by",
100
+ create: "Create",
101
+ dark: "Dark",
102
+ delete: "Delete",
103
+ descending: "Descending",
104
+ descendingSortDirection: "Descending sort direction",
105
+ direction: "Sort direction",
106
+ discard: "Discard",
107
+ done: "Done",
108
+ download: "Download",
109
+ edit: "Edit",
110
+ expand: "Expand",
111
+ filters: "Filters",
112
+ language: "Language",
113
+ light: "Light",
114
+ loading: "Loading",
115
+ logout: "Sign out",
116
+ mainNavigation: "Main navigation",
117
+ month: "Month",
118
+ more: "More",
119
+ name: "Name",
120
+ noRecordsFound: "No records found.",
121
+ openFilters: "Open filters",
122
+ profile: "Profile",
123
+ settings: "Settings",
124
+ theme: "Theme",
125
+ year: "Year",
126
+ no: "No",
127
+ yes: "Yes",
128
+ save: "Save",
129
+ search: "Search",
130
+ skipToMainContent: "Skip to main content"
131
+ },
132
+ pwa: {
133
+ newVersionAvailable: "New version available.",
134
+ reload: "Reload"
135
+ },
136
+ network: {
137
+ actionQueued: "Saved offline. Sent when connection returns.",
138
+ actionUnavailable: "This action is unavailable while offline.",
139
+ commandId: "Command ID",
140
+ connectingToLiveUpdates: "Connecting to live updates...",
141
+ createdAt: "Created at",
142
+ dataUnavailable: "This data is unavailable while offline.",
143
+ diagnostics: "Offline diagnostics",
144
+ errorMessage: "Error message",
145
+ failedLoadingData: "Failed loading data.",
146
+ httpMethod: "HTTP method",
147
+ hydratingInBackground: "Syncing local data in background. You can keep using the app.",
148
+ lastHeartbeat: "Last heartbeat",
149
+ lastSyncFailure: "Last failure",
150
+ mutationQueuedOffline: "Saved locally — pending sync",
151
+ offline: "Offline",
152
+ offlineBanner: "You are offline. Data may be unavailable and changes are disabled.",
153
+ offlineModeNotSupported: "This action is not available in offline mode yet.",
154
+ offlineQueuePending: "Offline — {{count}} changes pending sync",
155
+ online: "Online",
156
+ owner: "Owner",
157
+ processedAt: "Processed at",
158
+ queuePermanentlyFailed: "{{count}} change(s) failed to sync and need attention",
159
+ queueSize: "Queued commands",
160
+ queueSynced: "Synced",
161
+ reconnecting: "Reconnecting",
162
+ responseStatus: "Response status",
163
+ searchSyncCommands: "Search sync commands",
164
+ status: "Status",
165
+ syncCommands: "Sync commands",
166
+ syncFailures: "Sync failures",
167
+ syncIdle: "Idle",
168
+ syncInProgress: "In progress",
169
+ syncStatus: "Sync status",
170
+ unavailable: "Unavailable",
171
+ url: "URL",
172
+ youAreOffline: "Offline mode"
173
+ },
174
+ routing: {
175
+ errorChunkMessage: "This page could not be loaded. This can happen after an app update — try refreshing the application.",
176
+ errorGenericMessage: "An unexpected error occurred while loading this page.",
177
+ errorOfflineMessage: "You appear to be offline. Check your connection and try again.",
178
+ errorRefresh: "Refresh app",
179
+ errorRetry: "Retry",
180
+ errorTitle: "Something went wrong",
181
+ goHome: "Go to overview",
182
+ notFoundMessage: "The page you requested does not exist or may have moved.",
183
+ notFoundTitle: "Page not found",
184
+ unauthorizedMessage: "You do not have permission to view this page.",
185
+ unauthorizedTitle: "Access denied"
186
+ },
187
+ unsavedChanges: {
188
+ discardAndLeave: "Discard and leave",
189
+ message: "You have unsaved changes. Discard them and leave?",
190
+ savingMessage: "Your changes are being saved. Wait for the save to finish before leaving.",
191
+ savingTitle: "Saving changes",
192
+ stay: "Stay",
193
+ title: "Unsaved changes"
194
+ },
195
+ validation: { thisFieldIsRequired: "This field is required." },
196
+ auth: {
197
+ currentUserLoadFailed: "Sign-in succeeded, but your account could not be loaded. Please try again.",
198
+ discardPendingSyncCancel: "Stay signed in",
199
+ discardPendingSyncConfirm: "Sign out and discard",
200
+ discardPendingSyncMessage: "{{count}} offline change(s) have not been synced yet. Signing out deletes the local data on this device, so those changes will be lost permanently.",
201
+ discardPendingSyncTitle: "Unsynced offline changes",
202
+ invalidCredentials: "Invalid credentials.",
203
+ password: "Password",
204
+ sessionExpired: "Your session has expired. Sign in again to continue.",
205
+ signIn: "Sign in",
206
+ signInSubtitle: "Enter your credentials to access your account.",
207
+ signedInAs: "Signed in as",
208
+ username: "Username"
209
+ },
210
+ settings: {
211
+ lockNavigationBar: "Lock navigation bar",
212
+ noMaxWidth: "No max width",
213
+ pageBodyMaxWidth: "Page content width",
214
+ pageBodyMaxWidthLg: "Large",
215
+ pageBodyMaxWidthMd: "Medium",
216
+ pageBodyMaxWidthSm: "Small",
217
+ pageBodyMaxWidthXl: "Extra large",
218
+ pageBodyMaxWidthXs: "Extra small",
219
+ title: "Application settings",
220
+ userSettingsSavedSuccessfully: "User settings saved."
221
+ }
222
+ }, m = {
223
+ common: {
224
+ actions: "Akcije",
225
+ ascending: "Uzlazno",
226
+ ascendingSortDirection: "Uzlazni smjer sortiranja",
227
+ back: "Natrag",
228
+ bottomNavigation: "Navigacija pri dnu",
229
+ cancel: "Odustani",
230
+ clearAll: "Očisti sve",
231
+ clearSearch: "Očisti pretragu",
232
+ closeFilters: "Zatvori filtere",
233
+ closeNavigation: "Zatvori navigaciju",
234
+ collapse: "Sažmi",
235
+ column: "Sortiraj po",
236
+ create: "Kreiraj",
237
+ dark: "Tamna",
238
+ delete: "Obriši",
239
+ descending: "Silazno",
240
+ descendingSortDirection: "Silazni smjer sortiranja",
241
+ direction: "Smjer sortiranja",
242
+ discard: "Odbaci",
243
+ done: "Gotovo",
244
+ download: "Preuzmi",
245
+ edit: "Uredi",
246
+ expand: "Proširi",
247
+ filters: "Filteri",
248
+ language: "Jezik",
249
+ light: "Svijetla",
250
+ loading: "Učitavanje",
251
+ logout: "Odjava",
252
+ mainNavigation: "Glavna navigacija",
253
+ month: "Mjesec",
254
+ more: "Više",
255
+ name: "Naziv",
256
+ noRecordsFound: "Nema pronađenih zapisa.",
257
+ openFilters: "Otvori filtere",
258
+ profile: "Profil",
259
+ settings: "Postavke",
260
+ theme: "Tema",
261
+ year: "Godina",
262
+ no: "Ne",
263
+ yes: "Da",
264
+ save: "Spremi",
265
+ search: "Pretraži",
266
+ skipToMainContent: "Preskoči na glavni sadržaj"
267
+ },
268
+ pwa: {
269
+ newVersionAvailable: "Dostupna je nova verzija.",
270
+ reload: "Osvježi"
271
+ },
272
+ network: {
273
+ actionQueued: "Spremljeno offline. Šalje se kad se veza vrati.",
274
+ actionUnavailable: "Ova radnja nije dostupna dok ste izvan mreže.",
275
+ commandId: "ID naredbe",
276
+ connectingToLiveUpdates: "Povezivanje na promjene uživo...",
277
+ createdAt: "Kreirano",
278
+ dataUnavailable: "Ovi podaci nisu dostupni dok ste izvan mreže.",
279
+ diagnostics: "Offline dijagnostika",
280
+ errorMessage: "Poruka greške",
281
+ failedLoadingData: "Neuspjelo učitavanje podataka.",
282
+ httpMethod: "HTTP metoda",
283
+ hydratingInBackground: "Lokalni podaci se sinkroniziraju u pozadini. Možete nastaviti koristiti aplikaciju.",
284
+ lastHeartbeat: "Zadnji heartbeat",
285
+ lastSyncFailure: "Zadnja greška",
286
+ mutationQueuedOffline: "Spremljeno lokalno — čeka sinkronizaciju",
287
+ offline: "Offline",
288
+ offlineBanner: "Niste povezani s mrežom. Podaci možda nisu dostupni, a promjene su onemogućene.",
289
+ offlineModeNotSupported: "Ova akcija još nije dostupna u offline načinu rada.",
290
+ offlineQueuePending: "Offline — {{count}} promjene čekaju sinkronizaciju",
291
+ online: "Online",
292
+ owner: "Vlasnik",
293
+ processedAt: "Obrađeno",
294
+ queuePermanentlyFailed: "{{count}} promjena nije uspjelo sinkronizirati — potrebna provjera",
295
+ queueSize: "Naredbe u redu",
296
+ queueSynced: "Sinkronizirano",
297
+ reconnecting: "Ponovno povezivanje",
298
+ responseStatus: "Status odgovora",
299
+ searchSyncCommands: "Pretraži naredbe sinkronizacije",
300
+ status: "Status",
301
+ syncCommands: "Naredbe sinkronizacije",
302
+ syncFailures: "Greške sinkronizacije",
303
+ syncIdle: "Miruje",
304
+ syncInProgress: "U tijeku",
305
+ syncStatus: "Status sinkronizacije",
306
+ unavailable: "Nedostupno",
307
+ url: "URL",
308
+ youAreOffline: "Offline način rada"
309
+ },
310
+ routing: {
311
+ errorChunkMessage: "Ova stranica nije mogla biti učitana. To se može dogoditi nakon ažuriranja aplikacije — pokušajte osvježiti aplikaciju.",
312
+ errorGenericMessage: "Došlo je do neočekivane greške prilikom učitavanja ove stranice.",
313
+ errorOfflineMessage: "Izgleda da ste offline. Provjerite internetsku vezu i pokušajte ponovno.",
314
+ errorRefresh: "Osvježi aplikaciju",
315
+ errorRetry: "Pokušaj ponovno",
316
+ errorTitle: "Nešto je pošlo po zlu",
317
+ goHome: "Idi na pregled",
318
+ notFoundMessage: "Tražena stranica ne postoji ili je premještena.",
319
+ notFoundTitle: "Stranica nije pronađena",
320
+ unauthorizedMessage: "Nemate dopuštenje za prikaz ove stranice.",
321
+ unauthorizedTitle: "Pristup odbijen"
322
+ },
323
+ unsavedChanges: {
324
+ discardAndLeave: "Odbaci i napusti",
325
+ message: "Imate nespremljene promjene. Odbaciti ih i napustiti stranicu?",
326
+ savingMessage: "Promjene se spremaju. Pričekajte završetak spremanja prije napuštanja stranice.",
327
+ savingTitle: "Spremanje promjena",
328
+ stay: "Ostani",
329
+ title: "Nespremljene promjene"
330
+ },
331
+ validation: { thisFieldIsRequired: "Ovo polje je obavezno." },
332
+ auth: {
333
+ currentUserLoadFailed: "Prijava je uspjela, ali vaš račun nije moguće učitati. Pokušajte ponovno.",
334
+ discardPendingSyncCancel: "Ostani prijavljen",
335
+ discardPendingSyncConfirm: "Odjavi se i odbaci",
336
+ discardPendingSyncMessage: "Broj nesinkroniziranih offline promjena: {{count}}. Odjavom se lokalni podaci na ovom uređaju brišu pa će te promjene biti trajno izgubljene.",
337
+ discardPendingSyncTitle: "Nesinkronizirane offline promjene",
338
+ invalidCredentials: "Neispravni podaci za prijavu.",
339
+ password: "Lozinka",
340
+ sessionExpired: "Vaša sesija je istekla. Prijavite se ponovno za nastavak.",
341
+ signIn: "Prijava",
342
+ signInSubtitle: "Unesite svoje podatke za pristup računu.",
343
+ signedInAs: "Prijavljen kao",
344
+ username: "Korisničko ime"
345
+ },
346
+ settings: {
347
+ lockNavigationBar: "Zaključaj navigacijsku traku",
348
+ noMaxWidth: "Bez maksimalne širine",
349
+ pageBodyMaxWidth: "Širina sadržaja stranice",
350
+ pageBodyMaxWidthLg: "Široko",
351
+ pageBodyMaxWidthMd: "Srednje",
352
+ pageBodyMaxWidthSm: "Usko",
353
+ pageBodyMaxWidthXl: "Vrlo široko",
354
+ pageBodyMaxWidthXs: "Vrlo usko",
355
+ title: "Postavke aplikacije",
356
+ userSettingsSavedSuccessfully: "Postavke korisnika spremljene."
357
+ }
358
+ }, h = ["en", "hr"], g = {
359
+ en: p,
360
+ hr: m
361
+ };
362
+ function _(e) {
363
+ return c({
364
+ namespace: f,
365
+ baseResources: g,
366
+ seedFrom: e.seedFrom ?? "en",
367
+ locales: e.locales,
368
+ overrides: e.overrides
369
+ });
370
+ }
371
+ //#endregion
372
+ //#region src/queryengine/namespace.ts
373
+ var v = "queryengine", y = {
374
+ title: "Dev tools",
375
+ subtitle: "Inspect backend query metadata and render filters from it.",
376
+ availableEntities: "Available entities",
377
+ backendConfiguration: "Backend configuration JSON",
378
+ renderedFilterJson: "Rendered filter JSON",
379
+ filters: "Filters",
380
+ noFiltersAdded: "No filters added.",
381
+ addFilter: "+ Add filter",
382
+ relationType: "Relation",
383
+ fromDate: "From",
384
+ toDate: "To",
385
+ rowsJson: "Rows (JSON)",
386
+ rowsJsonPlaceholder: "[]",
387
+ fieldsCountLabel: "fields",
388
+ entityType: "Entity type",
389
+ entityKey: "Entity key",
390
+ operator: "Operator",
391
+ value: "Value",
392
+ noFilterableFields: "No filterable fields were returned for this entity.",
393
+ ok: "OK",
394
+ operators: {
395
+ EQUALS: "Equals",
396
+ NOT_EQUALS: "Not equals",
397
+ CONTAINS: "Contains",
398
+ STARTS_WITH: "Starts with",
399
+ ENDS_WITH: "Ends with",
400
+ IN: "In",
401
+ GREATER_THAN: "Greater than",
402
+ GREATER_OR_EQUAL: "Greater or equal",
403
+ LESS_THAN: "Less than",
404
+ LESS_OR_EQUAL: "Less or equal",
405
+ DATE_RANGE: "Date range",
406
+ IS_NULL: "Is null",
407
+ IS_NOT_NULL: "Is not null"
408
+ }
409
+ }, b = {
410
+ title: "Dev alati",
411
+ subtitle: "Pregledajte backend metapodatke upita i renderirajte filtere iz njih.",
412
+ availableEntities: "Dostupni entiteti",
413
+ backendConfiguration: "JSON konfiguracije iz backenda",
414
+ renderedFilterJson: "Renderirani JSON filtera",
415
+ filters: "Filteri",
416
+ noFiltersAdded: "Nema dodanih filtera.",
417
+ addFilter: "+ Dodaj filter",
418
+ relationType: "Relacija",
419
+ fromDate: "Od",
420
+ toDate: "Do",
421
+ rowsJson: "Retci (JSON)",
422
+ rowsJsonPlaceholder: "[]",
423
+ fieldsCountLabel: "polja",
424
+ entityType: "Tip entiteta",
425
+ entityKey: "Ključ entiteta",
426
+ operator: "Operator",
427
+ value: "Vrijednost",
428
+ noFilterableFields: "Za ovaj entitet nije vraćeno nijedno filterabilno polje.",
429
+ ok: "OK",
430
+ operators: {
431
+ EQUALS: "Jednako",
432
+ NOT_EQUALS: "Nije jednako",
433
+ CONTAINS: "Sadrži",
434
+ STARTS_WITH: "Počinje s",
435
+ ENDS_WITH: "Završava s",
436
+ IN: "U skupu",
437
+ GREATER_THAN: "Veće od",
438
+ GREATER_OR_EQUAL: "Veće ili jednako",
439
+ LESS_THAN: "Manje od",
440
+ LESS_OR_EQUAL: "Manje ili jednako",
441
+ DATE_RANGE: "Raspon datuma",
442
+ IS_NULL: "Je prazno",
443
+ IS_NOT_NULL: "Nije prazno"
444
+ }
445
+ }, x = ["en", "hr"], S = {
446
+ en: y,
447
+ hr: b
448
+ };
449
+ function C(e) {
450
+ return c({
451
+ namespace: v,
452
+ baseResources: S,
453
+ seedFrom: e.seedFrom ?? "en",
454
+ locales: e.locales,
455
+ overrides: e.overrides
456
+ });
457
+ }
458
+ //#endregion
459
+ //#region src/createStarterResources.ts
460
+ var w = [
461
+ f,
462
+ v,
463
+ n
464
+ ], T = ["en", "hr"];
465
+ function E(e, t, n) {
466
+ if (!t) return;
467
+ let r = {};
468
+ for (let i of e) {
469
+ let e = t[i]?.[n];
470
+ e && (r[i] = e);
471
+ }
472
+ return r;
473
+ }
474
+ function D(e) {
475
+ let { locales: t, seedFrom: r, overrides: i } = e;
476
+ s("createStarterResources", t, i);
477
+ let a = _({
478
+ locales: t,
479
+ seedFrom: r,
480
+ overrides: E(t, i, f)
481
+ }), o = C({
482
+ locales: t,
483
+ seedFrom: r,
484
+ overrides: E(t, i, v)
485
+ }), c = d({
486
+ locales: t,
487
+ seedFrom: r,
488
+ overrides: E(t, i, n)
489
+ }), l = {};
490
+ for (let e of t) l[e] = {
491
+ ...a[e],
492
+ ...o[e],
493
+ ...c[e]
494
+ };
495
+ return l;
496
+ }
497
+ function O(e, t) {
498
+ let n = D(t);
499
+ for (let t of Object.keys(n)) for (let r of w) e.addResourceBundle(t, r, n[t][r], !0, !0);
500
+ }
501
+ //#endregion
502
+ //#region src/formatters/intlNumberFormat.ts
503
+ function k(e, t) {
504
+ try {
505
+ return new Intl.NumberFormat(t.locale, t.options).format(e);
506
+ } catch {
507
+ return t.fallback?.(e) ?? String(e);
508
+ }
509
+ }
510
+ //#endregion
511
+ export { l as HISTORY_BASE_LOCALES, n as HISTORY_TRANSLATION_NAMESPACE, h as PLATFORM_BASE_LOCALES, f as PLATFORM_TRANSLATION_NAMESPACE, x as QUERYENGINE_BASE_LOCALES, v as QUERYENGINE_TRANSLATION_NAMESPACE, T as STARTER_BASE_LOCALES, w as STARTER_TRANSLATION_NAMESPACES, d as createHistoryResources, c as createNamespaceResources, _ as createPlatformResources, C as createQueryEngineResources, D as createStarterResources, o as deepMerge, k as formatIntlNumber, u as historyBaseResources, g as platformBaseResources, S as queryEngineBaseResources, O as registerStarterResources };
512
+
513
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/history/history.en.ts","../src/history/history.hr.ts","../src/history/namespace.ts","../src/toolkit/deepMerge.ts","../src/toolkit/validateResourceConfiguration.ts","../src/toolkit/createNamespaceResources.ts","../src/history/createHistoryResources.ts","../src/platform/namespace.ts","../src/platform/platform.en.ts","../src/platform/platform.hr.ts","../src/platform/createPlatformResources.ts","../src/queryengine/namespace.ts","../src/queryengine/queryengine.en.ts","../src/queryengine/queryengine.hr.ts","../src/queryengine/createQueryEngineResources.ts","../src/createStarterResources.ts","../src/formatters/intlNumberFormat.ts"],"sourcesContent":["const HISTORY_EN = {\n title: \"History\",\n empty: \"No history yet.\",\n showUnchanged: \"Show unchanged\",\n hideUnchanged: \"Hide unchanged\",\n viewHistory: \"View history\",\n} as const;\n\nexport default HISTORY_EN;\n","const HISTORY_HR = {\n title: \"Povijest\",\n empty: \"Još nema povijesti.\",\n showUnchanged: \"Prikaži nepromijenjeno\",\n hideUnchanged: \"Sakrij nepromijenjeno\",\n viewHistory: \"Prikaži povijest\",\n} as const;\n\nexport default HISTORY_HR;\n","export const HISTORY_TRANSLATION_NAMESPACE = \"history\" as const;\nexport type HistoryTranslationNamespace = typeof HISTORY_TRANSLATION_NAMESPACE;\n","type UnknownRecord = Record<string, unknown>;\nconst UNSAFE_OBJECT_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\nfunction isPlainObject(value: unknown): value is UnknownRecord {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction cloneValue<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map(item => cloneValue(item)) as T;\n }\n\n if (isPlainObject(value)) {\n const clone: UnknownRecord = {};\n for (const [key, nestedValue] of Object.entries(value)) {\n if (!UNSAFE_OBJECT_KEYS.has(key)) {\n clone[key] = cloneValue(nestedValue);\n }\n }\n return clone as T;\n }\n\n return value;\n}\n\n/**\n * Recursively merges `override` onto `base`, returning a new value.\n *\n * - Plain objects are merged key-by-key.\n * - Any non-plain-object value (string, number, array, etc.) in `override`\n * replaces the corresponding value in `base`.\n * - `undefined` values in `override` are ignored, so partial overrides never\n * erase base keys.\n * - Inputs and nested values are cloned, so callers cannot mutate source\n * resources through the returned object.\n * - Prototype-mutating keys are ignored.\n *\n * The result always retains the full shape of `base`, which is what guarantees\n * that a partial locale override can never introduce a missing translation key.\n */\nexport function deepMerge<T>(base: T, override: unknown): T {\n if (!isPlainObject(base) || !isPlainObject(override)) {\n return cloneValue(override === undefined ? base : (override as T));\n }\n\n const result = cloneValue(base) as UnknownRecord;\n\n for (const key of Object.keys(override)) {\n if (UNSAFE_OBJECT_KEYS.has(key)) {\n continue;\n }\n\n const overrideValue = override[key];\n if (overrideValue === undefined) {\n continue;\n }\n\n const baseValue = result[key];\n result[key] =\n isPlainObject(baseValue) && isPlainObject(overrideValue)\n ? deepMerge(baseValue, overrideValue)\n : cloneValue(overrideValue);\n }\n\n return result as T;\n}\n","type OverridesByLocale = Readonly<Record<string, unknown>> | undefined;\n\nexport function validateResourceConfiguration(\n caller: string,\n locales: readonly string[],\n overrides?: OverridesByLocale,\n): void {\n if (locales.length === 0) {\n throw new Error(`${caller} requires at least one locale identifier.`);\n }\n\n const invalidLocale = locales.find(locale => locale.trim().length === 0 || locale !== locale.trim());\n if (invalidLocale !== undefined) {\n throw new Error(`${caller} requires non-empty, trimmed locale identifiers.`);\n }\n\n if (new Set(locales).size !== locales.length) {\n throw new Error(`${caller} requires unique locale identifiers.`);\n }\n\n if (!overrides) {\n return;\n }\n\n const requestedLocales = new Set(locales);\n const unexpectedLocale = Object.keys(overrides).find(locale => !requestedLocales.has(locale));\n if (unexpectedLocale !== undefined) {\n throw new Error(`${caller} received an override for unrequested locale \"${unexpectedLocale}\".`);\n }\n}\n","import { deepMerge } from \"./deepMerge\";\nimport { validateResourceConfiguration } from \"./validateResourceConfiguration\";\n\n/**\n * A recursively partial version of `T`. Consumers use it to supply per-locale\n * value overrides without having to restate the full resource shape.\n */\nexport type DeepPartial<T> = T extends (infer U)[]\n ? DeepPartial<U>[]\n : T extends object\n ? { [K in keyof T]?: DeepPartial<T[K]> }\n : T;\n\n/**\n * Widens leaf string/number/boolean literals to their base primitive while\n * preserving object structure. Used to type base resource maps whose non-seed\n * locales share the shape but not the literal values of the canonical locale.\n */\nexport type WidenLeaves<T> = T extends string\n ? string\n : T extends number\n ? number\n : T extends boolean\n ? boolean\n : T extends (infer U)[]\n ? WidenLeaves<U>[]\n : T extends object\n ? { [K in keyof T]: WidenLeaves<T[K]> }\n : T;\n\nexport type CreateNamespaceResourcesConfig<TShape extends object, B extends string, L extends string> = {\n /** The i18next namespace the resulting resources are keyed under. */\n namespace: string;\n /** Locales the library ships out of the box, keyed by locale code. */\n baseResources: Record<B, TShape>;\n /** Base locale used to seed locales that the library does not ship. */\n seedFrom: B;\n /** The full set of locales the consumer app wants to support. */\n locales: readonly L[];\n /** Optional per-locale value overrides, deep-merged over the seeded base. */\n overrides?: Partial<Record<L, DeepPartial<TShape>>>;\n};\n\n/**\n * Builds a fully-populated i18next resource map for every requested locale.\n *\n * For each locale the merge chain is:\n * 1. Start from the `seedFrom` base resource (guarantees every key exists).\n * 2. If the locale is a shipped base locale, layer its shipped resource.\n * 3. Layer the consumer's partial override, if any.\n *\n * The result is `Record<Locale, { [namespace]: TShape }>`, so no key is ever\n * missing for any requested locale — including brand-new languages the library\n * does not ship, which fall back to the seed until translated.\n */\nexport function createNamespaceResources<TShape extends object, B extends string, L extends string, N extends string>(\n config: CreateNamespaceResourcesConfig<TShape, B, L> & { namespace: N },\n): Record<L, Record<N, TShape>> {\n const { namespace, baseResources, seedFrom, locales, overrides } = config;\n\n if (namespace.trim().length === 0) {\n throw new Error(\"createNamespaceResources requires a non-empty namespace.\");\n }\n if (!Object.prototype.hasOwnProperty.call(baseResources, seedFrom)) {\n throw new Error(`createNamespaceResources could not find seed locale \"${seedFrom}\".`);\n }\n validateResourceConfiguration(\"createNamespaceResources\", locales, overrides);\n\n const seed = baseResources[seedFrom];\n const result = {} as Record<L, Record<N, TShape>>;\n\n for (const locale of locales) {\n const shipped = (baseResources as Record<string, TShape | undefined>)[locale];\n const override = overrides?.[locale];\n\n let merged = deepMerge(seed, undefined);\n if (shipped) {\n merged = deepMerge(merged, shipped);\n }\n if (override) {\n merged = deepMerge(merged, override);\n }\n\n result[locale] = { [namespace]: merged } as Record<N, TShape>;\n }\n\n return result;\n}\n","import HISTORY_EN from \"./history.en\";\nimport HISTORY_HR from \"./history.hr\";\nimport { HISTORY_TRANSLATION_NAMESPACE } from \"./namespace\";\nimport { createNamespaceResources, type DeepPartial, type WidenLeaves } from \"../toolkit/createNamespaceResources\";\n\nexport { HISTORY_TRANSLATION_NAMESPACE, type HistoryTranslationNamespace } from \"./namespace\";\n\n/** The canonical History resource shape. English is the key source of truth. */\nexport type HistoryResources = WidenLeaves<typeof HISTORY_EN>;\n\n/**\n * A recursively partial resource, used for per-locale value overrides. Leaves\n * are widened, so an override may supply any string for a shipped key.\n */\nexport type HistoryResourcesOverride = DeepPartial<HistoryResources>;\n\n/** Locales the History namespace ships out of the box. */\nexport const HISTORY_BASE_LOCALES = [\"en\", \"hr\"] as const;\nexport type HistoryBaseLocale = (typeof HISTORY_BASE_LOCALES)[number];\n\nexport const historyBaseResources: Record<HistoryBaseLocale, HistoryResources> = {\n en: HISTORY_EN,\n hr: HISTORY_HR,\n};\n\nexport type CreateHistoryResourcesConfig<L extends string> = {\n /** The full set of locales the consumer app wants to support. */\n locales: readonly L[];\n /** Base locale used to seed locales the namespace does not ship. Defaults to `\"en\"`. */\n seedFrom?: HistoryBaseLocale;\n /** Optional per-locale value overrides, deep-merged over the seeded base. */\n overrides?: Partial<Record<L, HistoryResourcesOverride>>;\n};\n\n/**\n * Builds a fully-populated History resource map for every requested locale.\n */\nexport function createHistoryResources<L extends string>(\n config: CreateHistoryResourcesConfig<L>,\n): Record<L, { [HISTORY_TRANSLATION_NAMESPACE]: HistoryResources }> {\n return createNamespaceResources({\n namespace: HISTORY_TRANSLATION_NAMESPACE,\n baseResources: historyBaseResources,\n seedFrom: config.seedFrom ?? \"en\",\n locales: config.locales,\n overrides: config.overrides,\n });\n}\n","export const PLATFORM_TRANSLATION_NAMESPACE = \"platform\" as const;\nexport type PlatformTranslationNamespace = typeof PLATFORM_TRANSLATION_NAMESPACE;\n","const en = {\n common: {\n actions: \"Actions\",\n ascending: \"Ascending\",\n ascendingSortDirection: \"Ascending sort direction\",\n back: \"Back\",\n bottomNavigation: \"Bottom navigation\",\n cancel: \"Cancel\",\n clearAll: \"Clear all\",\n clearSearch: \"Clear search\",\n closeFilters: \"Close filters\",\n closeNavigation: \"Close navigation\",\n collapse: \"Collapse\",\n column: \"Sort by\",\n create: \"Create\",\n dark: \"Dark\",\n delete: \"Delete\",\n descending: \"Descending\",\n descendingSortDirection: \"Descending sort direction\",\n direction: \"Sort direction\",\n discard: \"Discard\",\n done: \"Done\",\n download: \"Download\",\n edit: \"Edit\",\n expand: \"Expand\",\n filters: \"Filters\",\n language: \"Language\",\n light: \"Light\",\n loading: \"Loading\",\n logout: \"Sign out\",\n mainNavigation: \"Main navigation\",\n month: \"Month\",\n more: \"More\",\n name: \"Name\",\n noRecordsFound: \"No records found.\",\n openFilters: \"Open filters\",\n profile: \"Profile\",\n settings: \"Settings\",\n theme: \"Theme\",\n year: \"Year\",\n no: \"No\",\n yes: \"Yes\",\n save: \"Save\",\n search: \"Search\",\n skipToMainContent: \"Skip to main content\",\n },\n pwa: {\n newVersionAvailable: \"New version available.\",\n reload: \"Reload\",\n },\n network: {\n actionQueued: \"Saved offline. Sent when connection returns.\",\n actionUnavailable: \"This action is unavailable while offline.\",\n commandId: \"Command ID\",\n connectingToLiveUpdates: \"Connecting to live updates...\",\n createdAt: \"Created at\",\n dataUnavailable: \"This data is unavailable while offline.\",\n diagnostics: \"Offline diagnostics\",\n errorMessage: \"Error message\",\n failedLoadingData: \"Failed loading data.\",\n httpMethod: \"HTTP method\",\n hydratingInBackground: \"Syncing local data in background. You can keep using the app.\",\n lastHeartbeat: \"Last heartbeat\",\n lastSyncFailure: \"Last failure\",\n mutationQueuedOffline: \"Saved locally — pending sync\",\n offline: \"Offline\",\n offlineBanner: \"You are offline. Data may be unavailable and changes are disabled.\",\n offlineModeNotSupported: \"This action is not available in offline mode yet.\",\n offlineQueuePending: \"Offline — {{count}} changes pending sync\",\n online: \"Online\",\n owner: \"Owner\",\n processedAt: \"Processed at\",\n queuePermanentlyFailed: \"{{count}} change(s) failed to sync and need attention\",\n queueSize: \"Queued commands\",\n queueSynced: \"Synced\",\n reconnecting: \"Reconnecting\",\n responseStatus: \"Response status\",\n searchSyncCommands: \"Search sync commands\",\n status: \"Status\",\n syncCommands: \"Sync commands\",\n syncFailures: \"Sync failures\",\n syncIdle: \"Idle\",\n syncInProgress: \"In progress\",\n syncStatus: \"Sync status\",\n unavailable: \"Unavailable\",\n url: \"URL\",\n youAreOffline: \"Offline mode\",\n },\n routing: {\n errorChunkMessage:\n \"This page could not be loaded. This can happen after an app update — try refreshing the application.\",\n errorGenericMessage: \"An unexpected error occurred while loading this page.\",\n errorOfflineMessage: \"You appear to be offline. Check your connection and try again.\",\n errorRefresh: \"Refresh app\",\n errorRetry: \"Retry\",\n errorTitle: \"Something went wrong\",\n goHome: \"Go to overview\",\n notFoundMessage: \"The page you requested does not exist or may have moved.\",\n notFoundTitle: \"Page not found\",\n unauthorizedMessage: \"You do not have permission to view this page.\",\n unauthorizedTitle: \"Access denied\",\n },\n unsavedChanges: {\n discardAndLeave: \"Discard and leave\",\n message: \"You have unsaved changes. Discard them and leave?\",\n savingMessage: \"Your changes are being saved. Wait for the save to finish before leaving.\",\n savingTitle: \"Saving changes\",\n stay: \"Stay\",\n title: \"Unsaved changes\",\n },\n validation: {\n thisFieldIsRequired: \"This field is required.\",\n },\n auth: {\n currentUserLoadFailed: \"Sign-in succeeded, but your account could not be loaded. Please try again.\",\n discardPendingSyncCancel: \"Stay signed in\",\n discardPendingSyncConfirm: \"Sign out and discard\",\n discardPendingSyncMessage:\n \"{{count}} offline change(s) have not been synced yet. Signing out deletes the local data on this device, so those changes will be lost permanently.\",\n discardPendingSyncTitle: \"Unsynced offline changes\",\n invalidCredentials: \"Invalid credentials.\",\n password: \"Password\",\n sessionExpired: \"Your session has expired. Sign in again to continue.\",\n signIn: \"Sign in\",\n signInSubtitle: \"Enter your credentials to access your account.\",\n signedInAs: \"Signed in as\",\n username: \"Username\",\n },\n settings: {\n lockNavigationBar: \"Lock navigation bar\",\n noMaxWidth: \"No max width\",\n pageBodyMaxWidth: \"Page content width\",\n pageBodyMaxWidthLg: \"Large\",\n pageBodyMaxWidthMd: \"Medium\",\n pageBodyMaxWidthSm: \"Small\",\n pageBodyMaxWidthXl: \"Extra large\",\n pageBodyMaxWidthXs: \"Extra small\",\n title: \"Application settings\",\n userSettingsSavedSuccessfully: \"User settings saved.\",\n },\n} as const;\n\nexport default en;\n","const hr = {\n common: {\n actions: \"Akcije\",\n ascending: \"Uzlazno\",\n ascendingSortDirection: \"Uzlazni smjer sortiranja\",\n back: \"Natrag\",\n bottomNavigation: \"Navigacija pri dnu\",\n cancel: \"Odustani\",\n clearAll: \"Očisti sve\",\n clearSearch: \"Očisti pretragu\",\n closeFilters: \"Zatvori filtere\",\n closeNavigation: \"Zatvori navigaciju\",\n collapse: \"Sažmi\",\n column: \"Sortiraj po\",\n create: \"Kreiraj\",\n dark: \"Tamna\",\n delete: \"Obriši\",\n descending: \"Silazno\",\n descendingSortDirection: \"Silazni smjer sortiranja\",\n direction: \"Smjer sortiranja\",\n discard: \"Odbaci\",\n done: \"Gotovo\",\n download: \"Preuzmi\",\n edit: \"Uredi\",\n expand: \"Proširi\",\n filters: \"Filteri\",\n language: \"Jezik\",\n light: \"Svijetla\",\n loading: \"Učitavanje\",\n logout: \"Odjava\",\n mainNavigation: \"Glavna navigacija\",\n month: \"Mjesec\",\n more: \"Više\",\n name: \"Naziv\",\n noRecordsFound: \"Nema pronađenih zapisa.\",\n openFilters: \"Otvori filtere\",\n profile: \"Profil\",\n settings: \"Postavke\",\n theme: \"Tema\",\n year: \"Godina\",\n no: \"Ne\",\n yes: \"Da\",\n save: \"Spremi\",\n search: \"Pretraži\",\n skipToMainContent: \"Preskoči na glavni sadržaj\",\n },\n pwa: {\n newVersionAvailable: \"Dostupna je nova verzija.\",\n reload: \"Osvježi\",\n },\n network: {\n actionQueued: \"Spremljeno offline. Šalje se kad se veza vrati.\",\n actionUnavailable: \"Ova radnja nije dostupna dok ste izvan mreže.\",\n commandId: \"ID naredbe\",\n connectingToLiveUpdates: \"Povezivanje na promjene uživo...\",\n createdAt: \"Kreirano\",\n dataUnavailable: \"Ovi podaci nisu dostupni dok ste izvan mreže.\",\n diagnostics: \"Offline dijagnostika\",\n errorMessage: \"Poruka greške\",\n failedLoadingData: \"Neuspjelo učitavanje podataka.\",\n httpMethod: \"HTTP metoda\",\n hydratingInBackground: \"Lokalni podaci se sinkroniziraju u pozadini. Možete nastaviti koristiti aplikaciju.\",\n lastHeartbeat: \"Zadnji heartbeat\",\n lastSyncFailure: \"Zadnja greška\",\n mutationQueuedOffline: \"Spremljeno lokalno — čeka sinkronizaciju\",\n offline: \"Offline\",\n offlineBanner: \"Niste povezani s mrežom. Podaci možda nisu dostupni, a promjene su onemogućene.\",\n offlineModeNotSupported: \"Ova akcija još nije dostupna u offline načinu rada.\",\n offlineQueuePending: \"Offline — {{count}} promjene čekaju sinkronizaciju\",\n online: \"Online\",\n owner: \"Vlasnik\",\n processedAt: \"Obrađeno\",\n queuePermanentlyFailed: \"{{count}} promjena nije uspjelo sinkronizirati — potrebna provjera\",\n queueSize: \"Naredbe u redu\",\n queueSynced: \"Sinkronizirano\",\n reconnecting: \"Ponovno povezivanje\",\n responseStatus: \"Status odgovora\",\n searchSyncCommands: \"Pretraži naredbe sinkronizacije\",\n status: \"Status\",\n syncCommands: \"Naredbe sinkronizacije\",\n syncFailures: \"Greške sinkronizacije\",\n syncIdle: \"Miruje\",\n syncInProgress: \"U tijeku\",\n syncStatus: \"Status sinkronizacije\",\n unavailable: \"Nedostupno\",\n url: \"URL\",\n youAreOffline: \"Offline način rada\",\n },\n routing: {\n errorChunkMessage:\n \"Ova stranica nije mogla biti učitana. To se može dogoditi nakon ažuriranja aplikacije — pokušajte osvježiti aplikaciju.\",\n errorGenericMessage: \"Došlo je do neočekivane greške prilikom učitavanja ove stranice.\",\n errorOfflineMessage: \"Izgleda da ste offline. Provjerite internetsku vezu i pokušajte ponovno.\",\n errorRefresh: \"Osvježi aplikaciju\",\n errorRetry: \"Pokušaj ponovno\",\n errorTitle: \"Nešto je pošlo po zlu\",\n goHome: \"Idi na pregled\",\n notFoundMessage: \"Tražena stranica ne postoji ili je premještena.\",\n notFoundTitle: \"Stranica nije pronađena\",\n unauthorizedMessage: \"Nemate dopuštenje za prikaz ove stranice.\",\n unauthorizedTitle: \"Pristup odbijen\",\n },\n unsavedChanges: {\n discardAndLeave: \"Odbaci i napusti\",\n message: \"Imate nespremljene promjene. Odbaciti ih i napustiti stranicu?\",\n savingMessage: \"Promjene se spremaju. Pričekajte završetak spremanja prije napuštanja stranice.\",\n savingTitle: \"Spremanje promjena\",\n stay: \"Ostani\",\n title: \"Nespremljene promjene\",\n },\n validation: {\n thisFieldIsRequired: \"Ovo polje je obavezno.\",\n },\n auth: {\n currentUserLoadFailed: \"Prijava je uspjela, ali vaš račun nije moguće učitati. Pokušajte ponovno.\",\n discardPendingSyncCancel: \"Ostani prijavljen\",\n discardPendingSyncConfirm: \"Odjavi se i odbaci\",\n discardPendingSyncMessage:\n \"Broj nesinkroniziranih offline promjena: {{count}}. Odjavom se lokalni podaci na ovom uređaju brišu pa će te promjene biti trajno izgubljene.\",\n discardPendingSyncTitle: \"Nesinkronizirane offline promjene\",\n invalidCredentials: \"Neispravni podaci za prijavu.\",\n password: \"Lozinka\",\n sessionExpired: \"Vaša sesija je istekla. Prijavite se ponovno za nastavak.\",\n signIn: \"Prijava\",\n signInSubtitle: \"Unesite svoje podatke za pristup računu.\",\n signedInAs: \"Prijavljen kao\",\n username: \"Korisničko ime\",\n },\n settings: {\n lockNavigationBar: \"Zaključaj navigacijsku traku\",\n noMaxWidth: \"Bez maksimalne širine\",\n pageBodyMaxWidth: \"Širina sadržaja stranice\",\n pageBodyMaxWidthLg: \"Široko\",\n pageBodyMaxWidthMd: \"Srednje\",\n pageBodyMaxWidthSm: \"Usko\",\n pageBodyMaxWidthXl: \"Vrlo široko\",\n pageBodyMaxWidthXs: \"Vrlo usko\",\n title: \"Postavke aplikacije\",\n userSettingsSavedSuccessfully: \"Postavke korisnika spremljene.\",\n },\n} as const;\n\nexport default hr;\n","import { PLATFORM_TRANSLATION_NAMESPACE } from \"./namespace\";\nimport PLATFORM_EN from \"./platform.en\";\nimport PLATFORM_HR from \"./platform.hr\";\nimport { createNamespaceResources, type DeepPartial, type WidenLeaves } from \"../toolkit/createNamespaceResources\";\n\nexport { PLATFORM_TRANSLATION_NAMESPACE, type PlatformTranslationNamespace } from \"./namespace\";\n\n/** The canonical platform resource shape. English is the key source of truth. */\nexport type PlatformResources = WidenLeaves<typeof PLATFORM_EN>;\n\n/**\n * A recursively partial platform resource, used for per-locale value overrides.\n * Leaves are widened, so an override may supply any string for a shipped key.\n */\nexport type PlatformResourcesOverride = DeepPartial<PlatformResources>;\n\n/** Locales the platform ships out of the box. */\nexport const PLATFORM_BASE_LOCALES = [\"en\", \"hr\"] as const;\nexport type PlatformBaseLocale = (typeof PLATFORM_BASE_LOCALES)[number];\n\nexport const platformBaseResources: Record<PlatformBaseLocale, PlatformResources> = {\n en: PLATFORM_EN,\n hr: PLATFORM_HR,\n};\n\nexport type CreatePlatformResourcesConfig<L extends string> = {\n /** The full set of locales the consumer app wants to support. */\n locales: readonly L[];\n /** Base locale used to seed locales the platform does not ship. Defaults to `\"en\"`. */\n seedFrom?: PlatformBaseLocale;\n /** Optional per-locale value overrides, deep-merged over the seeded base. */\n overrides?: Partial<Record<L, PlatformResourcesOverride>>;\n};\n\n/**\n * Builds a fully-populated platform resource map for every requested locale.\n *\n * Consumers can override any shipped value per locale and add brand-new\n * languages (seeded from a base locale until translated) without ever ending\n * up with a missing platform key.\n */\nexport function createPlatformResources<L extends string>(\n config: CreatePlatformResourcesConfig<L>,\n): Record<L, { [PLATFORM_TRANSLATION_NAMESPACE]: PlatformResources }> {\n return createNamespaceResources({\n namespace: PLATFORM_TRANSLATION_NAMESPACE,\n baseResources: platformBaseResources,\n seedFrom: config.seedFrom ?? \"en\",\n locales: config.locales,\n overrides: config.overrides,\n });\n}\n","export const QUERYENGINE_TRANSLATION_NAMESPACE = \"queryengine\" as const;\nexport type QueryEngineTranslationNamespace = typeof QUERYENGINE_TRANSLATION_NAMESPACE;\n","const en = {\n title: \"Dev tools\",\n subtitle: \"Inspect backend query metadata and render filters from it.\",\n availableEntities: \"Available entities\",\n backendConfiguration: \"Backend configuration JSON\",\n renderedFilterJson: \"Rendered filter JSON\",\n filters: \"Filters\",\n noFiltersAdded: \"No filters added.\",\n addFilter: \"+ Add filter\",\n relationType: \"Relation\",\n fromDate: \"From\",\n toDate: \"To\",\n rowsJson: \"Rows (JSON)\",\n rowsJsonPlaceholder: \"[]\",\n fieldsCountLabel: \"fields\",\n entityType: \"Entity type\",\n entityKey: \"Entity key\",\n operator: \"Operator\",\n value: \"Value\",\n noFilterableFields: \"No filterable fields were returned for this entity.\",\n ok: \"OK\",\n operators: {\n EQUALS: \"Equals\",\n NOT_EQUALS: \"Not equals\",\n CONTAINS: \"Contains\",\n STARTS_WITH: \"Starts with\",\n ENDS_WITH: \"Ends with\",\n IN: \"In\",\n GREATER_THAN: \"Greater than\",\n GREATER_OR_EQUAL: \"Greater or equal\",\n LESS_THAN: \"Less than\",\n LESS_OR_EQUAL: \"Less or equal\",\n DATE_RANGE: \"Date range\",\n IS_NULL: \"Is null\",\n IS_NOT_NULL: \"Is not null\",\n },\n} as const;\n\nexport default en;\n","const hr = {\n title: \"Dev alati\",\n subtitle: \"Pregledajte backend metapodatke upita i renderirajte filtere iz njih.\",\n availableEntities: \"Dostupni entiteti\",\n backendConfiguration: \"JSON konfiguracije iz backenda\",\n renderedFilterJson: \"Renderirani JSON filtera\",\n filters: \"Filteri\",\n noFiltersAdded: \"Nema dodanih filtera.\",\n addFilter: \"+ Dodaj filter\",\n relationType: \"Relacija\",\n fromDate: \"Od\",\n toDate: \"Do\",\n rowsJson: \"Retci (JSON)\",\n rowsJsonPlaceholder: \"[]\",\n fieldsCountLabel: \"polja\",\n entityType: \"Tip entiteta\",\n entityKey: \"Ključ entiteta\",\n operator: \"Operator\",\n value: \"Vrijednost\",\n noFilterableFields: \"Za ovaj entitet nije vraćeno nijedno filterabilno polje.\",\n ok: \"OK\",\n operators: {\n EQUALS: \"Jednako\",\n NOT_EQUALS: \"Nije jednako\",\n CONTAINS: \"Sadrži\",\n STARTS_WITH: \"Počinje s\",\n ENDS_WITH: \"Završava s\",\n IN: \"U skupu\",\n GREATER_THAN: \"Veće od\",\n GREATER_OR_EQUAL: \"Veće ili jednako\",\n LESS_THAN: \"Manje od\",\n LESS_OR_EQUAL: \"Manje ili jednako\",\n DATE_RANGE: \"Raspon datuma\",\n IS_NULL: \"Je prazno\",\n IS_NOT_NULL: \"Nije prazno\",\n },\n} as const;\n\nexport default hr;\n","import { QUERYENGINE_TRANSLATION_NAMESPACE } from \"./namespace\";\nimport QUERYENGINE_EN from \"./queryengine.en\";\nimport QUERYENGINE_HR from \"./queryengine.hr\";\nimport { createNamespaceResources, type DeepPartial, type WidenLeaves } from \"../toolkit/createNamespaceResources\";\n\nexport { QUERYENGINE_TRANSLATION_NAMESPACE, type QueryEngineTranslationNamespace } from \"./namespace\";\n\n/** The canonical Query Engine resource shape. English is the key source of truth. */\nexport type QueryEngineResources = WidenLeaves<typeof QUERYENGINE_EN>;\n\n/**\n * A recursively partial resource, used for per-locale value overrides. Leaves\n * are widened, so an override may supply any string for a shipped key.\n */\nexport type QueryEngineResourcesOverride = DeepPartial<QueryEngineResources>;\n\n/** Locales the QueryEngine namespace ships out of the box. */\nexport const QUERYENGINE_BASE_LOCALES = [\"en\", \"hr\"] as const;\nexport type QueryEngineBaseLocale = (typeof QUERYENGINE_BASE_LOCALES)[number];\n\nexport const queryEngineBaseResources: Record<QueryEngineBaseLocale, QueryEngineResources> = {\n en: QUERYENGINE_EN,\n hr: QUERYENGINE_HR,\n};\n\nexport type CreateQueryEngineResourcesConfig<L extends string> = {\n /** The full set of locales the consumer app wants to support. */\n locales: readonly L[];\n /** Base locale used to seed locales the namespace does not ship. Defaults to `\"en\"`. */\n seedFrom?: QueryEngineBaseLocale;\n /** Optional per-locale value overrides, deep-merged over the seeded base. */\n overrides?: Partial<Record<L, QueryEngineResourcesOverride>>;\n};\n\n/**\n * Builds a fully-populated QueryEngine resource map for every requested locale.\n */\nexport function createQueryEngineResources<L extends string>(\n config: CreateQueryEngineResourcesConfig<L>,\n): Record<L, { [QUERYENGINE_TRANSLATION_NAMESPACE]: QueryEngineResources }> {\n return createNamespaceResources({\n namespace: QUERYENGINE_TRANSLATION_NAMESPACE,\n baseResources: queryEngineBaseResources,\n seedFrom: config.seedFrom ?? \"en\",\n locales: config.locales,\n overrides: config.overrides,\n });\n}\n","import {\n createHistoryResources,\n HISTORY_TRANSLATION_NAMESPACE,\n type HistoryResources,\n type HistoryResourcesOverride,\n} from \"./history/createHistoryResources\";\nimport {\n createPlatformResources,\n PLATFORM_TRANSLATION_NAMESPACE,\n type PlatformResources,\n type PlatformResourcesOverride,\n} from \"./platform/createPlatformResources\";\nimport {\n createQueryEngineResources,\n QUERYENGINE_TRANSLATION_NAMESPACE,\n type QueryEngineResources,\n type QueryEngineResourcesOverride,\n} from \"./queryengine/createQueryEngineResources\";\nimport { type i18n as I18nInstance } from \"i18next\";\nimport { validateResourceConfiguration } from \"./toolkit/validateResourceConfiguration\";\n\n/** Every i18next namespace shipped by the starter libraries. */\nexport const STARTER_TRANSLATION_NAMESPACES = [\n PLATFORM_TRANSLATION_NAMESPACE,\n QUERYENGINE_TRANSLATION_NAMESPACE,\n HISTORY_TRANSLATION_NAMESPACE,\n] as const;\n\nexport type StarterTranslationNamespace = (typeof STARTER_TRANSLATION_NAMESPACES)[number];\n\n/** Locales every starter namespace ships out of the box. */\nexport const STARTER_BASE_LOCALES = [\"en\", \"hr\"] as const;\nexport type StarterBaseLocale = (typeof STARTER_BASE_LOCALES)[number];\n\n/** The resources contributed by the starter libraries, keyed by namespace. */\nexport type StarterNamespaceResources = {\n [PLATFORM_TRANSLATION_NAMESPACE]: PlatformResources;\n [QUERYENGINE_TRANSLATION_NAMESPACE]: QueryEngineResources;\n [HISTORY_TRANSLATION_NAMESPACE]: HistoryResources;\n};\n\n/** Per-locale, per-namespace value overrides. */\nexport type StarterResourcesOverride = {\n [PLATFORM_TRANSLATION_NAMESPACE]?: PlatformResourcesOverride;\n [QUERYENGINE_TRANSLATION_NAMESPACE]?: QueryEngineResourcesOverride;\n [HISTORY_TRANSLATION_NAMESPACE]?: HistoryResourcesOverride;\n};\n\nexport type CreateStarterResourcesConfig<L extends string> = {\n /** The full set of locales the consumer app wants to support. */\n locales: readonly L[];\n /** Base locale used to seed locales the starter does not ship. Defaults to `\"en\"`. */\n seedFrom?: StarterBaseLocale;\n /** Optional per-locale, per-namespace value overrides, deep-merged over the seeded base. */\n overrides?: Partial<Record<L, StarterResourcesOverride>>;\n};\n\n/** Narrows the per-locale override map down to a single namespace. */\nfunction namespaceOverrides<L extends string, N extends keyof StarterResourcesOverride>(\n locales: readonly L[],\n overrides: Partial<Record<L, StarterResourcesOverride>> | undefined,\n namespace: N,\n): Partial<Record<L, NonNullable<StarterResourcesOverride[N]>>> | undefined {\n if (!overrides) {\n return undefined;\n }\n\n const result: Partial<Record<L, NonNullable<StarterResourcesOverride[N]>>> = {};\n for (const locale of locales) {\n const override = overrides[locale]?.[namespace];\n if (override) {\n result[locale] = override as NonNullable<StarterResourcesOverride[N]>;\n }\n }\n\n return result;\n}\n\n/**\n * Builds every starter-owned namespace for the requested locales in a single\n * call, so apps spread one object per locale into their i18next resources and\n * pick up new starter namespaces without touching their wiring.\n */\nexport function createStarterResources<L extends string>(\n config: CreateStarterResourcesConfig<L>,\n): Record<L, StarterNamespaceResources> {\n const { locales, seedFrom, overrides } = config;\n\n validateResourceConfiguration(\"createStarterResources\", locales, overrides);\n\n const platform = createPlatformResources({\n locales,\n seedFrom,\n overrides: namespaceOverrides(locales, overrides, PLATFORM_TRANSLATION_NAMESPACE),\n });\n const queryengine = createQueryEngineResources({\n locales,\n seedFrom,\n overrides: namespaceOverrides(locales, overrides, QUERYENGINE_TRANSLATION_NAMESPACE),\n });\n const history = createHistoryResources({\n locales,\n seedFrom,\n overrides: namespaceOverrides(locales, overrides, HISTORY_TRANSLATION_NAMESPACE),\n });\n\n const result = {} as Record<L, StarterNamespaceResources>;\n for (const locale of locales) {\n result[locale] = {\n ...platform[locale],\n ...queryengine[locale],\n ...history[locale],\n };\n }\n\n return result;\n}\n\n/**\n * Imperatively registers every starter namespace onto an existing i18next\n * instance. Useful when resources are added after i18next has been initialized.\n */\nexport function registerStarterResources<L extends string>(\n i18n: I18nInstance,\n config: CreateStarterResourcesConfig<L>,\n): void {\n const resources = createStarterResources(config);\n\n for (const locale of Object.keys(resources) as L[]) {\n for (const namespace of STARTER_TRANSLATION_NAMESPACES) {\n i18n.addResourceBundle(locale, namespace, resources[locale][namespace], true, true);\n }\n }\n}\n","export type IntlNumberFormatRequest = {\n locale: string;\n options?: Intl.NumberFormatOptions;\n fallback?: (value: number) => string;\n};\n\n/** Locale-neutral formatting primitive; application locale/default policy stays at the call site. */\nexport function formatIntlNumber(value: number, request: IntlNumberFormatRequest): string {\n try {\n return new Intl.NumberFormat(request.locale, request.options).format(value);\n } catch {\n return request.fallback?.(value) ?? String(value);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { PLATFORM_TRANSLATION_NAMESPACE } from './namespace';
2
+ import { default as PLATFORM_EN } from './platform.en';
3
+ import { DeepPartial, WidenLeaves } from '../toolkit/createNamespaceResources';
4
+ export { PLATFORM_TRANSLATION_NAMESPACE, type PlatformTranslationNamespace } from './namespace';
5
+ /** The canonical platform resource shape. English is the key source of truth. */
6
+ export type PlatformResources = WidenLeaves<typeof PLATFORM_EN>;
7
+ /**
8
+ * A recursively partial platform resource, used for per-locale value overrides.
9
+ * Leaves are widened, so an override may supply any string for a shipped key.
10
+ */
11
+ export type PlatformResourcesOverride = DeepPartial<PlatformResources>;
12
+ /** Locales the platform ships out of the box. */
13
+ export declare const PLATFORM_BASE_LOCALES: readonly ["en", "hr"];
14
+ export type PlatformBaseLocale = (typeof PLATFORM_BASE_LOCALES)[number];
15
+ export declare const platformBaseResources: Record<PlatformBaseLocale, PlatformResources>;
16
+ export type CreatePlatformResourcesConfig<L extends string> = {
17
+ /** The full set of locales the consumer app wants to support. */
18
+ locales: readonly L[];
19
+ /** Base locale used to seed locales the platform does not ship. Defaults to `"en"`. */
20
+ seedFrom?: PlatformBaseLocale;
21
+ /** Optional per-locale value overrides, deep-merged over the seeded base. */
22
+ overrides?: Partial<Record<L, PlatformResourcesOverride>>;
23
+ };
24
+ /**
25
+ * Builds a fully-populated platform resource map for every requested locale.
26
+ *
27
+ * Consumers can override any shipped value per locale and add brand-new
28
+ * languages (seeded from a base locale until translated) without ever ending
29
+ * up with a missing platform key.
30
+ */
31
+ export declare function createPlatformResources<L extends string>(config: CreatePlatformResourcesConfig<L>): Record<L, {
32
+ [PLATFORM_TRANSLATION_NAMESPACE]: PlatformResources;
33
+ }>;
@@ -0,0 +1,2 @@
1
+ export declare const PLATFORM_TRANSLATION_NAMESPACE: "platform";
2
+ export type PlatformTranslationNamespace = typeof PLATFORM_TRANSLATION_NAMESPACE;
@@ -0,0 +1,140 @@
1
+ declare const en: {
2
+ readonly common: {
3
+ readonly actions: "Actions";
4
+ readonly ascending: "Ascending";
5
+ readonly ascendingSortDirection: "Ascending sort direction";
6
+ readonly back: "Back";
7
+ readonly bottomNavigation: "Bottom navigation";
8
+ readonly cancel: "Cancel";
9
+ readonly clearAll: "Clear all";
10
+ readonly clearSearch: "Clear search";
11
+ readonly closeFilters: "Close filters";
12
+ readonly closeNavigation: "Close navigation";
13
+ readonly collapse: "Collapse";
14
+ readonly column: "Sort by";
15
+ readonly create: "Create";
16
+ readonly dark: "Dark";
17
+ readonly delete: "Delete";
18
+ readonly descending: "Descending";
19
+ readonly descendingSortDirection: "Descending sort direction";
20
+ readonly direction: "Sort direction";
21
+ readonly discard: "Discard";
22
+ readonly done: "Done";
23
+ readonly download: "Download";
24
+ readonly edit: "Edit";
25
+ readonly expand: "Expand";
26
+ readonly filters: "Filters";
27
+ readonly language: "Language";
28
+ readonly light: "Light";
29
+ readonly loading: "Loading";
30
+ readonly logout: "Sign out";
31
+ readonly mainNavigation: "Main navigation";
32
+ readonly month: "Month";
33
+ readonly more: "More";
34
+ readonly name: "Name";
35
+ readonly noRecordsFound: "No records found.";
36
+ readonly openFilters: "Open filters";
37
+ readonly profile: "Profile";
38
+ readonly settings: "Settings";
39
+ readonly theme: "Theme";
40
+ readonly year: "Year";
41
+ readonly no: "No";
42
+ readonly yes: "Yes";
43
+ readonly save: "Save";
44
+ readonly search: "Search";
45
+ readonly skipToMainContent: "Skip to main content";
46
+ };
47
+ readonly pwa: {
48
+ readonly newVersionAvailable: "New version available.";
49
+ readonly reload: "Reload";
50
+ };
51
+ readonly network: {
52
+ readonly actionQueued: "Saved offline. Sent when connection returns.";
53
+ readonly actionUnavailable: "This action is unavailable while offline.";
54
+ readonly commandId: "Command ID";
55
+ readonly connectingToLiveUpdates: "Connecting to live updates...";
56
+ readonly createdAt: "Created at";
57
+ readonly dataUnavailable: "This data is unavailable while offline.";
58
+ readonly diagnostics: "Offline diagnostics";
59
+ readonly errorMessage: "Error message";
60
+ readonly failedLoadingData: "Failed loading data.";
61
+ readonly httpMethod: "HTTP method";
62
+ readonly hydratingInBackground: "Syncing local data in background. You can keep using the app.";
63
+ readonly lastHeartbeat: "Last heartbeat";
64
+ readonly lastSyncFailure: "Last failure";
65
+ readonly mutationQueuedOffline: "Saved locally — pending sync";
66
+ readonly offline: "Offline";
67
+ readonly offlineBanner: "You are offline. Data may be unavailable and changes are disabled.";
68
+ readonly offlineModeNotSupported: "This action is not available in offline mode yet.";
69
+ readonly offlineQueuePending: "Offline — {{count}} changes pending sync";
70
+ readonly online: "Online";
71
+ readonly owner: "Owner";
72
+ readonly processedAt: "Processed at";
73
+ readonly queuePermanentlyFailed: "{{count}} change(s) failed to sync and need attention";
74
+ readonly queueSize: "Queued commands";
75
+ readonly queueSynced: "Synced";
76
+ readonly reconnecting: "Reconnecting";
77
+ readonly responseStatus: "Response status";
78
+ readonly searchSyncCommands: "Search sync commands";
79
+ readonly status: "Status";
80
+ readonly syncCommands: "Sync commands";
81
+ readonly syncFailures: "Sync failures";
82
+ readonly syncIdle: "Idle";
83
+ readonly syncInProgress: "In progress";
84
+ readonly syncStatus: "Sync status";
85
+ readonly unavailable: "Unavailable";
86
+ readonly url: "URL";
87
+ readonly youAreOffline: "Offline mode";
88
+ };
89
+ readonly routing: {
90
+ readonly errorChunkMessage: "This page could not be loaded. This can happen after an app update — try refreshing the application.";
91
+ readonly errorGenericMessage: "An unexpected error occurred while loading this page.";
92
+ readonly errorOfflineMessage: "You appear to be offline. Check your connection and try again.";
93
+ readonly errorRefresh: "Refresh app";
94
+ readonly errorRetry: "Retry";
95
+ readonly errorTitle: "Something went wrong";
96
+ readonly goHome: "Go to overview";
97
+ readonly notFoundMessage: "The page you requested does not exist or may have moved.";
98
+ readonly notFoundTitle: "Page not found";
99
+ readonly unauthorizedMessage: "You do not have permission to view this page.";
100
+ readonly unauthorizedTitle: "Access denied";
101
+ };
102
+ readonly unsavedChanges: {
103
+ readonly discardAndLeave: "Discard and leave";
104
+ readonly message: "You have unsaved changes. Discard them and leave?";
105
+ readonly savingMessage: "Your changes are being saved. Wait for the save to finish before leaving.";
106
+ readonly savingTitle: "Saving changes";
107
+ readonly stay: "Stay";
108
+ readonly title: "Unsaved changes";
109
+ };
110
+ readonly validation: {
111
+ readonly thisFieldIsRequired: "This field is required.";
112
+ };
113
+ readonly auth: {
114
+ readonly currentUserLoadFailed: "Sign-in succeeded, but your account could not be loaded. Please try again.";
115
+ readonly discardPendingSyncCancel: "Stay signed in";
116
+ readonly discardPendingSyncConfirm: "Sign out and discard";
117
+ readonly discardPendingSyncMessage: "{{count}} offline change(s) have not been synced yet. Signing out deletes the local data on this device, so those changes will be lost permanently.";
118
+ readonly discardPendingSyncTitle: "Unsynced offline changes";
119
+ readonly invalidCredentials: "Invalid credentials.";
120
+ readonly password: "Password";
121
+ readonly sessionExpired: "Your session has expired. Sign in again to continue.";
122
+ readonly signIn: "Sign in";
123
+ readonly signInSubtitle: "Enter your credentials to access your account.";
124
+ readonly signedInAs: "Signed in as";
125
+ readonly username: "Username";
126
+ };
127
+ readonly settings: {
128
+ readonly lockNavigationBar: "Lock navigation bar";
129
+ readonly noMaxWidth: "No max width";
130
+ readonly pageBodyMaxWidth: "Page content width";
131
+ readonly pageBodyMaxWidthLg: "Large";
132
+ readonly pageBodyMaxWidthMd: "Medium";
133
+ readonly pageBodyMaxWidthSm: "Small";
134
+ readonly pageBodyMaxWidthXl: "Extra large";
135
+ readonly pageBodyMaxWidthXs: "Extra small";
136
+ readonly title: "Application settings";
137
+ readonly userSettingsSavedSuccessfully: "User settings saved.";
138
+ };
139
+ };
140
+ export default en;
@@ -0,0 +1,140 @@
1
+ declare const hr: {
2
+ readonly common: {
3
+ readonly actions: "Akcije";
4
+ readonly ascending: "Uzlazno";
5
+ readonly ascendingSortDirection: "Uzlazni smjer sortiranja";
6
+ readonly back: "Natrag";
7
+ readonly bottomNavigation: "Navigacija pri dnu";
8
+ readonly cancel: "Odustani";
9
+ readonly clearAll: "Očisti sve";
10
+ readonly clearSearch: "Očisti pretragu";
11
+ readonly closeFilters: "Zatvori filtere";
12
+ readonly closeNavigation: "Zatvori navigaciju";
13
+ readonly collapse: "Sažmi";
14
+ readonly column: "Sortiraj po";
15
+ readonly create: "Kreiraj";
16
+ readonly dark: "Tamna";
17
+ readonly delete: "Obriši";
18
+ readonly descending: "Silazno";
19
+ readonly descendingSortDirection: "Silazni smjer sortiranja";
20
+ readonly direction: "Smjer sortiranja";
21
+ readonly discard: "Odbaci";
22
+ readonly done: "Gotovo";
23
+ readonly download: "Preuzmi";
24
+ readonly edit: "Uredi";
25
+ readonly expand: "Proširi";
26
+ readonly filters: "Filteri";
27
+ readonly language: "Jezik";
28
+ readonly light: "Svijetla";
29
+ readonly loading: "Učitavanje";
30
+ readonly logout: "Odjava";
31
+ readonly mainNavigation: "Glavna navigacija";
32
+ readonly month: "Mjesec";
33
+ readonly more: "Više";
34
+ readonly name: "Naziv";
35
+ readonly noRecordsFound: "Nema pronađenih zapisa.";
36
+ readonly openFilters: "Otvori filtere";
37
+ readonly profile: "Profil";
38
+ readonly settings: "Postavke";
39
+ readonly theme: "Tema";
40
+ readonly year: "Godina";
41
+ readonly no: "Ne";
42
+ readonly yes: "Da";
43
+ readonly save: "Spremi";
44
+ readonly search: "Pretraži";
45
+ readonly skipToMainContent: "Preskoči na glavni sadržaj";
46
+ };
47
+ readonly pwa: {
48
+ readonly newVersionAvailable: "Dostupna je nova verzija.";
49
+ readonly reload: "Osvježi";
50
+ };
51
+ readonly network: {
52
+ readonly actionQueued: "Spremljeno offline. Šalje se kad se veza vrati.";
53
+ readonly actionUnavailable: "Ova radnja nije dostupna dok ste izvan mreže.";
54
+ readonly commandId: "ID naredbe";
55
+ readonly connectingToLiveUpdates: "Povezivanje na promjene uživo...";
56
+ readonly createdAt: "Kreirano";
57
+ readonly dataUnavailable: "Ovi podaci nisu dostupni dok ste izvan mreže.";
58
+ readonly diagnostics: "Offline dijagnostika";
59
+ readonly errorMessage: "Poruka greške";
60
+ readonly failedLoadingData: "Neuspjelo učitavanje podataka.";
61
+ readonly httpMethod: "HTTP metoda";
62
+ readonly hydratingInBackground: "Lokalni podaci se sinkroniziraju u pozadini. Možete nastaviti koristiti aplikaciju.";
63
+ readonly lastHeartbeat: "Zadnji heartbeat";
64
+ readonly lastSyncFailure: "Zadnja greška";
65
+ readonly mutationQueuedOffline: "Spremljeno lokalno — čeka sinkronizaciju";
66
+ readonly offline: "Offline";
67
+ readonly offlineBanner: "Niste povezani s mrežom. Podaci možda nisu dostupni, a promjene su onemogućene.";
68
+ readonly offlineModeNotSupported: "Ova akcija još nije dostupna u offline načinu rada.";
69
+ readonly offlineQueuePending: "Offline — {{count}} promjene čekaju sinkronizaciju";
70
+ readonly online: "Online";
71
+ readonly owner: "Vlasnik";
72
+ readonly processedAt: "Obrađeno";
73
+ readonly queuePermanentlyFailed: "{{count}} promjena nije uspjelo sinkronizirati — potrebna provjera";
74
+ readonly queueSize: "Naredbe u redu";
75
+ readonly queueSynced: "Sinkronizirano";
76
+ readonly reconnecting: "Ponovno povezivanje";
77
+ readonly responseStatus: "Status odgovora";
78
+ readonly searchSyncCommands: "Pretraži naredbe sinkronizacije";
79
+ readonly status: "Status";
80
+ readonly syncCommands: "Naredbe sinkronizacije";
81
+ readonly syncFailures: "Greške sinkronizacije";
82
+ readonly syncIdle: "Miruje";
83
+ readonly syncInProgress: "U tijeku";
84
+ readonly syncStatus: "Status sinkronizacije";
85
+ readonly unavailable: "Nedostupno";
86
+ readonly url: "URL";
87
+ readonly youAreOffline: "Offline način rada";
88
+ };
89
+ readonly routing: {
90
+ readonly errorChunkMessage: "Ova stranica nije mogla biti učitana. To se može dogoditi nakon ažuriranja aplikacije — pokušajte osvježiti aplikaciju.";
91
+ readonly errorGenericMessage: "Došlo je do neočekivane greške prilikom učitavanja ove stranice.";
92
+ readonly errorOfflineMessage: "Izgleda da ste offline. Provjerite internetsku vezu i pokušajte ponovno.";
93
+ readonly errorRefresh: "Osvježi aplikaciju";
94
+ readonly errorRetry: "Pokušaj ponovno";
95
+ readonly errorTitle: "Nešto je pošlo po zlu";
96
+ readonly goHome: "Idi na pregled";
97
+ readonly notFoundMessage: "Tražena stranica ne postoji ili je premještena.";
98
+ readonly notFoundTitle: "Stranica nije pronađena";
99
+ readonly unauthorizedMessage: "Nemate dopuštenje za prikaz ove stranice.";
100
+ readonly unauthorizedTitle: "Pristup odbijen";
101
+ };
102
+ readonly unsavedChanges: {
103
+ readonly discardAndLeave: "Odbaci i napusti";
104
+ readonly message: "Imate nespremljene promjene. Odbaciti ih i napustiti stranicu?";
105
+ readonly savingMessage: "Promjene se spremaju. Pričekajte završetak spremanja prije napuštanja stranice.";
106
+ readonly savingTitle: "Spremanje promjena";
107
+ readonly stay: "Ostani";
108
+ readonly title: "Nespremljene promjene";
109
+ };
110
+ readonly validation: {
111
+ readonly thisFieldIsRequired: "Ovo polje je obavezno.";
112
+ };
113
+ readonly auth: {
114
+ readonly currentUserLoadFailed: "Prijava je uspjela, ali vaš račun nije moguće učitati. Pokušajte ponovno.";
115
+ readonly discardPendingSyncCancel: "Ostani prijavljen";
116
+ readonly discardPendingSyncConfirm: "Odjavi se i odbaci";
117
+ readonly discardPendingSyncMessage: "Broj nesinkroniziranih offline promjena: {{count}}. Odjavom se lokalni podaci na ovom uređaju brišu pa će te promjene biti trajno izgubljene.";
118
+ readonly discardPendingSyncTitle: "Nesinkronizirane offline promjene";
119
+ readonly invalidCredentials: "Neispravni podaci za prijavu.";
120
+ readonly password: "Lozinka";
121
+ readonly sessionExpired: "Vaša sesija je istekla. Prijavite se ponovno za nastavak.";
122
+ readonly signIn: "Prijava";
123
+ readonly signInSubtitle: "Unesite svoje podatke za pristup računu.";
124
+ readonly signedInAs: "Prijavljen kao";
125
+ readonly username: "Korisničko ime";
126
+ };
127
+ readonly settings: {
128
+ readonly lockNavigationBar: "Zaključaj navigacijsku traku";
129
+ readonly noMaxWidth: "Bez maksimalne širine";
130
+ readonly pageBodyMaxWidth: "Širina sadržaja stranice";
131
+ readonly pageBodyMaxWidthLg: "Široko";
132
+ readonly pageBodyMaxWidthMd: "Srednje";
133
+ readonly pageBodyMaxWidthSm: "Usko";
134
+ readonly pageBodyMaxWidthXl: "Vrlo široko";
135
+ readonly pageBodyMaxWidthXs: "Vrlo usko";
136
+ readonly title: "Postavke aplikacije";
137
+ readonly userSettingsSavedSuccessfully: "Postavke korisnika spremljene.";
138
+ };
139
+ };
140
+ export default hr;
@@ -0,0 +1,29 @@
1
+ import { QUERYENGINE_TRANSLATION_NAMESPACE } from './namespace';
2
+ import { default as QUERYENGINE_EN } from './queryengine.en';
3
+ import { DeepPartial, WidenLeaves } from '../toolkit/createNamespaceResources';
4
+ export { QUERYENGINE_TRANSLATION_NAMESPACE, type QueryEngineTranslationNamespace } from './namespace';
5
+ /** The canonical Query Engine resource shape. English is the key source of truth. */
6
+ export type QueryEngineResources = WidenLeaves<typeof QUERYENGINE_EN>;
7
+ /**
8
+ * A recursively partial resource, used for per-locale value overrides. Leaves
9
+ * are widened, so an override may supply any string for a shipped key.
10
+ */
11
+ export type QueryEngineResourcesOverride = DeepPartial<QueryEngineResources>;
12
+ /** Locales the QueryEngine namespace ships out of the box. */
13
+ export declare const QUERYENGINE_BASE_LOCALES: readonly ["en", "hr"];
14
+ export type QueryEngineBaseLocale = (typeof QUERYENGINE_BASE_LOCALES)[number];
15
+ export declare const queryEngineBaseResources: Record<QueryEngineBaseLocale, QueryEngineResources>;
16
+ export type CreateQueryEngineResourcesConfig<L extends string> = {
17
+ /** The full set of locales the consumer app wants to support. */
18
+ locales: readonly L[];
19
+ /** Base locale used to seed locales the namespace does not ship. Defaults to `"en"`. */
20
+ seedFrom?: QueryEngineBaseLocale;
21
+ /** Optional per-locale value overrides, deep-merged over the seeded base. */
22
+ overrides?: Partial<Record<L, QueryEngineResourcesOverride>>;
23
+ };
24
+ /**
25
+ * Builds a fully-populated QueryEngine resource map for every requested locale.
26
+ */
27
+ export declare function createQueryEngineResources<L extends string>(config: CreateQueryEngineResourcesConfig<L>): Record<L, {
28
+ [QUERYENGINE_TRANSLATION_NAMESPACE]: QueryEngineResources;
29
+ }>;
@@ -0,0 +1,2 @@
1
+ export declare const QUERYENGINE_TRANSLATION_NAMESPACE: "queryengine";
2
+ export type QueryEngineTranslationNamespace = typeof QUERYENGINE_TRANSLATION_NAMESPACE;
@@ -0,0 +1,38 @@
1
+ declare const en: {
2
+ readonly title: "Dev tools";
3
+ readonly subtitle: "Inspect backend query metadata and render filters from it.";
4
+ readonly availableEntities: "Available entities";
5
+ readonly backendConfiguration: "Backend configuration JSON";
6
+ readonly renderedFilterJson: "Rendered filter JSON";
7
+ readonly filters: "Filters";
8
+ readonly noFiltersAdded: "No filters added.";
9
+ readonly addFilter: "+ Add filter";
10
+ readonly relationType: "Relation";
11
+ readonly fromDate: "From";
12
+ readonly toDate: "To";
13
+ readonly rowsJson: "Rows (JSON)";
14
+ readonly rowsJsonPlaceholder: "[]";
15
+ readonly fieldsCountLabel: "fields";
16
+ readonly entityType: "Entity type";
17
+ readonly entityKey: "Entity key";
18
+ readonly operator: "Operator";
19
+ readonly value: "Value";
20
+ readonly noFilterableFields: "No filterable fields were returned for this entity.";
21
+ readonly ok: "OK";
22
+ readonly operators: {
23
+ readonly EQUALS: "Equals";
24
+ readonly NOT_EQUALS: "Not equals";
25
+ readonly CONTAINS: "Contains";
26
+ readonly STARTS_WITH: "Starts with";
27
+ readonly ENDS_WITH: "Ends with";
28
+ readonly IN: "In";
29
+ readonly GREATER_THAN: "Greater than";
30
+ readonly GREATER_OR_EQUAL: "Greater or equal";
31
+ readonly LESS_THAN: "Less than";
32
+ readonly LESS_OR_EQUAL: "Less or equal";
33
+ readonly DATE_RANGE: "Date range";
34
+ readonly IS_NULL: "Is null";
35
+ readonly IS_NOT_NULL: "Is not null";
36
+ };
37
+ };
38
+ export default en;
@@ -0,0 +1,38 @@
1
+ declare const hr: {
2
+ readonly title: "Dev alati";
3
+ readonly subtitle: "Pregledajte backend metapodatke upita i renderirajte filtere iz njih.";
4
+ readonly availableEntities: "Dostupni entiteti";
5
+ readonly backendConfiguration: "JSON konfiguracije iz backenda";
6
+ readonly renderedFilterJson: "Renderirani JSON filtera";
7
+ readonly filters: "Filteri";
8
+ readonly noFiltersAdded: "Nema dodanih filtera.";
9
+ readonly addFilter: "+ Dodaj filter";
10
+ readonly relationType: "Relacija";
11
+ readonly fromDate: "Od";
12
+ readonly toDate: "Do";
13
+ readonly rowsJson: "Retci (JSON)";
14
+ readonly rowsJsonPlaceholder: "[]";
15
+ readonly fieldsCountLabel: "polja";
16
+ readonly entityType: "Tip entiteta";
17
+ readonly entityKey: "Ključ entiteta";
18
+ readonly operator: "Operator";
19
+ readonly value: "Vrijednost";
20
+ readonly noFilterableFields: "Za ovaj entitet nije vraćeno nijedno filterabilno polje.";
21
+ readonly ok: "OK";
22
+ readonly operators: {
23
+ readonly EQUALS: "Jednako";
24
+ readonly NOT_EQUALS: "Nije jednako";
25
+ readonly CONTAINS: "Sadrži";
26
+ readonly STARTS_WITH: "Počinje s";
27
+ readonly ENDS_WITH: "Završava s";
28
+ readonly IN: "U skupu";
29
+ readonly GREATER_THAN: "Veće od";
30
+ readonly GREATER_OR_EQUAL: "Veće ili jednako";
31
+ readonly LESS_THAN: "Manje od";
32
+ readonly LESS_OR_EQUAL: "Manje ili jednako";
33
+ readonly DATE_RANGE: "Raspon datuma";
34
+ readonly IS_NULL: "Je prazno";
35
+ readonly IS_NOT_NULL: "Nije prazno";
36
+ };
37
+ };
38
+ export default hr;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * A recursively partial version of `T`. Consumers use it to supply per-locale
3
+ * value overrides without having to restate the full resource shape.
4
+ */
5
+ export type DeepPartial<T> = T extends (infer U)[] ? DeepPartial<U>[] : T extends object ? {
6
+ [K in keyof T]?: DeepPartial<T[K]>;
7
+ } : T;
8
+ /**
9
+ * Widens leaf string/number/boolean literals to their base primitive while
10
+ * preserving object structure. Used to type base resource maps whose non-seed
11
+ * locales share the shape but not the literal values of the canonical locale.
12
+ */
13
+ export type WidenLeaves<T> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : T extends (infer U)[] ? WidenLeaves<U>[] : T extends object ? {
14
+ [K in keyof T]: WidenLeaves<T[K]>;
15
+ } : T;
16
+ export type CreateNamespaceResourcesConfig<TShape extends object, B extends string, L extends string> = {
17
+ /** The i18next namespace the resulting resources are keyed under. */
18
+ namespace: string;
19
+ /** Locales the library ships out of the box, keyed by locale code. */
20
+ baseResources: Record<B, TShape>;
21
+ /** Base locale used to seed locales that the library does not ship. */
22
+ seedFrom: B;
23
+ /** The full set of locales the consumer app wants to support. */
24
+ locales: readonly L[];
25
+ /** Optional per-locale value overrides, deep-merged over the seeded base. */
26
+ overrides?: Partial<Record<L, DeepPartial<TShape>>>;
27
+ };
28
+ /**
29
+ * Builds a fully-populated i18next resource map for every requested locale.
30
+ *
31
+ * For each locale the merge chain is:
32
+ * 1. Start from the `seedFrom` base resource (guarantees every key exists).
33
+ * 2. If the locale is a shipped base locale, layer its shipped resource.
34
+ * 3. Layer the consumer's partial override, if any.
35
+ *
36
+ * The result is `Record<Locale, { [namespace]: TShape }>`, so no key is ever
37
+ * missing for any requested locale — including brand-new languages the library
38
+ * does not ship, which fall back to the seed until translated.
39
+ */
40
+ export declare function createNamespaceResources<TShape extends object, B extends string, L extends string, N extends string>(config: CreateNamespaceResourcesConfig<TShape, B, L> & {
41
+ namespace: N;
42
+ }): Record<L, Record<N, TShape>>;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Recursively merges `override` onto `base`, returning a new value.
3
+ *
4
+ * - Plain objects are merged key-by-key.
5
+ * - Any non-plain-object value (string, number, array, etc.) in `override`
6
+ * replaces the corresponding value in `base`.
7
+ * - `undefined` values in `override` are ignored, so partial overrides never
8
+ * erase base keys.
9
+ * - Inputs and nested values are cloned, so callers cannot mutate source
10
+ * resources through the returned object.
11
+ * - Prototype-mutating keys are ignored.
12
+ *
13
+ * The result always retains the full shape of `base`, which is what guarantees
14
+ * that a partial locale override can never introduce a missing translation key.
15
+ */
16
+ export declare function deepMerge<T>(base: T, override: unknown): T;
@@ -0,0 +1,3 @@
1
+ type OverridesByLocale = Readonly<Record<string, unknown>> | undefined;
2
+ export declare function validateResourceConfiguration(caller: string, locales: readonly string[], overrides?: OverridesByLocale): void;
3
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vireocodedev/localization",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Foundation i18n toolkit and shared platform translations for the vireocodedev starter product.",
5
5
  "type": "module",
6
6
  "sideEffects": false,