From 60d8cfcf70b44853769a594db5fbb6bbb33c8aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E9=BB=84=E6=9E=97?= Date: Sun, 10 Sep 2023 01:24:52 +0800 Subject: [PATCH] rename to frps-panel add i18n for some words --- Makefile | 8 ++--- Makefile.cross-compiles | 28 ++++++++-------- README.md | 32 +++++++++---------- README_zh.md | 32 +++++++++---------- assets/lang/en.json | 8 +++-- assets/lang/zh.json | 8 +++-- assets/static/js/index-user-list.js | 4 ++- assets/templates/index.html | 10 +++--- cmd/{frps-multiuser => frps-panel}/cmd.go | 14 ++++---- cmd/{frps-multiuser => frps-panel}/main.go | 0 config/{frps-multiuser.ini => frps-panel.ini} | 14 ++++---- go.mod | 2 +- package.sh | 10 +++--- pkg/server/controller/controller.go | 6 ++-- pkg/server/server.go | 2 +- 15 files changed, 92 insertions(+), 86 deletions(-) rename cmd/{frps-multiuser => frps-panel}/cmd.go (93%) rename cmd/{frps-multiuser => frps-panel}/main.go (100%) rename config/{frps-multiuser.ini => frps-panel.ini} (72%) diff --git a/Makefile b/Makefile index e2f5471..e8075f7 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ export CGO_ENABLED=0 export GOOS=linux export GOARCH=amd64 -build: frps-multiuser - cp ./config/frps-multiuser.ini ./bin/frps-multiuser.ini +build: frps-panel + cp ./config/frps-panel.ini ./bin/frps-panel.ini cp -r ./assets/ ./bin/assets/ -frps-multiuser: +frps-panel: rm -rf ./bin - go build -o ./bin/frps-multiuser ./cmd/frps-multiuser + go build -o ./bin/frps-panel ./cmd/frps-panel diff --git a/Makefile.cross-compiles b/Makefile.cross-compiles index bf94e70..09a8de6 100644 --- a/Makefile.cross-compiles +++ b/Makefile.cross-compiles @@ -5,20 +5,20 @@ package: copy sh ./package.sh copy: build - cp ./config/frps-multiuser.ini ./release/frps-multiuser.ini + cp ./config/frps-panel.ini ./release/frps-panel.ini cp -r ./assets/ ./release/assets/ build: - env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-darwin-amd64 ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-freebsd-386 ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-freebsd-amd64 ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-linux-386 ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-linux-amd64 ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-linux-arm ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-linux-arm64 ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-windows-386.exe ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-windows-amd64.exe ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-linux-mips64 ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-linux-mips64le ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=linux GOARCH=mips GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-linux-mips ./cmd/frps-multiuser - env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frps-multiuser-linux-mipsle ./cmd/frps-multiuser \ No newline at end of file + env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-darwin-amd64 ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-freebsd-386 ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-freebsd-amd64 ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-linux-386 ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-linux-amd64 ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-linux-arm ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-linux-arm64 ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-windows-386.exe ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-windows-amd64.exe ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-linux-mips64 ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-linux-mips64le ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=linux GOARCH=mips GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-linux-mips ./cmd/frps-panel + env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frps-panel-linux-mipsle ./cmd/frps-panel \ No newline at end of file diff --git a/README.md b/README.md index db73456..697d07c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ frp server plugin to support multiple users for [frp](https://github.com/fatedier/frp). -frps-multiuser will run as one single process and accept HTTP requests from frps. +frps-panel will run as one single process and accept HTTP requests from frps. ![用户列表](screenshots/user%20list.png) ![新增列表](screenshots/new%20user.png) @@ -13,8 +13,8 @@ frps-multiuser will run as one single process and accept HTTP requests from frps ## Update Notes -+ **the default tokens file is frps-multiuser.ini now,ini file support comment** -+ **remove `-l`,it configure in `frps-multiuser.ini` now** ++ **the default tokens file is frps-panel.ini now,ini file support comment** ++ **remove `-l`,it configure in `frps-panel.ini` now** + **change `-f` to `-c`,the same as `frps`** + **if \[users\] section is empty,the authentication will only be handle by frps** + **if user under \[disabled\] section ,and the value is `disable`, it means that user is be disabled, and can not connect to server** @@ -34,7 +34,7 @@ frps-multiuser will run as one single process and accept HTTP requests from frps ### Download -Download frps-multiuser binary file from [Release](../../releases). +Download frps-panel binary file from [Release](../../releases). ### Requirements @@ -42,7 +42,7 @@ frp version >= v0.31.0 ### Usage -1. Create file `frps-multiuser.ini` including all support usernames and tokens. +1. Create file `frps-panel.ini` including all support usernames and tokens. ```ini [common] @@ -80,9 +80,9 @@ user2 = disable One user each line. Username and token are split by `=`. -2. Run frps-multiuser: +2. Run frps-panel: - `./frps-multiuser -c ./frps-multiuser.ini` + `./frps-panel -c ./frps-panel.ini` 3. Register plugin in frps. @@ -135,8 +135,8 @@ remote_port = 6000 this example is for `ubuntu` and with `root` user -+ 1.unzip `frps-multiuser.zip` to dir `/root/frps-multiuser` -+ 2.touch a file with command `touch frps-multiuser.service` in dir `/root/frps-multiuser`.the file content is: ++ 1.unzip `frps-panel.zip` to dir `/root/frps-panel` ++ 2.touch a file with command `touch frps-panel.service` in dir `/root/frps-panel`.the file content is: ```ini [Unit] Description = frp multiuser service @@ -145,23 +145,23 @@ Wants = network.target [Service] Type = simple -# config of frps-multiuser.ini,you should change the file path -Environment=FRPS_MULTIUSER_OPTS="-c /root/frps-multiuser/frps-multiuser.ini" -# command of run frps-multiuser,you should change the file path -ExecStart = /root/frps-multiuser/frps-multiuser $FRPS_MULTIUSER_OPTS +# config of frps-panel.ini,you should change the file path +Environment=FRPS_MULTIUSER_OPTS="-c /root/frps-panel/frps-panel.ini" +# command of run frps-panel,you should change the file path +ExecStart = /root/frps-panel/frps-panel $FRPS_MULTIUSER_OPTS [Install] WantedBy = multi-user.target ``` -+ 3.copy `frps-multiuser.service` to `/etc/systemd/system/` with command `cp /root/frps-multiuser.service /etc/systemd/system/` ++ 3.copy `frps-panel.service` to `/etc/systemd/system/` with command `cp /root/frps-panel.service /etc/systemd/system/` + 4.reload service with command `systemctl daemon-reload` -+ 5.start service with command `service frps-multiuser start` ++ 5.start service with command `service frps-panel start` ## Issues & Ideas ___If you want visit mange ui from internet, you should change `plugin_addr` to `0.0.0.0`___ -If you have any issues or ideas, put it on [issues](https://github.com/yhl452493373/frps-multiuser/issues). I will try my best to achieve it. +If you have any issues or ideas, put it on [issues](https://github.com/yhl452493373/frps-panel/issues). I will try my best to achieve it. ## Credits diff --git a/README_zh.md b/README_zh.md index a4e3f70..b7053af 100644 --- a/README_zh.md +++ b/README_zh.md @@ -1,10 +1,10 @@ -# frps-multiuser +# frps-panel [README](README.md) | [中文文档](README_zh.md) -frps-multiuser 是 [frp](https://github.com/fatedier/frp) 的一个服务端插件,用于支持多用户鉴权。 +frps-panel 是 [frp](https://github.com/fatedier/frp) 的一个服务端插件,用于支持多用户鉴权。 -frps-multiuser 会以一个单独的进程运行,并接收 frps 发送过来的 HTTP 请求。 +frps-panel 会以一个单独的进程运行,并接收 frps 发送过来的 HTTP 请求。 ![用户列表](screenshots/user%20list.png) ![新增列表](screenshots/new%20user.png) @@ -14,7 +14,7 @@ frps-multiuser 会以一个单独的进程运行,并接收 frps 发送过来 ## 更新说明 + **配置文件改为ini格式,便于增加注释** -+ **删除-l参数,其需要的配置由`frps-multiuser.ini`决定** ++ **删除-l参数,其需要的配置由`frps-panel.ini`决定** + **指定配置文件的参数由`-f`改为`-c`,和`frps`一致** + **配置文件中,\[users\]节下如无用户信息,则直接由frps的token认证** + **配置文件中,\[disabled\]节下用户名对应的值如果为`disable`,则说明该账户被禁用,无法连接到服务器** @@ -42,7 +42,7 @@ frps-multiuser 会以一个单独的进程运行,并接收 frps 发送过来 ### 使用示例 -1. 创建 `frps-multiuser.ini` 文件,内容为所有支持的用户名和 token。 +1. 创建 `frps-panel.ini` 文件,内容为所有支持的用户名和 token。 ```ini [common] @@ -80,9 +80,9 @@ user2 = disable 每一个用户占一行,用户名和 token 之间以 `=` 号分隔。 -2. 运行 frps-multiuser,指定监听地址以及 token 存储文件路径。 +2. 运行 frps-panel,指定监听地址以及 token 存储文件路径。 - `./frps-multiuser -c ./frps-multiuser.ini` + `./frps-panel -c ./frps-panel.ini` 3. 在 frps 的配置文件中注册插件,并启动。 @@ -135,8 +135,8 @@ remote_port = 6000 本实例是在 `ubuntu` 下, 以 `root` 用户执操作 -+ 1、解压 `frps-multiuser.zip` 到目录 `/root/frps-multiuser` -+ 2、在目录 `/root/frps-multiuser` 下 用命令创建文件:`touch frps-multiuser.service`。创建后修改文件内容: ++ 1、解压 `frps-panel.zip` 到目录 `/root/frps-panel` ++ 2、在目录 `/root/frps-panel` 下 用命令创建文件:`touch frps-panel.service`。创建后修改文件内容: ```ini [Unit] Description = frp multiuser service @@ -145,23 +145,23 @@ Wants = network.target [Service] Type = simple -# 启动frps-multiuser的配置文件路径,需修改为您的frps-multiuser.ini的路径 -Environment=FRPS_MULTIUSER_OPTS="-c /root/frps-multiuser/frps-multiuser.ini" -# 启动frps-multiuser的命令,需修改为您的frps-multiuser的安装路径 -ExecStart = /root/frps-multiuser/frps-multiuser $FRPS_MULTIUSER_OPTS +# 启动frps-panel的配置文件路径,需修改为您的frps-panel.ini的路径 +Environment=FRPS_MULTIUSER_OPTS="-c /root/frps-panel/frps-panel.ini" +# 启动frps-panel的命令,需修改为您的frps-panel的安装路径 +ExecStart = /root/frps-panel/frps-panel $FRPS_MULTIUSER_OPTS [Install] WantedBy = multi-user.target ``` -+ 3、复制服务文件: `cp /root/frps-multiuser.service /etc/systemd/system/` ++ 3、复制服务文件: `cp /root/frps-panel.service /etc/systemd/system/` + 4、重载服务: `systemctl daemon-reload` -+ 5、启动服务: `service frps-multiuser start` ++ 5、启动服务: `service frps-panel start` ## 使用 ___如果要从外网访问管理界面, 需要把配置中的 `plugin_addr` 改为 `0.0.0.0`___ -如果使用中有问题或者有其他想法,在[issues](https://github.com/yhl452493373/frps-multiuser/issues)上提出来。 如果我能搞定的话,我尽量搞。 +如果使用中有问题或者有其他想法,在[issues](https://github.com/yhl452493373/frps-panel/issues)上提出来。 如果我能搞定的话,我尽量搞。 ## 致谢 diff --git a/assets/lang/en.json b/assets/lang/en.json index 4982f48..f28b313 100644 --- a/assets/lang/en.json +++ b/assets/lang/en.json @@ -1,6 +1,5 @@ { - "User Manage": "User Manage", - "frps multiuser": "frps multiuser", + "Frps Panel": "Frps Panel", "User": "User", "Token": "Token", "Notes": "Notes", @@ -46,5 +45,8 @@ "Subdomains is invalid": "Subdomains is invalid", "Comment is invalid": "Comment is invalid, it cannot include line breaks", "Not limit": "Not limit", - "None": "None" + "None": "None", + "Server Info": "Server Info", + "Users": "Users", + "Proxies": "Proxies" } \ No newline at end of file diff --git a/assets/lang/zh.json b/assets/lang/zh.json index 80eb6a9..b34b0c3 100644 --- a/assets/lang/zh.json +++ b/assets/lang/zh.json @@ -1,6 +1,5 @@ { - "User Manage": "用户管理", - "frps multiuser": "frps用户管理", + "Frps Panel": "Frps 面板", "User": "用户名(user)", "Token": "凭证(meta_token)", "Notes": "备注", @@ -46,5 +45,8 @@ "Subdomains is invalid": "子域名不正确", "Comment is invalid": "备注不正确,不能包含换行", "Not limit": "无限制", - "None": "无" + "None": "无", + "Server Info": "服务器信息", + "Users": "用户列表", + "Proxies": "代理列表" } \ No newline at end of file diff --git a/assets/static/js/index-user-list.js b/assets/static/js/index-user-list.js index 3e5f280..e7d24a2 100644 --- a/assets/static/js/index-user-list.js +++ b/assets/static/js/index-user-list.js @@ -239,8 +239,11 @@ var loadUserList = (function ($) { verify: verifyRules }); + var $section = $('#content > section'); layui.table.render({ elem: '#tokenTable', + height: $section.height() - $('#searchForm').height() + 8, + text: {none: lang['EmptyData']}, url: '/tokens', method: 'get', where: {}, @@ -249,7 +252,6 @@ var loadUserList = (function ($) { page: navigator.language.indexOf("zh") !== -1, toolbar: '#userListToolbarTemplate', defaultToolbar: false, - text: {none: lang['EmptyData']}, cols: [[ {type: 'checkbox'}, {field: 'user', title: lang['User'], width: 150, sort: true}, diff --git a/assets/templates/index.html b/assets/templates/index.html index d981da6..299b924 100644 --- a/assets/templates/index.html +++ b/assets/templates/index.html @@ -1,7 +1,7 @@ - ${ .UserManage } + ${ .FrpsPanel } @@ -31,20 +31,20 @@
- +
  • - 服务器信息 + ${ .ServerInfo }
  • - 用户列表 + ${ .Users }
  • - 代理列表 + ${ .Proxies }
    TCP diff --git a/cmd/frps-multiuser/cmd.go b/cmd/frps-panel/cmd.go similarity index 93% rename from cmd/frps-multiuser/cmd.go rename to cmd/frps-panel/cmd.go index a3557d3..6e8c964 100644 --- a/cmd/frps-multiuser/cmd.go +++ b/cmd/frps-panel/cmd.go @@ -2,8 +2,8 @@ package main import ( "errors" - "frps-multiuser/pkg/server" - "frps-multiuser/pkg/server/controller" + "frps-panel/pkg/server" + "frps-panel/pkg/server/controller" "github.com/spf13/cobra" "gopkg.in/ini.v1" "io/fs" @@ -21,13 +21,13 @@ var ( ) func init() { - rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frps-multiuser") - rootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "./frps-multiuser.ini", "config file of frps-multiuser") + rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frps-panel") + rootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "./frps-panel.ini", "config file of frps-panel") } var rootCmd = &cobra.Command{ - Use: "frps-multiuser", - Short: "frps-multiuser is the server plugin of frp to support multiple users.", + Use: "frps-panel", + Short: "frps-panel is the server plugin of frp to support multiple users.", RunE: func(cmd *cobra.Command, args []string) error { if showVersion { log.Println(version) @@ -42,7 +42,7 @@ var rootCmd = &cobra.Command{ common, tokens, ports, domains, subdomains, iniFile, err := ParseConfigFile(configFile) if err != nil { - log.Printf("fail to start frps-multiuser : %v", err) + log.Printf("fail to start frps-panel : %v", err) return err } s, err := server.New( diff --git a/cmd/frps-multiuser/main.go b/cmd/frps-panel/main.go similarity index 100% rename from cmd/frps-multiuser/main.go rename to cmd/frps-panel/main.go diff --git a/config/frps-multiuser.ini b/config/frps-panel.ini similarity index 72% rename from config/frps-multiuser.ini rename to config/frps-panel.ini index 0f721f5..f714045 100644 --- a/config/frps-multiuser.ini +++ b/config/frps-panel.ini @@ -1,20 +1,18 @@ ; basic options [common] ; frps config info -plugin_addr = 127.0.0.1 -plugin_port = 7200 -admin_user = admin -admin_pwd = admin - +plugin_addr = 127.0.0.1 +plugin_port = 7200 +admin_user = admin +admin_pwd = admin ; frp dashboard config info -dashboard_addr = 127.0.0.1 +dashboard_addr = frp.yanghuanglin.com dashboard_port = 7500 dashboard_user = admin -dashboard_pwd = admin +dashboard_pwd = 19910621 ; user tokens [users] -user1 = token1 ; user been disabled [disabled] diff --git a/go.mod b/go.mod index b6a3a90..fed7ec7 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module frps-multiuser +module frps-panel go 1.21 diff --git a/package.sh b/package.sh index 576085f..57a103e 100644 --- a/package.sh +++ b/package.sh @@ -1,12 +1,12 @@ #!/bin/bash cd ./release || exit rm -rf *.zip -list=$(ls frps-multiuser-*) +list=$(ls frps-panel-*) echo "$list" for binFile in $list do - cp "$binFile" frps-multiuser - zip -r "$binFile".zip frps-multiuser frps-multiuser.ini assets -x "*.git*" "*.idea*" "*.DS_Store" "*.contentFlavour" - rm -rf "$binFile" frps-multiuser + cp "$binFile" frps-panel + zip -r "$binFile".zip frps-panel frps-panel.ini assets -x "*.git*" "*.idea*" "*.DS_Store" "*.contentFlavour" + rm -rf "$binFile" frps-panel done - rm -rf frps-multiuser.ini assets + rm -rf frps-panel.ini assets diff --git a/pkg/server/controller/controller.go b/pkg/server/controller/controller.go index eb4f776..8c94c32 100644 --- a/pkg/server/controller/controller.go +++ b/pkg/server/controller/controller.go @@ -176,8 +176,7 @@ func (c *HandleController) MakeHandlerFunc() gin.HandlerFunc { func (c *HandleController) MakeManagerFunc() func(context *gin.Context) { return func(context *gin.Context) { context.HTML(http.StatusOK, "index.html", gin.H{ - "UserManage": ginI18n.MustGetMessage(context, "User Manage"), - "FrpsMultiuser": ginI18n.MustGetMessage(context, "frps multiuser"), + "FrpsPanel": ginI18n.MustGetMessage(context, "Frps Panel"), "User": ginI18n.MustGetMessage(context, "User"), "Token": ginI18n.MustGetMessage(context, "Token"), "Notes": ginI18n.MustGetMessage(context, "Notes"), @@ -201,6 +200,9 @@ func (c *HandleController) MakeManagerFunc() func(context *gin.Context) { "PleaseInputAllowedSubdomains": ginI18n.MustGetMessage(context, "Please input allowed subdomains"), "NotLimit": ginI18n.MustGetMessage(context, "Not limit"), "None": ginI18n.MustGetMessage(context, "None"), + "ServerInfo": ginI18n.MustGetMessage(context, "Server Info"), + "Users": ginI18n.MustGetMessage(context, "Users"), + "Proxies": ginI18n.MustGetMessage(context, "Proxies"), }) } } diff --git a/pkg/server/server.go b/pkg/server/server.go index 6c081d8..bfb4152 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -5,7 +5,7 @@ import ( "encoding/json" "errors" "fmt" - "frps-multiuser/pkg/server/controller" + "frps-panel/pkg/server/controller" ginI18n "github.com/gin-contrib/i18n" "github.com/gin-gonic/gin" "golang.org/x/text/language"