Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/app/service/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/1Panel-dev/1Panel/core/buserr"
"github.com/1Panel-dev/1Panel/core/constant"
"github.com/1Panel-dev/1Panel/core/global"
"github.com/1Panel-dev/1Panel/core/i18n"
"github.com/1Panel-dev/1Panel/core/utils/common"
"github.com/1Panel-dev/1Panel/core/utils/controller"
"github.com/1Panel-dev/1Panel/core/utils/encrypt"
Expand Down Expand Up @@ -148,6 +149,7 @@ func (u *SettingService) Update(key, value string) error {
case "UserName", "Password":
_ = global.SESSION.Clean()
case "Language":
i18n.SetCachedDBLanguage(value)
if err := xpack.Sync(constant.SyncLanguage); err != nil {
global.LOG.Errorf("sync language to node failed, err: %v", err)
}
Expand Down
95 changes: 70 additions & 25 deletions core/i18n/i18n.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ package i18n

import (
"embed"
"github.com/1Panel-dev/1Panel/core/app/repo"
"fmt"
"strings"
"sync"
"sync/atomic"

"github.com/1Panel-dev/1Panel/core/app/repo"

"github.com/1Panel-dev/1Panel/core/global"

Expand All @@ -13,6 +17,21 @@ import (
"gopkg.in/yaml.v3"
)

const defaultLang = "en"

var langFiles = map[string]string{
"zh": "lang/zh.yaml",
"en": "lang/en.yaml",
"zh-Hant": "lang/zh-Hant.yaml",
"pt-BR": "lang/pt-BR.yaml",
"ja": "lang/ja.yaml",
"ru": "lang/ru.yaml",
"ms": "lang/ms.yaml",
"ko": "lang/ko.yaml",
"tr": "lang/tr.yaml",
"es-ES": "lang/es-ES.yaml",
}

func GetMsgWithMap(key string, maps map[string]interface{}) string {
var content string
if maps == nil {
Expand Down Expand Up @@ -114,41 +133,49 @@ func UseI18n() gin.HandlerFunc {
return func(context *gin.Context) {
lang := context.GetHeader("Accept-Language")
if lang == "" {
lang = GetLanguageFromDB()
lang = GetLanguage()
}
global.I18n = i18n.NewLocalizer(bundle, lang)
}
}

func Init() {
bundle = i18n.NewBundle(language.Chinese)
bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal)
_, _ = bundle.LoadMessageFileFS(fs, "lang/zh.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/en.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/zh-Hant.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/fa.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/pt.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/pt-BR.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/ja.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/ru.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/ms.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/ko.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/tr.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/es-ES.yaml")
lang := GetLanguageFromDB()
global.I18n = i18n.NewLocalizer(bundle, lang)
initOnce.Do(func() {
bundle = i18n.NewBundle(language.Chinese)
bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal)

isSuccess := true
for _, file := range langFiles {
if _, err := bundle.LoadMessageFileFS(fs, file); err != nil {
fmt.Printf("[i18n] load language file %s failed: %v\n", file, err)
isSuccess = false
}
}

if !isSuccess {
panic("[i18n] failed to init language files, See log above for details")
}

dbLang := getLanguageFromDBInternal()
if dbLang == "" {
dbLang = defaultLang
}
SetCachedDBLanguage(dbLang)

global.I18n = i18n.NewLocalizer(bundle, dbLang)
})
}

func UseI18nForCmd(lang string) {
if lang == "" {
lang = "en"
}

if bundle == nil {
Init()
}
if lang == "" {
lang = defaultLang
}
global.I18nForCmd = i18n.NewLocalizer(bundle, lang)
}

func GetMsgByKeyForCmd(key string) string {
if global.I18nForCmd == nil {
UseI18nForCmd("")
Expand All @@ -158,6 +185,7 @@ func GetMsgByKeyForCmd(key string) string {
})
return content
}

func GetMsgWithMapForCmd(key string, maps map[string]interface{}) string {
if global.I18nForCmd == nil {
UseI18nForCmd("")
Expand All @@ -181,13 +209,30 @@ func GetMsgWithMapForCmd(key string, maps map[string]interface{}) string {
}
}

func GetLanguageFromDB() string {
func getLanguageFromDBInternal() string {
if global.DB == nil {
return "en"
return defaultLang
}
lang, _ := repo.NewISettingRepo().GetValueByKey("Language")
if lang == "" {
return "en"
return defaultLang
}
return lang
}

var cachedDBLang atomic.Value
var initOnce sync.Once

func GetLanguage() string {
if v := cachedDBLang.Load(); v != nil {
return v.(string)
}
return defaultLang
}

func SetCachedDBLanguage(lang string) {
if lang == "" {
lang = defaultLang
}
cachedDBLang.Store(lang)
}
10 changes: 5 additions & 5 deletions core/i18n/lang/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ MasterNode: "Master Node"
# app
CustomAppStoreFileValid: "Application store package requires .tar.gz format"
ErrFileNotFound: "{{ .name }} file does not exist"
AppBackup: 'Application backup',
AppBackupPush: 'Transfer application backup file {{.file}} to node {{ .name }}',
ErrSourceTargetSame: 'Source node and target node cannot be the same!',
AppInstall: 'Install application {{ .name }} on node {{ .targetNode }}',
AppInstallCheck: 'Check application installation environment',
AppBackup: 'Application backup'
AppBackupPush: 'Transfer application backup file {{.file}} to node {{ .name }}'
ErrSourceTargetSame: 'Source node and target node cannot be the same!'
AppInstall: 'Install application {{ .name }} on node {{ .targetNode }}'
AppInstallCheck: 'Check application installation environment'

# backup
ErrBackupInUsed: "This backup account is used in scheduled tasks and cannot be deleted"
Expand Down
10 changes: 5 additions & 5 deletions core/i18n/lang/es-ES.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ MasterNode: "Nodo Maestro"
# app
CustomAppStoreFileValid: "El paquete de la tienda de aplicaciones debe tener formato .tar.gz"
ErrFileNotFound: "El archivo {{ .name }} no existe"
AppBackup: 'Copia de seguridad de aplicación',
AppBackupPush: 'Transferir archivo de copia de seguridad de aplicación {{.file}} al nodo {{ .name }}',
ErrSourceTargetSame: '¡El nodo de origen y el nodo de destino no pueden ser el mismo!',
AppInstall: 'Instalar aplicación {{ .name }} en nodo {{ .targetNode }}',
AppInstallCheck: 'Verificar entorno de instalación de aplicación',
AppBackup: 'Copia de seguridad de aplicación'
AppBackupPush: 'Transferir archivo de copia de seguridad de aplicación {{.file}} al nodo {{ .name }}'
ErrSourceTargetSame: '¡El nodo de origen y el nodo de destino no pueden ser el mismo!'
AppInstall: 'Instalar aplicación {{ .name }} en nodo {{ .targetNode }}'
AppInstallCheck: 'Verificar entorno de instalación de aplicación'

# backup
ErrBackupInUsed: "Esta cuenta de respaldo se utiliza en tareas programadas y no se puede eliminar"
Expand Down
10 changes: 5 additions & 5 deletions core/i18n/lang/ja.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ MasterNode: "マスターノード"
# app
CustomAppStoreFileValid: "アプリストアパッケージは .tar.gz 形式である必要があります"
ErrFileNotFound: "{{ .name }} ファイルが存在しません"
AppBackup: 'アプリケーションバックアップ',
AppBackupPush: 'アプリケーションバックアップファイル {{.file}} をノード {{ .name }} に転送',
ErrSourceTargetSame: 'ソースノードとターゲットノードは同じにできません!',
AppInstall: 'ノード {{ .targetNode }} にアプリケーション {{ .name }} をインストール',
AppInstallCheck: 'アプリケーションインストール環境を確認',
AppBackup: 'アプリケーションバックアップ'
AppBackupPush: 'アプリケーションバックアップファイル {{.file}} をノード {{ .name }} に転送'
ErrSourceTargetSame: 'ソースノードとターゲットノードは同じにできません!'
AppInstall: 'ノード {{ .targetNode }} にアプリケーション {{ .name }} をインストール'
AppInstallCheck: 'アプリケーションインストール環境を確認'

# backup
ErrBackupInUsed: "このバックアップアカウントはスケジュールタスクで使用されており、削除できません"
Expand Down
10 changes: 5 additions & 5 deletions core/i18n/lang/ko.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ MasterNode: "마스터 노드"
# app
CustomAppStoreFileValid: "앱 스토어 패키지는 .tar.gz 형식이어야 합니다"
ErrFileNotFound: "{{ .name }} 파일이 존재하지 않습니다"
AppBackup: '애플리케이션 백업',
AppBackupPush: '애플리케이션 백업 파일 {{.file}}을(를) 노드 {{ .name }}(으)로 전송',
ErrSourceTargetSame: '소스 노드와 대상 노드는 동일할 수 없습니다!',
AppInstall: '노드 {{ .targetNode }}에 애플리케이션 {{ .name }} 설치',
AppInstallCheck: '애플리케이션 설치 환경 확인',
AppBackup: '애플리케이션 백업'
AppBackupPush: '애플리케이션 백업 파일 {{.file}}을(를) 노드 {{ .name }}(으)로 전송'
ErrSourceTargetSame: '소스 노드와 대상 노드는 동일할 수 없습니다!'
AppInstall: '노드 {{ .targetNode }}에 애플리케이션 {{ .name }} 설치'
AppInstallCheck: '애플리케이션 설치 환경 확인'

# backup
ErrBackupInUsed: "이 백업 계정은 예약된 작업에 사용 중이며 삭제할 수 없습니다"
Expand Down
File renamed without changes.
10 changes: 5 additions & 5 deletions core/i18n/lang/pt-BR.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ MasterNode: "Nó Mestre"
# app
CustomAppStoreFileValid: "O pacote da loja de aplicativos deve estar no formato .tar.gz"
ErrFileNotFound: "Arquivo {{ .name }} não encontrado"
AppBackup: 'Backup de aplicação',
AppBackupPush: 'Transferir arquivo de backup de aplicação {{.file}} para o nó {{ .name }}',
ErrSourceTargetSame: 'O nó de origem e o nó de destino não podem ser os mesmos!',
AppInstall: 'Instalar aplicação {{ .name }} no nó {{ .targetNode }}',
AppInstallCheck: 'Verificar ambiente de instalação da aplicação',
AppBackup: 'Backup de aplicação'
AppBackupPush: 'Transferir arquivo de backup de aplicação {{.file}} para o nó {{ .name }}'
ErrSourceTargetSame: 'O nó de origem e o nó de destino não podem ser os mesmos!'
AppInstall: 'Instalar aplicação {{ .name }} no nó {{ .targetNode }}'
AppInstallCheck: 'Verificar ambiente de instalação da aplicação'

# backup
ErrBackupInUsed: "Esta conta de backup está em uso em tarefas agendadas e não pode ser excluída"
Expand Down
10 changes: 5 additions & 5 deletions core/i18n/lang/ru.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ MasterNode: "Главный узел"
# app
CustomAppStoreFileValid: "Пакет магазина приложений должен быть в формате .tar.gz"
ErrFileNotFound: "Файл {{ .name }} не найден"
AppBackup: 'Резервная копия приложения',
AppBackupPush: 'Передать файл резервной копии приложения {{.file}} на узел {{ .name }}',
ErrSourceTargetSame: 'Исходный узел и целевой узел не могут быть одинаковыми!',
AppInstall: 'Установить приложение {{ .name }} на узел {{ .targetNode }}',
AppInstallCheck: 'Проверить среду установки приложения',
AppBackup: 'Резервная копия приложения'
AppBackupPush: 'Передать файл резервной копии приложения {{.file}} на узел {{ .name }}'
ErrSourceTargetSame: 'Исходный узел и целевой узел не могут быть одинаковыми!'
AppInstall: 'Установить приложение {{ .name }} на узел {{ .targetNode }}'
AppInstallCheck: 'Проверить среду установки приложения'

# backup
ErrBackupInUsed: "Эта учетная запись резервного копирования используется в запланированных задачах и не может быть удалена"
Expand Down
10 changes: 5 additions & 5 deletions core/i18n/lang/tr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ MasterNode: "Ana Düğüm"
# app
CustomAppStoreFileValid: "Uygulama mağazası paketi .tar.gz formatında olmalıdır"
ErrFileNotFound: "{{ .name }} dosyası mevcut değil"
AppBackup: 'Uygulama yedekleme',
AppBackupPush: 'Uygulama yedek dosyası {{.file}} düğüm {{ .name }} a aktar',
ErrSourceTargetSame: 'Kaynak düğüm ve hedef düğüm aynı olamaz!',
AppInstall: 'Düğüm {{ .targetNode }} üzerine {{ .name }} uygulamasını yükle',
AppInstallCheck: 'Uygulama kurulum ortamını kontrol et',
AppBackup: 'Uygulama yedekleme'
AppBackupPush: 'Uygulama yedek dosyası {{.file}} düğüm {{ .name }} a aktar'
ErrSourceTargetSame: 'Kaynak düğüm ve hedef düğüm aynı olamaz!'
AppInstall: 'Düğüm {{ .targetNode }} üzerine {{ .name }} uygulamasını yükle'
AppInstallCheck: 'Uygulama kurulum ortamını kontrol et'

# backup
ErrBackupInUsed: "Bu yedekleme hesabı zamanlanmış görevlerde kullanılıyor ve silinemez"
Expand Down
10 changes: 5 additions & 5 deletions core/i18n/lang/zh-Hant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ MasterNode: "主節點"
#app
CustomAppStoreFileValid: "應用商店包需要 .tar.gz 格式"
ErrFileNotFound: "{{ .name }} 檔案不存在"
AppBackup: '應用備份',
AppBackupPush: '傳輸應用備份文件 {{.file}} 到節點 {{ .name }}',
ErrSourceTargetSame: '源節點和目標節點不能相同!',
AppInstall: '在 {{ .targetNode }} 節點安裝應用 {{ .name }}',
AppInstallCheck: '檢查應用安裝環境',
AppBackup: '應用備份'
AppBackupPush: '傳輸應用備份文件 {{.file}} 到節點 {{ .name }}'
ErrSourceTargetSame: '源節點和目標節點不能相同!'
AppInstall: '在 {{ .targetNode }} 節點安裝應用 {{ .name }}'
AppInstallCheck: '檢查應用安裝環境'

#backup
ErrBackupInUsed: "該備份帳號已在排程任務中使用,無法刪除"
Expand Down
Loading