Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHo3ein <ho3ein.sanaei@gmail.com>2023-05-22 10:56:14 +0300
committerGitHub <noreply@github.com>2023-05-22 10:56:14 +0300
commit5f489c3d08b36c9569fa67f0c5bf46be8ada7b21 (patch)
tree0241a998df1f52f5170aec9bc263414e8a2a3e96 /web/locale
parent3d712890753a4f9981cca95685dec7ad4fff0acf (diff)
parentf82d0051b2cf827228b5c939d22622bd0d066149 (diff)
Merge pull request #491 from hamid-gh98/main
[tgbot] Multi language + More...
Diffstat (limited to 'web/locale')
-rw-r--r--web/locale/locale.go144
1 files changed, 144 insertions, 0 deletions
diff --git a/web/locale/locale.go b/web/locale/locale.go
new file mode 100644
index 00000000..9a4357c3
--- /dev/null
+++ b/web/locale/locale.go
@@ -0,0 +1,144 @@
+package locale
+
+import (
+ "embed"
+ "io/fs"
+ "strings"
+ "x-ui/logger"
+
+ "github.com/gin-gonic/gin"
+ "github.com/nicksnyder/go-i18n/v2/i18n"
+ "github.com/pelletier/go-toml/v2"
+ "golang.org/x/text/language"
+)
+
+var i18nBundle *i18n.Bundle
+var LocalizerWeb *i18n.Localizer
+var LocalizerBot *i18n.Localizer
+
+type I18nType string
+
+const (
+ Bot I18nType = "bot"
+ Web I18nType = "web"
+)
+
+type SettingService interface {
+ GetTgLang() (string, error)
+}
+
+func InitLocalizer(i18nFS embed.FS, settingService SettingService) error {
+ // set default bundle to english
+ i18nBundle = i18n.NewBundle(language.English)
+ i18nBundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
+
+ // parse files
+ if err := parseTranslationFiles(i18nFS, i18nBundle); err != nil {
+ return err
+ }
+
+ // setup bot locale
+ if err := initTGBotLocalizer(settingService); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func createTemplateData(params []string, seperator ...string) map[string]interface{} {
+ var sep string = "=="
+ if len(seperator) > 0 {
+ sep = seperator[0]
+ }
+
+ templateData := make(map[string]interface{})
+ for _, param := range params {
+ parts := strings.SplitN(param, sep, 2)
+ templateData[parts[0]] = parts[1]
+ }
+
+ return templateData
+}
+
+func I18n(i18nType I18nType, key string, params ...string) string {
+ var localizer *i18n.Localizer
+
+ switch i18nType {
+ case "bot":
+ localizer = LocalizerBot
+ case "web":
+ localizer = LocalizerWeb
+ default:
+ logger.Errorf("Invalid type for I18n: %s", i18nType)
+ return ""
+ }
+
+ templateData := createTemplateData(params)
+
+ msg, err := localizer.Localize(&i18n.LocalizeConfig{
+ MessageID: key,
+ TemplateData: templateData,
+ })
+
+ if err != nil {
+ logger.Errorf("Failed to localize message: %v", err)
+ return ""
+ }
+
+ return msg
+}
+
+func initTGBotLocalizer(settingService SettingService) error {
+ botLang, err := settingService.GetTgLang()
+ if err != nil {
+ return err
+ }
+
+ LocalizerBot = i18n.NewLocalizer(i18nBundle, botLang)
+ return nil
+}
+
+func LocalizerMiddleware() gin.HandlerFunc {
+ return func(c *gin.Context) {
+ var lang string
+
+ if cookie, err := c.Request.Cookie("lang"); err == nil {
+ lang = cookie.Value
+ } else {
+ lang = c.GetHeader("Accept-Language")
+ }
+
+ LocalizerWeb = i18n.NewLocalizer(i18nBundle, lang)
+
+ c.Set("localizer", LocalizerWeb)
+ c.Set("I18n", I18n)
+ c.Next()
+ }
+}
+
+func parseTranslationFiles(i18nFS embed.FS, i18nBundle *i18n.Bundle) error {
+ err := fs.WalkDir(i18nFS, "translation",
+ func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+
+ if d.IsDir() {
+ return nil
+ }
+
+ data, err := i18nFS.ReadFile(path)
+ if err != nil {
+ return err
+ }
+
+ _, err = i18nBundle.ParseMessageFileBytes(data, path)
+ return err
+ })
+
+ if err != nil {
+ return err
+ }
+
+ return nil
+}