diff --git a/pkg/campsite/types/admin.go b/pkg/campsite/types/admin.go index 99653c8..3b30ad7 100644 --- a/pkg/campsite/types/admin.go +++ b/pkg/campsite/types/admin.go @@ -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 { diff --git a/pkg/campsite/types/carousel.go b/pkg/campsite/types/carousel.go index 81d8a6b..a273b2c 100644 --- a/pkg/campsite/types/carousel.go +++ b/pkg/campsite/types/carousel.go @@ -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) } diff --git a/pkg/campsite/types/feature.go b/pkg/campsite/types/feature.go index 8be62a0..a0fff7c 100644 --- a/pkg/campsite/types/feature.go +++ b/pkg/campsite/types/feature.go @@ -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 } diff --git a/pkg/campsite/types/l10n.go b/pkg/campsite/types/l10n.go deleted file mode 100644 index 285cff5..0000000 --- a/pkg/campsite/types/l10n.go +++ /dev/null @@ -1,270 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 jordi fita mas - * 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 -} diff --git a/pkg/campsite/types/option.go b/pkg/campsite/types/option.go index a305fe5..954ad2d 100644 --- a/pkg/campsite/types/option.go +++ b/pkg/campsite/types/option.go @@ -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.")) { diff --git a/pkg/database/funcs.go b/pkg/database/funcs.go index 0428b34..9692019 100644 --- a/pkg/database/funcs.go +++ b/pkg/database/funcs.go @@ -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 != "" { diff --git a/po/ca.po b/po/ca.po index 592d63b..683e02c 100644 --- a/po/ca.po +++ b/po/ca.po @@ -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 \n" "Language-Team: Catalan \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 s’ha afegit cap característica al tipus d’allotjament 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 d’allotjament 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 s’ha 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 d’allotjament 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 d’allotjament" -#: 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 s’ha afegit cap opció al tipus d’allotjament 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 d’allotjament 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 d’allotjament" #: 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 s’ha afegit cap tipus d’allotjament 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 d’allotjament 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 s’ha 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 d’allotjament" -#: 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 d’allotjament a %s" + +#~ msgctxt "title" +#~ msgid "Translate Campsite Type Carousel Slide to %s" +#~ msgstr "Traducció de la diapositiva del carrusel del tipus d’allotjament a %s" + +#~ msgctxt "title" +#~ msgid "Translate Campsite Type Option to %s" +#~ msgstr "Traducció de la opció del tipus d’allotjament a %s" + +#~ msgctxt "title" +#~ msgid "Translate Campsite Type to %s" +#~ msgstr "Traducció del tipus d’allotjament a %s" + #~ msgid "Starting from %s €/night" #~ msgstr "A partir de %s €/nit" diff --git a/po/es.po b/po/es.po index 055dc1c..7713432 100644 --- a/po/es.po +++ b/po/es.po @@ -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 \n" "Language-Team: Spanish \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" diff --git a/po/fr.po b/po/fr.po index c6c5091..fd9905f 100644 --- a/po/fr.po +++ b/po/fr.po @@ -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 \n" "Language-Team: French \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 n’a 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 n’a 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 d’emplacement 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 n’a 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 l’option 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 d’emplacement 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 d’emplacement n’a 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 n’a 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 l’image 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 "L’icône sélectionnée n’est 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 "L’image 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 "L’image de couverture doit être de type média d’image." -#: 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 l’option 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" diff --git a/web/templates/admin/campsite/carousel/form.gohtml b/web/templates/admin/campsite/carousel/form.gohtml index 4faf41e..a6d1e42 100644 --- a/web/templates/admin/campsite/carousel/form.gohtml +++ b/web/templates/admin/campsite/carousel/form.gohtml @@ -28,17 +28,22 @@ {{ end }} {{ CSRFInput }} -
+
{{ with .Media -}} {{ template "media-picker" . }} {{- end }} {{ with .Caption -}} - - {{ template "error-message" . }} +
+ {{( pgettext "Caption" "input")}} + {{ template "lang-selector" . }} + {{ range $lang, $input := . -}} + + {{- end }} + {{ template "error-message" . }} +
{{- end }}