@bagelink/vue 1.9.49 → 1.9.54

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 (79) hide show
  1. package/dist/components/AddressSearch.vue.d.ts.map +1 -1
  2. package/dist/components/Btn.vue.d.ts +2 -2
  3. package/dist/components/Btn.vue.d.ts.map +1 -1
  4. package/dist/components/Filter.vue.d.ts +0 -1
  5. package/dist/components/Filter.vue.d.ts.map +1 -1
  6. package/dist/components/ImportData.vue.d.ts.map +1 -1
  7. package/dist/components/ModalConfirm.vue.d.ts.map +1 -1
  8. package/dist/components/Spreadsheet/Index.vue.d.ts.map +1 -1
  9. package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
  10. package/dist/components/form/inputs/ColorInput.vue.d.ts.map +1 -1
  11. package/dist/components/form/inputs/DateInput.vue.d.ts +1 -1
  12. package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
  13. package/dist/components/form/inputs/DatePicker.vue.d.ts +1 -1
  14. package/dist/components/form/inputs/DatePicker.vue.d.ts.map +1 -1
  15. package/dist/components/form/inputs/EmailInput.vue.d.ts.map +1 -1
  16. package/dist/components/form/inputs/PasswordInput.vue.d.ts +1 -1
  17. package/dist/components/form/inputs/PasswordInput.vue.d.ts.map +1 -1
  18. package/dist/components/form/inputs/RadioPillsInput.vue.d.ts.map +1 -1
  19. package/dist/components/form/inputs/SelectInput.vue.d.ts +0 -1
  20. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  21. package/dist/components/form/inputs/TelInput.vue.d.ts.map +1 -1
  22. package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts.map +1 -1
  23. package/dist/components/lightbox/Lightbox.vue.d.ts.map +1 -1
  24. package/dist/dialog/DialogConfirm.vue.d.ts +0 -3
  25. package/dist/dialog/DialogConfirm.vue.d.ts.map +1 -1
  26. package/dist/dialog/DialogForm.vue.d.ts.map +1 -1
  27. package/dist/form-flow/FormFlow.vue.d.ts.map +1 -1
  28. package/dist/form-flow/MultiStepForm.vue.d.ts.map +1 -1
  29. package/dist/i18n/index.d.ts +996 -0
  30. package/dist/i18n/index.d.ts.map +1 -0
  31. package/dist/index.cjs +135 -130
  32. package/dist/index.d.ts +2 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.mjs +15415 -11483
  35. package/dist/plugins/bagel.d.ts +5 -7
  36. package/dist/plugins/bagel.d.ts.map +1 -1
  37. package/dist/plugins/useToast.d.ts.map +1 -1
  38. package/dist/style.css +1 -1
  39. package/dist/utils/calendar/dateUtils.d.ts +4 -3
  40. package/dist/utils/calendar/dateUtils.d.ts.map +1 -1
  41. package/dist/utils/index.d.ts +0 -1
  42. package/dist/utils/index.d.ts.map +1 -1
  43. package/dist/utils/lang.d.ts +6 -7
  44. package/dist/utils/lang.d.ts.map +1 -1
  45. package/package.json +2 -1
  46. package/src/components/AddressSearch.vue +5 -2
  47. package/src/components/Btn.vue +8 -6
  48. package/src/components/Filter.vue +37 -76
  49. package/src/components/ImportData.vue +35 -29
  50. package/src/components/ModalConfirm.vue +9 -7
  51. package/src/components/Spreadsheet/Index.vue +35 -60
  52. package/src/components/form/FieldArray.vue +4 -2
  53. package/src/components/form/inputs/ColorInput.vue +18 -12
  54. package/src/components/form/inputs/DateInput.vue +7 -4
  55. package/src/components/form/inputs/EmailInput.vue +9 -7
  56. package/src/components/form/inputs/PasswordInput.vue +17 -15
  57. package/src/components/form/inputs/RadioPillsInput.vue +5 -3
  58. package/src/components/form/inputs/SelectInput.vue +13 -11
  59. package/src/components/form/inputs/TelInput.vue +11 -9
  60. package/src/components/form/inputs/Upload/UploadInput.vue +7 -5
  61. package/src/components/lightbox/Lightbox.vue +4 -1
  62. package/src/dialog/DialogConfirm.vue +11 -6
  63. package/src/dialog/DialogForm.vue +9 -9
  64. package/src/form-flow/FormFlow.vue +7 -15
  65. package/src/form-flow/MultiStepForm.vue +16 -12
  66. package/src/i18n/index.ts +130 -0
  67. package/src/i18n/locales/en.json +153 -0
  68. package/src/i18n/locales/es.json +153 -0
  69. package/src/i18n/locales/fr.json +153 -0
  70. package/src/i18n/locales/he.json +174 -0
  71. package/src/i18n/locales/it.json +153 -0
  72. package/src/i18n/locales/ru.json +153 -0
  73. package/src/index.ts +11 -5
  74. package/src/plugins/bagel.ts +14 -26
  75. package/src/plugins/useToast.ts +4 -2
  76. package/src/styles/text.css +2 -1
  77. package/src/utils/calendar/dateUtils.ts +91 -59
  78. package/src/utils/index.ts +0 -2
  79. package/src/utils/lang.ts +0 -46
