nextjs-cms 0.6.7 → 0.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/core/config/config-loader.d.ts +4 -10
  2. package/dist/core/config/config-loader.d.ts.map +1 -1
  3. package/dist/core/config/config-loader.js +17 -16
  4. package/dist/core/factories/FieldFactory.d.ts.map +1 -1
  5. package/dist/core/factories/FieldFactory.js +8 -0
  6. package/dist/core/fields/color.js +2 -2
  7. package/dist/core/fields/date.js +2 -2
  8. package/dist/core/fields/document.js +13 -13
  9. package/dist/core/fields/field.d.ts +5 -1
  10. package/dist/core/fields/field.d.ts.map +1 -1
  11. package/dist/core/fields/field.js +12 -0
  12. package/dist/core/fields/map.js +2 -2
  13. package/dist/core/fields/number.js +7 -7
  14. package/dist/core/fields/password.js +4 -4
  15. package/dist/core/fields/photo.js +17 -17
  16. package/dist/core/fields/select.d.ts +1 -1
  17. package/dist/core/fields/select.js +2 -2
  18. package/dist/core/fields/slug.js +3 -3
  19. package/dist/core/fields/text.js +3 -3
  20. package/dist/core/fields/video.js +12 -12
  21. package/dist/core/sections/category.d.ts +34 -34
  22. package/dist/core/sections/hasItems.d.ts +34 -34
  23. package/dist/core/sections/section.d.ts +17 -17
  24. package/dist/core/sections/simple.d.ts +6 -6
  25. package/dist/core/submit/submit.d.ts.map +1 -1
  26. package/dist/core/submit/submit.js +10 -0
  27. package/dist/translations/client.d.ts +5178 -1
  28. package/dist/translations/client.d.ts.map +1 -1
  29. package/dist/translations/client.js +29 -4
  30. package/dist/translations/dict-store.d.ts +5 -1
  31. package/dist/translations/dict-store.d.ts.map +1 -1
  32. package/dist/translations/dict-store.js +30 -3
  33. package/dist/translations/index.d.ts +1 -1
  34. package/dist/translations/index.js +1 -1
  35. package/dist/translations/server.d.ts +5171 -1
  36. package/dist/translations/server.d.ts.map +1 -1
  37. package/dist/translations/server.js +26 -4
  38. package/package.json +1 -1
  39. package/dist/core/helpers/i18n.d.ts +0 -2
  40. package/dist/core/helpers/i18n.d.ts.map +0 -1
  41. package/dist/core/helpers/i18n.js +0 -3
  42. package/dist/core/localization.d.ts +0 -40
  43. package/dist/core/localization.d.ts.map +0 -1
  44. package/dist/core/localization.js +0 -48
  45. package/dist/logging/audit.d.ts +0 -20
  46. package/dist/logging/audit.d.ts.map +0 -1
  47. package/dist/logging/audit.js +0 -48
  48. package/dist/translations/localized-string.d.ts +0 -17
  49. package/dist/translations/localized-string.d.ts.map +0 -1
  50. package/dist/translations/localized-string.js +0 -32
  51. package/dist/translations/use-project-translation.d.ts +0 -19
  52. package/dist/translations/use-project-translation.d.ts.map +0 -1
  53. package/dist/translations/use-project-translation.js +0 -25
  54. package/dist/validators/types.d.ts +0 -7
  55. package/dist/validators/types.d.ts.map +0 -1
  56. package/dist/validators/types.js +0 -0
@@ -1,7 +1,7 @@
1
1
  import * as z from 'zod';
2
2
  import type { LocalizedString } from '../../translations/localization.js';
3
- /** Locale codes for which we ship dictionaries. Config i18n.supportedLanguages keys must use these. */
4
- export declare const AVAILABLE_I18N_LOCALES: readonly ["en", "ar"];
3
+ /** Locale codes for which we ship dictionaries in core. */
4
+ export declare const AVAILABLE_I18N_LOCALES: readonly ["en"];
5
5
  export type AvailableLocale = (typeof AVAILABLE_I18N_LOCALES)[number];
6
6
  declare const cmsConfigSchema: z.ZodObject<{
7
7
  ui: z.ZodOptional<z.ZodObject<{
@@ -66,14 +66,8 @@ declare const cmsConfigSchema: z.ZodObject<{
66
66
  }, z.core.$strip>>>;
67
67
  }, z.core.$strip>>>;
68
68
  i18n: z.ZodOptional<z.ZodObject<{
69
- supportedLanguages: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
70
- en: "en";
71
- ar: "ar";
72
- }>, z.ZodRecord<z.ZodString, z.ZodString>>>;
73
- fallbackLanguage: z.ZodOptional<z.ZodEnum<{
74
- en: "en";
75
- ar: "ar";
76
- }>>;
69
+ supportedLanguages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>>;
70
+ fallbackLanguage: z.ZodOptional<z.ZodString>;
77
71
  }, z.core.$strip>>;
