mirror of
https://codeberg.org/VnPower/PixivFE
synced 2024-12-06 19:16:23 +01:00
Add cookie: Locale
This commit is contained in:
+8
-8
@@ -29,14 +29,14 @@ const (
|
||||
R18G XRestrict = 2
|
||||
)
|
||||
|
||||
func (x XRestrict) Localize(l i18n.Localizer) string {
|
||||
func (x XRestrict) String() string {
|
||||
switch x {
|
||||
case Safe:
|
||||
return l.Tr("Safe")
|
||||
return i18n.Tr("Safe")
|
||||
case R18:
|
||||
return l.Tr("R18")
|
||||
return i18n.Tr("R18")
|
||||
case R18G:
|
||||
return l.Tr("R18G")
|
||||
return i18n.Tr("R18G")
|
||||
}
|
||||
log.Panicf("invalid value: %#v", int(x))
|
||||
return ""
|
||||
@@ -56,14 +56,14 @@ const (
|
||||
AI AiType = 2
|
||||
)
|
||||
|
||||
func (x AiType) Localize(l i18n.Localizer) string {
|
||||
func (x AiType) String() string {
|
||||
switch x {
|
||||
case Unrated:
|
||||
return l.Tr("Unrated")
|
||||
return i18n.Tr("Unrated")
|
||||
case NotAI:
|
||||
return l.Tr("Not AI")
|
||||
return i18n.Tr("Not AI")
|
||||
case AI:
|
||||
return l.Tr("AI")
|
||||
return i18n.Tr("AI")
|
||||
}
|
||||
log.Panicf("invalid value: %#v", int(x))
|
||||
return ""
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# Localization
|
||||
|
||||
Notes on i18n/
|
||||
Important notice: please don't translate server logs with `i18n.*()`. It uses the request locale, not the server one.
|
||||
|
||||
## Todo
|
||||
|
||||
- [ ] Add env PIXIVFE_SERVER_LOCALE and set `i18n.GlobalLocale` to that on startup
|
||||
- [x] Add cookie: Locale
|
||||
- [ ] Add option to set locale in settings page
|
||||
- [ ] Rewrite jet template on load to use translated strings
|
||||
- [ ] Check if any jet template strings are ignored (false negative)
|
||||
- Setup Crowdin
|
||||
|
||||
@@ -21,6 +21,7 @@ require (
|
||||
github.com/sethvargo/go-limiter v1.0.0
|
||||
github.com/soluble-ai/go-jnode v0.1.11
|
||||
github.com/tidwall/gjson v1.18.0
|
||||
github.com/timandy/routine v1.1.4
|
||||
github.com/yargevad/filepathx v1.0.0
|
||||
github.com/zeebo/xxh3 v1.0.2
|
||||
golang.org/x/net v0.30.0
|
||||
|
||||
@@ -10,6 +10,8 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
|
||||
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/go-faker/faker/v4 v4.5.0 h1:ARzAY2XoOL9tOUK+KSecUQzyXQsUaZHefjyF8x6YFHc=
|
||||
@@ -37,18 +39,24 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
||||
github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU=
|
||||
github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sethvargo/go-envconfig v1.1.0 h1:cWZiJxeTm7AlCvzGXrEXaSTCNgip5oJepekh/BOQuog=
|
||||
github.com/sethvargo/go-envconfig v1.1.0/go.mod h1:JLd0KFWQYzyENqnEPWWZ49i4vzZo/6nRidxI8YvGiHw=
|
||||
github.com/sethvargo/go-limiter v1.0.0 h1:JqW13eWEMn0VFv86OKn8wiYJY/m250WoXdrjRV0kLe4=
|
||||
github.com/sethvargo/go-limiter v1.0.0/go.mod h1:01b6tW25Ap+MeLYBuD4aHunMrJoNO5PVUFdS9rac3II=
|
||||
github.com/soluble-ai/go-jnode v0.1.11 h1:To9h6zWI6qr5Vphz0XO4JtCRlkhfilH2EDNwtAZkZT4=
|
||||
github.com/soluble-ai/go-jnode v0.1.11/go.mod h1:mKFUM7xxXMBVOygZeE8od2Qls1f3E3NHY1ZhMlzwx/U=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/timandy/routine v1.1.4 h1:L9eAli/ROJcW6LhmwZcusYQcdAqxAXGOQhEXLQSNWOA=
|
||||
github.com/timandy/routine v1.1.4/go.mod h1:siBcl8iIsGmhLCajRGRcy7Y7FVcicNXkr97JODdt9fc=
|
||||
github.com/yargevad/filepathx v1.0.0 h1:SYcT+N3tYGi+NvazubCNlvgIPbzAk7i7y2dwg3I5FYc=
|
||||
github.com/yargevad/filepathx v1.0.0/go.mod h1:BprfX/gpYNJHJfc35GjRRpVcwWXS89gGulUIU5tK3tA=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
@@ -97,3 +105,5 @@ golang.org/x/tools v0.0.0-20191203134012-c197fd4bf371/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
+15
-5
@@ -3,26 +3,36 @@ package i18n
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/timandy/routine"
|
||||
)
|
||||
|
||||
var GlobalLocale string = "en"
|
||||
var Locale = routine.NewInheritableThreadLocal[string]()
|
||||
|
||||
func getLocalizer() Localizer {
|
||||
locale := Locale.Get()
|
||||
if locale == "" {
|
||||
locale = "en"
|
||||
}
|
||||
return LocalizerOf(locale)
|
||||
}
|
||||
|
||||
func Error(text string) error {
|
||||
text = LocalizerOf(GlobalLocale).lookup(text)
|
||||
text = getLocalizer().lookup(text)
|
||||
return errors.New(text)
|
||||
}
|
||||
|
||||
func Errorf(format string, a ...any) error {
|
||||
format = LocalizerOf(GlobalLocale).lookup(format)
|
||||
format = getLocalizer().lookup(format)
|
||||
return fmt.Errorf(format, a...)
|
||||
}
|
||||
|
||||
func Sprintf(format string, a ...any) string {
|
||||
format = LocalizerOf(GlobalLocale).lookup(format)
|
||||
format = getLocalizer().lookup(format)
|
||||
return fmt.Sprintf(format, a...)
|
||||
}
|
||||
|
||||
// translate string
|
||||
func Tr(text string) string {
|
||||
return LocalizerOf(GlobalLocale).lookup(text)
|
||||
return getLocalizer().lookup(text)
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ func LocalizerOf(locale string) Localizer {
|
||||
return Localizer{locale: locale}
|
||||
}
|
||||
|
||||
// translate string
|
||||
// lookup string in the database
|
||||
func (l Localizer) lookup(text string) string {
|
||||
translation_map, exist := locales[l.locale]
|
||||
if !exist {
|
||||
|
||||
@@ -30,28 +30,30 @@ func main() {
|
||||
|
||||
// Conditionally initialize and start the proxy checker
|
||||
if config.GlobalConfig.ProxyCheckEnabled {
|
||||
var wg_firstCheck sync.WaitGroup
|
||||
wg_firstCheck.Add(1)
|
||||
|
||||
go func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.ProxyCheckTimeout)
|
||||
proxy_checker.CheckProxies(ctx)
|
||||
cancel()
|
||||
wg_firstCheck.Done()
|
||||
if config.GlobalConfig.ProxyCheckInterval != 0 {
|
||||
for {
|
||||
time.Sleep(config.GlobalConfig.ProxyCheckInterval)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.ProxyCheckTimeout)
|
||||
proxy_checker.CheckProxies(ctx)
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}()
|
||||
var wg_firstCheck sync.WaitGroup
|
||||
wg_firstCheck.Add(1)
|
||||
|
||||
// Wait for the first proxy check to complete
|
||||
log.Println("Waiting for initial proxy check to complete...")
|
||||
wg_firstCheck.Wait()
|
||||
log.Println("Initial proxy check completed.")
|
||||
go func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.ProxyCheckTimeout)
|
||||
proxy_checker.CheckProxies(ctx)
|
||||
cancel()
|
||||
wg_firstCheck.Done()
|
||||
if config.GlobalConfig.ProxyCheckInterval != 0 {
|
||||
for {
|
||||
time.Sleep(config.GlobalConfig.ProxyCheckInterval)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.ProxyCheckTimeout)
|
||||
proxy_checker.CheckProxies(ctx)
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for the first proxy check to complete
|
||||
log.Println("Waiting for initial proxy check to complete...")
|
||||
wg_firstCheck.Wait()
|
||||
log.Println("Initial proxy check completed.")
|
||||
}()
|
||||
} else {
|
||||
log.Println("Skipping proxy checker initialization.")
|
||||
}
|
||||
@@ -60,10 +62,11 @@ func main() {
|
||||
|
||||
router := middleware.DefineRoutes()
|
||||
// the first middleware is the most outer / first executed one
|
||||
router.Use(middleware.ProvideUserContext) // needed for everything else
|
||||
router.Use(middleware.LogRequest) // all pages need this
|
||||
router.Use(middleware.SetPrivacyHeaders) // all pages need this
|
||||
router.Use(middleware.HandleError) // if the inner handler fails, this shows the error page instead
|
||||
router.Use(middleware.ProvideUserContext) // needed for everything else
|
||||
router.Use(middleware.SetLocaleFromCookie) // needed for i18n.*()
|
||||
router.Use(middleware.LogRequest) // all pages need this
|
||||
router.Use(middleware.SetPrivacyHeaders) // all pages need this
|
||||
router.Use(middleware.HandleError) // if the inner handler fails, this shows the error page instead
|
||||
router.Use(middleware.InitializeRateLimiter())
|
||||
|
||||
// watch and compile sass when in development mode
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"codeberg.org/vnpower/pixivfe/v2/i18n"
|
||||
"codeberg.org/vnpower/pixivfe/v2/server/session"
|
||||
)
|
||||
|
||||
// ProvideUserContext is a middleware that wraps an http.Handler
|
||||
// to inject a user context into each incoming request.
|
||||
func SetLocaleFromCookie(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
i18n.Locale.Set(session.GetCookie(r, session.Cookie_Locale))
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -21,6 +21,7 @@ const ( // the __Host thing force it to be secure and same-origin (no subdomain)
|
||||
Cookie_HideArtR18 CookieName = "pixivfe-HideArtR18"
|
||||
Cookie_HideArtR18G CookieName = "pixivfe-HideArtR18G"
|
||||
Cookie_HideArtAI CookieName = "pixivfe-HideArtAI"
|
||||
Cookie_Locale CookieName = "pixivfe-Locale"
|
||||
)
|
||||
|
||||
// Go can't make this a const...
|
||||
@@ -35,6 +36,7 @@ var AllCookieNames []CookieName = []CookieName{
|
||||
Cookie_HideArtR18,
|
||||
Cookie_HideArtR18G,
|
||||
Cookie_HideArtAI,
|
||||
Cookie_Locale,
|
||||
}
|
||||
|
||||
func GetCookie(r *http.Request, name CookieName) string {
|
||||
|
||||
Reference in New Issue
Block a user