camper/po/ca.po

1739 lines
50 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
# Catalan translations for camper package
# Traduccions al català del paquet «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: 2023-12-20 19:48+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
"PO-Revision-Date: 2023-07-22 23:45+0200\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Catalan <ca@dodds.net>\n"
"Language: ca\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"
#: web/templates/public/payment/success.gohtml:6
#: web/templates/public/payment/success.gohtml:11
msgctxt "title"
msgid "Payment Successful"
msgstr "Pagament amb èxit"
#: web/templates/public/payment/request.gohtml:6
#: web/templates/public/payment/request.gohtml:11
msgctxt "title"
msgid "Payment"
msgstr "Pagament"
#: web/templates/public/payment/request.gohtml:23
msgctxt "action"
msgid "Pay"
msgstr "Paga"
#: web/templates/public/payment/failure.gohtml:6
#: web/templates/public/payment/failure.gohtml:11
msgctxt "title"
msgid "Payment Failed"
msgstr "Ha fallat el pagament"
#: web/templates/public/services.gohtml:6
#: web/templates/public/services.gohtml:15
#: web/templates/public/layout.gohtml:44 web/templates/public/layout.gohtml:71
#: web/templates/admin/services/index.gohtml:66
msgctxt "title"
msgid "Services"
msgstr "Serveis"
#: web/templates/public/services.gohtml:18
msgid "The campsite offers many different services."
msgstr "El càmping disposa de diversos serveis."
#: web/templates/public/home.gohtml:6 web/templates/public/layout.gohtml:30
#: web/templates/public/layout.gohtml:69
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 "Inici"
#: web/templates/public/home.gohtml:17
msgid "The pleasure of camping in the middle of nature…"
msgstr "El plaer dacampar en plena natura…"
#: web/templates/public/home.gohtml:18
msgctxt "link"
msgid "Booking"
msgstr "Reserva"
#: web/templates/public/home.gohtml:31
msgid "Our services"
msgstr "Els nostres serveis"
#: web/templates/public/home.gohtml:34
#: web/templates/public/surroundings.gohtml:6
#: web/templates/public/surroundings.gohtml:10
#: web/templates/public/layout.gohtml:45 web/templates/public/layout.gohtml:72
msgctxt "title"
msgid "Surroundings"
msgstr "Lentorn"
#: web/templates/public/home.gohtml:37
msgid "Located in <strong>Alta Garrotxa</strong>, between the <strong>Pyrenees</strong> and the <strong>Costa Brava</strong>."
msgstr "Situats a l<strong>Alta Garrotxa</strong>, entre els <strong>Pirineus</strong> i la <strong>Costa Brava</strong>."
#: web/templates/public/home.gohtml:38
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 "A prop teniu els <strong>gorgs de Sadernes</strong>, <strong>volcans</strong>, <strong>La Fageda den Jordà</strong>, el call jueu de <strong>Besalú</strong>, la cinglera basàltica de <strong>Castellfollit de la Roca</strong>… molt per veure i molt per fer."
#: web/templates/public/home.gohtml:39
msgid "Less than an hour from <strong>Girona</strong>, one from <strong>La Bisbal dEmpordà</strong>, and two from <strong>Barcelona</strong>."
msgstr "A menys duna hora de <strong>Girona</strong>, a una de <strong>La Bisbal dEmpordà</strong> i a dues de <strong>Barcelona</strong>."
#: web/templates/public/home.gohtml:40
msgid "Discover the surroundings"
msgstr "Descobreix lentorn"
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/public/home.gohtml:54
msgid "Come and enjoy!"
msgstr "Vine a gaudir!"
#: web/templates/public/campsite/type.gohtml:41
msgctxt "input"
msgid "Check-in Date"
msgstr "Data dentrada"
#: web/templates/public/campsite/type.gohtml:47
msgctxt "input"
msgid "Check-out Date"
msgstr "Data de sortida"
#: web/templates/public/campsite/type.gohtml:54
#: web/templates/public/booking.gohtml:155
msgctxt "action"
msgid "Book"
msgstr "Reserva"
#: web/templates/public/campsite/type.gohtml:60
#: web/templates/admin/campsite/option/form.gohtml:58
2023-10-01 19:14:39 +00:00
#: web/templates/admin/campsite/type/form.gohtml:73
msgctxt "title"
msgid "Prices"
msgstr "Preus"
#: web/templates/public/campsite/type.gohtml:72
msgid "Starting from %s €/night"
msgstr "A partir de %s €/nit"
#: web/templates/public/campsite/type.gohtml:74
2023-10-01 19:14:39 +00:00
msgid "%s €/night"
msgstr "%s €/nit"
#: web/templates/public/campsite/type.gohtml:77
2023-10-01 19:14:39 +00:00
msgid "*Minimum %d nights per stay"
msgstr "*Mínim %d nits per estada"
#: web/templates/public/campsite/type.gohtml:89
#: web/templates/admin/season/index.gohtml:59
msgctxt "title"
msgid "Calendar"
msgstr "Calendari"
#: web/templates/public/campsite/type.gohtml:100
msgctxt "title"
msgid "Features"
msgstr "Característiques"
#: web/templates/public/campsite/type.gohtml:111
msgctxt "title"
msgid "Info"
msgstr "Informació"
#: web/templates/public/campsite/type.gohtml:115
msgctxt "title"
msgid "Facilities"
msgstr "Equipaments"
#: web/templates/public/campsite/type.gohtml:119
msgctxt "title"
msgid "Description"
msgstr "Descripció"
#: web/templates/public/campsite/calendar.gohtml:18
#: web/templates/admin/season/calendar.gohtml:16
msgctxt "day"
msgid "Mon"
msgstr "dl"
#: web/templates/public/campsite/calendar.gohtml:19
#: web/templates/admin/season/calendar.gohtml:17
msgctxt "day"
msgid "Tue"
msgstr "dt"
#: web/templates/public/campsite/calendar.gohtml:20
#: web/templates/admin/season/calendar.gohtml:18
msgctxt "day"
msgid "Wed"
msgstr "dc"
#: web/templates/public/campsite/calendar.gohtml:21
#: web/templates/admin/season/calendar.gohtml:19
msgctxt "day"
msgid "Thu"
msgstr "dj"
#: web/templates/public/campsite/calendar.gohtml:22
#: web/templates/admin/season/calendar.gohtml:20
msgctxt "day"
msgid "Fri"
msgstr "dv"
#: web/templates/public/campsite/calendar.gohtml:23
#: web/templates/admin/season/calendar.gohtml:21
msgctxt "day"
msgid "Sat"
msgstr "ds"
#: web/templates/public/campsite/calendar.gohtml:24
#: web/templates/admin/season/calendar.gohtml:22
msgctxt "day"
msgid "Sun"
msgstr "dg"
#: web/templates/public/surroundings.gohtml:28
msgctxt "title"
msgid "What to Do Outside the Campsite?"
msgstr "Què fer des del càmping?"
#: web/templates/public/surroundings.gohtml:31
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 Càmping Montagut és ideal com a punt de partida dexcursions tranquil·les, escalada, banyar-se en el riu i gorgues, volcans, la Fageda den Jordà, sortides amb bicicleta per a tots els nivells…."
#: web/templates/public/surroundings.gohtml:38
msgid "Get to the Costa Brava and enjoy the beaches, the gastronomy or go kayaking…."
msgstr "Arribar fins a la costa brava i gaudir de les platges, la gastronomia o anar amb caiac…."
#: web/templates/public/surroundings.gohtml:47
msgid "You will also find museums in Olot, Figures, Girona."
msgstr "També trobareu museus a Olot, Figueres, Girona."
#: web/templates/public/surroundings.gohtml:48
msgid "As well as music festivals, dance, theater…."
msgstr "Com festivals de música, dansa, teatre…."
#: web/templates/public/surroundings.gohtml:54
msgctxt "title"
msgid "Once at the Campsite, We Can Inform You about What Activities are Available"
msgstr "Un cop en el càmping, us podem informar de quines activitats fer"
#: web/templates/public/surroundings.gohtml:57
msgid "Cycle routes"
msgstr "Rutes amb bicicleta"
#: web/templates/public/surroundings.gohtml:58
msgid "There are many bicycle rental companies in Olot."
msgstr "A Olot podeu trobar empreses de lloguer de bicicletes."
#: web/templates/public/surroundings.gohtml:62
msgid "Routes"
msgstr "Rutes"
#: web/templates/public/surroundings.gohtml:63
msgid "Routes of all kinds, climbing, mountain passes, for all levels."
msgstr "Rutes de tota mena, escalada, ports de muntanya, per a tots els nivells."
#: web/templates/public/surroundings.gohtml:67
msgid "Family outing"
msgstr "Excursions familiars"
#: web/templates/public/surroundings.gohtml:68
msgid "Many outing possibilities, for all ages."
msgstr "Múltiples excursions per a totes les edats."
#: web/templates/public/surroundings.gohtml:72
msgid "Kayak"
msgstr "Caiac"
#: web/templates/public/surroundings.gohtml:73
msgid "There are several points where you can go by kayak, from sections of the Ter river as well as on the coast…."
msgstr "Hi ha diversos punts on poder anar amb caiac, des de trams del riu Ter com també a la costa…."
#: web/templates/public/campground.gohtml:6
#: web/templates/public/campground.gohtml:11
#: web/templates/public/layout.gohtml:31 web/templates/public/layout.gohtml:70
msgctxt "title"
msgid "Campground"
msgstr "El càmping"
#: web/templates/public/contact.gohtml:6 web/templates/public/contact.gohtml:18
#: web/templates/public/layout.gohtml:46 web/templates/public/layout.gohtml:73
msgctxt "title"
msgid "Contact"
msgstr "Contacte"
#: web/templates/public/booking.gohtml:6 web/templates/public/booking.gohtml:11
msgctxt "title"
msgid "Booking"
msgstr "Reserva"
#: web/templates/public/booking.gohtml:15
msgctxt "title"
msgid "Customer Details"
msgstr "Detalls del client"
#: web/templates/public/booking.gohtml:18
msgctxt "input"
msgid "Full name"
msgstr "Nom i cognoms"
#: web/templates/public/booking.gohtml:27
msgctxt "input"
msgid "Address (optional)"
msgstr "Adreça (opcional)"
#: web/templates/public/booking.gohtml:36
msgctxt "input"
msgid "Postcode (optional)"
msgstr "Codi postal (opcional)"
#: web/templates/public/booking.gohtml:45
msgctxt "input"
msgid "Town or village (optional)"
msgstr "Població (opcional)"
#: web/templates/public/booking.gohtml:54
#: web/templates/admin/taxDetails.gohtml:98
msgctxt "input"
msgid "Country"
msgstr "País"
#: web/templates/public/booking.gohtml:57
msgid "Choose a country"
msgstr "Esculli un país"
#: web/templates/public/booking.gohtml:65 web/templates/admin/login.gohtml:22
#: web/templates/admin/profile.gohtml:35
#: web/templates/admin/taxDetails.gohtml:50
msgctxt "input"
msgid "Email"
msgstr "Correu-e"
#: web/templates/public/booking.gohtml:74
#: web/templates/admin/taxDetails.gohtml:42
msgctxt "input"
msgid "Phone"
msgstr "Telèfon"
#: web/templates/public/booking.gohtml:83
msgctxt "title"
msgid "Accommodation"
msgstr "Allotjaments"
#: web/templates/public/booking.gohtml:98
msgctxt "input"
msgid "Area preferences (optional)"
msgstr "Preferències dàrea (opcional)"
#: web/templates/public/booking.gohtml:120
msgctxt "title"
msgid "Booking Period"
msgstr "Període de reserva"
#: web/templates/public/booking.gohtml:123
msgctxt "input"
msgid "Arrival date"
msgstr "Data darribada"
#: web/templates/public/booking.gohtml:132
msgctxt "input"
msgid "Departure date"
msgstr "Data de sortida"
#: web/templates/public/booking.gohtml:143
msgctxt "input"
msgid "ACSI card? (optional)"
msgstr "Targeta ACSI? (opcional)"
#: web/templates/public/booking.gohtml:150
msgctxt "input"
msgid "I have read and I accept the reservation conditions"
msgstr "He llegit i accepto les condicions de reserves"
#: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:25
#: web/templates/public/layout.gohtml:102
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 "Campsite Montagut"
msgstr "Càmping Montagut"
#: web/templates/public/layout.gohtml:23 web/templates/admin/layout.gohtml:19
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 "Skip to main content"
msgstr "Salta al contingut principal"
#: web/templates/public/layout.gohtml:35 web/templates/public/layout.gohtml:80
#: web/templates/admin/campsite/index.gohtml:6
#: web/templates/admin/campsite/index.gohtml:12
#: web/templates/admin/layout.gohtml:44 web/templates/admin/layout.gohtml:75
msgctxt "title"
msgid "Campsites"
msgstr "Allotjaments"
#: web/templates/public/layout.gohtml:67
msgctxt "title"
msgid "Sections"
msgstr "Apartats"
#: web/templates/public/layout.gohtml:99
msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s"
msgstr "<abbr title=\"Número\">Núm.</abbr> <abbr title=\"Registre de Turisme de Catalunya\">RTC</abbr> %s"
#: web/templates/admin/carousel/form.gohtml:8
#: web/templates/admin/carousel/form.gohtml:25
msgctxt "title"
msgid "Edit Carousel Slide"
msgstr "Edició de la diapositiva del carrusel"
#: web/templates/admin/carousel/form.gohtml:10
#: web/templates/admin/carousel/form.gohtml:27
msgctxt "title"
msgid "New Carousel Slide"
msgstr "Nova diapositiva del carrusel"
#: web/templates/admin/carousel/form.gohtml:37
#: web/templates/admin/carousel/l10n.gohtml:20
#: web/templates/admin/campsite/carousel/form.gohtml:37
#: web/templates/admin/campsite/carousel/l10n.gohtml:20
msgctxt "input"
msgid "Caption"
msgstr "Llegenda"
#: web/templates/admin/carousel/form.gohtml:47
#: web/templates/admin/campsite/feature/form.gohtml:62
#: web/templates/admin/campsite/carousel/form.gohtml:47
#: web/templates/admin/campsite/form.gohtml:70
#: web/templates/admin/campsite/option/form.gohtml:78
#: web/templates/admin/campsite/type/form.gohtml:129
#: web/templates/admin/season/form.gohtml:64
#: web/templates/admin/services/form.gohtml:69
#: web/templates/admin/media/form.gohtml:35
msgctxt "action"
msgid "Update"
msgstr "Actualitza"
#: web/templates/admin/carousel/form.gohtml:49
#: web/templates/admin/campsite/feature/form.gohtml:64
#: web/templates/admin/campsite/carousel/form.gohtml:49
#: web/templates/admin/campsite/form.gohtml:72
#: web/templates/admin/campsite/option/form.gohtml:80
#: web/templates/admin/campsite/type/form.gohtml:131
#: web/templates/admin/season/form.gohtml:66
#: web/templates/admin/services/form.gohtml:71
msgctxt "action"
msgid "Add"
msgstr "Afegeix"
#: web/templates/admin/carousel/l10n.gohtml:7
#: web/templates/admin/carousel/l10n.gohtml:14
msgctxt "title"
msgid "Translate Carousel Slide to %s"
msgstr "Traducció de la diapositiva del carrusel a %s"
#: web/templates/admin/carousel/l10n.gohtml:21
#: web/templates/admin/campsite/feature/l10n.gohtml:21
#: web/templates/admin/campsite/carousel/l10n.gohtml:21
#: web/templates/admin/campsite/option/l10n.gohtml:21
#: web/templates/admin/campsite/type/l10n.gohtml:21
#: web/templates/admin/campsite/type/l10n.gohtml:33
#: web/templates/admin/campsite/type/l10n.gohtml:46
#: web/templates/admin/campsite/type/l10n.gohtml:59
#: web/templates/admin/campsite/type/l10n.gohtml:72
#: web/templates/admin/season/l10n.gohtml:21
#: web/templates/admin/services/l10n.gohtml:21
#: web/templates/admin/services/l10n.gohtml:33
msgid "Source:"
msgstr "Origen:"
#: web/templates/admin/carousel/l10n.gohtml:23
#: web/templates/admin/campsite/feature/l10n.gohtml:23
#: web/templates/admin/campsite/carousel/l10n.gohtml:23
#: web/templates/admin/campsite/option/l10n.gohtml:23
#: web/templates/admin/campsite/type/l10n.gohtml:23
#: web/templates/admin/campsite/type/l10n.gohtml:36
#: web/templates/admin/campsite/type/l10n.gohtml:49
#: web/templates/admin/campsite/type/l10n.gohtml:62
#: web/templates/admin/campsite/type/l10n.gohtml:75
#: web/templates/admin/season/l10n.gohtml:23
#: web/templates/admin/services/l10n.gohtml:23
#: web/templates/admin/services/l10n.gohtml:36
msgctxt "input"
msgid "Translation:"
msgstr "Traducció:"
#: web/templates/admin/carousel/l10n.gohtml:32
#: web/templates/admin/campsite/feature/l10n.gohtml:32
#: web/templates/admin/campsite/carousel/l10n.gohtml:32
#: web/templates/admin/campsite/option/l10n.gohtml:32
#: web/templates/admin/campsite/type/l10n.gohtml:84
#: web/templates/admin/season/l10n.gohtml:32
#: web/templates/admin/services/l10n.gohtml:45
msgctxt "action"
msgid "Translate"
msgstr "Tradueix"
#: web/templates/admin/campsite/feature/form.gohtml:8
#: web/templates/admin/campsite/feature/form.gohtml:25
msgctxt "title"
msgid "Edit Campsite Type Feature"
msgstr "Edició de les característiques del tipus dallotjament"
#: web/templates/admin/campsite/feature/form.gohtml:10
#: web/templates/admin/campsite/feature/form.gohtml:27
msgctxt "title"
msgid "New Campsite Type Feature"
msgstr "Nova característica de tipus dallotjament"
#: web/templates/admin/campsite/feature/form.gohtml:34
#: web/templates/admin/services/form.gohtml:34
msgctxt "input"
msgid "Icon"
msgstr "Icona"
#: web/templates/admin/campsite/feature/form.gohtml:52
#: web/templates/admin/campsite/feature/l10n.gohtml:20
#: web/templates/admin/campsite/option/form.gohtml:34
#: web/templates/admin/campsite/option/l10n.gohtml:20
#: web/templates/admin/campsite/type/form.gohtml:46
#: web/templates/admin/campsite/type/l10n.gohtml:20
#: web/templates/admin/season/form.gohtml:46
#: web/templates/admin/season/l10n.gohtml:20
#: web/templates/admin/services/form.gohtml:52
#: web/templates/admin/services/l10n.gohtml:20
#: web/templates/admin/profile.gohtml:26
msgctxt "input"
msgid "Name"
msgstr "Nom"
#: web/templates/admin/campsite/feature/index.gohtml:6
#: web/templates/admin/campsite/feature/index.gohtml:12
msgctxt "title"
msgid "Campsite Type Features"
msgstr "Característiques del tipus dallotjaments"
#: web/templates/admin/campsite/feature/index.gohtml:11
msgctxt "action"
msgid "Add Feature"
msgstr "Afegeix característica"
#: web/templates/admin/campsite/feature/index.gohtml:17
#: web/templates/admin/campsite/option/index.gohtml:25
#: web/templates/admin/campsite/type/index.gohtml:25
#: web/templates/admin/season/index.gohtml:26
msgctxt "header"
msgid "Name"
msgstr "Nom"
#: web/templates/admin/campsite/feature/index.gohtml:18
#: web/templates/admin/campsite/carousel/index.gohtml:27
#: web/templates/admin/campsite/option/index.gohtml:26
#: web/templates/admin/campsite/type/index.gohtml:26
#: web/templates/admin/season/index.gohtml:27
#: web/templates/admin/services/index.gohtml:27
#: web/templates/admin/services/index.gohtml:73
#: web/templates/admin/home/index.gohtml:27
msgctxt "header"
msgid "Translations"
msgstr "Traduccions"
#: web/templates/admin/campsite/feature/index.gohtml:39
msgid "No campsite type features added yet."
msgstr "No sha afegit cap característica al tipus dallotjament encara."
#: web/templates/admin/campsite/feature/l10n.gohtml:7
#: web/templates/admin/campsite/feature/l10n.gohtml:14
msgctxt "title"
msgid "Translate Campsite Type Feature to %s"
msgstr "Traducció de la característica del tipus dallotjament a %s"
#: web/templates/admin/campsite/carousel/form.gohtml:8
#: web/templates/admin/campsite/carousel/form.gohtml:25
msgctxt "title"
msgid "Edit Campsite Type Carousel Slide"
msgstr "Edició de la diapositiva del carrusel del tipus dallotjament"
#: web/templates/admin/campsite/carousel/form.gohtml:10
#: web/templates/admin/campsite/carousel/form.gohtml:27
msgctxt "title"
msgid "New Campsite Type Carousel Slide"
msgstr "Nova diapositiva del carrusel del tipus dallotjament"
#: web/templates/admin/campsite/carousel/index.gohtml:6
#: web/templates/admin/campsite/carousel/index.gohtml:11
msgctxt "title"
msgid "Campsite Type Carousel"
msgstr "Carrusel del tipus dallotjament"
#: web/templates/admin/campsite/carousel/index.gohtml:12
#: web/templates/admin/services/index.gohtml:12
#: web/templates/admin/home/index.gohtml:12
msgctxt "action"
msgid "Add slide"
msgstr "Afegeix diapositiva"
#: web/templates/admin/campsite/carousel/index.gohtml:25
#: web/templates/admin/services/index.gohtml:25
#: web/templates/admin/home/index.gohtml:25
msgctxt "header"
msgid "Image"
msgstr "Imatge"
#: web/templates/admin/campsite/carousel/index.gohtml:26
#: web/templates/admin/services/index.gohtml:26
#: web/templates/admin/home/index.gohtml:26
msgctxt "header"
msgid "Caption"
msgstr "Llegenda"
#: web/templates/admin/campsite/carousel/index.gohtml:28
#: web/templates/admin/services/index.gohtml:28
#: web/templates/admin/services/index.gohtml:74
#: web/templates/admin/home/index.gohtml:28
msgctxt "header"
msgid "Actions"
msgstr "Accions"
#: web/templates/admin/campsite/carousel/index.gohtml:32
#: web/templates/admin/services/index.gohtml:32
#: web/templates/admin/home/index.gohtml:32
msgid "Are you sure you wish to delete this slide?"
msgstr "Esteu segur de voler esborrar aquesta diapositiva?"
#: web/templates/admin/campsite/carousel/index.gohtml:55
#: web/templates/admin/services/index.gohtml:54
#: web/templates/admin/services/index.gohtml:93
#: web/templates/admin/home/index.gohtml:54
msgctxt "action"
msgid "Delete"
msgstr "Esborra"
#: web/templates/admin/campsite/carousel/index.gohtml:64
#: web/templates/admin/services/index.gohtml:63
#: web/templates/admin/home/index.gohtml:63
msgid "No slides added yet."
msgstr "No sha afegit cap diapositiva encara."
#: web/templates/admin/campsite/carousel/l10n.gohtml:7
#: web/templates/admin/campsite/carousel/l10n.gohtml:14
msgctxt "title"
msgid "Translate Campsite Type Carousel Slide to %s"
msgstr "Traducció de la diapositiva del carrusel del tipus dallotjament a %s"
#: web/templates/admin/campsite/form.gohtml:8
#: web/templates/admin/campsite/form.gohtml:25
msgctxt "title"
msgid "Edit Campsite"
msgstr "Edició de lallotjament"
#: web/templates/admin/campsite/form.gohtml:10
#: web/templates/admin/campsite/form.gohtml:27
msgctxt "title"
msgid "New Campsite"
msgstr "Nou allotjament"
#: web/templates/admin/campsite/form.gohtml:37
#: web/templates/admin/campsite/index.gohtml:20
msgctxt "campsite"
msgid "Active"
msgstr "Actiu"
#: web/templates/admin/campsite/form.gohtml:46
msgctxt "input"
msgid "Campsite Type"
msgstr "Tipus dallotjament"
#: web/templates/admin/campsite/form.gohtml:51
msgid "Select campsite type"
msgstr "Escolliu un tipus dallotjament"
#: web/templates/admin/campsite/form.gohtml:60
msgctxt "input"
msgid "Label"
msgstr "Etiqueta"
#: web/templates/admin/campsite/option/form.gohtml:8
#: web/templates/admin/campsite/option/form.gohtml:25
msgctxt "title"
msgid "Edit Campsite Type Option"
msgstr "Edició de lopció del tipus dallotjament"
#: web/templates/admin/campsite/option/form.gohtml:10
#: web/templates/admin/campsite/option/form.gohtml:27
msgctxt "title"
msgid "New Campsite Type Option"
msgstr "Nova opció del tipus dallotjament"
#: web/templates/admin/campsite/option/form.gohtml:42
msgctxt "input"
msgid "Minimum"
msgstr "Mínim"
#: web/templates/admin/campsite/option/form.gohtml:50
msgctxt "input"
msgid "Maximum"
msgstr "Màxim"
#: web/templates/admin/campsite/option/form.gohtml:64
#: web/templates/admin/campsite/type/form.gohtml:79
msgctxt "input"
msgid "Price per night"
msgstr "Preu per nit"
#: web/templates/admin/campsite/option/index.gohtml:6
#: web/templates/admin/campsite/option/index.gohtml:12
msgctxt "title"
msgid "Campsite Type Options"
msgstr "Opcions del tipus dallotjament"
#: web/templates/admin/campsite/option/index.gohtml:11
msgctxt "action"
msgid "Add Option"
msgstr "Afegeix opció"
#: web/templates/admin/campsite/option/index.gohtml:52
msgid "No campsite type options added yet."
msgstr "No sha afegit cap opció al tipus dallotjament encara."
#: web/templates/admin/campsite/option/l10n.gohtml:7
#: web/templates/admin/campsite/option/l10n.gohtml:14
msgctxt "title"
msgid "Translate Campsite Type Option to %s"
msgstr "Traducció de la opció del tipus dallotjament a %s"
#: web/templates/admin/campsite/index.gohtml:11
msgctxt "action"
msgid "Add Campsite"
msgstr "Afegeix allotjament"
#: web/templates/admin/campsite/index.gohtml:18
msgctxt "header"
msgid "Label"
msgstr "Etiqueta"
#: web/templates/admin/campsite/index.gohtml:19
msgctxt "header"
msgid "Type"
msgstr "Tipus"
#: web/templates/admin/campsite/index.gohtml:28
#: web/templates/admin/campsite/type/index.gohtml:59
#: web/templates/admin/season/index.gohtml:49
msgid "Yes"
msgstr "Sí"
#: web/templates/admin/campsite/index.gohtml:28
#: web/templates/admin/campsite/type/index.gohtml:59
#: web/templates/admin/season/index.gohtml:49
msgid "No"
msgstr "No"
#: web/templates/admin/campsite/index.gohtml:34
msgid "No campsites added yet."
msgstr "No sha afegit cap allotjament encara."
#: web/templates/admin/campsite/type/form.gohtml:8
#: web/templates/admin/campsite/type/form.gohtml:25
msgctxt "title"
msgid "Edit Campsite Type"
msgstr "Edició del tipus dallotjament"
#: web/templates/admin/campsite/type/form.gohtml:10
#: web/templates/admin/campsite/type/form.gohtml:27
msgctxt "title"
msgid "New Campsite Type"
msgstr "Nou tipus dallotjament"
#: web/templates/admin/campsite/type/form.gohtml:37
#: web/templates/admin/campsite/type/index.gohtml:30
msgctxt "campsite type"
msgid "Active"
msgstr "Actiu"
#: web/templates/admin/campsite/type/form.gohtml:57
msgctxt "input"
msgid "Maximum number of campers"
msgstr "Número màxim de persones"
#: web/templates/admin/campsite/type/form.gohtml:67
msgctxt "input"
msgid "Dogs allowed"
msgstr "Es permeten gossos"
2023-10-01 19:14:39 +00:00
#: web/templates/admin/campsite/type/form.gohtml:87
msgctxt "input"
msgid "Minimum number of nights"
msgstr "Número mínim de nits"
#: web/templates/admin/campsite/type/form.gohtml:99
#: web/templates/admin/campsite/type/l10n.gohtml:32
msgctxt "input"
msgid "Spiel"
msgstr "Introducció"
#: web/templates/admin/campsite/type/form.gohtml:106
#: web/templates/admin/campsite/type/l10n.gohtml:45
msgctxt "input"
msgid "Info"
msgstr "Informació"
#: web/templates/admin/campsite/type/form.gohtml:113
#: web/templates/admin/campsite/type/l10n.gohtml:58
msgctxt "input"
msgid "Facilities"
msgstr "Equipaments"
#: web/templates/admin/campsite/type/form.gohtml:120
#: web/templates/admin/campsite/type/l10n.gohtml:71
#: web/templates/admin/services/form.gohtml:60
#: web/templates/admin/services/l10n.gohtml:32
msgctxt "input"
msgid "Description"
msgstr "Descripció"
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/campsite/type/index.gohtml:6
#: web/templates/admin/campsite/type/index.gohtml:12
#: web/templates/admin/layout.gohtml:41
msgctxt "title"
msgid "Campsite Types"
msgstr "Tipus dallotjaments"
#: web/templates/admin/campsite/type/index.gohtml:11
msgctxt "action"
msgid "Add Type"
msgstr "Afegeix tipus"
#: web/templates/admin/campsite/type/index.gohtml:27
msgctxt "header"
msgid "Features"
msgstr "Característiques"
#: web/templates/admin/campsite/type/index.gohtml:28
msgctxt "header"
msgid "Options"
msgstr "Opcions"
#: web/templates/admin/campsite/type/index.gohtml:29
msgctxt "header"
msgid "Carousel"
msgstr "Carrusel"
#: web/templates/admin/campsite/type/index.gohtml:51
msgctxt "action"
msgid "Edit Features"
msgstr "Edita les característiques"
#: web/templates/admin/campsite/type/index.gohtml:54
msgctxt "action"
msgid "Edit Options"
msgstr "Edita les opcions"
#: web/templates/admin/campsite/type/index.gohtml:57
msgctxt "action"
msgid "Edit Carousel"
msgstr "Edita el carrusel"
#: web/templates/admin/campsite/type/index.gohtml:66
msgid "No campsite types added yet."
msgstr "No sha afegit cap tipus dallotjament encara."
#: web/templates/admin/campsite/type/l10n.gohtml:7
#: web/templates/admin/campsite/type/l10n.gohtml:14
msgctxt "title"
msgid "Translate Campsite Type to %s"
msgstr "Traducció del tipus dallotjament a %s"
#: web/templates/admin/season/form.gohtml:8
#: web/templates/admin/season/form.gohtml:25
msgctxt "title"
msgid "Edit Season"
msgstr "Edició de la temporada"
#: web/templates/admin/season/form.gohtml:10
#: web/templates/admin/season/form.gohtml:27
msgctxt "title"
msgid "New Season"
msgstr "Nova temporada"
#: web/templates/admin/season/form.gohtml:37
#: web/templates/admin/season/index.gohtml:28
msgctxt "season"
msgid "Active"
msgstr "Activa"
#: web/templates/admin/season/form.gohtml:54
msgctxt "input"
msgid "Color"
msgstr "Color"
#: web/templates/admin/season/index.gohtml:6
#: web/templates/admin/season/index.gohtml:12
#: web/templates/admin/layout.gohtml:47
msgctxt "title"
msgid "Seasons"
msgstr "Temporades"
#: web/templates/admin/season/index.gohtml:11
msgctxt "action"
msgid "Add Season"
msgstr "Afegeix temporada"
#: web/templates/admin/season/index.gohtml:25
msgctxt "header"
msgid "Color"
msgstr "Color"
#: web/templates/admin/season/index.gohtml:56
msgid "No seasons added yet."
msgstr "No sha afegit cap temporada encara."
#: web/templates/admin/season/l10n.gohtml:7
#: web/templates/admin/season/l10n.gohtml:14
msgctxt "title"
msgid "Translate Season to %s"
msgstr "Traducció de la temporada a %s"
#: web/templates/admin/season/calendar.gohtml:49
#: web/templates/admin/media/picker.gohtml:61
msgctxt "action"
msgid "Cancel"
msgstr "Canceŀla"
#: web/templates/admin/payment.gohtml:6 web/templates/admin/payment.gohtml:12
#: web/templates/admin/layout.gohtml:38
msgctxt "title"
msgid "Payment Settings"
msgstr "Paràmetres de pagament"
#: web/templates/admin/payment.gohtml:17
msgctxt "input"
msgid "Merchant Code"
msgstr "Codi del comerç"
#: web/templates/admin/payment.gohtml:26
msgctxt "input"
msgid "Terminal Number"
msgstr "Número de terminal"
#: web/templates/admin/payment.gohtml:36
msgctxt "input"
msgid "Merchant Key (only if must change it)"
msgstr "Clau del comerç (només si sha de canviar)"
#: web/templates/admin/payment.gohtml:38
msgctxt "input"
msgid "Merchant Key"
msgstr "Clau del comerç"
#: web/templates/admin/payment.gohtml:48
msgctxt "title"
msgid "Environment"
msgstr "Entorn"
#: web/templates/admin/payment.gohtml:55
msgctxt "title"
msgid "Integration"
msgstr "Integració"
#: web/templates/admin/payment.gohtml:62 web/templates/admin/profile.gohtml:75
#: web/templates/admin/taxDetails.gohtml:152
msgctxt "action"
msgid "Save changes"
msgstr "Desa els canvis"
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:10 web/templates/admin/layout.gohtml:72
msgctxt "title"
msgid "Dashboard"
msgstr "Tauler"
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/login.gohtml:6 web/templates/admin/login.gohtml:13
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"
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/login.gohtml:31 web/templates/admin/profile.gohtml:46
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 "Contrasenya"
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/login.gohtml:40
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 "Entra"
#: web/templates/admin/services/form.gohtml:8
#: web/templates/admin/services/form.gohtml:25
msgctxt "title"
msgid "Edit Service"
msgstr "Edició de servei"
#: web/templates/admin/services/form.gohtml:10
#: web/templates/admin/services/form.gohtml:27
msgctxt "title"
msgid "New Service"
msgstr "Nou servei"
#: web/templates/admin/services/index.gohtml:6
#: web/templates/admin/layout.gohtml:56
msgctxt "title"
msgid "Services Page"
msgstr "Pàgina de serveis"
#: web/templates/admin/services/index.gohtml:11
#: web/templates/admin/home/index.gohtml:11
msgctxt "title"
msgid "Carousel"
msgstr "Carrusel"
#: web/templates/admin/services/index.gohtml:67
2023-09-26 14:51:35 +00:00
msgctxt "action"
msgid "Add service"
msgstr "Afegeix servei"
#: web/templates/admin/services/index.gohtml:72
msgctxt "header"
msgid "Service"
msgstr "Servei"
#: web/templates/admin/services/index.gohtml:78
msgid "Are you sure you wish to delete this service?"
msgstr "Esteu segur de voler esborrar aquest servei?"
#: web/templates/admin/services/index.gohtml:101
msgid "No services added yet."
msgstr "No sha afegit cap servei encara."
#: web/templates/admin/services/l10n.gohtml:7
#: web/templates/admin/services/l10n.gohtml:14
msgctxt "title"
msgid "Translate Service to %s"
msgstr "Traducció del servei a %s"
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/profile.gohtml:6 web/templates/admin/profile.gohtml:12
#: web/templates/admin/layout.gohtml:31
msgctxt "title"
msgid "Profile"
msgstr "Perfil"
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/profile.gohtml:17
msgctxt "inut"
msgid "Profile Image"
msgstr "Imatge del perfil"
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/profile.gohtml:43
msgctxt "legend"
msgid "Change password"
msgstr "Canvi de contrasenya"
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/profile.gohtml:55
msgctxt "input"
msgid "Password Confirmation"
msgstr "Confirmació de la contrasenya"
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/profile.gohtml:65
msgctxt "input"
msgid "Language"
msgstr "Idioma"
#: web/templates/admin/taxDetails.gohtml:6
#: web/templates/admin/taxDetails.gohtml:12
msgctxt "title"
msgid "Tax Details"
msgstr "Configuració fiscal"
#: web/templates/admin/taxDetails.gohtml:17
#: web/templates/admin/taxDetails.gohtml:58
msgctxt "input"
msgid "Business Name"
msgstr "Nom de lempresa"
#: web/templates/admin/taxDetails.gohtml:26
msgctxt "input"
msgid "VAT Number"
msgstr "NIF"
#: web/templates/admin/taxDetails.gohtml:34
msgctxt "input"
msgid "Trade Name"
msgstr "Nom comercial"
#: web/templates/admin/taxDetails.gohtml:66
msgctxt "input"
msgid "Address"
msgstr "Adreça"
#: web/templates/admin/taxDetails.gohtml:74
msgctxt "input"
msgid "City"
msgstr "Població"
#: web/templates/admin/taxDetails.gohtml:82
msgctxt "input"
msgid "Province"
msgstr "Província"
#: web/templates/admin/taxDetails.gohtml:90
msgctxt "input"
msgid "Postcode"
msgstr "Codi postal"
#: web/templates/admin/taxDetails.gohtml:108
msgctxt "input"
msgid "RTC number"
msgstr "Número RTC"
#: web/templates/admin/taxDetails.gohtml:116
msgctxt "input"
msgid "Currency"
msgstr "Moneda"
#: web/templates/admin/taxDetails.gohtml:126
msgctxt "input"
msgid "Default Language"
msgstr "Idioma per defecte"
#: web/templates/admin/taxDetails.gohtml:136
msgctxt "input"
msgid "Invoice Number Format"
msgstr "Format del número de factura"
#: web/templates/admin/taxDetails.gohtml:144
msgctxt "input"
msgid "Legal Disclaimer"
msgstr "Nota legal"
#: web/templates/admin/layout.gohtml:27
msgctxt "title"
msgid "User Menu"
msgstr "Menú dusuari"
#: web/templates/admin/layout.gohtml:35
msgctxt "title"
msgid "Company Settings"
msgstr "Paràmetres de lempresa"
#: web/templates/admin/layout.gohtml:50
#: web/templates/admin/media/index.gohtml:6
#: web/templates/admin/media/index.gohtml:11
msgctxt "title"
msgid "Media"
msgstr "Mèdia"
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:53 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 dinici"
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:61
msgctxt "action"
msgid "Logout"
msgstr "Surt"
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 mèdia"
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 "Pujada de nou mèdia"
#: web/templates/admin/media/picker.gohtml:22
#: web/templates/admin/media/upload.gohtml:17
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 "Fitxer"
#: web/templates/admin/media/picker.gohtml:26
#: web/templates/admin/media/form.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
msgid "Maximum upload file size: %s"
msgstr "Mida màxima del fitxer a pujar: %s"
#: web/templates/admin/media/picker.gohtml:31
#: web/templates/admin/media/upload.gohtml:26
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 "Puja"
#: 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ó dun mèdia existent"
#: web/templates/admin/media/picker.gohtml:58
#: web/templates/admin/media/index.gohtml:20
msgid "No media uploaded yet."
msgstr "No sha pujat cap mèdia encara."
#: web/templates/admin/media/form.gohtml:6
#: web/templates/admin/media/form.gohtml:12
msgctxt "title"
msgid "Edit Media"
msgstr "Edició de mèdia"
#: web/templates/admin/media/form.gohtml:18
msgctxt "input"
msgid "Updated file"
msgstr "Fitxer actualitzat"
#: web/templates/admin/media/form.gohtml:27
msgctxt "input"
msgid "Filename"
msgstr "Nom del fitxer"
#: web/templates/admin/media/index.gohtml:12
msgctxt "action"
msgid "Upload media"
msgstr "Puja mèdia"
#: web/templates/admin/media/upload.gohtml:6
#: web/templates/admin/media/upload.gohtml:12
msgctxt "title"
msgid "Upload Media"
msgstr "Pujada de mèdia"
#: pkg/carousel/admin.go:274 pkg/campsite/types/carousel.go:242
msgctxt "input"
msgid "Slide image"
msgstr "Imatge de la diapositiva"
#: pkg/carousel/admin.go:275 pkg/campsite/types/carousel.go:243
msgctxt "action"
msgid "Set slide image"
msgstr "Estableix la imatge de la diapositiva"
#: pkg/carousel/admin.go:327 pkg/campsite/types/carousel.go:297
msgid "Slide image can not be empty."
msgstr "No podeu deixar la imatge de la diapositiva en blanc."
#: pkg/carousel/admin.go:328 pkg/campsite/types/carousel.go:298
msgid "Slide image must be an image media type."
msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge."
#: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:210
#: pkg/booking/public.go:269
msgid "Email can not be empty."
msgstr "No podeu deixar el correu-e en blanc."
#: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:211
#: pkg/booking/public.go:270
msgid "This email is not valid. It should be like name@domain.com."
msgstr "Aquest correu-e no és vàlid. Hauria de ser similar a nom@domini.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 podeu deixar la contrasenya en blanc."
#: pkg/app/login.go:86
msgid "Invalid user or password."
msgstr "Nom dusuari o contrasenya incorrectes."
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àtic"
#: pkg/app/user.go:249 pkg/campsite/types/l10n.go:87
#: pkg/campsite/types/l10n.go:144 pkg/campsite/types/l10n.go:268
#: pkg/campsite/types/option.go:350 pkg/campsite/types/feature.go:243
#: pkg/campsite/types/admin.go:447 pkg/season/l10n.go:69
#: pkg/season/admin.go:404 pkg/services/l10n.go:73 pkg/services/admin.go:266
msgid "Name can not be empty."
msgstr "No podeu deixar el nom en blanc."
#: pkg/app/user.go:250
msgid "Confirmation does not match password."
msgstr "La confirmació no es correspon amb la contrasenya."
#: pkg/app/user.go:251 pkg/company/admin.go:226
msgid "Selected language is not valid."
msgstr "Lidioma escollit no és vàlid."
#: pkg/app/user.go:253
msgid "File must be a valid PNG or JPEG image."
msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida."
#: pkg/app/admin.go:56
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 "Accés prohibit"
#: pkg/campsite/types/option.go:351 pkg/campsite/types/feature.go:244
#: pkg/campsite/types/admin.go:448
msgid "Name must have at least one letter."
msgstr "El nom ha de tenir com a mínim una lletra."
#: pkg/campsite/types/option.go:354
msgid "Minimum can not be empty."
msgstr "No podeu deixar el mínim en blanc."
#: pkg/campsite/types/option.go:355
msgid "Minimum must be an integer number."
msgstr "El valor del mínim ha de ser un número enter."
#: pkg/campsite/types/option.go:357
msgid "Minimum must be zero or greater."
msgstr "El valor del mínim ha de ser com a mínim zero."
#: pkg/campsite/types/option.go:360
msgid "Maximum can not be empty."
msgstr "No podeu deixar el màxim en blanc."
#: pkg/campsite/types/option.go:361
msgid "Maximum must be an integer number."
msgstr "El valor del màxim ha de ser un número enter."
#: pkg/campsite/types/option.go:363
msgid "Maximum must be equal or greater than minimum."
msgstr "El valor del màxim ha de ser igual o superir al del mínim."
#: pkg/campsite/types/option.go:367 pkg/campsite/types/admin.go:461
msgid "Price per night can not be empty."
msgstr "No podeu deixar el preu per nit en blanc."
#: pkg/campsite/types/option.go:368 pkg/campsite/types/admin.go:462
msgid "Price per night must be a decimal number."
msgstr "El preu per nit ha de ser un número decimal."
#: pkg/campsite/types/option.go:369 pkg/campsite/types/admin.go:463
msgid "Price per night must be zero or greater."
msgstr "El preu per nit ha de ser com a mínim zero."
#: pkg/campsite/types/feature.go:242 pkg/services/admin.go:265
msgid "Selected icon is not valid."
msgstr "La icona escollida no és vàlida."
#: pkg/campsite/types/admin.go:323
msgctxt "input"
msgid "Cover image"
msgstr "Imatge de portada"
#: pkg/campsite/types/admin.go:324
msgctxt "action"
msgid "Set campsite type cover"
msgstr "Estableix la portada del tipus dallotjament"
#: pkg/campsite/types/admin.go:450
msgid "Cover image can not be empty."
msgstr "No podeu deixar la imatge de portada en blanc."
#: pkg/campsite/types/admin.go:451
msgid "Cover image must be an image media type."
msgstr "La imatge de portada ha de ser un mèdia de tipus imatge."
#: pkg/campsite/types/admin.go:455
msgid "Maximum number of campers can not be empty."
msgstr "No podeu deixar el número màxim de persones en blanc."
#: pkg/campsite/types/admin.go:456
msgid "Maximum number of campers must be an integer number."
msgstr "El número màxim de persones ha de ser enter."
#: pkg/campsite/types/admin.go:457
msgid "Maximum number of campers must be one or greater."
msgstr "El número màxim de persones no pot ser zero."
#: pkg/campsite/types/admin.go:466
2023-10-01 19:14:39 +00:00
msgid "Minimum number of nights can not be empty."
msgstr "No podeu deixar el número mínim de nits en blanc."
#: pkg/campsite/types/admin.go:467
2023-10-01 19:14:39 +00:00
msgid "Minimum number of nights must be an integer."
msgstr "El número mínim de nits ha de ser enter."
#: pkg/campsite/types/admin.go:468
2023-10-01 19:14:39 +00:00
msgid "Minimum number of nights must be one or greater."
msgstr "El número mínim de nits no pot ser zero."
#: pkg/campsite/types/public.go:160
msgctxt "season"
msgid "Closed"
msgstr "Tancat"
#: pkg/campsite/admin.go:226 pkg/booking/public.go:278
msgid "Selected campsite type is not valid."
msgstr "El tipus dallotjament escollit no és vàlid."
#: pkg/campsite/admin.go:227
msgid "Label can not be empty."
msgstr "No podeu deixar letiqueta en blanc."
#: pkg/season/admin.go:222
msgctxt "month"
msgid "January"
msgstr "gener"
#: pkg/season/admin.go:223
msgctxt "month"
msgid "February"
msgstr "febrer"
#: pkg/season/admin.go:224
msgctxt "month"
msgid "March"
msgstr "març"
#: pkg/season/admin.go:225
msgctxt "month"
msgid "April"
msgstr "abril"
#: pkg/season/admin.go:226
msgctxt "month"
msgid "May"
msgstr "maig"
#: pkg/season/admin.go:227
msgctxt "month"
msgid "June"
msgstr "juny"
#: pkg/season/admin.go:228
msgctxt "month"
msgid "July"
msgstr "juliol"
#: pkg/season/admin.go:229
msgctxt "month"
msgid "August"
msgstr "agost"
#: pkg/season/admin.go:230
msgctxt "month"
msgid "September"
msgstr "setembre"
#: pkg/season/admin.go:231
msgctxt "month"
msgid "October"
msgstr "octubre"
#: pkg/season/admin.go:232
msgctxt "month"
msgid "November"
msgstr "novembre"
#: pkg/season/admin.go:233
msgctxt "month"
msgid "December"
msgstr "desembre"
#: pkg/season/admin.go:405
msgid "Color can not be empty."
msgstr "No podeu deixar el color en blanc."
#: pkg/season/admin.go:406
msgid "This color is not valid. It must be like #123abc."
msgstr "Aquest color no és vàlid. Hauria de ser similar a #123abc."
#: pkg/season/admin.go:506
msgctxt "action"
msgid "Unset"
msgstr "Desassigna"
#: pkg/season/admin.go:537
msgid "Start date can not be empty."
msgstr "No podeu deixar la data dinici en blanc."
#: pkg/season/admin.go:538
msgid "Start date must be a valid date."
msgstr "La data dinici ha de ser una data vàlida."
#: pkg/season/admin.go:540
msgid "End date can not be empty."
msgstr "No podeu deixar la data de fi en blanc."
#: pkg/season/admin.go:541
msgid "End date must be a valid date."
msgstr "La data de fi ha de ser una data vàlida."
#: pkg/company/admin.go:193 pkg/booking/public.go:256
msgid "Selected country is not valid."
msgstr "El país escollit no és vàlid."
#: pkg/company/admin.go:197
msgid "Business name can not be empty."
msgstr "No podeu deixar el nom dempresa en blanc."
#: pkg/company/admin.go:198
msgid "Business name must have at least two letters."
msgstr "El nom dempresa ha de tenir com a mínim dues lletres."
#: pkg/company/admin.go:200
msgid "VAT number can not be empty."
msgstr "No podeu deixar el NIF en blanc."
#: pkg/company/admin.go:201
msgid "This VAT number is not valid."
msgstr "Aquest NIF no és vàlid."
#: pkg/company/admin.go:205 pkg/booking/public.go:272
msgid "Phone can not be empty."
msgstr "No podeu deixar el telèfon en blanc."
#: pkg/company/admin.go:206 pkg/booking/public.go:273
msgid "This phone number is not valid."
msgstr "Aquest número de telèfon no és vàlid."
#: pkg/company/admin.go:214
msgid "This web address is not valid. It should be like https://domain.com/."
msgstr "Aquesta adreça web no és vàlida. Hauria de ser similar a https://domini.com/."
#: pkg/company/admin.go:216
msgid "Address can not be empty."
msgstr "No podeu deixar ladreça en blanc."
#: pkg/company/admin.go:217
msgid "City can not be empty."
msgstr "No podeu deixar la població en blanc."
#: pkg/company/admin.go:218
msgid "Province can not be empty."
msgstr "No podeu deixar la província en blanc."
#: pkg/company/admin.go:219
msgid "Postal code can not be empty."
msgstr "No podeu deixar el codi postal en blanc."
#: pkg/company/admin.go:220 pkg/booking/public.go:265
msgid "This postal code is not valid."
msgstr "Aquest codi postal no és vàlid."
#: pkg/company/admin.go:224
msgid "RTC number can not be empty."
msgstr "No podeu deixar el número dRTC en blanc."
#: pkg/company/admin.go:225
msgid "Selected currency is not valid."
msgstr "La moneda escollida no és vàlida."
#: pkg/company/admin.go:227
msgid "Invoice number format can not be empty."
msgstr "No podeu deixar el format del número de factura en blanc."
#: 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 "Sha detectat un intent de falsificació de petició a llocs creuats."
#: pkg/media/admin.go:265
msgid "Uploaded file can not be empty."
msgstr "No podeu deixar el fitxer del mèdia en blanc."
#: pkg/media/admin.go:324
msgid "Filename can not be empty."
msgstr "No podeu deixar el nom del fitxer en blanc."
#: pkg/booking/admin.go:74
msgctxt "redsys environment"
msgid "Test"
msgstr "Proves"
#: pkg/booking/admin.go:78
msgctxt "redsys environment"
msgid "Live"
msgstr "Real"
#: pkg/booking/admin.go:87
msgctxt "redsys integration"
msgid "InSite"
msgstr "InSite"
#: pkg/booking/admin.go:91
msgctxt "redsys integration"
msgid "Redirect"
msgstr "Redirecció"
#: pkg/booking/admin.go:135
msgid "Merchant code can not be empty."
msgstr "No podeu deixar el codi del comerç en blanc."
#: pkg/booking/admin.go:136
msgid "Merchant code must be exactly nine digits long."
msgstr "El codi del comerç ha de ser de nou dígits."
#: pkg/booking/admin.go:137
msgid "Merchant code must be a number."
msgstr "El codi del comerç."
#: pkg/booking/admin.go:141
msgid "Terminal number can not be empty."
msgstr "No podeu deixar el número del terminal en blanc."
#: pkg/booking/admin.go:142
msgid "Terminal number must be a number between 1 and 999."
msgstr "El número del terminal ha de ser entre 1 i 999"
#: pkg/booking/admin.go:150
msgid "Selected environment is not valid."
msgstr "Lentorn escollit no és vàlid."
#: pkg/booking/admin.go:151
msgid "Selected integration is not valid."
msgstr "La integració escollida no és vàlida."
#: pkg/booking/admin.go:154
msgid "The merchant key is not valid."
msgstr "Aquesta clau del comerç no és vàlid."
#: pkg/booking/public.go:260
msgid "Full name can not be empty."
msgstr "No podeu deixar el nom i els cognoms en blanc."
#: pkg/booking/public.go:261
msgid "Full name must have at least one letter."
msgstr "El nom i els cognoms han de tenir com a mínim una lletra."
#: pkg/booking/public.go:279
msgid "Arrival date can not be empty"
msgstr "No podeu deixar la data darribada en blanc."
#: pkg/booking/public.go:280
msgid "Arrival date must be a valid date."
msgstr "La data darribada ha de ser una data vàlida."
#: pkg/booking/public.go:284
msgid "Departure date can not be empty"
msgstr "No podeu deixar la data de sortida en blanc."
#: pkg/booking/public.go:285
msgid "Departure date must be a valid date."
msgstr "La data de sortida ha de ser una data vàlida."
#: pkg/booking/public.go:286
msgid "The departure date must be after the arrival date."
msgstr "La data de sortida ha de ser posterior a la darribada."
#: pkg/booking/public.go:289
msgid "It is mandatory to agree to the reservation conditions."
msgstr "És obligatori acceptar les condicions de reserves."
#: pkg/booking/public.go:292
#, c-format
msgid "%s can not be empty"
msgstr "No podeu deixar %s en blanc."
#: pkg/booking/public.go:293
#, c-format
msgid "%s must be an integer."
msgstr "%s ha de ser un número enter."
#: pkg/booking/public.go:294
#, c-format
msgid "%s must be %d or greater."
msgstr "El valor de %s ha de ser com a mínim %d."
#: pkg/booking/public.go:295
#, c-format
msgid "%s must be at most %d."
msgstr "El valor de %s ha de ser com a màxim %d."
#~ msgctxt "title"
#~ msgid "Party Details"
#~ msgstr "Dades dels visitants"
#~ msgctxt "input"
#~ msgid "Adults"
#~ msgstr "Adults"
#~ msgctxt "input"
#~ msgid "Teenagers (from 11 to 16 years old)"
#~ msgstr "Adolescents (entre 11 i 16 anys)"
#~ msgctxt "input"
#~ msgid "Children (up to 10 years old)"
#~ msgstr "Nens (fins a 10 anys)"
#~ msgctxt "input"
#~ msgid "Dogs"
#~ msgstr "Gossos"
#~ msgid "Number of adults can not be empty"
#~ msgstr "No podeu deixar el número dadults en blanc."
#~ msgid "Number of adults must be an integer."
#~ msgstr "El número dadults ha de ser enter."
#~ msgid "Number of adults must be one or greater."
#~ msgstr "El número dadults no pot ser zero."
#~ msgid "Number of teenagers can not be empty"
#~ msgstr "No podeu deixar el número dadolescents en blanc."
#~ msgid "Number of teenagers must be an integer."
#~ msgstr "El número dadolescents ha de ser enter."
#~ msgid "Number of teenagers must be zero or greater."
#~ msgstr "El número dadolescents ha de ser com a mínim zero."
#~ msgid "Number of children can not be empty"
#~ msgstr "No podeu deixar el número de nens en blanc."
#~ msgid "Number of children must be an integer."
#~ msgstr "El número de nens ha de ser enter."
#~ msgid "Number of children must be zero or greater."
#~ msgstr "El número de nens ha de ser com a mínim zero."
#~ msgid "Number of dogs can not be empty"
#~ msgstr "No podeu deixar el número de gossos en blanc."
#~ msgid "Number of dogs must be an integer."
#~ msgstr "El número de gossos ha de ser enter."
#~ msgid "Number of dogs must be zero or greater."
#~ msgstr "El número de gossos ha de ser com a mínim zero."
#~ msgid "%s: %s €/night"
#~ msgstr "%s: %s €/nit"
#~ msgctxt "title"
#~ msgid "Pricing"
#~ msgstr "Preus"
#~ msgctxt "input"
#~ msgid "Pricing"
#~ msgstr "Preus"
#~ msgctxt "input"
#~ msgid "Features"
#~ msgstr "Característiques"
#~ msgid "Singular Lodges"
#~ msgstr "Allotjaments singulars"
#~ msgctxt "campsite type"
#~ msgid "Translations"
#~ msgstr "Traduccions"
#~ msgid "Surroundings"
#~ msgstr "Entorn"
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
#~ msgid "Legend"
#~ msgstr "Llegenda"
#~ msgctxt "input"
#~ msgid "Title"
#~ msgstr "Títol"
#~ msgctxt "title"
#~ msgid "Pages"
#~ msgstr "Pàgines"
#~ msgctxt "action"
#~ msgid "Add Page"
#~ msgstr "Afegeix pàgina"
#~ msgctxt "header"
#~ msgid "Title"
#~ msgstr "Títol"