diff --git a/cmd/dashboard/controller/controller.go b/cmd/dashboard/controller/controller.go index 2b576e9..35350ed 100644 --- a/cmd/dashboard/controller/controller.go +++ b/cmd/dashboard/controller/controller.go @@ -12,6 +12,7 @@ import ( "code.cloudfoundry.org/bytefmt" "github.com/gin-contrib/pprof" "github.com/gin-gonic/gin" + "github.com/nicksnyder/go-i18n/v2/i18n" "github.com/naiba/nezha/pkg/mygin" "github.com/naiba/nezha/service/singleton" @@ -26,6 +27,18 @@ func ServeWeb(port uint) *http.Server { } r.Use(mygin.RecordPath) r.SetFuncMap(template.FuncMap{ + "tr": func(id string, dataAndCount ...interface{}) string { + conf := i18n.LocalizeConfig{ + MessageID: id, + } + if len(dataAndCount) > 1 { + conf.TemplateData = dataAndCount[1] + } + if len(dataAndCount) > 2 { + conf.PluralCount = dataAndCount[2] + } + return singleton.Localizer.MustLocalize(&conf) + }, "tf": func(t time.Time) string { return t.In(singleton.Loc).Format("2006年1月2号 15:04:05") }, diff --git a/cmd/dashboard/main.go b/cmd/dashboard/main.go index 540c2cf..f7e6c2e 100644 --- a/cmd/dashboard/main.go +++ b/cmd/dashboard/main.go @@ -2,12 +2,13 @@ package main import ( "context" + "log" + "github.com/naiba/nezha/cmd/dashboard/controller" "github.com/naiba/nezha/cmd/dashboard/rpc" "github.com/naiba/nezha/model" "github.com/naiba/nezha/service/singleton" "github.com/ory/graceful" - "log" ) func init() { @@ -15,6 +16,7 @@ func init() { singleton.Init() singleton.InitConfigFromPath("data/config.yaml") singleton.InitDBFromPath("data/sqlite.db") + singleton.InitLocalizer() initSystem() } diff --git a/cmd/playground/main.go b/cmd/playground/main.go index f2d59eb..a989b7f 100644 --- a/cmd/playground/main.go +++ b/cmd/playground/main.go @@ -3,25 +3,48 @@ package main import ( "fmt" - "github.com/jinzhu/copier" + "github.com/naiba/nezha/service/singleton" + "github.com/nicksnyder/go-i18n/v2/i18n" + "golang.org/x/text/language" ) -type Cat struct { - age int - name string - friends []string +func htmlTemplateTranslateFn(id string, data interface{}, count interface{}) string { + return singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{ + MessageID: id, + TemplateData: data, + PluralCount: count, + }) } func main() { - a := Cat{7, "Wilson", []string{"Tom", "Tabata", "Willie"}} - b := Cat{7, "Wilson", []string{"Tom", "Tabata", "Willie"}} - c := Cat{7, "Wilson", []string{"Tom", "Tabata", "Willie"}} - wilson := []*Cat{&a, &b, &c} - nikita := []Cat{} - copier.Copy(&nikita, &wilson) + singleton.InitLocalizer() + fmt.Println(singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{ + MessageID: "nezhaMonitor", + })) - nikita[0].friends = append(nikita[0].friends, "Syd") + fmt.Println(singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{ + MessageID: "nezhaMonitor", + })) - fmt.Println(wilson[0]) - fmt.Println(nikita[0]) + fmt.Println("tr nezhaMonitor", htmlTemplateTranslateFn("nezhaMonitor", nil, nil)) + fmt.Println("tr nezhaMonitor", htmlTemplateTranslateFn("nezhaMonitor", nil, 2)) + fmt.Println("tr nezhaMonitor", htmlTemplateTranslateFn("nezhaMonitor", map[string]string{ + "Ext": "Plus", + }, 2)) + + bundle := i18n.NewBundle(language.English) + localizer := i18n.NewLocalizer(bundle, "en") + catsMessage := &i18n.Message{ + ID: "Cats", + One: "I have {{.PluralCount}} cat.", + Other: "I have {{.PluralCount}} cats.", + } + fmt.Println(localizer.MustLocalize(&i18n.LocalizeConfig{ + DefaultMessage: catsMessage, + PluralCount: 1, + })) + fmt.Println(localizer.MustLocalize(&i18n.LocalizeConfig{ + DefaultMessage: catsMessage, + PluralCount: 2, + })) } diff --git a/go.mod b/go.mod index cf81e27..2192efc 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.18 require ( code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5 github.com/AlecAivazis/survey/v2 v2.3.4 + github.com/BurntSushi/toml v1.0.0 github.com/Erope/goss v0.0.0-20211230093305-df3c03fd1ed4 github.com/artdarek/go-unzip v1.0.0 github.com/blang/semver v3.5.1+incompatible @@ -19,6 +20,7 @@ require ( github.com/iamacarpet/go-winpty v1.0.2 github.com/jinzhu/copier v0.3.5 github.com/json-iterator/go v1.1.12 + github.com/nicksnyder/go-i18n/v2 v2.2.0 github.com/ory/graceful v0.1.2 github.com/p14yground/go-github-selfupdate v0.0.0-20220205132106-76a6d59b925b github.com/patrickmn/go-cache v2.1.0+incompatible @@ -30,6 +32,7 @@ require ( golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c + golang.org/x/text v0.3.7 google.golang.org/grpc v1.46.0 google.golang.org/protobuf v1.28.0 gopkg.in/yaml.v2 v2.4.0 @@ -80,7 +83,6 @@ require ( golang.org/x/net v0.0.0-20220412020605-290c469a71a5 // indirect golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.3.7 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac // indirect gopkg.in/ini.v1 v1.66.4 // indirect diff --git a/go.sum b/go.sum index f4ae231..85b762f 100644 --- a/go.sum +++ b/go.sum @@ -41,6 +41,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/AlecAivazis/survey/v2 v2.3.4 h1:pchTU9rsLUSvWEl2Aq9Pv3k0IE2fkqtGxazskAMd9Ng= github.com/AlecAivazis/survey/v2 v2.3.4/go.mod h1:hrV6Y/kQCLhIZXGcriDCUBtB3wnN7156gMXJ3+b23xM= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= +github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Erope/goss v0.0.0-20211230093305-df3c03fd1ed4 h1:X35U3bryt+j2a9RZyXyBPISNIYQsfNKWC/d/B8J861I= github.com/Erope/goss v0.0.0-20211230093305-df3c03fd1ed4/go.mod h1:gl55GUYOV6rvsL/V23GdfRNdnreh+McD5Yo1sNc+Qe0= @@ -203,7 +205,6 @@ github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= @@ -238,9 +239,6 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ= -github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= @@ -253,6 +251,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/nicksnyder/go-i18n/v2 v2.2.0 h1:MNXbyPvd141JJqlU6gJKrczThxJy+kdCNivxZpBQFkw= +github.com/nicksnyder/go-i18n/v2 v2.2.0/go.mod h1:4OtLfzqyAxsscyCb//3gfqSvBc81gImX91LrZzczN1o= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -652,7 +652,6 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= @@ -691,11 +690,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= -gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg= gorm.io/driver/sqlite v1.3.2 h1:nWTy4cE52K6nnMhv23wLmur9Y3qWbZvOBz+V4PrGAxg= gorm.io/driver/sqlite v1.3.2/go.mod h1:B+8GyC9K7VgzJAcrcXMRPdnMcck+8FgJynEehEPM16U= -gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.4 h1:1BKWM67O6CflSLcwGQR7ccfmC4ebOxQrTfOQGRE9wjg= gorm.io/gorm v1.23.4/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/model/config.go b/model/config.go index e509104..aa7f106 100644 --- a/model/config.go +++ b/model/config.go @@ -51,8 +51,9 @@ func (c *AgentConfig) Save() error { // Config 站点配置 type Config struct { - Debug bool // debug模式开关 - Site struct { + Debug bool // debug模式开关 + Language string // 系统语言,默认 zh-CN + Site struct { Brand string // 站点名称 CookieName string // 浏览器 Cookie 名称 Theme string @@ -100,6 +101,9 @@ func (c *Config) Read(path string) error { if c.Site.Theme == "" { c.Site.Theme = "default" } + if c.Language == "" { + c.Language = "zh-CN" + } if c.GRPCPort == 0 { c.GRPCPort = 5555 } diff --git a/resource/l10n/zh-CN.toml b/resource/l10n/zh-CN.toml new file mode 100644 index 0000000..b387822 --- /dev/null +++ b/resource/l10n/zh-CN.toml @@ -0,0 +1,2 @@ +[nezhaMonitor] +other = "哪吒监控" diff --git a/resource/template/common/footer.html b/resource/template/common/footer.html index 0f8774f..4c6a8e8 100644 --- a/resource/template/common/footer.html +++ b/resource/template/common/footer.html @@ -2,7 +2,7 @@ diff --git a/resource/template/dashboard/setting.html b/resource/template/dashboard/setting.html index eeb25b1..3c5f157 100644 --- a/resource/template/dashboard/setting.html +++ b/resource/template/dashboard/setting.html @@ -6,7 +6,7 @@
- +
diff --git a/resource/template/theme-daynight/home.html b/resource/template/theme-daynight/home.html index e4e38a4..8e3d73c 100644 --- a/resource/template/theme-daynight/home.html +++ b/resource/template/theme-daynight/home.html @@ -23,7 +23,7 @@