1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 00:09:16 +08:00

feat: Add Multi-Language Support for Application Labels (#7714)

This commit is contained in:
zhengkunwang 2025-01-14 16:00:09 +08:00 committed by GitHub
parent 999e5a779a
commit 04a1ec9a9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 95 additions and 38 deletions

View File

@ -22,7 +22,7 @@ func (b *BaseApi) SearchApp(c *gin.Context) {
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
list, err := appService.PageApp(req)
list, err := appService.PageApp(c, req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@ -173,7 +173,7 @@ func (b *BaseApi) InstallApp(c *gin.Context) {
}
func (b *BaseApi) GetAppTags(c *gin.Context) {
tags, err := appService.GetAppTags()
tags, err := appService.GetAppTags(c)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return

View File

@ -104,9 +104,20 @@ type AppConfigVersion struct {
}
type Tag struct {
Key string `json:"key"`
Name string `json:"name"`
Sort int `json:"sort"`
Key string `json:"key"`
Name string `json:"name"`
Sort int `json:"sort"`
Locales Locale `json:"locales"`
}
type Locale struct {
En string `json:"en"`
Ja string `json:"ja"`
Ms string `json:"ms"`
PtBr string `json:"pt-br"`
Ru string `json:"ru"`
ZhHant string `json:"zh-hant"`
Zh string `json:"zh"`
}
type AppForm struct {

View File

@ -29,23 +29,25 @@ type AppDTO struct {
}
type AppItem struct {
Name string `json:"name"`
Key string `json:"key"`
ID uint `json:"id"`
ShortDescZh string `json:"shortDescZh"`
ShortDescEn string `json:"shortDescEn"`
Icon string `json:"icon"`
Type string `json:"type"`
Status string `json:"status"`
Resource string `json:"resource"`
Installed bool `json:"installed"`
Versions []string `json:"versions"`
Limit int `json:"limit"`
Tags []model.Tag `json:"tags"`
Name string `json:"name"`
Key string `json:"key"`
ID uint `json:"id"`
ShortDescZh string `json:"shortDescZh"`
ShortDescEn string `json:"shortDescEn"`
Icon string `json:"icon"`
Type string `json:"type"`
Status string `json:"status"`
Resource string `json:"resource"`
Installed bool `json:"installed"`
Versions []string `json:"versions"`
Limit int `json:"limit"`
Tags []TagDTO `json:"tags"`
}
type TagDTO struct {
model.Tag
ID uint `json:"id"`
Key string `json:"key"`
Name string `json:"name"`
}
type AppInstalledCheck struct {

View File

@ -2,7 +2,8 @@ package model
type Tag struct {
BaseModel
Key string `json:"key" gorm:"type:varchar(64);not null"`
Name string `json:"name" gorm:"type:varchar(64);not null"`
Sort int `json:"sort" gorm:"type:int;not null;default:1"`
Key string `json:"key" gorm:"type:varchar(64);not null"`
Name string `json:"name" gorm:"type:varchar(64);not null"`
Translations string `json:"translations"`
Sort int `json:"sort" gorm:"type:int;not null;default:1"`
}

View File

@ -5,6 +5,7 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"os"
"path/filepath"
@ -34,8 +35,8 @@ type AppService struct {
}
type IAppService interface {
PageApp(req request.AppSearch) (interface{}, error)
GetAppTags() ([]response.TagDTO, error)
PageApp(ctx *gin.Context, req request.AppSearch) (interface{}, error)
GetAppTags(ctx *gin.Context) ([]response.TagDTO, error)
GetApp(key string) (*response.AppDTO, error)
GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error)
Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error)
@ -50,7 +51,7 @@ func NewIAppService() IAppService {
return &AppService{}
}
func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{}, error) {
var opts []repo.DBOption
opts = append(opts, appRepo.OrderByRecommend())
if req.Name != "" {
@ -90,6 +91,7 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
return nil, err
}
var appDTOs []*response.AppItem
lang := strings.ToLower(common.GetLang(ctx))
for _, ap := range apps {
appDTO := &response.AppItem{
ID: ap.ID,
@ -115,7 +117,27 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
if err != nil {
continue
}
appDTO.Tags = tags
for _, t := range tags {
if t.Name != "" {
tagDTO := response.TagDTO{
ID: t.ID,
Key: t.Key,
Name: t.Name,
}
appDTO.Tags = append(appDTO.Tags, tagDTO)
} else {
var translations = make(map[string]string)
_ = json.Unmarshal([]byte(t.Translations), &translations)
if name, ok := translations[lang]; ok {
tagDTO := response.TagDTO{
ID: t.ID,
Key: t.Key,
Name: name,
}
appDTO.Tags = append(appDTO.Tags, tagDTO)
}
}
}
installs, _ := appInstallRepo.ListBy(appInstallRepo.WithAppId(ap.ID))
appDTO.Installed = len(installs) > 0
}
@ -125,13 +147,21 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
return res, nil
}
func (a AppService) GetAppTags() ([]response.TagDTO, error) {
func (a AppService) GetAppTags(ctx *gin.Context) ([]response.TagDTO, error) {
tags, _ := tagRepo.All()
res := make([]response.TagDTO, 0)
lang := strings.ToLower(common.GetLang(ctx))
for _, tag := range tags {
res = append(res, response.TagDTO{
Tag: tag,
})
tagDTO := response.TagDTO{
ID: tag.ID,
Key: tag.Key,
}
var translations = make(map[string]string)
_ = json.Unmarshal([]byte(tag.Translations), &translations)
if name, ok := translations[lang]; ok {
tagDTO.Name = name
}
res = append(res, tagDTO)
}
return res, nil
}
@ -827,10 +857,11 @@ func (a AppService) SyncAppListFromRemote() (err error) {
oldAppIds []uint
)
for _, t := range list.Extra.Tags {
translations, _ := json.Marshal(t.Locales)
tags = append(tags, &model.Tag{
Key: t.Key,
Name: t.Name,
Sort: t.Sort,
Key: t.Key,
Translations: string(translations),
Sort: t.Sort,
})
}
oldApps, err := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote))

View File

@ -99,6 +99,8 @@ func Init() {
migrations.AddAutoRestart,
migrations.AddApiInterfaceConfig,
migrations.AddApiKeyValidityTime,
migrations.UpdateAppTag,
})
if err := m.Migrate(); err != nil {
global.LOG.Error(err)

View File

@ -360,3 +360,13 @@ var AddApiKeyValidityTime = &gormigrate.Migration{
return nil
},
}
var UpdateAppTag = &gormigrate.Migration{
ID: "20241226-update-app-tag",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.Tag{}); err != nil {
return err
}
return nil
},
}

View File

@ -20,7 +20,7 @@
:type="activeTag === item.key ? 'primary' : ''"
:plain="activeTag !== item.key"
>
{{ language == 'zh' || language == 'tw' ? item.name : item.key }}
{{ item.name }}
</el-button>
</div>
<div class="inline">
@ -42,7 +42,7 @@
@click="changeTag(item.key)"
:key="item.key"
>
{{ language == 'zh' || language == 'tw' ? item.name : item.key }}
{{ item.name }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
@ -139,7 +139,7 @@
<div class="app-tag">
<el-tag v-for="(tag, ind) in app.tags" :key="ind" class="p-mr-5">
<span>
{{ language == 'zh' || language == 'tw' ? tag.name : tag.key }}
{{ tag.name }}
</span>
</el-tag>
<el-tag v-if="app.status === 'TakeDown'" class="p-mr-5">
@ -270,7 +270,7 @@ const changeTag = (key: string) => {
const getTagValue = (key: string) => {
const tag = tags.value.find((tag) => tag.key === key);
if (tag) {
return language == 'zh' || language == 'tw' ? tag.name : tag.key;
return tag.name;
}
};

View File

@ -21,7 +21,7 @@
:type="activeTag === item.key ? 'primary' : ''"
:plain="activeTag !== item.key"
>
{{ language == 'zh' || language == 'tw' ? item.name : item.key }}
{{ item.name }}
</el-button>
</div>
<div class="inline">