Split templates and handlers into admin and public
I need to check that the user is an employee (or admin) in administration handlers, but i do not want to do it for each handler, because i am bound to forget it. Thus, i added the /admin sub-path for these resources. The public-facing web is the rest of the resources outside /admin, but for now there is only home, to test whether it works as expected or not. The public-facing web can not relay on the user’s language settings, as the guest user has no way to set that. I would be happy to just use the Accept-Language header for that, but apparently Google does not use that header[0], and they give four alternatives: a country-specific domain, a subdomain with a generic top-level domain (gTLD), subdirectories with a gTLD, or URL parameters (e.g., site.com?loc=de). Of the four, Google does not recommend URL parameters, and the customer is already using subdirectories with the current site, therefor that’s what i have chosen. Google also tells me that it is a very good idea to have links between localized version of the same resources, either with <link> elements, Link HTTP response headers, or a sitemap file[1]; they are all equivalent in the eyes of Google. I have choosen the Link response headers way, because for that i can simply “augment” ResponseHeader to automatically add these headers when the response status is 2xx, otherwise i would need to pass down the original URL path until it reaches the template. Even though Camper is supposed to be a “generic”, multi-company application, i think i will stick to the easiest route and write the templates for just the “first” customer. [0]: https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites [1]: https://developers.google.com/search/docs/specialty/international/localized-versions
This commit is contained in:
parent
9349cda5f6
commit
e128680e9a
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/campsite"
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||||
|
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
type adminHandler struct {
|
||||||
|
campsite *campsite.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
func newAdminHandler() *adminHandler {
|
||||||
|
return &adminHandler{
|
||||||
|
campsite: campsite.NewHandler(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *adminHandler) Handle(user *auth.User, company *auth.Company, conn *database.Conn, requestPath string) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !user.LoggedIn {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
serveLoginForm(w, r, user, company, requestPath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !user.IsEmployee() {
|
||||||
|
http.Error(w, user.Locale.Gettext("Access forbidden"), http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var head string
|
||||||
|
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
|
||||||
|
switch head {
|
||||||
|
case "campsites":
|
||||||
|
h.campsite.Handler(user, company, conn).ServeHTTP(w, r)
|
||||||
|
case "":
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
serveDashboard(w, r, user, company)
|
||||||
|
default:
|
||||||
|
httplib.MethodNotAllowed(w, r, http.MethodGet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func serveDashboard(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
||||||
|
template.MustRenderAdmin(w, r, user, company, "dashboard.gohtml", nil)
|
||||||
|
}
|
|
@ -11,18 +11,17 @@ import (
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||||
"dev.tandem.ws/tandem/camper/pkg/campsite"
|
|
||||||
"dev.tandem.ws/tandem/camper/pkg/database"
|
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||||
"dev.tandem.ws/tandem/camper/pkg/locale"
|
"dev.tandem.ws/tandem/camper/pkg/locale"
|
||||||
"dev.tandem.ws/tandem/camper/pkg/template"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
db *database.DB
|
db *database.DB
|
||||||
fileHandler http.Handler
|
fileHandler http.Handler
|
||||||
profile *profileHandler
|
profile *profileHandler
|
||||||
campsite *campsite.Handler
|
admin *adminHandler
|
||||||
|
public *publicHandler
|
||||||
locales locale.Locales
|
locales locale.Locales
|
||||||
defaultLocale *locale.Locale
|
defaultLocale *locale.Locale
|
||||||
languageMatcher language.Matcher
|
languageMatcher language.Matcher
|
||||||
|
@ -39,7 +38,8 @@ func New(db *database.DB, avatarsDir string) (http.Handler, error) {
|
||||||
db: db,
|
db: db,
|
||||||
fileHandler: static,
|
fileHandler: static,
|
||||||
profile: profile,
|
profile: profile,
|
||||||
campsite: campsite.NewHandler(),
|
admin: newAdminHandler(),
|
||||||
|
public: newPublicHandler(),
|
||||||
locales: locales,
|
locales: locales,
|
||||||
defaultLocale: locales[language.Catalan],
|
defaultLocale: locales[language.Catalan],
|
||||||
languageMatcher: language.NewMatcher(locales.Tags()),
|
languageMatcher: language.NewMatcher(locales.Tags()),
|
||||||
|
@ -81,41 +81,38 @@ func (h *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if head == "login" {
|
switch head {
|
||||||
|
case "":
|
||||||
|
http.Redirect(w, r, "/"+user.Locale.Language.String()+"/", http.StatusFound)
|
||||||
|
case "admin":
|
||||||
|
h.admin.Handle(user, company, conn, requestPath).ServeHTTP(w, r)
|
||||||
|
case "login":
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
serveLoginForm(w, r, user, company, "/")
|
serveLoginForm(w, r, user, company, "/admin")
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
handleLogin(w, r, user, company, conn)
|
handleLogin(w, r, user, company, conn)
|
||||||
default:
|
default:
|
||||||
httplib.MethodNotAllowed(w, r, http.MethodPost, http.MethodGet)
|
httplib.MethodNotAllowed(w, r, http.MethodPost, http.MethodGet)
|
||||||
}
|
}
|
||||||
} else {
|
case "me":
|
||||||
if !user.LoggedIn {
|
h.profile.Handler(user, company, conn, requestPath).ServeHTTP(w, r)
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
default:
|
||||||
serveLoginForm(w, r, user, company, requestPath)
|
langTag, err := language.Parse(head)
|
||||||
|
if err != nil {
|
||||||
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
urlLocale := h.locales[langTag]
|
||||||
switch head {
|
if urlLocale == nil {
|
||||||
case "me":
|
|
||||||
h.profile.Handler(user, company, conn).ServeHTTP(w, r)
|
|
||||||
case "campsites":
|
|
||||||
h.campsite.Handler(user, company, conn).ServeHTTP(w, r)
|
|
||||||
case "":
|
|
||||||
switch r.Method {
|
|
||||||
case http.MethodGet:
|
|
||||||
serveDashboard(w, r, user, company)
|
|
||||||
default:
|
|
||||||
httplib.MethodNotAllowed(w, r, http.MethodGet)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user.Locale = urlLocale
|
||||||
|
if r.Method == http.MethodGet || r.Method == http.MethodHead {
|
||||||
|
w = httplib.LanguageLinks(w, false, r.Host, r.URL.Path, h.locales)
|
||||||
|
}
|
||||||
|
h.public.Handler(user, company, conn).ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func serveDashboard(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
|
||||||
template.MustRender(w, r, user, company, "dashboard.gohtml", nil)
|
|
||||||
}
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ func (f *loginForm) Parse(r *http.Request) error {
|
||||||
f.Password.FillValue(r)
|
f.Password.FillValue(r)
|
||||||
f.Redirect.FillValue(r)
|
f.Redirect.FillValue(r)
|
||||||
if f.Redirect.Val == "" {
|
if f.Redirect.Val == "" {
|
||||||
f.Redirect.Val = "/"
|
f.Redirect.Val = "/admin/"
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ func (f *loginForm) Valid(l *locale.Locale) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *loginForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
func (f *loginForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
||||||
template.MustRender(w, r, user, company, "login.gohtml", f)
|
template.MustRenderAdmin(w, r, user, company, "login.gohtml", f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveLoginForm(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, redirectPath string) {
|
func serveLoginForm(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, redirectPath string) {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||||
|
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
type publicHandler struct{}
|
||||||
|
|
||||||
|
func newPublicHandler() *publicHandler {
|
||||||
|
return &publicHandler{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *publicHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var head string
|
||||||
|
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
|
||||||
|
switch head {
|
||||||
|
case "":
|
||||||
|
template.MustRenderPublic(w, r, user, company, "home.gohtml", nil)
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -80,8 +80,14 @@ func newProfileHandler(static http.Handler, avatarsDir string) (*profileHandler,
|
||||||
return handler, nil
|
return handler, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *profileHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.HandlerFunc {
|
func (h *profileHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn, requestPath string) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !user.LoggedIn {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
serveLoginForm(w, r, user, company, requestPath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var head string
|
var head string
|
||||||
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
|
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
|
||||||
|
|
||||||
|
@ -249,7 +255,7 @@ func (f *profileForm) Valid(l *locale.Locale) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *profileForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
func (f *profileForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
||||||
template.MustRender(w, r, user, company, "profile.gohtml", f)
|
template.MustRenderAdmin(w, r, user, company, "profile.gohtml", f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *profileForm) HasAvatarFile() bool {
|
func (f *profileForm) HasAvatarFile() bool {
|
||||||
|
|
|
@ -39,3 +39,8 @@ func (user *User) VerifyCSRFToken(r *http.Request) error {
|
||||||
}
|
}
|
||||||
return errors.New(user.Locale.Gettext("Cross-site request forgery detected."))
|
return errors.New(user.Locale.Gettext("Cross-site request forgery detected."))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (user *User) IsEmployee() bool {
|
||||||
|
role := user.Role[0]
|
||||||
|
return role == 'e' || role == 'a'
|
||||||
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ type typeIndex struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (page *typeIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
func (page *typeIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
||||||
template.MustRender(w, r, user, company, "campsite/type/index.gohtml", page)
|
template.MustRenderAdmin(w, r, user, company, "campsite/type/index.gohtml", page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addType(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
|
func addType(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
|
||||||
|
@ -145,5 +145,5 @@ func (f *typeForm) Valid(l *locale.Locale) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *typeForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
func (f *typeForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
||||||
template.MustRender(w, r, user, company, "campsite/type/new.gohtml", f)
|
template.MustRenderAdmin(w, r, user, company, "campsite/type/new.gohtml", f)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/locale"
|
||||||
|
)
|
||||||
|
|
||||||
|
type languageLinks struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
schemaAuthority string
|
||||||
|
path string
|
||||||
|
locales locale.Locales
|
||||||
|
wroteHeader bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *languageLinks) WriteHeader(statusCode int) {
|
||||||
|
if statusCode >= 200 && statusCode < 300 {
|
||||||
|
for k := range w.locales {
|
||||||
|
tag := k.String()
|
||||||
|
w.Header().Add("Link", fmt.Sprintf(`<%[1]s/%[2]s%[3]s>; rel="alternate"; hreflang="%[2]s"`, w.schemaAuthority, tag, w.path))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.wroteHeader = true
|
||||||
|
w.ResponseWriter.WriteHeader(statusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *languageLinks) Write(data []byte) (int, error) {
|
||||||
|
if !w.wroteHeader {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}
|
||||||
|
return w.ResponseWriter.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LanguageLinks(w http.ResponseWriter, https bool, authority string, path string, locales locale.Locales) http.ResponseWriter {
|
||||||
|
var schema string
|
||||||
|
if https {
|
||||||
|
schema = "https"
|
||||||
|
} else {
|
||||||
|
schema = "http"
|
||||||
|
}
|
||||||
|
return &languageLinks{w, schema + "://" + authority, path, locales, false}
|
||||||
|
}
|
|
@ -15,19 +15,28 @@ import (
|
||||||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func templateFile(name string) string {
|
func adminTemplateFile(name string) string {
|
||||||
return "web/templates/" + name
|
return "web/templates/admin/" + name
|
||||||
}
|
}
|
||||||
|
|
||||||
func MustRender(w io.Writer, r *http.Request, user *auth.User, company *auth.Company, filename string, data interface{}) {
|
func publicTemplateFile(name string) string {
|
||||||
|
return "web/templates/public/" + name
|
||||||
|
}
|
||||||
|
|
||||||
|
func MustRenderAdmin(w io.Writer, r *http.Request, user *auth.User, company *auth.Company, filename string, data interface{}) {
|
||||||
layout := "layout.gohtml"
|
layout := "layout.gohtml"
|
||||||
if httplib.IsHTMxRequest(r) {
|
if httplib.IsHTMxRequest(r) {
|
||||||
layout = "htmx.gohtml"
|
layout = "htmx.gohtml"
|
||||||
}
|
}
|
||||||
mustRenderLayout(w, user, company, layout, filename, data)
|
mustRenderLayout(w, user, company, adminTemplateFile, layout, filename, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustRenderLayout(w io.Writer, user *auth.User, company *auth.Company, layout string, filename string, data interface{}) {
|
func MustRenderPublic(w io.Writer, r *http.Request, user *auth.User, company *auth.Company, filename string, data interface{}) {
|
||||||
|
layout := "layout.gohtml"
|
||||||
|
mustRenderLayout(w, user, company, publicTemplateFile, layout, filename, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustRenderLayout(w io.Writer, user *auth.User, company *auth.Company, templateFile func(string) string, layout string, filename string, data interface{}) {
|
||||||
t := template.New(filename)
|
t := template.New(filename)
|
||||||
t.Funcs(template.FuncMap{
|
t.Funcs(template.FuncMap{
|
||||||
"gettext": user.Locale.Get,
|
"gettext": user.Locale.Get,
|
||||||
|
|
88
po/ca.po
88
po/ca.po
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: camper\n"
|
"Project-Id-Version: camper\n"
|
||||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||||
"POT-Creation-Date: 2023-08-04 19:51+0200\n"
|
"POT-Creation-Date: 2023-08-05 03:23+0200\n"
|
||||||
"PO-Revision-Date: 2023-07-22 23:45+0200\n"
|
"PO-Revision-Date: 2023-07-22 23:45+0200\n"
|
||||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||||
"Language-Team: Catalan <ca@dodds.net>\n"
|
"Language-Team: Catalan <ca@dodds.net>\n"
|
||||||
|
@ -18,123 +18,133 @@ msgstr ""
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: web/templates/campsite/type/new.gohtml:14
|
#: web/templates/public/home.gohtml:6
|
||||||
#: web/templates/campsite/type/new.gohtml:20
|
msgctxt "title"
|
||||||
|
msgid "Home"
|
||||||
|
msgstr "Inici"
|
||||||
|
|
||||||
|
#: web/templates/public/layout.gohtml:10 web/templates/public/layout.gohtml:17
|
||||||
|
msgid "Campsite Montagut"
|
||||||
|
msgstr "Càmping Montagut"
|
||||||
|
|
||||||
|
#: web/templates/public/layout.gohtml:16 web/templates/admin/layout.gohtml:18
|
||||||
|
msgid "Skip to main content"
|
||||||
|
msgstr "Salta al contingut principal"
|
||||||
|
|
||||||
|
#: web/templates/admin/campsite/type/new.gohtml:14
|
||||||
|
#: web/templates/admin/campsite/type/new.gohtml:20
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "New Campsite Type"
|
msgid "New Campsite Type"
|
||||||
msgstr "Nou tipus d’allotjament"
|
msgstr "Nou tipus d’allotjament"
|
||||||
|
|
||||||
#: web/templates/campsite/type/new.gohtml:25 web/templates/profile.gohtml:26
|
#: web/templates/admin/campsite/type/new.gohtml:25
|
||||||
|
#: web/templates/admin/profile.gohtml:26
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr "Nom"
|
msgstr "Nom"
|
||||||
|
|
||||||
#: web/templates/campsite/type/new.gohtml:33
|
#: web/templates/admin/campsite/type/new.gohtml:33
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Descripció"
|
msgstr "Descripció"
|
||||||
|
|
||||||
#: web/templates/campsite/type/new.gohtml:40
|
#: web/templates/admin/campsite/type/new.gohtml:40
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Add"
|
msgid "Add"
|
||||||
msgstr "Afegeix"
|
msgstr "Afegeix"
|
||||||
|
|
||||||
#: web/templates/campsite/type/index.gohtml:6
|
#: web/templates/admin/campsite/type/index.gohtml:6
|
||||||
#: web/templates/campsite/type/index.gohtml:12
|
#: web/templates/admin/campsite/type/index.gohtml:12
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Campsite Types"
|
msgid "Campsite Types"
|
||||||
msgstr "Tipus d’allotjaments"
|
msgstr "Tipus d’allotjaments"
|
||||||
|
|
||||||
#: web/templates/campsite/type/index.gohtml:11
|
#: web/templates/admin/campsite/type/index.gohtml:11
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Add Type"
|
msgid "Add Type"
|
||||||
msgstr "Afegeix tipus"
|
msgstr "Afegeix tipus"
|
||||||
|
|
||||||
#: web/templates/campsite/type/index.gohtml:17
|
#: web/templates/admin/campsite/type/index.gohtml:17
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr "Nom"
|
msgstr "Nom"
|
||||||
|
|
||||||
#: web/templates/campsite/type/index.gohtml:29
|
#: web/templates/admin/campsite/type/index.gohtml:29
|
||||||
msgid "No campsite types added yet."
|
msgid "No campsite types added yet."
|
||||||
msgstr "No s’ha afegit cap tipus d’allotjament encara."
|
msgstr "No s’ha afegit cap tipus d’allotjament encara."
|
||||||
|
|
||||||
#: web/templates/dashboard.gohtml:6 web/templates/dashboard.gohtml:10
|
#: web/templates/admin/dashboard.gohtml:6
|
||||||
#: web/templates/layout.gohtml:44
|
#: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:44
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Dashboard"
|
msgid "Dashboard"
|
||||||
msgstr "Tauler"
|
msgstr "Tauler"
|
||||||
|
|
||||||
#: web/templates/login.gohtml:6 web/templates/login.gohtml:13
|
#: web/templates/admin/login.gohtml:6 web/templates/admin/login.gohtml:13
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Login"
|
msgid "Login"
|
||||||
msgstr "Entrada"
|
msgstr "Entrada"
|
||||||
|
|
||||||
#: web/templates/login.gohtml:22 web/templates/profile.gohtml:35
|
#: web/templates/admin/login.gohtml:22 web/templates/admin/profile.gohtml:35
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "Correu-e"
|
msgstr "Correu-e"
|
||||||
|
|
||||||
#: web/templates/login.gohtml:31 web/templates/profile.gohtml:46
|
#: web/templates/admin/login.gohtml:31 web/templates/admin/profile.gohtml:46
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "Contrasenya"
|
msgstr "Contrasenya"
|
||||||
|
|
||||||
#: web/templates/login.gohtml:40
|
#: web/templates/admin/login.gohtml:40
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Login"
|
msgid "Login"
|
||||||
msgstr "Entra"
|
msgstr "Entra"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:6 web/templates/profile.gohtml:12
|
#: web/templates/admin/profile.gohtml:6 web/templates/admin/profile.gohtml:12
|
||||||
#: web/templates/layout.gohtml:29
|
#: web/templates/admin/layout.gohtml:29
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Profile"
|
msgid "Profile"
|
||||||
msgstr "Perfil"
|
msgstr "Perfil"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:17
|
#: web/templates/admin/profile.gohtml:17
|
||||||
msgctxt "inut"
|
msgctxt "inut"
|
||||||
msgid "Profile Image"
|
msgid "Profile Image"
|
||||||
msgstr "Imatge del perfil"
|
msgstr "Imatge del perfil"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:43
|
#: web/templates/admin/profile.gohtml:43
|
||||||
msgctxt "legend"
|
msgctxt "legend"
|
||||||
msgid "Change password"
|
msgid "Change password"
|
||||||
msgstr "Canvi de contrasenya"
|
msgstr "Canvi de contrasenya"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:55
|
#: web/templates/admin/profile.gohtml:55
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Password Confirmation"
|
msgid "Password Confirmation"
|
||||||
msgstr "Confirmació de la contrasenya"
|
msgstr "Confirmació de la contrasenya"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:65
|
#: web/templates/admin/profile.gohtml:65
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Language"
|
msgid "Language"
|
||||||
msgstr "Idioma"
|
msgstr "Idioma"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:75
|
#: web/templates/admin/profile.gohtml:75
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Save changes"
|
msgid "Save changes"
|
||||||
msgstr "Desa els canvis"
|
msgstr "Desa els canvis"
|
||||||
|
|
||||||
#: web/templates/layout.gohtml:18
|
#: web/templates/admin/layout.gohtml:25
|
||||||
msgid "Skip to main content"
|
|
||||||
msgstr "Salta al contingut principal"
|
|
||||||
|
|
||||||
#: web/templates/layout.gohtml:25
|
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "User Menu"
|
msgid "User Menu"
|
||||||
msgstr "Menú d’usuari"
|
msgstr "Menú d’usuari"
|
||||||
|
|
||||||
#: web/templates/layout.gohtml:33
|
#: web/templates/admin/layout.gohtml:33
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr "Surt"
|
msgstr "Surt"
|
||||||
|
|
||||||
#: pkg/app/login.go:56 pkg/app/user.go:239
|
#: pkg/app/login.go:56 pkg/app/user.go:245
|
||||||
msgid "Email can not be empty."
|
msgid "Email can not be empty."
|
||||||
msgstr "No podeu deixar el correu en blanc."
|
msgstr "No podeu deixar el correu en blanc."
|
||||||
|
|
||||||
#: pkg/app/login.go:57 pkg/app/user.go:240
|
#: pkg/app/login.go:57 pkg/app/user.go:246
|
||||||
msgid "This email is not valid. It should be like name@domain.com."
|
msgid "This email is not valid. It should be like name@domain.com."
|
||||||
msgstr "Aquest correu-e no és vàlid. Hauria de ser similar a nom@domini.com."
|
msgstr "Aquest correu-e no és vàlid. Hauria de ser similar a nom@domini.com."
|
||||||
|
|
||||||
|
@ -146,27 +156,31 @@ msgstr "No podeu deixar la contrasenya en blanc."
|
||||||
msgid "Invalid user or password."
|
msgid "Invalid user or password."
|
||||||
msgstr "Nom d’usuari o contrasenya incorrectes."
|
msgstr "Nom d’usuari o contrasenya incorrectes."
|
||||||
|
|
||||||
#: pkg/app/user.go:190
|
#: pkg/app/user.go:196
|
||||||
msgctxt "language option"
|
msgctxt "language option"
|
||||||
msgid "Automatic"
|
msgid "Automatic"
|
||||||
msgstr "Automàtic"
|
msgstr "Automàtic"
|
||||||
|
|
||||||
#: pkg/app/user.go:242 pkg/campsite/type.go:143
|
#: pkg/app/user.go:248 pkg/campsite/type.go:143
|
||||||
msgid "Name can not be empty."
|
msgid "Name can not be empty."
|
||||||
msgstr "No podeu deixar el nom en blanc."
|
msgstr "No podeu deixar el nom en blanc."
|
||||||
|
|
||||||
#: pkg/app/user.go:243
|
#: pkg/app/user.go:249
|
||||||
msgid "Confirmation does not match password."
|
msgid "Confirmation does not match password."
|
||||||
msgstr "La confirmació no es correspon amb la contrasenya."
|
msgstr "La confirmació no es correspon amb la contrasenya."
|
||||||
|
|
||||||
#: pkg/app/user.go:244
|
#: pkg/app/user.go:250
|
||||||
msgid "Selected language is not valid."
|
msgid "Selected language is not valid."
|
||||||
msgstr "L’idioma escollit no és vàlid."
|
msgstr "L’idioma escollit no és vàlid."
|
||||||
|
|
||||||
#: pkg/app/user.go:246
|
#: pkg/app/user.go:252
|
||||||
msgid "File must be a valid PNG or JPEG image."
|
msgid "File must be a valid PNG or JPEG image."
|
||||||
msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida."
|
msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida."
|
||||||
|
|
||||||
|
#: pkg/app/admin.go:37
|
||||||
|
msgid "Access forbidden"
|
||||||
|
msgstr "Accés prohibit"
|
||||||
|
|
||||||
#: pkg/auth/user.go:40
|
#: pkg/auth/user.go:40
|
||||||
msgid "Cross-site request forgery detected."
|
msgid "Cross-site request forgery detected."
|
||||||
msgstr "S’ha detectat un intent de falsificació de petició a llocs creuats."
|
msgstr "S’ha detectat un intent de falsificació de petició a llocs creuats."
|
||||||
|
|
88
po/es.po
88
po/es.po
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: camper\n"
|
"Project-Id-Version: camper\n"
|
||||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||||
"POT-Creation-Date: 2023-08-04 19:51+0200\n"
|
"POT-Creation-Date: 2023-08-05 03:23+0200\n"
|
||||||
"PO-Revision-Date: 2023-07-22 23:46+0200\n"
|
"PO-Revision-Date: 2023-07-22 23:46+0200\n"
|
||||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||||
"Language-Team: Spanish <es@tp.org.es>\n"
|
"Language-Team: Spanish <es@tp.org.es>\n"
|
||||||
|
@ -18,123 +18,133 @@ msgstr ""
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: web/templates/campsite/type/new.gohtml:14
|
#: web/templates/public/home.gohtml:6
|
||||||
#: web/templates/campsite/type/new.gohtml:20
|
msgctxt "title"
|
||||||
|
msgid "Home"
|
||||||
|
msgstr "Inicio"
|
||||||
|
|
||||||
|
#: web/templates/public/layout.gohtml:10 web/templates/public/layout.gohtml:17
|
||||||
|
msgid "Campsite Montagut"
|
||||||
|
msgstr "Camping Montagut"
|
||||||
|
|
||||||
|
#: web/templates/public/layout.gohtml:16 web/templates/admin/layout.gohtml:18
|
||||||
|
msgid "Skip to main content"
|
||||||
|
msgstr "Saltar al contenido principal"
|
||||||
|
|
||||||
|
#: web/templates/admin/campsite/type/new.gohtml:14
|
||||||
|
#: web/templates/admin/campsite/type/new.gohtml:20
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "New Campsite Type"
|
msgid "New Campsite Type"
|
||||||
msgstr "Nuevo tipo de alojamiento"
|
msgstr "Nuevo tipo de alojamiento"
|
||||||
|
|
||||||
#: web/templates/campsite/type/new.gohtml:25 web/templates/profile.gohtml:26
|
#: web/templates/admin/campsite/type/new.gohtml:25
|
||||||
|
#: web/templates/admin/profile.gohtml:26
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr "Nombre"
|
msgstr "Nombre"
|
||||||
|
|
||||||
#: web/templates/campsite/type/new.gohtml:33
|
#: web/templates/admin/campsite/type/new.gohtml:33
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Descripción"
|
msgstr "Descripción"
|
||||||
|
|
||||||
#: web/templates/campsite/type/new.gohtml:40
|
#: web/templates/admin/campsite/type/new.gohtml:40
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Add"
|
msgid "Add"
|
||||||
msgstr "Añadir"
|
msgstr "Añadir"
|
||||||
|
|
||||||
#: web/templates/campsite/type/index.gohtml:6
|
#: web/templates/admin/campsite/type/index.gohtml:6
|
||||||
#: web/templates/campsite/type/index.gohtml:12
|
#: web/templates/admin/campsite/type/index.gohtml:12
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Campsite Types"
|
msgid "Campsite Types"
|
||||||
msgstr "Tipos de alojamientos"
|
msgstr "Tipos de alojamientos"
|
||||||
|
|
||||||
#: web/templates/campsite/type/index.gohtml:11
|
#: web/templates/admin/campsite/type/index.gohtml:11
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Add Type"
|
msgid "Add Type"
|
||||||
msgstr "Añadir tipo"
|
msgstr "Añadir tipo"
|
||||||
|
|
||||||
#: web/templates/campsite/type/index.gohtml:17
|
#: web/templates/admin/campsite/type/index.gohtml:17
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr "Nombre"
|
msgstr "Nombre"
|
||||||
|
|
||||||
#: web/templates/campsite/type/index.gohtml:29
|
#: web/templates/admin/campsite/type/index.gohtml:29
|
||||||
msgid "No campsite types added yet."
|
msgid "No campsite types added yet."
|
||||||
msgstr "No se ha añadido ningún tipo de alojamiento todavía."
|
msgstr "No se ha añadido ningún tipo de alojamiento todavía."
|
||||||
|
|
||||||
#: web/templates/dashboard.gohtml:6 web/templates/dashboard.gohtml:10
|
#: web/templates/admin/dashboard.gohtml:6
|
||||||
#: web/templates/layout.gohtml:44
|
#: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:44
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Dashboard"
|
msgid "Dashboard"
|
||||||
msgstr "Panel"
|
msgstr "Panel"
|
||||||
|
|
||||||
#: web/templates/login.gohtml:6 web/templates/login.gohtml:13
|
#: web/templates/admin/login.gohtml:6 web/templates/admin/login.gohtml:13
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Login"
|
msgid "Login"
|
||||||
msgstr "Entrada"
|
msgstr "Entrada"
|
||||||
|
|
||||||
#: web/templates/login.gohtml:22 web/templates/profile.gohtml:35
|
#: web/templates/admin/login.gohtml:22 web/templates/admin/profile.gohtml:35
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "Correo-e"
|
msgstr "Correo-e"
|
||||||
|
|
||||||
#: web/templates/login.gohtml:31 web/templates/profile.gohtml:46
|
#: web/templates/admin/login.gohtml:31 web/templates/admin/profile.gohtml:46
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "Contraseña"
|
msgstr "Contraseña"
|
||||||
|
|
||||||
#: web/templates/login.gohtml:40
|
#: web/templates/admin/login.gohtml:40
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Login"
|
msgid "Login"
|
||||||
msgstr "Entrar"
|
msgstr "Entrar"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:6 web/templates/profile.gohtml:12
|
#: web/templates/admin/profile.gohtml:6 web/templates/admin/profile.gohtml:12
|
||||||
#: web/templates/layout.gohtml:29
|
#: web/templates/admin/layout.gohtml:29
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Profile"
|
msgid "Profile"
|
||||||
msgstr "Perfil"
|
msgstr "Perfil"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:17
|
#: web/templates/admin/profile.gohtml:17
|
||||||
msgctxt "inut"
|
msgctxt "inut"
|
||||||
msgid "Profile Image"
|
msgid "Profile Image"
|
||||||
msgstr "Imagen del perfil"
|
msgstr "Imagen del perfil"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:43
|
#: web/templates/admin/profile.gohtml:43
|
||||||
msgctxt "legend"
|
msgctxt "legend"
|
||||||
msgid "Change password"
|
msgid "Change password"
|
||||||
msgstr "Cambio de contraseña"
|
msgstr "Cambio de contraseña"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:55
|
#: web/templates/admin/profile.gohtml:55
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Password Confirmation"
|
msgid "Password Confirmation"
|
||||||
msgstr "Confirmación de la contraseña"
|
msgstr "Confirmación de la contraseña"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:65
|
#: web/templates/admin/profile.gohtml:65
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Language"
|
msgid "Language"
|
||||||
msgstr "Idioma"
|
msgstr "Idioma"
|
||||||
|
|
||||||
#: web/templates/profile.gohtml:75
|
#: web/templates/admin/profile.gohtml:75
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Save changes"
|
msgid "Save changes"
|
||||||
msgstr "Guardar los cambios"
|
msgstr "Guardar los cambios"
|
||||||
|
|
||||||
#: web/templates/layout.gohtml:18
|
#: web/templates/admin/layout.gohtml:25
|
||||||
msgid "Skip to main content"
|
|
||||||
msgstr "Saltar al contenido principal"
|
|
||||||
|
|
||||||
#: web/templates/layout.gohtml:25
|
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "User Menu"
|
msgid "User Menu"
|
||||||
msgstr "Menú de usuario"
|
msgstr "Menú de usuario"
|
||||||
|
|
||||||
#: web/templates/layout.gohtml:33
|
#: web/templates/admin/layout.gohtml:33
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr "Salir"
|
msgstr "Salir"
|
||||||
|
|
||||||
#: pkg/app/login.go:56 pkg/app/user.go:239
|
#: pkg/app/login.go:56 pkg/app/user.go:245
|
||||||
msgid "Email can not be empty."
|
msgid "Email can not be empty."
|
||||||
msgstr "No podéis dejar el correo-e en blanco."
|
msgstr "No podéis dejar el correo-e en blanco."
|
||||||
|
|
||||||
#: pkg/app/login.go:57 pkg/app/user.go:240
|
#: pkg/app/login.go:57 pkg/app/user.go:246
|
||||||
msgid "This email is not valid. It should be like name@domain.com."
|
msgid "This email is not valid. It should be like name@domain.com."
|
||||||
msgstr "Este correo-e no es válido. Tiene que ser parecido a nombre@dominio.com."
|
msgstr "Este correo-e no es válido. Tiene que ser parecido a nombre@dominio.com."
|
||||||
|
|
||||||
|
@ -146,27 +156,31 @@ msgstr "No podéis dejar la contraseña en blanco."
|
||||||
msgid "Invalid user or password."
|
msgid "Invalid user or password."
|
||||||
msgstr "Usuario o contraseña incorrectos."
|
msgstr "Usuario o contraseña incorrectos."
|
||||||
|
|
||||||
#: pkg/app/user.go:190
|
#: pkg/app/user.go:196
|
||||||
msgctxt "language option"
|
msgctxt "language option"
|
||||||
msgid "Automatic"
|
msgid "Automatic"
|
||||||
msgstr "Automático"
|
msgstr "Automático"
|
||||||
|
|
||||||
#: pkg/app/user.go:242 pkg/campsite/type.go:143
|
#: pkg/app/user.go:248 pkg/campsite/type.go:143
|
||||||
msgid "Name can not be empty."
|
msgid "Name can not be empty."
|
||||||
msgstr "No podéis dejar el nombre en blanco."
|
msgstr "No podéis dejar el nombre en blanco."
|
||||||
|
|
||||||
#: pkg/app/user.go:243
|
#: pkg/app/user.go:249
|
||||||
msgid "Confirmation does not match password."
|
msgid "Confirmation does not match password."
|
||||||
msgstr "La confirmación no se corresponde con la contraseña."
|
msgstr "La confirmación no se corresponde con la contraseña."
|
||||||
|
|
||||||
#: pkg/app/user.go:244
|
#: pkg/app/user.go:250
|
||||||
msgid "Selected language is not valid."
|
msgid "Selected language is not valid."
|
||||||
msgstr "El idioma escogido no es válido."
|
msgstr "El idioma escogido no es válido."
|
||||||
|
|
||||||
#: pkg/app/user.go:246
|
#: pkg/app/user.go:252
|
||||||
msgid "File must be a valid PNG or JPEG image."
|
msgid "File must be a valid PNG or JPEG image."
|
||||||
msgstr "El archivo tiene que ser una imagen PNG o JPEG válida."
|
msgstr "El archivo tiene que ser una imagen PNG o JPEG válida."
|
||||||
|
|
||||||
|
#: pkg/app/admin.go:37
|
||||||
|
msgid "Access forbidden"
|
||||||
|
msgstr "Acceso prohibido"
|
||||||
|
|
||||||
#: pkg/auth/user.go:40
|
#: pkg/auth/user.go:40
|
||||||
msgid "Cross-site request forgery detected."
|
msgid "Cross-site request forgery detected."
|
||||||
msgstr "Se ha detectado un intento de falsificación de petición en sitios cruzados."
|
msgstr "Se ha detectado un intento de falsificación de petición en sitios cruzados."
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
*, *::before, *::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-size: 62.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
background-color: white;
|
||||||
|
color: #3f3b37;
|
||||||
|
}
|
||||||
|
|
||||||
|
img, picture, video, canvas, svg {
|
||||||
|
display: block;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, button, textarea, select {
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, h1, h2, h3, h4, h5, h6 {
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
{{ define "content" -}}
|
{{ define "content" -}}
|
||||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.typeIndex*/ -}}
|
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.typeIndex*/ -}}
|
||||||
<a href="/campsites/types/new">{{( pgettext "Add Type" "action" )}}</a>
|
<a href="/admin/campsites/types/new">{{( pgettext "Add Type" "action" )}}</a>
|
||||||
<h2>{{( pgettext "Campsite Types" "title" )}}</h2>
|
<h2>{{( pgettext "Campsite Types" "title" )}}</h2>
|
||||||
{{ if .Types -}}
|
{{ if .Types -}}
|
||||||
<table>
|
<table>
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
{{ range .Types -}}
|
{{ range .Types -}}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="/campsites/type/{{ .Slug }}">{{ .Name }}</a></td>
|
<td><a href="/admin/campsites/type/{{ .Slug }}">{{ .Name }}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{- end }}
|
{{- end }}
|
||||||
</tbody>
|
</tbody>
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
{{ define "content" -}}
|
{{ define "content" -}}
|
||||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.typeForm*/ -}}
|
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.typeForm*/ -}}
|
||||||
<form action="/campsites/types" method="post">
|
<form action="/admin/campsites/types" method="post">
|
||||||
<h2>{{( pgettext "New Campsite Type" "title" )}}</h2>
|
<h2>{{( pgettext "New Campsite Type" "title" )}}</h2>
|
||||||
{{ CSRFInput }}
|
{{ CSRFInput }}
|
||||||
<fieldset>
|
<fieldset>
|
|
@ -41,7 +41,7 @@
|
||||||
<nav>
|
<nav>
|
||||||
<ul role="menu">
|
<ul role="menu">
|
||||||
<li role="presentation">
|
<li role="presentation">
|
||||||
<a role="menuitem" href="/">{{( pgettext "Dashboard" "title" )}}</a>
|
<a role="menuitem" href="/admin/">{{( pgettext "Dashboard" "title" )}}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
|
@ -0,0 +1 @@
|
||||||
|
../admin/form.gohtml
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
-->
|
||||||
|
{{ define "title" -}}
|
||||||
|
{{( pgettext "Home" "title" )}}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{ define "content" -}}
|
||||||
|
{{- end }}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
-->
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="{{ currentLocale }}">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>{{ template "title" . }} — {{( gettext "Campsite Montagut" )}}</title>
|
||||||
|
<link rel="stylesheet" media="screen" href="/static/public.css">
|
||||||
|
{{ block "head" . }}{{ end }}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<a href="#content">{{( gettext "Skip to main content" )}}</a>
|
||||||
|
<h1>{{( gettext "Campsite Montagut" )}}</h1>
|
||||||
|
</header>
|
||||||
|
<main id="content">
|
||||||
|
{{- template "content" . }}
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue