Add management of legal texts

This commit is contained in:
jordi fita mas 2023-12-22 02:23:18 +01:00
parent ee86b34e93
commit 03c20fec88
27 changed files with 1395 additions and 286 deletions

56
deploy/legal_text.sql Normal file
View File

@ -0,0 +1,56 @@
-- Deploy camper:legal_text to pg
-- requires: roles
-- requires: schema_camper
-- requires: company
-- requires: user_profile
begin;
set search_path to camper, public;
create table legal_text (
company_id integer not null references company,
slug text constraint valid_slug check(slug ~ '^[a-z0-9]+(-[a-z0-9])*$'),
name text not null constraint name_not_empty check(length(trim(name)) > 0),
content xml not null,
primary key (company_id, slug)
);
grant select on table legal_text to guest;
grant select on table legal_text to employee;
grant select, insert, update, delete on table legal_text to admin;
alter table legal_text enable row level security;
create policy guest_ok
on legal_text
for select
using (true)
;
create policy insert_to_company
on legal_text
for insert
with check (
company_id in (select company_id from user_profile)
)
;
create policy update_company
on legal_text
for update
using (
company_id in (select company_id from user_profile)
)
;
create policy delete_from_company
on legal_text
for delete
using (
company_id in (select company_id from user_profile)
)
;
commit;

View File

@ -0,0 +1,25 @@
-- Deploy camper:legal_text_i18n to pg
-- requires: roles
-- requires: schema_camper
-- requires: legal_text
-- requires: language
begin;
set search_path to camper, public;
create table legal_text_i18n (
company_id integer not null,
slug text not null,
lang_tag text not null references language,
name text not null,
content xml not null,
foreign key (company_id, slug) references legal_text,
primary key (company_id, slug, lang_tag)
);
grant select on table legal_text_i18n to guest;
grant select on table legal_text_i18n to employee;
grant select, insert, update, delete on table legal_text_i18n to admin;
commit;

View File

@ -0,0 +1,25 @@
-- Deploy camper:translate_legal_text to pg
-- requires: roles
-- requires: schema_camper
-- requires: legal_text_i18n
begin;
set search_path to camper, public;
create or replace function translate_legal_text(company_id integer, slug text, lang_tag text, name text, content text) returns void as
$$
insert into legal_text_i18n (company_id, slug, lang_tag, name, content)
values (company_id, slug, lang_tag, coalesce(name, ''), xmlparse(content coalesce(content, '')))
on conflict (company_id, slug, lang_tag) do update
set name = excluded.name
, content = excluded.content
;
$$
language sql
;
revoke execute on function translate_legal_text(integer, text, text, text, text) from public;
grant execute on function translate_legal_text(integer, text, text, text, text) to admin;
commit;

View File

@ -6,7 +6,6 @@
package app package app
import ( import (
"dev.tandem.ws/tandem/camper/pkg/location"
"net/http" "net/http"
"dev.tandem.ws/tandem/camper/pkg/auth" "dev.tandem.ws/tandem/camper/pkg/auth"
@ -16,7 +15,9 @@ import (
"dev.tandem.ws/tandem/camper/pkg/database" "dev.tandem.ws/tandem/camper/pkg/database"
"dev.tandem.ws/tandem/camper/pkg/home" "dev.tandem.ws/tandem/camper/pkg/home"
httplib "dev.tandem.ws/tandem/camper/pkg/http" httplib "dev.tandem.ws/tandem/camper/pkg/http"
"dev.tandem.ws/tandem/camper/pkg/legal"
"dev.tandem.ws/tandem/camper/pkg/locale" "dev.tandem.ws/tandem/camper/pkg/locale"
"dev.tandem.ws/tandem/camper/pkg/location"
"dev.tandem.ws/tandem/camper/pkg/media" "dev.tandem.ws/tandem/camper/pkg/media"
"dev.tandem.ws/tandem/camper/pkg/season" "dev.tandem.ws/tandem/camper/pkg/season"
"dev.tandem.ws/tandem/camper/pkg/services" "dev.tandem.ws/tandem/camper/pkg/services"
@ -27,6 +28,7 @@ type adminHandler struct {
campsite *campsite.AdminHandler campsite *campsite.AdminHandler
company *company.AdminHandler company *company.AdminHandler
home *home.AdminHandler home *home.AdminHandler
legal *legal.AdminHandler
location *location.AdminHandler location *location.AdminHandler
media *media.AdminHandler media *media.AdminHandler
payment *booking.AdminHandler payment *booking.AdminHandler
@ -39,6 +41,7 @@ func newAdminHandler(locales locale.Locales, mediaDir string) *adminHandler {
campsite: campsite.NewAdminHandler(locales), campsite: campsite.NewAdminHandler(locales),
company: company.NewAdminHandler(), company: company.NewAdminHandler(),
home: home.NewAdminHandler(locales), home: home.NewAdminHandler(locales),
legal: legal.NewAdminHandler(),
location: location.NewAdminHandler(), location: location.NewAdminHandler(),
media: media.NewAdminHandler(mediaDir), media: media.NewAdminHandler(mediaDir),
payment: booking.NewAdminHandler(), payment: booking.NewAdminHandler(),
@ -69,6 +72,8 @@ func (h *adminHandler) Handle(user *auth.User, company *auth.Company, conn *data
h.company.Handler(user, company, conn).ServeHTTP(w, r) h.company.Handler(user, company, conn).ServeHTTP(w, r)
case "home": case "home":
h.home.Handler(user, company, conn).ServeHTTP(w, r) h.home.Handler(user, company, conn).ServeHTTP(w, r)
case "legal":
h.legal.Handler(user, company, conn).ServeHTTP(w, r)
case "location": case "location":
h.location.Handler(user, company, conn).ServeHTTP(w, r) h.location.Handler(user, company, conn).ServeHTTP(w, r)
case "media": case "media":

View File

@ -6,6 +6,7 @@
package app package app
import ( import (
"dev.tandem.ws/tandem/camper/pkg/legal"
"net/http" "net/http"
"dev.tandem.ws/tandem/camper/pkg/auth" "dev.tandem.ws/tandem/camper/pkg/auth"
@ -23,6 +24,7 @@ type publicHandler struct {
home *home.PublicHandler home *home.PublicHandler
booking *booking.PublicHandler booking *booking.PublicHandler
campsite *campsite.PublicHandler campsite *campsite.PublicHandler
legal *legal.PublicHandler
location *location.PublicHandler location *location.PublicHandler
services *services.PublicHandler services *services.PublicHandler
} }
@ -32,6 +34,7 @@ func newPublicHandler() *publicHandler {
home: home.NewPublicHandler(), home: home.NewPublicHandler(),
booking: booking.NewPublicHandler(), booking: booking.NewPublicHandler(),
campsite: campsite.NewPublicHandler(), campsite: campsite.NewPublicHandler(),
legal: legal.NewPublicHandler(),
location: location.NewPublicHandler(), location: location.NewPublicHandler(),
services: services.NewPublicHandler(), services: services.NewPublicHandler(),
} }
@ -50,6 +53,8 @@ func (h *publicHandler) Handler(user *auth.User, company *auth.Company, conn *da
campgroundHandler(user, company, conn).ServeHTTP(w, r) campgroundHandler(user, company, conn).ServeHTTP(w, r)
case "campsites": case "campsites":
h.campsite.Handler(user, company, conn).ServeHTTP(w, r) h.campsite.Handler(user, company, conn).ServeHTTP(w, r)
case "legal":
h.legal.Handler(user, company, conn).ServeHTTP(w, r)
case "location": case "location":
h.location.Handler(user, company, conn).ServeHTTP(w, r) h.location.Handler(user, company, conn).ServeHTTP(w, r)
case "services": case "services":

View File

@ -102,3 +102,8 @@ func (tx *Tx) TranslateLocation(ctx context.Context, companyID int, langTag lang
_, err := tx.Exec(ctx, "select translate_location($1, $2, $3, $4)", companyID, langTag, directions, openingHours) _, err := tx.Exec(ctx, "select translate_location($1, $2, $3, $4)", companyID, langTag, directions, openingHours)
return err return err
} }
func (tx *Tx) TranslateLegalText(ctx context.Context, companyID int, slug string, langTag language.Tag, name string, content string) error {
_, err := tx.Exec(ctx, "select translate_legal_text($1, $2, $3, $4, $5)", companyID, slug, langTag, name, content)
return err
}

View File

@ -7,10 +7,14 @@ package form
import ( import (
"database/sql/driver" "database/sql/driver"
"dev.tandem.ws/tandem/camper/pkg/locale"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
"golang.org/x/text/language"
"dev.tandem.ws/tandem/camper/pkg/database"
"dev.tandem.ws/tandem/camper/pkg/locale"
) )
type Input struct { type Input struct {
@ -69,3 +73,14 @@ func (input I18nInput) FillValue(r *http.Request) {
inner.FillValue(r) inner.FillValue(r)
} }
} }
func (input I18nInput) FillArray(array database.RecordArray) error {
for _, el := range array.Elements {
tag, err := language.Parse(el.Fields[0].Get().(string))
if err != nil {
return err
}
input[tag.String()].Val = el.Fields[1].Get().(string)
}
return nil
}

263
pkg/legal/admin.go Normal file
View File

@ -0,0 +1,263 @@
package legal
import (
"context"
"net/http"
"github.com/jackc/pgx/v4"
"dev.tandem.ws/tandem/camper/pkg/auth"
"dev.tandem.ws/tandem/camper/pkg/database"
"dev.tandem.ws/tandem/camper/pkg/form"
httplib "dev.tandem.ws/tandem/camper/pkg/http"
"dev.tandem.ws/tandem/camper/pkg/locale"
"dev.tandem.ws/tandem/camper/pkg/template"
)
type AdminHandler struct {
}
func NewAdminHandler() *AdminHandler {
return &AdminHandler{}
}
func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var head string
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
switch head {
case "":
switch r.Method {
case http.MethodGet:
serveLegalIndex(w, r, user, company, conn)
case http.MethodPost:
addLegal(w, r, user, company, conn)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost)
}
case "new":
switch r.Method {
case http.MethodGet:
f := newLegalForm(company)
f.MustRender(w, r, user, company)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet)
}
default:
f := newLegalForm(company)
if err := f.FillFromDatabase(r.Context(), conn, head); err != nil {
if database.ErrorIsNotFound(err) {
http.NotFound(w, r)
return
}
panic(err)
}
h.legalHandler(user, company, conn, f).ServeHTTP(w, r)
}
})
}
func (h *AdminHandler) legalHandler(user *auth.User, company *auth.Company, conn *database.Conn, f *legalForm) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var head string
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
switch head {
case "":
switch r.Method {
case http.MethodGet:
f.MustRender(w, r, user, company)
case http.MethodPut:
editLegal(w, r, user, company, conn, f)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
}
default:
http.NotFound(w, r)
}
})
}
func serveLegalIndex(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
legals, err := collectLegalEntries(r.Context(), conn, company)
if err != nil {
panic(err)
}
page := &legalIndex{
Texts: legals,
}
page.MustRender(w, r, user, company)
}
func collectLegalEntries(ctx context.Context, conn *database.Conn, company *auth.Company) ([]*legalEntry, error) {
rows, err := conn.Query(ctx, `
select '/admin/legal/' || slug
, name
from legal_text
where company_id = $1
order by name
`, company.ID)
if err != nil {
return nil, err
}
defer rows.Close()
var legals []*legalEntry
for rows.Next() {
legal := &legalEntry{}
if err = rows.Scan(&legal.URL, &legal.Name); err != nil {
return nil, err
}
legals = append(legals, legal)
}
return legals, nil
}
type legalEntry struct {
URL string
Name string
}
type legalIndex struct {
Texts []*legalEntry
}
func (page *legalIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdmin(w, r, user, company, "legal/index.gohtml", page)
}
func addLegal(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
f := newLegalForm(company)
processLegalForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error {
_, err := tx.Exec(ctx, `
insert into legal_text (company_id, slug, name, content)
values ($1, $2, $3, xmlparse(content $4))
`, company.ID, f.Slug.Val, f.Name[company.DefaultLanguage.String()].Val, f.Content[company.DefaultLanguage.String()])
if err != nil {
return err
}
for lang := range company.Locales {
if err := tx.TranslateLegalText(ctx, company.ID, f.Slug.Val, lang, f.Name[lang.String()].Val, f.Content[lang.String()].Val); err != nil {
return err
}
}
return nil
})
}
func editLegal(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *legalForm) {
processLegalForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error {
_, err := tx.Exec(ctx, `
update legal_text
set name = $3
, content = xmlparse(content $4)
where company_id = $1
and slug = $2
`, company.ID, f.Slug.Val, f.Name[company.DefaultLanguage.String()].Val, f.Content[company.DefaultLanguage.String()])
if err != nil {
return err
}
for lang := range company.Locales {
if err := tx.TranslateLegalText(ctx, company.ID, f.Slug.Val, lang, f.Name[lang.String()].Val, f.Content[lang.String()].Val); err != nil {
return err
}
}
return nil
})
}
func processLegalForm(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *legalForm, act func(ctx context.Context, tx *database.Tx) error) {
if ok, err := form.Handle(f, w, r, user); err != nil {
return
} else if !ok {
f.MustRender(w, r, user, company)
return
}
tx := conn.MustBegin(r.Context())
if err := act(r.Context(), tx); err == nil {
if err := tx.Commit(r.Context()); err != nil {
panic(err)
}
} else {
if err := tx.Rollback(r.Context()); err != nil {
panic(err)
}
panic(err)
}
httplib.Redirect(w, r, "/admin/legal/"+f.Slug.Val, http.StatusSeeOther)
}
type legalForm struct {
company *auth.Company
URL string
Slug *form.Input
Name form.I18nInput
Content form.I18nInput
}
func newLegalForm(company *auth.Company) *legalForm {
f := &legalForm{
company: company,
Slug: &form.Input{
Name: "slug",
},
Name: form.NewI18nInput(company.Locales, "name"),
Content: form.NewI18nInput(company.Locales, "content"),
}
return f
}
func (f *legalForm) FillFromDatabase(ctx context.Context, conn *database.Conn, slug string) error {
var name database.RecordArray
var content database.RecordArray
row := conn.QueryRow(ctx, `
select '/admin/legal/' || text.slug
, text.slug
, text.name
, text.content::text
, array_agg((lang_tag, i18n.name))
, array_agg((lang_tag, i18n.content::text))
from legal_text as text
left join legal_text_i18n as i18n using (company_id, slug)
where text.company_id = $1
and text.slug = $2
group by text.slug
, text.name
, text.content::text
`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, f.company.ID, slug)
if err := row.Scan(&f.URL, &f.Slug.Val, &f.Name[f.company.DefaultLanguage.String()].Val, &f.Content[f.company.DefaultLanguage.String()].Val, &name, &content); err != nil {
return err
}
if err := f.Name.FillArray(name); err != nil {
return err
}
if err := f.Content.FillArray(content); err != nil {
return err
}
return nil
}
func (f *legalForm) Parse(r *http.Request) error {
if err := r.ParseForm(); err != nil {
return err
}
f.Slug.FillValue(r)
f.Name.FillValue(r)
f.Content.FillValue(r)
return nil
}
func (f *legalForm) Valid(l *locale.Locale) bool {
v := form.NewValidator(l)
if v.CheckRequired(f.Name[f.company.DefaultLanguage.String()], l.GettextNoop("Name can not be empty.")) {
v.CheckMinLength(f.Name[f.company.DefaultLanguage.String()], 1, l.GettextNoop("Name must have at least one letter."))
}
return v.AllOK
}
func (f *legalForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdmin(w, r, user, company, "legal/form.gohtml", f)
}