@@ -10,6 +10,7 @@ import type { DialogWidth, DialogPosition, DialogAction } from './dialogTypes'
10
10
  import { ref, computed } from 'vue'
11
11
  import Btn from '../components/Btn.vue'
12
12
  import FormFlow from '../form-flow/FormFlow.vue'
13
+ import { useI18n } from '../i18n'
13
14
  import Dialog from './Dialog.vue'
14
15
 
15
16
  const props = withDefaults(defineProps<{
@@ -29,9 +30,6 @@ const props = withDefaults(defineProps<{
29
30
  width: 'm',
30
31
  position: 'center',
31
32
  dismissable: true,
32
- submitText: 'Save',
33
- cancelText: 'Cancel',
34
- deleteText: 'Delete'
35
33
  })
36
34
 
37
35
  const emit = defineEmits<{
@@ -39,6 +37,8 @@ const emit = defineEmits<{
39
37
  'resolve': [result: { action: DialogAction, data: T }]
40
38
  }>()
41
39
 
40
+ const { $t } = useI18n()
41
+
42
42
  // Form state - use Record<string, any> internally for FormFlow compatibility
43
43
  const formData = ref<Record<string, any>>({ ...(props.modelValue || {}) })
44
44
  const isSubmitting = ref(false)
@@ -55,7 +55,7 @@ async function handleSubmit() {
55
55
 
56
56
  // Validate form before submitting
57
57
  if (!formFlowRef.value?.validate()) {
58
- error.value = 'Please fix the validation errors before submitting'
58
+ error.value = $t('dialogForm.validationError')
59
59
  return
60
60
  }
61
61
 
@@ -69,7 +69,7 @@ async function handleSubmit() {
69
69
  emit('resolve', { action: 'submit', data: formData.value as T })
70
70
  emit('update:open', false)
71
71
  } catch (err: unknown) {
72
- error.value = err instanceof Error ? err.message : 'An error occurred'
72
+ error.value = err instanceof Error ? err.message : $t('dialogForm.errorOccurred')
73
73
  } finally {
74
74
  isSubmitting.value = false
75
75
  }
@@ -86,7 +86,7 @@ async function handleDelete() {
86
86
  emit('resolve', { action: 'delete', data: formData.value as T })
87
87
  emit('update:open', false)
88
88
  } catch (err: unknown) {
89
- error.value = err instanceof Error ? err.message : 'An error occurred'
89
+ error.value = err instanceof Error ? err.message : $t('dialogForm.errorOccurred')
90
90
  } finally {
91
91
  isDeleting.value = false
92
92
  }
@@ -124,19 +124,19 @@ function handleClose() {
124
124
  v-if="hasDeleteHandler" color="red" flat :loading="isDeleting" :disabled="isSubmitting" class="me-auto"
125
125
  @click="handleDelete"
126
126
  >
127
- {{ deleteText }}
127
+ {{ deleteText || $t('dialogForm.delete') }}
128
128
  </Btn>
129
129
 
130
130
  <div class="flex-grow-1" />
131
131
 
132
132
  <!-- Cancel button -->
133
133
  <Btn flat :disabled="isSubmitting || isDeleting" @click="handleCancel">
134
- {{ cancelText }}
134
+ {{ cancelText || $t('dialogForm.cancel') }}
135
135
  </Btn>
136
136
 
137
137
  <!-- Submit button -->
138
138
  <Btn color="primary" :loading="isSubmitting" :disabled="isDeleting" @click="handleSubmit">
139
- {{ submitText }}
139
+ {{ submitText || $t('dialogForm.save') }}
140
140
  </Btn>
141
141
  </template>
142
142
  </Dialog>
@@ -1,21 +1,9 @@
1
1
  <script setup lang="ts" generic="T extends Record<string, any>">
2
- /**
3
- * FormFlow - Single-step form renderer
4
- *
5
- * Renders forms from schema definitions with automatic:
6
- * - Field rendering based on type
7
- * - Conditional visibility (.if() clauses)
8
- * - Validation (.validate() chains)
9
- * - Layout (.row() grouping)
10
- * - Custom component/slot rendering
11
- * - Nested object support (dot notation)
12
- */
13
-
14
2
  import type { SchemaDefinition, FieldBuilder } from './form-flow'
15
3
 
16
4
  import { computed, ref, watch } from 'vue'
17
-
18
5
  import ArrayInput from '../components/form/inputs/ArrayInput.vue'
6
+
19
7
  import CheckInput from '../components/form/inputs/CheckInput.vue'
20
8
  import CodeEditor from '../components/form/inputs/CodeEditor/Index.vue'
21
9
  import DateInput from '../components/form/inputs/DateInput.vue'
@@ -29,6 +17,7 @@ import TelInput from '../components/form/inputs/TelInput.vue'
29
17
  import TextInput from '../components/form/inputs/TextInput.vue'
30
18
  import ToggleInput from '../components/form/inputs/ToggleInput.vue'
31
19
  import UploadInput from '../components/form/inputs/Upload/UploadInput.vue'
20
+ import { useI18n } from '../i18n'
32
21
 
33
22
  import { parseQuery } from '../utils/queryFilter'
34
23
 
@@ -41,11 +30,14 @@ export interface Props<T extends Record<string, any> = Record<string, any>> {
41
30
  }
42
31
 
43
32
  const props = defineProps<Props<T>>()
33
+
44
34
  const emit = defineEmits<{
45
35
  'update:modelValue': [value: T]
46
36
  'submit': [value: T]
47
37
  }>()
48
38
 
39
+ const { $t } = useI18n()
40
+
49
41
  // Get value from nested path (e.g., 'meta.preferences.theme')
50
42
  function getNestedValue(obj: any, path: string): any {
51
43
  const keys = path.split('.')
@@ -224,7 +216,7 @@ function validateField(key: string, field: FieldBuilder): boolean {
224
216
  if (field._config.required === true) {
225
217
  const isEmpty = value == null || value === '' || (Array.isArray(value) && value.length === 0)
226
218
  if (isEmpty) {
227
- validationErrors.value = { ...validationErrors.value, [key]: field._config.requiredMessage || 'This field is required' }
219
+ validationErrors.value = { ...validationErrors.value, [key]: field._config.requiredMessage || $t('form.required') }
228
220
  return false
229
221
  }
230
222
  }
@@ -360,7 +352,7 @@ function validateAll(): boolean {
360
352
  if (field._config.required === true) {
361
353
  const isEmpty = value == null || value === '' || (Array.isArray(value) && value.length === 0)
362
354
  if (isEmpty) {
363
- newErrors[key] = field._config.requiredMessage || 'This field is required'
355
+ newErrors[key] = field._config.requiredMessage || $t('form.required')
364
356
  isValid = false
365
357
  continue
366
358
  }
@@ -12,22 +12,15 @@
12
12
  import type { FieldBuilder, SchemaDefinition } from './form-flow'
13
13
  import { computed, ref, watch } from 'vue'
14
14
 
15
+ import { useI18n } from '../i18n'
15
16
  import { parseQuery } from '../utils/queryFilter'
16
17
 
17
18
  import FormFlow from './FormFlow.vue'
18
19
 
19
- export interface Props {
20
- schema: Record<string, SchemaDefinition>
21
- modelValue?: Record<string, any>
22
- currentStep?: string
23
- components?: Record<string, any>
24
- /** Whether to validate required fields before allowing next step */
25
- validateOnNext?: boolean
26
- }
27
-
28
20
  const props = withDefaults(defineProps<Props>(), {
29
21
  validateOnNext: true
30
22
  })
23
+
31
24
  const emit = defineEmits<{
32
25
  'update:modelValue': [value: Record<string, any>]
33
26
  'update:currentStep': [step: string]
@@ -36,6 +29,17 @@ const emit = defineEmits<{
36
29
  'validationError': [errors: Record<string, string>]
37
30
  }>()
38
31
 
32
+ const { $t } = useI18n()
33
+
34
+ export interface Props {
35
+ schema: Record<string, SchemaDefinition>
36
+ modelValue?: Record<string, any>
37
+ currentStep?: string
38
+ components?: Record<string, any>
39
+ /** Whether to validate required fields before allowing next step */
40
+ validateOnNext?: boolean
41
+ }
42
+
39
43
  // Local form state - initialize with empty object if undefined
40
44
  const formData = ref({ ...(props.modelValue || {}) }) as any
41
45
 
@@ -366,15 +370,15 @@ defineExpose({
366
370
  <!-- Navigation Buttons -->
367
371
  <div class="step-navigation">
368
372
  <button type="button" class="btn-secondary" :disabled="isFirstStep" @click="prevStep">
369
- Previous
373
+ {{ $t('multiStep.previous') }}
370
374
  </button>
371
375
 
372
376
  <div class="step-counter">
373
- Step {{ currentStepIndex + 1 }} of {{ visibleSteps.length }}
377
+ {{ $t('multiStep.step', { current: currentStepIndex + 1, total: visibleSteps.length }) }}
374
378
  </div>
375
379
 
376
380
  <button type="button" class="btn-primary" @click="nextStep">
377
- {{ isLastStep ? 'Complete' : 'Next' }}
381
+ {{ isLastStep ? $t('multiStep.complete') : $t('multiStep.next') }}
378
382
  </button>
379
383
  </div>
380
384
  </div>
@@ -0,0 +1,130 @@
1
+ import type { Composer, I18n } from 'vue-i18n'
2
+ import { createI18n as createVueI18n, useI18n as useVueI18n } from 'vue-i18n'
3
+ import en from './locales/en.json'
4
+ import es from './locales/es.json'
5
+ import fr from './locales/fr.json'
6
+ import he from './locales/he.json'
7
+ import it from './locales/it.json'
8
+ import ru from './locales/ru.json'
9
+
10
+ export type MessageSchema = typeof en
11
+
12
+ // Bagelink's built-in locales
13
+ const bagelinkLocales = {
14
+ en,
15
+ he,
16
+ it,
17
+ es,
18
+ fr,
19
+ ru,
20
+ } as const
21
+
22
+ export interface CreateBagelI18nOptions {
23
+ /** Default language (default: 'en') */
24
+ defaultLang?: string
25
+ /** Initial language (default: 'en') */
26
+ language?: string
27
+ /** Available languages (default: all bagelink locales) */
28
+ availableLangs?: string[]
29
+ /** User's custom messages (merged with bagelink's) */
30
+ messages?: Record<string, Record<string, unknown>>
31
+ }
32
+
33
+ let i18nInstance: I18n | null = null
34
+
35
+ /**
36
+ * Creates an i18n instance with bagelink's translations merged with user's
37
+ */
38
+ export function createI18n(options: CreateBagelI18nOptions = {}): I18n {
39
+ const {
40
+ defaultLang = 'en',
41
+ language = 'en',
42
+ availableLangs = Object.keys(bagelinkLocales),
43
+ messages = {},
44
+ } = options
45
+
46
+ // Merge bagelink locales with user messages
47
+ const mergedMessages: Record<string, Record<string, unknown>> = {}
48
+
49
+ for (const lang of availableLangs) {
50
+ mergedMessages[lang] = {
51
+ ...(bagelinkLocales[lang as keyof typeof bagelinkLocales] || {}),
52
+ ...(messages[lang] || {}),
53
+ }
54
+ }
55
+
56
+ i18nInstance = createVueI18n({
57
+ locale: language,
58
+ fallbackLocale: defaultLang,
59
+ messages: mergedMessages as any,
60
+ legacy: false,
61
+ globalInjection: true,
62
+ })
63
+
64
+ return i18nInstance
65
+ }
66
+
67
+ /**
68
+ * Get the global i18n instance
69
+ */
70
+ export function getI18n(): I18n {
71
+ if (!i18nInstance) {
72
+ throw new Error('i18n not initialized. Call createI18n() first.')
73
+ }
74
+ return i18nInstance
75
+ }
76
+
77
+ interface UseI18nReturn {
78
+ $t: Composer['t']
79
+ t: Composer['t']
80
+ locale: Composer['locale']
81
+ availableLocales: Composer['availableLocales']
82
+ fallbackLocale: Composer['fallbackLocale']
83
+ n: Composer['n']
84
+ d: Composer['d']
85
+ }
86
+
87
+ /**
88
+ * useI18n wrapper that returns bagelink's typed i18n functions
89
+ */
90
+ export function useI18n(): UseI18nReturn {
91
+ const { t, locale, availableLocales, fallbackLocale, n, d } = useVueI18n()
92
+
93
+ return {
94
+ $t: t,
95
+ t,
96
+ locale,
97
+ availableLocales,
98
+ fallbackLocale,
99
+ n,
100
+ d,
101
+ }
102
+ }
103
+
104
+ // Export locale data for direct access if needed
105
+ export { bagelinkLocales }
106
+
107
+ /**
108
+ * A string that is either a plain string or a translation key prefixed with `$t:`.
109
+ * @example
110
+ * 'Save' // plain string, used as-is
111
+ * '$t:btn.save' // translation key, resolved via i18n
112
+ */
113
+ export type TranslatableString = string | `$t:${string}`
114
+
115
+ /**
116
+ * Resolves a TranslatableString.
117
+ * If the value starts with `$t:`, it's treated as a translation key.
118
+ * Otherwise the string is returned as-is.
119
+ * Works outside component context (uses the global i18n instance).
120
+ *
121
+ * @example
122
+ * resolveI18n('Save') // → 'Save'
123
+ * resolveI18n('$t:btn.save') // → 'Salva' (if locale is 'it')
124
+ * resolveI18n(undefined) // → undefined
125
+ */
126
+ export function resolveI18n(value: TranslatableString | undefined): string | undefined {
127
+ if (value == null) return undefined
128
+ if (!value.startsWith('$t:')) return value
129
+ return (getI18n().global.t as (key: string) => string)(value.slice(3))
130
+ }
@@ -0,0 +1,153 @@
1
+ {
2
+ "modalConfirm": {
3
+ "title": "Confirm",
4
+ "message": "Are you sure you want to continue?",
5
+ "confirm": "Confirm",
6
+ "cancel": "Cancel"
7
+ },
8
+ "upload": {
9
+ "upload": "Upload",
10
+ "uploading": "Uploading {count} file{plural}...",
11
+ "noFile": "No file selected",
12
+ "dropPlaceholder": "Drag and Drop files here or click to upload",
13
+ "delete": "Delete",
14
+ "replace": "Replace",
15
+ "download": "Download"
16
+ },
17
+ "pagination": {
18
+ "of": "of",
19
+ "prev": "Previous",
20
+ "next": "Next"
21
+ },
22
+ "form": {
23
+ "required": "This field is required",
24
+ "invalidEmail": "Please enter a valid email address",
25
+ "invalidUrl": "Please enter a valid URL",
26
+ "minLength": "Must be at least {min} characters",
27
+ "maxLength": "Must be no more than {max} characters",
28
+ "minValue": "Must be at least {min}",
29
+ "maxValue": "Must be no more than {max}",
30
+ "pattern": "Invalid format",
31
+ "passwordStrength": "Password strength"
32
+ },
33
+ "password": {
34
+ "veryWeak": "Very Weak",
35
+ "weak": "Weak",
36
+ "fair": "Fair",
37
+ "good": "Good",
38
+ "strong": "Strong"
39
+ },
40
+ "select": {
41
+ "placeholder": "Select",
42
+ "search": "Search",
43
+ "yes": "Yes",
44
+ "no": "No"
45
+ },
46
+ "fieldArray": {
47
+ "loadDefault": "Load Default {label}"
48
+ },
49
+ "btn": {
50
+ "loading": "Loading..."
51
+ },
52
+ "toast": {
53
+ "success": "Success",
54
+ "error": "Error",
55
+ "warning": "Warning",
56
+ "info": "Information"
57
+ },
58
+ "filter": {
59
+ "filter": "Filter",
60
+ "noActiveFilters": "No active filters",
61
+ "connectors": {
62
+ "and": "And",
63
+ "or": "Or"
64
+ },
65
+ "operators": {
66
+ "eq": "Equals",
67
+ "ne": "Not equals",
68
+ "gt": "Greater than",
69
+ "ge": "Greater or equal",
70
+ "lt": "Less than",
71
+ "le": "Less or equal",
72
+ "co": "Contains",
73
+ "sw": "Starts with",
74
+ "ew": "Ends with",
75
+ "pr": "Present"
76
+ },
77
+ "placeholders": {
78
+ "selectField": "Select field",
79
+ "selectOption": "Select option",
80
+ "selectDate": "Select date",
81
+ "enterValue": "Value"
82
+ },
83
+ "buttons": {
84
+ "addCondition": "Add condition",
85
+ "clearAll": "Clear all"
86
+ }
87
+ },
88
+ "multiStep": {
89
+ "previous": "Previous",
90
+ "next": "Next",
91
+ "complete": "Complete",
92
+ "step": "Step {current} of {total}"
93
+ },
94
+ "addressSearch": {
95
+ "placeholder": "Enter address"
96
+ },
97
+ "importData": {
98
+ "close": "Close",
99
+ "cancel": "Cancel",
100
+ "importData": "Import Data",
101
+ "changeFile": "Change File",
102
+ "selectSheet": "Select Sheet",
103
+ "hasHeaders": "Mark this if file has a header row",
104
+ "sourceKeyField": "Source Key Field (from this file)",
105
+ "relatedKeyField": "Related Key Field (from related file)",
106
+ "selectSourceValue": "Select source value",
107
+ "sourceValue": "Source value",
108
+ "selectTargetValue": "Select target value",
109
+ "targetValue": "Target value",
110
+ "selectColumn": "Select column..."
111
+ },
112
+ "timeAgo": {
113
+ "year": "year",
114
+ "month": "month",
115
+ "week": "week",
116
+ "day": "day",
117
+ "hour": "hour",
118
+ "minute": "minute",
119
+ "second": "second",
120
+ "ago": "ago",
121
+ "in": "in",
122
+ "justNow": "Just now"
123
+ },
124
+ "dialogForm": {
125
+ "save": "Save",
126
+ "cancel": "Cancel",
127
+ "delete": "Delete",
128
+ "validationError": "Please fix the validation errors before submitting",
129
+ "errorOccurred": "An error occurred"
130
+ },
131
+ "tel": {
132
+ "phoneNumber": "Phone Number",
133
+ "invalidPhone": "Please enter a valid phone number"
134
+ },
135
+ "email": {
136
+ "invalidEmail": "Please enter a valid email address",
137
+ "invalidDomain": "This email domain appears to be invalid"
138
+ },
139
+ "date": {
140
+ "invalidFormat": "Invalid date format"
141
+ },
142
+ "spreadsheet": {
143
+ "wrapText": "Wrap Text",
144
+ "selectAll": "Select All",
145
+ "clearAll": "Clear All"
146
+ },
147
+ "lightbox": {
148
+ "openFile": "Open File"
149
+ },
150
+ "color": {
151
+ "placeholder": "Enter color"
152
+ }
153
+ }
@@ -0,0 +1,153 @@
1
+ {
2
+ "modalConfirm": {
3
+ "title": "Confirmar",
4
+ "message": "¿Estás seguro de que quieres continuar?",
5
+ "confirm": "Confirmar",
6
+ "cancel": "Cancelar"
7
+ },
8
+ "upload": {
9
+ "upload": "Subir",
10
+ "uploading": "Subiendo {count} archivo{plural}...",
11
+ "noFile": "Ningún archivo seleccionado",
12
+ "dropPlaceholder": "Arrastra y suelta archivos aquí o haz clic para subir",
13
+ "delete": "Eliminar",
14
+ "replace": "Reemplazar",
15
+ "download": "Descargar"
16
+ },
17
+ "pagination": {
18
+ "of": "de",
19
+ "prev": "Anterior",
20
+ "next": "Siguiente"
21
+ },
22
+ "form": {
23
+ "required": "Este campo es obligatorio",
24
+ "invalidEmail": "Introduce un correo electrónico válido",
25
+ "invalidUrl": "Introduce una URL válida",
26
+ "minLength": "Debe tener al menos {min} caracteres",
27
+ "maxLength": "Debe tener como máximo {max} caracteres",
28
+ "minValue": "Debe ser al menos {min}",
29
+ "maxValue": "Debe ser como máximo {max}",
30
+ "pattern": "Formato inválido",
31
+ "passwordStrength": "Fortaleza de la contraseña"
32
+ },
33
+ "password": {
34
+ "veryWeak": "Muy débil",
35
+ "weak": "Débil",
36
+ "fair": "Regular",
37
+ "good": "Buena",
38
+ "strong": "Fuerte"
39
+ },
40
+ "select": {
41
+ "placeholder": "Seleccionar",
42
+ "search": "Buscar",
43
+ "yes": "Sí",
44
+ "no": "No"
45
+ },
46
+ "fieldArray": {
47
+ "loadDefault": "Cargar {label} predeterminado"
48
+ },
49
+ "btn": {
50
+ "loading": "Cargando..."
51
+ },
52
+ "toast": {
53
+ "success": "Éxito",
54
+ "error": "Error",
55
+ "warning": "Advertencia",
56
+ "info": "Información"
57
+ },
58
+ "filter": {
59
+ "filter": "Filtro",
60
+ "noActiveFilters": "Sin filtros activos",
61
+ "connectors": {
62
+ "and": "Y",
63
+ "or": "O"
64
+ },
65
+ "operators": {
66
+ "eq": "Igual a",
67
+ "ne": "No igual a",
68
+ "gt": "Mayor que",
69
+ "ge": "Mayor o igual",
70
+ "lt": "Menor que",
71
+ "le": "Menor o igual",
72
+ "co": "Contiene",
73
+ "sw": "Empieza con",
74
+ "ew": "Termina con",
75
+ "pr": "Presente"
76
+ },
77
+ "placeholders": {
78
+ "selectField": "Seleccionar campo",
79
+ "selectOption": "Seleccionar opción",
80
+ "selectDate": "Seleccionar fecha",
81
+ "enterValue": "Valor"
82
+ },
83
+ "buttons": {
84
+ "addCondition": "Añadir condición",
85
+ "clearAll": "Limpiar todo"
86
+ }
87
+ },
88
+ "multiStep": {
89
+ "previous": "Anterior",
90
+ "next": "Siguiente",
91
+ "complete": "Completar",
92
+ "step": "Paso {current} de {total}"
93
+ },
94
+ "addressSearch": {
95
+ "placeholder": "Introduce una dirección"
96
+ },
97
+ "importData": {
98
+ "close": "Cerrar",
99
+ "cancel": "Cancelar",
100
+ "importData": "Importar datos",
101
+ "changeFile": "Cambiar archivo",
102
+ "selectSheet": "Seleccionar hoja",
103
+ "hasHeaders": "Marcar si el archivo tiene fila de encabezado",
104
+ "sourceKeyField": "Campo clave de origen (de este archivo)",
105
+ "relatedKeyField": "Campo clave relacionado (del archivo relacionado)",
106
+ "selectSourceValue": "Seleccionar valor de origen",
107
+ "sourceValue": "Valor de origen",
108
+ "selectTargetValue": "Seleccionar valor de destino",
109
+ "targetValue": "Valor de destino",
110
+ "selectColumn": "Seleccionar columna..."
111
+ },
112
+ "timeAgo": {
113
+ "year": "año",
114
+ "month": "mes",
115
+ "week": "semana",
116
+ "day": "día",
117
+ "hour": "hora",
118
+ "minute": "minuto",
119
+ "second": "segundo",
120
+ "ago": "hace",
121
+ "in": "en",
122
+ "justNow": "Justo ahora"
123
+ },
124
+ "dialogForm": {
125
+ "save": "Guardar",
126
+ "cancel": "Cancelar",
127
+ "delete": "Eliminar",
128
+ "validationError": "Por favor corrija los errores de validación antes de enviar",
129
+ "errorOccurred": "Ocurrió un error"
130
+ },
131
+ "tel": {
132
+ "phoneNumber": "Número de teléfono",
133
+ "invalidPhone": "Por favor introduce un número de teléfono válido"
134
+ },
135
+ "email": {
136
+ "invalidEmail": "Introduce un correo electrónico válido",
137
+ "invalidDomain": "El dominio de este correo electrónico parece no ser válido"
138
+ },
139
+ "date": {
140
+ "invalidFormat": "Formato de fecha inválido"
141
+ },
142
+ "spreadsheet": {
143
+ "wrapText": "Ajuste de texto",
144
+ "selectAll": "Seleccionar todo",
145
+ "clearAll": "Limpiar todo"
146
+ },
147
+ "lightbox": {
148
+ "openFile": "Abrir archivo"
149
+ },
150
+ "color": {
151
+ "placeholder": "Introduce un color"
152
+ }
153
+ }