Replace use of L10NInput with I18nInput for campsite

This commit is contained in:
jordi fita mas 2024-01-10 21:52:49 +01:00
parent 3f46ea3a9a
commit f28664acce
22 changed files with 657 additions and 1213 deletions

View File

@ -105,23 +105,7 @@ func (h *AdminHandler) typeHandler(user *auth.User, company *auth.Company, conn
case "slides":
h.carouselHandler(user, company, conn, f.Slug).ServeHTTP(w, r)
default:
loc, ok := h.locales.Get(head)
if !ok {
http.NotFound(w, r)
return
}
l10n := newTypeL10nForm(f, loc)
if err := l10n.FillFromDatabase(r.Context(), conn); err != nil {
panic(err)
}
switch r.Method {
case http.MethodGet:
l10n.MustRender(w, r, user, company)
case http.MethodPut:
editTypeL10n(w, r, user, company, conn, l10n)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
}
http.NotFound(w, r)
}
})
}
@ -138,16 +122,9 @@ func serveTypeIndex(w http.ResponseWriter, r *http.Request, user *auth.User, com
}
type typeEntry struct {
Slug string
Name string
Active bool
Translations []*translation
}
type translation struct {
Language string
Endonym string
Missing bool
Slug string
Name string
Active bool
}
func collectTypeEntries(ctx context.Context, company *auth.Company, conn *database.Conn) ([]*typeEntry, error) {
@ -155,19 +132,10 @@ func collectTypeEntries(ctx context.Context, company *auth.Company, conn *databa
select campsite_type.slug
, campsite_type.name
, campsite_type.active
, array_agg((lang_tag, endonym, not exists (select 1 from campsite_type_i18n as i18n where i18n.campsite_type_id = campsite_type.campsite_type_id and i18n.lang_tag = language.lang_tag)) order by endonym)
from campsite_type
join company using (company_id)
, language
where lang_tag <> default_lang_tag
and language.selectable
and campsite_type.company_id = $1
group by campsite_type.slug
, campsite_type.name
, campsite_type.position
, campsite_type.active
where campsite_type.company_id = $1
order by position, name
`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, company.ID)
`, company.ID)
if err != nil {
return nil, err
}
@ -176,17 +144,9 @@ func collectTypeEntries(ctx context.Context, company *auth.Company, conn *databa
var types []*typeEntry
for rows.Next() {
entry := &typeEntry{}
var translations database.RecordArray
if err = rows.Scan(&entry.Slug, &entry.Name, &entry.Active, &translations); err != nil {
if err = rows.Scan(&entry.Slug, &entry.Name, &entry.Active); err != nil {
return nil, err
}
for _, el := range translations.Elements {
entry.Translations = append(entry.Translations, &translation{
el.Fields[0].Get().(string),
el.Fields[1].Get().(string),
el.Fields[2].Get().(bool),
})
}
types = append(types, entry)
}
@ -207,14 +167,30 @@ func addType(w http.ResponseWriter, r *http.Request, user *auth.User, company *a
panic(err)
}
processTypeForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error {
slug, err := tx.AddCampsiteType(ctx, company.ID, f.Media.Int(), f.Name.Val, f.Spiel.Val, f.Info.Val, f.Facilities.Val, f.Description.Val, f.MaxCampers.Int(), f.DogsAllowed.Checked)
slug, err := tx.AddCampsiteType(ctx, company.ID, f.Media.Int(), f.Name[f.DefaultLang].Val, f.Spiel[f.DefaultLang].Val, f.Info[f.DefaultLang].Val, f.Facilities[f.DefaultLang].Val, f.Description[f.DefaultLang].Val, f.MaxCampers.Int(), f.DogsAllowed.Checked)
if err != nil {
return err
}
if err := translateTypes(ctx, tx, company, f); err != nil {
return err
}
return setTypePrices(ctx, tx, slug, f.Prices)
})
}
func translateTypes(ctx context.Context, tx *database.Tx, company *auth.Company, f *typeForm) error {
for lang := range company.Locales {
l := lang.String()
if l == f.DefaultLang {
continue
}
if err := tx.TranslateCampsiteType(ctx, f.Slug, lang, f.Name[l].Val, f.Spiel[l].Val, f.Info[l].Val, f.Facilities[l].Val, f.Description[l].Val); err != nil {
return err
}
}
return nil
}
func setTypePrices(ctx context.Context, tx *database.Tx, slug string, prices map[int]*typePriceForm) error {
for seasonID, p := range prices {
if err := tx.SetCampsiteTypeCost(ctx, slug, seasonID, p.MinNights.Int(), p.PricePerNight.Val); err != nil {
@ -226,7 +202,10 @@ func setTypePrices(ctx context.Context, tx *database.Tx, slug string, prices map
func editType(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *typeForm) {
processTypeForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error {
if _, err := tx.EditCampsiteType(ctx, f.Slug, f.Media.Int(), f.Name.Val, f.Spiel.Val, f.Info.Val, f.Facilities.Val, f.Description.Val, f.MaxCampers.Int(), f.DogsAllowed.Checked, f.Active.Checked); err != nil {
if _, err := tx.EditCampsiteType(ctx, f.Slug, f.Media.Int(), f.Name[f.DefaultLang].Val, f.Spiel[f.DefaultLang].Val, f.Info[f.DefaultLang].Val, f.Facilities[f.DefaultLang].Val, f.Description[f.DefaultLang].Val, f.MaxCampers.Int(), f.DogsAllowed.Checked, f.Active.Checked); err != nil {
return err
}
if err := translateTypes(ctx, tx, company, f); err != nil {
return err
}
return setTypePrices(ctx, tx, f.Slug, f.Prices)
@ -291,16 +270,17 @@ func processTypeForm(w http.ResponseWriter, r *http.Request, user *auth.User, co
}
type typeForm struct {
DefaultLang string
Slug string
Active *form.Checkbox
Media *form.Media
Name *form.Input
Name form.I18nInput
MaxCampers *form.Input
DogsAllowed *form.Checkbox
Spiel *form.Input
Info *form.Input
Facilities *form.Input
Description *form.Input
Spiel form.I18nInput
Info form.I18nInput
Facilities form.I18nInput
Description form.I18nInput
Prices map[int]*typePriceForm
}
@ -312,6 +292,7 @@ type typePriceForm struct {
func newTypeForm(ctx context.Context, company *auth.Company, conn *database.Conn) (*typeForm, error) {
f := &typeForm{
DefaultLang: company.DefaultLanguage.String(),
Active: &form.Checkbox{
Name: "active",
Checked: true,
@ -323,27 +304,17 @@ func newTypeForm(ctx context.Context, company *auth.Company, conn *database.Conn
Label: locale.PgettextNoop("Cover image", "input"),
Prompt: locale.PgettextNoop("Set campsite type cover", "action"),
},
Name: &form.Input{
Name: "name",
},
Name: form.NewI18nInput(company.Locales, "name"),
MaxCampers: &form.Input{
Name: "max_campers",
},
DogsAllowed: &form.Checkbox{
Name: "dogs_allowed",
},
Spiel: &form.Input{
Name: "spiel",
},
Info: &form.Input{
Name: "info",
},
Facilities: &form.Input{
Name: "facilities",
},
Description: &form.Input{
Name: "description",
},
Spiel: form.NewI18nInput(company.Locales, "spiel"),
Info: form.NewI18nInput(company.Locales, "info"),
Facilities: form.NewI18nInput(company.Locales, "facilities"),
Description: form.NewI18nInput(company.Locales, "description"),
}
rows, err := conn.Query(ctx, "select season_id, name from season where active and company_id = $1", company.ID)
@ -377,20 +348,55 @@ func newTypeForm(ctx context.Context, company *auth.Company, conn *database.Conn
func (f *typeForm) FillFromDatabase(ctx context.Context, conn *database.Conn, slug string) error {
f.Slug = slug
var name database.RecordArray
var spiel database.RecordArray
var info database.RecordArray
var facilities database.RecordArray
var description database.RecordArray
row := conn.QueryRow(ctx, `
select name
, spiel::text
, info::text
, facilities::text
, description::text
select campsite_type.name
, campsite_type.spiel::text
, campsite_type.info::text
, campsite_type.facilities::text
, campsite_type.description::text
, media_id::text
, max_campers::text
, dogs_allowed
, active
, array_agg((lang_tag, i18n.name))
, array_agg((lang_tag, i18n.spiel::text))
, array_agg((lang_tag, i18n.info::text))
, array_agg((lang_tag, i18n.facilities::text))
, array_agg((lang_tag, i18n.description::text))
from campsite_type
left join campsite_type_i18n as i18n using (campsite_type_id)
where slug = $1
`, slug)
if err := row.Scan(&f.Name.Val, &f.Spiel.Val, &f.Info.Val, &f.Facilities.Val, &f.Description.Val, &f.Media.Val, &f.MaxCampers.Val, &f.DogsAllowed.Checked, &f.Active.Checked); err != nil {
group by campsite_type.name
, campsite_type.spiel::text
, campsite_type.info::text
, campsite_type.facilities::text
, campsite_type.description::text
, media_id::text
, max_campers::text
, dogs_allowed
, active
`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, slug)
if err := row.Scan(&f.Name[f.DefaultLang].Val, &f.Spiel[f.DefaultLang].Val, &f.Info[f.DefaultLang].Val, &f.Facilities[f.DefaultLang].Val, &f.Description[f.DefaultLang].Val, &f.Media.Val, &f.MaxCampers.Val, &f.DogsAllowed.Checked, &f.Active.Checked, &name, &spiel, &info, &facilities, &description); err != nil {
return err
}
if err := f.Name.FillArray(name); err != nil {
return err
}
if err := f.Spiel.FillArray(spiel); err != nil {
return err
}
if err := f.Info.FillArray(info); err != nil {
return err
}
if err := f.Facilities.FillArray(facilities); err != nil {
return err
}
if err := f.Description.FillArray(description); err != nil {
return err
}
@ -444,8 +450,8 @@ func (f *typeForm) Parse(r *http.Request) error {
func (f *typeForm) Valid(ctx context.Context, conn *database.Conn, l *locale.Locale) (bool, error) {
v := form.NewValidator(l)
if v.CheckRequired(f.Name, l.GettextNoop("Name can not be empty.")) {
v.CheckMinLength(f.Name, 1, l.GettextNoop("Name must have at least one letter."))
if v.CheckRequired(f.Name[f.DefaultLang], l.GettextNoop("Name can not be empty.")) {
v.CheckMinLength(f.Name[f.DefaultLang], 1, l.GettextNoop("Name must have at least one letter."))
}
if v.CheckRequired(f.Media.Input, l.GettextNoop("Cover image can not be empty.")) {
if _, err := v.CheckImageMedia(ctx, conn, f.Media.Input, l.GettextNoop("Cover image must be an image media type.")); err != nil {

View File

@ -39,7 +39,7 @@ func (h *AdminHandler) carouselHandler(user *auth.User, company *auth.Company, c
case "new":
switch r.Method {
case http.MethodGet:
f := newSlideForm(typeSlug)
f := newSlideForm(company, typeSlug)
f.MustRender(w, r, user, company)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet)
@ -57,7 +57,7 @@ func (h *AdminHandler) carouselHandler(user *auth.User, company *auth.Company, c
http.NotFound(w, r)
return
}
f := newSlideForm(typeSlug)
f := newSlideForm(company, typeSlug)
if err := f.FillFromDatabase(r.Context(), conn, mediaID); err != nil {
if database.ErrorIsNotFound(err) {
http.NotFound(w, r)
@ -82,23 +82,7 @@ func (h *AdminHandler) carouselHandler(user *auth.User, company *auth.Company, c
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut, http.MethodDelete)
}
default:
loc, ok := h.locales.Get(langTag)
if !ok {
http.NotFound(w, r)
return
}
l10n := newSlideL10nForm(f, loc)
if err := l10n.FillFromDatabase(r.Context(), conn); err != nil {
panic(err)
}
switch r.Method {
case http.MethodGet:
l10n.MustRender(w, r, user, company)
case http.MethodPut:
editSlideL10n(w, r, user, company, conn, l10n)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
}
http.NotFound(w, r)
}
}
})
@ -165,21 +149,12 @@ func collectSlideEntries(ctx context.Context, conn *database.Conn, typeSlug stri
select carousel.media_id
, media.path
, caption
, array_agg((lang_tag, endonym, not exists (select 1 from campsite_type_carousel_i18n as i18n where i18n.media_id = carousel.media_id and i18n.lang_tag = language.lang_tag)) order by endonym)
from campsite_type_carousel as carousel
join campsite_type using (campsite_type_id)
join media on media.media_id = carousel.media_id
join company on company.company_id = campsite_type.company_id
, language
where lang_tag <> default_lang_tag
and language.selectable
and campsite_type.slug = $1
group by carousel.media_id
, carousel.position
, media.path
, caption
where campsite_type.slug = $1
order by carousel.position, caption
`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, typeSlug)
`, typeSlug)
if err != nil {
return nil, err
}
@ -188,17 +163,9 @@ func collectSlideEntries(ctx context.Context, conn *database.Conn, typeSlug stri
var slides []*carousel.SlideEntry
for rows.Next() {
slide := &carousel.SlideEntry{}
var translations database.RecordArray
if err = rows.Scan(&slide.ID, &slide.Media, &slide.Caption, &translations); err != nil {
if err = rows.Scan(&slide.ID, &slide.Media, &slide.Caption); err != nil {
return nil, err
}
for _, el := range translations.Elements {
slide.Translations = append(slide.Translations, &carousel.Translation{
Language: el.Fields[0].Get().(string),
Endonym: el.Fields[1].Get().(string),
Missing: el.Fields[2].Get().(bool),
})
}
slides = append(slides, slide)
}
@ -206,13 +173,25 @@ func collectSlideEntries(ctx context.Context, conn *database.Conn, typeSlug stri
}
func addSlide(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, typeSlug string) {
f := newSlideForm(typeSlug)
f := newSlideForm(company, typeSlug)
editSlide(w, r, user, company, conn, f)
}
func editSlide(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *slideForm) {
f.process(w, r, user, company, conn, func(ctx context.Context) {
conn.MustExec(ctx, "select add_campsite_type_carousel_slide($1, $2, $3)", f.TypeSlug, f.Media, f.Caption)
f.process(w, r, user, company, conn, func(ctx context.Context, tx *database.Tx) error {
if err := tx.AddCampsiteTypeCarouselSlide(ctx, f.TypeSlug, f.Media.Int(), f.Caption[f.DefaultLang].Val); err != nil {
return nil
}
for lang := range company.Locales {
l := lang.String()
if l == f.DefaultLang {
continue
}
if err := tx.TranslateCampsiteTypeCarouselSlide(ctx, f.TypeSlug, f.Media.Int(), lang, f.Caption[l].Val); err != nil {
return err
}
}
return nil
})
}
@ -226,15 +205,17 @@ func (h *AdminHandler) deleteSlide(w http.ResponseWriter, r *http.Request, user
}
type slideForm struct {
TypeSlug string
MediaID int
Media *form.Media
Caption *form.Input
DefaultLang string
TypeSlug string
MediaID int
Media *form.Media
Caption form.I18nInput
}
func newSlideForm(typeSlug string) *slideForm {
func newSlideForm(company *auth.Company, typeSlug string) *slideForm {
return &slideForm{
TypeSlug: typeSlug,
DefaultLang: company.DefaultLanguage.String(),
TypeSlug: typeSlug,
Media: &form.Media{
Input: &form.Input{
Name: "media",
@ -242,26 +223,35 @@ func newSlideForm(typeSlug string) *slideForm {
Label: locale.PgettextNoop("Slide image", "input"),
Prompt: locale.PgettextNoop("Set slide image", "action"),
},
Caption: &form.Input{
Name: "caption",
},
Caption: form.NewI18nInput(company.Locales, "caption"),
}
}
func (f *slideForm) FillFromDatabase(ctx context.Context, conn *database.Conn, mediaID int) error {
f.MediaID = mediaID
var caption database.RecordArray
row := conn.QueryRow(ctx, `
select caption
select carousel.caption
, carousel.media_id::text
, array_agg((lang_tag, i18n.caption))
from campsite_type_carousel as carousel
left join campsite_type_carousel_i18n as i18n using (campsite_type_id, media_id)
join campsite_type using (campsite_type_id)
where campsite_type.slug = $1
and carousel.media_id = $2
`, f.TypeSlug, mediaID)
return row.Scan(&f.Caption.Val, &f.Media.Val)
group by carousel.caption
, carousel.media_id::text
`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, f.TypeSlug, mediaID)
if err := row.Scan(&f.Caption[f.DefaultLang].Val, &f.Media.Val, &caption); err != nil {
return err
}
if err := f.Caption.FillArray(caption); err != nil {
return err
}
return nil
}
func (f *slideForm) process(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, act func(ctx context.Context)) {
func (f *slideForm) process(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, act func(ctx context.Context, tx *database.Tx) error) {
if err := f.Parse(r); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
@ -279,7 +269,17 @@ func (f *slideForm) process(w http.ResponseWriter, r *http.Request, user *auth.U
f.MustRender(w, r, user, company)
return
}
act(r.Context())
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/campsites/types/"+f.TypeSlug+"/slides", http.StatusSeeOther)
}

View File

@ -38,7 +38,7 @@ func (h *AdminHandler) featuresHandler(user *auth.User, company *auth.Company, c
case "new":
switch r.Method {
case http.MethodGet:
f := newFeatureForm(r.Context(), conn, typeSlug)
f := newFeatureForm(r.Context(), company, conn, typeSlug)
f.MustRender(w, r, user, company)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet)
@ -56,7 +56,7 @@ func (h *AdminHandler) featuresHandler(user *auth.User, company *auth.Company, c
http.NotFound(w, r)
return
}
f := newFeatureForm(r.Context(), conn, typeSlug)
f := newFeatureForm(r.Context(), company, conn, typeSlug)
if err := f.FillFromDatabase(r.Context(), conn, id); err != nil {
if database.ErrorIsNotFound(err) {
http.NotFound(w, r)
@ -85,23 +85,7 @@ func (h *AdminHandler) featureHandler(user *auth.User, company *auth.Company, co
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
}
default:
loc, ok := h.locales.Get(head)
if !ok {
http.NotFound(w, r)
return
}
l10n := newFeatureL10nForm(f, loc)
if err := l10n.FillFromDatabase(r.Context(), conn); err != nil {
panic(err)
}
switch r.Method {
case http.MethodGet:
l10n.MustRender(w, r, user, company)
case http.MethodPut:
editFeatureL10n(w, r, user, company, conn, l10n)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
}
http.NotFound(w, r)
}
})
}
@ -124,20 +108,11 @@ func collectFeatureEntries(ctx context.Context, conn *database.Conn, typeSlug st
, '/admin/campsites/types/' || campsite_type.slug || '/features/' || campsite_type_feature_id
, feature.icon_name
, feature.name
, array_agg((lang_tag, endonym, not exists (select 1 from campsite_type_feature_i18n as i18n where i18n.campsite_type_feature_id = feature.campsite_type_feature_id and i18n.lang_tag = language.lang_tag)) order by endonym)
from campsite_type_feature as feature
join campsite_type using (campsite_type_id)
join company using (company_id)
, language
where lang_tag <> default_lang_tag
and language.selectable
and campsite_type.slug = $1
group by campsite_type_feature_id
, campsite_type.slug
, feature.name
, feature.position
where campsite_type.slug = $1
order by feature.position, feature.name
`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, typeSlug)
`, typeSlug)
if err != nil {
return nil, err
}
@ -146,17 +121,9 @@ func collectFeatureEntries(ctx context.Context, conn *database.Conn, typeSlug st
var features []*featureEntry
for rows.Next() {
feature := &featureEntry{}
var translations database.RecordArray
if err = rows.Scan(&feature.ID, &feature.URL, &feature.Icon, &feature.Name, &translations); err != nil {
if err = rows.Scan(&feature.ID, &feature.URL, &feature.Icon, &feature.Name); err != nil {
return nil, err
}
for _, el := range translations.Elements {
feature.Translations = append(feature.Translations, &locale.Translation{
URL: feature.URL + "/" + el.Fields[0].Get().(string),
Endonym: el.Fields[1].Get().(string),
Missing: el.Fields[2].Get().(bool),
})
}
features = append(features, feature)
}
@ -164,11 +131,10 @@ func collectFeatureEntries(ctx context.Context, conn *database.Conn, typeSlug st
}
type featureEntry struct {
ID int
URL string
Icon string
Name string
Translations []*locale.Translation
ID int
URL string
Icon string
Name string
}
type featureIndex struct {
@ -181,19 +147,40 @@ func (page *featureIndex) MustRender(w http.ResponseWriter, r *http.Request, use
}
func addFeature(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, typeSlug string) {
f := newFeatureForm(r.Context(), conn, typeSlug)
processFeatureForm(w, r, user, company, f, func(ctx context.Context) (int, error) {
return conn.AddCampsiteTypeFeature(ctx, typeSlug, f.Icon.String(), f.Name.Val)
f := newFeatureForm(r.Context(), company, conn, typeSlug)
processFeatureForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error {
var err error
f.ID, err = tx.AddCampsiteTypeFeature(ctx, typeSlug, f.Icon.String(), f.Name[f.DefaultLang].Val)
if err != nil {
return err
}
return translateFeatures(ctx, tx, company, f)
})
}
func translateFeatures(ctx context.Context, tx *database.Tx, company *auth.Company, f *featureForm) error {
for lang := range company.Locales {
l := lang.String()
if l == f.DefaultLang {
continue
}
if err := tx.TranslateCampsiteTypeFeature(ctx, f.ID, lang, f.Name[l].Val); err != nil {
return err
}
}
return nil
}
func editFeature(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *featureForm) {
processFeatureForm(w, r, user, company, f, func(ctx context.Context) (int, error) {
return conn.EditCampsiteTypeFeature(ctx, f.ID, f.Icon.String(), f.Name.Val)
processFeatureForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error {
if _, err := tx.EditCampsiteTypeFeature(ctx, f.ID, f.Icon.String(), f.Name[f.DefaultLang].Val); err != nil {
return err
}
return translateFeatures(ctx, tx, company, f)
})
}
func processFeatureForm(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, f *featureForm, act func(ctx context.Context) (int, error)) {
func processFeatureForm(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *featureForm, act func(ctx context.Context, tx *database.Tx) error) {
if ok, err := form.Handle(f, w, r, user); err != nil {
return
} else if !ok {
@ -201,41 +188,60 @@ func processFeatureForm(w http.ResponseWriter, r *http.Request, user *auth.User,
return
}
if _, err := act(r.Context()); err != nil {
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/campsites/types/"+f.TypeSlug+"/features", http.StatusSeeOther)
}
type featureForm struct {
ID int
TypeSlug string
Icon *form.Select
Name *form.Input
DefaultLang string
ID int
TypeSlug string
Icon *form.Select
Name form.I18nInput
}
func newFeatureForm(ctx context.Context, conn *database.Conn, typeSlug string) *featureForm {
func newFeatureForm(ctx context.Context, company *auth.Company, conn *database.Conn, typeSlug string) *featureForm {
return &featureForm{
TypeSlug: typeSlug,
DefaultLang: company.DefaultLanguage.String(),
TypeSlug: typeSlug,
Icon: &form.Select{
Name: "icon",
Options: form.MustGetOptions(ctx, conn, "select icon_name, icon_name from icon order by 1"),
},
Name: &form.Input{
Name: "name",
},
Name: form.NewI18nInput(company.Locales, "name"),
}
}
func (f *featureForm) FillFromDatabase(ctx context.Context, conn *database.Conn, id int) error {
f.ID = id
var name database.RecordArray
row := conn.QueryRow(ctx, `
select array[icon_name]
, name
from campsite_type_feature
, feature.name
, array_agg((lang_tag, i18n.name))
from campsite_type_feature as feature
left join campsite_type_feature_i18n as i18n using (campsite_type_feature_id)
where campsite_type_feature_id = $1
`, id)
return row.Scan(&f.Icon.Selected, &f.Name.Val)
group by icon_name
, feature.name
`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, id)
if err := row.Scan(&f.Icon.Selected, &f.Name[f.DefaultLang].Val, &name); err != nil {
return err
}
if err := f.Name.FillArray(name); err != nil {
return err
}
return nil
}
func (f *featureForm) Parse(r *http.Request) error {
@ -250,8 +256,8 @@ func (f *featureForm) Parse(r *http.Request) error {
func (f *featureForm) Valid(l *locale.Locale) bool {
v := form.NewValidator(l)
v.CheckSelectedOptions(f.Icon, l.GettextNoop("Selected icon is not valid."))
if v.CheckRequired(f.Name, l.GettextNoop("Name can not be empty.")) {
v.CheckMinLength(f.Name, 1, l.GettextNoop("Name must have at least one letter."))
if v.CheckRequired(f.Name[f.DefaultLang], l.GettextNoop("Name can not be empty.")) {
v.CheckMinLength(f.Name[f.DefaultLang], 1, l.GettextNoop("Name must have at least one letter."))
}
return v.AllOK
}

View File

@ -1,270 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
* SPDX-License-Identifier: AGPL-3.0-only
*/
package types
import (
"context"
"net/http"
"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 typeL10nForm struct {
Locale *locale.Locale
Slug string
Name *form.L10nInput
Spiel *form.L10nInput
Info *form.L10nInput
Facilities *form.L10nInput
Description *form.L10nInput
}
func newTypeL10nForm(f *typeForm, loc *locale.Locale) *typeL10nForm {
return &typeL10nForm{
Locale: loc,
Slug: f.Slug,
Name: f.Name.L10nInput(),
Spiel: f.Spiel.L10nInput(),
Info: f.Info.L10nInput(),
Facilities: f.Facilities.L10nInput(),
Description: f.Description.L10nInput(),
}
}
func (l10n *typeL10nForm) FillFromDatabase(ctx context.Context, conn *database.Conn) error {
row := conn.QueryRow(ctx, `
select coalesce(i18n.name, '') as l10n_name
, coalesce(i18n.spiel, '') as l10n_spiel
, coalesce(i18n.info, '') as l10n_info
, coalesce(i18n.facilities, '') as l10n_facilities
, coalesce(i18n.description, '') as l10n_description
from campsite_type
left join campsite_type_i18n as i18n on campsite_type.campsite_type_id = i18n.campsite_type_id and i18n.lang_tag = $1
where slug = $2
`, l10n.Locale.Language, l10n.Slug)
return row.Scan(&l10n.Name.Val, &l10n.Spiel.Val, &l10n.Info.Val, &l10n.Facilities.Val, &l10n.Description.Val)
}
func (l10n *typeL10nForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdmin(w, r, user, company, "campsite/type/l10n.gohtml", l10n)
}
func editTypeL10n(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, l10n *typeL10nForm) {
if ok, err := form.Handle(l10n, w, r, user); err != nil {
return
} else if !ok {
l10n.MustRender(w, r, user, company)
return
}
if err := conn.TranslateCampsiteType(r.Context(), l10n.Slug, l10n.Locale.Language, l10n.Name.Val, l10n.Spiel.Val, l10n.Info.Val, l10n.Facilities.Val, l10n.Description.Val); err != nil {
panic(err)
}
httplib.Redirect(w, r, "/admin/campsites/types", http.StatusSeeOther)
}
func (l10n *typeL10nForm) Parse(r *http.Request) error {
if err := r.ParseForm(); err != nil {
return err
}
l10n.Name.FillValue(r)
l10n.Spiel.FillValue(r)
l10n.Info.FillValue(r)
l10n.Facilities.FillValue(r)
l10n.Description.FillValue(r)
return nil
}
func (l10n *typeL10nForm) Valid(l *locale.Locale) bool {
v := form.NewValidator(l)
v.CheckRequired(&l10n.Name.Input, l.GettextNoop("Name can not be empty."))
return v.AllOK
}
type optionL10nForm struct {
Locale *locale.Locale
TypeSlug string
ID int
Name *form.L10nInput
}
func newOptionL10nForm(f *optionForm, loc *locale.Locale) *optionL10nForm {
return &optionL10nForm{
Locale: loc,
TypeSlug: f.TypeSlug,
ID: f.ID,
Name: f.Name.L10nInput(),
}
}
func (l10n *optionL10nForm) FillFromDatabase(ctx context.Context, conn *database.Conn) error {
row := conn.QueryRow(ctx, `
select coalesce(i18n.name, '') as l10n_name
from campsite_type_option
left join campsite_type_option_i18n as i18n on campsite_type_option.campsite_type_option_id = i18n.campsite_type_option_id and i18n.lang_tag = $1
where campsite_type_option.campsite_type_option_id = $2
`, l10n.Locale.Language, l10n.ID)
return row.Scan(&l10n.Name.Val)
}
func (l10n *optionL10nForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdmin(w, r, user, company, "campsite/option/l10n.gohtml", l10n)
}
func editOptionL10n(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, l10n *optionL10nForm) {
if ok, err := form.Handle(l10n, w, r, user); err != nil {
return
} else if !ok {
l10n.MustRender(w, r, user, company)
return
}
if err := conn.TranslateCampsiteTypeOption(r.Context(), l10n.ID, l10n.Locale.Language, l10n.Name.Val); err != nil {
panic(err)
}
httplib.Redirect(w, r, "/admin/campsites/types/"+l10n.TypeSlug+"/options", http.StatusSeeOther)
}
func (l10n *optionL10nForm) Parse(r *http.Request) error {
if err := r.ParseForm(); err != nil {
return err
}
l10n.Name.FillValue(r)
return nil
}
func (l10n *optionL10nForm) Valid(l *locale.Locale) bool {
v := form.NewValidator(l)
v.CheckRequired(&l10n.Name.Input, l.GettextNoop("Name can not be empty."))
return v.AllOK
}
type slideL10nForm struct {
Locale *locale.Locale
TypeSlug string
MediaID int
Caption *form.L10nInput
}
func newSlideL10nForm(f *slideForm, loc *locale.Locale) *slideL10nForm {
return &slideL10nForm{
Locale: loc,
TypeSlug: f.TypeSlug,
MediaID: f.MediaID,
Caption: f.Caption.L10nInput(),
}
}
func (l10n *slideL10nForm) FillFromDatabase(ctx context.Context, conn *database.Conn) error {
row := conn.QueryRow(ctx, `
select coalesce(i18n.caption, '') as l10n_caption
from campsite_type_carousel as carousel
join campsite_type using (campsite_type_id)
left join campsite_type_carousel_i18n as i18n
on carousel.campsite_type_id = i18n.campsite_type_id
and carousel.media_id = i18n.media_id
and i18n.lang_tag = $1
where campsite_type.slug = $2 and carousel.media_id = $3
`, l10n.Locale.Language, l10n.TypeSlug, l10n.MediaID)
return row.Scan(&l10n.Caption.Val)
}
func (l10n *slideL10nForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdmin(w, r, user, company, "campsite/carousel/l10n.gohtml", l10n)
}
func editSlideL10n(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, l10n *slideL10nForm) {
if err := l10n.Parse(r); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if err := user.VerifyCSRFToken(r); err != nil {
http.Error(w, err.Error(), http.StatusForbidden)
return
}
if !l10n.Valid(user.Locale) {
if !httplib.IsHTMxRequest(r) {
w.WriteHeader(http.StatusUnprocessableEntity)
}
l10n.MustRender(w, r, user, company)
return
}
conn.MustExec(r.Context(), "select translate_campsite_type_carousel_slide($1, $2, $3, $4)", l10n.TypeSlug, l10n.MediaID, l10n.Locale.Language, l10n.Caption)
httplib.Redirect(w, r, "/admin/campsites/types/"+l10n.TypeSlug+"/slides", http.StatusSeeOther)
}
func (l10n *slideL10nForm) Parse(r *http.Request) error {
if err := r.ParseForm(); err != nil {
return err
}
l10n.Caption.FillValue(r)
return nil
}
func (l10n *slideL10nForm) Valid(l *locale.Locale) bool {
v := form.NewValidator(l)
return v.AllOK
}
type featureL10nForm struct {
Locale *locale.Locale
TypeSlug string
ID int
Name *form.L10nInput
}
func newFeatureL10nForm(f *featureForm, loc *locale.Locale) *featureL10nForm {
return &featureL10nForm{
Locale: loc,
TypeSlug: f.TypeSlug,
ID: f.ID,
Name: f.Name.L10nInput(),
}
}
func (l10n *featureL10nForm) FillFromDatabase(ctx context.Context, conn *database.Conn) error {
row := conn.QueryRow(ctx, `
select coalesce(i18n.name, '') as l10n_name
from campsite_type_feature
left join campsite_type_feature_i18n as i18n on campsite_type_feature.campsite_type_feature_id = i18n.campsite_type_feature_id and i18n.lang_tag = $1
where campsite_type_feature.campsite_type_feature_id = $2
`, l10n.Locale.Language, l10n.ID)
return row.Scan(&l10n.Name.Val)
}
func (l10n *featureL10nForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
template.MustRenderAdmin(w, r, user, company, "campsite/feature/l10n.gohtml", l10n)
}
func editFeatureL10n(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, l10n *featureL10nForm) {
if ok, err := form.Handle(l10n, w, r, user); err != nil {
return
} else if !ok {
l10n.MustRender(w, r, user, company)
return
}
if err := conn.TranslateCampsiteTypeFeature(r.Context(), l10n.ID, l10n.Locale.Language, l10n.Name.Val); err != nil {
panic(err)
}
httplib.Redirect(w, r, "/admin/campsites/types/"+l10n.TypeSlug+"/features", http.StatusSeeOther)
}
func (l10n *featureL10nForm) Parse(r *http.Request) error {
if err := r.ParseForm(); err != nil {
return err
}
l10n.Name.FillValue(r)
return nil
}
func (l10n *featureL10nForm) Valid(l *locale.Locale) bool {
v := form.NewValidator(l)
v.CheckRequired(&l10n.Name.Input, l.GettextNoop("Name can not be empty."))
return v.AllOK
}

View File

@ -92,23 +92,7 @@ func (h *AdminHandler) optionHandler(user *auth.User, company *auth.Company, con
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
}
default:
loc, ok := h.locales.Get(head)
if !ok {
http.NotFound(w, r)
return
}
l10n := newOptionL10nForm(f, loc)
if err := l10n.FillFromDatabase(r.Context(), conn); err != nil {
panic(err)
}
switch r.Method {
case http.MethodGet:
l10n.MustRender(w, r, user, company)
case http.MethodPut:
editOptionL10n(w, r, user, company, conn, l10n)
default:
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
}
http.NotFound(w, r)
}
})
}
@ -130,20 +114,11 @@ func collectOptionEntries(ctx context.Context, conn *database.Conn, typeSlug str
select campsite_type_option_id
, '/admin/campsites/types/' || campsite_type.slug || '/options/' || campsite_type_option_id
, option.name
, array_agg((lang_tag, endonym, not exists (select 1 from campsite_type_option_i18n as i18n where i18n.campsite_type_option_id = option.campsite_type_option_id and i18n.lang_tag = language.lang_tag)) order by endonym)
from campsite_type_option as option
join campsite_type using (campsite_type_id)
join company using (company_id)
, language
where lang_tag <> default_lang_tag
and language.selectable
and campsite_type.slug = $1
group by campsite_type_option_id
, campsite_type.slug
, option.position
, option.name
where campsite_type.slug = $1
order by option.position, option.name
`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, typeSlug)
`, typeSlug)
if err != nil {
return nil, err
}
@ -152,17 +127,9 @@ func collectOptionEntries(ctx context.Context, conn *database.Conn, typeSlug str
var options []*optionEntry
for rows.Next() {
option := &optionEntry{}
var translations database.RecordArray
if err = rows.Scan(&option.ID, &option.URL, &option.Name, &translations); err != nil {
if err = rows.Scan(&option.ID, &option.URL, &option.Name); err != nil {
return nil, err
}
for _, el := range translations.Elements {
option.Translations = append(option.Translations, &locale.Translation{
URL: option.URL + "/" + el.Fields[0].Get().(string),
Endonym: el.Fields[1].Get().(string),
Missing: el.Fields[2].Get().(bool),
})
}
options = append(options, option)
}
@ -170,10 +137,9 @@ func collectOptionEntries(ctx context.Context, conn *database.Conn, typeSlug str
}
type optionEntry struct {
ID int
URL string
Name string
Translations []*locale.Translation
ID int
URL string
Name string
}
type optionIndex struct {
@ -191,17 +157,37 @@ func addOption(w http.ResponseWriter, r *http.Request, user *auth.User, company
panic(err)
}
processOptionForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error {
id, err := tx.AddCampsiteTypeOption(ctx, typeSlug, f.Name.Val, f.Min.Int(), f.Max.Int())
var err error
f.ID, err = tx.AddCampsiteTypeOption(ctx, typeSlug, f.Name[f.DefaultLang].Val, f.Min.Int(), f.Max.Int())
if err != nil {
return err
}
return setOptionPrices(ctx, tx, id, f.Prices)
if err := translateOptions(ctx, tx, company, f); err != nil {
return err
}
return setOptionPrices(ctx, tx, f.ID, f.Prices)
})
}
func translateOptions(ctx context.Context, tx *database.Tx, company *auth.Company, f *optionForm) error {
for lang := range company.Locales {
l := lang.String()
if l == f.DefaultLang {
continue
}
if err := tx.TranslateCampsiteTypeOption(ctx, f.ID, lang, f.Name[l].Val); err != nil {
return err
}
}
return nil
}
func editOption(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *optionForm) {
processOptionForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error {
if _, err := tx.EditCampsiteTypeOption(ctx, f.ID, f.Name.Val, f.Min.Int(), f.Max.Int()); err != nil {
if _, err := tx.EditCampsiteTypeOption(ctx, f.ID, f.Name[f.DefaultLang].Val, f.Min.Int(), f.Max.Int()); err != nil {
return err
}
if err := translateOptions(ctx, tx, company, f); err != nil {
return err
}
return setOptionPrices(ctx, tx, f.ID, f.Prices)
@ -240,12 +226,13 @@ func setOptionPrices(ctx context.Context, tx *database.Tx, id int, prices map[in
}
type optionForm struct {
ID int
TypeSlug string
Name *form.Input
Min *form.Input
Max *form.Input
Prices map[int]*optionPriceForm
DefaultLang string
ID int
TypeSlug string
Name form.I18nInput
Min *form.Input
Max *form.Input
Prices map[int]*optionPriceForm
}
type optionPriceForm struct {
@ -255,10 +242,9 @@ type optionPriceForm struct {
func newOptionForm(ctx context.Context, company *auth.Company, conn *database.Conn, typeSlug string) (*optionForm, error) {
f := &optionForm{
TypeSlug: typeSlug,
Name: &form.Input{
Name: "name",
},
DefaultLang: company.DefaultLanguage.String(),
TypeSlug: typeSlug,
Name: form.NewI18nInput(company.Locales, "name"),
Min: &form.Input{
Name: "min",
Val: "0",
@ -296,14 +282,22 @@ func newOptionForm(ctx context.Context, company *auth.Company, conn *database.Co
func (f *optionForm) FillFromDatabase(ctx context.Context, conn *database.Conn, id int) error {
f.ID = id
var name database.RecordArray
row := conn.QueryRow(ctx, `
select name
select option.name
, lower(range)::text
, (upper(range) - 1)::text
from campsite_type_option
, array_agg((lang_tag, i18n.name))
from campsite_type_option as option
left join campsite_type_option_i18n as i18n using (campsite_type_option_id)
where campsite_type_option_id = $1
`, id)
if err := row.Scan(&f.Name.Val, &f.Min.Val, &f.Max.Val); err != nil {
group by option.name
, range
`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, id)
if err := row.Scan(&f.Name[f.DefaultLang].Val, &f.Min.Val, &f.Max.Val, &name); err != nil {
return err
}
if err := f.Name.FillArray(name); err != nil {
return err
}
@ -347,8 +341,8 @@ func (f *optionForm) Parse(r *http.Request) error {
func (f *optionForm) Valid(l *locale.Locale) bool {
v := form.NewValidator(l)
if v.CheckRequired(f.Name, l.GettextNoop("Name can not be empty.")) {
v.CheckMinLength(f.Name, 1, l.GettextNoop("Name must have at least one letter."))
if v.CheckRequired(f.Name[f.DefaultLang], l.GettextNoop("Name can not be empty.")) {
v.CheckMinLength(f.Name[f.DefaultLang], 1, l.GettextNoop("Name must have at least one letter."))
}
minValidInt := false
if v.CheckRequired(f.Min, l.GettextNoop("Minimum can not be empty.")) {

View File

@ -24,8 +24,8 @@ func (c *Conn) OrderCampsiteTypes(ctx context.Context, slugs []string) error {
return err
}
func (c *Conn) TranslateCampsiteType(ctx context.Context, slug string, langTag language.Tag, name string, spiel string, info string, facilities string, description string) error {
_, err := c.Exec(ctx, "select translate_campsite_type($1, $2, $3, $4, $5, $6, $7)", slug, langTag, name, spiel, info, facilities, description)
func (tx *Tx) TranslateCampsiteType(ctx context.Context, slug string, langTag language.Tag, name string, spiel string, info string, facilities string, description string) error {
_, err := tx.Exec(ctx, "select translate_campsite_type($1, $2, $3, $4, $5, $6, $7)", slug, langTag, name, spiel, info, facilities, description)
return err
}
func (tx *Tx) SetCampsiteTypeCost(ctx context.Context, slug string, seasonID int, minNights int, costPerNight string) error {
@ -46,8 +46,8 @@ func (tx *Tx) SetCampsiteTypeOptionCost(ctx context.Context, id int, seasonID in
return err
}
func (c *Conn) TranslateCampsiteTypeOption(ctx context.Context, id int, langTag language.Tag, name string) error {
_, err := c.Exec(ctx, "select translate_campsite_type_option($1, $2, $3)", id, langTag, name)
func (tx *Tx) TranslateCampsiteTypeOption(ctx context.Context, id int, langTag language.Tag, name string) error {
_, err := tx.Exec(ctx, "select translate_campsite_type_option($1, $2, $3)", id, langTag, name)
return err
}
@ -61,16 +61,16 @@ func (c *Conn) OrderCampsiteTypeCarousel(ctx context.Context, typeSlug string, m
return err
}
func (c *Conn) AddCampsiteTypeFeature(ctx context.Context, typeSlug string, iconName string, name string) (int, error) {
return c.GetInt(ctx, "select add_campsite_type_feature($1, $2, $3)", typeSlug, iconName, name)
func (tx *Tx) AddCampsiteTypeFeature(ctx context.Context, typeSlug string, iconName string, name string) (int, error) {
return tx.GetInt(ctx, "select add_campsite_type_feature($1, $2, $3)", typeSlug, iconName, name)
}
func (c *Conn) EditCampsiteTypeFeature(ctx context.Context, id int, iconName string, name string) (int, error) {
return c.GetInt(ctx, "select edit_campsite_type_feature($1, $2, $3)", id, iconName, name)
func (tx *Tx) EditCampsiteTypeFeature(ctx context.Context, id int, iconName string, name string) (int, error) {
return tx.GetInt(ctx, "select edit_campsite_type_feature($1, $2, $3)", id, iconName, name)
}
func (c *Conn) TranslateCampsiteTypeFeature(ctx context.Context, id int, langTag language.Tag, name string) error {
_, err := c.Exec(ctx, "select translate_campsite_type_feature($1, $2, $3)", id, langTag, name)
func (tx *Tx) TranslateCampsiteTypeFeature(ctx context.Context, id int, langTag language.Tag, name string) error {
_, err := tx.Exec(ctx, "select translate_campsite_type_feature($1, $2, $3)", id, langTag, name)
return err
}
@ -79,6 +79,16 @@ func (c *Conn) OrderCampsiteTypeFeatures(ctx context.Context, ids []int) error {
return err
}
func (tx *Tx) AddCampsiteTypeCarouselSlide(ctx context.Context, typeSlug string, mediaID int, caption string) error {
_, err := tx.Exec(ctx, "select add_campsite_type_carousel_slide($1, $2, $3)", typeSlug, mediaID, caption)
return err
}
func (tx *Tx) TranslateCampsiteTypeCarouselSlide(ctx context.Context, typeSlug string, mediaID int, langTag language.Tag, caption string) error {
_, err := tx.Exec(ctx, "select translate_campsite_type_carousel_slide($1, $2, $3, $4)", typeSlug, mediaID, langTag, caption)
return err
}
func (c *Conn) SetupRedsys(ctx context.Context, companyID int, merchantCode string, terminalNumber int, environment string, integration string, encryptKey string) error {
var encryptKeyParam interface{}
if encryptKey != "" {

221
po/ca.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-01-10 19:33+0100\n"
"POT-Creation-Date: 2024-01-10 21:49+0100\n"
"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"
@ -131,8 +131,8 @@ msgid "Calendar"
msgstr "Calendari"
#: web/templates/public/campsite/type.gohtml:73
#: web/templates/admin/campsite/option/form.gohtml:58
#: web/templates/admin/campsite/type/form.gohtml:73
#: web/templates/admin/campsite/option/form.gohtml:63
#: web/templates/admin/campsite/type/form.gohtml:78
msgctxt "title"
msgid "Prices"
msgstr "Preus"
@ -419,11 +419,8 @@ 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
@ -440,11 +437,11 @@ 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/feature/form.gohtml:67
#: web/templates/admin/campsite/carousel/form.gohtml:52
#: 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/campsite/option/form.gohtml:83
#: web/templates/admin/campsite/type/form.gohtml:158
#: web/templates/admin/season/form.gohtml:64
#: web/templates/admin/services/form.gohtml:69
#: web/templates/admin/media/form.gohtml:35
@ -454,11 +451,11 @@ 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/feature/form.gohtml:69
#: web/templates/admin/campsite/carousel/form.gohtml:54
#: 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/campsite/option/form.gohtml:85
#: web/templates/admin/campsite/type/form.gohtml:160
#: web/templates/admin/season/form.gohtml:66
#: web/templates/admin/services/form.gohtml:71
msgctxt "action"
@ -505,7 +502,6 @@ 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"
@ -517,14 +513,6 @@ 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
@ -532,14 +520,6 @@ 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
@ -548,10 +528,6 @@ 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"
@ -614,28 +590,10 @@ msgctxt "action"
msgid "Add Feature"
msgstr "Afegeix característica"
#: web/templates/admin/campsite/feature/index.gohtml:27
#: 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:53
#: web/templates/admin/campsite/feature/index.gohtml:43
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"
@ -675,7 +633,7 @@ msgctxt "header"
msgid "Caption"
msgstr "Llegenda"
#: web/templates/admin/campsite/carousel/index.gohtml:28
#: web/templates/admin/campsite/carousel/index.gohtml:27
#: web/templates/admin/services/index.gohtml:28
#: web/templates/admin/services/index.gohtml:74
#: web/templates/admin/home/index.gohtml:28
@ -683,13 +641,13 @@ msgctxt "header"
msgid "Actions"
msgstr "Accions"
#: web/templates/admin/campsite/carousel/index.gohtml:32
#: web/templates/admin/campsite/carousel/index.gohtml:31
#: 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/campsite/carousel/index.gohtml:45
#: web/templates/admin/services/index.gohtml:54
#: web/templates/admin/services/index.gohtml:93
#: web/templates/admin/home/index.gohtml:54
@ -697,18 +655,12 @@ msgctxt "action"
msgid "Delete"
msgstr "Esborra"
#: web/templates/admin/campsite/carousel/index.gohtml:64
#: web/templates/admin/campsite/carousel/index.gohtml:54
#: 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"
@ -753,18 +705,18 @@ msgctxt "title"
msgid "New Campsite Type Option"
msgstr "Nova opció del tipus dallotjament"
#: web/templates/admin/campsite/option/form.gohtml:42
#: web/templates/admin/campsite/option/form.gohtml:47
msgctxt "input"
msgid "Minimum"
msgstr "Mínim"
#: web/templates/admin/campsite/option/form.gohtml:50
#: web/templates/admin/campsite/option/form.gohtml:55
msgctxt "input"
msgid "Maximum"
msgstr "Màxim"
#: web/templates/admin/campsite/option/form.gohtml:64
#: web/templates/admin/campsite/type/form.gohtml:79
#: web/templates/admin/campsite/option/form.gohtml:69
#: web/templates/admin/campsite/type/form.gohtml:84
msgctxt "input"
msgid "Price per night"
msgstr "Preu per nit"
@ -780,16 +732,10 @@ msgctxt "action"
msgid "Add Option"
msgstr "Afegeix opció"
#: web/templates/admin/campsite/option/index.gohtml:52
#: web/templates/admin/campsite/option/index.gohtml:42
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"
@ -806,13 +752,13 @@ msgid "Type"
msgstr "Tipus"
#: web/templates/admin/campsite/index.gohtml:28
#: web/templates/admin/campsite/type/index.gohtml:59
#: web/templates/admin/campsite/type/index.gohtml:49
#: 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/campsite/type/index.gohtml:49
#: web/templates/admin/season/index.gohtml:49
msgid "No"
msgstr "No"
@ -834,46 +780,42 @@ msgid "New Campsite Type"
msgstr "Nou tipus dallotjament"
#: web/templates/admin/campsite/type/form.gohtml:37
#: web/templates/admin/campsite/type/index.gohtml:30
#: web/templates/admin/campsite/type/index.gohtml:29
msgctxt "campsite type"
msgid "Active"
msgstr "Actiu"
#: web/templates/admin/campsite/type/form.gohtml:57
#: web/templates/admin/campsite/type/form.gohtml:62
msgctxt "input"
msgid "Maximum number of campers"
msgstr "Número màxim de persones"
#: web/templates/admin/campsite/type/form.gohtml:67
#: web/templates/admin/campsite/type/form.gohtml:72
msgctxt "input"
msgid "Dogs allowed"
msgstr "Es permeten gossos"
#: web/templates/admin/campsite/type/form.gohtml:87
#: web/templates/admin/campsite/type/form.gohtml:92
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
#: web/templates/admin/campsite/type/form.gohtml:104
msgctxt "input"
msgid "Spiel"
msgstr "Introducció"
#: web/templates/admin/campsite/type/form.gohtml:106
#: web/templates/admin/campsite/type/l10n.gohtml:45
#: web/templates/admin/campsite/type/form.gohtml:117
msgctxt "input"
msgid "Info"
msgstr "Informació"
#: web/templates/admin/campsite/type/form.gohtml:113
#: web/templates/admin/campsite/type/l10n.gohtml:58
#: web/templates/admin/campsite/type/form.gohtml:130
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/campsite/type/form.gohtml:143
#: web/templates/admin/services/form.gohtml:60
#: web/templates/admin/services/l10n.gohtml:32
msgctxt "input"
@ -892,46 +834,40 @@ msgctxt "action"
msgid "Add Type"
msgstr "Afegeix tipus"
#: web/templates/admin/campsite/type/index.gohtml:27
#: web/templates/admin/campsite/type/index.gohtml:26
msgctxt "header"
msgid "Features"
msgstr "Característiques"
#: web/templates/admin/campsite/type/index.gohtml:28
#: web/templates/admin/campsite/type/index.gohtml:27
msgctxt "header"
msgid "Options"
msgstr "Opcions"
#: web/templates/admin/campsite/type/index.gohtml:29
#: web/templates/admin/campsite/type/index.gohtml:28
msgctxt "header"
msgid "Carousel"
msgstr "Carrusel"
#: web/templates/admin/campsite/type/index.gohtml:51
#: web/templates/admin/campsite/type/index.gohtml:41
msgctxt "action"
msgid "Edit Features"
msgstr "Edita les característiques"
#: web/templates/admin/campsite/type/index.gohtml:54
#: web/templates/admin/campsite/type/index.gohtml:44
msgctxt "action"
msgid "Edit Options"
msgstr "Edita les opcions"
#: web/templates/admin/campsite/type/index.gohtml:57
#: web/templates/admin/campsite/type/index.gohtml:47
msgctxt "action"
msgid "Edit Carousel"
msgstr "Edita el carrusel"
#: web/templates/admin/campsite/type/index.gohtml:66
#: web/templates/admin/campsite/type/index.gohtml:56
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"
@ -972,6 +908,14 @@ msgctxt "header"
msgid "Color"
msgstr "Color"
#: 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/season/index.gohtml:56
msgid "No seasons added yet."
msgstr "No sha afegit cap temporada encara."
@ -1278,25 +1222,24 @@ msgctxt "title"
msgid "Upload Media"
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
#: pkg/legal/admin.go:255 pkg/app/user.go:249 pkg/campsite/types/option.go:344
#: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:453
#: 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
#: pkg/legal/admin.go:256 pkg/campsite/types/option.go:345
#: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:454
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:223
msgctxt "input"
msgid "Slide image"
msgstr "Imatge de la diapositiva"
#: pkg/carousel/admin.go:286 pkg/campsite/types/carousel.go:243
#: pkg/carousel/admin.go:286 pkg/campsite/types/carousel.go:224
msgctxt "action"
msgid "Set slide image"
msgstr "Estableix la imatge de la diapositiva"
@ -1348,85 +1291,85 @@ msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida."
msgid "Access forbidden"
msgstr "Accés prohibit"
#: pkg/campsite/types/option.go:354
#: pkg/campsite/types/option.go:348
msgid "Minimum can not be empty."
msgstr "No podeu deixar el mínim en blanc."
#: pkg/campsite/types/option.go:355
#: pkg/campsite/types/option.go:349
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
#: pkg/campsite/types/option.go:351
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
#: pkg/campsite/types/option.go:354
msgid "Maximum can not be empty."
msgstr "No podeu deixar el màxim en blanc."
#: pkg/campsite/types/option.go:361
#: pkg/campsite/types/option.go:355
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
#: pkg/campsite/types/option.go:357
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
#: pkg/campsite/types/option.go:361 pkg/campsite/types/admin.go:467
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
#: pkg/campsite/types/option.go:362 pkg/campsite/types/admin.go:468
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
#: pkg/campsite/types/option.go:363 pkg/campsite/types/admin.go:469
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:252 pkg/services/admin.go:265
#: pkg/campsite/types/feature.go:258 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
#: pkg/campsite/types/admin.go:304
msgctxt "input"
msgid "Cover image"
msgstr "Imatge de portada"
#: pkg/campsite/types/admin.go:324
#: pkg/campsite/types/admin.go:305
msgctxt "action"
msgid "Set campsite type cover"
msgstr "Estableix la portada del tipus dallotjament"
#: pkg/campsite/types/admin.go:450
#: pkg/campsite/types/admin.go:456
msgid "Cover image can not be empty."
msgstr "No podeu deixar la imatge de portada en blanc."
#: pkg/campsite/types/admin.go:451
#: pkg/campsite/types/admin.go:457
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
#: pkg/campsite/types/admin.go:461
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
#: pkg/campsite/types/admin.go:462
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
#: pkg/campsite/types/admin.go:463
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
#: pkg/campsite/types/admin.go:472
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
#: pkg/campsite/types/admin.go:473
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
#: pkg/campsite/types/admin.go:474
msgid "Minimum number of nights must be one or greater."
msgstr "El número mínim de nits no pot ser zero."
@ -1707,6 +1650,22 @@ msgstr "El valor de %s ha de ser com a mínim %d."
msgid "%s must be at most %d."
msgstr "El valor de %s ha de ser com a màxim %d."
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Feature to %s"
#~ msgstr "Traducció de la característica del tipus dallotjament a %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Carousel Slide to %s"
#~ msgstr "Traducció de la diapositiva del carrusel del tipus dallotjament a %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Option to %s"
#~ msgstr "Traducció de la opció del tipus dallotjament a %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type to %s"
#~ msgstr "Traducció del tipus dallotjament a %s"
#~ msgid "Starting from %s €/night"
#~ msgstr "A partir de %s €/nit"

221
po/es.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-01-10 19:33+0100\n"
"POT-Creation-Date: 2024-01-10 21:49+0100\n"
"PO-Revision-Date: 2023-07-22 23:46+0200\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Spanish <es@tp.org.es>\n"
@ -131,8 +131,8 @@ msgid "Calendar"
msgstr "Calendario"
#: web/templates/public/campsite/type.gohtml:73
#: web/templates/admin/campsite/option/form.gohtml:58
#: web/templates/admin/campsite/type/form.gohtml:73
#: web/templates/admin/campsite/option/form.gohtml:63
#: web/templates/admin/campsite/type/form.gohtml:78
msgctxt "title"
msgid "Prices"
msgstr "Precios"
@ -419,11 +419,8 @@ 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
@ -440,11 +437,11 @@ 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/feature/form.gohtml:67
#: web/templates/admin/campsite/carousel/form.gohtml:52
#: 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/campsite/option/form.gohtml:83
#: web/templates/admin/campsite/type/form.gohtml:158
#: web/templates/admin/season/form.gohtml:64
#: web/templates/admin/services/form.gohtml:69
#: web/templates/admin/media/form.gohtml:35
@ -454,11 +451,11 @@ 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/feature/form.gohtml:69
#: web/templates/admin/campsite/carousel/form.gohtml:54
#: 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/campsite/option/form.gohtml:85
#: web/templates/admin/campsite/type/form.gohtml:160
#: web/templates/admin/season/form.gohtml:66
#: web/templates/admin/services/form.gohtml:71
msgctxt "action"
@ -505,7 +502,6 @@ msgstr "Nueva 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 "Leyenda"
@ -517,14 +513,6 @@ msgid "Translate Carousel Slide to %s"
msgstr "Traducción de la diapositiva de 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
@ -532,14 +520,6 @@ 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
@ -548,10 +528,6 @@ msgid "Translation:"
msgstr "Traducción"
#: 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"
@ -614,28 +590,10 @@ msgctxt "action"
msgid "Add Feature"
msgstr "Añadir características"
#: web/templates/admin/campsite/feature/index.gohtml:27
#: 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 "Traducciones"
#: web/templates/admin/campsite/feature/index.gohtml:53
#: web/templates/admin/campsite/feature/index.gohtml:43
msgid "No campsite type features added yet."
msgstr "No se ha añadido ninguna característica al tipo de alojamiento todavía."
#: web/templates/admin/campsite/feature/l10n.gohtml:7
#: web/templates/admin/campsite/feature/l10n.gohtml:14
msgctxt "title"
msgid "Translate Campsite Type Feature to %s"
msgstr "Traducción de la característica del tipo de alojamiento a %s"
#: web/templates/admin/campsite/carousel/form.gohtml:8
#: web/templates/admin/campsite/carousel/form.gohtml:25
msgctxt "title"
@ -675,7 +633,7 @@ msgctxt "header"
msgid "Caption"
msgstr "Leyenda"
#: web/templates/admin/campsite/carousel/index.gohtml:28
#: web/templates/admin/campsite/carousel/index.gohtml:27
#: web/templates/admin/services/index.gohtml:28
#: web/templates/admin/services/index.gohtml:74
#: web/templates/admin/home/index.gohtml:28
@ -683,13 +641,13 @@ msgctxt "header"
msgid "Actions"
msgstr "Acciones"
#: web/templates/admin/campsite/carousel/index.gohtml:32
#: web/templates/admin/campsite/carousel/index.gohtml:31
#: 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 "¿Estáis seguro de querer borrar esta diapositiva?"
#: web/templates/admin/campsite/carousel/index.gohtml:55
#: web/templates/admin/campsite/carousel/index.gohtml:45
#: web/templates/admin/services/index.gohtml:54
#: web/templates/admin/services/index.gohtml:93
#: web/templates/admin/home/index.gohtml:54
@ -697,18 +655,12 @@ msgctxt "action"
msgid "Delete"
msgstr "Borrar"
#: web/templates/admin/campsite/carousel/index.gohtml:64
#: web/templates/admin/campsite/carousel/index.gohtml:54
#: web/templates/admin/services/index.gohtml:63
#: web/templates/admin/home/index.gohtml:63
msgid "No slides added yet."
msgstr "No se ha añadido ninguna diapositiva todavía."
#: 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ón de la diapositiva de carrusel del tipo de alojamiento a %s"
#: web/templates/admin/campsite/form.gohtml:8
#: web/templates/admin/campsite/form.gohtml:25
msgctxt "title"
@ -753,18 +705,18 @@ msgctxt "title"
msgid "New Campsite Type Option"
msgstr "Nueva opción del tipo de alojamiento"
#: web/templates/admin/campsite/option/form.gohtml:42
#: web/templates/admin/campsite/option/form.gohtml:47
msgctxt "input"
msgid "Minimum"
msgstr "Mínimo"
#: web/templates/admin/campsite/option/form.gohtml:50
#: web/templates/admin/campsite/option/form.gohtml:55
msgctxt "input"
msgid "Maximum"
msgstr "Màximo"
#: web/templates/admin/campsite/option/form.gohtml:64
#: web/templates/admin/campsite/type/form.gohtml:79
#: web/templates/admin/campsite/option/form.gohtml:69
#: web/templates/admin/campsite/type/form.gohtml:84
msgctxt "input"
msgid "Price per night"
msgstr "Precio por noche"
@ -780,16 +732,10 @@ msgctxt "action"
msgid "Add Option"
msgstr "Añadir opción"
#: web/templates/admin/campsite/option/index.gohtml:52
#: web/templates/admin/campsite/option/index.gohtml:42
msgid "No campsite type options added yet."
msgstr "No se ha añadido ninguna opció al tipo de alojamiento todavía."
#: web/templates/admin/campsite/option/l10n.gohtml:7
#: web/templates/admin/campsite/option/l10n.gohtml:14
msgctxt "title"
msgid "Translate Campsite Type Option to %s"
msgstr "Traducción de la opción del tipo de alojamiento a %s"
#: web/templates/admin/campsite/index.gohtml:11
msgctxt "action"
msgid "Add Campsite"
@ -806,13 +752,13 @@ msgid "Type"
msgstr "Tipo"
#: web/templates/admin/campsite/index.gohtml:28
#: web/templates/admin/campsite/type/index.gohtml:59
#: web/templates/admin/campsite/type/index.gohtml:49
#: 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/campsite/type/index.gohtml:49
#: web/templates/admin/season/index.gohtml:49
msgid "No"
msgstr "No"
@ -834,46 +780,42 @@ msgid "New Campsite Type"
msgstr "Nuevo tipo de alojamiento"
#: web/templates/admin/campsite/type/form.gohtml:37
#: web/templates/admin/campsite/type/index.gohtml:30
#: web/templates/admin/campsite/type/index.gohtml:29
msgctxt "campsite type"
msgid "Active"
msgstr "Activo"
#: web/templates/admin/campsite/type/form.gohtml:57
#: web/templates/admin/campsite/type/form.gohtml:62
msgctxt "input"
msgid "Maximum number of campers"
msgstr "Número máximo de personas"
#: web/templates/admin/campsite/type/form.gohtml:67
#: web/templates/admin/campsite/type/form.gohtml:72
msgctxt "input"
msgid "Dogs allowed"
msgstr "Se permiten perros"
#: web/templates/admin/campsite/type/form.gohtml:87
#: web/templates/admin/campsite/type/form.gohtml:92
msgctxt "input"
msgid "Minimum number of nights"
msgstr "Número mínimos de noches"
#: web/templates/admin/campsite/type/form.gohtml:99
#: web/templates/admin/campsite/type/l10n.gohtml:32
#: web/templates/admin/campsite/type/form.gohtml:104
msgctxt "input"
msgid "Spiel"
msgstr "Introducción"
#: web/templates/admin/campsite/type/form.gohtml:106
#: web/templates/admin/campsite/type/l10n.gohtml:45
#: web/templates/admin/campsite/type/form.gohtml:117
msgctxt "input"
msgid "Info"
msgstr "Información"
#: web/templates/admin/campsite/type/form.gohtml:113
#: web/templates/admin/campsite/type/l10n.gohtml:58
#: web/templates/admin/campsite/type/form.gohtml:130
msgctxt "input"
msgid "Facilities"
msgstr "Equipamento"
#: web/templates/admin/campsite/type/form.gohtml:120
#: web/templates/admin/campsite/type/l10n.gohtml:71
#: web/templates/admin/campsite/type/form.gohtml:143
#: web/templates/admin/services/form.gohtml:60
#: web/templates/admin/services/l10n.gohtml:32
msgctxt "input"
@ -892,46 +834,40 @@ msgctxt "action"
msgid "Add Type"
msgstr "Añadir tipo"
#: web/templates/admin/campsite/type/index.gohtml:27
#: web/templates/admin/campsite/type/index.gohtml:26
msgctxt "header"
msgid "Features"
msgstr "Características"
#: web/templates/admin/campsite/type/index.gohtml:28
#: web/templates/admin/campsite/type/index.gohtml:27
msgctxt "header"
msgid "Options"
msgstr "Opciones"
#: web/templates/admin/campsite/type/index.gohtml:29
#: web/templates/admin/campsite/type/index.gohtml:28
msgctxt "header"
msgid "Carousel"
msgstr "Carrusel"
#: web/templates/admin/campsite/type/index.gohtml:51
#: web/templates/admin/campsite/type/index.gohtml:41
msgctxt "action"
msgid "Edit Features"
msgstr "Editar las características"
#: web/templates/admin/campsite/type/index.gohtml:54
#: web/templates/admin/campsite/type/index.gohtml:44
msgctxt "action"
msgid "Edit Options"
msgstr "Editar opciones"
#: web/templates/admin/campsite/type/index.gohtml:57
#: web/templates/admin/campsite/type/index.gohtml:47
msgctxt "action"
msgid "Edit Carousel"
msgstr "Editar el carrusel"
#: web/templates/admin/campsite/type/index.gohtml:66
#: web/templates/admin/campsite/type/index.gohtml:56
msgid "No campsite types added yet."
msgstr "No se ha añadido ningún tipo de alojamiento todavía."
#: 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ón de tipo de alojamiento a %s"
#: web/templates/admin/season/form.gohtml:8
#: web/templates/admin/season/form.gohtml:25
msgctxt "title"
@ -972,6 +908,14 @@ msgctxt "header"
msgid "Color"
msgstr "Color"
#: 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 "Traducciones"
#: web/templates/admin/season/index.gohtml:56
msgid "No seasons added yet."
msgstr "No se ha añadido ninguna temporada todavía."
@ -1278,25 +1222,24 @@ msgctxt "title"
msgid "Upload Media"
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
#: pkg/legal/admin.go:255 pkg/app/user.go:249 pkg/campsite/types/option.go:344
#: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:453
#: 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
#: pkg/legal/admin.go:256 pkg/campsite/types/option.go:345
#: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:454
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:223
msgctxt "input"
msgid "Slide image"
msgstr "Imagen de la diapositiva"
#: pkg/carousel/admin.go:286 pkg/campsite/types/carousel.go:243
#: pkg/carousel/admin.go:286 pkg/campsite/types/carousel.go:224
msgctxt "action"
msgid "Set slide image"
msgstr "Establecer la imagen de la diapositiva"
@ -1348,85 +1291,85 @@ msgstr "El archivo tiene que ser una imagen PNG o JPEG válida."
msgid "Access forbidden"
msgstr "Acceso prohibido"
#: pkg/campsite/types/option.go:354
#: pkg/campsite/types/option.go:348
msgid "Minimum can not be empty."
msgstr "No podéis dejar el mínimo en blanco."
#: pkg/campsite/types/option.go:355
#: pkg/campsite/types/option.go:349
msgid "Minimum must be an integer number."
msgstr "El valor de mínimo tiene que ser un número entero."
#: pkg/campsite/types/option.go:357
#: pkg/campsite/types/option.go:351
msgid "Minimum must be zero or greater."
msgstr "El valor de mínimo tiene que ser como mínimo cero."
#: pkg/campsite/types/option.go:360
#: pkg/campsite/types/option.go:354
msgid "Maximum can not be empty."
msgstr "No podéis dejar el máxmimo en blanco."
#: pkg/campsite/types/option.go:361
#: pkg/campsite/types/option.go:355
msgid "Maximum must be an integer number."
msgstr "El valor del máximo tiene que ser un número entero."
#: pkg/campsite/types/option.go:363
#: pkg/campsite/types/option.go:357
msgid "Maximum must be equal or greater than minimum."
msgstr "El valor del máximo tiene que ser igual o mayor al del mínimo."
#: pkg/campsite/types/option.go:367 pkg/campsite/types/admin.go:461
#: pkg/campsite/types/option.go:361 pkg/campsite/types/admin.go:467
msgid "Price per night can not be empty."
msgstr "No podéis dejar el precio por noche en blanco."
#: pkg/campsite/types/option.go:368 pkg/campsite/types/admin.go:462
#: pkg/campsite/types/option.go:362 pkg/campsite/types/admin.go:468
msgid "Price per night must be a decimal number."
msgstr "El precio por noche tien que ser un número decimal."
#: pkg/campsite/types/option.go:369 pkg/campsite/types/admin.go:463
#: pkg/campsite/types/option.go:363 pkg/campsite/types/admin.go:469
msgid "Price per night must be zero or greater."
msgstr "El precio por noche tiene que ser como mínimo cero."
#: pkg/campsite/types/feature.go:252 pkg/services/admin.go:265
#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:265
msgid "Selected icon is not valid."
msgstr "El icono escogido no es válido."
#: pkg/campsite/types/admin.go:323
#: pkg/campsite/types/admin.go:304
msgctxt "input"
msgid "Cover image"
msgstr "Imagen de portada"
#: pkg/campsite/types/admin.go:324
#: pkg/campsite/types/admin.go:305
msgctxt "action"
msgid "Set campsite type cover"
msgstr "Establecer la portada del tipo de alojamiento"
#: pkg/campsite/types/admin.go:450
#: pkg/campsite/types/admin.go:456
msgid "Cover image can not be empty."
msgstr "No podéis dejar la imagen de portada en blanco."
#: pkg/campsite/types/admin.go:451
#: pkg/campsite/types/admin.go:457
msgid "Cover image must be an image media type."
msgstr "La imagen de portada tiene que ser un medio de tipo imagen."
#: pkg/campsite/types/admin.go:455
#: pkg/campsite/types/admin.go:461
msgid "Maximum number of campers can not be empty."
msgstr "No podéis dejar el número máximo de personas en blanco."
#: pkg/campsite/types/admin.go:456
#: pkg/campsite/types/admin.go:462
msgid "Maximum number of campers must be an integer number."
msgstr "El número máximo de personas tiene que ser entero."
#: pkg/campsite/types/admin.go:457
#: pkg/campsite/types/admin.go:463
msgid "Maximum number of campers must be one or greater."
msgstr "El número máximo de personas no puede ser cero."
#: pkg/campsite/types/admin.go:466
#: pkg/campsite/types/admin.go:472
msgid "Minimum number of nights can not be empty."
msgstr "No podéis dejar el número mínimo de noches en blanco."
#: pkg/campsite/types/admin.go:467
#: pkg/campsite/types/admin.go:473
msgid "Minimum number of nights must be an integer."
msgstr "El número mínimo de noches tiene que ser entero."
#: pkg/campsite/types/admin.go:468
#: pkg/campsite/types/admin.go:474
msgid "Minimum number of nights must be one or greater."
msgstr "El número mínimo de noches no puede ser cero."
@ -1707,6 +1650,22 @@ msgstr "%s tiene que ser como mínimo %d."
msgid "%s must be at most %d."
msgstr "%s tiene que ser como máximo %d"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Feature to %s"
#~ msgstr "Traducción de la característica del tipo de alojamiento a %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Carousel Slide to %s"
#~ msgstr "Traducción de la diapositiva de carrusel del tipo de alojamiento a %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Option to %s"
#~ msgstr "Traducción de la opción del tipo de alojamiento a %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type to %s"
#~ msgstr "Traducción de tipo de alojamiento a %s"
#~ msgid "Starting from %s €/night"
#~ msgstr "A partir de %s €/noche"

221
po/fr.po
View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-01-10 19:33+0100\n"
"POT-Creation-Date: 2024-01-10 21:49+0100\n"
"PO-Revision-Date: 2023-12-20 10:13+0100\n"
"Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n"
"Language-Team: French <traduc@traduc.org>\n"
@ -132,8 +132,8 @@ msgid "Calendar"
msgstr "Calendrier"
#: web/templates/public/campsite/type.gohtml:73
#: web/templates/admin/campsite/option/form.gohtml:58
#: web/templates/admin/campsite/type/form.gohtml:73
#: web/templates/admin/campsite/option/form.gohtml:63
#: web/templates/admin/campsite/type/form.gohtml:78
msgctxt "title"
msgid "Prices"
msgstr "Prix"
@ -420,11 +420,8 @@ msgstr "Slug"
#: 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
@ -441,11 +438,11 @@ msgstr "Contenu"
#: 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/feature/form.gohtml:67
#: web/templates/admin/campsite/carousel/form.gohtml:52
#: 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/campsite/option/form.gohtml:83
#: web/templates/admin/campsite/type/form.gohtml:158
#: web/templates/admin/season/form.gohtml:64
#: web/templates/admin/services/form.gohtml:69
#: web/templates/admin/media/form.gohtml:35
@ -455,11 +452,11 @@ 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/feature/form.gohtml:69
#: web/templates/admin/campsite/carousel/form.gohtml:54
#: 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/campsite/option/form.gohtml:85
#: web/templates/admin/campsite/type/form.gohtml:160
#: web/templates/admin/season/form.gohtml:66
#: web/templates/admin/services/form.gohtml:71
msgctxt "action"
@ -506,7 +503,6 @@ msgstr "Nouveau toboggan carrousel"
#: 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 "Légende"
@ -518,14 +514,6 @@ msgid "Translate Carousel Slide to %s"
msgstr "Traduire la diapositive Carousel en %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
@ -533,14 +521,6 @@ msgid "Source:"
msgstr "Source :"
#: 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
@ -549,10 +529,6 @@ msgid "Translation:"
msgstr "Traduction :"
#: 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"
@ -615,28 +591,10 @@ msgctxt "action"
msgid "Add Feature"
msgstr "Ajouter une fonctionnalité"
#: web/templates/admin/campsite/feature/index.gohtml:27
#: 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 "Traductions"
#: web/templates/admin/campsite/feature/index.gohtml:53
#: web/templates/admin/campsite/feature/index.gohtml:43
msgid "No campsite type features added yet."
msgstr "Aucune fonctionnalité de type camping na encore été ajoutée."
#: 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 "Traduire Caractéristique de type de camping en %s"
#: web/templates/admin/campsite/carousel/form.gohtml:8
#: web/templates/admin/campsite/carousel/form.gohtml:25
msgctxt "title"
@ -676,7 +634,7 @@ msgctxt "header"
msgid "Caption"
msgstr "Légende"
#: web/templates/admin/campsite/carousel/index.gohtml:28
#: web/templates/admin/campsite/carousel/index.gohtml:27
#: web/templates/admin/services/index.gohtml:28
#: web/templates/admin/services/index.gohtml:74
#: web/templates/admin/home/index.gohtml:28
@ -684,13 +642,13 @@ msgctxt "header"
msgid "Actions"
msgstr "Actions"
#: web/templates/admin/campsite/carousel/index.gohtml:32
#: web/templates/admin/campsite/carousel/index.gohtml:31
#: 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 "Êtes-vous sûr de vouloir supprimer cette diapositive ?"
#: web/templates/admin/campsite/carousel/index.gohtml:55
#: web/templates/admin/campsite/carousel/index.gohtml:45
#: web/templates/admin/services/index.gohtml:54
#: web/templates/admin/services/index.gohtml:93
#: web/templates/admin/home/index.gohtml:54
@ -698,18 +656,12 @@ msgctxt "action"
msgid "Delete"
msgstr "Supprimer"
#: web/templates/admin/campsite/carousel/index.gohtml:64
#: web/templates/admin/campsite/carousel/index.gohtml:54
#: web/templates/admin/services/index.gohtml:63
#: web/templates/admin/home/index.gohtml:63
msgid "No slides added yet."
msgstr "Aucune diapositive na encore été ajoutée."
#: 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 "Convertir Glissière de carrousel de type camping en %s"
#: web/templates/admin/campsite/form.gohtml:8
#: web/templates/admin/campsite/form.gohtml:25
msgctxt "title"
@ -754,18 +706,18 @@ msgctxt "title"
msgid "New Campsite Type Option"
msgstr "Nouvelle option de type demplacement de camping"
#: web/templates/admin/campsite/option/form.gohtml:42
#: web/templates/admin/campsite/option/form.gohtml:47
msgctxt "input"
msgid "Minimum"
msgstr "Minimum"
#: web/templates/admin/campsite/option/form.gohtml:50
#: web/templates/admin/campsite/option/form.gohtml:55
msgctxt "input"
msgid "Maximum"
msgstr "Maximum"
#: web/templates/admin/campsite/option/form.gohtml:64
#: web/templates/admin/campsite/type/form.gohtml:79
#: web/templates/admin/campsite/option/form.gohtml:69
#: web/templates/admin/campsite/type/form.gohtml:84
msgctxt "input"
msgid "Price per night"
msgstr "Prix par nuit"
@ -781,16 +733,10 @@ msgctxt "action"
msgid "Add Option"
msgstr "Ajouter une option"
#: web/templates/admin/campsite/option/index.gohtml:52
#: web/templates/admin/campsite/option/index.gohtml:42
msgid "No campsite type options added yet."
msgstr "Aucune option de type de camping na encore été ajoutée."
#: 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 "Traduire loption Type de camping en %s"
#: web/templates/admin/campsite/index.gohtml:11
msgctxt "action"
msgid "Add Campsite"
@ -807,13 +753,13 @@ msgid "Type"
msgstr "Type"
#: web/templates/admin/campsite/index.gohtml:28
#: web/templates/admin/campsite/type/index.gohtml:59
#: web/templates/admin/campsite/type/index.gohtml:49
#: web/templates/admin/season/index.gohtml:49
msgid "Yes"
msgstr "Oui"
#: web/templates/admin/campsite/index.gohtml:28
#: web/templates/admin/campsite/type/index.gohtml:59
#: web/templates/admin/campsite/type/index.gohtml:49
#: web/templates/admin/season/index.gohtml:49
msgid "No"
msgstr "Non"
@ -835,46 +781,42 @@ msgid "New Campsite Type"
msgstr "Nouveau type demplacement de camping"
#: web/templates/admin/campsite/type/form.gohtml:37
#: web/templates/admin/campsite/type/index.gohtml:30
#: web/templates/admin/campsite/type/index.gohtml:29
msgctxt "campsite type"
msgid "Active"
msgstr "Actif"
#: web/templates/admin/campsite/type/form.gohtml:57
#: web/templates/admin/campsite/type/form.gohtml:62
msgctxt "input"
msgid "Maximum number of campers"
msgstr "Nombre maximum de campeurs"
#: web/templates/admin/campsite/type/form.gohtml:67
#: web/templates/admin/campsite/type/form.gohtml:72
msgctxt "input"
msgid "Dogs allowed"
msgstr "Chiens acceptés"
#: web/templates/admin/campsite/type/form.gohtml:87
#: web/templates/admin/campsite/type/form.gohtml:92
msgctxt "input"
msgid "Minimum number of nights"
msgstr "Nombre minimum de nuits"
#: web/templates/admin/campsite/type/form.gohtml:99
#: web/templates/admin/campsite/type/l10n.gohtml:32
#: web/templates/admin/campsite/type/form.gohtml:104
msgctxt "input"
msgid "Spiel"
msgstr "Boniment"
#: web/templates/admin/campsite/type/form.gohtml:106
#: web/templates/admin/campsite/type/l10n.gohtml:45
#: web/templates/admin/campsite/type/form.gohtml:117
msgctxt "input"
msgid "Info"
msgstr "Info"
#: web/templates/admin/campsite/type/form.gohtml:113
#: web/templates/admin/campsite/type/l10n.gohtml:58
#: web/templates/admin/campsite/type/form.gohtml:130
msgctxt "input"
msgid "Facilities"
msgstr "Installations"
#: web/templates/admin/campsite/type/form.gohtml:120
#: web/templates/admin/campsite/type/l10n.gohtml:71
#: web/templates/admin/campsite/type/form.gohtml:143
#: web/templates/admin/services/form.gohtml:60
#: web/templates/admin/services/l10n.gohtml:32
msgctxt "input"
@ -893,46 +835,40 @@ msgctxt "action"
msgid "Add Type"
msgstr "Ajouter un type"
#: web/templates/admin/campsite/type/index.gohtml:27
#: web/templates/admin/campsite/type/index.gohtml:26
msgctxt "header"
msgid "Features"
msgstr "Caractéristiques"
#: web/templates/admin/campsite/type/index.gohtml:28
#: web/templates/admin/campsite/type/index.gohtml:27
msgctxt "header"
msgid "Options"
msgstr "Options"
#: web/templates/admin/campsite/type/index.gohtml:29
#: web/templates/admin/campsite/type/index.gohtml:28
msgctxt "header"
msgid "Carousel"
msgstr "Carrousel"
#: web/templates/admin/campsite/type/index.gohtml:51
#: web/templates/admin/campsite/type/index.gohtml:41
msgctxt "action"
msgid "Edit Features"
msgstr "Edit Caractéristiques"
#: web/templates/admin/campsite/type/index.gohtml:54
#: web/templates/admin/campsite/type/index.gohtml:44
msgctxt "action"
msgid "Edit Options"
msgstr "Modifier les options"
#: web/templates/admin/campsite/type/index.gohtml:57
#: web/templates/admin/campsite/type/index.gohtml:47
msgctxt "action"
msgid "Edit Carousel"
msgstr "Modifier le carrousel"
#: web/templates/admin/campsite/type/index.gohtml:66
#: web/templates/admin/campsite/type/index.gohtml:56
msgid "No campsite types added yet."
msgstr "Aucun type demplacement na encore été ajouté."
#: 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 "Traduire Type de camping en %s"
#: web/templates/admin/season/form.gohtml:8
#: web/templates/admin/season/form.gohtml:25
msgctxt "title"
@ -973,6 +909,14 @@ msgctxt "header"
msgid "Color"
msgstr "Couleur"
#: 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 "Traductions"
#: web/templates/admin/season/index.gohtml:56
msgid "No seasons added yet."
msgstr "Aucune saison na encore été ajoutée."
@ -1279,25 +1223,24 @@ msgctxt "title"
msgid "Upload Media"
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
#: pkg/legal/admin.go:255 pkg/app/user.go:249 pkg/campsite/types/option.go:344
#: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:453
#: 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
#: pkg/legal/admin.go:256 pkg/campsite/types/option.go:345
#: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:454
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:223
msgctxt "input"
msgid "Slide image"
msgstr "Image du diaporama"
#: pkg/carousel/admin.go:286 pkg/campsite/types/carousel.go:243
#: pkg/carousel/admin.go:286 pkg/campsite/types/carousel.go:224
msgctxt "action"
msgid "Set slide image"
msgstr "Définir limage de la diapositive"
@ -1349,85 +1292,85 @@ msgstr "Le fichier doit être une image PNG ou JPEG valide."
msgid "Access forbidden"
msgstr "Accès interdit"
#: pkg/campsite/types/option.go:354
#: pkg/campsite/types/option.go:348
msgid "Minimum can not be empty."
msgstr "Le minimum ne peut pas être vide."
#: pkg/campsite/types/option.go:355
#: pkg/campsite/types/option.go:349
msgid "Minimum must be an integer number."
msgstr "Le minimum doit être un nombre entier."
#: pkg/campsite/types/option.go:357
#: pkg/campsite/types/option.go:351
msgid "Minimum must be zero or greater."
msgstr "Le minimum doit être égal ou supérieur à zéro."
#: pkg/campsite/types/option.go:360
#: pkg/campsite/types/option.go:354
msgid "Maximum can not be empty."
msgstr "Le maximum ne peut pas être vide."
#: pkg/campsite/types/option.go:361
#: pkg/campsite/types/option.go:355
msgid "Maximum must be an integer number."
msgstr "Le maximum doit être un nombre entier."
#: pkg/campsite/types/option.go:363
#: pkg/campsite/types/option.go:357
msgid "Maximum must be equal or greater than minimum."
msgstr "Le maximum doit être égal ou supérieur au minimum."
#: pkg/campsite/types/option.go:367 pkg/campsite/types/admin.go:461
#: pkg/campsite/types/option.go:361 pkg/campsite/types/admin.go:467
msgid "Price per night can not be empty."
msgstr "Le prix par nuit ne peut pas être vide."
#: pkg/campsite/types/option.go:368 pkg/campsite/types/admin.go:462
#: pkg/campsite/types/option.go:362 pkg/campsite/types/admin.go:468
msgid "Price per night must be a decimal number."
msgstr "Le prix par nuit doit être un nombre décimal."
#: pkg/campsite/types/option.go:369 pkg/campsite/types/admin.go:463
#: pkg/campsite/types/option.go:363 pkg/campsite/types/admin.go:469
msgid "Price per night must be zero or greater."
msgstr "Le prix par nuit doit être égal ou supérieur."
#: pkg/campsite/types/feature.go:252 pkg/services/admin.go:265
#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:265
msgid "Selected icon is not valid."
msgstr "Licône sélectionnée nest pas valide."
#: pkg/campsite/types/admin.go:323
#: pkg/campsite/types/admin.go:304
msgctxt "input"
msgid "Cover image"
msgstr "Image de couverture"
#: pkg/campsite/types/admin.go:324
#: pkg/campsite/types/admin.go:305
msgctxt "action"
msgid "Set campsite type cover"
msgstr "Définir une couverture type camping"
#: pkg/campsite/types/admin.go:450
#: pkg/campsite/types/admin.go:456
msgid "Cover image can not be empty."
msgstr "Limage de couverture ne peut pas être vide."
#: pkg/campsite/types/admin.go:451
#: pkg/campsite/types/admin.go:457
msgid "Cover image must be an image media type."
msgstr "Limage de couverture doit être de type média dimage."
#: pkg/campsite/types/admin.go:455
#: pkg/campsite/types/admin.go:461
msgid "Maximum number of campers can not be empty."
msgstr "Le nombre maximum de campeurs ne peut pas être vide."
#: pkg/campsite/types/admin.go:456
#: pkg/campsite/types/admin.go:462
msgid "Maximum number of campers must be an integer number."
msgstr "Le nombre maximum de campeurs doit être un nombre entier."
#: pkg/campsite/types/admin.go:457
#: pkg/campsite/types/admin.go:463
msgid "Maximum number of campers must be one or greater."
msgstr "Le nombre maximum de campeurs doit être égal ou supérieur à un campeur."
#: pkg/campsite/types/admin.go:466
#: pkg/campsite/types/admin.go:472
msgid "Minimum number of nights can not be empty."
msgstr "Le nombre minimum de nuits ne peut pas être vide."
#: pkg/campsite/types/admin.go:467
#: pkg/campsite/types/admin.go:473
msgid "Minimum number of nights must be an integer."
msgstr "Le nombre minimum de nuits doit être un entier."
#: pkg/campsite/types/admin.go:468
#: pkg/campsite/types/admin.go:474
msgid "Minimum number of nights must be one or greater."
msgstr "Le nombre minimum de nuits doit être supérieur ou égal à une nuit."
@ -1708,6 +1651,22 @@ msgstr "%s doit être %d ou plus."
msgid "%s must be at most %d."
msgstr "%s doit être tout au plus %d."
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Feature to %s"
#~ msgstr "Traduire Caractéristique de type de camping en %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Carousel Slide to %s"
#~ msgstr "Convertir Glissière de carrousel de type camping en %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type Option to %s"
#~ msgstr "Traduire loption Type de camping en %s"
#~ msgctxt "title"
#~ msgid "Translate Campsite Type to %s"
#~ msgstr "Traduire Type de camping en %s"
#~ msgid "Starting from %s €/night"
#~ msgstr "À partir de %s €/nuit"

View File

@ -28,17 +28,22 @@
{{ end }}
</h2>
{{ CSRFInput }}
<fieldset>
<fieldset x-data="{ lang: '{{ .DefaultLang }}' }">
{{ with .Media -}}
{{ template "media-picker" . }}
{{- end }}
{{ with .Caption -}}
<label>
{{( pgettext "Caption" "input")}}<br>
<input type="text" name="{{ .Name }}" value="{{ .Val }}"
{{ template "error-attrs" . }}><br>
</label>
{{ template "error-message" . }}
<fieldset>
<legend>{{( pgettext "Caption" "input")}}</legend>
{{ template "lang-selector" . }}
{{ 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 }}
</fieldset>
<footer>

View File

@ -24,7 +24,6 @@
<tr>
<th scope="col">{{( pgettext "Image" "header" )}}</th>
<th scope="col">{{( pgettext "Caption" "header" )}}</th>
<th scope="col">{{( pgettext "Translations" "header" )}}</th>
<th scope="col">{{( pgettext "Actions" "header" )}}</th>
</tr>
</thead>
@ -39,15 +38,6 @@
alt=""></a>
</td>
<td><a href="/admin/campsites/types/{{ $.TypeSlug }}/slides/{{ .ID }}">{{ .Caption }}</a></td>
<td>
{{ range .Translations }}
<a
{{ if .Missing }}
class="missing-translation"
{{ end }}
href="/admin/campsites/types/{{ $.TypeSlug }}/slides/{{ $slide.ID }}/{{ .Language }}">{{ .Endonym }}</a>
{{ end }}
</td>
<td>
<form data-hx-delete="/admin/campsites/types/{{ $.TypeSlug }}/slides/{{ .ID }}"
data-hx-confirm="{{ $confirm }}"

View File

@ -1,35 +0,0 @@
<!--
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/campsite/types.slideL10nForm*/ -}}
{{printf (pgettext "Translate Campsite Type Carousel Slide to %s" "title") .Locale.Endonym }}
{{- end }}
{{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.slideL10nForm*/ -}}
<form data-hx-put="/admin/campsites/types/{{ .TypeSlug }}/slides/{{ .MediaID }}/{{ .Locale.Language }}">
<h2>
{{printf (pgettext "Translate Campsite Type Carousel Slide to %s" "title") .Locale.Endonym }}
</h2>
{{ CSRFInput }}
<fieldset>
{{ with .Caption -}}
<fieldset>
<legend>{{( pgettext "Caption" "input")}}</legend>
{{( gettext "Source:" )}} {{ .Source }}<br>
<label>
{{( pgettext "Translation:" "input" )}}
<input type="text" name="{{ .Name }}" value="{{ .Val }}"
{{ template "error-attrs" . }}><br>
</label>
{{ template "error-message" . }}
</fieldset>
{{- end }}
</fieldset>
<footer>
<button type="submit">{{( pgettext "Translate" "action" )}}</button>
</footer>
</form>
{{- end }}

View File

@ -28,7 +28,7 @@
{{ end }}
</h2>
{{ CSRFInput }}
<fieldset>
<fieldset x-data="{ lang: '{{ .DefaultLang }}' }">
{{ with $field := .Icon -}}
<fieldset class="icon-input">
<legend>{{( pgettext "Icon" "input")}}</legend>
@ -48,12 +48,17 @@
</fieldset>
{{- end }}
{{ with .Name -}}
<label>
{{( pgettext "Name" "input")}}<br>
<input type="text" name="{{ .Name }}" value="{{ .Val }}"
required {{ template "error-attrs" . }}><br>
</label>
{{ template "error-message" . }}
<fieldset>
<legend>{{( pgettext "Name" "input")}}</legend>
{{ template "lang-selector" . }}
{{ 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 }}
</fieldset>
<footer>

View File

@ -24,7 +24,6 @@
<tr>
<th scope="col" style="width: 1.5em"></th>
<th scope="col">{{( pgettext "Name" "header" )}}</th>
<th scope="col">{{( pgettext "Translations" "header" )}}</th>
</tr>
</thead>
<tbody>
@ -35,15 +34,6 @@
<input type="hidden" name="feature_id" value="{{ .ID }}">
</td>
<td class="icon_{{ .Icon }}"><a href="{{ .URL }}">{{ .Name }}</a></td>
<td>
{{ range .Translations }}
<a
{{ if .Missing }}
class="missing-translation"
{{ end }}
href="{{ .URL }}">{{ .Endonym }}</a>
{{ end }}
</td>
</tr>
{{- end }}
</tbody>

View File

@ -1,35 +0,0 @@
<!--
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/campsite/types.featureL10nForm*/ -}}
{{printf (pgettext "Translate Campsite Type Feature to %s" "title") .Locale.Endonym }}
{{- end }}
{{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.featureL10nForm*/ -}}
<form data-hx-put="/admin/campsites/types/{{ .TypeSlug }}/features/{{ .ID }}/{{ .Locale.Language }}">
<h2>
{{printf (pgettext "Translate Campsite Type Feature to %s" "title") .Locale.Endonym }}
</h2>
{{ CSRFInput }}
<fieldset>
{{ with .Name -}}
<fieldset>
<legend>{{( pgettext "Name" "input")}}</legend>
{{( gettext "Source:" )}} {{ .Source }}<br>
<label>
{{( pgettext "Translation:" "input" )}}
<input type="text" name="{{ .Name }}" value="{{ .Val }}"
required {{ template "error-attrs" . }}><br>
</label>
{{ template "error-message" . }}
</fieldset>
{{- end }}
</fieldset>
<footer>
<button type="submit">{{( pgettext "Translate" "action" )}}</button>
</footer>
</form>
{{- end }}

View File

@ -28,14 +28,19 @@
{{ end }}
</h2>
{{ CSRFInput }}
<fieldset>
<fieldset x-data="{ lang: '{{ .DefaultLang }}' }">
{{ with .Name -}}
<label>
{{( pgettext "Name" "input")}}<br>
<input type="text" name="{{ .Name }}" value="{{ .Val }}"
required {{ template "error-attrs" . }}><br>
</label>
{{ template "error-message" . }}
<fieldset>
<legend>{{( pgettext "Name" "input")}}</legend>
{{ template "lang-selector" . }}
{{ 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 .Min -}}
<label>

View File

@ -23,7 +23,6 @@
<thead>
<tr>
<th scope="col">{{( pgettext "Name" "header" )}}</th>
<th scope="col">{{( pgettext "Translations" "header" )}}</th>
</tr>
</thead>
<tbody>
@ -34,15 +33,6 @@
<input type="hidden" name="option_id" value="{{ .ID }}">
<a href="{{ .URL }}">{{ .Name }}</a>
</td>
<td>
{{ range .Translations }}
<a
{{ if .Missing }}
class="missing-translation"
{{ end }}
href="{{ .URL }}">{{ .Endonym }}</a>
{{ end }}
</td>
</tr>
{{- end }}
</tbody>

View File

@ -1,35 +0,0 @@
<!--
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/campsite/types.optionL10nForm*/ -}}
{{printf (pgettext "Translate Campsite Type Option to %s" "title") .Locale.Endonym }}
{{- end }}
{{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.optionL10nForm*/ -}}
<form data-hx-put="/admin/campsites/types/{{ .TypeSlug }}/options/{{ .ID }}/{{ .Locale.Language }}">
<h2>
{{printf (pgettext "Translate Campsite Type Option to %s" "title") .Locale.Endonym }}
</h2>
{{ CSRFInput }}
<fieldset>
{{ with .Name -}}
<fieldset>
<legend>{{( pgettext "Name" "input")}}</legend>
{{( gettext "Source:" )}} {{ .Source }}<br>
<label>
{{( pgettext "Translation:" "input" )}}
<input type="text" name="{{ .Name }}" value="{{ .Val }}"
required {{ template "error-attrs" . }}><br>
</label>
{{ template "error-message" . }}
</fieldset>
{{- end }}
</fieldset>
<footer>
<button type="submit">{{( pgettext "Translate" "action" )}}</button>
</footer>
</form>
{{- end }}

View File

@ -28,7 +28,7 @@
{{ end }}
</h2>
{{ CSRFInput }}
<fieldset>
<fieldset x-data="{ lang: '{{ .DefaultLang }}' }">
{{ if .Slug }}
{{ with .Active -}}
<label>
@ -42,12 +42,17 @@
<input type="hidden" name="{{ .Active.Name }}" value="true">
{{ end }}
{{ with .Name -}}
<label>
{{( pgettext "Name" "input")}}<br>
<input type="text" name="{{ .Name }}" value="{{ .Val }}"
required {{ template "error-attrs" . }}><br>
</label>
{{ template "error-message" . }}
<fieldset>
<legend>{{( pgettext "Name" "input")}}</legend>
{{ template "lang-selector" . }}
{{ 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 .Media -}}
{{ template "media-picker" . }}
@ -95,32 +100,56 @@
</fieldset>
{{- end }}
{{ with .Spiel -}}
<label>
{{( pgettext "Spiel" "input")}}<br>
<textarea class="html" name="{{ .Name }}" {{ template "error-attrs" . }}>{{ .Val }}</textarea><br>
</label>
{{ template "error-message" . }}
<fieldset>
<legend>{{( pgettext "Spiel" "input")}}</legend>
{{ template "lang-selector" . }}
{{ 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 }}
{{ with .Info -}}
<label>
{{( pgettext "Info" "input")}}<br>
<textarea class="html" name="{{ .Name }}" {{ template "error-attrs" . }}>{{ .Val }}</textarea><br>
</label>
{{ template "error-message" . }}
<fieldset>
<legend>{{( pgettext "Info" "input")}}<br></legend>
{{ template "lang-selector" . }}
{{ range $lang, $input := . -}}
<label x-cloak x-show="lang === '{{ $lang }}'"><span>{{ $lang }}</span><br>
<textarea class="html"
name="{{ .Name }}" {{ template "error-attrs" . }}>{{ .Val }}</textarea><br>
</label>
{{- end }}
{{ template "error-message" . }}
</fieldset>
{{- end }}
{{ with .Facilities -}}
<label>
{{( pgettext "Facilities" "input")}}<br>
<textarea class="html" name="{{ .Name }}" {{ template "error-attrs" . }}>{{ .Val }}</textarea><br>
</label>
{{ template "error-message" . }}
<fieldset>
<legend>{{( pgettext "Facilities" "input")}}<br></legend>
{{ template "lang-selector" . }}
{{ range $lang, $input := . -}}
<label x-cloak x-show="lang === '{{ $lang }}'"><span>{{ $lang }}</span><br>
<textarea class="html"
name="{{ .Name }}" {{ template "error-attrs" . }}>{{ .Val }}</textarea><br>
</label>
{{- end }}
{{ template "error-message" . }}
</fieldset>
{{- end }}
{{ with .Description -}}
<label>
{{( pgettext "Description" "input")}}<br>
<textarea class="html" name="{{ .Name }}" {{ template "error-attrs" . }}>{{ .Val }}</textarea><br>
</label>
{{ template "error-message" . }}
<fieldset>
<legend>{{( pgettext "Description" "input")}}<br></legend>
{{ template "lang-selector" . }}
{{ range $lang, $input := . -}}
<label x-cloak x-show="lang === '{{ $lang }}'"><span>{{ $lang }}</span><br>
<textarea class="html"
name="{{ .Name }}" {{ template "error-attrs" . }}>{{ .Val }}</textarea><br>
</label>
{{- end }}
{{ template "error-message" . }}
</fieldset>
{{- end }}
</fieldset>
<footer>

View File

@ -23,7 +23,6 @@
<thead>
<tr>
<th scope="col">{{( pgettext "Name" "header" )}}</th>
<th scope="col">{{( pgettext "Translations" "header" )}}</th>
<th scope="col">{{( pgettext "Features" "header" )}}</th>
<th scope="col">{{( pgettext "Options" "header" )}}</th>
<th scope="col">{{( pgettext "Carousel" "header" )}}</th>
@ -38,15 +37,6 @@
<input type="hidden" name="slug" value="{{ .Slug }}">
<a href="/admin/campsites/types/{{ .Slug }}">{{ .Name }}</a>
</td>
<td>
{{ range .Translations }}
<a
{{ if .Missing }}
class="missing-translation"
{{ end }}
href="/admin/campsites/types/{{ $type.Slug }}/{{ .Language }}">{{ .Endonym }}</a>
{{ end }}
</td>
<td>
<a href="/admin/campsites/types/{{ .Slug }}/features">{{( pgettext "Edit Features" "action" )}}</a>
</td>

View File

@ -1,87 +0,0 @@
<!--
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/campsite/types.typeL10nForm*/ -}}
{{printf (pgettext "Translate Campsite Type to %s" "title") .Locale.Endonym }}
{{- end }}
{{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.typeL10nForm*/ -}}
<form data-hx-put="/admin/campsites/types/{{ .Slug }}/{{ .Locale.Language }}">
<h2>
{{printf (pgettext "Translate Campsite Type to %s" "title") .Locale.Endonym }}
</h2>
{{ CSRFInput }}
<fieldset>
{{ with .Name -}}
<fieldset>
<legend>{{( pgettext "Name" "input")}}</legend>
{{( gettext "Source:" )}} {{ .Source }}<br>
<label>
{{( pgettext "Translation:" "input" )}}
<input type="text" name="{{ .Name }}" value="{{ .Val }}"
required {{ template "error-attrs" . }}><br>
</label>
{{ template "error-message" . }}
</fieldset>
{{- end }}
{{ with .Spiel -}}
<fieldset>
<legend{{( pgettext "Spiel" "input")}}></legend>
{{( gettext "Source:" )}}<br>
{{ .Source | raw }}<br>
<label>
{{( pgettext "Translation:" "input" )}}
<textarea class="html"
name="{{ .Name }}" {{ template "error-attrs" . }}>{{ .Val }}</textarea><br>
</label>
{{ template "error-message" . }}
</fieldset>
{{- end }}
{{ with .Info -}}
<fieldset>
<legend{{( pgettext "Info" "input")}}></legend>
{{( gettext "Source:" )}}<br>
{{ .Source | raw }}<br>
<label>
{{( pgettext "Translation:" "input" )}}
<textarea class="html"
name="{{ .Name }}" {{ template "error-attrs" . }}>{{ .Val }}</textarea><br>
</label>
{{ template "error-message" . }}
</fieldset>
{{- end }}
{{ with .Facilities -}}
<fieldset>
<legend{{( pgettext "Facilities" "input")}}></legend>
{{( gettext "Source:" )}}<br>
{{ .Source | raw }}<br>
<label>
{{( pgettext "Translation:" "input" )}}
<textarea class="html"
name="{{ .Name }}" {{ template "error-attrs" . }}>{{ .Val }}</textarea><br>
</label>
{{ template "error-message" . }}
</fieldset>
{{- end }}
{{ with .Description -}}
<fieldset>
<legend{{( pgettext "Description" "input")}}></legend>
{{( gettext "Source:" )}}<br>
{{ .Source | raw }}<br>
<label>
{{( pgettext "Translation:" "input" )}}
<textarea class="html"
name="{{ .Name }}" {{ template "error-attrs" . }}>{{ .Val }}</textarea><br>
</label>
{{ template "error-message" . }}
</fieldset>
{{- end }}
</fieldset>
<footer>
<button type="submit">{{( pgettext "Translate" "action" )}}</button>
</footer>
</form>
{{- end }}

View File

@ -41,3 +41,12 @@
{{ template "error-message" . }}
</fieldset>
{{- end }}
{{ define "lang-selector" -}}
<div class="lang-selector" role="toolbar">
{{ range $lang, $input := . -}}
<button :aria-pressed="lang === '{{ $lang }}'"
@click.prevent="lang = '{{ $lang }}'">{{ $lang }}</button>
{{- end }}
</div>
{{- end }}