78
pkg/legal/public.go Normal file
View File

@ -0,0 +1,78 @@
package legal
import (
"context"
"dev.tandem.ws/tandem/camper/pkg/locale"
gotemplate "html/template"
"net/http"
"dev.tandem.ws/tandem/camper/pkg/auth"
"dev.tandem.ws/tandem/camper/pkg/database"
httplib "dev.tandem.ws/tandem/camper/pkg/http"
"dev.tandem.ws/tandem/camper/pkg/template"
)
type PublicHandler struct {
}
func NewPublicHandler() *PublicHandler {
return &PublicHandler{}
}
func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var slug string
slug, r.URL.Path = httplib.ShiftPath(r.URL.Path)
var head string
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
switch head {
case "":
switch r.Method {
case http.MethodGet:
page, err := newLegalPage(r.Context(), company, conn, user.Locale, slug)
if database.ErrorIsNotFound(err) {
http.NotFound(w, r)
return
} else if err != nil {
panic(err)
}
page.MustRender(w, r, user, company, conn)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet)
}
default:
http.NotFound(w, r)
}
})
}
type legalPage struct {
*template.PublicPage
Name string
Content gotemplate.HTML
}
func newLegalPage(ctx context.Context, company *auth.Company, conn *database.Conn, loc *locale.Locale, slug string) (*legalPage, error) {
page := &legalPage{
PublicPage: template.NewPublicPage(),
}
row := conn.QueryRow(ctx, `
select coalesce(i18n.name, text.name) as l10n_name
, coalesce(i18n.content, text.content)::text as l10n_description
from legal_text as text
left join legal_text_i18n as i18n on text.company_id = i18n.company_id and text.slug = i18n.slug and i18n.lang_tag = $1
where text.company_id = $2
and text.slug = $3
`, loc.Language, company.ID, slug)
if err := row.Scan(&page.Name, &page.Content); err != nil {
return nil, err
}
return page, nil
}
func (p *legalPage) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
p.Setup(r, user, company, conn)
template.MustRenderPublic(w, r, user, company, "legal.gohtml", p)
}

View File