78
72
  dashboard: z.ZodOptional<z.ZodObject<{
79
73
  override: z.ZodOptional<z.ZodString>;
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../../src/core/config/config-loader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAGxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AAEzE,uGAAuG;AACvG,eAAO,MAAM,sBAAsB,uBAAwB,CAAA;AAE3D,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAA;AAGrE,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2OnB,CAAA;AAGF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAEvD,MAAM,WAAW,mBAAmB;IAChC,KAAK,CAAC,EAAE,eAAe,CAAA;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,iEAAiE;IACjE,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;CAC/C;AAGD,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE;QACA,KAAK,EAAE,MAAM,CAAA;QACb,YAAY,EAAE,MAAM,CAAA;QACpB,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,MAAM,CAAA;KACnB,CAAA;IACD,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,EAAE;QACN,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,OAAO,CAAA;QACf,QAAQ,EAAE;YACN,oBAAoB,EAAE,OAAO,CAAA;SAChC,CAAA;KACJ,CAAA;IACD,KAAK,EAAE;QACH,MAAM,EAAE;YACJ,IAAI,EAAE,MAAM,CAAA;YACZ,iBAAiB,EAAE,OAAO,CAAA;SAC7B,CAAA;QACD,MAAM,EAAE;YACJ,UAAU,EAAE;gBAAE,CAAC,EAAE,MAAM,CAAC;gBAAC,CAAC,EAAE,MAAM,CAAC;gBAAC,CAAC,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,MAAM,CAAA;aAAE,CAAA;YAC9D,SAAS,EAAE;gBACP,KAAK,EAAE,MAAM,CAAA;gBACb,MAAM,EAAE,MAAM,CAAA;gBACd,IAAI,EAAE,OAAO,CAAA;gBACb,OAAO,EAAE,MAAM,CAAA;aAClB,CAAA;YACD,SAAS,EAAE,OAAO,CAAA;SACrB,CAAA;KACJ,CAAA;IACD,gBAAgB,EAAE;QACd,OAAO,EAAE;YACL,OAAO,EAAE,OAAO,CAAA;YAChB,MAAM,EAAE,MAAM,CAAA;YACd,QAAQ,EAAE,MAAM,CAAA;YAChB,MAAM,EAAE;gBACJ,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,CAAA;gBAChD,OAAO,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,CAAA;aACpD,CAAA;SACJ,CAAA;KACJ,CAAA;IACD,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAC5B,IAAI,EAAE;QACF,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAA;QACrC,gBAAgB,EAAE,MAAM,CAAA;KAC3B,CAAA;IACD,SAAS,EAAE;QACP,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAC1B,CAAA;CACJ;AA6KD;;;;;;GAMG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAazE"}
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../../src/core/config/config-loader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAGxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AAEzE,2DAA2D;AAC3D,eAAO,MAAM,sBAAsB,iBAAkB,CAAA;AAErD,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAA;AAGrE,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8OnB,CAAA;AAGF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAEvD,MAAM,WAAW,mBAAmB;IAChC,KAAK,CAAC,EAAE,eAAe,CAAA;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,iEAAiE;IACjE,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;CAC/C;AAGD,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE;QACA,KAAK,EAAE,MAAM,CAAA;QACb,YAAY,EAAE,MAAM,CAAA;QACpB,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,MAAM,CAAA;KACnB,CAAA;IACD,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,EAAE;QACN,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,OAAO,CAAA;QACf,QAAQ,EAAE;YACN,oBAAoB,EAAE,OAAO,CAAA;SAChC,CAAA;KACJ,CAAA;IACD,KAAK,EAAE;QACH,MAAM,EAAE;YACJ,IAAI,EAAE,MAAM,CAAA;YACZ,iBAAiB,EAAE,OAAO,CAAA;SAC7B,CAAA;QACD,MAAM,EAAE;YACJ,UAAU,EAAE;gBAAE,CAAC,EAAE,MAAM,CAAC;gBAAC,CAAC,EAAE,MAAM,CAAC;gBAAC,CAAC,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,MAAM,CAAA;aAAE,CAAA;YAC9D,SAAS,EAAE;gBACP,KAAK,EAAE,MAAM,CAAA;gBACb,MAAM,EAAE,MAAM,CAAA;gBACd,IAAI,EAAE,OAAO,CAAA;gBACb,OAAO,EAAE,MAAM,CAAA;aAClB,CAAA;YACD,SAAS,EAAE,OAAO,CAAA;SACrB,CAAA;KACJ,CAAA;IACD,gBAAgB,EAAE;QACd,OAAO,EAAE;YACL,OAAO,EAAE,OAAO,CAAA;YAChB,MAAM,EAAE,MAAM,CAAA;YACd,QAAQ,EAAE,MAAM,CAAA;YAChB,MAAM,EAAE;gBACJ,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,CAAA;gBAChD,OAAO,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,CAAA;aACpD,CAAA;SACJ,CAAA;KACJ,CAAA;IACD,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAC5B,IAAI,EAAE;QACF,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAA;QACrC,gBAAgB,EAAE,MAAM,CAAA;KAC3B,CAAA;IACD,SAAS,EAAE;QACP,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAC1B,CAAA;CACJ;AA4KD;;;;;;GAMG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAazE"}
@@ -6,8 +6,8 @@ if (typeof window !== 'undefined') {
6
6
  import * as z from 'zod';
7
7
  import { loadConfigModule, getConfigImportVersion } from './loader.js';
8
8
  import { setConfigDicts } from '../../translations/dict-store.js';
9
- /** Locale codes for which we ship dictionaries. Config i18n.supportedLanguages keys must use these. */
10
- export const AVAILABLE_I18N_LOCALES = ['en', 'ar'];
9
+ /** Locale codes for which we ship dictionaries in core. */
10
+ export const AVAILABLE_I18N_LOCALES = ['en'];
11
11
  // 1. Define config schema
12
12
  const cmsConfigSchema = z.object({
13
13
  /**
@@ -191,28 +191,31 @@ const cmsConfigSchema = z.object({
191
191
  .optional(),
192
192
  /**
193
193
  * Interface (admin UI) i18n configuration.
194
- * Import dicts from `nextjs-cms/translations/dictionaries/en` etc. and pass
195
- * as supportedLanguages. Keys are locale codes; only those locales are offered.
194
+ * Import dictionaries (core provides `en`) and pass them as supportedLanguages.
195
+ * Keys are locale codes; only those locales are offered.
196
196
  */
197
197
  i18n: z
198
198
  .object({
199
199
  /**
200
200
  * Supported locales and their translation dictionaries.
201
- * Import from `nextjs-cms/translations/dictionaries/en` (and /ar) and pass
202
- * e.g. `{ en, ar }`. Keys = locale codes offered in the dropdown.
201
+ * Core ships `en`; additional locales should be installed and imported by the app.
202
+ * Example: `{ en, ar }`, `{ en, fr }`, etc. Keys = locale codes offered in the dropdown.
203
+ * Dictionaries can be partial overrides; they are merged with the built-in defaults.
204
+ * English is always included by core as the base fallback locale.
205
+ * At least one locale is required.
203
206
  */
204
207
  supportedLanguages: z
205
- .record(z.enum(AVAILABLE_I18N_LOCALES), z.record(z.string(), z.string()))
206
- .optional()
207
- .refine((v) => v === undefined || Object.keys(v).length >= 1, {
208
+ .record(z.string(), z.record(z.string(), z.string()))
209
+ .refine((v) => Object.keys(v).length > 0, {
208
210
  message: 'i18n.supportedLanguages must have at least one locale',
209
- }),
211
+ })
212
+ .optional(),
210
213
  /**
211
214
  * Fallback locale when the user's stored locale is not in supportedLanguages,
212
215
  * or when no session exists (e.g. login page).
213
216
  * @default 'en'
214
217
  */
215
- fallbackLanguage: z.enum(AVAILABLE_I18N_LOCALES).optional(),
218
+ fallbackLanguage: z.string().optional(),
216
219
  })
217
220
  .optional(),
218
221
  /**
@@ -231,21 +234,19 @@ const cmsConfigSchema = z.object({
231
234
  .optional(),
232
235
  });
233
236
  function normalizeI18n(userConfig) {
234
- const available = new Set(AVAILABLE_I18N_LOCALES);
235
237
  const fallback = userConfig.i18n?.fallbackLanguage ?? 'en';
236
238
  const record = userConfig.i18n?.supportedLanguages;
237
239
  let supported;
238
240
  if (record && Object.keys(record).length >= 1) {
239
- supported = Object.keys(record).filter((code) => available.has(code));
240
- if (supported.length === 0)
241
- supported = ['en'];
241
+ supported = ['en', ...Object.keys(record).filter((locale) => locale !== 'en')];
242
242
  setConfigDicts(record);
243
243
  }
244
244
  else {
245
245
  supported = ['en'];
246
+ setConfigDicts({});
246
247
  }
247
248
  const supportedSet = new Set(supported);
248
- const effectiveFallback = supportedSet.has(fallback) ? fallback : supported[0];
249
+ const effectiveFallback = supportedSet.has(fallback) ? fallback : 'en';
249
250
  return {
250
251
  supportedLanguages: supported,
251
252
  fallbackLanguage: effectiveFallback,
@@ -1 +1 @@
1
- {"version":3,"file":"FieldFactory.d.ts","sourceRoot":"","sources":["../../../src/core/factories/FieldFactory.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAGnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAQlD,KAAK,eAAe,GACd;IACI,IAAI,EAAE,KAAK,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,KAAK,CAAA;CACjB,GACD;IACI,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;CAC1B,CAAA;AAEP,qBAAa,YAAY;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,MAAM,CAAyC;IACvD,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,aAAa,CAAa;IAClC,SAAS,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;IAC9B,SAAS,CAAC,WAAW,EAAE,MAAM,CAAA;IAC7B,OAAO,CAAC,YAAY,CAA4B;IAGhD;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAY;IAEjD;;OAEG;gBACS,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,eAAe;IASnE;;OAEG;IACU,UAAU;YAUT,aAAa;YASb,qBAAqB;IAwFnC;;;;OAIG;YACW,qBAAqB;IAuCnC;;;;OAIG;YACW,cAAc;IAuB5B;;;;;OAKG;YACW,YAAY;IAiB1B,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;IACU,cAAc;IAqB3B;;;OAGG;IACH,OAAO,CAAC,UAAU;IA4ElB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,iBAAiB;IAOzB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAqB1B;;;OAGG;IACU,gBAAgB;;;;;;;;;;;;;;;IAmF7B,IAAI,WAAW,IAAI,OAAO,GAAG,SAAS,CAErC;IACD,IAAI,YAAY,IAAI,MAAM,CAEzB;IACD,IAAI,KAAK,IAAI,OAAO,CAEnB;CACJ"}
1
+ {"version":3,"file":"FieldFactory.d.ts","sourceRoot":"","sources":["../../../src/core/factories/FieldFactory.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAGnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAQlD,KAAK,eAAe,GACd;IACI,IAAI,EAAE,KAAK,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,KAAK,CAAA;CACjB,GACD;IACI,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;CAC1B,CAAA;AAEP,qBAAa,YAAY;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,MAAM,CAAyC;IACvD,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,aAAa,CAAa;IAClC,SAAS,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;IAC9B,SAAS,CAAC,WAAW,EAAE,MAAM,CAAA;IAC7B,OAAO,CAAC,YAAY,CAA4B;IAGhD;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAY;IAEjD;;OAEG;gBACS,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,eAAe;IASnE;;OAEG;IACU,UAAU;YAUT,aAAa;YASb,qBAAqB;IAwFnC;;;;OAIG;YACW,qBAAqB;IAoDnC;;;;OAIG;YACW,cAAc;IAuB5B;;;;;OAKG;YACW,YAAY;IAiB1B,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;IACU,cAAc;IAqB3B;;;OAGG;IACH,OAAO,CAAC,UAAU;IA4ElB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,iBAAiB;IAOzB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAqB1B;;;OAGG;IACU,gBAAgB;;;;;;;;;;;;;;;IAmF7B,IAAI,WAAW,IAAI,OAAO,GAAG,SAAS,CAErC;IACD,IAAI,YAAY,IAAI,MAAM,CAEzB;IACD,IAAI,KAAK,IAAI,OAAO,CAEnB;CACJ"}
@@ -158,6 +158,14 @@ export class FieldFactory {
158
158
  * Build the fields from the field configs
159
159
  */
160
160
  this._sectionInfo.buildFields();
161
+ /**
162
+ * Set locale for fields so validation/build errors are localized
163
+ */
164
+ const cmsConfig = await getCMSConfig();
165
+ const locale = resolveLocale(this.session.user.locale, cmsConfig.i18n.supportedLanguages, cmsConfig.i18n.fallbackLanguage);
166
+ for (const field of this._sectionInfo.fields) {
167
+ field.setLocale(locale, cmsConfig.i18n.fallbackLanguage);
168
+ }
161
169
  }
162
170
  else {
163
171
  const errorMessage = 'Section config must have a build() method. Use helper functions like simpleSection(), hasItemsSection(), categorySection() to create section configs.';
@@ -36,7 +36,7 @@ export class ColorField extends Field {
36
36
  */
37
37
  if (this.required) {
38
38
  if (!this.value || this.value.trim().length === 0) {
39
- throw new Error(getString('fieldIsRequired', 'en', { field: String(this.label) }));
39
+ throw new Error(getString('fieldIsRequired', this.locale, { field: this.getLocalizedLabel() }));
40
40
  }
41
41
  }
42
42
  }
@@ -54,7 +54,7 @@ export class ColorField extends Field {
54
54
  * Check if the value represents a color
55
55
  */
56
56
  if (this.value && !/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(this.value)) {
57
- throw new Error(getString('invalidColorPleaseProvideValidHex', 'en'));
57
+ throw new Error(getString('invalidColorPleaseProvideValidHex', this.locale));
58
58
  }
59
59
  }
60
60
  }
@@ -78,7 +78,7 @@ export class DateField extends Field {
78
78
  if (this.required) {
79
79
  const date = this.parseDate();
80
80
  if (!date) {
81
- throw new Error(getString('fieldIsRequired', 'en', { field: String(this.label) }));
81
+ throw new Error(getString('fieldIsRequired', this.locale, { field: this.getLocalizedLabel() }));
82
82
  }
83
83
  }
84
84
  }
@@ -98,7 +98,7 @@ export class DateField extends Field {
98
98
  this.value = date.toISOString();
99
99
  }
100
100
  else if (this.required) {
101
- throw new Error(getString('invalidDatePleaseProvideValid', 'en', { field: String(this.label) }));
101
+ throw new Error(getString('invalidDatePleaseProvideValid', this.locale, { field: this.getLocalizedLabel() }));
102
102
  }
103
103
  // If not required and no valid date, keep value as-is (null/undefined)
104
104
  }
@@ -81,7 +81,7 @@ export class DocumentField extends FileField {
81
81
  case 'csv':
82
82
  return 'text/csv';
83
83
  default:
84
- throw new Error(getString('invalidFileExtension', 'en', { extensions: e }));
84
+ throw new Error(getString('invalidFileExtension', this.locale, { extensions: e }));
85
85
  }
86
86
  });
