runique 2.1.1

A Django-inspired web framework for Rust with ORM, templates, and comprehensive security middleware
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
{
  "forms": {
    "upload_dir_error": "Error al crear el directorio de subida",
    "file_create_error": "Error al crear el archivo",
    "multipart_stream_error": "Error en el stream multipart",
    "file_write_error": "Error al escribir el archivo",
    "required": "Este campo es obligatorio",
    "too_short": "Demasiado corto (mín {})",
    "too_long": "Demasiado largo (máx {})",
    "email_invalid": "Formato de dirección de correo electrónico no válido",
    "url_invalid": "Por favor introduce una URL válida",
    "hash_error": "Error de hash: {}",
    "password_empty": "La contraseña no puede estar vacía",
    "filter_invalid_value": "El filtro static/media recibió un valor no válido ({}) en lugar de una ruta de archivo.",
    "number_invalid": "Número no válido",
    "number_required": "Requerido",
    "integer_required": "Debe ser un número entero",
    "decimal_required": "Debe estar en formato decimal",
    "min_value": "Mín {} requerido",
    "max_value": "Máx {} superado",
    "precision_max": "Precisión máxima {} dígitos después de la coma",
    "precision_min": "Precisión mínima {} dígitos después de la coma",
    "color_invalid": "Color no válido (formato: #RRGGBB o #RGB)",
    "color_no_hash": "El color debe comenzar con #",
    "color_bad_hex": "Contiene caracteres no hexadecimales",
    "slug_invalid": "Slug no válido",
    "slug_no_dash": "El slug no debe comenzar ni terminar con un guion",
    "uuid_invalid": "Formato UUID no válido (esperado: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)",
    "json_invalid": "JSON no válido: {}",
    "ipv4_only": "Solo se aceptan direcciones IPv4",
    "ipv6_only": "Solo se aceptan direcciones IPv6",
    "ip_invalid": "Dirección IP no válida",
    "date_invalid": "Formato de fecha no válido",
    "date_too_old": "Demasiado antiguo (mín: {})",
    "date_too_far": "Demasiado lejano (máx: {})",
    "time_invalid": "Formato de hora no válido",
    "file_required": "Por favor selecciona al menos un archivo",
    "file_extension_blocked": "Archivo '{}' no permitido. Extensiones: {}",
    "finalize_error": "Error al finalizar el campo '{}': {}",
    "template_missing": "Plantilla faltante: {}",
    "render_js_error": "Error al renderizar JS: {}",
    "tera_not_configured": "Tera no configurado",
    "config_not_found": "Configuración no encontrada en las extensiones",
    "hint_slug": "Formato: letras-números-guiones",
    "hint_uuid": "Formato: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "hint_json": "Se requiere un formato JSON válido",
    "hint_ip_v4": "Formato IPv4: 192.168.1.1",
    "hint_ip_v6": "Formato IPv6: 2001:0db8:85a3::8a2e:0370:7334",
    "hint_ip": "Formato IPv4 o IPv6",
    "validation_overflow": "Stack overflow detectado: recursión infinita en la validación",
    "choice_invalid": "Opción no válida",
    "choice_invalid_value": "Opción no válida: {}",
    "select_required": "Por favor selecciona una opción",
    "checkbox_required": "Por favor selecciona al menos una opción",
    "multipart_error": "Error multipart",
    "body_error": "Error al leer el body",
    "aegis_query_error": "Error al analizar la query string: {}",
    "aegis_urlencoded_error": "Error al analizar el body urlencoded: {}",
    "aegis_json_error": "Error al analizar el body JSON: {}",
    "auth_required": "Autenticación requerida",
    "role_insufficient": "Rol insuficiente",
    "time_too_old": "Demasiado temprano (mín: {})",
    "time_too_far": "Demasiado tarde (máx: {})",
    "datetime_too_old": "Demasiado temprano (mín: {})",
    "datetime_too_far": "Demasiado tarde (máx: {})",
    "duration_invalid": "Duración no válida (se espera número de segundos)",
    "duration_too_short": "Duración mínima: {} segundos",
    "duration_too_long": "Duración máxima: {} segundos",
    "file_max_count": "Máximo {} archivos permitidos",
    "file_too_large": "Archivo '{}' demasiado grande ({}MB > {}MB máx)",
    "file_invalid_image": "El archivo '{}' no es una imagen válida",
    "image_too_wide": "La imagen '{}' es demasiado ancha ({}px > {}px)",
    "image_too_tall": "La imagen '{}' es demasiado alta ({}px > {}px)",
    "boolean_required": "Debes aceptar este campo",
    "slug_unicode_invalid": "Solo se permiten letras, números, guiones y guiones bajos",
    "unique_field_taken": "Este {} ya está en uso.",
    "unique_value_taken": "El valor del campo '{}' ya está en uso.",
    "unique_constraint_violated": "Se ha violado una restricción de unicidad.",
    "db_error": "Error de base de datos: {}",
    "text_field_too_large": "Campo de texto demasiado grande (max 1 MB)",
    "upload_too_large": "Archivo demasiado grande (max {}MB)"
  },
  "csrf": {
    "missing": "Token CSRF faltante",
    "invalid": "Token CSRF no válido",
    "invalid_or_missing": "Token CSRF no válido o faltante",
    "forbidden": "Token CSRF no válido",
    "session_write_error": "Error de escritura de sesión"
  },
  "error": {
    "source": "Fuente: {}",
    "AppError": "Error de aplicación",
    "build": "Error de compilación: {}",
    "internal": "Error interno",
    "forbidden": "Acceso prohibido",
    "not_found": "Recurso no encontrado",
    "validation": "Error de validación: {}",
    "database": "Error de base de datos: {}",
    "io": "Error IO: {}",
    "template": "Error de plantilla: {}",
    "custom": "Error personalizado: {}",
    "title": {
      "not_found": "Página no encontrada",
      "forbidden": "Acceso prohibido",
      "validation": "Error de validación",
      "database": "Error de base de datos",
      "template": "Error de renderizado de plantilla",
      "internal": "Error interno del servidor"
    },
    "path_not_found": "La ruta solicitada '{}' no fue encontrada",
    "internal_occurred": "Ocurrió un error interno",
    "context_occurred": "Error AppError ocurrido"
  },
  "title": {
    "template": "Error de plantilla en '{}'"
  },
  "build": {
    "validation_failed": "La validación del build falló: {}",
    "check_failed": "El build falló con {} error(es) de verificación",
    "template_failed": "La carga de la plantilla falló: {}",
    "db_missing": "Se requiere conexión a la base de datos cuando la feature 'orm' está activada",
    "component_not_ready": "El componente '{}' no está listo"
  },
  "middleware": {
    "host_invalid": "Host no válido: '{}' (Hosts permitidos: {})",
    "host_debug": "Host no válido: '{}'. Añádelo a RUNIQUE_ALLOWED_HOSTS.",
    "bad_request": "Solicitud incorrecta"
  },
  "html": {
    "404_title": "404",
    "404_text": "Página no encontrada",
    "500_title": "500",
    "500_text": "Error interno del servidor",
    "500_notice": "Nuestro equipo ha sido notificado y está trabajando en el problema.",
    "429_title": "429",
    "429_text": "Demasiadas solicitudes. Por favor espere un momento antes de intentarlo de nuevo.",
    "back_home": "Volver al inicio",
    "critical_error_title": "Error crítico",
    "critical_error_text": "El sistema de gestión de errores ha encontrado un error.",
    "critical_error_contact": "Esta situación no debería ocurrir nunca. Por favor contacta al administrador del sistema."
  },
  "debug": {
    "stack_trace_title": "Traza de error detallada",
    "stack_trace_tip": "El error más alto (nivel 0) suele ser la causa raíz. Los errores siguientes muestran cómo se propagó el error en el código."
  },
  "flash": {
    "welcome": "Bienvenido {}, ¡tu cuenta ha sido creada!",
    "fix_errors": "Por favor corrige los errores",
    "success_demo": "Este es un mensaje de éxito.",
    "info_demo": "Este es un mensaje informativo.",
    "warning_demo": "Este es un mensaje de advertencia.",
    "error_demo": "Este es un mensaje de error."
  },
  "log": {
    "db_connecting": "Conectando a la base de datos {}...",
    "db_connected": "Base de datos conectada con éxito ({})",
    "db_failed": "Conexión a la base de datos fallida",
    "db_engine": "Motor: {}",
    "template_render_error": "Error de renderizado del template",
    "error_handler": "Error crítico ocurrido",
    "error_handled": "Error gestionado",
    "files_count": "añadir archivos JS al formulario",
    "js_file_skip": "Archivo JS omitido",
    "already_initialized": "Logger ya inicializado"
  },
  "cli": {
    "creating_project": "Creando el proyecto '{}'...",
    "admin_detected": "Admin detectado → iniciando el daemon",
    "add_admin_hint": "Añade .with_admin(...) en tu builder para activar el panel de administración.",
    "daemon_error": "[Daemon] Error: {}",
    "cargo_run_failed": "El servidor de aplicaciones no se inició correctamente (cargo run)",
    "file_not_found": "Archivo no encontrado: {}\\nAsegúrate de estar en la raíz de tu proyecto Runique.",
    "admin_not_found": "Archivo admin no encontrado: {}\\nCrea src/admin.rs con la macro admin!{{}}.",
    "name_empty": "El nombre del proyecto no puede estar vacío",
    "name_invalid": "El nombre del proyecto solo debe contener letras, números, _ o -",
    "name_dash": "El nombre del proyecto no puede comenzar con -",
    "folder_exists": "La carpeta '{}' ya existe",
    "cargo_run_expect": "Error al lanzar cargo run",
    "project_created": "¡Proyecto '{}' creado con éxito!",
    "getting_started": "Para comenzar:",
    "cd_hint": "cd {}",
    "cargo_run_hint": "cargo run"
  },
  "daemon": {
    "modification_detected": "Modificación detectada → regenerando...",
    "unable_read": "No se puede leer: {}",
    "parse_error": "Error de análisis: {}",
    "no_resource": "No hay recursos en admin!{{}} — nada que generar",
    "with_admin_disabled": "with_admin desactivado → daemon detenido",
    "operational": "Daemon operativo → src/admin/generated.rs",
    "generation_error": "Error de generación: {}",
    "watcher_error": "Error del watcher: {}",
    "unable_create": "No se puede crear el watcher: {}",
    "unable_watch": "No se puede monitorear {} : {}"
  },
  "macro": {
    "named_fields_only": "Solo structs con campos nombrados",
    "structs_only": "Solo funciona en structs",
    "forms_field_required": "La struct '{}' debe tener un campo 'Forms'",
    "field_no_name": "Campo sin nombre",
    "model_form_named_only": "DeriveModelForm: solo structs con campos nombrados",
    "model_form_structs_only": "DeriveModelForm: solo structs"
  },
  "parser": {
    "string_expected": "Se esperaba un literal de cadena, encontrado: {}",
    "string_eof": "Se esperaba un literal de cadena, fin del archivo",
    "array_expected": "Se esperaba [...] para los permisos, encontrado: {}",
    "array_eof": "Se esperaba [...] para los permisos, fin del archivo",
    "role_required": "Se requiere al menos un rol en permissions: [...]",
    "punct_expected": "Se esperaba '{}', encontrado: {}",
    "punct_eof": "Se esperaba '{}', fin del archivo",
    "title_required": "admin!: 'title' es obligatorio",
    "permissions_required": "admin!: 'permissions' es obligatorio",
    "list_display_exclude_exclusive": "admin!: 'list_display' y 'list_exclude' son mutuamente excluyentes"
  },
  "TemplateMessage": {
    "debug_info_title": "Información de depuración",
    "debug_field_title": "Título",
    "debug_field_count": "Cantidad de campos",
    "debug_error_count": "Errores",
    "debug_main_message": "Mensaje principal",
    "debug_root_cause": "Causa raíz",
    "debug_details": "Detalles adicionales",
    "debug_request_info": "Información de la solicitud",
    "debug_http_method": "Método HTTP",
    "debug_path": "Ruta",
    "debug_query_params": "Parámetros de consulta",
    "debug_http_headers": "Encabezados HTTP",
    "debug_template_info": "Información del template",
    "debug_template_name": "Nombre del template",
    "debug_error_line": "Línea del error",
    "debug_template_source": "Código fuente del template",
    "debug_available_templates": "Templates disponibles",
    "debug_stack_trace_title": "Traza de error detallada",
    "debug_stack_trace_tip": "El error superior (nivel 0) suele ser la causa raíz. Los errores siguientes muestran cómo se propagó el error en el código.",
    "debug_environment": "Entorno",
    "debug_debug_mode": "Modo debug",
    "debug_enabled": "Activado",
    "debug_disabled": "Desactivado",
    "debug_rust_version": "Versión de Rust",
    "debug_app_version": "Versión de la app",
    "debug_status_code": "Código de estado",
    "debug_header_name": "Nombre",
    "debug_header_value": "Valor"
  },
  "admin": {
    "group": "Grupo",
    "groups": "Grupos",
    "resource": "Recurso",
    "resources": "Recursos",
    "can_create": "Crear",
    "can_read": "Leer",
    "can_update": "Modificar",
    "can_delete": "Eliminar",
    "can_update_own": "Modificar",
    "can_delete_own": "Eliminar",
    "name": "Nombre",
    "username": "Nombre de usuario",
    "email": "Email",
    "staff": "Staff",
    "superuser": "Superusuario",
    "active": "Activo",
    "user": {
      "username_too_short": "El nombre de usuario es demasiado corto (min 3 car.)",
      "invalid_email": "Formato de dirección de correo electrónico no válido"
    },

    "login": {
      "title": "Inicio de sesión",
      "subtitle": "Inicie sesión para acceder al panel de administración",
      "label_username": "Nombre de usuario",
      "label_password": "Contraseña",
      "btn_submit": "Iniciar sesión",
      "error_session": "Error al abrir la sesión.",
      "error_credentials": "Credenciales incorrectas o permisos insuficientes.",
      "error_locked": "Demasiados intentos. Cuenta bloqueada temporalmente. Inténtelo de nuevo en {} segundos."
    },
    "logout": {
      "success": "Sesión cerrada correctamente."
    },
    "access": {
      "no_auth_handler": "No hay ningún controlador de autenticación configurado. Llame a .auth(MyAuth) en AdminConfig.",
      "insufficient_rights": "Permisos insuficientes para acceder a la administración"
    },
    "dashboard": {
      "title": "Panel de control",
      "subtitle": "Resumen de la aplicación",
      "card_resources": "Recursos",
      "th_resource": "Recurso",
      "th_key": "Clave",
      "th_permissions": "Permisos",
      "th_actions": "Acciones",
      "btn_list": "Lista",
      "btn_create": "Crear",
      "empty_title": "No hay recursos registrados",
      "empty_desc": "Declare sus recursos en src/admin.rs con la macro admin!{{}} y luego ejecute runique start"
    },
    "list": {
      "breadcrumb_admin": "Administración",
      "entries_count_one": "entrada",
      "entries_count_many": "entradas",
      "btn_create": "Crear",
      "th_id": "id",
      "th_actions": "Acciones",
      "bool_true": "Sí",
      "bool_false": "No",
      "btn_detail": "Detalle",
      "btn_edit": "Editar",
      "btn_delete": "Eliminar",
      "confirm_delete": "¿Realmente eliminar?",
      "empty_title": "No hay entradas",
      "empty_desc": "Comience creando un elemento.",
      "btn_create_first": "Crear el primero",
      "search_placeholder": "Buscar..."
    },
    "create": {
      "title": "Crear",
      "breadcrumb": "Crear",
      "card_info": "Información",
      "no_fields": "No hay campos disponibles por el momento.",
      "btn_cancel": "Cancelar",
      "btn_submit": "Crear",
      "success": "¡Entrada creada con éxito!"
    },
    "edit": {
      "title": "Editar",
      "breadcrumb": "Editar",
      "card_info": "Información",
      "no_fields": "No hay campos disponibles por el momento.",
      "btn_cancel": "Cancelar",
      "btn_submit": "Guardar",
      "success": "¡Entrada actualizada con éxito!"
    },
    "detail": {
      "title": "Detalle",
      "breadcrumb": "Detalle",
      "entry_label": "Entrada",
      "btn_list": "← Lista",
      "btn_edit": "Editar",
      "btn_delete": "Eliminar",
      "confirm_delete": "¿Eliminar esta entrada?"
    },
    "reset_password": {
      "btn": "Restablecer contraseña",
      "success_email": "Reset link sent to {}.",
      "success_link": "Reset link (mailer not configured): {}",
      "error_no_email": "No email field found for this user.",
      "error_send": "Error sending email: {}",
      "email_subject": "Restablece tu contraseña",
      "email_title": "Restablecimiento de contraseña",
      "email_greeting": "Hola,",
      "email_body": "Haz clic en el enlace para restablecer tu contraseña (válido 1 hora):",
      "email_btn": "Restablecer mi contraseña",
      "email_ignore": "Si no solicitaste este restablecimiento, ignora este mensaje."
    },
    "user_created": {
      "email_subject": "Bienvenido — define tu contraseña",
      "email_sent": "Correo de bienvenida enviado a {}.",
      "email_greeting": "Bienvenido,",
      "email_body": "Se ha creado una cuenta para ti. Haz clic en el enlace para definir tu contraseña:",
      "email_btn": "Definir mi contraseña",
      "email_validity": "Este enlace es válido por 1 hora. Si no esperabas este mensaje, ignóralo."
    },
    "delete": {
      "title": "Eliminar",
      "breadcrumb": "Eliminar",
      "heading": "Confirmar eliminación",
      "btn_cancel": "← Cancelar",
      "btn_confirm": "Sí, eliminar permanentemente",
      "warning": {
        "title": "¡Advertencia!",
        "desc": "Está a punto de eliminar la entrada",
        "of": "del recurso",
        "irreversible": "Esta acción es irreversible."
      },
      "success": "¡Entrada eliminada con éxito!",
      "not_found": "Recurso no encontrado."
    },
    "bulk": {
      "no_selection": "Ningún elemento seleccionado.",
      "no_field_selected": "Ningún campo modificado.",
      "delete_success": "elemento(s) eliminado(s).",
      "update_success": "elemento(s) actualizado(s)."
    },
    "base": {
      "title": "Administración",
      "breadcrumb": "Admin",
      "toggle": "Contraer menú",
      "logout_title": "Cerrar sesión"
    },
    "superuser_wizard": {
      "title": "=== Crear superusuario ===",
      "algo_prompt": "[1/5] Algoritmo de hash",
      "algo_argon2": "Argon2 (recomendado)",
      "algo_bcrypt": "Bcrypt",
      "algo_scrypt": "Scrypt",
      "algo_custom": "Proveedor personalizado",
      "provider_path": "Ruta del proveedor",
      "invalid_path": "Ruta inválida.",
      "username_prompt": "[2/5] Nombre de usuario",
      "username_empty": "El nombre de usuario no puede estar vacío.",
      "username_taken": "Ya existe un usuario con este nombre.",
      "email_prompt": "[3/5] Correo electrónico",
      "email_invalid": "Correo electrónico inválido.",
      "email_taken": "Ya existe un usuario con este correo.",
      "password_prompt": "[4/5] Contraseña",
      "password_too_short": "La contraseña debe tener al menos 10 caracteres.",
      "confirm_prompt": "[5/5] Confirmar contraseña",
      "password_mismatch": "Las contraseñas no coinciden. Por favor, inténtelo de nuevo.",
      "review_algo": "  Algoritmo  : {}",
      "review_username": "  Usuario    : {}",
      "review_email": "  Email      : {}",
      "review_password": "  Contraseña : ••••••••",
      "review_action": "Acción",
      "confirm_create": "Confirmar y crear",
      "change_algo": "Cambiar algoritmo",
      "modify_password": "Modificar contraseña",
      "success": "✓ Superusuario creado con éxito!",
      "id_line": "  ID         : {}",
      "username_line": "  Usuario    : {}",
      "email_line": "  Email      : {}"
    },
    "builtin": {
      "invalid_id": "Identificador inválido.",
      "droit_resource_required": "Por favor, seleccione al menos un recurso.",
      "droit_exists": "El permiso \"{}\" ya existe.",
      "groupe_exists": "Ya existe un grupo llamado \"{}\"."
    }
  },
  "makemigrations": {
    "scanning": "Escaneando entidades en '{}'...",
    "found_schema": "-> Esquema encontrado: {}",
    "found_extend": "-> Extensión de tabla de framework encontrada: {}",
    "no_schema": "No se encontraron funciones schema() en '{}'.",
    "schema_count": "{} esquema(s) encontrado(s).",
    "updated_lib": "Actualizado {}",
    "no_changes": "No se detectaron cambios. Su esquema está actualizado.",
    "destructive_detected": "Cambios destructivos detectados:",
    "generated": "Generado: {}",
    "snapshot_updated": "Instantánea actualizada: {}",
    "seaorm_alter": "Migración ALTER de SeaORM generada: {}",
    "batch_up": "Lote up generado: {}",
    "batch_down": "Lote down generado: {}",
    "apply_hint": "Ejecute 'sea-orm-cli migrate up' para aplicar.",
    "extend_unknown_table": "extend!{{}} : \"{}\" no es una tabla de framework conocida. Tablas permitidas: {}. Para extender una tabla de aplicación, modifique su model!{{}} directamente.",
    "extend_invalid_syntax": "extend!{{}} : sintaxis inválida. Esperado: table: \"nombre_tabla\", fields: {{ ... }}",
    "admin_positioned": "AdminTableMigration posicionada después de la migración de '{}'",
    "files_ready": "{} archivo(s) listo(s) para migrar."
  },
  "migrate": {
    "applying": "Aplicando migraciones desde '{}'...",
    "run_hint": "Ejecutar: sea-orm-cli migrate up",
    "complete": "Reversión completa.",
    "complete_up": "Migración completada.",
    "available_for": "Archivos de reversión disponibles para '{}':",
    "rolling_back_batch": "Revirtiendo lote: {}",
    "done": "Hecho: {}",
    "rolling_back": "Revirtiendo: {}",
    "no_applied_dir": "No se encontró el directorio applied/.",
    "by_time_header": "by_time (lotes completos):",
    "none_available": "No hay archivos de reversión disponibles.",
    "usage": "Uso:",
    "usage_files": "runique migration down --files <table/timestamp> [<table/timestamp> ...]",
    "usage_batch": "runique migration down --batch <timestamp>",
    "no_down": "No se encontraron instrucciones down.",
    "executing": "Ejecutando: {}"
  },
  "reset": {
    "forgot_title": "Contraseña olvidada",
    "reset_title": "Nueva contraseña",
    "success_title": "Contraseña restablecida",
    "email_label": "Dirección de correo electrónico",
    "new_password_label": "Nueva contraseña",
    "confirm_label": "Confirmar contraseña",
    "email_mismatch": "La dirección de correo no coincide con el enlace.",
    "invalid_link": "Enlace inválido.",
    "invalid_or_expired": "El enlace de restablecimiento es inválido o ha expirado.",
    "password_min_length": "La contraseña debe tener al menos {} caracteres.",
    "password_mismatch": "Las contraseñas no coinciden.",
    "check_inbox": "Si esta dirección está asociada a una cuenta, recibirá un correo de restablecimiento.",
    "email_subject": "Restablecer contraseña",
    "email_body": "<p>Hola {0},</p><p>Haga clic en el siguiente enlace para restablecer su contraseña (válido durante 1 hora):</p><p><a href=\"{1}\">{2}</a></p>"
  },
  "permission": {
    "col.id": "ID",
    "col.can_create": "Crear",
    "col.can_delete": "Eliminar",
    "col.can_delete_own": "Eliminar (propio)",
    "col.can_read": "Leer",
    "col.can_update": "Modificar",
    "col.can_update_own": "Modificar (propio)",
    "col.groupes": "Grupos",
    "col.resource_key": "Recurso",
    "col.actions": "Acciones"
  }
}