@ -2,7 +2,6 @@ package location
import ( import (
"context" "context"
"golang.org/x/text/language"
"net/http" "net/http"
"github.com/jackc/pgx/v4" "github.com/jackc/pgx/v4"
@ -116,26 +115,15 @@ func (f *locationForm) FillFromDatabase(ctx context.Context, company *auth.Compa
if err != nil { if err != nil {
return err return err
} }
if err := fillI18nInput(f.Directions, directions); err != nil { if err := f.Directions.FillArray(directions); err != nil {
return err return err
} }
if err := fillI18nInput(f.OpeningDates, openingDates); err != nil { if err := f.OpeningDates.FillArray(openingDates); err != nil {
return err return err
} }
return nil return nil
} }
func fillI18nInput(input form.I18nInput, array database.RecordArray) error {
for _, el := range array.Elements {
tag, err := language.Parse(el.Fields[0].Get().(string))
if err != nil {
return err
}
input[tag.String()].Val = el.Fields[1].Get().(string)
}
return nil
}
func (f *locationForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { func (f *locationForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdmin(w, r, user, company, "location.gohtml", f) template.MustRenderAdmin(w, r, user, company, "location.gohtml", f)
} }

218
po/ca.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: camper\n" "Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2023-12-21 21:08+0100\n" "POT-Creation-Date: 2023-12-22 02:19+0100\n"
"PO-Revision-Date: 2023-07-22 23:45+0200\n" "PO-Revision-Date: 2023-07-22 23:45+0200\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n" "Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Catalan <ca@dodds.net>\n" "Language-Team: Catalan <ca@dodds.net>\n"
@ -43,7 +43,7 @@ msgstr "Ha fallat el pagament"
#: web/templates/public/services.gohtml:6 #: web/templates/public/services.gohtml:6
#: web/templates/public/services.gohtml:15 #: web/templates/public/services.gohtml:15
#: web/templates/public/layout.gohtml:51 web/templates/public/layout.gohtml:79 #: web/templates/public/layout.gohtml:66 web/templates/public/layout.gohtml:94
#: web/templates/admin/services/index.gohtml:66 #: web/templates/admin/services/index.gohtml:66
msgctxt "title" msgctxt "title"
msgid "Services" msgid "Services"
@ -55,14 +55,14 @@ msgstr "El càmping disposa de diversos serveis."
#: web/templates/public/location.gohtml:6 #: web/templates/public/location.gohtml:6
#: web/templates/public/location.gohtml:12 #: web/templates/public/location.gohtml:12
#: web/templates/public/layout.gohtml:53 web/templates/public/layout.gohtml:81 #: web/templates/public/layout.gohtml:68 web/templates/public/layout.gohtml:96
#: web/templates/admin/layout.gohtml:60 #: web/templates/admin/layout.gohtml:60
msgctxt "title" msgctxt "title"
msgid "Location" msgid "Location"
msgstr "Com arribar" msgstr "Com arribar"
#: web/templates/public/home.gohtml:6 web/templates/public/layout.gohtml:37 #: web/templates/public/home.gohtml:6 web/templates/public/layout.gohtml:52
#: web/templates/public/layout.gohtml:77 #: web/templates/public/layout.gohtml:92
msgctxt "title" msgctxt "title"
msgid "Home" msgid "Home"
msgstr "Inici" msgstr "Inici"
@ -87,7 +87,7 @@ msgstr "Vine a gaudir!"
#: web/templates/public/home.gohtml:35 #: web/templates/public/home.gohtml:35
#: web/templates/public/surroundings.gohtml:6 #: web/templates/public/surroundings.gohtml:6
#: web/templates/public/surroundings.gohtml:10 #: web/templates/public/surroundings.gohtml:10
#: web/templates/public/layout.gohtml:52 web/templates/public/layout.gohtml:80 #: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95
msgctxt "title" msgctxt "title"
msgid "Surroundings" msgid "Surroundings"
msgstr "Lentorn" msgstr "Lentorn"
@ -271,13 +271,13 @@ msgstr "Hi ha diversos punts on poder anar amb caiac, des de trams del riu Ter c
#: web/templates/public/campground.gohtml:6 #: web/templates/public/campground.gohtml:6
#: web/templates/public/campground.gohtml:11 #: web/templates/public/campground.gohtml:11
#: web/templates/public/layout.gohtml:38 web/templates/public/layout.gohtml:78 #: web/templates/public/layout.gohtml:53 web/templates/public/layout.gohtml:93
msgctxt "title" msgctxt "title"
msgid "Campground" msgid "Campground"
msgstr "El càmping" msgstr "El càmping"
#: web/templates/public/booking.gohtml:6 web/templates/public/booking.gohtml:11 #: web/templates/public/booking.gohtml:6 web/templates/public/booking.gohtml:11
#: web/templates/public/layout.gohtml:54 #: web/templates/public/layout.gohtml:69
msgctxt "title" msgctxt "title"
msgid "Booking" msgid "Booking"
msgstr "Reserva" msgstr "Reserva"
@ -365,8 +365,8 @@ msgctxt "input"
msgid "I have read and I accept the reservation conditions" msgid "I have read and I accept the reservation conditions"
msgstr "He llegit i accepto les condicions de reserves" msgstr "He llegit i accepto les condicions de reserves"
#: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:32 #: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:47
#: web/templates/public/layout.gohtml:109 #: web/templates/public/layout.gohtml:130
msgid "Campsite Montagut" msgid "Campsite Montagut"
msgstr "Càmping Montagut" msgstr "Càmping Montagut"
@ -374,28 +374,118 @@ msgstr "Càmping Montagut"
msgid "Skip to main content" msgid "Skip to main content"
msgstr "Salta al contingut principal" msgstr "Salta al contingut principal"
#: web/templates/public/layout.gohtml:42 web/templates/public/layout.gohtml:88 #: web/templates/public/layout.gohtml:57 web/templates/public/layout.gohtml:103
#: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:6
#: web/templates/admin/campsite/index.gohtml:12 #: web/templates/admin/campsite/index.gohtml:12
#: web/templates/admin/layout.gohtml:45 web/templates/admin/layout.gohtml:79 #: web/templates/admin/layout.gohtml:45 web/templates/admin/layout.gohtml:82
msgctxt "title" msgctxt "title"
msgid "Campsites" msgid "Campsites"
msgstr "Allotjaments" msgstr "Allotjaments"
#: web/templates/public/layout.gohtml:75 #: web/templates/public/layout.gohtml:90
msgctxt "title" msgctxt "title"
msgid "Sections" msgid "Sections"
msgstr "Apartats" msgstr "Apartats"
#: web/templates/public/layout.gohtml:99 #: web/templates/public/layout.gohtml:114
msgctxt "title" msgctxt "title"
msgid "Opening" msgid "Opening"
msgstr "Obertura" msgstr "Obertura"
#: web/templates/public/layout.gohtml:106 #: web/templates/public/layout.gohtml:121
msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s" 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" msgstr "<abbr title=\"Número\">Núm.</abbr> <abbr title=\"Registre de Turisme de Catalunya\">RTC</abbr> %s"
#: web/templates/admin/legal/form.gohtml:8
#: web/templates/admin/legal/form.gohtml:25
msgctxt "title"
msgid "Edit Legal Text"
msgstr "Edició del text legal"
#: web/templates/admin/legal/form.gohtml:10
#: web/templates/admin/legal/form.gohtml:27
msgctxt "title"
msgid "New Legal Text"
msgstr "Nou text legal"
#: web/templates/admin/legal/form.gohtml:37
msgctxt "input"
msgid "Slug"
msgstr "Àlies"
#: web/templates/admin/legal/form.gohtml:46
#: 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/legal/form.gohtml:64
msgctxt "input"
msgid "Content"
msgstr "Contingut"
#: web/templates/admin/legal/form.gohtml:84
#: 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/legal/form.gohtml:86
#: 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/legal/index.gohtml:6
#: web/templates/admin/legal/index.gohtml:12
#: web/templates/admin/layout.gohtml:63
msgctxt "title"
msgid "Legal Texts"
msgstr "Texts legals"
#: web/templates/admin/legal/index.gohtml:11
msgctxt "action"
msgid "Add Legal Text"
msgstr "Afegeix text legal"
#: web/templates/admin/legal/index.gohtml:17
#: web/templates/admin/campsite/feature/index.gohtml:26
#: 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/legal/index.gohtml:29
msgid "No legal texts added yet."
msgstr "No sha afegit cap text legal encara."
#: web/templates/admin/carousel/form.gohtml:8 #: web/templates/admin/carousel/form.gohtml:8
#: web/templates/admin/carousel/form.gohtml:25 #: web/templates/admin/carousel/form.gohtml:25
msgctxt "title" msgctxt "title"
@ -416,31 +506,6 @@ msgctxt "input"
msgid "Caption" msgid "Caption"
msgstr "Llegenda" 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:7
#: web/templates/admin/carousel/l10n.gohtml:14 #: web/templates/admin/carousel/l10n.gohtml:14
msgctxt "title" msgctxt "title"
@ -534,21 +599,6 @@ msgctxt "input"
msgid "Icon" msgid "Icon"
msgstr "Icona" 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:6
#: web/templates/admin/campsite/feature/index.gohtml:12 #: web/templates/admin/campsite/feature/index.gohtml:12
msgctxt "title" msgctxt "title"
@ -560,14 +610,6 @@ msgctxt "action"
msgid "Add Feature" msgid "Add Feature"
msgstr "Afegeix característica" msgstr "Afegeix característica"
#: web/templates/admin/campsite/feature/index.gohtml:26
#: 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:27 #: web/templates/admin/campsite/feature/index.gohtml:27
#: web/templates/admin/campsite/carousel/index.gohtml:27 #: web/templates/admin/campsite/carousel/index.gohtml:27
#: web/templates/admin/campsite/option/index.gohtml:26 #: web/templates/admin/campsite/option/index.gohtml:26
@ -979,7 +1021,7 @@ msgid "Integration"
msgstr "Integració" msgstr "Integració"
#: web/templates/admin/dashboard.gohtml:6 #: web/templates/admin/dashboard.gohtml:6
#: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:76 #: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:79
msgctxt "title" msgctxt "title"
msgid "Dashboard" msgid "Dashboard"
msgstr "Tauler" msgstr "Tauler"
@ -1162,7 +1204,7 @@ msgctxt "title"
msgid "Home Page" msgid "Home Page"
msgstr "Pàgina dinici" msgstr "Pàgina dinici"
#: web/templates/admin/layout.gohtml:65 #: web/templates/admin/layout.gohtml:68
msgctxt "action" msgctxt "action"
msgid "Logout" msgid "Logout"
msgstr "Surt" msgstr "Surt"
@ -1232,6 +1274,19 @@ msgctxt "title"
msgid "Upload Media" msgid "Upload Media"
msgstr "Pujada de mèdia" msgstr "Pujada de mèdia"
#: pkg/legal/admin.go:255 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:253
#: pkg/campsite/types/admin.go:447 pkg/season/l10n.go:69
#: pkg/season/admin.go:405 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/legal/admin.go:256 pkg/campsite/types/option.go:351
#: pkg/campsite/types/feature.go:254 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/carousel/admin.go:285 pkg/campsite/types/carousel.go:242 #: pkg/carousel/admin.go:285 pkg/campsite/types/carousel.go:242
msgctxt "input" msgctxt "input"
msgid "Slide image" msgid "Slide image"
@ -1273,14 +1328,6 @@ msgctxt "language option"
msgid "Automatic" msgid "Automatic"
msgstr "Automàtic" 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:253
#: 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 #: pkg/app/user.go:250
msgid "Confirmation does not match password." msgid "Confirmation does not match password."
msgstr "La confirmació no es correspon amb la contrasenya." msgstr "La confirmació no es correspon amb la contrasenya."
@ -1293,15 +1340,10 @@ msgstr "Lidioma escollit no és vàlid."
msgid "File must be a valid PNG or JPEG image." msgid "File must be a valid PNG or JPEG image."
msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida." msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida."
#: pkg/app/admin.go:59 #: pkg/app/admin.go:62
msgid "Access forbidden" msgid "Access forbidden"
msgstr "Accés prohibit" msgstr "Accés prohibit"
#: pkg/campsite/types/option.go:351 pkg/campsite/types/feature.go:254
#: 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 #: pkg/campsite/types/option.go:354
msgid "Minimum can not be empty." msgid "Minimum can not be empty."
msgstr "No podeu deixar el mínim en blanc." msgstr "No podeu deixar el mínim en blanc."
@ -1457,32 +1499,32 @@ msgctxt "month"
msgid "December" msgid "December"
msgstr "desembre" msgstr "desembre"
#: pkg/season/admin.go:405 #: pkg/season/admin.go:406
msgid "Color can not be empty." msgid "Color can not be empty."
msgstr "No podeu deixar el color en blanc." msgstr "No podeu deixar el color en blanc."
#: pkg/season/admin.go:406 #: pkg/season/admin.go:407
msgid "This color is not valid. It must be like #123abc." msgid "This color is not valid. It must be like #123abc."
msgstr "Aquest color no és vàlid. Hauria de ser similar a #123abc." msgstr "Aquest color no és vàlid. Hauria de ser similar a #123abc."
#: pkg/season/admin.go:506 #: pkg/season/admin.go:507
msgctxt "action" msgctxt "action"
msgid "Unset" msgid "Unset"
msgstr "Desassigna" msgstr "Desassigna"
#: pkg/season/admin.go:537 #: pkg/season/admin.go:538
msgid "Start date can not be empty." msgid "Start date can not be empty."
msgstr "No podeu deixar la data dinici en blanc." msgstr "No podeu deixar la data dinici en blanc."
#: pkg/season/admin.go:538 #: pkg/season/admin.go:539
msgid "Start date must be a valid date." msgid "Start date must be a valid date."
msgstr "La data dinici ha de ser una data vàlida." msgstr "La data dinici ha de ser una data vàlida."
#: pkg/season/admin.go:540 #: pkg/season/admin.go:541
msgid "End date can not be empty." msgid "End date can not be empty."
msgstr "No podeu deixar la data de fi en blanc." msgstr "No podeu deixar la data de fi en blanc."
#: pkg/season/admin.go:541 #: pkg/season/admin.go:542
msgid "End date must be a valid date." msgid "End date must be a valid date."
msgstr "La data de fi ha de ser una data vàlida." msgstr "La data de fi ha de ser una data vàlida."
@ -1666,10 +1708,6 @@ msgstr "El valor de %s ha de ser com a mínim %d."
msgid "%s must be at most %d." msgid "%s must be at most %d."
msgstr "El valor de %s ha de ser com a màxim %d." msgstr "El valor de %s ha de ser com a màxim %d."
#~ msgctxt "title"
#~ msgid "Contact"
#~ msgstr "Contacte"
#~ msgctxt "title" #~ msgctxt "title"
#~ msgid "Party Details" #~ msgid "Party Details"
#~ msgstr "Dades dels visitants" #~ msgstr "Dades dels visitants"

218
po/es.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: camper\n" "Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2023-12-21 21:08+0100\n" "POT-Creation-Date: 2023-12-22 02:19+0100\n"
"PO-Revision-Date: 2023-07-22 23:46+0200\n" "PO-Revision-Date: 2023-07-22 23:46+0200\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n" "Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Spanish <es@tp.org.es>\n" "Language-Team: Spanish <es@tp.org.es>\n"
@ -43,7 +43,7 @@ msgstr "Pago fallido"
#: web/templates/public/services.gohtml:6 #: web/templates/public/services.gohtml:6
#: web/templates/public/services.gohtml:15 #: web/templates/public/services.gohtml:15
#: web/templates/public/layout.gohtml:51 web/templates/public/layout.gohtml:79 #: web/templates/public/layout.gohtml:66 web/templates/public/layout.gohtml:94
#: web/templates/admin/services/index.gohtml:66 #: web/templates/admin/services/index.gohtml:66
msgctxt "title" msgctxt "title"
msgid "Services" msgid "Services"
@ -55,14 +55,14 @@ msgstr "El camping dispone de varios servicios."
#: web/templates/public/location.gohtml:6 #: web/templates/public/location.gohtml:6
#: web/templates/public/location.gohtml:12 #: web/templates/public/location.gohtml:12
#: web/templates/public/layout.gohtml:53 web/templates/public/layout.gohtml:81 #: web/templates/public/layout.gohtml:68 web/templates/public/layout.gohtml:96
#: web/templates/admin/layout.gohtml:60 #: web/templates/admin/layout.gohtml:60
msgctxt "title" msgctxt "title"
msgid "Location" msgid "Location"
msgstr "Cómo llegar" msgstr "Cómo llegar"
#: web/templates/public/home.gohtml:6 web/templates/public/layout.gohtml:37 #: web/templates/public/home.gohtml:6 web/templates/public/layout.gohtml:52
#: web/templates/public/layout.gohtml:77 #: web/templates/public/layout.gohtml:92
msgctxt "title" msgctxt "title"
msgid "Home" msgid "Home"
msgstr "Inicio" msgstr "Inicio"
@ -87,7 +87,7 @@ msgstr "¡Ven a disfrutar!"
#: web/templates/public/home.gohtml:35 #: web/templates/public/home.gohtml:35
#: web/templates/public/surroundings.gohtml:6 #: web/templates/public/surroundings.gohtml:6
#: web/templates/public/surroundings.gohtml:10 #: web/templates/public/surroundings.gohtml:10
#: web/templates/public/layout.gohtml:52 web/templates/public/layout.gohtml:80 #: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95
msgctxt "title" msgctxt "title"
msgid "Surroundings" msgid "Surroundings"
msgstr "El entorno" msgstr "El entorno"
@ -271,13 +271,13 @@ msgstr "Hay diversos puntos dónde podéis ir en kayak, desde tramos del río Te
#: web/templates/public/campground.gohtml:6 #: web/templates/public/campground.gohtml:6
#: web/templates/public/campground.gohtml:11 #: web/templates/public/campground.gohtml:11
#: web/templates/public/layout.gohtml:38 web/templates/public/layout.gohtml:78 #: web/templates/public/layout.gohtml:53 web/templates/public/layout.gohtml:93
msgctxt "title" msgctxt "title"
msgid "Campground" msgid "Campground"
msgstr "El camping" msgstr "El camping"
#: web/templates/public/booking.gohtml:6 web/templates/public/booking.gohtml:11 #: web/templates/public/booking.gohtml:6 web/templates/public/booking.gohtml:11
#: web/templates/public/layout.gohtml:54 #: web/templates/public/layout.gohtml:69
msgctxt "title" msgctxt "title"
msgid "Booking" msgid "Booking"
msgstr "Reserva" msgstr "Reserva"
@ -365,8 +365,8 @@ msgctxt "input"
msgid "I have read and I accept the reservation conditions" msgid "I have read and I accept the reservation conditions"
msgstr "He leído y acepto las condiciones de reserva" msgstr "He leído y acepto las condiciones de reserva"
#: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:32 #: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:47
#: web/templates/public/layout.gohtml:109 #: web/templates/public/layout.gohtml:130
msgid "Campsite Montagut" msgid "Campsite Montagut"
msgstr "Camping Montagut" msgstr "Camping Montagut"
@ -374,28 +374,118 @@ msgstr "Camping Montagut"
msgid "Skip to main content" msgid "Skip to main content"
msgstr "Saltar al contenido principal" msgstr "Saltar al contenido principal"
#: web/templates/public/layout.gohtml:42 web/templates/public/layout.gohtml:88 #: web/templates/public/layout.gohtml:57 web/templates/public/layout.gohtml:103
#: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:6
#: web/templates/admin/campsite/index.gohtml:12 #: web/templates/admin/campsite/index.gohtml:12
#: web/templates/admin/layout.gohtml:45 web/templates/admin/layout.gohtml:79 #: web/templates/admin/layout.gohtml:45 web/templates/admin/layout.gohtml:82
msgctxt "title" msgctxt "title"
msgid "Campsites" msgid "Campsites"
msgstr "Alojamientos" msgstr "Alojamientos"
#: web/templates/public/layout.gohtml:75 #: web/templates/public/layout.gohtml:90
msgctxt "title" msgctxt "title"
msgid "Sections" msgid "Sections"
msgstr "Apartados" msgstr "Apartados"
#: web/templates/public/layout.gohtml:99 #: web/templates/public/layout.gohtml:114
msgctxt "title" msgctxt "title"
msgid "Opening" msgid "Opening"
msgstr "Apertura" msgstr "Apertura"
#: web/templates/public/layout.gohtml:106 #: web/templates/public/layout.gohtml:121
msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s" msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s"
msgstr "<abbr title=\"Número\">Nº</abbr> <abbr title=\"Registro de Turismo de Cataluña\">RTC</abbr> %s" msgstr "<abbr title=\"Número\">Nº</abbr> <abbr title=\"Registro de Turismo de Cataluña\">RTC</abbr> %s"
#: web/templates/admin/legal/form.gohtml:8
#: web/templates/admin/legal/form.gohtml:25
msgctxt "title"
msgid "Edit Legal Text"
msgstr "Edición del texto legal"
#: web/templates/admin/legal/form.gohtml:10
#: web/templates/admin/legal/form.gohtml:27
msgctxt "title"
msgid "New Legal Text"
msgstr "Nuevo texto legal"
#: web/templates/admin/legal/form.gohtml:37
msgctxt "input"
msgid "Slug"
msgstr "Álias"
#: web/templates/admin/legal/form.gohtml:46
#: 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 "Nombre"
#: web/templates/admin/legal/form.gohtml:64
msgctxt "input"
msgid "Content"
msgstr "Contenido"
#: web/templates/admin/legal/form.gohtml:84
#: 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 "Actualizar"
#: web/templates/admin/legal/form.gohtml:86
#: 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 "Añadir"
#: web/templates/admin/legal/index.gohtml:6
#: web/templates/admin/legal/index.gohtml:12
#: web/templates/admin/layout.gohtml:63
msgctxt "title"
msgid "Legal Texts"
msgstr "Textos legales"
#: web/templates/admin/legal/index.gohtml:11
msgctxt "action"
msgid "Add Legal Text"
msgstr "Añadir texto legal"
#: web/templates/admin/legal/index.gohtml:17
#: web/templates/admin/campsite/feature/index.gohtml:26
#: 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 "Nombre"
#: web/templates/admin/legal/index.gohtml:29
msgid "No legal texts added yet."
msgstr "No se ha añadido ningún texto legal todavía."
#: web/templates/admin/carousel/form.gohtml:8 #: web/templates/admin/carousel/form.gohtml:8
#: web/templates/admin/carousel/form.gohtml:25 #: web/templates/admin/carousel/form.gohtml:25
msgctxt "title" msgctxt "title"
@ -416,31 +506,6 @@ msgctxt "input"
msgid "Caption" msgid "Caption"
msgstr "Leyenda" msgstr "Leyenda"
#: 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 "Actualizar"
#: 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 "Añadir"
#: web/templates/admin/carousel/l10n.gohtml:7 #: web/templates/admin/carousel/l10n.gohtml:7
#: web/templates/admin/carousel/l10n.gohtml:14 #: web/templates/admin/carousel/l10n.gohtml:14
msgctxt "title" msgctxt "title"
@ -534,21 +599,6 @@ msgctxt "input"
msgid "Icon" msgid "Icon"
msgstr "Icono" msgstr "Icono"
#: 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 "Nombre"
#: web/templates/admin/campsite/feature/index.gohtml:6 #: web/templates/admin/campsite/feature/index.gohtml:6
#: web/templates/admin/campsite/feature/index.gohtml:12 #: web/templates/admin/campsite/feature/index.gohtml:12
msgctxt "title" msgctxt "title"
@ -560,14 +610,6 @@ msgctxt "action"
msgid "Add Feature" msgid "Add Feature"
msgstr "Añadir características" msgstr "Añadir características"
#: web/templates/admin/campsite/feature/index.gohtml:26
#: 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 "Nombre"
#: web/templates/admin/campsite/feature/index.gohtml:27 #: web/templates/admin/campsite/feature/index.gohtml:27
#: web/templates/admin/campsite/carousel/index.gohtml:27 #: web/templates/admin/campsite/carousel/index.gohtml:27
#: web/templates/admin/campsite/option/index.gohtml:26 #: web/templates/admin/campsite/option/index.gohtml:26
@ -979,7 +1021,7 @@ msgid "Integration"
msgstr "Integración" msgstr "Integración"
#: web/templates/admin/dashboard.gohtml:6 #: web/templates/admin/dashboard.gohtml:6
#: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:76 #: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:79
msgctxt "title" msgctxt "title"
msgid "Dashboard" msgid "Dashboard"
msgstr "Panel" msgstr "Panel"
@ -1162,7 +1204,7 @@ msgctxt "title"
msgid "Home Page" msgid "Home Page"
msgstr "Página de inicio" msgstr "Página de inicio"
#: web/templates/admin/layout.gohtml:65 #: web/templates/admin/layout.gohtml:68
msgctxt "action" msgctxt "action"
msgid "Logout" msgid "Logout"
msgstr "Salir" msgstr "Salir"
@ -1232,6 +1274,19 @@ msgctxt "title"
msgid "Upload Media" msgid "Upload Media"
msgstr "Subida de medio" msgstr "Subida de medio"
#: pkg/legal/admin.go:255 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:253
#: pkg/campsite/types/admin.go:447 pkg/season/l10n.go:69
#: pkg/season/admin.go:405 pkg/services/l10n.go:73 pkg/services/admin.go:266
msgid "Name can not be empty."
msgstr "No podéis dejar el nombre en blanco."
#: pkg/legal/admin.go:256 pkg/campsite/types/option.go:351
#: pkg/campsite/types/feature.go:254 pkg/campsite/types/admin.go:448
msgid "Name must have at least one letter."
msgstr "El nombre tiene que tener como mínimo una letra."
#: pkg/carousel/admin.go:285 pkg/campsite/types/carousel.go:242 #: pkg/carousel/admin.go:285 pkg/campsite/types/carousel.go:242
msgctxt "input" msgctxt "input"
msgid "Slide image" msgid "Slide image"
@ -1273,14 +1328,6 @@ msgctxt "language option"
msgid "Automatic" msgid "Automatic"
msgstr "Automático" msgstr "Automático"
#: 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:253
#: 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 podéis dejar el nombre en blanco."
#: pkg/app/user.go:250 #: pkg/app/user.go:250
msgid "Confirmation does not match password." msgid "Confirmation does not match password."
msgstr "La confirmación no se corresponde con la contraseña." msgstr "La confirmación no se corresponde con la contraseña."
@ -1293,15 +1340,10 @@ msgstr "El idioma escogido no es válido."
msgid "File must be a valid PNG or JPEG image." msgid "File must be a valid PNG or JPEG image."
msgstr "El archivo tiene que ser una imagen PNG o JPEG válida." msgstr "El archivo tiene que ser una imagen PNG o JPEG válida."
#: pkg/app/admin.go:59 #: pkg/app/admin.go:62
msgid "Access forbidden" msgid "Access forbidden"
msgstr "Acceso prohibido" msgstr "Acceso prohibido"
#: pkg/campsite/types/option.go:351 pkg/campsite/types/feature.go:254
#: pkg/campsite/types/admin.go:448
msgid "Name must have at least one letter."
msgstr "El nombre tiene que tener como mínimo una letra."
#: pkg/campsite/types/option.go:354 #: pkg/campsite/types/option.go:354
msgid "Minimum can not be empty." msgid "Minimum can not be empty."
msgstr "No podéis dejar el mínimo en blanco." msgstr "No podéis dejar el mínimo en blanco."
@ -1457,32 +1499,32 @@ msgctxt "month"
msgid "December" msgid "December"
msgstr "diciembre" msgstr "diciembre"
#: pkg/season/admin.go:405 #: pkg/season/admin.go:406
msgid "Color can not be empty." msgid "Color can not be empty."
msgstr "No podéis dejar el color en blanco." msgstr "No podéis dejar el color en blanco."
#: pkg/season/admin.go:406 #: pkg/season/admin.go:407
msgid "This color is not valid. It must be like #123abc." msgid "This color is not valid. It must be like #123abc."
msgstr "Este color no es válido. Tiene que ser parecido a #123abc." msgstr "Este color no es válido. Tiene que ser parecido a #123abc."
#: pkg/season/admin.go:506 #: pkg/season/admin.go:507
msgctxt "action" msgctxt "action"
msgid "Unset" msgid "Unset"
msgstr "Desasignar" msgstr "Desasignar"
#: pkg/season/admin.go:537 #: pkg/season/admin.go:538
msgid "Start date can not be empty." msgid "Start date can not be empty."
msgstr "No podéis dejar la fecha de inicio en blanco." msgstr "No podéis dejar la fecha de inicio en blanco."
#: pkg/season/admin.go:538 #: pkg/season/admin.go:539
msgid "Start date must be a valid date." msgid "Start date must be a valid date."
msgstr "La fecha de inicio tiene que ser una fecha válida." msgstr "La fecha de inicio tiene que ser una fecha válida."
#: pkg/season/admin.go:540 #: pkg/season/admin.go:541
msgid "End date can not be empty." msgid "End date can not be empty."
msgstr "No podéis dejar la fecha final en blanco." msgstr "No podéis dejar la fecha final en blanco."
#: pkg/season/admin.go:541 #: pkg/season/admin.go:542
msgid "End date must be a valid date." msgid "End date must be a valid date."
msgstr "La fecha final tiene que ser una fecha válida." msgstr "La fecha final tiene que ser una fecha válida."
@ -1666,10 +1708,6 @@ msgstr "%s tiene que ser como mínimo %d."
msgid "%s must be at most %d." msgid "%s must be at most %d."
msgstr "%s tiene que ser como máximo %d" msgstr "%s tiene que ser como máximo %d"
#~ msgctxt "title"
#~ msgid "Contact"
#~ msgstr "Contacto"
#~ msgctxt "title" #~ msgctxt "title"
#~ msgid "Party Details" #~ msgid "Party Details"
#~ msgstr "Datos de los visitantes" #~ msgstr "Datos de los visitantes"

220
po/fr.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: camper\n" "Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2023-12-21 21:08+0100\n" "POT-Creation-Date: 2023-12-22 02:19+0100\n"
"PO-Revision-Date: 2023-12-20 10:13+0100\n" "PO-Revision-Date: 2023-12-20 10:13+0100\n"
"Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n" "Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n"
"Language-Team: French <traduc@traduc.org>\n" "Language-Team: French <traduc@traduc.org>\n"
@ -44,7 +44,7 @@ msgstr "Le paiement a échoué"
#: web/templates/public/services.gohtml:6 #: web/templates/public/services.gohtml:6
#: web/templates/public/services.gohtml:15 #: web/templates/public/services.gohtml:15
#: web/templates/public/layout.gohtml:51 web/templates/public/layout.gohtml:79 #: web/templates/public/layout.gohtml:66 web/templates/public/layout.gohtml:94
#: web/templates/admin/services/index.gohtml:66 #: web/templates/admin/services/index.gohtml:66
msgctxt "title" msgctxt "title"
msgid "Services" msgid "Services"
@ -56,14 +56,14 @@ msgstr "Le camping propose de nombreux services différents."
#: web/templates/public/location.gohtml:6 #: web/templates/public/location.gohtml:6
#: web/templates/public/location.gohtml:12 #: web/templates/public/location.gohtml:12
#: web/templates/public/layout.gohtml:53 web/templates/public/layout.gohtml:81 #: web/templates/public/layout.gohtml:68 web/templates/public/layout.gohtml:96
#: web/templates/admin/layout.gohtml:60 #: web/templates/admin/layout.gohtml:60
msgctxt "title" msgctxt "title"
msgid "Location" msgid "Location"
msgstr "Comment nous rejoindre" msgstr "Comment nous rejoindre"
#: web/templates/public/home.gohtml:6 web/templates/public/layout.gohtml:37 #: web/templates/public/home.gohtml:6 web/templates/public/layout.gohtml:52
#: web/templates/public/layout.gohtml:77 #: web/templates/public/layout.gohtml:92
msgctxt "title" msgctxt "title"
msgid "Home" msgid "Home"
msgstr "Accueil" msgstr "Accueil"
@ -88,7 +88,7 @@ msgstr "Venez et profitez-en !"
#: web/templates/public/home.gohtml:35 #: web/templates/public/home.gohtml:35
#: web/templates/public/surroundings.gohtml:6 #: web/templates/public/surroundings.gohtml:6
#: web/templates/public/surroundings.gohtml:10 #: web/templates/public/surroundings.gohtml:10
#: web/templates/public/layout.gohtml:52 web/templates/public/layout.gohtml:80 #: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95
msgctxt "title" msgctxt "title"
msgid "Surroundings" msgid "Surroundings"
msgstr "Entourage" msgstr "Entourage"
@ -272,13 +272,13 @@ msgstr "Il y a plusieurs points où vous pouvez aller en kayak, à partir de sec
#: web/templates/public/campground.gohtml:6 #: web/templates/public/campground.gohtml:6
#: web/templates/public/campground.gohtml:11 #: web/templates/public/campground.gohtml:11
#: web/templates/public/layout.gohtml:38 web/templates/public/layout.gohtml:78 #: web/templates/public/layout.gohtml:53 web/templates/public/layout.gohtml:93
msgctxt "title" msgctxt "title"
msgid "Campground" msgid "Campground"
msgstr "Camping" msgstr "Camping"
#: web/templates/public/booking.gohtml:6 web/templates/public/booking.gohtml:11 #: web/templates/public/booking.gohtml:6 web/templates/public/booking.gohtml:11
#: web/templates/public/layout.gohtml:54 #: web/templates/public/layout.gohtml:69
msgctxt "title" msgctxt "title"
msgid "Booking" msgid "Booking"
msgstr "Reservation" msgstr "Reservation"
@ -366,8 +366,8 @@ msgctxt "input"
msgid "I have read and I accept the reservation conditions" msgid "I have read and I accept the reservation conditions"
msgstr "Jai lu et jaccepte les conditions de réservation" msgstr "Jai lu et jaccepte les conditions de réservation"
#: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:32 #: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:47
#: web/templates/public/layout.gohtml:109 #: web/templates/public/layout.gohtml:130
msgid "Campsite Montagut" msgid "Campsite Montagut"
msgstr "Camping Montagut" msgstr "Camping Montagut"
@ -375,28 +375,120 @@ msgstr "Camping Montagut"
msgid "Skip to main content" msgid "Skip to main content"
msgstr "Passer au contenu principal" msgstr "Passer au contenu principal"
#: web/templates/public/layout.gohtml:42 web/templates/public/layout.gohtml:88 #: web/templates/public/layout.gohtml:57 web/templates/public/layout.gohtml:103
#: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:6
#: web/templates/admin/campsite/index.gohtml:12 #: web/templates/admin/campsite/index.gohtml:12
#: web/templates/admin/layout.gohtml:45 web/templates/admin/layout.gohtml:79 #: web/templates/admin/layout.gohtml:45 web/templates/admin/layout.gohtml:82
msgctxt "title" msgctxt "title"
msgid "Campsites" msgid "Campsites"
msgstr "Locatifs" msgstr "Locatifs"
#: web/templates/public/layout.gohtml:75 #: web/templates/public/layout.gohtml:90
msgctxt "title" msgctxt "title"
msgid "Sections" msgid "Sections"
msgstr "Sections" msgstr "Sections"
#: web/templates/public/layout.gohtml:99 #: web/templates/public/layout.gohtml:114
msgctxt "title" msgctxt "title"
msgid "Opening" msgid "Opening"
msgstr "Ouverture" msgstr "Ouverture"
#: web/templates/public/layout.gohtml:106 #: web/templates/public/layout.gohtml:121
msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s" msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s"
msgstr "<abbr title=\"Registre du tourisme de Catalogne\"># RTC</abbr> %s" msgstr "<abbr title=\"Registre du tourisme de Catalogne\"># RTC</abbr> %s"
#: web/templates/admin/legal/form.gohtml:8
#: web/templates/admin/legal/form.gohtml:25
msgctxt "title"
msgid "Edit Legal Text"
msgstr ""
#: web/templates/admin/legal/form.gohtml:10
#: web/templates/admin/legal/form.gohtml:27
msgctxt "title"
msgid "New Legal Text"
msgstr ""
#: web/templates/admin/legal/form.gohtml:37
msgctxt "input"
msgid "Slug"
msgstr ""
#: web/templates/admin/legal/form.gohtml:46
#: 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/legal/form.gohtml:64
#, fuzzy
msgctxt "input"
msgid "Content"
msgstr "Contact"
#: web/templates/admin/legal/form.gohtml:84
#: 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 "Mettre à jour"
#: web/templates/admin/legal/form.gohtml:86
#: 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 "Ajouter"
#: web/templates/admin/legal/index.gohtml:6
#: web/templates/admin/legal/index.gohtml:12
#: web/templates/admin/layout.gohtml:63
msgctxt "title"
msgid "Legal Texts"
msgstr ""
#: web/templates/admin/legal/index.gohtml:11
msgctxt "action"
msgid "Add Legal Text"
msgstr ""
#: web/templates/admin/legal/index.gohtml:17
#: web/templates/admin/campsite/feature/index.gohtml:26
#: 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/legal/index.gohtml:29
#, fuzzy
msgid "No legal texts added yet."
msgstr "Aucune diapositive na encore été ajoutée."
#: web/templates/admin/carousel/form.gohtml:8 #: web/templates/admin/carousel/form.gohtml:8
#: web/templates/admin/carousel/form.gohtml:25 #: web/templates/admin/carousel/form.gohtml:25
msgctxt "title" msgctxt "title"
@ -417,31 +509,6 @@ msgctxt "input"
msgid "Caption" msgid "Caption"
msgstr "Légende" msgstr "Légende"
#: 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 "Mettre à jour"
#: 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 "Ajouter"
#: web/templates/admin/carousel/l10n.gohtml:7 #: web/templates/admin/carousel/l10n.gohtml:7
#: web/templates/admin/carousel/l10n.gohtml:14 #: web/templates/admin/carousel/l10n.gohtml:14
msgctxt "title" msgctxt "title"
@ -535,21 +602,6 @@ msgctxt "input"
msgid "Icon" msgid "Icon"
msgstr "Icône" msgstr "Icône"
#: 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:6
#: web/templates/admin/campsite/feature/index.gohtml:12 #: web/templates/admin/campsite/feature/index.gohtml:12
msgctxt "title" msgctxt "title"
@ -561,14 +613,6 @@ msgctxt "action"
msgid "Add Feature" msgid "Add Feature"
msgstr "Ajouter une fonctionnalité" msgstr "Ajouter une fonctionnalité"
#: web/templates/admin/campsite/feature/index.gohtml:26
#: 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:27 #: web/templates/admin/campsite/feature/index.gohtml:27
#: web/templates/admin/campsite/carousel/index.gohtml:27 #: web/templates/admin/campsite/carousel/index.gohtml:27
#: web/templates/admin/campsite/option/index.gohtml:26 #: web/templates/admin/campsite/option/index.gohtml:26
@ -980,7 +1024,7 @@ msgid "Integration"
msgstr "Intégration" msgstr "Intégration"
#: web/templates/admin/dashboard.gohtml:6 #: web/templates/admin/dashboard.gohtml:6
#: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:76 #: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:79
msgctxt "title" msgctxt "title"
msgid "Dashboard" msgid "Dashboard"
msgstr "Tableau de bord" msgstr "Tableau de bord"
@ -1163,7 +1207,7 @@ msgctxt "title"
msgid "Home Page" msgid "Home Page"
msgstr "Page d'accueil" msgstr "Page d'accueil"
#: web/templates/admin/layout.gohtml:65 #: web/templates/admin/layout.gohtml:68
msgctxt "action" msgctxt "action"
msgid "Logout" msgid "Logout"
msgstr "Déconnexion" msgstr "Déconnexion"
@ -1233,6 +1277,19 @@ msgctxt "title"
msgid "Upload Media" msgid "Upload Media"
msgstr "Envoyer un fichier" msgstr "Envoyer un fichier"
#: pkg/legal/admin.go:255 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:253
#: pkg/campsite/types/admin.go:447 pkg/season/l10n.go:69
#: pkg/season/admin.go:405 pkg/services/l10n.go:73 pkg/services/admin.go:266
msgid "Name can not be empty."
msgstr "Le nom ne peut pas être laissé vide."
#: pkg/legal/admin.go:256 pkg/campsite/types/option.go:351
#: pkg/campsite/types/feature.go:254 pkg/campsite/types/admin.go:448
msgid "Name must have at least one letter."
msgstr "Le nom doit comporter au moins une lettre."
#: pkg/carousel/admin.go:285 pkg/campsite/types/carousel.go:242 #: pkg/carousel/admin.go:285 pkg/campsite/types/carousel.go:242
msgctxt "input" msgctxt "input"
msgid "Slide image" msgid "Slide image"
@ -1274,14 +1331,6 @@ msgctxt "language option"
msgid "Automatic" msgid "Automatic"
msgstr "Automatique" msgstr "Automatique"
#: 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:253
#: 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 "Le nom ne peut pas être laissé vide."
#: pkg/app/user.go:250 #: pkg/app/user.go:250
msgid "Confirmation does not match password." msgid "Confirmation does not match password."
msgstr "La confirmation ne correspond pas au mot de passe." msgstr "La confirmation ne correspond pas au mot de passe."
@ -1294,15 +1343,10 @@ msgstr "La langue sélectionnée nest pas valide."
msgid "File must be a valid PNG or JPEG image." msgid "File must be a valid PNG or JPEG image."
msgstr "Le fichier doit être une image PNG ou JPEG valide." msgstr "Le fichier doit être une image PNG ou JPEG valide."
#: pkg/app/admin.go:59 #: pkg/app/admin.go:62
msgid "Access forbidden" msgid "Access forbidden"
msgstr "Accès interdit" msgstr "Accès interdit"
#: pkg/campsite/types/option.go:351 pkg/campsite/types/feature.go:254
#: pkg/campsite/types/admin.go:448
msgid "Name must have at least one letter."
msgstr "Le nom doit comporter au moins une lettre."
#: pkg/campsite/types/option.go:354 #: pkg/campsite/types/option.go:354
msgid "Minimum can not be empty." msgid "Minimum can not be empty."
msgstr "Le minimum ne peut pas être vide." msgstr "Le minimum ne peut pas être vide."
@ -1458,32 +1502,32 @@ msgctxt "month"
msgid "December" msgid "December"
msgstr "Décembre" msgstr "Décembre"
#: pkg/season/admin.go:405 #: pkg/season/admin.go:406
msgid "Color can not be empty." msgid "Color can not be empty."
msgstr "La couleur ne peut pas être vide." msgstr "La couleur ne peut pas être vide."
#: pkg/season/admin.go:406 #: pkg/season/admin.go:407
msgid "This color is not valid. It must be like #123abc." msgid "This color is not valid. It must be like #123abc."
msgstr "Cette couleur nest pas valide. Il doit être comme #123abc." msgstr "Cette couleur nest pas valide. Il doit être comme #123abc."
#: pkg/season/admin.go:506 #: pkg/season/admin.go:507
msgctxt "action" msgctxt "action"
msgid "Unset" msgid "Unset"
msgstr "Unset" msgstr "Unset"
#: pkg/season/admin.go:537 #: pkg/season/admin.go:538
msgid "Start date can not be empty." msgid "Start date can not be empty."
msgstr "La date de début ne peut pas être vide." msgstr "La date de début ne peut pas être vide."
#: pkg/season/admin.go:538 #: pkg/season/admin.go:539
msgid "Start date must be a valid date." msgid "Start date must be a valid date."
msgstr "La date de début doit être une date valide." msgstr "La date de début doit être une date valide."
#: pkg/season/admin.go:540 #: pkg/season/admin.go:541
msgid "End date can not be empty." msgid "End date can not be empty."
msgstr "La date de fin ne peut pas être vide." msgstr "La date de fin ne peut pas être vide."
#: pkg/season/admin.go:541 #: pkg/season/admin.go:542
msgid "End date must be a valid date." msgid "End date must be a valid date."
msgstr "La date de fin doit être une date valide." msgstr "La date de fin doit être une date valide."
@ -1666,7 +1710,3 @@ msgstr "%s doit être %d ou plus."
#, c-format #, c-format
msgid "%s must be at most %d." msgid "%s must be at most %d."
msgstr "%s doit être tout au plus %d." msgstr "%s doit être tout au plus %d."
#~ msgctxt "title"
#~ msgid "Contact"
#~ msgstr "Contact"

7
revert/legal_text.sql Normal file
View File

@ -0,0 +1,7 @@
-- Revert camper:legal_text from pg
begin;
drop table if exists camper.legal_text;
commit;

View File

@ -0,0 +1,7 @@
-- Revert camper:legal_text_i18n from pg
begin;
drop table if exists camper.legal_text_i18n;
commit;

View File

@ -0,0 +1,7 @@
-- Revert camper:translate_legal_text from pg
begin;
drop function if exists camper.translate_legal_text(integer, text, text, text, text);
commit;

View File

@ -128,3 +128,6 @@ location [schema_camper roles company user_profile] 2023-12-21T17:01:28Z jordi f
location_i18n [roles schema_camper location language] 2023-12-21T17:32:50Z jordi fita mas <jordi@tandem.blog> # Add relation for location internationalization location_i18n [roles schema_camper location language] 2023-12-21T17:32:50Z jordi fita mas <jordi@tandem.blog> # Add relation for location internationalization
translate_location [roles schema_camper location_i18n] 2023-12-21T17:37:47Z jordi fita mas <jordi@tandem.blog> # Add function to translate location translate_location [roles schema_camper location_i18n] 2023-12-21T17:37:47Z jordi fita mas <jordi@tandem.blog> # Add function to translate location
setup_location [roles schema_camper location] 2023-12-21T19:26:53Z jordi fita mas <jordi@tandem.blog> # Add function to setup location settings setup_location [roles schema_camper location] 2023-12-21T19:26:53Z jordi fita mas <jordi@tandem.blog> # Add function to setup location settings
legal_text [roles schema_camper company user_profile] 2023-12-21T23:29:28Z jordi fita mas <jordi@tandem.blog> # Add relation for legal documents
legal_text_i18n [roles schema_camper legal_text language] 2023-12-21T23:51:09Z jordi fita mas <jordi@tandem.blog> # Add relation for legal text internationalization
translate_legal_text [roles schema_camper legal_text_i18n] 2023-12-22T00:10:05Z jordi fita mas <jordi@tandem.blog> # Add function to translate legal texts

198
test/legal_text.sql Normal file
View File

@ -0,0 +1,198 @@
-- Test legal_text
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(41);
set search_path to camper, public;
select has_table('legal_text');
select has_pk('legal_text');
select col_is_pk('legal_text', array['company_id', 'slug']);
select table_privs_are('legal_text', 'guest', array['SELECT']);
select table_privs_are('legal_text', 'employee', array['SELECT']);
select table_privs_are('legal_text', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']);
select table_privs_are('legal_text', 'authenticator', array[]::text[]);
select has_column('legal_text', 'slug');
select col_type_is('legal_text', 'slug', 'text');
select col_not_null('legal_text', 'slug');
select col_hasnt_default('legal_text', 'slug');
select has_column('legal_text', 'company_id');
select col_is_fk('legal_text', 'company_id');
select fk_ok('legal_text', 'company_id', 'company', 'company_id');
select col_type_is('legal_text', 'company_id', 'integer');
select col_not_null('legal_text', 'company_id');
select col_hasnt_default('legal_text', 'company_id');
select has_column('legal_text', 'name');
select col_type_is('legal_text', 'name', 'text');
select col_not_null('legal_text', 'name');
select col_hasnt_default('legal_text', 'name');
select has_column('legal_text', 'content');
select col_type_is('legal_text', 'content', 'xml');
select col_not_null('legal_text', 'content');
select col_hasnt_default('legal_text', 'content');
set client_min_messages to warning;
truncate legal_text cascade;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
truncate auth."user" cascade;
reset client_min_messages;
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 'ES', 'EUR', 'ca')
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 'FR', 'USD', 'ca')
;
insert into company_user (company_id, user_id, role)
values (2, 1, 'admin')
, (4, 5, 'admin')
;
insert into company_host (company_id, host)
values (2, 'co2')
, (4, 'co4')
;
insert into legal_text (company_id, slug, name, content)
values (2, 'reservation', 'Reservation', '')
, (4, 'cookies', 'Cookies', '')
;
prepare legal_data as
select company_id, slug
from legal_text
order by company_id, slug;
set role guest;
select bag_eq(
'legal_data',
$$ values (2, 'reservation')
, (4, 'cookies')
$$,
'Everyone should be able to list all legal texts across all companies'
);
reset role;
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2');
select lives_ok(
$$ insert into legal_text(company_id, slug, name, content) values (2, 'tos', 'Terms of Service', '') $$,
'Admin from company 2 should be able to insert a new legal text to that company.'
);
select bag_eq(
'legal_data',
$$ values (2, 'tos')
, (2, 'reservation')
, (4, 'cookies')
$$,
'The new row should have been added'
);
select lives_ok(
$$ update legal_text set slug = 'terms' where company_id = 2 and slug = 'tos' $$,
'Admin from company 2 should be able to update legal text of that company.'
);
select bag_eq(
'legal_data',
$$ values (2, 'terms')
, (2, 'reservation')
, (4, 'cookies')
$$,
'The row should have been updated.'
);
select lives_ok(
$$ delete from legal_text where company_id = 2 and slug = 'terms' $$,
'Admin from company 2 should be able to delete legal text from that company.'
);
select bag_eq(
'legal_data',
$$ values (2, 'reservation')
, (4, 'cookies')
$$,
'The row should have been deleted.'
);
select throws_ok(
$$ insert into legal_text (company_id, slug, name, content) values (4, 'terms', 'Terms', '') $$,
'42501', 'new row violates row-level security policy for table "legal_text"',
'Admin from company 2 should NOT be able to insert new legal texts to company 4.'
);
select lives_ok(
$$ update legal_text set slug = 'nope' where company_id = 4 $$,
'Admin from company 2 should not be able to update new legal texts of company 4, but no error if company_id is not changed.'
);
select bag_eq(
'legal_data',
$$ values (2, 'reservation')
, (4, 'cookies')
$$,
'No row should have been changed.'
);
select throws_ok(
$$ update legal_text set company_id = 4 where company_id = 2 $$,
'42501', 'new row violates row-level security policy for table "legal_text"',
'Admin from company 2 should NOT be able to move legal texts to company 4'
);
select lives_ok(
$$ delete from legal_text where company_id = 4 $$,
'Admin from company 2 should NOT be able to delete legal texts from company 4, but not error is thrown'
);
select bag_eq(
'legal_data',
$$ values (2, 'reservation')
, (4, 'cookies')
$$,
'No row should have been changed'
);
select throws_ok(
$$ insert into legal_text (company_id, slug, name, content) values (2, 'ToS', 'Term of Services', '') $$,
'23514', 'new row for relation "legal_text" violates check constraint "valid_slug"',
'Should not be able to insert legal texts with a invalid slug.'
);
select throws_ok(
$$ insert into legal_text (company_id, slug, name, content) values (2, 'terms of service', 'Term of Services', '') $$,
'23514', 'new row for relation "legal_text" violates check constraint "valid_slug"',
'Should not be able to insert legal texts with a spaces in the slug.'
);
select throws_ok(
$$ insert into legal_text (company_id, slug, name, content) values (2, 'tos', ' ', '') $$,
'23514', 'new row for relation "legal_text" violates check constraint "name_not_empty"',
'Should not be able to insert legal texts with a blank name.'
);
reset role;
select *
from finish();
rollback;

54
test/legal_text_i18n.sql Normal file
View File

@ -0,0 +1,54 @@
-- Test legal_text_i18n
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(31);
set search_path to camper, public;
select has_table('legal_text_i18n');
select has_pk('legal_text_i18n');
select col_is_pk('legal_text_i18n', array['company_id', 'slug', 'lang_tag']);
select col_is_fk('legal_text_i18n', array['company_id', 'slug']);
select fk_ok('legal_text_i18n', array['company_id', 'slug'], 'legal_text', array['company_id', 'slug']);
select table_privs_are('legal_text_i18n', 'guest', array['SELECT']);
select table_privs_are('legal_text_i18n', 'employee', array['SELECT']);
select table_privs_are('legal_text_i18n', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']);
select table_privs_are('legal_text_i18n', 'authenticator', array[]::text[]);
select has_column('legal_text_i18n', 'company_id');
select col_type_is('legal_text_i18n', 'company_id', 'integer');
select col_not_null('legal_text_i18n', 'company_id');
select col_hasnt_default('legal_text_i18n', 'company_id');
select has_column('legal_text_i18n', 'slug');
select col_type_is('legal_text_i18n', 'slug', 'text');
select col_not_null('legal_text_i18n', 'slug');
select col_hasnt_default('legal_text_i18n', 'slug');
select has_column('legal_text_i18n', 'lang_tag');
select col_is_fk('legal_text_i18n', 'lang_tag');
select fk_ok('legal_text_i18n', 'lang_tag', 'language', 'lang_tag');
select col_type_is('legal_text_i18n', 'lang_tag', 'text');
select col_not_null('legal_text_i18n', 'lang_tag');
select col_hasnt_default('legal_text_i18n', 'lang_tag');
select has_column('legal_text_i18n', 'name');
select col_type_is('legal_text_i18n', 'name', 'text');
select col_not_null('legal_text_i18n', 'name');
select col_hasnt_default('legal_text_i18n', 'name');
select has_column('legal_text_i18n', 'content');
select col_type_is('legal_text_i18n', 'content', 'xml');
select col_not_null('legal_text_i18n', 'content');
select col_hasnt_default('legal_text_i18n', 'content');
select *
from finish();
rollback;

View File

@ -0,0 +1,72 @@
-- Test translate_legal_text
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(13);
set search_path to camper, public;
select has_function('camper', 'translate_legal_text', array['integer', 'text', 'text', 'text', 'text']);
select function_lang_is('camper', 'translate_legal_text', array['integer', 'text', 'text', 'text', 'text'], 'sql');
select function_returns('camper', 'translate_legal_text', array['integer', 'text', 'text', 'text', 'text'], 'void');
select isnt_definer('camper', 'translate_legal_text', array['integer', 'text', 'text', 'text', 'text']);
select volatility_is('camper', 'translate_legal_text', array['integer', 'text', 'text', 'text', 'text'], 'volatile');
select function_privs_are('camper', 'translate_legal_text', array['integer', 'text', 'text', 'text', 'text'], 'guest', array[]::text[]);
select function_privs_are('camper', 'translate_legal_text', array['integer', 'text', 'text', 'text', 'text'], 'employee', array[]::text[]);
select function_privs_are('camper', 'translate_legal_text', array['integer', 'text', 'text', 'text', 'text'], 'admin', array['EXECUTE']);
select function_privs_are('camper', 'translate_legal_text', array['integer', 'text', 'text', 'text', 'text'], 'authenticator', array[]::text[]);
set client_min_messages to warning;
truncate legal_text_i18n cascade;
truncate legal_text cascade;
truncate company cascade;
reset client_min_messages;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 'ES', 'EUR', 'ca')
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 'FR', 'USD', 'ca')
;
insert into legal_text (company_id, slug, name, content)
values (2, 'tos', 'Terms of Service', '<p>Go away</p>')
, (4, 'cookies', 'Cookies', '<p>Yummy</p>')
;
insert into legal_text_i18n (company_id, slug, lang_tag, name, content)
values (2, 'tos', 'ca', '<p>Termes i condicions</p>', '<p>Uh?</p>')
, (4, 'cookies', 'ca', '<p>Galetes</p>', '<p>Uh?</p>')
;
select lives_ok(
$$ select translate_legal_text(2, 'tos', 'es', 'Términos', '<p>Adiós</p>') $$,
'Should be able to translate the legal text of the first company to a new language'
);
select lives_ok(
$$ select translate_legal_text(2, 'tos', 'ca', 'Termes', '<p>Adéu</p>') $$,
'Should be able to overwrite a legal texts translation'
);
select lives_ok(
$$ select translate_legal_text(4, 'cookies', 'ca', null, null) $$,
'Should be able to “translate” a legal_text to empty strings'
);
select bag_eq(
$$ select company_id, slug, lang_tag, name, content::text from legal_text_i18n $$,
$$ values (2, 'tos', 'ca', 'Termes', '<p>Adéu</p>')
, (2, 'tos', 'es', 'Términos', '<p>Adiós</p>')
, (4, 'cookies', 'ca', '', '')
$$,
'Should have translated all legal texts'
);
select *
from finish();
rollback;

