camper/po/es.po

3128 lines
92 KiB
Plaintext
Raw Normal View History

Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
# Spanish translations for camper package
# Traducciones al español para el paquete camper.
# Copyright (C) 2023 THE camper'S COPYRIGHT HOLDER
# This file is distributed under the same license as the camper package.
# jordi fita mas <jordi@tandem.blog>, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-04-19 11:18+0200\n"
"PO-Revision-Date: 2024-02-06 10:04+0100\n"
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Spanish <es@tp.org.es>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.4.2\n"
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
#: web/templates/campground_map.svg:1598
msgctxt "title"
msgid "Zones"
msgstr "Zonas"
#: web/templates/campground_map.svg:1599
msgctxt "tooltip"
msgid "Zone 7"
msgstr "Zona 7"
#: web/templates/campground_map.svg:1600
msgctxt "tooltip"
msgid "Zone 6"
msgstr "Zona 6"
#: web/templates/campground_map.svg:1601
msgctxt "tooltip"
msgid "Zone 5"
msgstr "Zona 6"
#: web/templates/campground_map.svg:1602
msgctxt "tooltip"
msgid "Zone 4"
msgstr "Zona 4"
#: web/templates/campground_map.svg:1603
msgctxt "tooltip"
msgid "Zone 3"
msgstr "Zona 3"
#: web/templates/campground_map.svg:1604
msgctxt "tooltip"
msgid "Zone 2"
msgstr "Zona 2"
#: web/templates/campground_map.svg:1605
msgctxt "tooltip"
msgid "Zone 1"
msgstr "Zona 1"
#: web/templates/mail/payment/details.gotxt:1
#: web/templates/mail/payment/body.gohtml:33
#: web/templates/mail/payment/body.gotxt:1
msgid "Hi %s,"
msgstr "Hola %s,"
#: web/templates/mail/payment/details.gotxt:3
#: web/templates/mail/payment/body.gohtml:35
#: web/templates/mail/payment/body.gotxt:3
msgid "We have successfully received the payment for the booking with the following details:"
msgstr "Hemos recibido correctamente el pago de la reserva con los siguientes detalles:"
#: web/templates/mail/payment/details.gotxt:7
#: web/templates/admin/payment/details.gohtml:49
msgctxt "title"
msgid "Payment"
msgstr "Pago"
#: web/templates/mail/payment/details.gotxt:9
#: web/templates/admin/payment/index.gohtml:21
#: web/templates/admin/payment/details.gohtml:52
#: web/templates/admin/booking/index.gohtml:21
msgctxt "header"
msgid "Reference"
msgstr "Referencia"
#: web/templates/mail/payment/details.gotxt:10
#: web/templates/admin/payment/index.gohtml:22
#: web/templates/admin/payment/details.gohtml:56
#: web/templates/admin/booking/index.gohtml:25
msgctxt "header"
msgid "Status"
msgstr "Estado"
#: web/templates/mail/payment/details.gotxt:11
#: web/templates/admin/payment/details.gohtml:60
msgctxt "payment header"
msgid "Created at"
msgstr "Creado el"
#: web/templates/mail/payment/details.gotxt:12
#: web/templates/admin/payment/details.gohtml:64
msgctxt "payment header"
msgid "Last updated at"
msgstr "Actualizado por última vez el"
#: web/templates/mail/payment/details.gotxt:14
#: web/templates/public/layout.gohtml:71
#: web/templates/public/booking/page.gohtml:7
#: web/templates/admin/payment/details.gohtml:71
msgctxt "title"
msgid "Booking"
msgstr "Reserva"
#: web/templates/mail/payment/details.gotxt:16
#: web/templates/public/booking/fields.gohtml:14
#: web/templates/admin/payment/details.gohtml:74
msgctxt "title"
msgid "Accommodation"
msgstr "Alojamientos"
#: web/templates/mail/payment/details.gotxt:17
#: web/templates/admin/payment/details.gohtml:78
msgctxt "header"
msgid "Area preferences"
msgstr "Preferencias de área"
#: web/templates/mail/payment/details.gotxt:18
#: web/templates/admin/payment/details.gohtml:82
msgctxt "input"
msgid "ACSI card?"
msgstr "¿Tarjeta ACSI?"
#: web/templates/mail/payment/details.gotxt:18
#: web/templates/admin/payment/details.gohtml:83
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "Yes"
msgstr "Sí"
#: web/templates/mail/payment/details.gotxt:18
#: web/templates/admin/payment/details.gohtml:83
#: web/templates/admin/campsite/type/index.gohtml:53
#: web/templates/admin/season/index.gohtml:44
#: web/templates/admin/user/login-attempts.gohtml:31
#: web/templates/admin/amenity/index.gohtml:40
msgid "No"
msgstr "No"
#: web/templates/mail/payment/details.gotxt:19
#: web/templates/public/campsite/dates.gohtml:4
#: web/templates/public/booking/fields.gohtml:30
#: web/templates/admin/payment/details.gohtml:86
msgctxt "input"
msgid "Arrival date"
msgstr "Fecha de llegada"
#: web/templates/mail/payment/details.gotxt:20
#: web/templates/public/campsite/dates.gohtml:15
#: web/templates/public/booking/fields.gohtml:41
#: web/templates/admin/payment/details.gohtml:90
msgctxt "input"
msgid "Departure date"
msgstr "Fecha de salida"
#: web/templates/mail/payment/details.gotxt:21
#: web/templates/admin/payment/details.gohtml:94
msgctxt "cart"
msgid "Nights"
msgstr "Noches"
#: web/templates/mail/payment/details.gotxt:22
#: web/templates/public/booking/fields.gohtml:60
#: web/templates/admin/payment/details.gohtml:98
msgctxt "input"
msgid "Adults aged 17 or older"
msgstr "Adultos de 17 años o más"
#: web/templates/mail/payment/details.gotxt:23
#: web/templates/public/booking/fields.gohtml:71
#: web/templates/admin/payment/details.gohtml:102
msgctxt "input"
msgid "Teenagers from 11 to 16 years old"
msgstr "Adolescentes de 11 a 16 años"
#: web/templates/mail/payment/details.gotxt:24
#: web/templates/public/booking/fields.gohtml:82
#: web/templates/admin/payment/details.gohtml:106
msgctxt "input"
msgid "Children from 2 to 10 years old"
msgstr "Niños de 2 a 10 años"
#: web/templates/mail/payment/details.gotxt:25
#: web/templates/public/booking/fields.gohtml:100
#: web/templates/admin/payment/details.gohtml:110
msgctxt "input"
msgid "Dogs"
msgstr "Perros"
#: web/templates/mail/payment/details.gotxt:26
#: web/templates/admin/payment/details.gohtml:114 pkg/booking/cart.go:197
msgctxt "cart"
msgid "Tourist tax"
msgstr "Impuesto turístico"
#: web/templates/mail/payment/details.gotxt:27
#: web/templates/public/booking/fields.gohtml:225
msgctxt "cart"
msgid "Total"
msgstr "Total"
#: web/templates/mail/payment/details.gotxt:28
#: web/templates/public/booking/fields.gohtml:230
#: web/templates/admin/payment/details.gohtml:118
msgctxt "cart"
msgid "Down payment"
msgstr "A cuenta"
#: web/templates/mail/payment/details.gotxt:31
#: web/templates/admin/payment/details.gohtml:126
#: web/templates/admin/campsite/type/option/form.gohtml:18
#: web/templates/admin/campsite/type/option/index.gohtml:6
#: web/templates/admin/campsite/type/option/index.gohtml:17
msgctxt "title"
msgid "Campsite Type Options"
msgstr "Opciones del tipo de alojamiento"
#: web/templates/mail/payment/details.gotxt:39
#: web/templates/public/booking/fields.gohtml:146
#: web/templates/admin/payment/details.gohtml:140
msgctxt "title"
msgid "Customer Details"
msgstr "Detalles del cliente"
#: web/templates/mail/payment/details.gotxt:41
#: web/templates/public/booking/fields.gohtml:149
#: web/templates/admin/payment/details.gohtml:143
msgctxt "input"
msgid "Full name"
msgstr "Nombre y apellidos"
#: web/templates/mail/payment/details.gotxt:42
#: web/templates/public/booking/fields.gohtml:158
#: web/templates/admin/payment/details.gohtml:147
#: web/templates/admin/taxDetails.gohtml:69
msgctxt "input"
msgid "Address"
msgstr "Dirección"
#: web/templates/mail/payment/details.gotxt:43
#: web/templates/public/booking/fields.gohtml:167
#: web/templates/admin/payment/details.gohtml:151
#: web/templates/admin/taxDetails.gohtml:93
msgctxt "input"
msgid "Postcode"
msgstr "Código postal"
#: web/templates/mail/payment/details.gotxt:44
#: web/templates/admin/payment/details.gohtml:155
#: web/templates/admin/taxDetails.gohtml:77
msgctxt "input"
msgid "City"
msgstr "Población"
#: web/templates/mail/payment/details.gotxt:45
#: web/templates/public/booking/fields.gohtml:185
#: web/templates/admin/payment/details.gohtml:159
#: web/templates/admin/taxDetails.gohtml:101
msgctxt "input"
msgid "Country"
msgstr "País"
#: web/templates/mail/payment/details.gotxt:46
#: web/templates/public/booking/fields.gohtml:196
#: web/templates/admin/payment/details.gohtml:163
#: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38
#: web/templates/admin/taxDetails.gohtml:53
msgctxt "input"
msgid "Email"
msgstr "Correo-e"
#: web/templates/mail/payment/details.gotxt:47
#: web/templates/public/booking/fields.gohtml:205
#: web/templates/admin/payment/details.gohtml:167
#: web/templates/admin/taxDetails.gohtml:45
msgctxt "input"
msgid "Phone"
msgstr "Teléfono"
#: web/templates/mail/payment/details.gotxt:48
#: web/templates/admin/payment/details.gohtml:171
#: web/templates/admin/profile.gohtml:68
msgctxt "input"
msgid "Language"
msgstr "Idioma"
#: web/templates/mail/payment/details.gotxt:54
msgid "Best regards,"
msgstr "Saludos,"
#: web/templates/mail/payment/body.gohtml:6
msgctxt "title"
msgid "Booking Payment Notification"
msgstr "Notificación de pago de reserva"
#: web/templates/mail/payment/body.gohtml:37
msgid "Payment reference: <strong>%s</strong>"
msgstr "Referencia del pago: <strong>%s</strong>"
#: web/templates/mail/payment/body.gohtml:39
msgid "Accommodation: <strong>%s</strong>"
msgstr "Alojamiento: <strong>%s</strong>"
#: web/templates/mail/payment/body.gohtml:41
msgid "Arrival Date: <strong>%s</strong>"
msgstr "Fecha de llegada: <strong>%s</strong>"
#: web/templates/mail/payment/body.gohtml:43
msgid "Departure Date: <strong>%s</strong>"
msgstr "Fecha de salida: <strong>%s</strong>"
#: web/templates/mail/payment/body.gohtml:45
msgid "Total: <strong>%s</strong>"
msgstr "Total: <strong>%s</strong>"
#: web/templates/mail/payment/body.gohtml:48
msgid "Down payment: <strong>%s</strong>"
msgstr "A cuenta: <strong>%s</strong>"
#: web/templates/mail/payment/body.gohtml:52
#: web/templates/mail/payment/body.gotxt:12
msgid "Thank you for your booking, and see you soon!"
msgstr "Gracias por su reserva y ¡hasta pronto!"
#: web/templates/mail/payment/body.gotxt:5
msgid "Payment reference: **%s**"
msgstr "Referencia del pago: **%s**"
#: web/templates/mail/payment/body.gotxt:6
msgid "Accommodation: **%s**"
msgstr "Alojamiento: **%s**"
#: web/templates/mail/payment/body.gotxt:7
msgid "Arrival Date: **%s**"
msgstr "Fecha de llegada: **%s**"
#: web/templates/mail/payment/body.gotxt:8
msgid "Departure Date: **%s**"
msgstr "Fecha de salida: **%s**"
#: web/templates/mail/payment/body.gotxt:9
msgid "Total: **%s**"
msgstr "Total: **%s**"
#: web/templates/mail/payment/body.gotxt:10
msgid "Down payment: **%s**"
msgstr "A cuenta: **%s**"
#: web/templates/public/payment/success.gohtml:6
msgctxt "title"
msgid "Payment Successful"
msgstr "Pago con éxito"
#: web/templates/public/payment/success.gohtml:12
msgid "We have received the payment. Thank you."
msgstr "Hemos recibido su pago. Gracias."
#: web/templates/public/payment/request.gohtml:6
msgctxt "title"
msgid "Booking Payment"
msgstr "Pago de la reserva"
#: web/templates/public/payment/request.gohtml:18
msgid "Thank you for your booking. Please, click the button below to pay with a credit card via Servired/Redsys."
msgstr "Gracias por vuestro pedido. Haced clic al botón de abajo para pagar con tarjeta de crédito vía Servired/Redsys."
#: web/templates/public/payment/request.gohtml:27
msgctxt "action"
msgid "Pay with credit card"
msgstr "Pagar con tarjeta de crédito"
#: web/templates/public/payment/request.gohtml:30
msgid "Please, wait until we redirect you to the payment page."
msgstr "Esperad mientras se os redirige a la página de pago."
#: web/templates/public/payment/failure.gohtml:6
msgctxt "title"
msgid "Payment Failed"
msgstr "Pago fallido"
#: web/templates/public/payment/failure.gohtml:12
msgid "We could not process the payment. Please, contact us for support."
msgstr "No hemos podido procesar su pago. Póngase en contacto con nosotros para solucionar el problema."
#: web/templates/public/payment/details.gohtml:4
msgctxt "title"
msgid "Order Number"
msgstr "Número de pedido"
#: web/templates/public/payment/details.gohtml:8
msgctxt "title"
msgid "Date"
msgstr "Fecha"
#: web/templates/public/payment/details.gohtml:12
msgctxt "title"
msgid "Total"
msgstr "Total"
#: web/templates/public/payment/details.gohtml:17
msgctxt "title"
msgid "Down Payment"
msgstr "A cuenta"
#: web/templates/public/services.gohtml:7
#: web/templates/public/services.gohtml:16
#: web/templates/public/layout.gohtml:68 web/templates/public/layout.gohtml:96
#: web/templates/admin/services/index.gohtml:59
msgctxt "title"
msgid "Services"
msgstr "Servicios"
#: web/templates/public/services.gohtml:19
msgid "The campsite offers many different services."
msgstr "El camping dispone de varios servicios."
#: web/templates/public/amenity.gohtml:39
#: web/templates/public/campsite/type.gohtml:114
#: web/templates/public/campsite/page.gohtml:39
msgctxt "title"
msgid "Features"
msgstr "Características"
#: web/templates/public/location.gohtml:7
#: web/templates/public/location.gohtml:13
#: web/templates/public/layout.gohtml:70 web/templates/public/layout.gohtml:98
#: web/templates/admin/layout.gohtml:64
msgctxt "title"
msgid "Location"
msgstr "Cómo llegar"
#: web/templates/public/home.gohtml:7 web/templates/public/layout.gohtml:54
#: web/templates/public/layout.gohtml:94
Split templates and handlers into admin and public I need to check that the user is an employee (or admin) in administration handlers, but i do not want to do it for each handler, because i am bound to forget it. Thus, i added the /admin sub-path for these resources. The public-facing web is the rest of the resources outside /admin, but for now there is only home, to test whether it works as expected or not. The public-facing web can not relay on the user’s language settings, as the guest user has no way to set that. I would be happy to just use the Accept-Language header for that, but apparently Google does not use that header[0], and they give four alternatives: a country-specific domain, a subdomain with a generic top-level domain (gTLD), subdirectories with a gTLD, or URL parameters (e.g., site.com?loc=de). Of the four, Google does not recommend URL parameters, and the customer is already using subdirectories with the current site, therefor that’s what i have chosen. Google also tells me that it is a very good idea to have links between localized version of the same resources, either with <link> elements, Link HTTP response headers, or a sitemap file[1]; they are all equivalent in the eyes of Google. I have choosen the Link response headers way, because for that i can simply “augment” ResponseHeader to automatically add these headers when the response status is 2xx, otherwise i would need to pass down the original URL path until it reaches the template. Even though Camper is supposed to be a “generic”, multi-company application, i think i will stick to the easiest route and write the templates for just the “first” customer. [0]: https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites [1]: https://developers.google.com/search/docs/specialty/international/localized-versions
2023-08-05 01:42:37 +00:00
msgctxt "title"
msgid "Home"
msgstr "Inicio"
#: web/templates/public/home.gohtml:25
msgctxt "link"
msgid "Booking"
msgstr "Reservar"
#: web/templates/public/home.gohtml:28
msgid "The pleasure of camping in the middle of nature…"
msgstr "El placer de acampar en plena naturaleza…"
#: web/templates/public/home.gohtml:40
msgid "Our services"
msgstr "Nuestros servicios"
#: web/templates/public/home.gohtml:44
#: web/templates/public/surroundings.gohtml:7
#: web/templates/public/surroundings.gohtml:12
#: web/templates/public/layout.gohtml:69 web/templates/public/layout.gohtml:97
#: web/templates/admin/surroundings/form.gohtml:15
#: web/templates/admin/layout.gohtml:67
msgctxt "title"
msgid "Surroundings"
msgstr "El entorno"
#: web/templates/public/home.gohtml:47
msgid "Located in <strong>Alta Garrotxa</strong>, between the <strong>Pyrenees</strong> and the <strong>Costa Brava</strong>."
msgstr "Situados en la <strong>Alta Garrotxa</strong>, entre los <strong>Pirineos</strong> y la <strong>Costa Brava</strong>."
#: web/templates/public/home.gohtml:48
msgid "Nearby there are the <strong>gorges of Sadernes</strong>, <strong>volcanoes</strong>, <strong>La Fageda den Jordà</strong>, the Jewish quarter of <strong>Besalú</strong>, the basaltic cliff of <strong>Castellfollit de la Roca</strong>… much to see and much to do."
msgstr "Cerca tenéis los <strong>piletones de Sadernes</strong>, <strong>volcanes</strong>, <strong>La Fageda den Jordà</strong>, la judería de <strong>Besalú</strong>, el riscal basáltico de <strong>Castellfollit de la Roca</strong>… mucho por ver y mucho por hacer."
#: web/templates/public/home.gohtml:49
msgid "Less than an hour from <strong>Girona</strong>, one from <strong>La Bisbal dEmpordà</strong>, and two from <strong>Barcelona</strong>."
msgstr "A menos de una hora de <strong>Girona</strong>, a una de <strong>La Bisbal dEmpordà</strong> y a dos de <strong>Barcelona</strong>."
#: web/templates/public/home.gohtml:50
msgid "Discover"
msgstr "Descubre"
#: web/templates/public/form.gohtml:28 web/templates/admin/form.gohtml:28
msgctxt "input"
msgid "Month"
msgstr "Mes"
#: web/templates/public/form.gohtml:30 web/templates/admin/form.gohtml:30
#: pkg/season/admin.go:183
msgctxt "month"
msgid "January"
msgstr "enero"
#: web/templates/public/form.gohtml:31 web/templates/admin/form.gohtml:31
#: pkg/season/admin.go:184
msgctxt "month"
msgid "February"
msgstr "febrero"
#: web/templates/public/form.gohtml:32 web/templates/admin/form.gohtml:32
#: pkg/season/admin.go:185
msgctxt "month"
msgid "March"
msgstr "marzo"
#: web/templates/public/form.gohtml:33 web/templates/admin/form.gohtml:33
#: pkg/season/admin.go:186
msgctxt "month"
msgid "April"
msgstr "abril"
#: web/templates/public/form.gohtml:34 web/templates/admin/form.gohtml:34
#: pkg/season/admin.go:187
msgctxt "month"
msgid "May"
msgstr "mayo"
#: web/templates/public/form.gohtml:35 web/templates/admin/form.gohtml:35
#: pkg/season/admin.go:188
msgctxt "month"
msgid "June"
msgstr "junio"
#: web/templates/public/form.gohtml:36 web/templates/admin/form.gohtml:36
#: pkg/season/admin.go:189
msgctxt "month"
msgid "July"
msgstr "julio"
#: web/templates/public/form.gohtml:37 web/templates/admin/form.gohtml:37
#: pkg/season/admin.go:190
msgctxt "month"
msgid "August"
msgstr "agosto"
#: web/templates/public/form.gohtml:38 web/templates/admin/form.gohtml:38
#: pkg/season/admin.go:191
msgctxt "month"
msgid "September"
msgstr "septiembre"
#: web/templates/public/form.gohtml:39 web/templates/admin/form.gohtml:39
#: pkg/season/admin.go:192
msgctxt "month"
msgid "October"
msgstr "octubre"
#: web/templates/public/form.gohtml:40 web/templates/admin/form.gohtml:40
#: pkg/season/admin.go:193
msgctxt "month"
msgid "November"
msgstr "noviembre"
#: web/templates/public/form.gohtml:41 web/templates/admin/form.gohtml:41
#: pkg/season/admin.go:194
msgctxt "month"
msgid "December"
msgstr "diciembre"
#: web/templates/public/form.gohtml:45 web/templates/admin/form.gohtml:45
msgctxt "input"
msgid "Year"
msgstr "Año"
#: web/templates/public/campsite/type.gohtml:49
#: web/templates/public/booking/fields.gohtml:273
msgctxt "action"
msgid "Book"
msgstr "Reservar"
#: web/templates/public/campsite/type.gohtml:57
#: web/templates/admin/season/index.gohtml:54
2023-12-22 02:32:40 +00:00
msgctxt "title"
msgid "Calendar"
msgstr "Calendario"
#: web/templates/public/campsite/type.gohtml:68
#: web/templates/admin/campsite/type/form.gohtml:153
#: web/templates/admin/campsite/type/option/form.gohtml:70
2023-10-01 19:14:39 +00:00
msgctxt "title"
msgid "Prices"
msgstr "Precios"
#: web/templates/public/campsite/type.gohtml:82
msgid "%s: %s/night"
msgstr "%s: %s/noche"
2023-12-22 02:32:40 +00:00
#: web/templates/public/campsite/type.gohtml:84
msgid "%s: %s"
msgstr "%s: %s"
#: web/templates/public/campsite/type.gohtml:88
msgid "%s/night"
msgstr "%s/noche"
#: web/templates/public/campsite/type.gohtml:96
2023-10-01 19:14:39 +00:00
msgid "*Minimum %d nights per stay"
msgstr "*Mínimo %d noches por estancia"
#: web/templates/public/campsite/type.gohtml:101
msgid "10 % VAT included."
msgstr "IVA del 10 % incluido."
#: web/templates/public/campsite/type.gohtml:102
msgid "Tourist tax: %s/night per person aged 17 or older. Maximum %d nights."
msgstr "Impuesto turístico: %s/noche por persona mayor de 16 años. Máximo %d noches."
#: web/templates/public/campsite/type.gohtml:104
msgid "Dogs: %s/night, tied, accompanied, and minimal barking."
msgstr "Perros: %s/noche, atados, acompañados y con mínimo de ladrido."
#: web/templates/public/campsite/type.gohtml:106
msgid "No dogs allowed."
msgstr "No se permiten perros"
#: web/templates/public/campsite/type.gohtml:125
msgctxt "title"
msgid "Info"
msgstr "Información"
#: web/templates/public/campsite/type.gohtml:129
msgctxt "title"
msgid "Facilities"
msgstr "Equipamiento"
#: web/templates/public/campsite/type.gohtml:133
msgctxt "title"
msgid "Description"
msgstr "Descripción"
#: web/templates/public/campsite/type.gohtml:137
msgctxt "title"
msgid "Additional Information"
msgstr "Información adicional"
#: web/templates/public/campsite/type.gohtml:140
msgctxt "time"
msgid "Check-in"
msgstr "Entrada"
#: web/templates/public/campsite/type.gohtml:144
msgctxt "time"
msgid "Check-out"
msgstr "Salida"
#: web/templates/public/campsite/calendar.gohtml:18
#: web/templates/admin/season/calendar.gohtml:16
msgctxt "day"
msgid "Mon"
msgstr "lu"
#: web/templates/public/campsite/calendar.gohtml:19
#: web/templates/admin/season/calendar.gohtml:17
msgctxt "day"
msgid "Tue"
msgstr "ma"
#: web/templates/public/campsite/calendar.gohtml:20
#: web/templates/admin/season/calendar.gohtml:18
msgctxt "day"
msgid "Wed"
msgstr "mi"
#: web/templates/public/campsite/calendar.gohtml:21
#: web/templates/admin/season/calendar.gohtml:19
msgctxt "day"
msgid "Thu"
msgstr "ju"
#: web/templates/public/campsite/calendar.gohtml:22
#: web/templates/admin/season/calendar.gohtml:20
msgctxt "day"
msgid "Fri"
msgstr "vi"
#: web/templates/public/campsite/calendar.gohtml:23
#: web/templates/admin/season/calendar.gohtml:21
msgctxt "day"
msgid "Sat"
msgstr "sá"
#: web/templates/public/campsite/calendar.gohtml:24
#: web/templates/admin/season/calendar.gohtml:22
msgctxt "day"
msgid "Sun"
msgstr "do"
#: web/templates/public/surroundings.gohtml:30
msgctxt "title"
msgid "What to Do Outside the Campsite?"
msgstr "¿Qué hacer desde el camping?"
#: web/templates/public/surroundings.gohtml:50
msgctxt "title"
msgid "Once at the Campsite, We Can Inform You about What Activities are Available"
msgstr "Una vez en el camping, os podemos informar de qué actividades hacer"
#: web/templates/public/surroundings.gohtml:53
msgid "Cycle routes"
msgstr "Rutas en bicicleta"
#: web/templates/public/surroundings.gohtml:54
msgid "There are many bicycle rental companies in Olot."
msgstr "A Olot podéis encontrar empresas de alquiler de bicicletas."
#: web/templates/public/surroundings.gohtml:58
msgid "Routes"
msgstr "Rutas"
#: web/templates/public/surroundings.gohtml:59
msgid "Routes of all kinds, climbing, mountain passes, for all levels."
msgstr "Rutas de todo tipo, escalada, puertos de montaña, para todos los niveles."
#: web/templates/public/surroundings.gohtml:63
msgid "Family outing"
msgstr "Excusiones familiares"
#: web/templates/public/surroundings.gohtml:64
msgid "Many outing possibilities, for all ages."
msgstr "Múltiples excursiones para todas las edades."
#: web/templates/public/surroundings.gohtml:68
msgid "Kayak"
msgstr "Kayak"
#: web/templates/public/surroundings.gohtml:69
msgid "There are several points where you can go by kayak, from sections of the Ter river as well as on the coast…."
msgstr "Hay diversos puntos dónde podéis ir en kayak, desde tramos del río Ter como también en la costa…."
#: web/templates/public/campground.gohtml:7
#: web/templates/public/campground.gohtml:16
#: web/templates/public/layout.gohtml:55 web/templates/public/layout.gohtml:95
msgctxt "title"
msgid "Campground"
msgstr "El camping"
2024-01-29 13:37:27 +00:00
#: web/templates/public/campground.gohtml:20
msgctxt "title"
msgid "Legend"
msgstr "Leyenda"
#: web/templates/public/campground.gohtml:21
msgctxt "title"
msgid "Entrance"
msgstr "Entrada"
#: web/templates/public/campground.gohtml:23
msgctxt "legend"
msgid "Information"
msgstr "Información"
#: web/templates/public/campground.gohtml:24
msgctxt "legend"
msgid "Shop"
msgstr "Tienda"
#: web/templates/public/campground.gohtml:25
msgctxt "legend"
msgid "Restaurant"
msgstr "Restaurante"
#: web/templates/public/campground.gohtml:26
msgctxt "legend"
msgid "Bar"
msgstr "Bar"
#: web/templates/public/campground.gohtml:27
msgctxt "legend"
msgid "TV room"
msgstr "Sala de televisión"
#: web/templates/public/campground.gohtml:28
msgctxt "legend"
msgid "Game room"
msgstr "Sala de juegos"
#: web/templates/public/campground.gohtml:29
msgctxt "legend"
msgid "Recycling"
msgstr "Reciclaje"
#: web/templates/public/campground.gohtml:30
msgctxt "legend"
msgid "Waste"
msgstr "Basura"
#: web/templates/public/campground.gohtml:31
msgctxt "legend"
msgid "Service station"
msgstr "Estación de servicio"
#: web/templates/public/campground.gohtml:33
msgctxt "title"
msgid "Playtime"
msgstr "Recreo"
#: web/templates/public/campground.gohtml:35
msgctxt "legend"
msgid "Pool"
msgstr "Piscina"
#: web/templates/public/campground.gohtml:36
msgctxt "legend"
msgid "Playground"
msgstr "Parque infantil"
#: web/templates/public/campground.gohtml:37
msgctxt "legend"
msgid "Sports field"
msgstr "Campo de deportes"
#: web/templates/public/campground.gohtml:39
msgctxt "title"
msgid "Accomodations"
msgstr "Alojamientos"
#: web/templates/public/campground.gohtml:41
msgctxt "legend"
msgid "Wooden lodge"
msgstr "Cabaña de madera"
#: web/templates/public/campground.gohtml:42
msgctxt "legend"
msgid "Bungalow"
msgstr "Bungaló"
#: web/templates/public/campground.gohtml:43
msgctxt "legend"
msgid "Safari tent"
msgstr "Safari tent"
#: web/templates/public/campground.gohtml:45
msgctxt "title"
msgid "Main Building"
msgstr "Edificio principal"
#: web/templates/public/campground.gohtml:47
msgctxt "legend"
msgid "Restroom"
msgstr "Lavabo"
#: web/templates/public/campground.gohtml:48
msgctxt "legend"
msgid "Shower"
msgstr "Duchas"
#: web/templates/public/campground.gohtml:49
msgctxt "legend"
msgid "Baby bath"
msgstr "Baño para bebés"
#: web/templates/public/campground.gohtml:50
msgctxt "legend"
msgid "Washing machine"
msgstr "Lavadora"
#: web/templates/public/campground.gohtml:51
msgctxt "legend"
msgid "Clothesline"
msgstr "Tendedero"
#: web/templates/public/campground.gohtml:52
msgctxt "legend"
msgid "Barbecue"
msgstr "Barbacoa"
#: web/templates/public/campground.gohtml:53
msgctxt "legend"
msgid "Chemical waste disposal"
msgstr "Vaciado váter químico"
#: web/templates/public/campground.gohtml:55
msgctxt "title"
msgid "Throughout the Campground"
msgstr "En todo el camping"
#: web/templates/public/campground.gohtml:57
msgctxt "legend"
msgid "Fire extinguisher"
msgstr "Extintor"
#: web/templates/public/campground.gohtml:58
msgctxt "legend"
msgid "Faucet"
msgstr "Grifo"
#: web/templates/public/layout.gohtml:12 web/templates/public/layout.gohtml:49
msgid "Campsite Montagut"
msgstr "Camping Montagut"
#: web/templates/public/layout.gohtml:25 web/templates/admin/layout.gohtml:21
msgid "Skip to main content"
msgstr "Saltar al contenido principal"
#: web/templates/public/layout.gohtml:51
msgid "Menu"
msgstr "Menú"
#: web/templates/public/layout.gohtml:59 web/templates/public/layout.gohtml:105
#: web/templates/admin/campsite/feature/form.gohtml:16
#: web/templates/admin/campsite/feature/index.gohtml:10
#: web/templates/admin/campsite/carousel/form.gohtml:16
#: web/templates/admin/campsite/carousel/index.gohtml:10
#: web/templates/admin/campsite/form.gohtml:15
#: web/templates/admin/campsite/index.gohtml:6
#: web/templates/admin/campsite/index.gohtml:15
#: web/templates/admin/campsite/type/feature/form.gohtml:16
#: web/templates/admin/campsite/type/feature/index.gohtml:10
#: web/templates/admin/campsite/type/carousel/form.gohtml:16
#: web/templates/admin/campsite/type/carousel/index.gohtml:10
#: web/templates/admin/campsite/type/form.gohtml:15
#: web/templates/admin/campsite/type/option/form.gohtml:16
#: web/templates/admin/campsite/type/option/index.gohtml:10
#: web/templates/admin/campsite/type/index.gohtml:10
#: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:95
msgctxt "title"
msgid "Campsites"
msgstr "Alojamientos"
#: web/templates/public/layout.gohtml:92
msgctxt "title"
msgid "Sections"
msgstr "Apartados"
#: web/templates/public/layout.gohtml:116
msgctxt "title"
msgid "Opening"
msgstr "Apertura"
#: web/templates/public/layout.gohtml:123
msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s"
msgstr "<abbr title=\"Número\">Nº</abbr> <abbr title=\"Registro de Turismo de Cataluña\">RTC</abbr> %s"
#: web/templates/public/layout.gohtml:132
2024-02-26 18:13:17 +00:00
msgctxt "title"
msgid "Credits"
msgstr "Créditos"
#: web/templates/public/layout.gohtml:132
2024-02-26 18:13:17 +00:00
msgctxt "title"
msgid "Terms and Conditions"
msgstr "Aviso legal"
#: web/templates/public/layout.gohtml:132
2024-02-26 18:13:17 +00:00
msgctxt "title"
msgid "Reservation Conditions"
msgstr "Condiciones de reserva"
#: web/templates/public/booking/page.gohtml:19
msgid "Sorry, there was a problem. Youll find more details highlighted below."
msgstr "Ha habido un problema. Encontraréis más información resaltada debajo."
#: web/templates/public/booking/page.gohtml:24
msgid "Payment is in test mode. You can make the booking regardless, but no money will be charged. We will send you an additional email with instructions on how to perform the payment."
msgstr "El pago está en modo de pruebas. Igualmente podéis hacer la reserva, pero no se os hará ningún cargo. Os enviaremos un correo adicional con instrucciones sobre cómo realizar el pago."
#: web/templates/public/booking/fields.gohtml:27
msgctxt "title"
msgid "Booking Period"
msgstr "Periodo de reserva"
#: web/templates/public/booking/fields.gohtml:56
msgctxt "title"
msgid "Guests"
msgstr "Huéspedes"
#: web/templates/public/booking/fields.gohtml:92
msgid "Note: Due to guest capacity, we have added more accomodations to the booking, but we <strong>cannot</strong> guarantee that they will be next to each other."
msgstr "Nota: Se han añadido alojamientos a la reserva debido a la capacidad de cada una, pero <strong>no</strong> se garantiza que estén de lado."
#: web/templates/public/booking/fields.gohtml:109
msgid "Note: This accommodation does <strong>not</strong> allow dogs."
msgstr "Nota: En este alojamiento <strong>no</strong> se permiten perros."
#: web/templates/public/booking/fields.gohtml:121
msgctxt "input"
msgid "Area preferences (optional)"
msgstr "Preferencias de área (opcional)"
#: web/templates/public/booking/fields.gohtml:123
msgid "Campground map"
msgstr "Mapa del camping"
#: web/templates/public/booking/fields.gohtml:176
msgctxt "input"
msgid "Town or village"
msgstr "Población"
#: web/templates/public/booking/fields.gohtml:188
msgid "Choose a country"
msgstr "Escoja un país"
#: web/templates/public/booking/fields.gohtml:242
msgctxt "input"
msgid "ACSI card? (optional)"
msgstr "¿Tarjeta ACSI? (opcional)"
#: web/templates/public/booking/fields.gohtml:250
msgctxt "input"
msgid "I have read and I accept %[1]sthe reservation conditions%[2]s"
msgstr "He leído y acepto %[1]slas condiciones de reserva%[2]s"
#: web/templates/public/booking/fields.gohtml:258
msgid "By down paying the %d %% of the total, you are pre-booking your preferences. We will respond within 24 hours and this percentage will be charged if accepted."
msgstr "En tramitar el %d %% del total estáis realizando la prerreserva de vuestras preferencias. Os responderemos en un término de 24 horas y os cobraremos este porcentaje en caso que sea aceptada."
#: web/templates/public/booking/fields.gohtml:260
msgid "By paying the total you are pre-booking your preferences. We will respond within 24 hours and this amount will be charged if accepted."
msgstr "En tramitar el pago del total estáis realizando la prerreserva de vuestras preferencias. Os responderemos en un término de 24 horas y os cobraremos esta cantidad en caso que sea aceptada."
#: web/templates/public/booking/fields.gohtml:264
msgid "See <%s>our conditions</%s> for more information."
msgstr "Consultad <%s>nuestras condiciones</%s> para más información."
#: web/templates/admin/payment/settings.gohtml:6
#: web/templates/admin/payment/index.gohtml:14
msgctxt "title"
msgid "Payment Settings"
msgstr "Parámetros de pago"
#: web/templates/admin/payment/settings.gohtml:10
#: web/templates/admin/payment/index.gohtml:6
#: web/templates/admin/payment/details.gohtml:11
#: web/templates/admin/layout.gohtml:40
msgctxt "title"
msgid "Payments"
msgstr "Pagos"
#: web/templates/admin/payment/settings.gohtml:21
msgctxt "input"
msgid "Merchant Code"
msgstr "Código del comercio"
#: web/templates/admin/payment/settings.gohtml:30
msgctxt "input"
msgid "Terminal Number"
msgstr "Número de terminal"
#: web/templates/admin/payment/settings.gohtml:40
msgctxt "input"
msgid "Merchant Key (only if must change it)"
msgstr "Clave del comercio (sólo si se debe cambiar)"
#: web/templates/admin/payment/settings.gohtml:42
msgctxt "input"
msgid "Merchant Key"
msgstr "Clave del comercio"
#: web/templates/admin/payment/settings.gohtml:52
msgctxt "title"
msgid "Environment"
msgstr "Entorno"
#: web/templates/admin/payment/settings.gohtml:59
msgctxt "title"
msgid "Integration"
msgstr "Integración"
#: web/templates/admin/payment/settings.gohtml:66
#: web/templates/admin/location.gohtml:53 web/templates/admin/profile.gohtml:78
#: web/templates/admin/taxDetails.gohtml:179
msgctxt "action"
msgid "Save changes"
msgstr "Guardar los cambios"
#: web/templates/admin/payment/index.gohtml:20
#: web/templates/admin/user/login-attempts.gohtml:19
msgctxt "header"
msgid "Date"
msgstr "Fecha"
#: web/templates/admin/payment/index.gohtml:23
msgctxt "header"
msgid "Down payment"
msgstr "A cuenta"
#: web/templates/admin/payment/index.gohtml:24
msgctxt "header"
msgid "Total"
msgstr "Total"
#: web/templates/admin/payment/index.gohtml:40
msgid "No payments found."
msgstr "No se ha encontrado ningún pago."
#: web/templates/admin/payment/details.gohtml:7
msgctxt "title"
msgid "Payment %s"
msgstr "Pago %s"
#: web/templates/admin/payment/details.gohtml:20
msgid "Are you sure you wish to accept this pre-authorization?"
msgstr "¿Estáis seguro de querer acceptar esta preautorización?"
#: web/templates/admin/payment/details.gohtml:29
msgctxt "action"
msgid "Accept pre-authorization"
msgstr "Acceptar preautorización"
#: web/templates/admin/payment/details.gohtml:34
msgid "Are you sure you wish to void this pre-authorization?"
msgstr "¿Estáis seguro de querer anular esta preautorización?"
#: web/templates/admin/payment/details.gohtml:43
msgctxt "action"
msgid "Void pre-authorization"
msgstr "Anular preautorización"
2023-12-22 01:23:18 +00:00
#: web/templates/admin/legal/form.gohtml:8
#: web/templates/admin/legal/form.gohtml:29
msgctxt "title"
2023-12-22 01:23:18 +00:00
msgid "Edit Legal Text"
msgstr "Edición del texto legal"
2023-12-22 01:23:18 +00:00
#: web/templates/admin/legal/form.gohtml:10
#: web/templates/admin/legal/form.gohtml:31
msgctxt "title"
2023-12-22 01:23:18 +00:00
msgid "New Legal Text"
msgstr "Nuevo texto legal"
#: web/templates/admin/legal/form.gohtml:15
#: web/templates/admin/legal/index.gohtml:6
#: web/templates/admin/legal/index.gohtml:15
#: web/templates/admin/layout.gohtml:70
msgctxt "title"
msgid "Legal Texts"
msgstr "Textos legales"
#: web/templates/admin/legal/form.gohtml:41
msgctxt "input"
2023-12-22 01:23:18 +00:00
msgid "Slug"
msgstr "Álias"
#: web/templates/admin/legal/form.gohtml:50
#: web/templates/admin/campsite/feature/form.gohtml:51
#: web/templates/admin/campsite/type/feature/form.gohtml:59
#: web/templates/admin/campsite/type/form.gohtml:51
#: web/templates/admin/campsite/type/option/form.gohtml:41
#: web/templates/admin/season/form.gohtml:50
#: web/templates/admin/services/form.gohtml:53
#: web/templates/admin/profile.gohtml:29
#: web/templates/admin/surroundings/form.gohtml:41
#: web/templates/admin/amenity/feature/form.gohtml:50
#: web/templates/admin/amenity/form.gohtml:50
2023-12-22 01:23:18 +00:00
msgctxt "input"
msgid "Name"
msgstr "Nombre"
#: web/templates/admin/legal/form.gohtml:68
2023-12-22 01:23:18 +00:00
msgctxt "input"
msgid "Content"
msgstr "Contenido"
#: web/templates/admin/legal/form.gohtml:88
#: web/templates/admin/carousel/form.gohtml:55
#: web/templates/admin/campsite/feature/form.gohtml:66
#: web/templates/admin/campsite/carousel/form.gohtml:51
#: web/templates/admin/campsite/form.gohtml:96
#: web/templates/admin/campsite/type/feature/form.gohtml:74
#: web/templates/admin/campsite/type/carousel/form.gohtml:59
#: web/templates/admin/campsite/type/form.gohtml:287
#: web/templates/admin/campsite/type/option/form.gohtml:98
#: web/templates/admin/season/form.gohtml:73
#: web/templates/admin/services/form.gohtml:81
#: web/templates/admin/surroundings/form.gohtml:69
#: web/templates/admin/surroundings/index.gohtml:58
#: web/templates/admin/amenity/feature/form.gohtml:65
#: web/templates/admin/amenity/carousel/form.gohtml:50
#: web/templates/admin/amenity/form.gohtml:91
#: web/templates/admin/home/index.gohtml:34
#: web/templates/admin/media/form.gohtml:39
msgctxt "action"
msgid "Update"
msgstr "Actualizar"
#: web/templates/admin/legal/form.gohtml:90
#: web/templates/admin/carousel/form.gohtml:57
#: web/templates/admin/campsite/feature/form.gohtml:68
#: web/templates/admin/campsite/carousel/form.gohtml:53
#: web/templates/admin/campsite/form.gohtml:98
#: web/templates/admin/campsite/type/feature/form.gohtml:76
#: web/templates/admin/campsite/type/carousel/form.gohtml:61
#: web/templates/admin/campsite/type/form.gohtml:289
#: web/templates/admin/campsite/type/option/form.gohtml:100
#: web/templates/admin/season/form.gohtml:75
#: web/templates/admin/services/form.gohtml:83
#: web/templates/admin/surroundings/form.gohtml:71
#: web/templates/admin/amenity/feature/form.gohtml:67
#: web/templates/admin/amenity/carousel/form.gohtml:52
#: web/templates/admin/amenity/form.gohtml:93
msgctxt "action"
msgid "Add"
msgstr "Añadir"
#: web/templates/admin/legal/index.gohtml:14
2023-12-22 01:23:18 +00:00
msgctxt "action"
msgid "Add Legal Text"
msgstr "Añadir texto legal"
#: web/templates/admin/legal/index.gohtml:20
#: web/templates/admin/campsite/feature/index.gohtml:31
#: web/templates/admin/campsite/type/feature/index.gohtml:31
#: web/templates/admin/campsite/type/option/index.gohtml:30
#: web/templates/admin/campsite/type/index.gohtml:29
#: web/templates/admin/season/index.gohtml:29
#: web/templates/admin/user/index.gohtml:20
#: web/templates/admin/surroundings/index.gohtml:83
#: web/templates/admin/amenity/feature/index.gohtml:30
#: web/templates/admin/amenity/index.gohtml:21
2023-12-22 01:23:18 +00:00
msgctxt "header"
msgid "Name"
msgstr "Nombre"
#: web/templates/admin/legal/index.gohtml:32
2023-12-22 01:23:18 +00:00
msgid "No legal texts added yet."
msgstr "No se ha añadido ningún texto legal todavía."
#: web/templates/admin/carousel/form.gohtml:8
#: web/templates/admin/carousel/form.gohtml:28
2023-12-22 01:23:18 +00:00
msgctxt "title"
msgid "Edit Carousel Slide"
msgstr "Edición de la diapositiva del carrusel"
#: web/templates/admin/carousel/form.gohtml:10
#: web/templates/admin/carousel/form.gohtml:30
2023-12-22 01:23:18 +00:00
msgctxt "title"
msgid "New Carousel Slide"
msgstr "Nueva diapositiva del carrusel"
#: web/templates/admin/carousel/form.gohtml:40
#: web/templates/admin/campsite/carousel/form.gohtml:36
#: web/templates/admin/campsite/type/carousel/form.gohtml:44
#: web/templates/admin/amenity/carousel/form.gohtml:35
2023-12-22 01:23:18 +00:00
msgctxt "input"
msgid "Caption"
msgstr "Leyenda"
#: web/templates/admin/location.gohtml:6 web/templates/admin/location.gohtml:15
msgctxt "title"
msgid "Location Settings"
msgstr "Parámetros de cómo llegar"
#: web/templates/admin/location.gohtml:20
msgctxt "input"
msgid "Directions"
msgstr "Instrucciones"
#: web/templates/admin/location.gohtml:33
msgctxt "input"
msgid "Opening Dates"
msgstr "Fechas de apertura"
#: web/templates/admin/location.gohtml:46
msgctxt "input"
msgid "Map Embed"
msgstr "Incrustación del mapa"
#: web/templates/admin/campsite/feature/form.gohtml:8
msgctxt "title"
msgid "Edit Campsite Feature"
msgstr "Edición de las características del alojamiento"
#: web/templates/admin/campsite/feature/form.gohtml:10
msgctxt "title"
msgid "New Campsite Feature"
msgstr "Nueva característica del alojamiento"
#: web/templates/admin/campsite/feature/form.gohtml:17
#: web/templates/admin/campsite/feature/index.gohtml:11
#: web/templates/admin/campsite/carousel/form.gohtml:17
#: web/templates/admin/campsite/carousel/index.gohtml:11
#: web/templates/admin/campsite/form.gohtml:8
msgctxt "title"
msgid "Edit Campsite"
msgstr "Edición del alojamientos"
#: web/templates/admin/campsite/feature/form.gohtml:18
#: web/templates/admin/campsite/feature/index.gohtml:6
msgctxt "title"
msgid "Campsite Features"
msgstr "Características del alojamiento"
#: web/templates/admin/campsite/feature/form.gohtml:33
#: web/templates/admin/campsite/type/feature/form.gohtml:41
#: web/templates/admin/services/form.gohtml:35
#: web/templates/admin/amenity/feature/form.gohtml:32
msgctxt "input"
msgid "Icon"
msgstr "Icono"
#: web/templates/admin/campsite/feature/index.gohtml:16
#: web/templates/admin/campsite/type/feature/index.gohtml:16
#: web/templates/admin/amenity/feature/index.gohtml:15
msgctxt "action"
msgid "Add Feature"
msgstr "Añadir características"
#: web/templates/admin/campsite/feature/index.gohtml:32
#: web/templates/admin/campsite/carousel/index.gohtml:32
#: web/templates/admin/campsite/type/feature/index.gohtml:32
#: web/templates/admin/campsite/type/carousel/index.gohtml:32
#: web/templates/admin/campsite/type/option/index.gohtml:31
#: web/templates/admin/services/index.gohtml:30
#: web/templates/admin/services/index.gohtml:75
#: web/templates/admin/user/index.gohtml:23
#: web/templates/admin/surroundings/index.gohtml:84
#: web/templates/admin/amenity/feature/index.gohtml:31
#: web/templates/admin/amenity/carousel/index.gohtml:31
#: web/templates/admin/amenity/index.gohtml:25
#: web/templates/admin/home/index.gohtml:54
#: web/templates/admin/home/index.gohtml:99
msgctxt "header"
msgid "Actions"
msgstr "Acciones"
#: web/templates/admin/campsite/feature/index.gohtml:36
#: web/templates/admin/campsite/type/feature/index.gohtml:36
#: web/templates/admin/amenity/feature/index.gohtml:35
msgid "Are you sure you wish to delete this feature?"
msgstr "¿Estáis seguro de querer borrar esta característica?"
#: web/templates/admin/campsite/feature/index.gohtml:48
#: web/templates/admin/campsite/carousel/index.gohtml:50
#: web/templates/admin/campsite/type/feature/index.gohtml:48
#: web/templates/admin/campsite/type/carousel/index.gohtml:50
#: web/templates/admin/campsite/type/option/index.gohtml:47
#: web/templates/admin/services/index.gohtml:47
#: web/templates/admin/services/index.gohtml:91
#: web/templates/admin/user/index.gohtml:37
#: web/templates/admin/surroundings/index.gohtml:63
#: web/templates/admin/surroundings/index.gohtml:101
#: web/templates/admin/amenity/feature/index.gohtml:47
#: web/templates/admin/amenity/carousel/index.gohtml:49
#: web/templates/admin/amenity/index.gohtml:45
#: web/templates/admin/home/index.gohtml:71
#: web/templates/admin/home/index.gohtml:116
msgctxt "action"
msgid "Delete"
msgstr "Borrar"
#: web/templates/admin/campsite/feature/index.gohtml:57
msgid "No campsite features added yet."
msgstr "No se ha añadido ninguna característica al alojamiento todavía."
#: web/templates/admin/campsite/carousel/form.gohtml:8
msgctxt "title"
msgid "Edit Campsite Carousel Slide"
msgstr "Edición de la diapositiva del carrusel del alojamiento"
#: web/templates/admin/campsite/carousel/form.gohtml:10
msgctxt "title"
msgid "New Campsite Carousel Slide"
msgstr "Nueva diapositiva del carrusel del alojamiento"
#: web/templates/admin/campsite/carousel/form.gohtml:18
#: web/templates/admin/campsite/carousel/index.gohtml:6
msgctxt "title"
msgid "Campsite Carousel"
msgstr "Carrusel del alojamiento"
#: web/templates/admin/campsite/carousel/index.gohtml:17
#: web/templates/admin/campsite/type/carousel/index.gohtml:17
#: web/templates/admin/services/index.gohtml:15
#: web/templates/admin/amenity/carousel/index.gohtml:16
#: web/templates/admin/home/index.gohtml:84
msgctxt "action"
msgid "Add slide"
msgstr "Añadir diapositiva"
#: web/templates/admin/campsite/carousel/index.gohtml:30
#: web/templates/admin/campsite/type/carousel/index.gohtml:30
#: web/templates/admin/services/index.gohtml:28
#: web/templates/admin/surroundings/index.gohtml:82
#: web/templates/admin/amenity/carousel/index.gohtml:29
#: web/templates/admin/home/index.gohtml:52
#: web/templates/admin/home/index.gohtml:97
msgctxt "header"
msgid "Image"
msgstr "Imagen"
#: web/templates/admin/campsite/carousel/index.gohtml:31
#: web/templates/admin/campsite/type/carousel/index.gohtml:31
#: web/templates/admin/services/index.gohtml:29
#: web/templates/admin/amenity/carousel/index.gohtml:30
#: web/templates/admin/home/index.gohtml:53
#: web/templates/admin/home/index.gohtml:98
msgctxt "header"
msgid "Caption"
msgstr "Leyenda"
#: web/templates/admin/campsite/carousel/index.gohtml:36
#: web/templates/admin/campsite/type/carousel/index.gohtml:36
#: web/templates/admin/services/index.gohtml:34
#: web/templates/admin/amenity/carousel/index.gohtml:35
#: web/templates/admin/home/index.gohtml:103
msgid "Are you sure you wish to delete this slide?"
msgstr "¿Estáis seguro de querer borrar esta diapositiva?"
#: web/templates/admin/campsite/carousel/index.gohtml:59
#: web/templates/admin/campsite/type/carousel/index.gohtml:59
#: web/templates/admin/services/index.gohtml:56
#: web/templates/admin/amenity/carousel/index.gohtml:58
#: web/templates/admin/home/index.gohtml:125
msgid "No slides added yet."
msgstr "No se ha añadido ninguna diapositiva todavía."
#: web/templates/admin/campsite/form.gohtml:10
msgctxt "title"
msgid "New Campsite"
msgstr "Nuevo alojamiento"
#: web/templates/admin/campsite/form.gohtml:21
#: web/templates/admin/campsite/type/index.gohtml:45
#: web/templates/admin/amenity/index.gohtml:35
msgctxt "action"
msgid "Edit Features"
msgstr "Editar las características"
#: web/templates/admin/campsite/form.gohtml:22
#: web/templates/admin/campsite/type/index.gohtml:51
#: web/templates/admin/amenity/index.gohtml:38
msgctxt "action"
msgid "Edit Carousel"
msgstr "Editar el carrusel"
#: web/templates/admin/campsite/form.gohtml:37
msgctxt "campsite"
msgid "Active"
msgstr "Activo"
#: web/templates/admin/campsite/form.gohtml:46
msgctxt "input"
msgid "Campsite Type"
msgstr "Tipo de alojamiento"
#: web/templates/admin/campsite/form.gohtml:51
msgid "Select campsite type"
msgstr "Escoged un tipo de alojamiento"
#: web/templates/admin/campsite/form.gohtml:60
#: web/templates/admin/amenity/form.gohtml:42
msgctxt "input"
msgid "Label"
msgstr "Etiqueta"
#: web/templates/admin/campsite/form.gohtml:68
#: web/templates/admin/amenity/form.gohtml:63
msgctxt "input"
msgid "Info (First Column)"
msgstr "Información (primera columna)"
#: web/templates/admin/campsite/form.gohtml:81
#: web/templates/admin/amenity/form.gohtml:76
msgctxt "input"
msgid "Info (Second Column)"
msgstr "Información (segunda columna)"
#: web/templates/admin/campsite/index.gohtml:14
msgctxt "action"
msgid "Add Campsite"
msgstr "Añadir alojamiento"
#: web/templates/admin/campsite/index.gohtml:21
msgid "From Date"
msgstr "De la fecha"
#: web/templates/admin/campsite/index.gohtml:28
msgid "To Date"
msgstr "A la fecha"
#: web/templates/admin/campsite/index.gohtml:35
msgctxt "action"
msgid "Show"
msgstr "Mostrar"
#: web/templates/admin/campsite/index.gohtml:50
#: web/templates/admin/amenity/index.gohtml:20
msgctxt "header"
msgid "Label"
msgstr "Etiqueta"
#: web/templates/admin/campsite/index.gohtml:78
msgid "No campsites added yet."
msgstr "No se ha añadido ningún alojamiento todavía."
#: web/templates/admin/campsite/type/feature/form.gohtml:8
#: web/templates/admin/campsite/type/feature/form.gohtml:32
msgctxt "title"
msgid "Edit Campsite Type Feature"
msgstr "Edición de las características del tipo de alojamiento"
#: web/templates/admin/campsite/type/feature/form.gohtml:10
#: web/templates/admin/campsite/type/feature/form.gohtml:34
msgctxt "title"
msgid "New Campsite Type Feature"
msgstr "Nueva característica del tipo de alojamiento"
#: web/templates/admin/campsite/type/feature/form.gohtml:17
#: web/templates/admin/campsite/type/feature/index.gohtml:11
#: web/templates/admin/campsite/type/carousel/form.gohtml:17
#: web/templates/admin/campsite/type/carousel/index.gohtml:11
#: web/templates/admin/campsite/type/form.gohtml:16
#: web/templates/admin/campsite/type/option/form.gohtml:17
#: web/templates/admin/campsite/type/option/index.gohtml:11
#: web/templates/admin/campsite/type/index.gohtml:6
#: web/templates/admin/campsite/type/index.gohtml:16
#: web/templates/admin/layout.gohtml:43
msgctxt "title"
msgid "Campsite Types"
msgstr "Tipos de alojamientos"
#: web/templates/admin/campsite/type/feature/form.gohtml:18
#: web/templates/admin/campsite/type/feature/index.gohtml:6
#: web/templates/admin/campsite/type/feature/index.gohtml:17
msgctxt "title"
msgid "Campsite Type Features"
msgstr "Características del tipo de alojamiento"
#: web/templates/admin/campsite/type/feature/index.gohtml:57
msgid "No campsite type features added yet."
msgstr "No se ha añadido ninguna característica al tipo de alojamiento todavía."
#: web/templates/admin/campsite/type/carousel/form.gohtml:8
#: web/templates/admin/campsite/type/carousel/form.gohtml:32
msgctxt "title"
msgid "Edit Campsite Type Carousel Slide"
msgstr "Edición de la diapositiva del carrusel del tipo de alojamiento"
#: web/templates/admin/campsite/type/carousel/form.gohtml:10
#: web/templates/admin/campsite/type/carousel/form.gohtml:34
msgctxt "title"
msgid "New Campsite Type Carousel Slide"
msgstr "Nueva diapositiva del carrusel del tipo de alojamiento"
#: web/templates/admin/campsite/type/carousel/form.gohtml:18
#: web/templates/admin/campsite/type/carousel/index.gohtml:6
#: web/templates/admin/campsite/type/carousel/index.gohtml:16
msgctxt "title"
msgid "Campsite Type Carousel"
msgstr "Carrusel del tipo de alojamiento"
#: web/templates/admin/campsite/type/form.gohtml:8
#: web/templates/admin/campsite/type/form.gohtml:30
msgctxt "title"
msgid "Edit Campsite Type"
msgstr "Edición del tipo de alojamiento"
#: web/templates/admin/campsite/type/form.gohtml:10
#: web/templates/admin/campsite/type/form.gohtml:32
msgctxt "title"
msgid "New Campsite Type"
msgstr "Nuevo tipo de alojamiento"
#: web/templates/admin/campsite/type/form.gohtml:42
#: web/templates/admin/campsite/type/index.gohtml:33
msgctxt "campsite type"
msgid "Active"
msgstr "Activo"
#: web/templates/admin/campsite/type/form.gohtml:67
msgctxt "input"
msgid "Check-in"
msgstr "Entrada"
#: web/templates/admin/campsite/type/form.gohtml:80
msgctxt "input"
msgid "Check-out"
msgstr "Salida"
#: web/templates/admin/campsite/type/form.gohtml:93
msgctxt "input"
msgid "Minimum number of nights"
msgstr "Número mínimos de noches"
#: web/templates/admin/campsite/type/form.gohtml:101
msgctxt "input"
msgid "Maximum number of nights"
msgstr "Número máximo de noches"
#: web/templates/admin/campsite/type/form.gohtml:110
msgctxt "input"
msgid "Maximum number of campers"
msgstr "Número máximo de personas"
#: web/templates/admin/campsite/type/form.gohtml:120
msgctxt "input"
msgid "Allow overflowing guests to neighbouring campsites"
msgstr "Permitir reservar alojamientos vecinos si se supera el máximo de personas"
#: web/templates/admin/campsite/type/form.gohtml:129
msgctxt "input"
msgid "Ask for zone preferences when booking"
msgstr "Pedir la preferencia de zona durante la reserva"
#: web/templates/admin/campsite/type/form.gohtml:139
msgctxt "input"
msgid "Dogs allowed"
msgstr "Se permiten perros"
#: web/templates/admin/campsite/type/form.gohtml:144
msgctxt "input"
msgid "Dogs price"
msgstr "Precio de los perros"
#: web/templates/admin/campsite/type/form.gohtml:157
msgctxt "header"
msgid "Season"
msgstr "Temporada"
#: web/templates/admin/campsite/type/form.gohtml:158
msgctxt "header"
msgid "Price per night"
msgstr "Precio por noche"
#: web/templates/admin/campsite/type/form.gohtml:159
msgctxt "header"
msgid "Price per adult (> 16)"
msgstr "Precio por adulto (> 16)"
#: web/templates/admin/campsite/type/form.gohtml:160
msgctxt "header"
msgid "Price per teenager (1116)"
msgstr "Precio por adolescente (1116)"
#: web/templates/admin/campsite/type/form.gohtml:161
msgctxt "header"
msgid "Price per child (210)"
msgstr "Precio por niño (210)"
#: web/templates/admin/campsite/type/form.gohtml:171
msgctxt "input"
msgid "Price per night"
msgstr "Precio por noche"
#: web/templates/admin/campsite/type/form.gohtml:182
msgctxt "input"
msgid "Price per adult (> 16)"
msgstr "Precio por adulto (> 16)"
#: web/templates/admin/campsite/type/form.gohtml:193
msgctxt "input"
msgid "Price per teenager (1116)"
msgstr "Precio por adolescente (1116)"
#: web/templates/admin/campsite/type/form.gohtml:204
msgctxt "input"
msgid "Price per child (210)"
msgstr "Precio por niño (210)"
#: web/templates/admin/campsite/type/form.gohtml:220
msgctxt "input"
msgid "Spiel"
msgstr "Introducción"
#: web/templates/admin/campsite/type/form.gohtml:233
msgctxt "input"
msgid "Info"
msgstr "Información"
#: web/templates/admin/campsite/type/form.gohtml:246
msgctxt "input"
msgid "Facilities"
msgstr "Equipamento"
#: web/templates/admin/campsite/type/form.gohtml:259
#: web/templates/admin/services/form.gohtml:66
#: web/templates/admin/surroundings/form.gohtml:54
msgctxt "input"
msgid "Description"
msgstr "Descripción"
#: web/templates/admin/campsite/type/form.gohtml:272
msgctxt "input"
msgid "Additional Information"
msgstr "Información adicional"
#: web/templates/admin/campsite/type/option/form.gohtml:8
#: web/templates/admin/campsite/type/option/form.gohtml:32
msgctxt "title"
msgid "Edit Campsite Type Option"
msgstr "Edición de la opción del tipo de alojamiento"
#: web/templates/admin/campsite/type/option/form.gohtml:10
#: web/templates/admin/campsite/type/option/form.gohtml:34
msgctxt "title"
msgid "New Campsite Type Option"
msgstr "Nueva opción del tipo de alojamiento"
#: web/templates/admin/campsite/type/option/form.gohtml:54
msgctxt "input"
msgid "Minimum"
msgstr "Mínimo"
#: web/templates/admin/campsite/type/option/form.gohtml:62
msgctxt "input"
msgid "Maximum"
msgstr "Màximo"
#: web/templates/admin/campsite/type/option/form.gohtml:75
msgctxt "campsite type"
msgid "Per night"
msgstr "Por noche"
#: web/templates/admin/campsite/type/option/form.gohtml:84
msgctxt "input"
msgid "Price"
msgstr "Precio"
#: web/templates/admin/campsite/type/option/index.gohtml:16
msgctxt "action"
msgid "Add Option"
msgstr "Añadir opción"
#: web/templates/admin/campsite/type/option/index.gohtml:35
msgid "Are you sure you wish to delete this option?"
msgstr "¿Estáis seguro de querer borrar esta opción?"
#: web/templates/admin/campsite/type/option/index.gohtml:56
msgid "No campsite type options added yet."
msgstr "No se ha añadido ninguna opció al tipo de alojamiento todavía."
#: web/templates/admin/campsite/type/index.gohtml:15
msgctxt "action"
msgid "Add Type"
msgstr "Añadir tipo"
#: web/templates/admin/campsite/type/index.gohtml:30
#: web/templates/admin/amenity/index.gohtml:22
msgctxt "header"
msgid "Features"
msgstr "Características"
#: web/templates/admin/campsite/type/index.gohtml:31
msgctxt "header"
msgid "Options"
msgstr "Opciones"
#: web/templates/admin/campsite/type/index.gohtml:32
#: web/templates/admin/amenity/index.gohtml:23
msgctxt "header"
msgid "Carousel"
msgstr "Carrusel"
#: web/templates/admin/campsite/type/index.gohtml:48
msgctxt "action"
msgid "Edit Options"
msgstr "Editar opciones"
#: web/templates/admin/campsite/type/index.gohtml:60
msgid "No campsite types added yet."
msgstr "No se ha añadido ningún tipo de alojamiento todavía."
#: web/templates/admin/season/form.gohtml:8
#: web/templates/admin/season/form.gohtml:29
msgctxt "title"
msgid "Edit Season"
msgstr "Edición de temporada"
#: web/templates/admin/season/form.gohtml:10
#: web/templates/admin/season/form.gohtml:31
msgctxt "title"
msgid "New Season"
msgstr "Nueva temporada"
#: web/templates/admin/season/form.gohtml:15
#: web/templates/admin/season/index.gohtml:6
#: web/templates/admin/season/index.gohtml:15
#: web/templates/admin/layout.gohtml:52
msgctxt "title"
msgid "Seasons"
msgstr "Temporadas"
#: web/templates/admin/season/form.gohtml:41
#: web/templates/admin/season/index.gohtml:30
msgctxt "season"
msgid "Active"
msgstr "Activa"
#: web/templates/admin/season/form.gohtml:63
msgctxt "input"
msgid "Color"
msgstr "Color"
#: web/templates/admin/season/index.gohtml:14
msgctxt "action"
msgid "Add Season"
msgstr "Añadir temporada"
#: web/templates/admin/season/index.gohtml:28
msgctxt "header"
msgid "Color"
msgstr "Color"
#: web/templates/admin/season/index.gohtml:51
msgid "No seasons added yet."
msgstr "No se ha añadido ninguna temporada todavía."
#: web/templates/admin/season/calendar.gohtml:49
#: web/templates/admin/media/picker.gohtml:61
msgctxt "action"
msgid "Cancel"
msgstr "Cancelar"
Split templates and handlers into admin and public I need to check that the user is an employee (or admin) in administration handlers, but i do not want to do it for each handler, because i am bound to forget it. Thus, i added the /admin sub-path for these resources. The public-facing web is the rest of the resources outside /admin, but for now there is only home, to test whether it works as expected or not. The public-facing web can not relay on the user’s language settings, as the guest user has no way to set that. I would be happy to just use the Accept-Language header for that, but apparently Google does not use that header[0], and they give four alternatives: a country-specific domain, a subdomain with a generic top-level domain (gTLD), subdirectories with a gTLD, or URL parameters (e.g., site.com?loc=de). Of the four, Google does not recommend URL parameters, and the customer is already using subdirectories with the current site, therefor that’s what i have chosen. Google also tells me that it is a very good idea to have links between localized version of the same resources, either with <link> elements, Link HTTP response headers, or a sitemap file[1]; they are all equivalent in the eyes of Google. I have choosen the Link response headers way, because for that i can simply “augment” ResponseHeader to automatically add these headers when the response status is 2xx, otherwise i would need to pass down the original URL path until it reaches the template. Even though Camper is supposed to be a “generic”, multi-company application, i think i will stick to the easiest route and write the templates for just the “first” customer. [0]: https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites [1]: https://developers.google.com/search/docs/specialty/international/localized-versions
2023-08-05 01:42:37 +00:00
#: web/templates/admin/dashboard.gohtml:6
#: web/templates/admin/dashboard.gohtml:13 web/templates/admin/layout.gohtml:89
msgctxt "title"
msgid "Dashboard"
msgstr "Panel"
#: web/templates/admin/login.gohtml:6 web/templates/admin/login.gohtml:18
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
msgctxt "title"
msgid "Login"
msgstr "Entrada"
#: web/templates/admin/login.gohtml:36 web/templates/admin/profile.gohtml:49
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
msgctxt "input"
msgid "Password"
msgstr "Contraseña"
#: web/templates/admin/login.gohtml:45
Add the skeleton of the web application It does nothing more than to server a single page that does nothing interesting. This time i do not use a router. Instead, i am trying out a technique i have seen in an article[0] that i have tried in other, smaller, projects and seems to work surprisingly well: it just “cuts off” the URI path by path, passing the request from handler to handler until it finds its way to a handler that actually serves the request. That helps to loosen the coupling between the application and lower handlers, and makes dependencies explicit, because i need to pass the locale, company, etc. down instead of storing them in contexts. Let’s see if i do not regret it on a later date. I also made a lot more packages that in Numerus. In Numerus i actually only have the single pkg package, and it works, kind of, but i notice how i name my methods to avoid clashing instead of using packages for that. That is, instead of pkg.NewApp i now have app.New. Initially i thought that Locale should be inside app, but then there was a circular dependency between app and template. That is why i created a separate package, but now i am wondering if template should be inside app too, but then i would have app.MustRenderTemplate instead of template.MustRender. The CSS is the most bare-bones file i could write because i am focusing in markup right now; Oriol will fill in the file once the application is working. [0]: https://blog.merovius.de/posts/2017-06-18-how-not-to-use-an-http-router/
2023-07-22 22:11:00 +00:00
msgctxt "action"
msgid "Login"
msgstr "Entrar"
#: web/templates/admin/services/form.gohtml:8
#: web/templates/admin/services/form.gohtml:26
msgctxt "title"
msgid "Edit Service"
msgstr "Edición de servicio"
#: web/templates/admin/services/form.gohtml:10
#: web/templates/admin/services/form.gohtml:28
msgctxt "title"
msgid "New Service"
msgstr "Nuevo servicio"
#: web/templates/admin/services/form.gohtml:15
#: web/templates/admin/services/index.gohtml:6
#: web/templates/admin/layout.gohtml:61
msgctxt "title"
msgid "Services Page"
msgstr "Página de servicios"
#: web/templates/admin/services/index.gohtml:14
#: web/templates/admin/home/index.gohtml:83
msgctxt "title"
msgid "Carousel"
msgstr "Carrusel"
#: web/templates/admin/services/index.gohtml:60
2023-09-26 14:51:35 +00:00
msgctxt "action"
msgid "Add service"
msgstr "Añadir servicio"
#: web/templates/admin/services/index.gohtml:73
msgctxt "header"
msgid "Order"
msgstr "Orden"
#: web/templates/admin/services/index.gohtml:74
msgctxt "header"
msgid "Service"
msgstr "Servicio"
#: web/templates/admin/services/index.gohtml:79
msgid "Are you sure you wish to delete this service?"
msgstr "¿Estáis seguro de querer borrar este servicio?"
#: web/templates/admin/services/index.gohtml:100
msgid "No services added yet."
msgstr "No se ha añadido ningún servicio todavía."
#: web/templates/admin/profile.gohtml:6 web/templates/admin/profile.gohtml:15
#: web/templates/admin/layout.gohtml:33
msgctxt "title"
msgid "Profile"
msgstr "Perfil"
#: web/templates/admin/profile.gohtml:20
msgctxt "inut"
msgid "Profile Image"
msgstr "Imagen del perfil"
#: web/templates/admin/profile.gohtml:46
msgctxt "legend"
msgid "Change password"
msgstr "Cambio de contraseña"
#: web/templates/admin/profile.gohtml:58
msgctxt "input"
msgid "Password Confirmation"
msgstr "Confirmación de la contraseña"
#: web/templates/admin/user/login-attempts.gohtml:6
#: web/templates/admin/user/login-attempts.gohtml:15
msgctxt "title"
msgid "Login Attempts"
msgstr "Intentos de entrada"
#: web/templates/admin/user/login-attempts.gohtml:10
#: web/templates/admin/user/index.gohtml:6
#: web/templates/admin/user/index.gohtml:16
#: web/templates/admin/layout.gohtml:73
msgctxt "title"
msgid "Users"
msgstr "Usuarios"
#: web/templates/admin/user/login-attempts.gohtml:20
#: web/templates/admin/user/index.gohtml:21
msgctxt "header"
msgid "Email"
msgstr "Correo-e"
#: web/templates/admin/user/login-attempts.gohtml:21
msgctxt "header"
msgid "IP Address"
msgstr "Dirección IP"
#: web/templates/admin/user/login-attempts.gohtml:22
msgctxt "header"
msgid "Success"
msgstr "Éxito"
#: web/templates/admin/user/index.gohtml:14
msgctxt "action"
msgid "Add User"
msgstr "Añadir usuario"
#: web/templates/admin/user/index.gohtml:15
msgctxt "action"
msgid "Logs"
msgstr "Registros"
#: web/templates/admin/user/index.gohtml:22
msgctxt "header"
msgid "Role"
msgstr "Rol"
#: web/templates/admin/user/index.gohtml:27
msgid "Are you sure you wish to delete this user?"
msgstr "¿Estáis seguro de querer borrar este usuario?"
#: web/templates/admin/taxDetails.gohtml:6
#: web/templates/admin/taxDetails.gohtml:15
msgctxt "title"
msgid "Tax Details"
msgstr "Configuración fiscal"
#: web/templates/admin/taxDetails.gohtml:20
#: web/templates/admin/taxDetails.gohtml:61
msgctxt "input"
msgid "Business Name"
msgstr "Nombre de empresa"
#: web/templates/admin/taxDetails.gohtml:29
msgctxt "input"
msgid "VAT Number"
msgstr "NIF"
#: web/templates/admin/taxDetails.gohtml:37
msgctxt "input"
msgid "Trade Name"
msgstr "Nombre comercial"
#: web/templates/admin/taxDetails.gohtml:85
msgctxt "input"
msgid "Province"
msgstr "Provincia"
#: web/templates/admin/taxDetails.gohtml:111
msgctxt "input"
msgid "Currency"
msgstr "Moneda"
#: web/templates/admin/taxDetails.gohtml:121
msgctxt "input"
msgid "Default Language"
msgstr "Idioma por defecto"
#: web/templates/admin/taxDetails.gohtml:130
msgctxt "title"
msgid "Tourism"
msgstr "Turismo"
#: web/templates/admin/taxDetails.gohtml:133
msgctxt "input"
msgid "RTC number"
msgstr "Número RTC"
#: web/templates/admin/taxDetails.gohtml:141
msgctxt "input"
msgid "Tourist Tax"
msgstr "Impuesto turístico"
#: web/templates/admin/taxDetails.gohtml:150
msgctxt "input"
msgid "Tourist Tax Days"
msgstr "Días del impuesto turístico"
#: web/templates/admin/taxDetails.gohtml:159
msgctxt "title"
msgid "Invoicing"
msgstr "Facturación"
#: web/templates/admin/taxDetails.gohtml:162
msgctxt "input"
msgid "Invoice Number Format"
msgstr "Formato de número de factura"
#: web/templates/admin/taxDetails.gohtml:170
msgctxt "input"
msgid "Legal Disclaimer"
msgstr "Nota legal"
#: web/templates/admin/surroundings/form.gohtml:8
#: web/templates/admin/surroundings/form.gohtml:29
msgctxt "title"
msgid "Edit Highlight"
msgstr "Edición del punto de interés"
#: web/templates/admin/surroundings/form.gohtml:10
#: web/templates/admin/surroundings/form.gohtml:31
msgctxt "title"
msgid "New Highlight"
msgstr "Nuevo punto de interés"
#: web/templates/admin/surroundings/index.gohtml:6
msgctxt "title"
msgid "Surroundings Page"
msgstr "Página del entorno"
#: web/templates/admin/surroundings/index.gohtml:14
msgctxt "title"
msgid "Ad"
msgstr "Anuncio"
#: web/templates/admin/surroundings/index.gohtml:21
msgctxt "input"
msgid "Title"
msgstr "Título"
#: web/templates/admin/surroundings/index.gohtml:37
msgctxt "input"
msgid "Link Text"
msgstr "Texto del enlace"
#: web/templates/admin/surroundings/index.gohtml:50
msgctxt "input"
msgid "Link URL"
msgstr "Dirección del enlace"
#: web/templates/admin/surroundings/index.gohtml:59
msgid "Are you sure you wish to delete the ad?"
msgstr "¿Estáis seguro de querer borrar este enlace?"
#: web/templates/admin/surroundings/index.gohtml:68
msgctxt "title"
msgid "Highlights"
msgstr "Puntos de interés"
#: web/templates/admin/surroundings/index.gohtml:69
msgctxt "action"
msgid "Add highlight"
msgstr "Añadir punto de interés"
#: web/templates/admin/surroundings/index.gohtml:88
msgid "Are you sure you wish to delete this highlight?"
msgstr "¿Estáis seguro de querer borrar este punto de interés?"
#: web/templates/admin/surroundings/index.gohtml:110
msgid "No highlights added yet."
msgstr "No se ha añadido ningún punto de interés todavía."
#: web/templates/admin/amenity/feature/form.gohtml:8
msgctxt "title"
msgid "Edit Amenity Feature"
msgstr "Edición de las características de la instalación"
#: web/templates/admin/amenity/feature/form.gohtml:10
msgctxt "title"
msgid "New Amenity Feature"
msgstr "Nueva característica de la instalación"
#: web/templates/admin/amenity/feature/form.gohtml:16
#: web/templates/admin/amenity/feature/index.gohtml:10
#: web/templates/admin/amenity/carousel/form.gohtml:16
#: web/templates/admin/amenity/carousel/index.gohtml:10
#: web/templates/admin/amenity/form.gohtml:15
#: web/templates/admin/amenity/index.gohtml:6
#: web/templates/admin/layout.gohtml:49
msgctxt "title"
msgid "Amenities"
msgstr "Instalaciones"
#: web/templates/admin/amenity/feature/form.gohtml:17
#: web/templates/admin/amenity/feature/index.gohtml:6
msgctxt "title"
msgid "Amenity Features"
msgstr "Características de la instalación"
#: web/templates/admin/amenity/feature/index.gohtml:56
msgid "No amenity features added yet."
msgstr "No se ha añadido ninguna característica a la instalación todavía."
#: web/templates/admin/amenity/carousel/form.gohtml:8
msgctxt "title"
msgid "Edit Amenity Carousel Slide"
msgstr "Edición de la diapositiva del carrusel de la instalación"
#: web/templates/admin/amenity/carousel/form.gohtml:10
msgctxt "title"
msgid "New Amenity Carousel Slide"
msgstr "Nueva diapositiva del carrusel de la instalación"
#: web/templates/admin/amenity/carousel/form.gohtml:17
#: web/templates/admin/amenity/carousel/index.gohtml:6
msgctxt "title"
msgid "Amenity Carousel"
msgstr "Carrusel de la instalación"
#: web/templates/admin/amenity/form.gohtml:8
msgctxt "title"
msgid "Edit Amenity"
msgstr "Edición de la instalación"
#: web/templates/admin/amenity/form.gohtml:10
msgctxt "title"
msgid "New Amenity"
msgstr "Nueva instalación"
#: web/templates/admin/amenity/form.gohtml:33
#: web/templates/admin/amenity/index.gohtml:24
msgctxt "amenity"
msgid "Active"
msgstr "Activa"
#: web/templates/admin/amenity/index.gohtml:14
msgctxt "action"
msgid "Add Amenity"
msgstr "Añadir instalación"
#: web/templates/admin/amenity/index.gohtml:29
msgid "Are you sure you wish to delete this amenity?"
msgstr "¿Estáis seguro de querer borrar esta instalación?"
#: web/templates/admin/amenity/index.gohtml:53
msgid "No amenities added yet."
msgstr "No se ha añadido ninguna instalación todavía."
#: web/templates/admin/layout.gohtml:29
msgctxt "title"
msgid "User Menu"
msgstr "Menú de usuario"
#: web/templates/admin/layout.gohtml:37
msgctxt "title"
msgid "Company Settings"
msgstr "Parámetros de la empresa"
#: web/templates/admin/layout.gohtml:55
#: web/templates/admin/media/form.gohtml:10
#: web/templates/admin/media/index.gohtml:6
#: web/templates/admin/media/index.gohtml:14
#: web/templates/admin/media/upload.gohtml:10
msgctxt "title"
msgid "Media"
msgstr "Medios"
Add the logout button Conceptually, to logout we have to “delete the session”, thus the best HTTP verb would be `DELETE`. However, there is no way to send a `DELETE` request with a regular HTML form, and it seems that never will be[0]. I could use a POST, optionally with a “method override” technique, but i was planing to use HTMx anyway, so this was as good an opportunity to include it as any. In this application i am not concerned with people not having JavaScript enabled, because it is for a customer that has a known environment, and we do not have much time anyway. Therefore, i opted to forgo progressive enhancement in cases like this: if `DELETE` is needed, use `hx-delete`. Unfortunately, i can not use a <form> with a hidden <input> for the CSRF token, because `DELETE` requests do not have body and the value should be added as query parameters, like a form with GET method, but HTMx does the incorrect thing here: sends the values in the request’s body. That’s why i have to use a custom header and the `hx-header` directive to include the CSRF token. Then, by default HTMx targets the triggered element for swap with the response from the server, but after a logout i want to redirect the user to the login form again. I could set the hx-target to button to replace the whole body, or tell the client to redirect to the new location. I actually do not know which one is “better”. Maybe the hx-target is best because then everything is handled by the client, but in the case of logout, since it is possible that i might want to load scripts only for logged-in users in the future, i opted for the full page reload. However, HTMx does not want to reload a page that return HTTP 401, hence i had to include the GET method to /login in order to return the login form with a response of HTTP 200, which also helps when reloading in the browser after a failed login attempt. I am not worried with the HTTP 401 when attempting to load a page as guest, because this request most probably comes from the browser, not HTMx, and it will show the login form as intended—even though it is not compliant, since it does not return the WWW-Authenticate header, but this is the best i can do given that no cookie-based authentication method has been accepted[1]. [0]: https://www.w3.org/Bugs/Public/show_bug.cgi?id=10671#c16 [1]: https://datatracker.ietf.org/doc/id/draft-broyer-http-cookie-auth-00.html
2023-07-26 11:49:47 +00:00
#: web/templates/admin/layout.gohtml:58 web/templates/admin/home/index.gohtml:6
Make home page’s carousel manageable via the database I debated with myself whether to create the home_carousel relation or rather if it would be better to have a single carousel relation for all pages. However, i thought that it would be actually harder to maintain a single relation because i would need an additional column to tell one carrousel from another, and what would that column be? An enum? A foreign key to another relation? home_carousel carries no such issues. I was starting to duplicate logic all over the packages, such as the way to encode media paths or “localization” (l10n) input fields. Therefore, i refactorized them. In the case of media path, i added a function that accepts rows of media, because always need the same columns from the row, and it was yet another repetition if i needed to pass them all the time. Plus, these kind of functions can be called as `table.function`, that make them look like columns from the table; if PostgreSQL implemented virtual generated columns, i would have used that instead. I am not sure whether that media_path function can be immutable. An immutable function is “guaranteed to return the same results given the same arguments forever”, which would be true if the inputs where the hash and the original_filename columns, instead of the whole rows, but i left it as static because i did not know whether PostgreSQL interprets the “same row but with different values” as a different input. That is, whether PostgreSQL’s concept of row is the actual tuple or the space that has a rowid, irrespective of contents; in the latter case, the function can not be immutable. Just to be in the safe side, i left it stable. The home page was starting to grow a bit too much inside the app package, new that it has its own admin handler, and moved it all to a separate package.
2023-09-14 23:05:38 +00:00
msgctxt "title"
msgid "Home Page"
msgstr "Página de inicio"
Make home page’s carousel manageable via the database I debated with myself whether to create the home_carousel relation or rather if it would be better to have a single carousel relation for all pages. However, i thought that it would be actually harder to maintain a single relation because i would need an additional column to tell one carrousel from another, and what would that column be? An enum? A foreign key to another relation? home_carousel carries no such issues. I was starting to duplicate logic all over the packages, such as the way to encode media paths or “localization” (l10n) input fields. Therefore, i refactorized them. In the case of media path, i added a function that accepts rows of media, because always need the same columns from the row, and it was yet another repetition if i needed to pass them all the time. Plus, these kind of functions can be called as `table.function`, that make them look like columns from the table; if PostgreSQL implemented virtual generated columns, i would have used that instead. I am not sure whether that media_path function can be immutable. An immutable function is “guaranteed to return the same results given the same arguments forever”, which would be true if the inputs where the hash and the original_filename columns, instead of the whole rows, but i left it as static because i did not know whether PostgreSQL interprets the “same row but with different values” as a different input. That is, whether PostgreSQL’s concept of row is the actual tuple or the space that has a rowid, irrespective of contents; in the latter case, the function can not be immutable. Just to be in the safe side, i left it stable. The home page was starting to grow a bit too much inside the app package, new that it has its own admin handler, and moved it all to a separate package.
2023-09-14 23:05:38 +00:00
#: web/templates/admin/layout.gohtml:78
msgctxt "action"
msgid "Logout"
msgstr "Salir"
#: web/templates/admin/layout.gohtml:92
#: web/templates/admin/booking/index.gohtml:6
#: web/templates/admin/booking/index.gohtml:16
msgctxt "title"
msgid "Bookings"
msgstr "Reservas"
#: web/templates/admin/layout.gohtml:101
msgid "Breadcrumb"
msgstr "Migas de pan"
#: web/templates/admin/layout.gohtml:113
msgid "Camper Version: %s"
msgstr "Camper versión: %s"
#: web/templates/admin/home/index.gohtml:15
msgctxt "title"
msgid "Slogan"
msgstr "Eslogan"
#: web/templates/admin/home/index.gohtml:21
msgctxt "input"
msgid "Slogan"
msgstr "Eslogan"
#: web/templates/admin/home/index.gohtml:38
msgctxt "title"
msgid "Cover"
msgstr "Portada"
#: web/templates/admin/home/index.gohtml:39
msgctxt "action"
msgid "Add cover image"
msgstr "Añadir imagen de portada"
#: web/templates/admin/home/index.gohtml:58
msgid "Are you sure you wish to delete this cover image?"
msgstr "¿Estáis seguro de querer borrar esta imagen de portada?"
#: web/templates/admin/home/index.gohtml:80
msgid "No images added to the cover yet."
msgstr "No se ha añadido ninguna imagen de portada todavía."
Add the upload form to the media picker It makes easier to upload new images from the place where we need it, instead of having to go to the media section each time. It was a little messy, this one. First of all, I realized that POSTint to /admin/media/picker to get the new media field was wrong: i was not asking the server to “accept an entity”, but only requesting a new HTML value, just like a GET to /admin/media/upload requests the form to upload a new media, thus here i should do the same, except i needed the query parameters to change the field, which is fine—it is actually a different resource, thus a different URL. Then, i thought that i could not POST the upload to /admin/media, because i returned a different HTML —the media field—, so i reused the recently unused POST to /admin/media/picker to upload that file and return the HTML for the field. It was wrong, because i was not requesting the server to put the file as a subordinate of /admin/media/picker, only /admin/media, but i did not come up with any other solution. Since i had two different upload functions now, i created uploadForm’s Handle method to refactorize the duplicated logic to a single place. Unfortunately, i did not work as i expected because uploadForm’s and mediaPicker’s MustRender methods are different, and mediaPicker has to embed uploadForm to render the form in the picker. That made me change Handle’s output to a boolean and error in order for the HTTP handler function know when to render the form with the error messages with the proper MustRender handler. However, I saw the opportunity of reusing that Handler method for editMedia, that was doing mostly the same job, but had to call a different Validate than uploadForm’s, because editMedia does not require the uploaded file. That’s when i realized that i could use an interface and that this interface could be reused not only within media but throughout the application, and added HandleMultipart in form. Had to create a different interface for multipart forms because they need different parameters in Parse that non-multipart form, when i add that interface, hence had to also change Parse to ParseForm to account for the difference in signature; not a big deal. After all that, i realized that i **could** POST to /admin/media in both cases, because i always return “an HTML entity”, it just happens that for the media section it is empty with a redirect, and for the picker is the field. That made the whole Handle method a bit redundant, but i left it nevertheless, as i find it slightly easier to read the uploadMedia function now.
2023-09-21 23:40:22 +00:00
#: web/templates/admin/media/picker.gohtml:8
msgctxt "title"
msgid "Media Picker"
msgstr "Selector de medio"
Add the upload form to the media picker It makes easier to upload new images from the place where we need it, instead of having to go to the media section each time. It was a little messy, this one. First of all, I realized that POSTint to /admin/media/picker to get the new media field was wrong: i was not asking the server to “accept an entity”, but only requesting a new HTML value, just like a GET to /admin/media/upload requests the form to upload a new media, thus here i should do the same, except i needed the query parameters to change the field, which is fine—it is actually a different resource, thus a different URL. Then, i thought that i could not POST the upload to /admin/media, because i returned a different HTML —the media field—, so i reused the recently unused POST to /admin/media/picker to upload that file and return the HTML for the field. It was wrong, because i was not requesting the server to put the file as a subordinate of /admin/media/picker, only /admin/media, but i did not come up with any other solution. Since i had two different upload functions now, i created uploadForm’s Handle method to refactorize the duplicated logic to a single place. Unfortunately, i did not work as i expected because uploadForm’s and mediaPicker’s MustRender methods are different, and mediaPicker has to embed uploadForm to render the form in the picker. That made me change Handle’s output to a boolean and error in order for the HTTP handler function know when to render the form with the error messages with the proper MustRender handler. However, I saw the opportunity of reusing that Handler method for editMedia, that was doing mostly the same job, but had to call a different Validate than uploadForm’s, because editMedia does not require the uploaded file. That’s when i realized that i could use an interface and that this interface could be reused not only within media but throughout the application, and added HandleMultipart in form. Had to create a different interface for multipart forms because they need different parameters in Parse that non-multipart form, when i add that interface, hence had to also change Parse to ParseForm to account for the difference in signature; not a big deal. After all that, i realized that i **could** POST to /admin/media in both cases, because i always return “an HTML entity”, it just happens that for the media section it is empty with a redirect, and for the picker is the field. That made the whole Handle method a bit redundant, but i left it nevertheless, as i find it slightly easier to read the uploadMedia function now.
2023-09-21 23:40:22 +00:00
#: web/templates/admin/media/picker.gohtml:19
msgctxt "title"
msgid "Upload New Media"
msgstr "Subida de un nuevo medio"
#: web/templates/admin/media/picker.gohtml:22
#: web/templates/admin/media/upload.gohtml:21
Add the upload form to the media picker It makes easier to upload new images from the place where we need it, instead of having to go to the media section each time. It was a little messy, this one. First of all, I realized that POSTint to /admin/media/picker to get the new media field was wrong: i was not asking the server to “accept an entity”, but only requesting a new HTML value, just like a GET to /admin/media/upload requests the form to upload a new media, thus here i should do the same, except i needed the query parameters to change the field, which is fine—it is actually a different resource, thus a different URL. Then, i thought that i could not POST the upload to /admin/media, because i returned a different HTML —the media field—, so i reused the recently unused POST to /admin/media/picker to upload that file and return the HTML for the field. It was wrong, because i was not requesting the server to put the file as a subordinate of /admin/media/picker, only /admin/media, but i did not come up with any other solution. Since i had two different upload functions now, i created uploadForm’s Handle method to refactorize the duplicated logic to a single place. Unfortunately, i did not work as i expected because uploadForm’s and mediaPicker’s MustRender methods are different, and mediaPicker has to embed uploadForm to render the form in the picker. That made me change Handle’s output to a boolean and error in order for the HTTP handler function know when to render the form with the error messages with the proper MustRender handler. However, I saw the opportunity of reusing that Handler method for editMedia, that was doing mostly the same job, but had to call a different Validate than uploadForm’s, because editMedia does not require the uploaded file. That’s when i realized that i could use an interface and that this interface could be reused not only within media but throughout the application, and added HandleMultipart in form. Had to create a different interface for multipart forms because they need different parameters in Parse that non-multipart form, when i add that interface, hence had to also change Parse to ParseForm to account for the difference in signature; not a big deal. After all that, i realized that i **could** POST to /admin/media in both cases, because i always return “an HTML entity”, it just happens that for the media section it is empty with a redirect, and for the picker is the field. That made the whole Handle method a bit redundant, but i left it nevertheless, as i find it slightly easier to read the uploadMedia function now.
2023-09-21 23:40:22 +00:00
msgctxt "input"
msgid "File"
msgstr "Archivo"
#: web/templates/admin/media/picker.gohtml:26
#: web/templates/admin/media/form.gohtml:26
#: web/templates/admin/media/upload.gohtml:25
Add the upload form to the media picker It makes easier to upload new images from the place where we need it, instead of having to go to the media section each time. It was a little messy, this one. First of all, I realized that POSTint to /admin/media/picker to get the new media field was wrong: i was not asking the server to “accept an entity”, but only requesting a new HTML value, just like a GET to /admin/media/upload requests the form to upload a new media, thus here i should do the same, except i needed the query parameters to change the field, which is fine—it is actually a different resource, thus a different URL. Then, i thought that i could not POST the upload to /admin/media, because i returned a different HTML —the media field—, so i reused the recently unused POST to /admin/media/picker to upload that file and return the HTML for the field. It was wrong, because i was not requesting the server to put the file as a subordinate of /admin/media/picker, only /admin/media, but i did not come up with any other solution. Since i had two different upload functions now, i created uploadForm’s Handle method to refactorize the duplicated logic to a single place. Unfortunately, i did not work as i expected because uploadForm’s and mediaPicker’s MustRender methods are different, and mediaPicker has to embed uploadForm to render the form in the picker. That made me change Handle’s output to a boolean and error in order for the HTTP handler function know when to render the form with the error messages with the proper MustRender handler. However, I saw the opportunity of reusing that Handler method for editMedia, that was doing mostly the same job, but had to call a different Validate than uploadForm’s, because editMedia does not require the uploaded file. That’s when i realized that i could use an interface and that this interface could be reused not only within media but throughout the application, and added HandleMultipart in form. Had to create a different interface for multipart forms because they need different parameters in Parse that non-multipart form, when i add that interface, hence had to also change Parse to ParseForm to account for the difference in signature; not a big deal. After all that, i realized that i **could** POST to /admin/media in both cases, because i always return “an HTML entity”, it just happens that for the media section it is empty with a redirect, and for the picker is the field. That made the whole Handle method a bit redundant, but i left it nevertheless, as i find it slightly easier to read the uploadMedia function now.
2023-09-21 23:40:22 +00:00
msgid "Maximum upload file size: %s"
msgstr "Tamaño máximo del archivos a subir: %s"
#: web/templates/admin/media/picker.gohtml:31
#: web/templates/admin/media/upload.gohtml:30
Add the upload form to the media picker It makes easier to upload new images from the place where we need it, instead of having to go to the media section each time. It was a little messy, this one. First of all, I realized that POSTint to /admin/media/picker to get the new media field was wrong: i was not asking the server to “accept an entity”, but only requesting a new HTML value, just like a GET to /admin/media/upload requests the form to upload a new media, thus here i should do the same, except i needed the query parameters to change the field, which is fine—it is actually a different resource, thus a different URL. Then, i thought that i could not POST the upload to /admin/media, because i returned a different HTML —the media field—, so i reused the recently unused POST to /admin/media/picker to upload that file and return the HTML for the field. It was wrong, because i was not requesting the server to put the file as a subordinate of /admin/media/picker, only /admin/media, but i did not come up with any other solution. Since i had two different upload functions now, i created uploadForm’s Handle method to refactorize the duplicated logic to a single place. Unfortunately, i did not work as i expected because uploadForm’s and mediaPicker’s MustRender methods are different, and mediaPicker has to embed uploadForm to render the form in the picker. That made me change Handle’s output to a boolean and error in order for the HTTP handler function know when to render the form with the error messages with the proper MustRender handler. However, I saw the opportunity of reusing that Handler method for editMedia, that was doing mostly the same job, but had to call a different Validate than uploadForm’s, because editMedia does not require the uploaded file. That’s when i realized that i could use an interface and that this interface could be reused not only within media but throughout the application, and added HandleMultipart in form. Had to create a different interface for multipart forms because they need different parameters in Parse that non-multipart form, when i add that interface, hence had to also change Parse to ParseForm to account for the difference in signature; not a big deal. After all that, i realized that i **could** POST to /admin/media in both cases, because i always return “an HTML entity”, it just happens that for the media section it is empty with a redirect, and for the picker is the field. That made the whole Handle method a bit redundant, but i left it nevertheless, as i find it slightly easier to read the uploadMedia function now.
2023-09-21 23:40:22 +00:00
msgctxt "action"
msgid "Upload"
msgstr "Subir"
#: web/templates/admin/media/picker.gohtml:47
Add the upload form to the media picker It makes easier to upload new images from the place where we need it, instead of having to go to the media section each time. It was a little messy, this one. First of all, I realized that POSTint to /admin/media/picker to get the new media field was wrong: i was not asking the server to “accept an entity”, but only requesting a new HTML value, just like a GET to /admin/media/upload requests the form to upload a new media, thus here i should do the same, except i needed the query parameters to change the field, which is fine—it is actually a different resource, thus a different URL. Then, i thought that i could not POST the upload to /admin/media, because i returned a different HTML —the media field—, so i reused the recently unused POST to /admin/media/picker to upload that file and return the HTML for the field. It was wrong, because i was not requesting the server to put the file as a subordinate of /admin/media/picker, only /admin/media, but i did not come up with any other solution. Since i had two different upload functions now, i created uploadForm’s Handle method to refactorize the duplicated logic to a single place. Unfortunately, i did not work as i expected because uploadForm’s and mediaPicker’s MustRender methods are different, and mediaPicker has to embed uploadForm to render the form in the picker. That made me change Handle’s output to a boolean and error in order for the HTTP handler function know when to render the form with the error messages with the proper MustRender handler. However, I saw the opportunity of reusing that Handler method for editMedia, that was doing mostly the same job, but had to call a different Validate than uploadForm’s, because editMedia does not require the uploaded file. That’s when i realized that i could use an interface and that this interface could be reused not only within media but throughout the application, and added HandleMultipart in form. Had to create a different interface for multipart forms because they need different parameters in Parse that non-multipart form, when i add that interface, hence had to also change Parse to ParseForm to account for the difference in signature; not a big deal. After all that, i realized that i **could** POST to /admin/media in both cases, because i always return “an HTML entity”, it just happens that for the media section it is empty with a redirect, and for the picker is the field. That made the whole Handle method a bit redundant, but i left it nevertheless, as i find it slightly easier to read the uploadMedia function now.
2023-09-21 23:40:22 +00:00
msgctxt "title"
msgid "Choose Existing Media"
msgstr "Elección de un medio existente"
#: web/templates/admin/media/picker.gohtml:58
#: web/templates/admin/media/index.gohtml:23
msgid "No media uploaded yet."
msgstr "No se ha subido ningún medio todavía."
#: web/templates/admin/media/form.gohtml:6
#: web/templates/admin/media/form.gohtml:16
msgctxt "title"
msgid "Edit Media"
msgstr "Edición de medio"
#: web/templates/admin/media/form.gohtml:22
msgctxt "input"
msgid "Updated file"
msgstr "Archivo actualizado"
#: web/templates/admin/media/form.gohtml:31
msgctxt "input"
msgid "Filename"
msgstr "Nombre de archivo"
#: web/templates/admin/media/index.gohtml:15
msgctxt "action"
msgid "Upload media"
msgstr "Subir medio"
#: web/templates/admin/media/upload.gohtml:6
#: web/templates/admin/media/upload.gohtml:16
msgctxt "title"
msgid "Upload Media"
msgstr "Subida de medio"
#: web/templates/admin/booking/index.gohtml:14
msgctxt "action"
msgid "Add Booking"
msgstr "Añadir reserva"
#: web/templates/admin/booking/index.gohtml:15
msgctxt "action"
msgid "Export Bookings"
msgstr "Exportar eservas"
#: web/templates/admin/booking/index.gohtml:22
msgctxt "header"
msgid "Arrival Date"
msgstr "Fecha de llegada"
#: web/templates/admin/booking/index.gohtml:23
msgctxt "header"
msgid "Departure Date"
msgstr "Fecha de salida"
#: web/templates/admin/booking/index.gohtml:24
msgctxt "header"
msgid "Holder Name"
msgstr "Nombre del titular"
#: web/templates/admin/booking/index.gohtml:41
msgid "No booking found."
msgstr "No se ha encontrado ninguna reserva."
#: pkg/payment/settings.go:37
msgctxt "redsys environment"
msgid "Test"
msgstr "Pruebas"
#: pkg/payment/settings.go:41
msgctxt "redsys environment"
msgid "Live"
msgstr "Real"
#: pkg/payment/settings.go:50
msgctxt "redsys integration"
msgid "InSite"
msgstr "InSite"
#: pkg/payment/settings.go:54
msgctxt "redsys integration"
msgid "Redirect"
msgstr "Redirección"
#: pkg/payment/settings.go:98
msgid "Merchant code can not be empty."
msgstr "No podéis dejar el código del comercio en blanco."
#: pkg/payment/settings.go:99
msgid "Merchant code must be exactly nine digits long."
msgstr "El código del comercio tiene que ser de nueve dígitos."
#: pkg/payment/settings.go:100
msgid "Merchant code must be a number."
msgstr "El código del comercio tiene que ser un número."
#: pkg/payment/settings.go:104
msgid "Terminal number can not be empty."
msgstr "No podéis dejar el número de terminal en blanco."
#: pkg/payment/settings.go:105
msgid "Terminal number must be a number between 1 and 999."
msgstr "El número de terminal tiene que ser entre 1 y 999."
#: pkg/payment/settings.go:113
msgid "Selected environment is not valid."
msgstr "El entorno escogido no es válido."
#: pkg/payment/settings.go:114
msgid "Selected integration is not valid."
msgstr "La integración escogida no es válida."
#: pkg/payment/settings.go:117
msgid "The merchant key is not valid."
msgstr "Esta clave del comercio no es válida."
#: pkg/payment/public.go:110
msgctxt "order product name"
msgid "Campsite Booking"
msgstr "Reserva de camping"
#: pkg/payment/public.go:374
msgctxt "subject"
msgid "Booking payment successfully received"
msgstr "Se ha recibido correctamente el pago de la reserva"
#: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:365
#: pkg/campsite/types/feature.go:272 pkg/campsite/types/admin.go:577
#: pkg/campsite/feature.go:269 pkg/season/admin.go:411
#: pkg/services/admin.go:316 pkg/surroundings/admin.go:340
#: pkg/amenity/feature.go:269 pkg/amenity/admin.go:283
2023-12-22 01:23:18 +00:00
msgid "Name can not be empty."
msgstr "No podéis dejar el nombre en blanco."
#: pkg/legal/admin.go:259 pkg/campsite/types/option.go:366
#: pkg/campsite/types/feature.go:273 pkg/campsite/types/admin.go:578
#: pkg/campsite/feature.go:270 pkg/amenity/feature.go:270
2023-12-22 01:23:18 +00:00
msgid "Name must have at least one letter."
msgstr "El nombre tiene que tener como mínimo una letra."
#: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:225
#: pkg/campsite/carousel.go:227 pkg/amenity/carousel.go:227
msgctxt "input"
msgid "Slide image"
msgstr "Imagen de la diapositiva"
#: pkg/carousel/admin.go:277 pkg/campsite/types/carousel.go:226
#: pkg/campsite/carousel.go:228 pkg/amenity/carousel.go:228
msgctxt "action"
msgid "Set slide image"
msgstr "Establecer la imagen de la diapositiva"
#: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:299
#: pkg/campsite/carousel.go:302 pkg/surroundings/admin.go:335
#: pkg/amenity/carousel.go:302
msgid "Slide image can not be empty."
msgstr "No podéis dejar la imagen de la diapositiva en blanco."
#: pkg/carousel/admin.go:347 pkg/campsite/types/carousel.go:300
#: pkg/campsite/carousel.go:303 pkg/surroundings/admin.go:336
#: pkg/amenity/carousel.go:303
msgid "Slide image must be an image media type."
msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen."
#: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:224
#: pkg/booking/public.go:544
msgid "Email can not be empty."
msgstr "No podéis dejar el correo-e en blanco."
#: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:225
#: pkg/booking/public.go:545
msgid "This email is not valid. It should be like name@domain.com."
msgstr "Este correo-e no es válido. Tiene que ser parecido a nombre@dominio.com."
Add the logout button Conceptually, to logout we have to “delete the session”, thus the best HTTP verb would be `DELETE`. However, there is no way to send a `DELETE` request with a regular HTML form, and it seems that never will be[0]. I could use a POST, optionally with a “method override” technique, but i was planing to use HTMx anyway, so this was as good an opportunity to include it as any. In this application i am not concerned with people not having JavaScript enabled, because it is for a customer that has a known environment, and we do not have much time anyway. Therefore, i opted to forgo progressive enhancement in cases like this: if `DELETE` is needed, use `hx-delete`. Unfortunately, i can not use a <form> with a hidden <input> for the CSRF token, because `DELETE` requests do not have body and the value should be added as query parameters, like a form with GET method, but HTMx does the incorrect thing here: sends the values in the request’s body. That’s why i have to use a custom header and the `hx-header` directive to include the CSRF token. Then, by default HTMx targets the triggered element for swap with the response from the server, but after a logout i want to redirect the user to the login form again. I could set the hx-target to button to replace the whole body, or tell the client to redirect to the new location. I actually do not know which one is “better”. Maybe the hx-target is best because then everything is handled by the client, but in the case of logout, since it is possible that i might want to load scripts only for logged-in users in the future, i opted for the full page reload. However, HTMx does not want to reload a page that return HTTP 401, hence i had to include the GET method to /login in order to return the login form with a response of HTTP 200, which also helps when reloading in the browser after a failed login attempt. I am not worried with the HTTP 401 when attempting to load a page as guest, because this request most probably comes from the browser, not HTMx, and it will show the login form as intended—even though it is not compliant, since it does not return the WWW-Authenticate header, but this is the best i can do given that no cookie-based authentication method has been accepted[1]. [0]: https://www.w3.org/Bugs/Public/show_bug.cgi?id=10671#c16 [1]: https://datatracker.ietf.org/doc/id/draft-broyer-http-cookie-auth-00.html
2023-07-26 11:49:47 +00:00
#: pkg/app/login.go:59
msgid "Password can not be empty."
msgstr "No podéis dejar la contraseña en blanco."
#: pkg/app/login.go:86
msgid "Invalid user or password."
msgstr "Usuario o contraseña incorrectos."
Add the logout button Conceptually, to logout we have to “delete the session”, thus the best HTTP verb would be `DELETE`. However, there is no way to send a `DELETE` request with a regular HTML form, and it seems that never will be[0]. I could use a POST, optionally with a “method override” technique, but i was planing to use HTMx anyway, so this was as good an opportunity to include it as any. In this application i am not concerned with people not having JavaScript enabled, because it is for a customer that has a known environment, and we do not have much time anyway. Therefore, i opted to forgo progressive enhancement in cases like this: if `DELETE` is needed, use `hx-delete`. Unfortunately, i can not use a <form> with a hidden <input> for the CSRF token, because `DELETE` requests do not have body and the value should be added as query parameters, like a form with GET method, but HTMx does the incorrect thing here: sends the values in the request’s body. That’s why i have to use a custom header and the `hx-header` directive to include the CSRF token. Then, by default HTMx targets the triggered element for swap with the response from the server, but after a logout i want to redirect the user to the login form again. I could set the hx-target to button to replace the whole body, or tell the client to redirect to the new location. I actually do not know which one is “better”. Maybe the hx-target is best because then everything is handled by the client, but in the case of logout, since it is possible that i might want to load scripts only for logged-in users in the future, i opted for the full page reload. However, HTMx does not want to reload a page that return HTTP 401, hence i had to include the GET method to /login in order to return the login form with a response of HTTP 200, which also helps when reloading in the browser after a failed login attempt. I am not worried with the HTTP 401 when attempting to load a page as guest, because this request most probably comes from the browser, not HTMx, and it will show the login form as intended—even though it is not compliant, since it does not return the WWW-Authenticate header, but this is the best i can do given that no cookie-based authentication method has been accepted[1]. [0]: https://www.w3.org/Bugs/Public/show_bug.cgi?id=10671#c16 [1]: https://datatracker.ietf.org/doc/id/draft-broyer-http-cookie-auth-00.html
2023-07-26 11:49:47 +00:00
#: pkg/app/user.go:197
msgctxt "language option"
msgid "Automatic"
msgstr "Automático"
#: pkg/app/user.go:250
msgid "Confirmation does not match password."
msgstr "La confirmación no se corresponde con la contraseña."
#: pkg/app/user.go:251 pkg/company/admin.go:250
msgid "Selected language is not valid."
msgstr "El idioma escogido no es válido."
#: pkg/app/user.go:253
msgid "File must be a valid PNG or JPEG image."
msgstr "El archivo tiene que ser una imagen PNG o JPEG válida."
#: pkg/app/admin.go:73
Split templates and handlers into admin and public I need to check that the user is an employee (or admin) in administration handlers, but i do not want to do it for each handler, because i am bound to forget it. Thus, i added the /admin sub-path for these resources. The public-facing web is the rest of the resources outside /admin, but for now there is only home, to test whether it works as expected or not. The public-facing web can not relay on the user’s language settings, as the guest user has no way to set that. I would be happy to just use the Accept-Language header for that, but apparently Google does not use that header[0], and they give four alternatives: a country-specific domain, a subdomain with a generic top-level domain (gTLD), subdirectories with a gTLD, or URL parameters (e.g., site.com?loc=de). Of the four, Google does not recommend URL parameters, and the customer is already using subdirectories with the current site, therefor that’s what i have chosen. Google also tells me that it is a very good idea to have links between localized version of the same resources, either with <link> elements, Link HTTP response headers, or a sitemap file[1]; they are all equivalent in the eyes of Google. I have choosen the Link response headers way, because for that i can simply “augment” ResponseHeader to automatically add these headers when the response status is 2xx, otherwise i would need to pass down the original URL path until it reaches the template. Even though Camper is supposed to be a “generic”, multi-company application, i think i will stick to the easiest route and write the templates for just the “first” customer. [0]: https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites [1]: https://developers.google.com/search/docs/specialty/international/localized-versions
2023-08-05 01:42:37 +00:00
msgid "Access forbidden"
msgstr "Acceso prohibido"
#: pkg/campsite/types/option.go:369
msgid "Minimum can not be empty."
msgstr "No podéis dejar el mínimo en blanco."
#: pkg/campsite/types/option.go:370
msgid "Minimum must be an integer number."
msgstr "El valor de mínimo tiene que ser un número entero."
#: pkg/campsite/types/option.go:372
msgid "Minimum must be zero or greater."
msgstr "El valor de mínimo tiene que ser como mínimo cero."
#: pkg/campsite/types/option.go:375
msgid "Maximum can not be empty."
msgstr "No podéis dejar el máxmimo en blanco."
#: pkg/campsite/types/option.go:376
msgid "Maximum must be an integer number."
msgstr "El valor del máximo tiene que ser un número entero."
#: pkg/campsite/types/option.go:378
msgid "Maximum must be equal or greater than minimum."
msgstr "El valor del máximo tiene que ser igual o mayor al del mínimo."
#: pkg/campsite/types/option.go:382
msgid "Price can not be empty."
msgstr "No podéis dejar el precio en blanco."
#: pkg/campsite/types/option.go:383
msgid "Price must be a decimal number."
msgstr "El precio tiene que ser un número decimal."
#: pkg/campsite/types/option.go:384
msgid "Price must be zero or greater."
msgstr "El precio tiene que ser como mínimo cero."
#: pkg/campsite/types/feature.go:271 pkg/campsite/feature.go:268
#: pkg/services/admin.go:315 pkg/amenity/feature.go:268
msgid "Selected icon is not valid."
msgstr "El icono escogido no es válido."
#: pkg/campsite/types/admin.go:328
msgctxt "input"
msgid "Cover image"
msgstr "Imagen de portada"
#: pkg/campsite/types/admin.go:329
msgctxt "action"
msgid "Set campsite type cover"
msgstr "Establecer la portada del tipo de alojamiento"
#: pkg/campsite/types/admin.go:580
msgid "Check-in can not be empty."
msgstr "No podéis dejar la entrada en blanco."
#: pkg/campsite/types/admin.go:581
msgid "Check-out can not be empty."
msgstr "No podéis dejar la salida en blanco."
#: pkg/campsite/types/admin.go:582
msgid "Cover image can not be empty."
msgstr "No podéis dejar la imagen de portada en blanco."
#: pkg/campsite/types/admin.go:583
msgid "Cover image must be an image media type."
msgstr "La imagen de portada tiene que ser un medio de tipo imagen."
#: pkg/campsite/types/admin.go:587
msgid "Maximum number of campers can not be empty."
msgstr "No podéis dejar el número máximo de personas en blanco."
#: pkg/campsite/types/admin.go:588
msgid "Maximum number of campers must be an integer number."
msgstr "El número máximo de personas tiene que ser entero."
#: pkg/campsite/types/admin.go:589
msgid "Maximum number of campers must be one or greater."
msgstr "El número máximo de personas no puede ser cero."
#: pkg/campsite/types/admin.go:592
2023-10-01 19:14:39 +00:00
msgid "Minimum number of nights can not be empty."
msgstr "No podéis dejar el número mínimo de noches en blanco."
#: pkg/campsite/types/admin.go:593
2023-10-01 19:14:39 +00:00
msgid "Minimum number of nights must be an integer."
msgstr "El número mínimo de noches tiene que ser entero."
#: pkg/campsite/types/admin.go:594
2023-10-01 19:14:39 +00:00
msgid "Minimum number of nights must be one or greater."
msgstr "El número mínimo de noches no puede ser cero."
#: pkg/campsite/types/admin.go:597
msgid "Maximum number of nights can not be empty."
msgstr "No podéis dejar el número máximo de noches en blanco."
#: pkg/campsite/types/admin.go:598
msgid "Maximum number of nights must be an integer."
msgstr "El número máximo de noches tiene que ser entero."
#: pkg/campsite/types/admin.go:599
msgid "Maximum number of nights must be equal or greater than the minimum."
msgstr "El valor del número máximo de noches tiene que ser igual o mayor al del mínimo."
#: pkg/campsite/types/admin.go:603
msgid "Dogs price can not be empty when dogs are allowed."
msgstr "El precio de los perros no puede ser vacío cuando son permitidos."
#: pkg/campsite/types/admin.go:604
msgid "Dogs price must be a decimal number."
msgstr "El precio de los perros tiene que ser un número decimal."
#: pkg/campsite/types/admin.go:605
msgid "Dogs price must be zero or greater."
msgstr "El precio de los perros tiene que ser como mínimo cero."
#: pkg/campsite/types/admin.go:610
msgid "Price per night can not be empty."
msgstr "No podéis dejar el precio por noche en blanco."
#: pkg/campsite/types/admin.go:611
msgid "Price per night must be a decimal number."
msgstr "El precio por noche tiene que ser un número decimal."
#: pkg/campsite/types/admin.go:612
msgid "Price per night must be zero or greater."
msgstr "El precio por noche tiene que ser como mínimo cero."
#: pkg/campsite/types/admin.go:615
msgid "Price per adult can not be empty."
msgstr "No podéis dejar el precio por adulto en blanco."
#: pkg/campsite/types/admin.go:616
msgid "Price per adult must be a decimal number."
msgstr "El precio por adulto tiene que ser un número decimal."
#: pkg/campsite/types/admin.go:617
msgid "Price per adult must be zero or greater."
msgstr "El precio por adulto tiene que ser como mínimo cero."
#: pkg/campsite/types/admin.go:620
msgid "Price per teenager can not be empty."
msgstr "No podéis dejar el precio por adolescente en blanco."
#: pkg/campsite/types/admin.go:621
msgid "Price per teenager must be a decimal number."
msgstr "El precio por adolescente tiene que ser un número decimal."
#: pkg/campsite/types/admin.go:622
msgid "Price per teenager must be zero or greater."
msgstr "El precio por adolescente tiene que ser como mínimo cero."
#: pkg/campsite/types/admin.go:625
msgid "Price per child can not be empty."
msgstr "No podéis dejar el precio por niño en blanco."
#: pkg/campsite/types/admin.go:626
msgid "Price per child must be a decimal number."
msgstr "El precio por niño tiene que ser un número decimal."
#: pkg/campsite/types/admin.go:627
msgid "Price per child must be zero or greater."
msgstr "El precio por niño tiene que ser como mínimo cero."
#: pkg/campsite/types/public.go:248
msgctxt "header"
msgid "Adults"
msgstr "Adultos"
#: pkg/campsite/types/public.go:255
msgctxt "header"
msgid "Teenagers (aged 11 to 16)"
msgstr "Adolescentes (de 11 a 16 años)"
#: pkg/campsite/types/public.go:262
msgctxt "header"
msgid "Children (aged 2 to 10)"
msgstr "Niños (de 2 a 10 años)"
#: pkg/campsite/admin.go:366 pkg/booking/public.go:172
#: pkg/booking/public.go:227
msgid "Selected campsite type is not valid."
msgstr "El tipo de alojamiento escogido no es válido."
#: pkg/campsite/admin.go:367 pkg/amenity/admin.go:282
msgid "Label can not be empty."
msgstr "No podéis dejar la etiqueta en blanco."
#: pkg/season/admin.go:412
msgid "Color can not be empty."
msgstr "No podéis dejar el color en blanco."
#: pkg/season/admin.go:413
msgid "This color is not valid. It must be like #123abc."
msgstr "Este color no es válido. Tiene que ser parecido a #123abc."
#: pkg/season/admin.go:513
msgctxt "action"
msgid "Unset"
msgstr "Desasignar"
#: pkg/season/admin.go:544
msgid "Start date can not be empty."
msgstr "No podéis dejar la fecha de inicio en blanco."
#: pkg/season/admin.go:545
msgid "Start date must be a valid date."
msgstr "La fecha de inicio tiene que ser una fecha válida."
#: pkg/season/admin.go:547
msgid "End date can not be empty."
msgstr "No podéis dejar la fecha final en blanco."
#: pkg/season/admin.go:548
msgid "End date must be a valid date."
msgstr "La fecha final tiene que ser una fecha válida."
#: pkg/user/admin.go:18
msgctxt "role"
msgid "guest"
msgstr "invitado"
#: pkg/user/admin.go:19
msgctxt "role"
msgid "employee"
msgstr "trabajador"
#: pkg/user/admin.go:20
msgctxt "role"
msgid "admin"
msgstr "administrador"
#: pkg/surroundings/admin.go:286
msgctxt "input"
msgid "Highlight image"
msgstr "Imagen del punto de interés"
#: pkg/surroundings/admin.go:287
msgctxt "action"
msgid "Set highlight image"
msgstr "Establecer la imagen del punto de interés"
#: pkg/surroundings/admin.go:407
msgctxt "input"
msgid "Ad image"
msgstr "Imagen del anuncio"
#: pkg/surroundings/admin.go:408
msgctxt "action"
msgid "Set ad image"
msgstr "Establecer la imagen del anuncio"
#: pkg/surroundings/admin.go:459
msgid "Ad image can not be empty."
msgstr "No podéis dejar la imagen del anuncio en blanco."
#: pkg/surroundings/admin.go:460
msgid "Ad image must be an image media type."
msgstr "La imagen del anuncio tiene que ser un medio de tipo imagen."
#: pkg/surroundings/admin.go:464
msgid "The title can not be empty."
msgstr "No podéis dejar el título en blanco."
#: pkg/surroundings/admin.go:465
msgid "The link text can not be empty."
msgstr "No podéis dejar el texto del enlace en blanco."
#: pkg/surroundings/admin.go:466
msgid "The ad URL can not be empty"
msgstr "No podéis dejar la dirección del enlace en blanco."
#: pkg/surroundings/admin.go:467 pkg/company/admin.go:228
msgid "This web address is not valid. It should be like https://domain.com/."
msgstr "Esta dirección web no es válida. Tiene que ser parecido a https://dominio.com/."
#: pkg/company/admin.go:207 pkg/booking/public.go:529
msgid "Selected country is not valid."
msgstr "El país escogido no es válido."
#: pkg/company/admin.go:211
msgid "Business name can not be empty."
msgstr "No podéis dejar el nombre de empresa en blanco."
#: pkg/company/admin.go:212
msgid "Business name must have at least two letters."
msgstr "El nombre de la empresa tiene que tener como mínimo dos letras."
#: pkg/company/admin.go:214
msgid "VAT number can not be empty."
msgstr "No podéis dejar el NIF en blanco."
#: pkg/company/admin.go:215
msgid "This VAT number is not valid."
msgstr "Este NIF no es válido."
#: pkg/company/admin.go:219 pkg/booking/public.go:547
msgid "Phone can not be empty."
msgstr "No podéis dejar el teléfono en blanco."
#: pkg/company/admin.go:220 pkg/booking/public.go:548
msgid "This phone number is not valid."
msgstr "Este teléfono no es válido."
#: pkg/company/admin.go:230 pkg/booking/public.go:537
msgid "Address can not be empty."
msgstr "No podéis dejar la dirección en blanco."
#: pkg/company/admin.go:231
msgid "City can not be empty."
msgstr "No podéis dejar la población en blanco."
#: pkg/company/admin.go:232
msgid "Province can not be empty."
msgstr "No podéis dejar la provincia en blanco."
#: pkg/company/admin.go:233 pkg/booking/public.go:539
msgid "Postcode can not be empty."
msgstr "No podéis dejar el código postal en blanco."
#: pkg/company/admin.go:234 pkg/booking/public.go:540
msgid "This postcode is not valid."
msgstr "Este código postal no es válido."
#: pkg/company/admin.go:238
msgid "RTC number can not be empty."
msgstr "No podéis dejar el número RTC en blanco."
#: pkg/company/admin.go:239
msgid "Tourist tax can not be empty."
msgstr "No podéis dejar el impuesto turístico en blanco."
#: pkg/company/admin.go:240
msgid "Tourist tax must be a decimal number."
msgstr "El impuesto turístico tiene que ser un número decimal."
#: pkg/company/admin.go:241
msgid "Tourist tax must be zero or greater."
msgstr "El impuesto turístico tiene que ser como mínimo cero."
#: pkg/company/admin.go:244
msgid "Tourist tax days can not be empty."
msgstr "No podéis dejar el números de días del impuesto turístico en blanco."
#: pkg/company/admin.go:245
msgid "Tourist tax days must be an integer number."
msgstr "El números de días de impuesto turístico tiene que ser un número entero."
#: pkg/company/admin.go:246
msgid "Tourist tax days must be one or greater."
msgstr "El número de días del impuesto turístico tiene que ser como mínimo uno."
#: pkg/company/admin.go:249
msgid "Selected currency is not valid."
msgstr "La moneda escogida no es válida."
#: pkg/company/admin.go:251
msgid "Invoice number format can not be empty."
msgstr "No podéis dejar el formato de número de factura en blanco."
#: pkg/auth/user.go:40
Add the logout button Conceptually, to logout we have to “delete the session”, thus the best HTTP verb would be `DELETE`. However, there is no way to send a `DELETE` request with a regular HTML form, and it seems that never will be[0]. I could use a POST, optionally with a “method override” technique, but i was planing to use HTMx anyway, so this was as good an opportunity to include it as any. In this application i am not concerned with people not having JavaScript enabled, because it is for a customer that has a known environment, and we do not have much time anyway. Therefore, i opted to forgo progressive enhancement in cases like this: if `DELETE` is needed, use `hx-delete`. Unfortunately, i can not use a <form> with a hidden <input> for the CSRF token, because `DELETE` requests do not have body and the value should be added as query parameters, like a form with GET method, but HTMx does the incorrect thing here: sends the values in the request’s body. That’s why i have to use a custom header and the `hx-header` directive to include the CSRF token. Then, by default HTMx targets the triggered element for swap with the response from the server, but after a logout i want to redirect the user to the login form again. I could set the hx-target to button to replace the whole body, or tell the client to redirect to the new location. I actually do not know which one is “better”. Maybe the hx-target is best because then everything is handled by the client, but in the case of logout, since it is possible that i might want to load scripts only for logged-in users in the future, i opted for the full page reload. However, HTMx does not want to reload a page that return HTTP 401, hence i had to include the GET method to /login in order to return the login form with a response of HTTP 200, which also helps when reloading in the browser after a failed login attempt. I am not worried with the HTTP 401 when attempting to load a page as guest, because this request most probably comes from the browser, not HTMx, and it will show the login form as intended—even though it is not compliant, since it does not return the WWW-Authenticate header, but this is the best i can do given that no cookie-based authentication method has been accepted[1]. [0]: https://www.w3.org/Bugs/Public/show_bug.cgi?id=10671#c16 [1]: https://datatracker.ietf.org/doc/id/draft-broyer-http-cookie-auth-00.html
2023-07-26 11:49:47 +00:00
msgid "Cross-site request forgery detected."
msgstr "Se ha detectado un intento de falsificación de petición en sitios cruzados."
#: pkg/media/admin.go:312
msgid "Uploaded file can not be empty."
msgstr "No podéis dejar el archivo del medio en blanco."
#: pkg/media/admin.go:371
msgid "Filename can not be empty."
msgstr "No podéis dejar el nombre del archivo en blanco."
#: pkg/booking/cart.go:159
msgctxt "cart"
msgid "Night"
msgstr "Noche"
#: pkg/booking/cart.go:160
msgctxt "cart"
msgid "Adult"
msgstr "Adulto"
#: pkg/booking/cart.go:161
msgctxt "cart"
msgid "Teenager"
msgstr "Adolescente"
#: pkg/booking/cart.go:162
msgctxt "cart"
msgid "Child"
msgstr "Niño"
#: pkg/booking/cart.go:163
msgctxt "cart"
msgid "Dog"
msgstr "Perro"
#: pkg/booking/admin.go:126
msgctxt "filename"
msgid "bookings.ods"
msgstr "reservas.ods"
#: pkg/booking/public.go:276 pkg/booking/public.go:305
msgid "Arrival date must be a valid date."
msgstr "La fecha de llegada tiene que ser una fecha válida."
#: pkg/booking/public.go:290 pkg/booking/public.go:312
msgid "Departure date must be a valid date."
msgstr "La fecha de partida tiene que ser una fecha válida."
#: pkg/booking/public.go:304
msgid "Arrival date can not be empty"
msgstr "No podéis dejar la fecha de llegada en blanco."
#: pkg/booking/public.go:306
#, c-format
msgid "Arrival date must be %s or after."
msgstr "La fecha de llegada tiene que ser igual o posterior a %s."
#: pkg/booking/public.go:307
#, c-format
msgid "Arrival date must be %s or before."
msgstr "La fecha de llegada tiene que ser anterior o igual a %s."
#: pkg/booking/public.go:311
msgid "Departure date can not be empty"
msgstr "No podéis dejar la fecha de partida en blanco."
#: pkg/booking/public.go:313
#, c-format
msgid "Departure date must be %s or after."
msgstr "La fecha de partida tiene que igual o posterior a %s."
#: pkg/booking/public.go:314
#, c-format
msgid "Departure date must be %s or before."
msgstr "La fecha de partida tiene que ser anterior o igual a %s."
#: pkg/booking/public.go:368
#, c-format
msgid "There can be at most %d guests in this accommodation."
msgstr "Solo puede haber como máximo %d invitados en este alojamiento."
#: pkg/booking/public.go:388
msgid "Number of adults can not be empty"
msgstr "No podéis dejar el número de adultos blanco."
#: pkg/booking/public.go:389
msgid "Number of adults must be an integer."
msgstr "El número de adultos tiene que ser entero."
#: pkg/booking/public.go:390
msgid "There must be at least one adult."
msgstr "Tiene que haber como mínimo un adulto."
#: pkg/booking/public.go:393
msgid "Number of teenagers can not be empty"
msgstr "No podéis dejar el número de adolescentes en blanco."
#: pkg/booking/public.go:394
msgid "Number of teenagers must be an integer."
msgstr "El número de adolescentes tiene que ser entero."
#: pkg/booking/public.go:395
msgid "Number of teenagers can not be negative."
msgstr "El número de adolescentes no puede ser negativo."
#: pkg/booking/public.go:398
msgid "Number of children can not be empty"
msgstr "No podéis dejar el número de niños en blanco."
#: pkg/booking/public.go:399
msgid "Number of children must be an integer."
msgstr "El número de niños tiene que ser entero."
#: pkg/booking/public.go:400
msgid "Number of children can not be negative."
msgstr "El número de niños no puede ser negativo."
#: pkg/booking/public.go:403
msgid "Number of dogs can not be empty"
msgstr "No podéis dejar el número de perros en blanco."
#: pkg/booking/public.go:404
msgid "Number of dogs must be an integer."
msgstr "El número de perros tiene que ser entero."
#: pkg/booking/public.go:405
msgid "Number of dogs can not be negative."
msgstr "El número de perros no puede ser negativo."
#: pkg/booking/public.go:476
Implement Redsys request signature in PostgreSQL Every company need to have its own merchant code and encryption key, thus it is not possible to use environment variables to keep that data, and i have to store it in the database. I do not want to give SELECT permission on the encryption key to guest, because i am going to fuck it up sooner or later, and everyone would be able to read that secret; i know it would. Therefore, i need a security definer function that takes the data to encrypt, use the key to encrypt it, and returns the result; nobody else should have access to that key, not even admins! By the way, i found out that every merchant receives the same key, thus it is not a problem to keep it in the repository. Since i need that SQL function to encrypt the data, i thought that i may go the whole nine yards and sign the request in PostgreSQL too, after all the data to sign comes from there, and it has JSON functions to create and base64-code an object. Fortunately, pg_crypto has all the functions that i need, but i can no longer keep that extension inside the auth schema, because it is used from others, and the public schema, like every other extensions, seems more appropriate. Instead of having the list of currency and language codes that Redsys uses as constants in the code, i moved that as field to the currency and language relations, so i can simply pass the lang_tag to the function and it can transform that tag to the correct code; the currency is from the company’s relation, since it is the only currency used in the whole application (for now). As a consequence, i had to grant execute to currency and the parse_price functions to guest, too. To generate the test data used in the unit tests, i used a third-party PHP implementation[0], but i only got from that the resulting base64-coded JSON object and signature, using the same that as in the unit test, and did not use any code from there. PostgreSQL formats the JSON as text differently than most implementations i have seen: it adds spaces between the key name and the colons, and space between the value and the separating comma. The first implementation used replace() to format the JSON as exactly as the PHP implementation, so that the result matches, and then tried to do generate the form by hand using the output from PostgreSQL without the replace(), to verify that Redsys would still accept my input. Finally, i adjusted the unit test to whatever pg_prove said it was getting from the function. I still have the form’s action hard-codded to the test environment, but the idea is that administrators should be able to switch from test to live themselves. That means that i need that info in the redsys relation as well. I think this is one of the few use cases for SQL’s types, because it is unlikely to change anytime soon, and i do not need the actual labels. Unfortunately, i could not use enumerations for the request’s transaction type because i can not attach an arbitrary number to the enum’s values. Having a relation is overkill, because i would need a constant in Go to refer to its primary key anyway, thus i kept the same constant i had before for that. Language and currency constant went out, as this is in the corresponding relations. In setup_redsys i must have a separate update if the encrypt_key is null because PostgreSQL checks constraints before key conflict, and i do not want to give a default value to the key if the row is not there yet. The problem is that i want to use null to mean “keep the same password”, because it is what i intend to do with the user-facing form: leave the input empty to keep the same password. As now Go needs to pass composite types back and forth with PostgreSQL, i need to register these types, and i have to do it every time because the only moment i have access to the non-pooled connection is in the AfterConnect function, but at that point i have no idea whether the user is going to request a payment. I do not know how much the performance degrades because of this. [0]: https://github.com/ssheduardo/sermepa/blob/master/src/Sermepa/Tpv/Tpv.php
2023-10-26 23:52:04 +00:00
#, c-format
msgid "%s can not be empty"
msgstr "No podéis dejar %s en blanco."
#: pkg/booking/public.go:477
#, c-format
msgid "%s must be an integer."
msgstr "%s tiene que ser un número entero."
#: pkg/booking/public.go:478
#, c-format
msgid "%s must be %d or greater."
msgstr "%s tiene que ser como mínimo %d."
#: pkg/booking/public.go:479
#, c-format
msgid "%s must be at most %d."
msgstr "%s tiene que ser como máximo %d"
#: pkg/booking/public.go:533
msgid "Full name can not be empty."
msgstr "No podéis dejar el nombre y los apellidos en blanco."
#: pkg/booking/public.go:534
msgid "Full name must have at least one letter."
msgstr "El nombre y los apellidos tienen que tener como mínimo una letra."
#: pkg/booking/public.go:538
msgid "Town or village can not be empty."
msgstr "No podéis dejar la población en blanco."
#: pkg/booking/public.go:553
msgid "It is mandatory to agree to the reservation conditions."
msgstr "Es obligatorio aceptar las condiciones de reserva."
#~ msgctxt "header"
#~ msgid "Type"
#~ msgstr "Tipo"
#~ msgid "Postal code can not be empty."
#~ msgstr "No podéis dejar el código postal en blanco."
#~ msgid "This postal code is not valid."
#~ msgstr "Este código postal no es válido."
#~ msgctxt "input"
#~ msgid "Address (optional)"
#~ msgstr "Dirección (opcional)"
#~ msgctxt "input"
#~ msgid "Postcode (optional)"
#~ msgstr "Código postal (opcional)"
#~ msgctxt "action"
#~ msgid "Pay"
#~ msgstr "Pagar"
#~ msgctxt "input"
#~ msgid "Check-in Date"
#~ msgstr "Fecha de entrada"
#~ msgctxt "input"
#~ msgid "Check-out Date"
#~ msgstr "Fecha de salida"
#~ msgid "The departure date must be after the arrival date."
#~ msgstr "La fecha de partida tiene que ser posterior a la de llegada."
#~ msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda den Jordà, cycle tours for all ages…."
#~ msgstr "El Camping Montagut es ideal como punto de salida de excursiones tranquilas, escalada, bañarse en el río y piletones, volcanes, la Fageda den Jordà, salidas en bicicleta para todos los niveles…."
#~ msgid "Get to the Costa Brava and enjoy the beaches, the gastronomy or go kayaking…."
#~ msgstr "Llegar hasta la Costa Brava y disfrutar de las playas, la gastronomía o ir en kayak…."
#~ msgid "You will also find museums in Olot, Figures, Girona."
#~ msgstr "También encontraréis museos en Olot, Figueres, Girona."
#~ msgid "As well as music festivals, dance, theater…."
#~ msgstr "Como festivales de música, danza, teatro…."
#~ msgctxt "header"
#~ msgid "Translations"
#~ msgstr "Traducciones"
#~ msgctxt "title"
#~ msgid "Translate Season to %s"
#~ msgstr "Traducción de la temporada a %s"
#~ msgid "Source:"
#~ msgstr "Origen:"
#~ msgctxt "input"
#~ msgid "Translation:"
#~ msgstr "Traducción"
#~ msgctxt "action"
#~ msgid "Translate"
#~ msgstr "Traducir"
#~ msgctxt "title"
#~ msgid "Translate Service to %s"
#~ msgstr "Traducción del servicio a %s"
#~ msgctxt "title"
#~ msgid "Translate Carousel Slide to %s"
#~ msgstr "Traducción de la diapositiva de carrusel a %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Feature to %s"
#~ msgstr "Traducción de la característica del tipo de alojamiento a %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Carousel Slide to %s"
#~ msgstr "Traducción de la diapositiva de carrusel del tipo de alojamiento a %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Option to %s"
#~ msgstr "Traducción de la opción del tipo de alojamiento a %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type to %s"
#~ msgstr "Traducción de tipo de alojamiento a %s"
2023-12-22 02:32:40 +00:00
#~ msgid "Starting from %s €/night"
#~ msgstr "A partir de %s €/noche"
#~ msgctxt "season"
#~ msgid "Closed"
#~ msgstr "Cerrado"
#~ msgctxt "title"
#~ msgid "Party Details"
#~ msgstr "Datos de los visitantes"
#~ msgid "Number of adults must be one or greater."
#~ msgstr "El número de adultos no puede ser cero."
#~ msgid "Number of teenagers must be zero or greater."
#~ msgstr "El número de adolescentes tiene que ser como mínimo cero."
#~ msgid "Number of children must be zero or greater."
#~ msgstr "El número de niños tiene que ser como mínimo cero."
#~ msgid "Number of dogs must be zero or greater."
#~ msgstr "El número de perros tiene que ser como mínimo cero."
#~ msgctxt "input"
#~ msgid "Pricing"
#~ msgstr "Precios"
#~ msgctxt "input"
#~ msgid "Features"
#~ msgstr "Características"
#~ msgid "Singular Lodges"
#~ msgstr "Alojamientos singulares"
#~ msgctxt "campsite type"
#~ msgid "Translations"
#~ msgstr "Traducciones"
#~ msgid "Surroundings"
#~ msgstr "Entorno"
#~ msgctxt "title"
#~ msgid "Pages"
#~ msgstr "Páginas"
#~ msgctxt "action"
#~ msgid "Add Page"
#~ msgstr "Añadir página"
#~ msgctxt "header"
#~ msgid "Title"
#~ msgstr "Título"