feat: added seo template and prioduct.slug
This commit is contained in:
@@ -0,0 +1,535 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-11-22 21:22+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: shop/api/v1/viewsets.py:72
|
||||||
|
msgid "No se puede borrar el producto"
|
||||||
|
msgstr "No se puede borrar el producto"
|
||||||
|
|
||||||
|
#: shop/filters.py:9
|
||||||
|
msgid "Nombre"
|
||||||
|
msgstr "Nombre"
|
||||||
|
|
||||||
|
#: shop/filters.py:11
|
||||||
|
msgid "Etiquetas"
|
||||||
|
msgstr "Etiquetas"
|
||||||
|
|
||||||
|
#: shop/models.py:11
|
||||||
|
msgid "fecha de creación"
|
||||||
|
msgstr "fecha de creación"
|
||||||
|
|
||||||
|
#: shop/models.py:14
|
||||||
|
msgid "fecha de última modificación"
|
||||||
|
msgstr "fecha de última modificación"
|
||||||
|
|
||||||
|
#: shop/models.py:28
|
||||||
|
msgid "etiqueta"
|
||||||
|
msgstr "etiqueta"
|
||||||
|
|
||||||
|
#: shop/models.py:29 shop/models.py:65
|
||||||
|
msgid "etiquetas"
|
||||||
|
msgstr "etiquetas"
|
||||||
|
|
||||||
|
#: shop/models.py:39
|
||||||
|
msgid "código de referencia"
|
||||||
|
msgstr "código de referencia"
|
||||||
|
|
||||||
|
#: shop/models.py:45 shop/models.py:185 shop/models.py:212 shop/models.py:239
|
||||||
|
msgid "nombre"
|
||||||
|
msgstr "nombre"
|
||||||
|
|
||||||
|
#: shop/models.py:50
|
||||||
|
msgid "descripción"
|
||||||
|
msgstr "descripción"
|
||||||
|
|
||||||
|
#: shop/models.py:56
|
||||||
|
msgid "stock"
|
||||||
|
msgstr "stock"
|
||||||
|
|
||||||
|
#: shop/models.py:59
|
||||||
|
msgid "es un activo digital"
|
||||||
|
msgstr "es un activo digital"
|
||||||
|
|
||||||
|
#: shop/models.py:61
|
||||||
|
msgid "URL de descarga"
|
||||||
|
msgstr "URL de descarga"
|
||||||
|
|
||||||
|
#: shop/models.py:63
|
||||||
|
msgid "imágenes"
|
||||||
|
msgstr "imágenes"
|
||||||
|
|
||||||
|
#: shop/models.py:71 shop/models.py:243
|
||||||
|
msgid "marca"
|
||||||
|
msgstr "marca"
|
||||||
|
|
||||||
|
#: shop/models.py:73
|
||||||
|
msgid "Slug"
|
||||||
|
msgstr "Slug"
|
||||||
|
|
||||||
|
#: shop/models.py:92 shop/models.py:105 shop/models.py:134 shop/models.py:259
|
||||||
|
msgid "producto"
|
||||||
|
msgstr "producto"
|
||||||
|
|
||||||
|
#: shop/models.py:93
|
||||||
|
msgid "productos"
|
||||||
|
msgstr "productos"
|
||||||
|
|
||||||
|
#: shop/models.py:99 shop/models.py:272
|
||||||
|
msgid "precio"
|
||||||
|
msgstr "precio"
|
||||||
|
|
||||||
|
#: shop/models.py:101
|
||||||
|
msgid "fecha"
|
||||||
|
msgstr "fecha"
|
||||||
|
|
||||||
|
#: shop/models.py:111
|
||||||
|
msgid "impuesto aplicable"
|
||||||
|
msgstr "impuesto aplicable"
|
||||||
|
|
||||||
|
#: shop/models.py:113
|
||||||
|
msgid "es el precio actual"
|
||||||
|
msgstr "es el precio actual"
|
||||||
|
|
||||||
|
#: shop/models.py:124 shop/models.py:125
|
||||||
|
msgid "precio de producto"
|
||||||
|
msgstr "precio de producto"
|
||||||
|
|
||||||
|
#: shop/models.py:131
|
||||||
|
msgid "código"
|
||||||
|
msgstr "código"
|
||||||
|
|
||||||
|
#: shop/models.py:140 shop/models.py:267
|
||||||
|
msgid "cantidad"
|
||||||
|
msgstr "cantidad"
|
||||||
|
|
||||||
|
#: shop/models.py:143
|
||||||
|
msgid "fecha de caducidad / consumo preferente"
|
||||||
|
msgstr "fecha de caducidad / consumo preferente"
|
||||||
|
|
||||||
|
#: shop/models.py:150 shop/models.py:233
|
||||||
|
msgid "proveedor"
|
||||||
|
msgstr "proveedor"
|
||||||
|
|
||||||
|
#: shop/models.py:157
|
||||||
|
msgid "remesa de producto"
|
||||||
|
msgstr "remesa de producto"
|
||||||
|
|
||||||
|
#: shop/models.py:158
|
||||||
|
msgid "remesas de productos"
|
||||||
|
msgstr "remesas de productos"
|
||||||
|
|
||||||
|
#: shop/models.py:163
|
||||||
|
msgid "código de impuesto"
|
||||||
|
msgstr "código de impuesto"
|
||||||
|
|
||||||
|
#: shop/models.py:166
|
||||||
|
msgid "valor entero (porcentaje)"
|
||||||
|
msgstr "valor entero (porcentaje)"
|
||||||
|
|
||||||
|
#: shop/models.py:173
|
||||||
|
msgid "impuesto"
|
||||||
|
msgstr "impuesto"
|
||||||
|
|
||||||
|
#: shop/models.py:174 shop/models.py:292
|
||||||
|
msgid "impuestos"
|
||||||
|
msgstr "impuestos"
|
||||||
|
|
||||||
|
#: shop/models.py:183 shop/models.py:210
|
||||||
|
msgid "documento de identidad"
|
||||||
|
msgstr "documento de identidad"
|
||||||
|
|
||||||
|
#: shop/models.py:187
|
||||||
|
msgid "apellidos"
|
||||||
|
msgstr "apellidos"
|
||||||
|
|
||||||
|
#: shop/models.py:189
|
||||||
|
msgid "e-mail"
|
||||||
|
msgstr "e-mail"
|
||||||
|
|
||||||
|
#: shop/models.py:191 shop/models.py:223 shop/models.py:360
|
||||||
|
msgid "dirección"
|
||||||
|
msgstr "dirección"
|
||||||
|
|
||||||
|
#: shop/models.py:192 shop/models.py:224 shop/models.py:363
|
||||||
|
msgid "ciudad"
|
||||||
|
msgstr "ciudad"
|
||||||
|
|
||||||
|
#: shop/models.py:193 shop/models.py:225 shop/models.py:366
|
||||||
|
msgid "región"
|
||||||
|
msgstr "región"
|
||||||
|
|
||||||
|
#: shop/models.py:194 shop/models.py:226 shop/models.py:369
|
||||||
|
msgid "país"
|
||||||
|
msgstr "país"
|
||||||
|
|
||||||
|
#: shop/models.py:195 shop/models.py:227 shop/models.py:372
|
||||||
|
msgid "código postal"
|
||||||
|
msgstr "código postal"
|
||||||
|
|
||||||
|
#: shop/models.py:201 shop/models.py:338
|
||||||
|
msgid "cliente"
|
||||||
|
msgstr "cliente"
|
||||||
|
|
||||||
|
#: shop/models.py:202
|
||||||
|
msgid "clientes"
|
||||||
|
msgstr "clientes"
|
||||||
|
|
||||||
|
#: shop/models.py:214
|
||||||
|
msgid "e-mail de contacto"
|
||||||
|
msgstr "e-mail de contacto"
|
||||||
|
|
||||||
|
#: shop/models.py:220
|
||||||
|
msgid "Teléfono de contacto"
|
||||||
|
msgstr "Teléfono de contacto"
|
||||||
|
|
||||||
|
#: shop/models.py:234
|
||||||
|
msgid "proveedores"
|
||||||
|
msgstr "proveedores"
|
||||||
|
|
||||||
|
#: shop/models.py:244
|
||||||
|
msgid "marcas"
|
||||||
|
msgstr "marcas"
|
||||||
|
|
||||||
|
#: shop/models.py:252 shop/models.py:389
|
||||||
|
msgid "pedido"
|
||||||
|
msgstr "pedido"
|
||||||
|
|
||||||
|
#: shop/models.py:282
|
||||||
|
msgid "total sin impuestos"
|
||||||
|
msgstr "total sin impuestos"
|
||||||
|
|
||||||
|
#: shop/models.py:287
|
||||||
|
msgid "valor de impuestos"
|
||||||
|
msgstr "valor de impuestos"
|
||||||
|
|
||||||
|
#: shop/models.py:297 shop/models.py:333
|
||||||
|
msgid "total"
|
||||||
|
msgstr "total"
|
||||||
|
|
||||||
|
#: shop/models.py:304
|
||||||
|
msgid "línea de pedido"
|
||||||
|
msgstr "línea de pedido"
|
||||||
|
|
||||||
|
#: shop/models.py:305
|
||||||
|
msgid "líneas de pedido"
|
||||||
|
msgstr "líneas de pedido"
|
||||||
|
|
||||||
|
#: shop/models.py:310
|
||||||
|
msgid "pendiente de pago"
|
||||||
|
msgstr "pendiente de pago"
|
||||||
|
|
||||||
|
#: shop/models.py:311
|
||||||
|
msgid "pagado"
|
||||||
|
msgstr "pagado"
|
||||||
|
|
||||||
|
#: shop/models.py:312
|
||||||
|
msgid "preparado"
|
||||||
|
msgstr "preparado"
|
||||||
|
|
||||||
|
#: shop/models.py:313
|
||||||
|
msgid "listo para ser enviado"
|
||||||
|
msgstr"listo para ser enviado"
|
||||||
|
|
||||||
|
#: shop/models.py:314
|
||||||
|
msgid "enviado"
|
||||||
|
msgstr "enviado"
|
||||||
|
|
||||||
|
#: shop/models.py:315
|
||||||
|
msgid "entregado"
|
||||||
|
msgstr "entregado"
|
||||||
|
|
||||||
|
#: shop/models.py:316
|
||||||
|
msgid "finalizado"
|
||||||
|
msgstr "finalizado"
|
||||||
|
|
||||||
|
#: shop/models.py:317
|
||||||
|
msgid "cancelado"
|
||||||
|
msgstr "cancelado"
|
||||||
|
|
||||||
|
#: shop/models.py:318
|
||||||
|
msgid "devuelto"
|
||||||
|
msgstr "devuelto"
|
||||||
|
|
||||||
|
#: shop/models.py:320
|
||||||
|
msgid "UUID"
|
||||||
|
msgstr "UUID"
|
||||||
|
|
||||||
|
#: shop/models.py:323
|
||||||
|
msgid "estado"
|
||||||
|
msgstr "estado"
|
||||||
|
|
||||||
|
#: shop/models.py:330
|
||||||
|
msgid "base imponible"
|
||||||
|
msgstr "base imponible"
|
||||||
|
|
||||||
|
#: shop/models.py:343
|
||||||
|
msgid "dirección de facturación"
|
||||||
|
msgstr "dirección de facturación"
|
||||||
|
|
||||||
|
#: shop/models.py:346
|
||||||
|
msgid "ciudad de facturación"
|
||||||
|
msgstr "ciudad de facturación"
|
||||||
|
|
||||||
|
#: shop/models.py:349
|
||||||
|
msgid "región de facturación"
|
||||||
|
msgstr "región de facturación"
|
||||||
|
|
||||||
|
#: shop/models.py:352
|
||||||
|
msgid "país de facturación"
|
||||||
|
msgstr "país de facturación"
|
||||||
|
|
||||||
|
#: shop/models.py:355
|
||||||
|
msgid "código postal de facturación"
|
||||||
|
msgstr "código postal de facturación"
|
||||||
|
|
||||||
|
#: shop/models.py:375
|
||||||
|
msgid "teléfono de contacto"
|
||||||
|
msgstr "teléfono de contacto"
|
||||||
|
|
||||||
|
#: shop/models.py:390
|
||||||
|
msgid "pedidos"
|
||||||
|
msgstr "pedidos"
|
||||||
|
|
||||||
|
#: shop/templates/shop/index.html:28
|
||||||
|
msgid "Mostrar mas"
|
||||||
|
msgstr "Mostrar mas"
|
||||||
|
|
||||||
|
#: tpv/forms.py:7
|
||||||
|
msgid "Introduce tu e-mail"
|
||||||
|
msgstr "Introduce tu e-mail"
|
||||||
|
|
||||||
|
#: tpv/models.py:14
|
||||||
|
msgid "Pagado"
|
||||||
|
msgstr "Pagado"
|
||||||
|
|
||||||
|
#: tpv/models.py:15
|
||||||
|
msgid "Pendiente"
|
||||||
|
msgstr "Pendiente"
|
||||||
|
|
||||||
|
#: tpv/models.py:16
|
||||||
|
msgid "Error"
|
||||||
|
msgstr "Error"
|
||||||
|
|
||||||
|
#: tpv/models.py:18
|
||||||
|
msgid "Hash"
|
||||||
|
msgstr "Hash"
|
||||||
|
|
||||||
|
#: tpv/models.py:24
|
||||||
|
msgid "Estado"
|
||||||
|
msgstr "Estado"
|
||||||
|
|
||||||
|
#: tpv/models.py:30
|
||||||
|
msgid "Cantidad a pagar"
|
||||||
|
msgstr "Cantidad a pagar"
|
||||||
|
|
||||||
|
#: tpv/models.py:34
|
||||||
|
msgid "Fecha de creación"
|
||||||
|
msgstr "Fecha de creación"
|
||||||
|
|
||||||
|
#: tpv/models.py:37
|
||||||
|
msgid "Fecha de última modificación"
|
||||||
|
msgstr "Fecha de última modificación"
|
||||||
|
|
||||||
|
#: tpv/models.py:41
|
||||||
|
msgid "Email de contacto"
|
||||||
|
msgstr "Email de contacto"
|
||||||
|
|
||||||
|
#: tpv/models.py:48
|
||||||
|
msgid "Observaciones"
|
||||||
|
msgstr "Observaciones"
|
||||||
|
|
||||||
|
#: tpv/models.py:52
|
||||||
|
msgid "Metadata"
|
||||||
|
msgstr "Metadata"
|
||||||
|
|
||||||
|
#: tpv/models.py:71
|
||||||
|
msgid "Pago de pedido en Redsys"
|
||||||
|
msgstr "Pago de pedido en Redsys"
|
||||||
|
|
||||||
|
#: tpv/models.py:72
|
||||||
|
msgid "Pagos de pedidos en Redsys"
|
||||||
|
msgstr "Pagos de pedidos en Redsys"
|
||||||
|
|
||||||
|
#: tpv/settings.py:230 tpv/utils.py:87
|
||||||
|
msgid "Error no tipificado"
|
||||||
|
msgstr "Error no tipificado"
|
||||||
|
|
||||||
|
#: tpv/settings.py:231
|
||||||
|
msgid "Transacción autorizada para devoluciones y confirmaciones"
|
||||||
|
msgstr "Transacción autorizada para devoluciones y confirmaciones"
|
||||||
|
|
||||||
|
#: tpv/settings.py:232
|
||||||
|
msgid "Transacción autorizada para anulaciones"
|
||||||
|
msgstr "Transacción autorizada para anulaciones"
|
||||||
|
|
||||||
|
#: tpv/settings.py:233
|
||||||
|
msgid "Tarjeta caducada"
|
||||||
|
msgstr "Tarjeta caducada"
|
||||||
|
|
||||||
|
#: tpv/settings.py:234
|
||||||
|
msgid "Tarjeta en excepción transitoria o bajo sospecha de fraude"
|
||||||
|
msgstr "Tarjeta en excepción transitoria o bajo sospecha de fraude"
|
||||||
|
|
||||||
|
#: tpv/settings.py:235
|
||||||
|
msgid "Intentos de PIN excedidos"
|
||||||
|
msgstr "Intentos de PIN excedidos"
|
||||||
|
|
||||||
|
#: tpv/settings.py:236
|
||||||
|
msgid "Tarjeta no efectiva"
|
||||||
|
msgstr "Tarjeta no efectiva"
|
||||||
|
|
||||||
|
#: tpv/settings.py:237
|
||||||
|
msgid "Código de seguridad (CVV2/CVC2) incorrecto"
|
||||||
|
msgstr "Código de seguridad (CVV2/CVC2) incorrecto"
|
||||||
|
|
||||||
|
#: tpv/settings.py:238
|
||||||
|
msgid "Denegada, no repetir."
|
||||||
|
msgstr "Denegada, no repetir."
|
||||||
|
|
||||||
|
#: tpv/settings.py:239
|
||||||
|
msgid "Denegada, no repetir sin actualizar datos de tarjeta."
|
||||||
|
msgstr "Denegada, no repetir sin actualizar datos de tarjeta."
|
||||||
|
|
||||||
|
#: tpv/settings.py:240
|
||||||
|
msgid "Denegada, no repetir antes de 72 horas."
|
||||||
|
msgstr "Denegada, no repetir antes de 72 horas."
|
||||||
|
|
||||||
|
#: tpv/settings.py:241
|
||||||
|
msgid "Tarjeta ajena al servicio"
|
||||||
|
msgstr "Tarjeta ajena al servicio"
|
||||||
|
|
||||||
|
#: tpv/settings.py:242
|
||||||
|
msgid "Error en la autenticación del titular"
|
||||||
|
msgstr "Error en la autenticación del titular"
|
||||||
|
|
||||||
|
#: tpv/settings.py:243
|
||||||
|
msgid "Denegación del emisor sin especificar motivo"
|
||||||
|
msgstr "Denegación del emisor sin especificar motivo"
|
||||||
|
|
||||||
|
#: tpv/settings.py:244
|
||||||
|
msgid "Fecha de caducidad errónea"
|
||||||
|
msgstr "Fecha de caducidad errónea"
|
||||||
|
|
||||||
|
#: tpv/settings.py:245
|
||||||
|
msgid "Requiere autenticación SCA"
|
||||||
|
msgstr "Requiere autenticación SCA"
|
||||||
|
|
||||||
|
#: tpv/settings.py:247
|
||||||
|
msgid ""
|
||||||
|
"Tarjeta en excepción transitoria o bajo sospecha de fraude con retirada de "
|
||||||
|
"tarjeta"
|
||||||
|
msgstr ""
|
||||||
|
"Tarjeta en excepción transitoria o bajo sospecha de fraude con retirada de "
|
||||||
|
"tarjeta"
|
||||||
|
|
||||||
|
#: tpv/settings.py:249
|
||||||
|
msgid "Comercio no registrado en FUC"
|
||||||
|
msgstr "Comercio no registrado en FUC"
|
||||||
|
|
||||||
|
#: tpv/settings.py:250
|
||||||
|
msgid "Error de sistema"
|
||||||
|
msgstr "Error de sistema"
|
||||||
|
|
||||||
|
#: tpv/settings.py:251
|
||||||
|
msgid "Pedido repetido"
|
||||||
|
msgstr "Pedido repetido"
|
||||||
|
|
||||||
|
#: tpv/settings.py:252
|
||||||
|
msgid "Sesión Incorrecta"
|
||||||
|
msgstr "Sesión Incorrecta"
|
||||||
|
|
||||||
|
#: tpv/settings.py:253
|
||||||
|
msgid "Operación de devolución no permitida"
|
||||||
|
msgstr "Operación de devolución no permitida"
|
||||||
|
|
||||||
|
#: tpv/settings.py:254 tpv/settings.py:255
|
||||||
|
msgid "Emisor no disponible"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tpv/settings.py:256
|
||||||
|
msgid "Número de posiciones de la tarjeta incorrecto"
|
||||||
|
msgstr "Número de posiciones de la tarjeta incorrecto"
|
||||||
|
|
||||||
|
#: tpv/settings.py:257
|
||||||
|
msgid "Tipo de operación no permitida para esa tarjeta"
|
||||||
|
msgstr "Tipo de operación no permitida para esa tarjeta"
|
||||||
|
|
||||||
|
#: tpv/settings.py:258
|
||||||
|
msgid "Tarjeta no existente"
|
||||||
|
msgstr "Tarjeta no existente"
|
||||||
|
|
||||||
|
#: tpv/settings.py:259
|
||||||
|
msgid "Rechazo servidores internacionales"
|
||||||
|
msgstr "Rechazo servidores internacionales"
|
||||||
|
|
||||||
|
#: tpv/settings.py:260
|
||||||
|
msgid "Comercio con titular seguro y titular sin clave de compra segura"
|
||||||
|
msgstr "Comercio con titular seguro y titular sin clave de compra segura"
|
||||||
|
|
||||||
|
#: tpv/settings.py:261
|
||||||
|
msgid "El comercio no permite op. seguras por entrada /operaciones"
|
||||||
|
msgstr "El comercio no permite op. seguras por entrada /operaciones"
|
||||||
|
|
||||||
|
#: tpv/settings.py:262
|
||||||
|
msgid "Tarjeta no cumple el check-digit"
|
||||||
|
msgstr "Tarjeta no cumple el check-digit"
|
||||||
|
|
||||||
|
#: tpv/settings.py:263
|
||||||
|
msgid "El comercio no puede realizar preautorizaciones"
|
||||||
|
msgstr "El comercio no puede realizar preautorizaciones"
|
||||||
|
|
||||||
|
#: tpv/settings.py:264
|
||||||
|
msgid "Esta tarjeta no permite operativa de preautorizaciones"
|
||||||
|
msgstr "Esta tarjeta no permite operativa de preautorizaciones"
|
||||||
|
|
||||||
|
#: tpv/settings.py:266
|
||||||
|
msgid ""
|
||||||
|
"Operación detenida por superar el control de restricciones en la entrada al "
|
||||||
|
"SIS"
|
||||||
|
msgstr ""
|
||||||
|
"Operación detenida por superar el control de restricciones en la entrada al "
|
||||||
|
"SIS"
|
||||||
|
|
||||||
|
#: tpv/settings.py:268
|
||||||
|
msgid "A petición del usuario se ha cancelado el pago"
|
||||||
|
msgstr "A petición del usuario se ha cancelado el pago"
|
||||||
|
|
||||||
|
#: tpv/settings.py:269
|
||||||
|
msgid "Se está procesando otra transacción en SIS con la misma tarjeta"
|
||||||
|
msgstr "Se está procesando otra transacción en SIS con la misma tarjeta"
|
||||||
|
|
||||||
|
#: tpv/settings.py:270
|
||||||
|
msgid "Operación en proceso de solicitud de datos de tarjeta"
|
||||||
|
msgstr "Operación en proceso de solicitud de datos de tarjeta"
|
||||||
|
|
||||||
|
#: tpv/settings.py:271
|
||||||
|
msgid "Operación que ha sido redirigida al emisor a autenticar"
|
||||||
|
msgstr "Operación que ha sido redirigida al emisor a autenticar"
|
||||||
|
|
||||||
|
#: tpv/utils.py:75
|
||||||
|
msgid "No se ha recibido ningún valor para Ds_MerchantParameters"
|
||||||
|
msgstr "No se ha recibido ningún valor para Ds_MerchantParameters"
|
||||||
|
|
||||||
|
#: tpv/utils.py:89
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "No se ha realizado el pago. Motivo: {reason}"
|
||||||
|
msgstr "No se ha realizado el pago. Motivo: {reason}"
|
||||||
|
|
||||||
|
#: users/forms/login.py:18
|
||||||
|
msgid "Password"
|
||||||
|
msgstr "Contraseña"
|
||||||
+1
-1
@@ -5,7 +5,7 @@ django-cors-headers==3.13.0
|
|||||||
django-cryptography==1.1
|
django-cryptography==1.1
|
||||||
django-debug-toolbar==4.4.6
|
django-debug-toolbar==4.4.6
|
||||||
django-extensions==3.2.0
|
django-extensions==3.2.0
|
||||||
django-filter==23.1
|
django-filter==24.3
|
||||||
django-environ==0.10.0
|
django-environ==0.10.0
|
||||||
django-watchman==1.3.0
|
django-watchman==1.3.0
|
||||||
django-silk==5.1.0
|
django-silk==5.1.0
|
||||||
|
|||||||
+7
-1
@@ -1,6 +1,6 @@
|
|||||||
import django_filters
|
import django_filters
|
||||||
from django.utils.text import gettext_lazy as _
|
from django.utils.text import gettext_lazy as _
|
||||||
|
from django_filters import OrderingFilter
|
||||||
from shop.models import Product
|
from shop.models import Product
|
||||||
|
|
||||||
|
|
||||||
@@ -9,6 +9,11 @@ class ProductFilter(django_filters.FilterSet):
|
|||||||
field_name="name", lookup_expr="icontains", label=_("Nombre")
|
field_name="name", lookup_expr="icontains", label=_("Nombre")
|
||||||
)
|
)
|
||||||
tags = django_filters.BaseInFilter(field_name="tags", label=_("Etiquetas"))
|
tags = django_filters.BaseInFilter(field_name="tags", label=_("Etiquetas"))
|
||||||
|
ordering = OrderingFilter(
|
||||||
|
fields={
|
||||||
|
'name': 'name'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Product
|
model = Product
|
||||||
@@ -17,4 +22,5 @@ class ProductFilter(django_filters.FilterSet):
|
|||||||
"stock",
|
"stock",
|
||||||
"is_digital_asset",
|
"is_digital_asset",
|
||||||
"tags",
|
"tags",
|
||||||
|
"ordering",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-22 19:53
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
from django.utils.text import slugify
|
||||||
|
|
||||||
|
|
||||||
|
def add_product_slug(apps, schema_editor):
|
||||||
|
Product = apps.get_model("shop", "Product")
|
||||||
|
|
||||||
|
for product in Product.objects.all():
|
||||||
|
product.slug = slugify(product.name)[:128]
|
||||||
|
product.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("shop", "0003_alter_brand_creation_date_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="product",
|
||||||
|
options={
|
||||||
|
"ordering": ("id",),
|
||||||
|
"verbose_name": "producto",
|
||||||
|
"verbose_name_plural": "productos",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="product",
|
||||||
|
name="slug",
|
||||||
|
field=models.SlugField(
|
||||||
|
blank=True, default="", max_length=128, null=True, verbose_name="Slug"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.RunPython(
|
||||||
|
add_product_slug,
|
||||||
|
)
|
||||||
|
]
|
||||||
+12
-2
@@ -3,7 +3,7 @@ from uuid import uuid4
|
|||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.text import gettext_lazy as _
|
from django.utils.text import gettext_lazy as _, slugify
|
||||||
|
|
||||||
|
|
||||||
class TimestampedModel(models.Model):
|
class TimestampedModel(models.Model):
|
||||||
@@ -70,10 +70,20 @@ class Product(TimestampedModel):
|
|||||||
on_delete=models.SET_NULL,
|
on_delete=models.SET_NULL,
|
||||||
verbose_name=_("marca"),
|
verbose_name=_("marca"),
|
||||||
)
|
)
|
||||||
|
slug = models.SlugField(default="", blank=True, null=True, max_length=128, verbose_name=_('Slug'))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def save(
|
||||||
|
self,
|
||||||
|
*args,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
if not self.pk:
|
||||||
|
self.slug = slugify(self.name)[:128]
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def price(self):
|
def price(self):
|
||||||
return self.prices.filter(current=True).first()
|
return self.prices.filter(current=True).first()
|
||||||
@@ -81,7 +91,7 @@ class Product(TimestampedModel):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("producto")
|
verbose_name = _("producto")
|
||||||
verbose_name_plural = _("productos")
|
verbose_name_plural = _("productos")
|
||||||
ordering = ("-id",)
|
ordering = ("id",)
|
||||||
|
|
||||||
|
|
||||||
class ProductPrice(TimestampedModel):
|
class ProductPrice(TimestampedModel):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div
|
<div
|
||||||
class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
||||||
<div class="h-56 w-full">
|
<div class="h-56 w-full">
|
||||||
<a href="#">
|
<a href="{% url 'shop:product_detail' pk=product.pk slug=product.slug %}">
|
||||||
<img class="mx-auto h-full dark:hidden" src="{{ product.images.all|first }}"
|
<img class="mx-auto h-full dark:hidden" src="{{ product.images.all|first }}"
|
||||||
alt="{{ product.name }}"/>
|
alt="{{ product.name }}"/>
|
||||||
<img class="mx-auto hidden h-full dark:block" src="{{ product.images.all|first }}"
|
<img class="mx-auto hidden h-full dark:block" src="{{ product.images.all|first }}"
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pt-6">
|
<div class="pt-6">
|
||||||
|
|
||||||
<a href="{% url 'shop:product_detail' pk=product.pk %}"
|
<a href="{% url 'shop:product_detail' pk=product.pk slug=product.slug %}"
|
||||||
class="text-lg font-semibold leading-tight text-gray-900 hover:underline dark:text-white">{{ product.name }}</a>
|
class="text-lg font-semibold leading-tight text-gray-900 hover:underline dark:text-white">{{ product.name }}</a>
|
||||||
|
|
||||||
<div class="mt-2 flex items-center gap-2">
|
<div class="mt-2 flex items-center gap-2">
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
hx-target="#products"
|
hx-target="#products"
|
||||||
hx-trigger="keyup changed delay:500ms"
|
hx-trigger="keyup changed delay:500ms"
|
||||||
hx-swap="innerHTML"
|
hx-swap="innerHTML"
|
||||||
|
hx-push="true"
|
||||||
>
|
>
|
||||||
<label for="simple-search" class="sr-only">Buscar</label>
|
<label for="simple-search" class="sr-only">Buscar</label>
|
||||||
<div class="relative w-full">
|
<div class="relative w-full">
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{% extends 'theme/base.html' %}
|
{% extends 'theme/base.html' %}
|
||||||
|
{% load static i18n %}
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div>
|
<div>
|
||||||
@@ -13,17 +12,20 @@
|
|||||||
hx-swap="innerHTML"
|
hx-swap="innerHTML"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div id="products" class="mb-4 grid gap-4 sm:grid-cols-2 md:mb-8 lg:grid-cols-3 xl:grid-cols-4">
|
<ul id="products" class="mb-4 grid gap-4 sm:grid-cols-2 md:mb-8 lg:grid-cols-3 xl:grid-cols-4">
|
||||||
</div>
|
</ul>
|
||||||
<div class="w-full text-center">
|
<div class="w-full text-center">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="rounded-lg border border-gray-200 bg-white px-5 py-2.5 text-sm font-medium text-gray-900 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:outline-none focus:ring-4 focus:ring-gray-100 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white dark:focus:ring-gray-700"
|
class="rounded-lg border border-gray-200 bg-white px-5 py-2.5 text-sm font-medium text-gray-900
|
||||||
|
hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:outline-none focus:ring-4
|
||||||
|
focus:ring-gray-100 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700
|
||||||
|
dark:hover:text-white dark:focus:ring-gray-700"
|
||||||
hx-get="{% url 'shop:list_products' %}{% querystring request.GET %}{% querystring page=9 %}"
|
hx-get="{% url 'shop:list_products' %}{% querystring request.GET %}{% querystring page=9 %}"
|
||||||
hx-trigger="click"
|
hx-trigger="click"
|
||||||
hx-target="#products"
|
hx-target="#products"
|
||||||
hx-swap="beforeend"
|
hx-swap="beforeend"
|
||||||
>
|
>
|
||||||
Mostrar mas
|
{% translate 'Mostrar mas' %}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% for product in products %}
|
{% for product in products %}
|
||||||
|
<li>
|
||||||
{% include 'components/product_card.html' %}
|
{% include 'components/product_card.html' %}
|
||||||
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
+1
-1
@@ -7,6 +7,6 @@ app_name = "shop"
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", index, name="index"),
|
path("", index, name="index"),
|
||||||
path("products/<int:pk>/", product_detail, name="product_detail"),
|
path("products/<int:pk>/<str:slug>/", product_detail, name="product_detail"),
|
||||||
path("shop/components/products/", list_products, name="list_products"),
|
path("shop/components/products/", list_products, name="list_products"),
|
||||||
]
|
]
|
||||||
|
|||||||
+9
-1
@@ -9,6 +9,11 @@ from shop.models import Product
|
|||||||
class IndexView(TemplateView):
|
class IndexView(TemplateView):
|
||||||
template_name = "shop/index.html"
|
template_name = "shop/index.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
return {
|
||||||
|
"title": "Shoppy",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ListProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
class ListProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
||||||
template_name = "shop/list_products.html"
|
template_name = "shop/list_products.html"
|
||||||
@@ -27,11 +32,14 @@ class ListProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
|||||||
class ProductDetail(TemplateView):
|
class ProductDetail(TemplateView):
|
||||||
template_name = "shop/product_detail.html"
|
template_name = "shop/product_detail.html"
|
||||||
|
|
||||||
def get_context_data(self, pk, **kwargs):
|
def get_context_data(self, pk, slug, **kwargs):
|
||||||
product = get_object_or_404(Product, pk=pk)
|
product = get_object_or_404(Product, pk=pk)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"product": product,
|
"product": product,
|
||||||
|
"title": product.name,
|
||||||
|
"description": product.description,
|
||||||
|
"image": product.images.first(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<title>{{ title }}</title>
|
<title>{{ title }}</title>
|
||||||
|
|
||||||
|
{% include "theme/seo.html" %}
|
||||||
|
|
||||||
<script src="https://unpkg.com/htmx.org@2.0.3"></script>
|
<script src="https://unpkg.com/htmx.org@2.0.3"></script>
|
||||||
|
|
||||||
{% tailwind_css %}
|
{% tailwind_css %}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:title" content="{{ title }}" />
|
||||||
|
<meta property="og:description" content="{{ description }}" />
|
||||||
|
<meta property="og:image" content="{{ image }}" />
|
||||||
|
<meta property="og:url" content="permalink" />
|
||||||
Reference in New Issue
Block a user