mirror of
https://github.com/unmojang/drasl.git
synced 2025-09-08 22:56:49 -04:00
Initial i18n support
This commit is contained in:
parent
ecd485cc1d
commit
38d533581b
2
Makefile
2
Makefile
@ -23,7 +23,7 @@ install: build
|
|||||||
install -Dm 755 drasl "$(prefix)/bin/drasl"
|
install -Dm 755 drasl "$(prefix)/bin/drasl"
|
||||||
install -Dm 644 LICENSE "$(prefix)/share/licenses/drasl/LICENSE"
|
install -Dm 644 LICENSE "$(prefix)/share/licenses/drasl/LICENSE"
|
||||||
mkdir -p "$(prefix)/share/drasl/"
|
mkdir -p "$(prefix)/share/drasl/"
|
||||||
cp -R assets view public "$(prefix)/share/drasl/"
|
cp -R assets view public locales "$(prefix)/share/drasl/"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f drasl
|
rm -f drasl
|
||||||
|
178
front.go
178
front.go
@ -10,9 +10,11 @@ import (
|
|||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/jxskiss/base62"
|
"github.com/jxskiss/base62"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
"github.com/samber/mo"
|
"github.com/samber/mo"
|
||||||
"github.com/zitadel/oidc/v3/pkg/client/rp"
|
"github.com/zitadel/oidc/v3/pkg/client/rp"
|
||||||
"github.com/zitadel/oidc/v3/pkg/oidc"
|
"github.com/zitadel/oidc/v3/pkg/oidc"
|
||||||
|
"golang.org/x/text/language"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
@ -28,6 +30,7 @@ import (
|
|||||||
Web front end for creating user accounts, changing passwords, skins, player names, etc.
|
Web front end for creating user accounts, changing passwords, skins, player names, etc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const CONTEXT_KEY_LOCALE = "DraslLocale"
|
||||||
const BROWSER_TOKEN_AGE_SEC = 24 * 60 * 60
|
const BROWSER_TOKEN_AGE_SEC = 24 * 60 * 60
|
||||||
const COOKIE_PREFIX = "__Host-"
|
const COOKIE_PREFIX = "__Host-"
|
||||||
const BROWSER_TOKEN_COOKIE_NAME = COOKIE_PREFIX + "browserToken"
|
const BROWSER_TOKEN_COOKIE_NAME = COOKIE_PREFIX + "browserToken"
|
||||||
@ -82,6 +85,21 @@ func NewTemplate(app *App) *Template {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *App) GetLanguageMiddleware() func(echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
matcher := language.NewMatcher(app.LocaleTags)
|
||||||
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
header := c.Request().Header.Get("Accept-Language")
|
||||||
|
t, _, _ := language.ParseAcceptLanguage(header)
|
||||||
|
// Use only the returned index, not the returned tag: https://github.com/golang/go/issues/24211
|
||||||
|
_, localeTagIndex, _ := matcher.Match(t...)
|
||||||
|
l := app.Locales[app.LocaleTags[localeTagIndex]]
|
||||||
|
c.Set(CONTEXT_KEY_LOCALE, l)
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
||||||
return t.Templates[name].ExecuteTemplate(w, "base", data)
|
return t.Templates[name].ExecuteTemplate(w, "base", data)
|
||||||
}
|
}
|
||||||
@ -138,15 +156,31 @@ func NewWebError(returnURL string, message string, args ...interface{}) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type errorContext struct {
|
type baseContext struct {
|
||||||
App *App
|
App *App
|
||||||
User *User
|
L *gotext.Locale
|
||||||
URL string
|
URL string
|
||||||
SuccessMessage string
|
SuccessMessage string
|
||||||
WarningMessage string
|
WarningMessage string
|
||||||
ErrorMessage string
|
ErrorMessage string
|
||||||
Message string
|
}
|
||||||
StatusCode int
|
|
||||||
|
func (app *App) NewBaseContext(c *echo.Context) baseContext {
|
||||||
|
return baseContext{
|
||||||
|
App: app,
|
||||||
|
L: (*c).Get(CONTEXT_KEY_LOCALE).(*gotext.Locale),
|
||||||
|
URL: (*c).Request().URL.RequestURI(),
|
||||||
|
SuccessMessage: app.lastSuccessMessage(c),
|
||||||
|
WarningMessage: app.lastWarningMessage(c),
|
||||||
|
ErrorMessage: app.lastErrorMessage(c),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type errorContext struct {
|
||||||
|
baseContext
|
||||||
|
User *User
|
||||||
|
Message string
|
||||||
|
StatusCode int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set error message and redirect
|
// Set error message and redirect
|
||||||
@ -182,14 +216,10 @@ func (app *App) HandleWebError(err error, c *echo.Context) error {
|
|||||||
}
|
}
|
||||||
if Contains(safeMethods, (*c).Request().Method) {
|
if Contains(safeMethods, (*c).Request().Method) {
|
||||||
return (*c).Render(code, "error", errorContext{
|
return (*c).Render(code, "error", errorContext{
|
||||||
App: app,
|
baseContext: app.NewBaseContext(c),
|
||||||
User: nil,
|
User: nil,
|
||||||
URL: (*c).Request().URL.RequestURI(),
|
Message: message,
|
||||||
Message: message,
|
StatusCode: code,
|
||||||
SuccessMessage: app.lastSuccessMessage(c),
|
|
||||||
WarningMessage: app.lastWarningMessage(c),
|
|
||||||
ErrorMessage: app.lastErrorMessage(c),
|
|
||||||
StatusCode: code,
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
returnURL := getReturnURL(app, c)
|
returnURL := getReturnURL(app, c)
|
||||||
@ -301,13 +331,9 @@ func EncodeOIDCState(state oidcState) (string, error) {
|
|||||||
// GET /
|
// GET /
|
||||||
func FrontRoot(app *App) func(c echo.Context) error {
|
func FrontRoot(app *App) func(c echo.Context) error {
|
||||||
type rootContext struct {
|
type rootContext struct {
|
||||||
App *App
|
baseContext
|
||||||
User *User
|
User *User
|
||||||
URL string
|
|
||||||
Destination string
|
Destination string
|
||||||
SuccessMessage string
|
|
||||||
WarningMessage string
|
|
||||||
ErrorMessage string
|
|
||||||
WebOIDCProviders []webOIDCProvider
|
WebOIDCProviders []webOIDCProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,13 +374,9 @@ func FrontRoot(app *App) func(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return c.Render(http.StatusOK, "root", rootContext{
|
return c.Render(http.StatusOK, "root", rootContext{
|
||||||
App: app,
|
baseContext: app.NewBaseContext(&c),
|
||||||
User: user,
|
User: user,
|
||||||
URL: c.Request().URL.RequestURI(),
|
|
||||||
Destination: destination,
|
Destination: destination,
|
||||||
SuccessMessage: app.lastSuccessMessage(&c),
|
|
||||||
WarningMessage: app.lastWarningMessage(&c),
|
|
||||||
ErrorMessage: app.lastErrorMessage(&c),
|
|
||||||
WebOIDCProviders: webOIDCProviders,
|
WebOIDCProviders: webOIDCProviders,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -408,12 +430,8 @@ type oidcState struct {
|
|||||||
// GET /registration
|
// GET /registration
|
||||||
func FrontRegistration(app *App) func(c echo.Context) error {
|
func FrontRegistration(app *App) func(c echo.Context) error {
|
||||||
type registrationContext struct {
|
type registrationContext struct {
|
||||||
App *App
|
baseContext
|
||||||
User *User
|
User *User
|
||||||
URL string
|
|
||||||
SuccessMessage string
|
|
||||||
WarningMessage string
|
|
||||||
ErrorMessage string
|
|
||||||
InviteCode string
|
InviteCode string
|
||||||
WebOIDCProviders []webOIDCProvider
|
WebOIDCProviders []webOIDCProvider
|
||||||
}
|
}
|
||||||
@ -454,12 +472,8 @@ func FrontRegistration(app *App) func(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return c.Render(http.StatusOK, "registration", registrationContext{
|
return c.Render(http.StatusOK, "registration", registrationContext{
|
||||||
App: app,
|
baseContext: app.NewBaseContext(&c),
|
||||||
User: user,
|
User: user,
|
||||||
URL: c.Request().URL.RequestURI(),
|
|
||||||
SuccessMessage: app.lastSuccessMessage(&c),
|
|
||||||
WarningMessage: app.lastWarningMessage(&c),
|
|
||||||
ErrorMessage: app.lastErrorMessage(&c),
|
|
||||||
InviteCode: inviteCode,
|
InviteCode: inviteCode,
|
||||||
WebOIDCProviders: webOIDCProviders,
|
WebOIDCProviders: webOIDCProviders,
|
||||||
})
|
})
|
||||||
@ -502,12 +516,8 @@ func (app *App) getIDTokenCookie(c *echo.Context) (*OIDCProvider, string, oidc.I
|
|||||||
|
|
||||||
func FrontCompleteRegistration(app *App) func(c echo.Context) error {
|
func FrontCompleteRegistration(app *App) func(c echo.Context) error {
|
||||||
type completeRegistrationContext struct {
|
type completeRegistrationContext struct {
|
||||||
App *App
|
baseContext
|
||||||
User *User
|
User *User
|
||||||
URL string
|
|
||||||
SuccessMessage string
|
|
||||||
WarningMessage string
|
|
||||||
ErrorMessage string
|
|
||||||
InviteCode string
|
InviteCode string
|
||||||
AnyUnmigratedUsers bool
|
AnyUnmigratedUsers bool
|
||||||
AllowChoosingPlayerName bool
|
AllowChoosingPlayerName bool
|
||||||
@ -547,12 +557,8 @@ func FrontCompleteRegistration(app *App) func(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return c.Render(http.StatusOK, "complete-registration", completeRegistrationContext{
|
return c.Render(http.StatusOK, "complete-registration", completeRegistrationContext{
|
||||||
App: app,
|
baseContext: app.NewBaseContext(&c),
|
||||||
User: user,
|
User: user,
|
||||||
URL: c.Request().URL.RequestURI(),
|
|
||||||
SuccessMessage: app.lastSuccessMessage(&c),
|
|
||||||
WarningMessage: app.lastWarningMessage(&c),
|
|
||||||
ErrorMessage: app.lastErrorMessage(&c),
|
|
||||||
InviteCode: inviteCode,
|
InviteCode: inviteCode,
|
||||||
PreferredPlayerName: preferredPlayerName,
|
PreferredPlayerName: preferredPlayerName,
|
||||||
AllowChoosingPlayerName: provider.Config.AllowChoosingPlayerName,
|
AllowChoosingPlayerName: provider.Config.AllowChoosingPlayerName,
|
||||||
@ -775,14 +781,10 @@ func FrontOIDCCallback(app *App) func(c echo.Context) error {
|
|||||||
// GET /web/admin
|
// GET /web/admin
|
||||||
func FrontAdmin(app *App) func(c echo.Context) error {
|
func FrontAdmin(app *App) func(c echo.Context) error {
|
||||||
type adminContext struct {
|
type adminContext struct {
|
||||||
App *App
|
baseContext
|
||||||
User *User
|
User *User
|
||||||
URL string
|
Users []User
|
||||||
SuccessMessage string
|
Invites []Invite
|
||||||
WarningMessage string
|
|
||||||
ErrorMessage string
|
|
||||||
Users []User
|
|
||||||
Invites []Invite
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return withBrowserAdmin(app, func(c echo.Context, user *User) error {
|
return withBrowserAdmin(app, func(c echo.Context, user *User) error {
|
||||||
@ -799,14 +801,10 @@ func FrontAdmin(app *App) func(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return c.Render(http.StatusOK, "admin", adminContext{
|
return c.Render(http.StatusOK, "admin", adminContext{
|
||||||
App: app,
|
baseContext: app.NewBaseContext(&c),
|
||||||
User: user,
|
User: user,
|
||||||
URL: c.Request().URL.RequestURI(),
|
Users: users,
|
||||||
SuccessMessage: app.lastSuccessMessage(&c),
|
Invites: invites,
|
||||||
WarningMessage: app.lastWarningMessage(&c),
|
|
||||||
ErrorMessage: app.lastErrorMessage(&c),
|
|
||||||
Users: users,
|
|
||||||
Invites: invites,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -925,12 +923,8 @@ func FrontNewInvite(app *App) func(c echo.Context) error {
|
|||||||
// GET /web/user/:uuid
|
// GET /web/user/:uuid
|
||||||
func FrontUser(app *App) func(c echo.Context) error {
|
func FrontUser(app *App) func(c echo.Context) error {
|
||||||
type userContext struct {
|
type userContext struct {
|
||||||
App *App
|
baseContext
|
||||||
User *User
|
User *User
|
||||||
URL string
|
|
||||||
SuccessMessage string
|
|
||||||
WarningMessage string
|
|
||||||
ErrorMessage string
|
|
||||||
TargetUser *User
|
TargetUser *User
|
||||||
TargetUserID string
|
TargetUserID string
|
||||||
SkinURL *string
|
SkinURL *string
|
||||||
@ -1014,12 +1008,8 @@ func FrontUser(app *App) func(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return c.Render(http.StatusOK, "user", userContext{
|
return c.Render(http.StatusOK, "user", userContext{
|
||||||
App: app,
|
baseContext: app.NewBaseContext(&c),
|
||||||
User: user,
|
User: user,
|
||||||
URL: c.Request().URL.RequestURI(),
|
|
||||||
SuccessMessage: app.lastSuccessMessage(&c),
|
|
||||||
WarningMessage: app.lastWarningMessage(&c),
|
|
||||||
ErrorMessage: app.lastErrorMessage(&c),
|
|
||||||
TargetUser: targetUser,
|
TargetUser: targetUser,
|
||||||
AdminView: adminView,
|
AdminView: adminView,
|
||||||
LinkedOIDCProviderNames: linkedOIDCProviderNames.ToSlice(),
|
LinkedOIDCProviderNames: linkedOIDCProviderNames.ToSlice(),
|
||||||
@ -1032,18 +1022,14 @@ func FrontUser(app *App) func(c echo.Context) error {
|
|||||||
// GET /web/player/:uuid
|
// GET /web/player/:uuid
|
||||||
func FrontPlayer(app *App) func(c echo.Context) error {
|
func FrontPlayer(app *App) func(c echo.Context) error {
|
||||||
type playerContext struct {
|
type playerContext struct {
|
||||||
App *App
|
baseContext
|
||||||
User *User
|
User *User
|
||||||
URL string
|
PlayerUser *User
|
||||||
SuccessMessage string
|
Player *Player
|
||||||
WarningMessage string
|
PlayerID string
|
||||||
ErrorMessage string
|
SkinURL *string
|
||||||
PlayerUser *User
|
CapeURL *string
|
||||||
Player *Player
|
AdminView bool
|
||||||
PlayerID string
|
|
||||||
SkinURL *string
|
|
||||||
CapeURL *string
|
|
||||||
AdminView bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return withBrowserAuthentication(app, true, func(c echo.Context, user *User) error {
|
return withBrowserAuthentication(app, true, func(c echo.Context, user *User) error {
|
||||||
@ -1081,18 +1067,14 @@ func FrontPlayer(app *App) func(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return c.Render(http.StatusOK, "player", playerContext{
|
return c.Render(http.StatusOK, "player", playerContext{
|
||||||
App: app,
|
baseContext: app.NewBaseContext(&c),
|
||||||
User: user,
|
User: user,
|
||||||
URL: c.Request().URL.RequestURI(),
|
PlayerUser: &playerUser,
|
||||||
SuccessMessage: app.lastSuccessMessage(&c),
|
Player: &player,
|
||||||
WarningMessage: app.lastWarningMessage(&c),
|
PlayerID: id,
|
||||||
ErrorMessage: app.lastErrorMessage(&c),
|
SkinURL: skinURL,
|
||||||
PlayerUser: &playerUser,
|
CapeURL: capeURL,
|
||||||
Player: &player,
|
AdminView: adminView,
|
||||||
PlayerID: id,
|
|
||||||
SkinURL: skinURL,
|
|
||||||
CapeURL: capeURL,
|
|
||||||
AdminView: adminView,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1283,12 +1265,8 @@ func FrontRegisterChallenge(app *App) func(c echo.Context) error {
|
|||||||
|
|
||||||
func frontChallenge(app *App, action string) func(c echo.Context) error {
|
func frontChallenge(app *App, action string) func(c echo.Context) error {
|
||||||
type challengeContext struct {
|
type challengeContext struct {
|
||||||
App *App
|
baseContext
|
||||||
User *User
|
User *User
|
||||||
URL string
|
|
||||||
SuccessMessage string
|
|
||||||
WarningMessage string
|
|
||||||
ErrorMessage string
|
|
||||||
PlayerName string
|
PlayerName string
|
||||||
RegistrationProvider string
|
RegistrationProvider string
|
||||||
SkinBase64 string
|
SkinBase64 string
|
||||||
@ -1372,12 +1350,8 @@ func frontChallenge(app *App, action string) func(c echo.Context) error {
|
|||||||
skinBase64 := base64.StdEncoding.EncodeToString(challengeSkinBytes)
|
skinBase64 := base64.StdEncoding.EncodeToString(challengeSkinBytes)
|
||||||
|
|
||||||
return c.Render(http.StatusOK, "challenge", challengeContext{
|
return c.Render(http.StatusOK, "challenge", challengeContext{
|
||||||
App: app,
|
baseContext: app.NewBaseContext(&c),
|
||||||
User: user,
|
User: user,
|
||||||
URL: c.Request().URL.RequestURI(),
|
|
||||||
SuccessMessage: app.lastSuccessMessage(&c),
|
|
||||||
WarningMessage: app.lastWarningMessage(&c),
|
|
||||||
ErrorMessage: app.lastErrorMessage(&c),
|
|
||||||
PlayerName: playerName,
|
PlayerName: playerName,
|
||||||
SkinBase64: skinBase64,
|
SkinBase64: skinBase64,
|
||||||
SkinFilename: playerName + "-challenge.png",
|
SkinFilename: playerName + "-challenge.png",
|
||||||
|
5
go.mod
5
go.mod
@ -1,8 +1,8 @@
|
|||||||
module unmojang.org/drasl
|
module unmojang.org/drasl
|
||||||
|
|
||||||
go 1.23.0
|
go 1.23.5
|
||||||
|
|
||||||
toolchain go1.23.2
|
toolchain go1.23.10
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v1.3.2
|
github.com/BurntSushi/toml v1.3.2
|
||||||
@ -38,6 +38,7 @@ require (
|
|||||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||||
github.com/kr/pretty v0.3.1 // indirect
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/labstack/gommon v0.4.2 // indirect
|
github.com/labstack/gommon v0.4.2 // indirect
|
||||||
|
github.com/leonelquinteros/gotext v1.7.2 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.18 // indirect
|
github.com/mattn/go-sqlite3 v1.14.18 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -64,6 +64,8 @@ github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zG
|
|||||||
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
|
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
|
||||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||||
|
github.com/leonelquinteros/gotext v1.7.2 h1:bDPndU8nt+/kRo1m4l/1OXiiy2v7Z7dfPQ9+YP7G1Mc=
|
||||||
|
github.com/leonelquinteros/gotext v1.7.2/go.mod h1:9/haCkm5P7Jay1sxKDGJ5WIg4zkz8oZKw4ekNpALob8=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
0
locales/en-US/default.po
Normal file
0
locales/en-US/default.po
Normal file
7
locales/es/default.po
Normal file
7
locales/es/default.po
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Language: es\n"
|
||||||
|
|
||||||
|
msgid "Register"
|
||||||
|
msgstr "Registrarse"
|
79
main.go
79
main.go
@ -13,8 +13,10 @@ import (
|
|||||||
"github.com/dgraph-io/ristretto"
|
"github.com/dgraph-io/ristretto"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
"github.com/zitadel/oidc/v3/pkg/client/rp"
|
"github.com/zitadel/oidc/v3/pkg/client/rp"
|
||||||
httphelper "github.com/zitadel/oidc/v3/pkg/http"
|
httphelper "github.com/zitadel/oidc/v3/pkg/http"
|
||||||
|
"golang.org/x/text/language"
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"image"
|
"image"
|
||||||
@ -25,6 +27,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -71,6 +74,8 @@ type App struct {
|
|||||||
OIDCProvidersByName map[string]*OIDCProvider
|
OIDCProvidersByName map[string]*OIDCProvider
|
||||||
OIDCProvidersByIssuer map[string]*OIDCProvider
|
OIDCProvidersByIssuer map[string]*OIDCProvider
|
||||||
FallbackAPIServers []FallbackAPIServer
|
FallbackAPIServers []FallbackAPIServer
|
||||||
|
Locales map[language.Tag]*gotext.Locale
|
||||||
|
LocaleTags []language.Tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func LogInfo(args ...interface{}) {
|
func LogInfo(args ...interface{}) {
|
||||||
@ -195,31 +200,36 @@ func (app *App) MakeServer() *echo.Echo {
|
|||||||
t := NewTemplate(app)
|
t := NewTemplate(app)
|
||||||
e.Renderer = t
|
e.Renderer = t
|
||||||
frontUser := FrontUser(app)
|
frontUser := FrontUser(app)
|
||||||
e.GET("/", FrontRoot(app))
|
|
||||||
e.GET("/web/admin", FrontAdmin(app))
|
getLanguage := app.GetLanguageMiddleware()
|
||||||
e.GET("/web/complete-registration", FrontCompleteRegistration(app))
|
|
||||||
e.GET("/web/create-player-challenge", FrontCreatePlayerChallenge(app))
|
e.GET("/", FrontRoot(app), getLanguage)
|
||||||
e.GET("/web/manifest.webmanifest", FrontWebManifest(app))
|
g := e.Group("/web")
|
||||||
e.GET("/web/oidc-callback/:providerName", FrontOIDCCallback(app))
|
g.Use(getLanguage)
|
||||||
e.GET("/web/player/:uuid", FrontPlayer(app))
|
g.GET("/admin", FrontAdmin(app))
|
||||||
e.GET("/web/register-challenge", FrontRegisterChallenge(app))
|
g.GET("/complete-registration", FrontCompleteRegistration(app))
|
||||||
e.GET("/web/registration", FrontRegistration(app))
|
g.GET("/create-player-challenge", FrontCreatePlayerChallenge(app))
|
||||||
e.GET("/web/user", frontUser)
|
g.GET("/manifest.webmanifest", FrontWebManifest(app))
|
||||||
e.GET("/web/user/:uuid", frontUser)
|
g.GET("/oidc-callback/:providerName", FrontOIDCCallback(app))
|
||||||
e.POST("/web/admin/delete-invite", FrontDeleteInvite(app))
|
g.GET("/player/:uuid", FrontPlayer(app))
|
||||||
e.POST("/web/admin/new-invite", FrontNewInvite(app))
|
g.GET("/register-challenge", FrontRegisterChallenge(app))
|
||||||
e.POST("/web/admin/update-users", FrontUpdateUsers(app))
|
g.GET("/registration", FrontRegistration(app))
|
||||||
e.POST("/web/create-player", FrontCreatePlayer(app))
|
g.GET("/user", frontUser)
|
||||||
e.POST("/web/delete-player", FrontDeletePlayer(app))
|
g.GET("/user/:uuid", frontUser)
|
||||||
e.POST("/web/delete-user", FrontDeleteUser(app))
|
g.POST("/admin/delete-invite", FrontDeleteInvite(app))
|
||||||
e.POST("/web/login", FrontLogin(app))
|
g.POST("/admin/new-invite", FrontNewInvite(app))
|
||||||
e.POST("/web/logout", FrontLogout(app))
|
g.POST("/admin/update-users", FrontUpdateUsers(app))
|
||||||
e.POST("/web/oidc-migrate", app.FrontOIDCMigrate())
|
g.POST("/create-player", FrontCreatePlayer(app))
|
||||||
e.POST("/web/oidc-unlink", app.FrontOIDCUnlink())
|
g.POST("/delete-player", FrontDeletePlayer(app))
|
||||||
e.POST("/web/register", FrontRegister(app))
|
g.POST("/delete-user", FrontDeleteUser(app))
|
||||||
e.POST("/web/update-player", FrontUpdatePlayer(app))
|
g.POST("/login", FrontLogin(app))
|
||||||
e.POST("/web/update-user", FrontUpdateUser(app))
|
g.POST("/logout", FrontLogout(app))
|
||||||
e.Static("/web/public", path.Join(app.Config.DataDirectory, "public"))
|
g.POST("/oidc-migrate", app.FrontOIDCMigrate())
|
||||||
|
g.POST("/oidc-unlink", app.FrontOIDCUnlink())
|
||||||
|
g.POST("/register", FrontRegister(app))
|
||||||
|
g.POST("/update-player", FrontUpdatePlayer(app))
|
||||||
|
g.POST("/update-user", FrontUpdateUser(app))
|
||||||
|
g.Static("/public", path.Join(app.Config.DataDirectory, "public"))
|
||||||
}
|
}
|
||||||
e.Static("/web/texture/cape", path.Join(app.Config.StateDirectory, "cape"))
|
e.Static("/web/texture/cape", path.Join(app.Config.StateDirectory, "cape"))
|
||||||
e.Static("/web/texture/default-cape", path.Join(app.Config.StateDirectory, "default-cape"))
|
e.Static("/web/texture/default-cape", path.Join(app.Config.StateDirectory, "default-cape"))
|
||||||
@ -425,6 +435,23 @@ func setup(config *Config) *App {
|
|||||||
log.Fatalf("Couldn't access DataDirectory: %s", err)
|
log.Fatalf("Couldn't access DataDirectory: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Locales
|
||||||
|
locales := map[language.Tag]*gotext.Locale{}
|
||||||
|
localeTags := make([]language.Tag, 0)
|
||||||
|
locales_path := path.Join(config.DataDirectory, "locales")
|
||||||
|
lang_paths, err := filepath.Glob(path.Join(locales_path, "*"))
|
||||||
|
for _, lang_path := range lang_paths {
|
||||||
|
lang := filepath.Base(lang_path)
|
||||||
|
tag, err := language.Parse(lang)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unrecognized language tag: %s", lang)
|
||||||
|
}
|
||||||
|
l := gotext.NewLocale(locales_path, lang)
|
||||||
|
l.AddDomain("default")
|
||||||
|
localeTags = append(localeTags, tag)
|
||||||
|
locales[tag] = l
|
||||||
|
}
|
||||||
|
|
||||||
// Crypto
|
// Crypto
|
||||||
key := ReadOrCreateKey(config)
|
key := ReadOrCreateKey(config)
|
||||||
keyBytes := Unwrap(x509.MarshalPKCS8PrivateKey(key))
|
keyBytes := Unwrap(x509.MarshalPKCS8PrivateKey(key))
|
||||||
@ -575,6 +602,8 @@ func setup(config *Config) *App {
|
|||||||
OIDCProvidersByName: oidcProvidersByName,
|
OIDCProvidersByName: oidcProvidersByName,
|
||||||
OIDCProvidersByIssuer: oidcProvidersByIssuer,
|
OIDCProvidersByIssuer: oidcProvidersByIssuer,
|
||||||
FallbackAPIServers: fallbackAPIServers,
|
FallbackAPIServers: fallbackAPIServers,
|
||||||
|
Locales: locales,
|
||||||
|
LocaleTags: localeTags,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post-setup
|
// Post-setup
|
||||||
|
@ -92,7 +92,7 @@ a:visited {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
font-family: Helvetica, Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
color: white;
|
color: white;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<input type="submit" value="Log out" />
|
<input type="submit" value="Log out" />
|
||||||
</form>
|
</form>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<a href="{{ .App.FrontEndURL }}/web/registration">Register</a>
|
<a href="{{ .App.FrontEndURL }}/web/registration">{{ .L.Get "Register" }}</a>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user