Introduce i18n. Теперь переведу сайт на русский!
This commit is contained in:
parent
4b351ed7a9
commit
50ba6bb74b
@ -15,8 +15,10 @@ import (
|
|||||||
"git.arav.su/Arav/dwelling-home/internal/version"
|
"git.arav.su/Arav/dwelling-home/internal/version"
|
||||||
mfsqlite "git.arav.su/Arav/dwelling-home/pkg/mindflow/database/sqlite"
|
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"
|
||||||
|
"git.arav.su/Arav/dwelling-home/web/locales"
|
||||||
"git.arav.su/Arav/httpr"
|
"git.arav.su/Arav/httpr"
|
||||||
gb "git.arav.su/Arav/justguestbook"
|
gb "git.arav.su/Arav/justguestbook"
|
||||||
|
"github.com/invopop/ctxi18n"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -50,6 +52,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer mindflowDB.Close()
|
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)
|
hand := dwhttp.NewHandlers(*captchaExpiry, owner, *guestbookPageSize, guestbookDB, mindflowDB)
|
||||||
|
|
||||||
r := httpr.New()
|
r := httpr.New()
|
||||||
@ -101,7 +107,7 @@ func main() {
|
|||||||
s.Handler(http.MethodPatch, "/category/:id", mindflowApi.EditCategory)
|
s.Handler(http.MethodPatch, "/category/:id", mindflowApi.EditCategory)
|
||||||
s.Handler(http.MethodDelete, "/category/:id", mindflowApi.DeleteCategory)
|
s.Handler(http.MethodDelete, "/category/:id", mindflowApi.DeleteCategory)
|
||||||
|
|
||||||
srv := dwhttp.NewHttpServer(r)
|
srv := dwhttp.NewHttpServer(I18nMiddleware(r))
|
||||||
|
|
||||||
if err := srv.Start(*listenAddress); err != nil {
|
if err := srv.Start(*listenAddress); err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
@ -117,3 +123,13 @@ func main() {
|
|||||||
|
|
||||||
<-doneSignal
|
<-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))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
"net/http"
|
"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) {
|
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) {
|
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) {
|
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) {
|
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
|
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) {
|
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
|
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) {
|
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) {
|
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
|
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) {
|
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)
|
dwc := dwcaptcha.NewDwellingCaptcha(h.captchaExpire)
|
||||||
_, id := inmemdb.New(r.RemoteAddr, dwc)
|
_, 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) {
|
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")
|
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) {
|
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"
|
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) {
|
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) {
|
func Error(w http.ResponseWriter, code int, reason, message string, r *http.Request) {
|
||||||
w.WriteHeader(code)
|
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) {
|
func cleanupNewlines(text string) (out string) {
|
||||||
|
30
web/locales/en/en.yaml
Normal file
30
web/locales/en/en.yaml
Normal file
@ -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 <small>(only I can see if set)</small>"
|
||||||
|
quote-usage: "Use > to make a quote."
|
||||||
|
captcha-validity: "Valid for <b>10</b> minutes."
|
||||||
|
send-post: "Send"
|
||||||
|
post:
|
||||||
|
by: "by"
|
||||||
|
on: "on"
|
||||||
|
reply: "Reply by"
|
||||||
|
no-posts: "No posts."
|
9
web/locales/locales.go
Normal file
9
web/locales/locales.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package locales
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed en
|
||||||
|
//go:embed ru
|
||||||
|
var Content embed.FS
|
31
web/locales/ru/ru.yaml
Normal file
31
web/locales/ru/ru.yaml
Normal file
@ -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: "Действительна <b>10</b> минут."
|
||||||
|
send-post: "Отправить"
|
||||||
|
post:
|
||||||
|
by: "от"
|
||||||
|
on: " "
|
||||||
|
reply: "Ответ"
|
||||||
|
no-posts: "Нет постов."
|
Loading…
Reference in New Issue
Block a user