87
87
  /**
@@ -99,13 +99,13 @@ export class DocumentField extends FileField {
99
99
  }
100
100
  async readChunkFromFile({ arrayBuffer, length, startPosition = 0, }) {
101
101
  if (!arrayBuffer) {
102
- throw new Error(getString('errorReadingFile', 'en'));
102
+ throw new Error(getString('errorReadingFile', this.locale));
103
103
  }
104
104
  const buffer = new Uint8Array(arrayBuffer);
105
105
  const start = Math.max(0, startPosition);
106
106
  const end = Math.min(start + length, buffer.length);
107
107
  if (start >= end) {
108
- throw new Error(getString('errorReadingFile', 'en'));
108
+ throw new Error(getString('errorReadingFile', this.locale));
109
109
  }
110
110
  return buffer.subarray(start, end);
111
111
  }
@@ -114,10 +114,10 @@ export class DocumentField extends FileField {
114
114
  */
115
115
  async writeToFile() {
116
116
  if (!this._folder) {
117
- throw new Error(getString('folderNotSet', 'en', { field: String(this.label) }));
117
+ throw new Error(getString('folderNotSet', this.locale, { field: this.getLocalizedLabel() }));
118
118
  }
119
119
  if (!this._buffer) {
120
- throw new Error(getString('bufferNotSet', 'en', { field: String(this.label) }));
120
+ throw new Error(getString('bufferNotSet', this.locale, { field: this.getLocalizedLabel() }));
121
121
  }
122
122
  try {
123
123
  /**
@@ -134,7 +134,7 @@ export class DocumentField extends FileField {
134
134
  await fs.promises.writeFile(path.join(uploadsFolder, '.documents', this._folder, this.value), this._buffer);
135
135
  }
136
136
  catch (error) {
137
- throw new Error(getString('documentWriteError', 'en', { field: String(this.label) }) + ` ${error.message}`);
137
+ throw new Error(getString('documentWriteError', this.locale, { field: this.getLocalizedLabel() }) + ` ${error.message}`);
138
138
  }
139
139
  }
140
140
  async postSubmit(folder) {
@@ -147,7 +147,7 @@ export class DocumentField extends FileField {
147
147
  if (!this._file)
148
148
  return;
149
149
  if (!this._folder) {
150
- throw new Error(getString('folderNotSet', 'en', { field: String(this.label) }));
150
+ throw new Error(getString('folderNotSet', this.locale, { field: this.getLocalizedLabel() }));
151
151
  }
152
152
  try {
153
153
  const uploadsFolder = (await getCMSConfig()).media.upload.path;
@@ -155,7 +155,7 @@ export class DocumentField extends FileField {
155
155
  await fs.promises.unlink(pathToFile);
156
156
  }
157
157
  catch (error) {
158
- throw new Error(getString('documentDeleteError', 'en', { field: String(this.label) }));
158
+ throw new Error(getString('documentDeleteError', this.locale, { field: this.getLocalizedLabel() }));
159
159
  }
160
160
  }
161
161
  async cleanupReplacedFile(previousValue, sectionName) {
@@ -195,7 +195,7 @@ export class DocumentField extends FileField {
195
195
  if (!this.required)
196
196
  return;
197
197
  if (!this._file || !this._file?.type || !this._file?.name || !this._file?.size) {
198
- throw new Error(getString('fieldIsRequired', 'en', { field: String(this.label) }));
198
+ throw new Error(getString('fieldIsRequired', this.locale, { field: this.getLocalizedLabel() }));
199
199
  }
200
200
  }
201
201
  /**
@@ -210,14 +210,14 @@ export class DocumentField extends FileField {
210
210
  const arrayBuffer = await this._file.arrayBuffer();
211
211
  this._buffer = Buffer.from(arrayBuffer);
212
212
  if (!this._buffer.length) {
213
- throw new Error(getString('fieldIsRequired', 'en', { field: String(this.label) }));
213
+ throw new Error(getString('fieldIsRequired', this.locale, { field: this.getLocalizedLabel() }));
214
214
  }
215
215
  /**
216
216
  * Check extension
217
217
  */
218
218
  const ext = this._file.name.split('.').pop();
219
219
  if (!ext || !this.extensions.includes(ext)) {
220
- throw new Error(getString('invalidFileTypeOrExtension', 'en', { field: String(this.label), extensions: this.extensions.join(', ') }));
220
+ throw new Error(getString('invalidFileTypeOrExtension', this.locale, { field: this.getLocalizedLabel(), extensions: this.extensions.join(', ') }));
221
221
  }
222
222
  /**
223
223
  * Read the first 4100 bytes of the file
@@ -232,14 +232,14 @@ export class DocumentField extends FileField {
232
232
  * If the file type is invalid, return an error
233
233
  */
234
234
  if (!fileType) {
235
- throw new Error(getString('invalidDocumentFileType', 'en', { field: String(this.label) }));
235
+ throw new Error(getString('invalidDocumentFileType', this.locale, { field: this.getLocalizedLabel() }));
236
236
  }
237
237
  /**
238
238
  * Don't just trust the file extension
239
239
  * Check the `fileType.ext` against the allowed extensions
240
240
  */
241
241
  if (!fileType.ext || !this.extensions.includes(fileType.ext)) {
242
- throw new Error(getString('invalidFileTypeOrExtension', 'en', { field: String(this.label), extensions: this.extensions.join(', ') }));
242
+ throw new Error(getString('invalidFileTypeOrExtension', this.locale, { field: this.getLocalizedLabel(), extensions: this.extensions.join(', ') }));
243
243
  }
244
244
  /**
245
245
  * Generate a random name for the file
@@ -1,6 +1,6 @@
1
1
  import { entityKind } from '../helpers/index.js';
2
2
  import type { ConditionalField, ConditionalRule, FieldType } from '../types/index.js';
3
- import type { LocalizedString } from '../../translations/localization.js';
3
+ import { type LocalizedString } from '../../translations/localization.js';
4
4
  import * as z from 'zod';
5
5
  /**
6
6
  * The Field class is used in the submit class to handle submission of the field
@@ -19,6 +19,8 @@ export declare abstract class Field<TType extends FieldType = FieldType, TExtraF
19
19
  readonly order: number | undefined;
20
20
  readonly groupId: number | undefined;
21
21
  readonly conditionalRules: ConditionalRule[] | undefined;
22
+ protected locale: string;
23
+ protected fallbackLocale: string;
22
24
  /**
23
25
  * adminGenerated is used to determine if the field is generated by the admin or not.
24
26
  * If set to false, the field will not be included in the form.
@@ -49,6 +51,8 @@ export declare abstract class Field<TType extends FieldType = FieldType, TExtraF
49
51
  constructor(config: BaseFieldConfig<TExtraFieldConfig>, fieldType: TType);
50
52
  abstract checkRequired(): void;
51
53
  setValue(value: any): void;
54
+ setLocale(locale: string, fallbackLocale?: string): void;
55
+ protected getLocalizedLabel(): string;
52
56
  /**
53
57
  * Perform any action after submitting the form
54
58
  */
@@ -1 +1 @@
1
- {"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../../../src/core/fields/field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AACrF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB;;;GAGG;AACH,8BAAsB,KAAK,CAEvB,KAAK,SAAS,SAAS,GAAG,SAAS,EACnC,iBAAiB,SAAS,MAAM,GAAG,MAAM,CAC3C,YAAW,QAAQ,CAAC,KAAK,CAAC;IAExB,MAAM,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,EAAE,MAAM,CAAU;IAC9C,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAA;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,gBAAgB,EAAE,eAAe,EAAE,GAAG,SAAS,CAAA;IAExD;;;;OAIG;IACH,cAAc,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,UAAU,CAAA;IAE1C;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE;QACrB,KAAK,EAAE,MAAM,CAAA;QACb,cAAc,EAAE,MAAM,CAAA;QACtB,gBAAgB,EAAE,MAAM,CAAA;KAC3B,CAAA;IAED;;OAEG;IACI,iBAAiB,EAAE,gBAAgB,EAAE,CAAK;IACnC,KAAK,EAAE,GAAG,CAAA;gBAKZ,MAAM,EAAE,eAAe,CAAC,iBAAiB,CAAC,EAAE,SAAS,EAAE,KAAK;IAaxE,QAAQ,CAAC,aAAa,IAAI,IAAI;IAE9B,QAAQ,CAAC,KAAK,EAAE,GAAG;IAInB;;OAEG;IACU,UAAU,CAAC,QAAQ,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhD;;OAEG;IACH,QAAQ,CAAC,QAAQ,IAAI,GAAG;IAExB,cAAc,IAAI,GAAG;IAIrB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,QAAQ,CAAC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAE9C;;;OAGG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAY1C,eAAe;;;;;;;;;;IAef,kBAAkB,IAAI,OAAO;IAI7B;;OAEG;IACH,aAAa,IAAI,OAAO;CAa3B;AAED,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAA;AAGpE,eAAO,MAAM,qBAAqB,+CAA8B,CAAA;AAEhE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;;;IAW9B;;;;OAIG;;IAEH;;;;OAIG;;kBAEL,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,eAAe,CAAC,iBAAiB,SAAS,MAAM,GAAG,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,GAC1G,iBAAiB,CAAA;AAErB;;GAEG;AACH,UAAU,QAAQ,CAAC,KAAK,SAAS,SAAS,CAAE,SAAQ,eAAe,CAAC,EAAE,CAAC;IACnE,IAAI,EAAE,KAAK,CAAA;CACd"}
1
+ {"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../../../src/core/fields/field.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { entityKind } from '../helpers/index.js';
2
+ import { resolveLocalizedString } from '../../translations/localization.js';
2
3
  import * as z from 'zod';
3
4
  /**
4
5
  * The Field class is used in the submit class to handle submission of the field
@@ -17,6 +18,8 @@ export class Field {
17
18
  order;
18
19
  groupId;
19
20
  conditionalRules;
21
+ locale;
22
+ fallbackLocale;
20
23
  /**
21
24
  * adminGenerated is used to determine if the field is generated by the admin or not.
22
25
  * If set to false, the field will not be included in the form.
@@ -53,10 +56,19 @@ export class Field {
53
56
  this.conditionalRules = config.conditionalRules;
54
57
  this.adminGenerated = config.adminGenerated ?? true;
55
58
  this.value = undefined;
59
+ this.locale = 'en';
60
+ this.fallbackLocale = 'en';
56
61
  }
57
62
  setValue(value) {
58
63
  this.value = value;
59
64
  }
65
+ setLocale(locale, fallbackLocale = 'en') {
66
+ this.locale = locale;
67
+ this.fallbackLocale = fallbackLocale;
68
+ }
69
+ getLocalizedLabel() {
70
+ return resolveLocalizedString(this.label, this.locale, this.fallbackLocale);
71
+ }
60
72
  /**
61
73
  * Perform any action after submitting the form
62
74
  */
@@ -97,7 +97,7 @@ export class MapField extends Field {
97
97
  */
98
98
  if (this.required) {
99
99
  if (!this.value) {
100
- throw new Error(getString('fieldIsRequired', 'en', { field: String(this.label) }));
100
+ throw new Error(getString('fieldIsRequired', this.locale, { field: this.getLocalizedLabel() }));
101
101
  }
102
102
  }
103
103
  }
@@ -115,7 +115,7 @@ export class MapField extends Field {
115
115
  * Check if the value if well formatted as `lat,lng` string
116
116
  */
117
117
  if (!/^-?\d+(\.\d+)?,-?\d+(\.\d+)?$/.test(`${this.value?.lat},${this.value?.lng}`)) {
118
- throw new Error(getString('invalidMapFormat', 'en'));
118
+ throw new Error(getString('invalidMapFormat', this.locale));
119
119
  }
120
120
  }
121
121
  }
@@ -76,10 +76,10 @@ export class NumberField extends Field {
76
76
  * Basic structural logic checks
77
77
  */
78
78
  if (this.minValue !== undefined && this.maxValue !== undefined && this.minValue > this.maxValue) {
79
- throw new Error(getString('fieldMinMaxMismatch', 'en', { field: String(this.label) }));
79
+ throw new Error(getString('fieldMinMaxMismatch', this.locale, { field: this.getLocalizedLabel() }));
80
80
  }
81
81
  if (this.minLength !== undefined && this.maxLength !== undefined && this.minLength > this.maxLength) {
82
- throw new Error(getString('fieldLengthMismatch', 'en', { field: String(this.label) }));
82
+ throw new Error(getString('fieldLengthMismatch', this.locale, { field: this.getLocalizedLabel() }));
83
83
  }
84
84
  /**
85
85
  * Attempt to coerce the value
@@ -143,7 +143,7 @@ export class NumberField extends Field {
143
143
  */
144
144
  if (this.required) {
145
145
  if (this.value === undefined || this.value === null || Number.isNaN(this.value)) {
146
- throw new Error(getString('fieldIsRequired', 'en', { field: String(this.label) }));
146
+ throw new Error(getString('fieldIsRequired', this.locale, { field: this.getLocalizedLabel() }));
147
147
  }
148
148
  }
149
149
  }
@@ -164,7 +164,7 @@ export class NumberField extends Field {
164
164
  */
165
165
  if (this.minValue) {
166
166
  if (this.minValue > this.value) {
167
- throw new Error(getString('fieldMinValueError', 'en', { field: String(this.label), min: this.minValue }));
167
+ throw new Error(getString('fieldMinValueError', this.locale, { field: this.getLocalizedLabel(), min: this.minValue }));
168
168
  }
169
169
  }
170
170
  /**
@@ -172,7 +172,7 @@ export class NumberField extends Field {
172
172
  */
173
173
  if (this.maxValue) {
174
174
  if (this.maxValue < this.value) {
175
- throw new Error(getString('fieldMaxValueError', 'en', { field: String(this.label), max: this.maxValue }));
175
+ throw new Error(getString('fieldMaxValueError', this.locale, { field: this.getLocalizedLabel(), max: this.maxValue }));
176
176
  }
177
177
  }
178
178
  /**
@@ -180,7 +180,7 @@ export class NumberField extends Field {
180
180
  */
181
181
  if (this.minLength) {
182
182
  if (this.minLength > this.value.toString().length) {
183
- throw new Error(getString('numberMinLength', 'en', { min: this.minLength }));
183
+ throw new Error(getString('numberMinLength', this.locale, { min: this.minLength }));
184
184
  }
185
185
  }
186
186
  /**
@@ -188,7 +188,7 @@ export class NumberField extends Field {
188
188
  */
189
189
  if (this.maxLength) {
190
190
  if (this.maxLength < this.value.toString().length) {
191
- throw new Error(getString('numberMaxLength', 'en', { max: this.maxLength }));
191
+ throw new Error(getString('numberMaxLength', this.locale, { max: this.maxLength }));
192
192
  }
193
193
  }
194
194
  }
@@ -56,7 +56,7 @@ export class PasswordField extends Field {
56
56
  */
57
57
  if (this.adminGenerated && this.required) {
58
58
  if (!this.value || this.value.trim().length === 0) {
59
- throw new Error(getString('fieldIsRequired', 'en', { field: String(this.label) }));
59
+ throw new Error(getString('fieldIsRequired', this.locale, { field: this.getLocalizedLabel() }));
60
60
  }
61
61
  }
62
62
  }
@@ -75,7 +75,7 @@ export class PasswordField extends Field {
75
75
  /**
76
76
  * Display the provided message
77
77
  */
78
- throw new Error(`${String(this.label)}: ${this.validation.message}`);
78
+ throw new Error(`${this.getLocalizedLabel()}: ${this.validation.message}`);
79
79
  }
80
80
  }
81
81
  /**
@@ -83,7 +83,7 @@ export class PasswordField extends Field {
83
83
  */
84
84
  if (this.minLength) {
85
85
  if (this.minLength > this.value.length) {
86
- throw new Error(getString('minLength', 'en', { min: this.minLength }));
86
+ throw new Error(getString('minLength', this.locale, { min: this.minLength }));
87
87
  }
88
88
  }
89
89
  /**
@@ -91,7 +91,7 @@ export class PasswordField extends Field {
91
91
  */
92
92
  if (this.maxLength) {
93
93
  if (this.maxLength < this.value.length) {
94
- throw new Error(getString('maxLength', 'en', { max: this.maxLength }));
94
+ throw new Error(getString('maxLength', this.locale, { max: this.maxLength }));
95
95
  }
96
96
  }
97
97
  /**
@@ -131,7 +131,7 @@ export class PhotoField extends FileField {
131
131
  return 'image/png';
132
132
  if (e === 'webp')
133
133
  return 'image/webp';
134
- throw new Error(getString('invalidImageExtension', 'en', { extensions: e }));
134
+ throw new Error(getString('invalidImageExtension', this.locale, { extensions: e }));
135
135
  });
136
136
  /**
137
137
  * Set the allowed extensions, add jpg if jpeg is present
@@ -166,7 +166,7 @@ export class PhotoField extends FileField {
166
166
  }
167
167
  exportForClient() {
168
168
  if (this._thumbnail === undefined) {
169
- throw new Error(getString('photoFieldBuildRequired', 'en'));
169
+ throw new Error(getString('photoFieldBuildRequired', this.locale));
170
170
  }
171
171
  return {
172
172
  ...super.exportForClient(),
@@ -184,10 +184,10 @@ export class PhotoField extends FileField {
184
184
  */
185
185
  async writeToFile() {
186
186
  if (!this._folder) {
187
- throw new Error(getString('folderNotSet', 'en', { field: String(this.label) }));
187
+ throw new Error(getString('folderNotSet', this.locale, { field: this.getLocalizedLabel() }));
188
188
  }
189
189
  if (!this._sharpImage) {
190
- throw new Error(getString('imageNotSet', 'en', { field: String(this.label) }));
190
+ throw new Error(getString('imageNotSet', this.locale, { field: this.getLocalizedLabel() }));
191
191
  }
192
192
  try {
193
193
  /**
@@ -259,7 +259,7 @@ export class PhotoField extends FileField {
259
259
  .toFile(path.join(uploadsFolder, '.thumbs', this._folder, this.value));
260
260
  }
261
261
  catch (error) {
262
- throw new Error(getString('fileWriteError', 'en', { field: String(this.label) }) + ` ${error.message}`);
262
+ throw new Error(getString('fileWriteError', this.locale, { field: this.getLocalizedLabel() }) + ` ${error.message}`);
263
263
  }
264
264
  }
265
265
  async postSubmit(folder) {
@@ -272,7 +272,7 @@ export class PhotoField extends FileField {
272
272
  if (!this._file)
273
273
  return;
274
274
  if (!this._folder) {
275
- throw new Error(getString('folderNotSet', 'en', { field: String(this.label) }));
275
+ throw new Error(getString('folderNotSet', this.locale, { field: this.getLocalizedLabel() }));
276
276
  }
277
277
  try {
278
278
  const uploadsFolder = (await getCMSConfig()).media.upload.path;
@@ -280,7 +280,7 @@ export class PhotoField extends FileField {
280
280
  await fs.promises.unlink(pathToFile);
281
281
  }
282
282
  catch (error) {
283
- throw new Error(getString('fileDeleteError', 'en', { field: String(this.label) }));
283
+ throw new Error(getString('fileDeleteError', this.locale, { field: this.getLocalizedLabel() }));
284
284
  }
285
285
  }
286
286
  async cleanupReplacedFile(previousValue, sectionName) {
@@ -319,7 +319,7 @@ export class PhotoField extends FileField {
319
319
  */
320
320
  if (this.required) {
321
321
  if (!this._file?.type || !this._file?.name || !this._file?.size) {
322
- throw new Error(getString('fieldIsRequired', 'en', { field: String(this.label) }));
322
+ throw new Error(getString('fieldIsRequired', this.locale, { field: this.getLocalizedLabel() }));
323
323
  }
324
324
  }
325
325
  }
@@ -340,7 +340,7 @@ export class PhotoField extends FileField {
340
340
  if (ext === 'jpg')
341
341
  ext = 'jpeg';
342
342
  if (!ext || !this.extensions.includes(ext)) {
343
- throw new Error(getString('invalidFileTypeOrExtension', 'en', { field: String(this.label), extensions: this.extensions.join(', ') }));
343
+ throw new Error(getString('invalidFileTypeOrExtension', this.locale, { field: this.getLocalizedLabel(), extensions: this.extensions.join(', ') }));
344
344
  }
345
345
  /**
346
346
  * Construct the image
@@ -351,7 +351,7 @@ export class PhotoField extends FileField {
351
351
  * Check mime type
352
352
  */
353
353
  if (!this.mimeType.includes(this._file.type)) {
354
- throw new Error(getString('invalidFileTypeOrExtension', 'en', { field: String(this.label), extensions: this.extensions.join(', ') }));
354
+ throw new Error(getString('invalidFileTypeOrExtension', this.locale, { field: this.getLocalizedLabel(), extensions: this.extensions.join(', ') }));
355
355
  }
356
356
  /**
357
357
  * Check actual mime type
@@ -361,7 +361,7 @@ export class PhotoField extends FileField {
361
361
  if (!actualMimeType ||
362
362
  !this.extensions.includes(actualMimeType.ext) ||
363
363
  !this.mimeType.includes(actualMimeType.mime)) {
364
- throw new Error(getString('invalidFileTypeOrExtension', 'en', { field: String(this.label), extensions: this.extensions.join(', ') }));
364
+ throw new Error(getString('invalidFileTypeOrExtension', this.locale, { field: this.getLocalizedLabel(), extensions: this.extensions.join(', ') }));
365
365
  }
366
366
  /**
367
367
  * Disable caching for the image to avoid unlink issues
@@ -382,20 +382,20 @@ export class PhotoField extends FileField {
382
382
  */
383
383
  const fileSize = buffer.length;
384
384
  if (!fileSize || !metadata.size) {
385
- throw new Error(getString('fieldIsRequired', 'en', { field: String(this.label) }));
385
+ throw new Error(getString('fieldIsRequired', this.locale, { field: this.getLocalizedLabel() }));
386
386
  }
387
387
  /**
388
388
  * Check the file size
389
389
  */
390
390
  if (fileSize > this.maxFileSize.size * (this.maxFileSize.unit === 'kb' ? 1024 : 1024 * 1024)) {
391
- throw new Error(getString('fileSizeExceedsMax', 'en', { field: String(this.label), actual: humanReadableFileSize(fileSize), max: `${this.maxFileSize.size} ${this.maxFileSize.unit}` }));
391
+ throw new Error(getString('fileSizeExceedsMax', this.locale, { field: this.getLocalizedLabel(), actual: humanReadableFileSize(fileSize), max: `${this.maxFileSize.size} ${this.maxFileSize.unit}` }));
392
392
  }
393
393
  /**
394
394
  * Don't just trust the file extension
395
395
  * Check the format
396
396
  */
397
397
  if (!metadata.format || !this.extensions.includes(metadata.format)) {
398
- throw new Error(getString('invalidFileTypeOrExtension', 'en', { field: String(this.label), extensions: this.extensions.join(', ') }));
398
+ throw new Error(getString('invalidFileTypeOrExtension', this.locale, { field: this.getLocalizedLabel(), extensions: this.extensions.join(', ') }));
399
399
  }
400
400
  /**
401
401
  * Check stat
@@ -404,7 +404,7 @@ export class PhotoField extends FileField {
404
404
  await image.stats();
405
405
  }
406
406
  catch (error) {
407
- throw new Error(getString('fileCorrupted', 'en'));
407
+ throw new Error(getString('fileCorrupted', this.locale));
408
408
  }
409
409
  /**
410
410
  * Convert the image to webp
@@ -413,7 +413,7 @@ export class PhotoField extends FileField {
413
413
  image.toFormat('webp').withExif({});
414
414
  }
415
415
  catch (error) {
416
- throw new Error(getString('fileCorrupted', 'en'));
416
+ throw new Error(getString('fileCorrupted', this.locale));
417
417
  }
418
418
  /**
419
419
  * Check the size
@@ -430,7 +430,7 @@ export class PhotoField extends FileField {
430
430
  * Check if the size matches the required size
431
431
  */
432
432
  if (metadata.width !== this.size.width || metadata.height !== this.size.height) {
433
- throw new Error(getString('imageDimensionMismatchDetailed', 'en', { field: String(this.label), actual: `${metadata.width}x${metadata.height}`, required: `${this.size.width}x${this.size.height}` }));
433
+ throw new Error(getString('imageDimensionMismatchDetailed', this.locale, { field: this.getLocalizedLabel(), actual: `${metadata.width}x${metadata.height}`, required: `${this.size.width}x${this.size.height}` }));
434
434
  }
435
435
  }
436
436
  }
@@ -346,8 +346,8 @@ declare const selectFieldConfigSchema: z.ZodIntersection<z.ZodUnion<readonly [z.
346
346
  }, z.core.$strict>]>, z.ZodObject<{
347
347
  type: z.ZodLiteral<"select">;
348
348
  optionsType: z.ZodEnum<{
349
- db: "db";
350
349
  section: "section";
350
+ db: "db";
351
351
  static: "static";
352
352
  }>;
353
353
  build: z.ZodFunction<z.core.$ZodFunctionArgs, z.ZodCustom<SelectField, SelectField>>;