diff --git a/cmd/dwelling-home/main.go b/cmd/dwelling-home/main.go index d6bb6e5..c41ce6f 100644 --- a/cmd/dwelling-home/main.go +++ b/cmd/dwelling-home/main.go @@ -15,8 +15,10 @@ import ( "git.arav.su/Arav/dwelling-home/internal/version" mfsqlite "git.arav.su/Arav/dwelling-home/pkg/mindflow/database/sqlite" "git.arav.su/Arav/dwelling-home/web" + "git.arav.su/Arav/dwelling-home/web/locales" "git.arav.su/Arav/httpr" gb "git.arav.su/Arav/justguestbook" + "github.com/invopop/ctxi18n" ) var ( @@ -50,6 +52,10 @@ func main() { } defer mindflowDB.Close() + if err := ctxi18n.LoadWithDefault(locales.Content, "en"); err != nil { + log.Fatalln("Failed to load i18n:", err) + } + hand := dwhttp.NewHandlers(*captchaExpiry, owner, *guestbookPageSize, guestbookDB, mindflowDB) r := httpr.New() @@ -101,7 +107,7 @@ func main() { s.Handler(http.MethodPatch, "/category/:id", mindflowApi.EditCategory) s.Handler(http.MethodDelete, "/category/:id", mindflowApi.DeleteCategory) - srv := dwhttp.NewHttpServer(r) + srv := dwhttp.NewHttpServer(I18nMiddleware(r)) if err := srv.Start(*listenAddress); err != nil { log.Fatalln(err) @@ -117,3 +123,13 @@ func main() { <-doneSignal } + +func I18nMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx, err := ctxi18n.WithLocale(r.Context(), r.Header.Get("Accept-Language")) + if err != nil { + log.Println("i18nmw:", err) + } + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} diff --git a/internal/http/web_handlers.go b/internal/http/web_handlers.go index ba298e1..1d963fe 100644 --- a/internal/http/web_handlers.go +++ b/internal/http/web_handlers.go @@ -1,7 +1,6 @@ package http import ( - "context" "log" "math" "net/http" @@ -36,15 +35,15 @@ func NewHandlers(captchaExpire time.Duration, owner string, gbPageSize int64, } func (h *Handlers) Index(w http.ResponseWriter, r *http.Request) { - web.Index(r).Render(context.Background(), w) + web.Index(r).Render(r.Context(), w) } func (h *Handlers) Privacy(w http.ResponseWriter, r *http.Request) { - web.Privacy(r).Render(context.Background(), w) + web.Privacy(r).Render(r.Context(), w) } func (h *Handlers) Stuff(w http.ResponseWriter, r *http.Request) { - web.Stuff(r).Render(context.Background(), w) + web.Stuff(r).Render(r.Context(), w) } func (h *Handlers) Mindflow(w http.ResponseWriter, r *http.Request) { @@ -62,7 +61,7 @@ func (h *Handlers) Mindflow(w http.ResponseWriter, r *http.Request) { return } - web.Mindflow(posts, categories, r).Render(context.Background(), w) + web.Mindflow(posts, categories, r).Render(r.Context(), w) } func (h *Handlers) MindflowAdmin(w http.ResponseWriter, r *http.Request) { @@ -78,7 +77,7 @@ func (h *Handlers) MindflowAdmin(w http.ResponseWriter, r *http.Request) { return } - web.MindflowAdmin(posts, categories, r).Render(context.Background(), w) + web.MindflowAdmin(posts, categories, r).Render(r.Context(), w) } func (h *Handlers) About(w http.ResponseWriter, r *http.Request) { @@ -96,7 +95,7 @@ func (h *Handlers) About(w http.ResponseWriter, r *http.Request) { } } - web.About(&lst, r).Render(context.Background(), w) + web.About(&lst, r).Render(r.Context(), w) } func (h *Handlers) Article(w http.ResponseWriter, r *http.Request) { @@ -107,7 +106,7 @@ func (h *Handlers) Article(w http.ResponseWriter, r *http.Request) { return } - web.Article(artcl.Title, artcl.Description, string(artcl.Body), name, artcl.Date, r).Render(context.Background(), w) + web.Article(artcl.Title, artcl.Description, string(artcl.Body), name, artcl.Date, r).Render(r.Context(), w) } func (h *Handlers) Guestbook(w http.ResponseWriter, r *http.Request) { @@ -144,7 +143,7 @@ func (h *Handlers) Guestbook(w http.ResponseWriter, r *http.Request) { dwc := dwcaptcha.NewDwellingCaptcha(h.captchaExpire) _, id := inmemdb.New(r.RemoteAddr, dwc) - web.Guestbook(string(id), h.owner, entries, pageCount, page, r).Render(context.Background(), w) + web.Guestbook(string(id), h.owner, entries, pageCount, page, r).Render(r.Context(), w) } func (h *Handlers) GuestbookAdmin(w http.ResponseWriter, r *http.Request) { @@ -158,7 +157,7 @@ func (h *Handlers) GuestbookAdmin(w http.ResponseWriter, r *http.Request) { entry.Message = strings.ReplaceAll(entry.Message, "\\n", "\n") } - web.GuestbookAdmin(h.owner, entries, r).Render(context.Background(), w) + web.GuestbookAdmin(h.owner, entries, r).Render(r.Context(), w) } func (h *Handlers) RSS(w http.ResponseWriter, r *http.Request) { @@ -172,7 +171,7 @@ func (h *Handlers) RSS(w http.ResponseWriter, r *http.Request) { scheme = "http" } - web.RSS(scheme+"://"+r.Host, h.owner, posts, r).Render(context.Background(), w) + web.RSS(scheme+"://"+r.Host, h.owner, posts, r).Render(r.Context(), w) } func ServeAsset(path string) func(http.ResponseWriter, *http.Request) { @@ -184,7 +183,7 @@ func ServeAsset(path string) func(http.ResponseWriter, *http.Request) { func Error(w http.ResponseWriter, code int, reason, message string, r *http.Request) { w.WriteHeader(code) - web.ErrorXXX(code, reason, message, r).Render(context.Background(), w) + web.ErrorXXX(code, reason, message, r).Render(r.Context(), w) } func cleanupNewlines(text string) (out string) { diff --git a/web/locales/en/en.yaml b/web/locales/en/en.yaml new file mode 100644 index 0000000..4966f93 --- /dev/null +++ b/web/locales/en/en.yaml @@ -0,0 +1,30 @@ +en: + base: + rss-feed: "RSS" + rss-feed-title: "Stay up to date on what's going on." + copy-author: "Alexander \"Arav\" Andreev" + privacy-statements-link: "Privacy statements" + menu: + home: "Home" + stuff: "Stuff" + mindflow: "Mindflow" + about: "About" + guestbook: "Guestbook" + privacy: "Privacy" + article: + go-back: "Back to a list" + guestbook: + description: "This is my guestbook. Welcome." + form: + name: "Name (Anonymous if left blank)" + website: "Website (optional)" + message: "Your message" + hide-website: "Hide website (only I can see if set)" + quote-usage: "Use > to make a quote." + captcha-validity: "Valid for 10 minutes." + send-post: "Send" + post: + by: "by" + on: "on" + reply: "Reply by" + no-posts: "No posts." \ No newline at end of file diff --git a/web/locales/locales.go b/web/locales/locales.go new file mode 100644 index 0000000..a99396c --- /dev/null +++ b/web/locales/locales.go @@ -0,0 +1,9 @@ +package locales + +import ( + "embed" +) + +//go:embed en +//go:embed ru +var Content embed.FS diff --git a/web/locales/ru/ru.yaml b/web/locales/ru/ru.yaml new file mode 100644 index 0000000..65e903f --- /dev/null +++ b/web/locales/ru/ru.yaml @@ -0,0 +1,31 @@ +ru: + base: + rss-feed: "RSS" + rss-feed-title: "Будь в курсе происходящего." + copy-author: "Александр «Arav» Андреев" + privacy-statements-link: "О приватности" + section: + home: "Домой" + stuff: "Всякое" + mindflow: "Блог" + about: "О..." + guestbook: "Гостевая" + privacy: "Приватность" + article: + go-back: "К списку" + guestbook: + description: "Моя гостевая. Добро пожаловать." + form: + name: "Имя (Аноним если оставить пустым)" + website: "Вебсайт (необязательно)" + message: "Твоё сообщение" + hide-website-1: "Скрыть вебсайт" + hide-website-2: "(будет видно только мне)" + quote-usage: "Используй > для цитаты." + captcha-validity: "Действительна 10 минут." + send-post: "Отправить" + post: + by: "от" + on: " " + reply: "Ответ" + no-posts: "Нет постов." \ No newline at end of file