18
verify/legal_text.sql Normal file
View File

@ -0,0 +1,18 @@
-- Verify camper:legal_text on pg
begin;
select company_id
, slug
, name
, content
from camper.legal_text
where false;
select 1 / count(*) from pg_class where oid = 'camper.legal_text'::regclass and relrowsecurity;
select 1 / count(*) from pg_policy where polname = 'guest_ok' and polrelid = 'camper.legal_text'::regclass;
select 1 / count(*) from pg_policy where polname = 'insert_to_company' and polrelid = 'camper.legal_text'::regclass;
select 1 / count(*) from pg_policy where polname = 'update_company' and polrelid = 'camper.legal_text'::regclass;
select 1 / count(*) from pg_policy where polname = 'delete_from_company' and polrelid = 'camper.legal_text'::regclass;
rollback;

View File

@ -0,0 +1,13 @@
-- Verify camper:legal_text_i18n on pg
begin;
select company_id
, slug
, lang_tag
, name
, content
from camper.legal_text_i18n
where false;
rollback;

View File

@ -0,0 +1,7 @@
-- Verify camper:translate_legal_text on pg
begin;
select has_function_privilege('camper.translate_legal_text(integer, text, text, text, text)', 'execute');
rollback;

View File

@ -59,6 +59,9 @@
<li> <li>
<a href="/admin/location">{{( pgettext "Location" "title" )}}</a> <a href="/admin/location">{{( pgettext "Location" "title" )}}</a>
</li> </li>
<li>
<a href="/admin/legal">{{( pgettext "Legal Texts" "title" )}}</a>
</li>
{{- end }} {{- end }}
<li class="icon_logout"> <li class="icon_logout">
<button data-hx-delete="/me/session" data-hx-headers='{ {{ CSRFHeader }} }' <button data-hx-delete="/me/session" data-hx-headers='{ {{ CSRFHeader }} }'

