@stapel/listings-react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -0
- package/MODULE.md +191 -0
- package/README.md +169 -0
- package/dist/api/generated/schema.d.ts +1253 -0
- package/dist/api/generated/schema.d.ts.map +1 -0
- package/dist/api/generated/schema.js +2 -0
- package/dist/api/generated/schema.js.map +1 -0
- package/dist/api/listingsApi.d.ts +145 -0
- package/dist/api/listingsApi.d.ts.map +1 -0
- package/dist/api/listingsApi.js +38 -0
- package/dist/api/listingsApi.js.map +1 -0
- package/dist/api/types.d.ts +156 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +37 -0
- package/dist/api/types.js.map +1 -0
- package/dist/default/ErrorAlert.d.ts +9 -0
- package/dist/default/ErrorAlert.d.ts.map +1 -0
- package/dist/default/ErrorAlert.js +27 -0
- package/dist/default/ErrorAlert.js.map +1 -0
- package/dist/default/FavoritesPane.d.ts +18 -0
- package/dist/default/FavoritesPane.d.ts.map +1 -0
- package/dist/default/FavoritesPane.js +28 -0
- package/dist/default/FavoritesPane.js.map +1 -0
- package/dist/default/ListingCard.d.ts +42 -0
- package/dist/default/ListingCard.d.ts.map +1 -0
- package/dist/default/ListingCard.js +37 -0
- package/dist/default/ListingCard.js.map +1 -0
- package/dist/default/ListingComposerPage.d.ts +46 -0
- package/dist/default/ListingComposerPage.d.ts.map +1 -0
- package/dist/default/ListingComposerPage.js +99 -0
- package/dist/default/ListingComposerPage.js.map +1 -0
- package/dist/default/ListingDetailPane.d.ts +33 -0
- package/dist/default/ListingDetailPane.d.ts.map +1 -0
- package/dist/default/ListingDetailPane.js +48 -0
- package/dist/default/ListingDetailPane.js.map +1 -0
- package/dist/default/ListingPhoto.d.ts +25 -0
- package/dist/default/ListingPhoto.d.ts.map +1 -0
- package/dist/default/ListingPhoto.js +20 -0
- package/dist/default/ListingPhoto.js.map +1 -0
- package/dist/default/MyListingsPane.d.ts +25 -0
- package/dist/default/MyListingsPane.d.ts.map +1 -0
- package/dist/default/MyListingsPane.js +84 -0
- package/dist/default/MyListingsPane.js.map +1 -0
- package/dist/default/StatusTags.d.ts +31 -0
- package/dist/default/StatusTags.d.ts.map +1 -0
- package/dist/default/StatusTags.js +40 -0
- package/dist/default/StatusTags.js.map +1 -0
- package/dist/default/icons.d.ts +16 -0
- package/dist/default/icons.d.ts.map +1 -0
- package/dist/default/icons.js +5 -0
- package/dist/default/icons.js.map +1 -0
- package/dist/default/index.d.ts +35 -0
- package/dist/default/index.d.ts.map +1 -0
- package/dist/default/index.js +26 -0
- package/dist/default/index.js.map +1 -0
- package/dist/default/theme.d.ts +25 -0
- package/dist/default/theme.d.ts.map +1 -0
- package/dist/default/theme.js +40 -0
- package/dist/default/theme.js.map +1 -0
- package/dist/default/types.d.ts +12 -0
- package/dist/default/types.d.ts.map +1 -0
- package/dist/default/types.js +2 -0
- package/dist/default/types.js.map +1 -0
- package/dist/flows/registry.d.ts +35 -0
- package/dist/flows/registry.d.ts.map +1 -0
- package/dist/flows/registry.js +33 -0
- package/dist/flows/registry.js.map +1 -0
- package/dist/headless/Favorites.d.ts +52 -0
- package/dist/headless/Favorites.d.ts.map +1 -0
- package/dist/headless/Favorites.js +78 -0
- package/dist/headless/Favorites.js.map +1 -0
- package/dist/headless/ListingActions.d.ts +30 -0
- package/dist/headless/ListingActions.d.ts.map +1 -0
- package/dist/headless/ListingActions.js +54 -0
- package/dist/headless/ListingActions.js.map +1 -0
- package/dist/headless/ListingComposer.d.ts +133 -0
- package/dist/headless/ListingComposer.d.ts.map +1 -0
- package/dist/headless/ListingComposer.js +246 -0
- package/dist/headless/ListingComposer.js.map +1 -0
- package/dist/headless/ListingDetail.d.ts +81 -0
- package/dist/headless/ListingDetail.d.ts.map +1 -0
- package/dist/headless/ListingDetail.js +101 -0
- package/dist/headless/ListingDetail.js.map +1 -0
- package/dist/headless/ListingsProvider.d.ts +17 -0
- package/dist/headless/ListingsProvider.d.ts.map +1 -0
- package/dist/headless/ListingsProvider.js +16 -0
- package/dist/headless/ListingsProvider.js.map +1 -0
- package/dist/headless/MyListings.d.ts +44 -0
- package/dist/headless/MyListings.d.ts.map +1 -0
- package/dist/headless/MyListings.js +82 -0
- package/dist/headless/MyListings.js.map +1 -0
- package/dist/headless/useMandateGate.d.ts +28 -0
- package/dist/headless/useMandateGate.d.ts.map +1 -0
- package/dist/headless/useMandateGate.js +39 -0
- package/dist/headless/useMandateGate.js.map +1 -0
- package/dist/i18n/errorsMap.d.ts +34 -0
- package/dist/i18n/errorsMap.d.ts.map +1 -0
- package/dist/i18n/errorsMap.js +45 -0
- package/dist/i18n/errorsMap.js.map +1 -0
- package/dist/i18n/es.d.ts +21 -0
- package/dist/i18n/es.d.ts.map +1 -0
- package/dist/i18n/es.js +146 -0
- package/dist/i18n/es.js.map +1 -0
- package/dist/i18n/generated/errors.es.gen.d.ts +16 -0
- package/dist/i18n/generated/errors.es.gen.d.ts.map +1 -0
- package/dist/i18n/generated/errors.es.gen.js +58 -0
- package/dist/i18n/generated/errors.es.gen.js.map +1 -0
- package/dist/i18n/generated/errors.gen.d.ts +413 -0
- package/dist/i18n/generated/errors.gen.d.ts.map +1 -0
- package/dist/i18n/generated/errors.gen.js +210 -0
- package/dist/i18n/generated/errors.gen.js.map +1 -0
- package/dist/i18n/generated/errors.ru.gen.d.ts +16 -0
- package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -0
- package/dist/i18n/generated/errors.ru.gen.js +58 -0
- package/dist/i18n/generated/errors.ru.gen.js.map +1 -0
- package/dist/i18n/keys.d.ts +170 -0
- package/dist/i18n/keys.d.ts.map +1 -0
- package/dist/i18n/keys.js +295 -0
- package/dist/i18n/keys.js.map +1 -0
- package/dist/i18n/ru.d.ts +37 -0
- package/dist/i18n/ru.d.ts.map +1 -0
- package/dist/i18n/ru.js +162 -0
- package/dist/i18n/ru.js.map +1 -0
- package/dist/index.d.ts +103 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +98 -0
- package/dist/index.js.map +1 -0
- package/dist/model/context.d.ts +11 -0
- package/dist/model/context.d.ts.map +1 -0
- package/dist/model/context.js +16 -0
- package/dist/model/context.js.map +1 -0
- package/dist/model/draft.d.ts +138 -0
- package/dist/model/draft.d.ts.map +1 -0
- package/dist/model/draft.js +192 -0
- package/dist/model/draft.js.map +1 -0
- package/dist/model/features.d.ts +69 -0
- package/dist/model/features.d.ts.map +1 -0
- package/dist/model/features.js +73 -0
- package/dist/model/features.js.map +1 -0
- package/dist/model/mineSource.d.ts +47 -0
- package/dist/model/mineSource.d.ts.map +1 -0
- package/dist/model/mineSource.js +45 -0
- package/dist/model/mineSource.js.map +1 -0
- package/dist/model/mutations.d.ts +60 -0
- package/dist/model/mutations.d.ts.map +1 -0
- package/dist/model/mutations.js +165 -0
- package/dist/model/mutations.js.map +1 -0
- package/dist/model/queries.d.ts +75 -0
- package/dist/model/queries.d.ts.map +1 -0
- package/dist/model/queries.js +117 -0
- package/dist/model/queries.js.map +1 -0
- package/dist/model/queryKeys.d.ts +50 -0
- package/dist/model/queryKeys.d.ts.map +1 -0
- package/dist/model/queryKeys.js +24 -0
- package/dist/model/queryKeys.js.map +1 -0
- package/dist/model/runtime.d.ts +69 -0
- package/dist/model/runtime.d.ts.map +1 -0
- package/dist/model/runtime.js +14 -0
- package/dist/model/runtime.js.map +1 -0
- package/dist/model/status.d.ts +117 -0
- package/dist/model/status.d.ts.map +1 -0
- package/dist/model/status.js +164 -0
- package/dist/model/status.js.map +1 -0
- package/dist/model/transitions.d.ts +41 -0
- package/dist/model/transitions.d.ts.map +1 -0
- package/dist/model/transitions.js +25 -0
- package/dist/model/transitions.js.map +1 -0
- package/dist/model/validation.d.ts +135 -0
- package/dist/model/validation.d.ts.map +1 -0
- package/dist/model/validation.js +191 -0
- package/dist/model/validation.js.map +1 -0
- package/dist/nav/manifest.d.ts +46 -0
- package/dist/nav/manifest.d.ts.map +1 -0
- package/dist/nav/manifest.js +56 -0
- package/dist/nav/manifest.js.map +1 -0
- package/llms.txt +118 -0
- package/manifest.json +1044 -0
- package/nav-manifest.json +84 -0
- package/package.json +121 -0
- package/src/analytics/generated/events.json +7 -0
- package/src/api/generated/schema.ts +1255 -0
- package/src/api/listingsApi.ts +237 -0
- package/src/api/types.ts +193 -0
- package/src/default/ErrorAlert.tsx +46 -0
- package/src/default/FavoritesPane.tsx +123 -0
- package/src/default/ListingCard.tsx +178 -0
- package/src/default/ListingComposerPage.tsx +466 -0
- package/src/default/ListingDetailPane.tsx +271 -0
- package/src/default/ListingPhoto.tsx +62 -0
- package/src/default/MyListingsPane.tsx +333 -0
- package/src/default/StatusTags.tsx +86 -0
- package/src/default/icons.tsx +31 -0
- package/src/default/index.ts +35 -0
- package/src/default/theme.tsx +67 -0
- package/src/default/types.ts +12 -0
- package/src/flows/registry.ts +45 -0
- package/src/headless/Favorites.tsx +137 -0
- package/src/headless/ListingActions.tsx +101 -0
- package/src/headless/ListingComposer.tsx +476 -0
- package/src/headless/ListingDetail.tsx +231 -0
- package/src/headless/ListingsProvider.tsx +20 -0
- package/src/headless/MyListings.tsx +148 -0
- package/src/headless/useMandateGate.ts +40 -0
- package/src/i18n/errorsMap.ts +62 -0
- package/src/i18n/es.ts +198 -0
- package/src/i18n/generated/errors.es.gen.ts +64 -0
- package/src/i18n/generated/errors.gen.ts +241 -0
- package/src/i18n/generated/errors.json +499 -0
- package/src/i18n/generated/errors.ru.gen.ts +64 -0
- package/src/i18n/keys.ts +356 -0
- package/src/i18n/ru.ts +215 -0
- package/src/index.ts +260 -0
- package/src/model/context.tsx +28 -0
- package/src/model/draft.ts +307 -0
- package/src/model/features.ts +122 -0
- package/src/model/mineSource.ts +55 -0
- package/src/model/mutations.ts +224 -0
- package/src/model/queries.ts +150 -0
- package/src/model/queryKeys.ts +76 -0
- package/src/model/runtime.ts +87 -0
- package/src/model/status.ts +279 -0
- package/src/model/transitions.ts +62 -0
- package/src/model/validation.ts +271 -0
- package/src/nav/manifest.ts +97 -0
- package/tsconfig.json +26 -0
package/src/i18n/es.ts
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import type { I18nDictionary, I18nEngine } from "@stapel/core";
|
|
2
|
+
import { listingsErrorBundleEs } from "./generated/errors.es.gen.js";
|
|
3
|
+
|
|
4
|
+
export { listingsErrorBundleEs } from "./generated/errors.es.gen.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Spanish bundle for listings-react — the `@stapel/listings-react/i18n/es`
|
|
8
|
+
* subpath (i18n-shipping.md §2), opt-in exactly like `./i18n/ru`.
|
|
9
|
+
*
|
|
10
|
+
* It carries the UI copy too, not only the nine module-owned error keys. The
|
|
11
|
+
* composer and the owner's dashboard are the surfaces a seller works in for
|
|
12
|
+
* minutes at a time; a half-translated form there is visible immediately, in
|
|
13
|
+
* the way a half-translated settings pane is not. Same call chat-react made
|
|
14
|
+
* for the buyer↔seller thread.
|
|
15
|
+
*
|
|
16
|
+
* Provenance and the owner split are as in `./ru.ts`: 42 cross-cutting codes
|
|
17
|
+
* generated from stapel-core's catalogue, 9 `stapel_listings` codes authored
|
|
18
|
+
* here until upstream ships `translations/`, and the 12 `stapel_attributes`
|
|
19
|
+
* codes deliberately left to `@stapel/attributes-react`.
|
|
20
|
+
*/
|
|
21
|
+
export const listingsI18nBundleEs: I18nDictionary = {
|
|
22
|
+
...listingsErrorBundleEs,
|
|
23
|
+
|
|
24
|
+
// ── the 9 stapel_listings-owned codes, pair-authored ─────────────────────
|
|
25
|
+
"error.400.category_required": "Hay que elegir una categoría",
|
|
26
|
+
"error.400.image_required":
|
|
27
|
+
"Para publicar el anuncio hace falta al menos una foto",
|
|
28
|
+
"error.400.listing_feature_not_allowed":
|
|
29
|
+
"El detalle «{feature}» no pertenece a esta categoría",
|
|
30
|
+
"error.400.publish_validation_failed":
|
|
31
|
+
"El anuncio no pasó la revisión y no se publicó",
|
|
32
|
+
"error.403.listing_not_owner": "Este anuncio no es tuyo",
|
|
33
|
+
"error.404.listing_not_found": "No se encontró el anuncio",
|
|
34
|
+
"error.409.already_favorited": "El anuncio ya está en favoritos",
|
|
35
|
+
"error.409.invalid_listing_transition":
|
|
36
|
+
"Un anuncio en estado «{from_status}» no se puede mover así",
|
|
37
|
+
"error.409.listing_cannot_delete_active":
|
|
38
|
+
"Archívalo primero — un anuncio a la venta no se puede borrar",
|
|
39
|
+
|
|
40
|
+
"listings.error.unknown": "Algo salió mal con este anuncio",
|
|
41
|
+
|
|
42
|
+
"listings.status.draft": "Borrador",
|
|
43
|
+
"listings.status.pending": "En revisión",
|
|
44
|
+
"listings.status.published": "Publicado",
|
|
45
|
+
"listings.status.paused": "En pausa",
|
|
46
|
+
"listings.status.expired": "Caducado",
|
|
47
|
+
"listings.status.sold": "Vendido",
|
|
48
|
+
"listings.status.rejected": "Rechazado",
|
|
49
|
+
"listings.status.blocked": "Retirado",
|
|
50
|
+
"listings.status.archived": "Archivado",
|
|
51
|
+
|
|
52
|
+
"listings.moderation.first_review":
|
|
53
|
+
"Enviado a revisión. Saldrá a la venta cuando un moderador lo apruebe.",
|
|
54
|
+
"listings.moderation.live_edit_pending":
|
|
55
|
+
"Tu anuncio sigue publicado mientras revisamos los cambios — la gente lo ve ahora mismo.",
|
|
56
|
+
"listings.moderation.pending_offline":
|
|
57
|
+
"Se pidió una revisión, pero este anuncio ya no está a la venta.",
|
|
58
|
+
"listings.moderation.needs_review":
|
|
59
|
+
"Un moderador lo está mirando a mano.",
|
|
60
|
+
"listings.moderation.live_needs_review":
|
|
61
|
+
"Publicado, y un moderador está mirando los cambios a mano.",
|
|
62
|
+
"listings.moderation.rejected":
|
|
63
|
+
"Un moderador rechazó este anuncio. Edítalo y vuelve a enviarlo.",
|
|
64
|
+
"listings.moderation.rejected_still_live":
|
|
65
|
+
"Un moderador rechazó este anuncio; sigue visible mientras se aplica.",
|
|
66
|
+
|
|
67
|
+
"listings.card.no_photo": "Sin foto",
|
|
68
|
+
"listings.card.photo_unavailable": "Foto no disponible",
|
|
69
|
+
"listings.card.price_absent": "Precio a consultar",
|
|
70
|
+
"listings.card.favorite_add": "Guardar en favoritos",
|
|
71
|
+
"listings.card.favorite_remove": "Quitar de favoritos",
|
|
72
|
+
"listings.card.open": "Abrir",
|
|
73
|
+
|
|
74
|
+
"listings.detail.loading": "Cargando el anuncio…",
|
|
75
|
+
"listings.detail.load_failed": "No pudimos cargar este anuncio",
|
|
76
|
+
"listings.detail.retry": "Reintentar",
|
|
77
|
+
"listings.detail.not_found": "No hay ningún anuncio en esta dirección",
|
|
78
|
+
"listings.detail.removed": "Este anuncio fue eliminado",
|
|
79
|
+
"listings.detail.not_published":
|
|
80
|
+
"Este anuncio no está a la venta ahora, así que lo que ves puede estar desactualizado",
|
|
81
|
+
"listings.detail.owner_only_view":
|
|
82
|
+
"Solo tú ves esto — todavía no está publicado",
|
|
83
|
+
"listings.detail.description": "Descripción",
|
|
84
|
+
"listings.detail.specs": "Detalles",
|
|
85
|
+
"listings.detail.no_specs": "El vendedor no indicó más detalles",
|
|
86
|
+
"listings.detail.unreadable_features":
|
|
87
|
+
"Detalles que esta versión no pudo leer: {count}",
|
|
88
|
+
"listings.detail.photos_unavailable":
|
|
89
|
+
"Aquí no se pueden mostrar las fotos — la aplicación no sabe resolverlas",
|
|
90
|
+
"listings.detail.photo_alt": "Foto {index} de {total}",
|
|
91
|
+
"listings.detail.published_at": "Publicado el {date}",
|
|
92
|
+
"listings.detail.expires_at": "A la venta hasta el {date}",
|
|
93
|
+
"listings.detail.stock": "Disponibles: {count}",
|
|
94
|
+
|
|
95
|
+
"listings.compose.new_title": "Anuncio nuevo",
|
|
96
|
+
"listings.compose.edit_title": "Editar el anuncio",
|
|
97
|
+
"listings.compose.category": "Categoría",
|
|
98
|
+
"listings.compose.category_help":
|
|
99
|
+
"La categoría decide qué detalles se le piden al vendedor",
|
|
100
|
+
"listings.compose.category_required": "Elige una categoría primero",
|
|
101
|
+
"listings.compose.category_changed_dropped":
|
|
102
|
+
"Respuestas que no aplican a esta categoría y se han borrado: {count}",
|
|
103
|
+
"listings.compose.title_label": "Título",
|
|
104
|
+
"listings.compose.title_too_long":
|
|
105
|
+
"El título debe tener como mucho {max_length} caracteres",
|
|
106
|
+
"listings.compose.description_label": "Descripción",
|
|
107
|
+
"listings.compose.price_label": "Precio",
|
|
108
|
+
"listings.compose.price_invalid":
|
|
109
|
+
"Escribe el precio como un número, con dos decimales como mucho",
|
|
110
|
+
"listings.compose.currency_label": "Moneda",
|
|
111
|
+
"listings.compose.location_label": "Dónde está",
|
|
112
|
+
"listings.compose.lat_label": "Latitud",
|
|
113
|
+
"listings.compose.lon_label": "Longitud",
|
|
114
|
+
"listings.compose.geo_incomplete":
|
|
115
|
+
"Una latitud necesita su longitud al lado — media coordenada no apunta a ningún sitio",
|
|
116
|
+
"listings.compose.photos": "Fotos",
|
|
117
|
+
"listings.compose.too_many_images":
|
|
118
|
+
"Un anuncio admite como mucho {max} fotos",
|
|
119
|
+
"listings.compose.details": "Detalles",
|
|
120
|
+
"listings.compose.details_loading": "Cargando lo que pide esta categoría…",
|
|
121
|
+
"listings.compose.details_failed":
|
|
122
|
+
"No pudimos cargar lo que pide esta categoría",
|
|
123
|
+
"listings.compose.details_empty": "Esta categoría no pide más detalles",
|
|
124
|
+
"listings.compose.countable": "Vendo un artículo contable",
|
|
125
|
+
"listings.compose.stock": "Cuántas unidades",
|
|
126
|
+
"listings.compose.auto_republish": "Volver a publicar cuando caduque",
|
|
127
|
+
"listings.compose.save": "Guardar borrador",
|
|
128
|
+
"listings.compose.saving": "Guardando…",
|
|
129
|
+
"listings.compose.saved": "Borrador guardado",
|
|
130
|
+
"listings.compose.publish": "Publicar",
|
|
131
|
+
"listings.compose.republish": "Enviar los cambios",
|
|
132
|
+
"listings.compose.publishing": "Enviando…",
|
|
133
|
+
"listings.compose.published_first":
|
|
134
|
+
"Enviado a revisión. Saldrá a la venta cuando un moderador lo apruebe.",
|
|
135
|
+
"listings.compose.published_live":
|
|
136
|
+
"Cambios enviados. Tu anuncio sigue publicado mientras los revisamos.",
|
|
137
|
+
"listings.compose.invalid_summary":
|
|
138
|
+
"Antes de enviarlo, revisa estos detalles: {count}",
|
|
139
|
+
|
|
140
|
+
"listings.compose.blocked.no_category":
|
|
141
|
+
"Elige una categoría — el resto del formulario depende de ella",
|
|
142
|
+
"listings.compose.blocked.unsupported_type":
|
|
143
|
+
"Esta categoría pide un tipo de detalle que la aplicación todavía no sabe mostrar ({types}), así que aquí no se puede rellenar",
|
|
144
|
+
"listings.compose.blocked.photos_pending":
|
|
145
|
+
"Espera a que terminen de subirse las fotos",
|
|
146
|
+
"listings.compose.blocked.no_draft": "El borrador todavía no está creado",
|
|
147
|
+
"listings.compose.blocked.busy":
|
|
148
|
+
"Un momento — el último cambio se está guardando",
|
|
149
|
+
"listings.compose.blocked.mirror": "Corrige primero los campos marcados",
|
|
150
|
+
"listings.compose.blocked.details_unavailable":
|
|
151
|
+
"No pudimos cargar lo que pide esta categoría, así que no podemos revisar el formulario",
|
|
152
|
+
|
|
153
|
+
"listings.mine.title": "Mis anuncios",
|
|
154
|
+
"listings.mine.tab.active": "Activos",
|
|
155
|
+
"listings.mine.tab.drafts": "Borradores",
|
|
156
|
+
"listings.mine.tab.archived": "Archivo",
|
|
157
|
+
"listings.mine.loading": "Cargando tus anuncios…",
|
|
158
|
+
"listings.mine.load_failed": "No pudimos cargar tus anuncios",
|
|
159
|
+
"listings.mine.empty": "Aquí todavía no hay nada",
|
|
160
|
+
"listings.mine.retry": "Reintentar",
|
|
161
|
+
"listings.mine.counters_failed": "No pudimos contar tus anuncios",
|
|
162
|
+
"listings.mine.source_missing":
|
|
163
|
+
"Esta aplicación todavía no puede enumerar tus anuncios: el servicio de anuncios no tiene una lista limitada al propietario. Los contadores de abajo sí son reales.",
|
|
164
|
+
"listings.mine.live_under_review": "Publicado, cambios en revisión",
|
|
165
|
+
"listings.mine.edit": "Editar",
|
|
166
|
+
"listings.mine.archive": "Archivar",
|
|
167
|
+
"listings.mine.complete": "Marcar como vendido",
|
|
168
|
+
"listings.mine.delete": "Borrar",
|
|
169
|
+
|
|
170
|
+
"listings.favorites.title": "Favoritos",
|
|
171
|
+
"listings.favorites.loading": "Cargando tus favoritos…",
|
|
172
|
+
"listings.favorites.load_failed": "No pudimos cargar tus favoritos",
|
|
173
|
+
"listings.favorites.empty": "Todavía no has guardado nada",
|
|
174
|
+
|
|
175
|
+
"listings.blocked.sign_in": "Inicia sesión para hacer esto",
|
|
176
|
+
"listings.blocked.guest":
|
|
177
|
+
"Esta cuenta todavía no puede hacerlo — termina de configurarla primero",
|
|
178
|
+
"listings.blocked.mandate_unknown":
|
|
179
|
+
"No pudimos comprobar tu cuenta, así que no adivinamos si puedes hacerlo",
|
|
180
|
+
"listings.blocked.transition":
|
|
181
|
+
"Un anuncio en estado «{from_status}» no se puede mover así",
|
|
182
|
+
"listings.blocked.delete_active":
|
|
183
|
+
"Archívalo primero — un anuncio a la venta no se puede borrar",
|
|
184
|
+
"listings.blocked.in_flight": "Un momento — eso ya está en marcha",
|
|
185
|
+
|
|
186
|
+
"listings.page.prev": "Anterior",
|
|
187
|
+
"listings.page.next": "Siguiente",
|
|
188
|
+
|
|
189
|
+
"listings.nav.detail": "Anuncio",
|
|
190
|
+
"listings.nav.compose": "Poner un anuncio",
|
|
191
|
+
"listings.nav.mine": "Mis anuncios",
|
|
192
|
+
"listings.nav.favorites": "Favoritos",
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/** Register the Spanish bundle into a core i18n engine. */
|
|
196
|
+
export function registerListingsI18nEs(i18n: I18nEngine): void {
|
|
197
|
+
i18n.registerBundle("es", listingsI18nBundleEs);
|
|
198
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/gen-errors.mjs — do not edit by hand.
|
|
2
|
+
// Source: stapel-auth canonical errors.json (backend codegen artifact).
|
|
3
|
+
// Regenerate: pnpm gen:errors · Drift gate: pnpm gen:errors:check
|
|
4
|
+
// Locale source: backend translations/errors.es.json (locale catalog
|
|
5
|
+
// beside the canonical errors.json — i18n-shipping.md §1).
|
|
6
|
+
import type { ListingsErrorCode } from "./errors.gen.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `es` texts for the backend error codes this catalog carries.
|
|
10
|
+
*
|
|
11
|
+
* PARTIAL, and deliberately typed to say so: 21 key(s) owned by
|
|
12
|
+
* stapel_attributes, stapel_listings are absent, because that owner ships no locale catalog
|
|
13
|
+
* (ERRORS_LOCALE_EXEMPT_OWNERS). English for them still comes from the registry
|
|
14
|
+
* artifact via the en bundle; the pair layers its own authored `es`
|
|
15
|
+
* strings over this one until upstream ships translations. `Partial` is what
|
|
16
|
+
* makes the gap visible to TypeScript instead of a silent English fallback.
|
|
17
|
+
*
|
|
18
|
+
* Import from the pair's `./i18n/es` subpath, NOT the main entry, so
|
|
19
|
+
* the locale stays out of hosts that don't ship it.
|
|
20
|
+
*/
|
|
21
|
+
export const listingsErrorBundleEs: Partial<Record<ListingsErrorCode, string>> = {
|
|
22
|
+
"error.400.bad_request": "Solicitud incorrecta",
|
|
23
|
+
"error.400.captcha_invalid": "La verificación del captcha ha fallado. Inténtalo de nuevo.",
|
|
24
|
+
"error.400.captcha_required": "Se requiere el token del captcha.",
|
|
25
|
+
"error.400.expected_list": "Se esperaba una lista de elementos",
|
|
26
|
+
"error.400.field.blank": "{field} no puede estar vacío",
|
|
27
|
+
"error.400.field.does_not_exist": "{field} no existe",
|
|
28
|
+
"error.400.field.invalid": "{field} no es válido",
|
|
29
|
+
"error.400.field.invalid_choice": "{field} no es una opción válida",
|
|
30
|
+
"error.400.field.max_length": "{field} debe tener como máximo {max_length} caracteres",
|
|
31
|
+
"error.400.field.max_value": "{field} debe ser como máximo {max_value}",
|
|
32
|
+
"error.400.field.min_length": "{field} debe tener al menos {min_length} caracteres",
|
|
33
|
+
"error.400.field.min_value": "{field} debe ser como mínimo {min_value}",
|
|
34
|
+
"error.400.field.null": "{field} no puede ser nulo",
|
|
35
|
+
"error.400.field.required": "{field} es obligatorio",
|
|
36
|
+
"error.400.field.unique": "{field} debe ser único",
|
|
37
|
+
"error.400.invalid_ad_id": "ID de anuncio no válido",
|
|
38
|
+
"error.400.validation_error": "Error de validación",
|
|
39
|
+
"error.400.verification_failed": "La verificación ha fallado",
|
|
40
|
+
"error.400.verification_invalid_factor": "Este factor de verificación no está disponible",
|
|
41
|
+
"error.401.unauthorized": "Se requiere autenticación",
|
|
42
|
+
"error.402.payment_required": "Se requiere pago",
|
|
43
|
+
"error.403.forbidden": "No tienes permiso para realizar esta acción",
|
|
44
|
+
"error.403.network_blocked": "No se permiten solicitudes desde esta red.",
|
|
45
|
+
"error.403.verification_enrollment_required": "Es necesario registrar un factor de verificación.",
|
|
46
|
+
"error.403.verification_required": "Se requiere verificación adicional",
|
|
47
|
+
"error.404.ad_not_found": "Anuncio no encontrado",
|
|
48
|
+
"error.404.not_found": "Recurso solicitado no encontrado",
|
|
49
|
+
"error.404.verification_challenge_not_found": "Desafío de verificación no encontrado o caducado",
|
|
50
|
+
"error.405.method_not_allowed": "Método no permitido",
|
|
51
|
+
"error.406.not_acceptable": "No aceptable",
|
|
52
|
+
"error.408.request_timeout": "Tiempo de espera de la solicitud agotado",
|
|
53
|
+
"error.409.conflict": "El recurso ya existe",
|
|
54
|
+
"error.410.gone": "El recurso se ha eliminado permanentemente",
|
|
55
|
+
"error.413.payload_too_large": "El cuerpo de la solicitud es demasiado grande",
|
|
56
|
+
"error.415.unsupported_media_type": "Tipo de contenido no compatible",
|
|
57
|
+
"error.422.unprocessable_entity": "Entidad no procesable",
|
|
58
|
+
"error.423.locked": "El recurso está bloqueado",
|
|
59
|
+
"error.423.verification_locked": "Demasiados intentos fallidos — verificación bloqueada",
|
|
60
|
+
"error.429.rate_limit": "Demasiados intentos. Inténtalo de nuevo en {retry_after_minutes} minutos.",
|
|
61
|
+
"error.429.too_many_requests": "Demasiadas solicitudes. Inténtalo de nuevo más tarde.",
|
|
62
|
+
"error.500.internal": "Algo salió mal",
|
|
63
|
+
"error.503.mandate_unavailable": "No se puede verificar el mandato del espacio de trabajo",
|
|
64
|
+
};
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/gen-errors.mjs — do not edit by hand.
|
|
2
|
+
// Source: stapel-auth canonical errors.json (backend codegen artifact).
|
|
3
|
+
// Regenerate: pnpm gen:errors · Drift gate: pnpm gen:errors:check
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Remediation vocabulary (frontend-core-architecture §2.5). Declared by the
|
|
7
|
+
* backend on the error registry and consumed verbatim from its `errors.json`
|
|
8
|
+
* artifact. A host maps it to UX — retryable → "try again"; `wait_and_retry` →
|
|
9
|
+
* timer from `params.retry_after_minutes`; `verify` → the step-up seam;
|
|
10
|
+
* `fix_input` → highlight the offending field.
|
|
11
|
+
*/
|
|
12
|
+
export type Remediation =
|
|
13
|
+
| "retry"
|
|
14
|
+
| "wait_and_retry"
|
|
15
|
+
| "reauthenticate"
|
|
16
|
+
| "verify"
|
|
17
|
+
| "fix_input"
|
|
18
|
+
| "contact_support"
|
|
19
|
+
| "bug";
|
|
20
|
+
|
|
21
|
+
export interface ListingsErrorSpec {
|
|
22
|
+
/** HTTP status the backend raises this key with. */
|
|
23
|
+
readonly status: number;
|
|
24
|
+
/** `{param}` interpolation slots present in the message. */
|
|
25
|
+
readonly params: readonly string[];
|
|
26
|
+
/** Remediation hint declared by the backend (see {@link Remediation}). */
|
|
27
|
+
readonly remediation: Remediation;
|
|
28
|
+
/** English fallback (source: stapel-auth errors.json). */
|
|
29
|
+
readonly en: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The LISTINGS_ERRORS map — every `error.*` key stapel-auth can raise, keyed by its
|
|
34
|
+
* canonical code. The single source of truth behind the en fallback bundle, the
|
|
35
|
+
* remediation lookup, and the manifest `errors` block.
|
|
36
|
+
*/
|
|
37
|
+
export const LISTINGS_ERRORS = {
|
|
38
|
+
"error.400.bad_request": { status: 400, params: [], remediation: "fix_input", en: "Bad request" },
|
|
39
|
+
"error.400.captcha_invalid": { status: 400, params: [], remediation: "retry", en: "Captcha verification failed. Please try again." },
|
|
40
|
+
"error.400.captcha_required": { status: 400, params: [], remediation: "retry", en: "Captcha token is required." },
|
|
41
|
+
"error.400.category_required": { status: 400, params: [], remediation: "fix_input", en: "Category is required" },
|
|
42
|
+
"error.400.description_too_long": { status: 400, params: ["max_length"], remediation: "fix_input", en: "Description must be at most {max_length} characters" },
|
|
43
|
+
"error.400.description_too_short": { status: 400, params: ["min_length"], remediation: "fix_input", en: "Description must be at least {min_length} characters" },
|
|
44
|
+
"error.400.expected_list": { status: 400, params: [], remediation: "fix_input", en: "Expected a list of items" },
|
|
45
|
+
"error.400.feature_above_maximum": { status: 400, params: ["feature"], remediation: "fix_input", en: "Value is above maximum for {feature}" },
|
|
46
|
+
"error.400.feature_below_minimum": { status: 400, params: ["feature"], remediation: "fix_input", en: "Value is below minimum for {feature}" },
|
|
47
|
+
"error.400.feature_invalid_config": { status: 400, params: ["feature"], remediation: "fix_input", en: "Invalid config for {feature}" },
|
|
48
|
+
"error.400.feature_invalid_format": { status: 400, params: ["feature"], remediation: "fix_input", en: "Invalid format for {feature}" },
|
|
49
|
+
"error.400.feature_invalid_type": { status: 400, params: ["feature"], remediation: "fix_input", en: "Invalid type for {feature}" },
|
|
50
|
+
"error.400.feature_mandatory_missing": { status: 400, params: ["feature"], remediation: "fix_input", en: "Mandatory feature {feature} is required" },
|
|
51
|
+
"error.400.feature_not_allowed": { status: 400, params: ["feature"], remediation: "fix_input", en: "Feature {feature} is not allowed here" },
|
|
52
|
+
"error.400.feature_not_in_options": { status: 400, params: ["feature"], remediation: "fix_input", en: "Value is not in allowed options for {feature}" },
|
|
53
|
+
"error.400.feature_unknown": { status: 400, params: ["feature"], remediation: "fix_input", en: "Unknown feature {feature}" },
|
|
54
|
+
"error.400.feature_unknown_type": { status: 400, params: ["feature"], remediation: "fix_input", en: "Unknown feature type for {feature}" },
|
|
55
|
+
"error.400.field.blank": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} may not be blank" },
|
|
56
|
+
"error.400.field.does_not_exist": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} does not exist" },
|
|
57
|
+
"error.400.field.invalid": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} is invalid" },
|
|
58
|
+
"error.400.field.invalid_choice": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} is not a valid choice" },
|
|
59
|
+
"error.400.field.max_length": { status: 400, params: ["field","max_length"], remediation: "fix_input", en: "{field} must be at most {max_length} characters" },
|
|
60
|
+
"error.400.field.max_value": { status: 400, params: ["field","max_value"], remediation: "fix_input", en: "{field} must be at most {max_value}" },
|
|
61
|
+
"error.400.field.min_length": { status: 400, params: ["field","min_length"], remediation: "fix_input", en: "{field} must be at least {min_length} characters" },
|
|
62
|
+
"error.400.field.min_value": { status: 400, params: ["field","min_value"], remediation: "fix_input", en: "{field} must be at least {min_value}" },
|
|
63
|
+
"error.400.field.null": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} may not be null" },
|
|
64
|
+
"error.400.field.required": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} is required" },
|
|
65
|
+
"error.400.field.unique": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} must be unique" },
|
|
66
|
+
"error.400.image_required": { status: 400, params: [], remediation: "fix_input", en: "At least one image is required to publish" },
|
|
67
|
+
"error.400.invalid_ad_id": { status: 400, params: [], remediation: "fix_input", en: "Invalid advertisement ID" },
|
|
68
|
+
"error.400.listing_feature_not_allowed": { status: 400, params: ["feature"], remediation: "fix_input", en: "Feature '{feature}' is not allowed for this category" },
|
|
69
|
+
"error.400.publish_validation_failed": { status: 400, params: [], remediation: "fix_input", en: "Listing validation failed" },
|
|
70
|
+
"error.400.validation_error": { status: 400, params: [], remediation: "fix_input", en: "Validation error" },
|
|
71
|
+
"error.400.verification_failed": { status: 400, params: [], remediation: "verify", en: "Verification failed" },
|
|
72
|
+
"error.400.verification_invalid_factor": { status: 400, params: [], remediation: "verify", en: "This verification factor is not available" },
|
|
73
|
+
"error.401.unauthorized": { status: 401, params: [], remediation: "reauthenticate", en: "Authentication required" },
|
|
74
|
+
"error.402.payment_required": { status: 402, params: [], remediation: "retry", en: "Payment required" },
|
|
75
|
+
"error.403.forbidden": { status: 403, params: [], remediation: "retry", en: "You do not have permission to perform this action" },
|
|
76
|
+
"error.403.listing_not_owner": { status: 403, params: [], remediation: "retry", en: "Not your listing" },
|
|
77
|
+
"error.403.network_blocked": { status: 403, params: [], remediation: "contact_support", en: "Requests from this network are not allowed" },
|
|
78
|
+
"error.403.verification_enrollment_required": { status: 403, params: [], remediation: "verify", en: "Verification factor enrollment required" },
|
|
79
|
+
"error.403.verification_required": { status: 403, params: [], remediation: "verify", en: "Additional verification required" },
|
|
80
|
+
"error.404.ad_not_found": { status: 404, params: [], remediation: "retry", en: "Listing not found" },
|
|
81
|
+
"error.404.listing_not_found": { status: 404, params: [], remediation: "retry", en: "Listing not found" },
|
|
82
|
+
"error.404.not_found": { status: 404, params: [], remediation: "retry", en: "Requested resource not found" },
|
|
83
|
+
"error.404.verification_challenge_not_found": { status: 404, params: [], remediation: "verify", en: "Verification challenge not found or expired" },
|
|
84
|
+
"error.405.method_not_allowed": { status: 405, params: [], remediation: "retry", en: "Method not allowed" },
|
|
85
|
+
"error.406.not_acceptable": { status: 406, params: [], remediation: "retry", en: "Not acceptable" },
|
|
86
|
+
"error.408.request_timeout": { status: 408, params: [], remediation: "retry", en: "Request timeout" },
|
|
87
|
+
"error.409.already_favorited": { status: 409, params: [], remediation: "fix_input", en: "Listing already favorited" },
|
|
88
|
+
"error.409.conflict": { status: 409, params: [], remediation: "fix_input", en: "Resource already exists" },
|
|
89
|
+
"error.409.invalid_listing_transition": { status: 409, params: ["from_status"], remediation: "fix_input", en: "Invalid status transition for {from_status}" },
|
|
90
|
+
"error.409.listing_cannot_delete_active": { status: 409, params: [], remediation: "fix_input", en: "Cannot delete an active listing. Archive it first." },
|
|
91
|
+
"error.410.gone": { status: 410, params: [], remediation: "retry", en: "Resource has been permanently removed" },
|
|
92
|
+
"error.413.payload_too_large": { status: 413, params: [], remediation: "retry", en: "Request body is too large" },
|
|
93
|
+
"error.415.unsupported_media_type": { status: 415, params: [], remediation: "retry", en: "Unsupported media type" },
|
|
94
|
+
"error.422.unprocessable_entity": { status: 422, params: [], remediation: "wait_and_retry", en: "Unprocessable entity" },
|
|
95
|
+
"error.423.locked": { status: 423, params: [], remediation: "wait_and_retry", en: "Resource is locked" },
|
|
96
|
+
"error.423.verification_locked": { status: 423, params: [], remediation: "wait_and_retry", en: "Too many failed attempts — verification locked" },
|
|
97
|
+
"error.429.rate_limit": { status: 429, params: ["retry_after_minutes"], remediation: "wait_and_retry", en: "Too many attempts. Try again in {retry_after_minutes} minutes." },
|
|
98
|
+
"error.429.too_many_requests": { status: 429, params: [], remediation: "wait_and_retry", en: "Too many requests. Please try again later." },
|
|
99
|
+
"error.500.internal": { status: 500, params: [], remediation: "contact_support", en: "Something went wrong" },
|
|
100
|
+
"error.503.mandate_unavailable": { status: 503, params: [], remediation: "retry", en: "Cannot verify workspace mandate right now" },
|
|
101
|
+
} as const;
|
|
102
|
+
|
|
103
|
+
export type ListingsErrorCode = keyof typeof LISTINGS_ERRORS;
|
|
104
|
+
|
|
105
|
+
/** Every backend error code this module can surface, sorted. */
|
|
106
|
+
export const LISTINGS_ERROR_CODES: readonly ListingsErrorCode[] = [
|
|
107
|
+
"error.400.bad_request",
|
|
108
|
+
"error.400.captcha_invalid",
|
|
109
|
+
"error.400.captcha_required",
|
|
110
|
+
"error.400.category_required",
|
|
111
|
+
"error.400.description_too_long",
|
|
112
|
+
"error.400.description_too_short",
|
|
113
|
+
"error.400.expected_list",
|
|
114
|
+
"error.400.feature_above_maximum",
|
|
115
|
+
"error.400.feature_below_minimum",
|
|
116
|
+
"error.400.feature_invalid_config",
|
|
117
|
+
"error.400.feature_invalid_format",
|
|
118
|
+
"error.400.feature_invalid_type",
|
|
119
|
+
"error.400.feature_mandatory_missing",
|
|
120
|
+
"error.400.feature_not_allowed",
|
|
121
|
+
"error.400.feature_not_in_options",
|
|
122
|
+
"error.400.feature_unknown",
|
|
123
|
+
"error.400.feature_unknown_type",
|
|
124
|
+
"error.400.field.blank",
|
|
125
|
+
"error.400.field.does_not_exist",
|
|
126
|
+
"error.400.field.invalid",
|
|
127
|
+
"error.400.field.invalid_choice",
|
|
128
|
+
"error.400.field.max_length",
|
|
129
|
+
"error.400.field.max_value",
|
|
130
|
+
"error.400.field.min_length",
|
|
131
|
+
"error.400.field.min_value",
|
|
132
|
+
"error.400.field.null",
|
|
133
|
+
"error.400.field.required",
|
|
134
|
+
"error.400.field.unique",
|
|
135
|
+
"error.400.image_required",
|
|
136
|
+
"error.400.invalid_ad_id",
|
|
137
|
+
"error.400.listing_feature_not_allowed",
|
|
138
|
+
"error.400.publish_validation_failed",
|
|
139
|
+
"error.400.validation_error",
|
|
140
|
+
"error.400.verification_failed",
|
|
141
|
+
"error.400.verification_invalid_factor",
|
|
142
|
+
"error.401.unauthorized",
|
|
143
|
+
"error.402.payment_required",
|
|
144
|
+
"error.403.forbidden",
|
|
145
|
+
"error.403.listing_not_owner",
|
|
146
|
+
"error.403.network_blocked",
|
|
147
|
+
"error.403.verification_enrollment_required",
|
|
148
|
+
"error.403.verification_required",
|
|
149
|
+
"error.404.ad_not_found",
|
|
150
|
+
"error.404.listing_not_found",
|
|
151
|
+
"error.404.not_found",
|
|
152
|
+
"error.404.verification_challenge_not_found",
|
|
153
|
+
"error.405.method_not_allowed",
|
|
154
|
+
"error.406.not_acceptable",
|
|
155
|
+
"error.408.request_timeout",
|
|
156
|
+
"error.409.already_favorited",
|
|
157
|
+
"error.409.conflict",
|
|
158
|
+
"error.409.invalid_listing_transition",
|
|
159
|
+
"error.409.listing_cannot_delete_active",
|
|
160
|
+
"error.410.gone",
|
|
161
|
+
"error.413.payload_too_large",
|
|
162
|
+
"error.415.unsupported_media_type",
|
|
163
|
+
"error.422.unprocessable_entity",
|
|
164
|
+
"error.423.locked",
|
|
165
|
+
"error.423.verification_locked",
|
|
166
|
+
"error.429.rate_limit",
|
|
167
|
+
"error.429.too_many_requests",
|
|
168
|
+
"error.500.internal",
|
|
169
|
+
"error.503.mandate_unavailable",
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* English fallback bundle — one string per backend key, so a `StapelApiError.code`
|
|
174
|
+
* never renders as a raw key. Merged UNDER the hand-polished UI copy in
|
|
175
|
+
* {@link authI18nBundleEn} (polish wins; this guarantees coverage).
|
|
176
|
+
*/
|
|
177
|
+
export const listingsErrorBundleEn: Record<ListingsErrorCode, string> = {
|
|
178
|
+
"error.400.bad_request": "Bad request",
|
|
179
|
+
"error.400.captcha_invalid": "Captcha verification failed. Please try again.",
|
|
180
|
+
"error.400.captcha_required": "Captcha token is required.",
|
|
181
|
+
"error.400.category_required": "Category is required",
|
|
182
|
+
"error.400.description_too_long": "Description must be at most {max_length} characters",
|
|
183
|
+
"error.400.description_too_short": "Description must be at least {min_length} characters",
|
|
184
|
+
"error.400.expected_list": "Expected a list of items",
|
|
185
|
+
"error.400.feature_above_maximum": "Value is above maximum for {feature}",
|
|
186
|
+
"error.400.feature_below_minimum": "Value is below minimum for {feature}",
|
|
187
|
+
"error.400.feature_invalid_config": "Invalid config for {feature}",
|
|
188
|
+
"error.400.feature_invalid_format": "Invalid format for {feature}",
|
|
189
|
+
"error.400.feature_invalid_type": "Invalid type for {feature}",
|
|
190
|
+
"error.400.feature_mandatory_missing": "Mandatory feature {feature} is required",
|
|
191
|
+
"error.400.feature_not_allowed": "Feature {feature} is not allowed here",
|
|
192
|
+
"error.400.feature_not_in_options": "Value is not in allowed options for {feature}",
|
|
193
|
+
"error.400.feature_unknown": "Unknown feature {feature}",
|
|
194
|
+
"error.400.feature_unknown_type": "Unknown feature type for {feature}",
|
|
195
|
+
"error.400.field.blank": "{field} may not be blank",
|
|
196
|
+
"error.400.field.does_not_exist": "{field} does not exist",
|
|
197
|
+
"error.400.field.invalid": "{field} is invalid",
|
|
198
|
+
"error.400.field.invalid_choice": "{field} is not a valid choice",
|
|
199
|
+
"error.400.field.max_length": "{field} must be at most {max_length} characters",
|
|
200
|
+
"error.400.field.max_value": "{field} must be at most {max_value}",
|
|
201
|
+
"error.400.field.min_length": "{field} must be at least {min_length} characters",
|
|
202
|
+
"error.400.field.min_value": "{field} must be at least {min_value}",
|
|
203
|
+
"error.400.field.null": "{field} may not be null",
|
|
204
|
+
"error.400.field.required": "{field} is required",
|
|
205
|
+
"error.400.field.unique": "{field} must be unique",
|
|
206
|
+
"error.400.image_required": "At least one image is required to publish",
|
|
207
|
+
"error.400.invalid_ad_id": "Invalid advertisement ID",
|
|
208
|
+
"error.400.listing_feature_not_allowed": "Feature '{feature}' is not allowed for this category",
|
|
209
|
+
"error.400.publish_validation_failed": "Listing validation failed",
|
|
210
|
+
"error.400.validation_error": "Validation error",
|
|
211
|
+
"error.400.verification_failed": "Verification failed",
|
|
212
|
+
"error.400.verification_invalid_factor": "This verification factor is not available",
|
|
213
|
+
"error.401.unauthorized": "Authentication required",
|
|
214
|
+
"error.402.payment_required": "Payment required",
|
|
215
|
+
"error.403.forbidden": "You do not have permission to perform this action",
|
|
216
|
+
"error.403.listing_not_owner": "Not your listing",
|
|
217
|
+
"error.403.network_blocked": "Requests from this network are not allowed",
|
|
218
|
+
"error.403.verification_enrollment_required": "Verification factor enrollment required",
|
|
219
|
+
"error.403.verification_required": "Additional verification required",
|
|
220
|
+
"error.404.ad_not_found": "Listing not found",
|
|
221
|
+
"error.404.listing_not_found": "Listing not found",
|
|
222
|
+
"error.404.not_found": "Requested resource not found",
|
|
223
|
+
"error.404.verification_challenge_not_found": "Verification challenge not found or expired",
|
|
224
|
+
"error.405.method_not_allowed": "Method not allowed",
|
|
225
|
+
"error.406.not_acceptable": "Not acceptable",
|
|
226
|
+
"error.408.request_timeout": "Request timeout",
|
|
227
|
+
"error.409.already_favorited": "Listing already favorited",
|
|
228
|
+
"error.409.conflict": "Resource already exists",
|
|
229
|
+
"error.409.invalid_listing_transition": "Invalid status transition for {from_status}",
|
|
230
|
+
"error.409.listing_cannot_delete_active": "Cannot delete an active listing. Archive it first.",
|
|
231
|
+
"error.410.gone": "Resource has been permanently removed",
|
|
232
|
+
"error.413.payload_too_large": "Request body is too large",
|
|
233
|
+
"error.415.unsupported_media_type": "Unsupported media type",
|
|
234
|
+
"error.422.unprocessable_entity": "Unprocessable entity",
|
|
235
|
+
"error.423.locked": "Resource is locked",
|
|
236
|
+
"error.423.verification_locked": "Too many failed attempts — verification locked",
|
|
237
|
+
"error.429.rate_limit": "Too many attempts. Try again in {retry_after_minutes} minutes.",
|
|
238
|
+
"error.429.too_many_requests": "Too many requests. Please try again later.",
|
|
239
|
+
"error.500.internal": "Something went wrong",
|
|
240
|
+
"error.503.mandate_unavailable": "Cannot verify workspace mandate right now",
|
|
241
|
+
};
|