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