View File

@ -0,0 +1,91 @@
<!--
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
SPDX-License-Identifier: AGPL-3.0-only
-->
{{ define "title" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/legal.legalForm*/ -}}
{{ if .URL }}
{{( pgettext "Edit Legal Text" "title" )}}
{{ else }}
{{( pgettext "New Legal Text" "title" )}}
{{ end }}
{{- end }}
{{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/legal.legalForm*/ -}}
<form
{{ if .URL }}
data-hx-put="{{ .URL }}"
{{ else }}
action="/admin/legal" method="post"
{{ end }}
>
<h2>
{{ if .URL }}
{{( pgettext "Edit Legal Text" "title" )}}
{{ else }}
{{( pgettext "New Legal Text" "title" )}}
{{ end }}
</h2>
{{ CSRFInput }}
<fieldset x-data="{ lang: 'ca' }">
{{ if .URL }}
<input type="hidden" name="{{ .Slug.Name }}" value="{{ .Slug.Val }}">
{{ else }}
{{ with .Slug -}}
<label>
{{( pgettext "Slug" "input")}}<br>
<input type="text" name="{{ .Name }}" value="{{ .Val }}"
required {{ template "error-attrs" . }}><br>
</label>
{{ template "error-message" . }}
{{- end }}
{{ end }}
{{ with .Name -}}
<fieldset>
<legend>{{( pgettext "Name" "input" )}}</legend>
<div class="lang-selector" role="toolbar">
{{ range $lang, $input := . -}}
<button :aria-pressed="lang === '{{ $lang }}'"
@click.prevent="lang = '{{ $lang }}'">{{ $lang }}</button>
{{- end }}
</div>
{{ range $lang, $input := . -}}
<label x-cloak x-show="lang === '{{ $lang }}'"><span>{{ $lang }}</span><br>
<input type="text" name="{{ $input.Name }}" value="{{ $input.Val }}"
{{ template "error-attrs" . }}><br>
</label>
{{- end }}
{{ template "error-message" . }}
</fieldset>
{{- end }}
{{ with .Content -}}
<fieldset>
<legend>{{( pgettext "Content" "input" )}}</legend>
<div class="lang-selector" role="toolbar">
{{ range $lang, $input := . -}}
<button :aria-pressed="lang === '{{ $lang }}'"
@click.prevent="lang = '{{ $lang }}'">{{ $lang }}</button>
{{- end }}
</div>
{{ range $lang, $input := . -}}
<label x-cloak x-show="lang === '{{ $lang }}'"><span>{{ $lang }}</span><br>
<textarea class="html"
name="{{ $input.Name }}" {{ template "error-attrs" . }}>{{ $input.Val }}</textarea><br>
</label>
{{- end }}
{{ template "error-message" . }}
</fieldset>
{{- end }}
</fieldset>
<footer>
<button type="submit">
{{ if .URL }}
{{( pgettext "Update" "action" )}}
{{ else }}
{{( pgettext "Add" "action" )}}
{{ end }}
</button>
</footer>
</form>
{{- end }}

View File

@ -0,0 +1,31 @@
<!--
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
SPDX-License-Identifier: AGPL-3.0-only
-->
{{ define "title" -}}
{{( pgettext "Legal Texts" "title" )}}
{{- end }}
{{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/legal.legalIndex*/ -}}
<a href="/admin/legal/new">{{( pgettext "Add Legal Text" "action" )}}</a>
<h2>{{( pgettext "Legal Texts" "title" )}}</h2>
{{ if .Texts -}}
<table>
<thead>
<tr>
<th scope="col">{{( pgettext "Name" "header" )}}</th>
</tr>
</thead>
<tbody>
{{ range $text := .Texts -}}
<tr>
<td><a href="{{ .URL }}">{{ .Name }}</a></td>
</tr>
{{- end }}
</tbody>
</table>
{{ else -}}
<p>{{( gettext "No legal texts added yet." )}}</p>
{{- end }}
{{- end }}

View File

@ -0,0 +1,17 @@
<!--
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
SPDX-License-Identifier: AGPL-3.0-only
-->
{{ define "title" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/legal.legalPage*/ -}}
{{ .Name }}
{{- end }}
{{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/legal.legalPage*/ -}}
<h2>{{ .Name }}</h2>
<div class="legal-page">
{{ .Content }}
</div>
{{- end }}