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:
parent
999e5a779a
commit
04a1ec9a9a
@ -22,7 +22,7 @@ func (b *BaseApi) SearchApp(c *gin.Context) {
|
|||||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
list, err := appService.PageApp(req)
|
list, err := appService.PageApp(c, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
@ -173,7 +173,7 @@ func (b *BaseApi) InstallApp(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseApi) GetAppTags(c *gin.Context) {
|
func (b *BaseApi) GetAppTags(c *gin.Context) {
|
||||||
tags, err := appService.GetAppTags()
|
tags, err := appService.GetAppTags(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
|
@ -104,9 +104,20 @@ type AppConfigVersion struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Tag struct {
|
type Tag struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Sort int `json:"sort"`
|
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 {
|
type AppForm struct {
|
||||||
|
@ -29,23 +29,25 @@ type AppDTO struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AppItem struct {
|
type AppItem struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
ID uint `json:"id"`
|
ID uint `json:"id"`
|
||||||
ShortDescZh string `json:"shortDescZh"`
|
ShortDescZh string `json:"shortDescZh"`
|
||||||
ShortDescEn string `json:"shortDescEn"`
|
ShortDescEn string `json:"shortDescEn"`
|
||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Resource string `json:"resource"`
|
Resource string `json:"resource"`
|
||||||
Installed bool `json:"installed"`
|
Installed bool `json:"installed"`
|
||||||
Versions []string `json:"versions"`
|
Versions []string `json:"versions"`
|
||||||
Limit int `json:"limit"`
|
Limit int `json:"limit"`
|
||||||
Tags []model.Tag `json:"tags"`
|
Tags []TagDTO `json:"tags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TagDTO struct {
|
type TagDTO struct {
|
||||||
model.Tag
|
ID uint `json:"id"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppInstalledCheck struct {
|
type AppInstalledCheck struct {
|
||||||
|
@ -2,7 +2,8 @@ package model
|
|||||||
|
|
||||||
type Tag struct {
|
type Tag struct {
|
||||||
BaseModel
|
BaseModel
|
||||||
Key string `json:"key" gorm:"type:varchar(64);not null"`
|
Key string `json:"key" gorm:"type:varchar(64);not null"`
|
||||||
Name string `json:"name" 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"`
|
Translations string `json:"translations"`
|
||||||
|
Sort int `json:"sort" gorm:"type:int;not null;default:1"`
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -34,8 +35,8 @@ type AppService struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type IAppService interface {
|
type IAppService interface {
|
||||||
PageApp(req request.AppSearch) (interface{}, error)
|
PageApp(ctx *gin.Context, req request.AppSearch) (interface{}, error)
|
||||||
GetAppTags() ([]response.TagDTO, error)
|
GetAppTags(ctx *gin.Context) ([]response.TagDTO, error)
|
||||||
GetApp(key string) (*response.AppDTO, error)
|
GetApp(key string) (*response.AppDTO, error)
|
||||||
GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error)
|
GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error)
|
||||||
Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error)
|
Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error)
|
||||||
@ -50,7 +51,7 @@ func NewIAppService() IAppService {
|
|||||||
return &AppService{}
|
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
|
var opts []repo.DBOption
|
||||||
opts = append(opts, appRepo.OrderByRecommend())
|
opts = append(opts, appRepo.OrderByRecommend())
|
||||||
if req.Name != "" {
|
if req.Name != "" {
|
||||||
@ -90,6 +91,7 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var appDTOs []*response.AppItem
|
var appDTOs []*response.AppItem
|
||||||
|
lang := strings.ToLower(common.GetLang(ctx))
|
||||||
for _, ap := range apps {
|
for _, ap := range apps {
|
||||||
appDTO := &response.AppItem{
|
appDTO := &response.AppItem{
|
||||||
ID: ap.ID,
|
ID: ap.ID,
|
||||||
@ -115,7 +117,27 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
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))
|
installs, _ := appInstallRepo.ListBy(appInstallRepo.WithAppId(ap.ID))
|
||||||
appDTO.Installed = len(installs) > 0
|
appDTO.Installed = len(installs) > 0
|
||||||
}
|
}
|
||||||
@ -125,13 +147,21 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AppService) GetAppTags() ([]response.TagDTO, error) {
|
func (a AppService) GetAppTags(ctx *gin.Context) ([]response.TagDTO, error) {
|
||||||
tags, _ := tagRepo.All()
|
tags, _ := tagRepo.All()
|
||||||
res := make([]response.TagDTO, 0)
|
res := make([]response.TagDTO, 0)
|
||||||
|
lang := strings.ToLower(common.GetLang(ctx))
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
res = append(res, response.TagDTO{
|
tagDTO := response.TagDTO{
|
||||||
Tag: tag,
|
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
|
return res, nil
|
||||||
}
|
}
|
||||||
@ -827,10 +857,11 @@ func (a AppService) SyncAppListFromRemote() (err error) {
|
|||||||
oldAppIds []uint
|
oldAppIds []uint
|
||||||
)
|
)
|
||||||
for _, t := range list.Extra.Tags {
|
for _, t := range list.Extra.Tags {
|
||||||
|
translations, _ := json.Marshal(t.Locales)
|
||||||
tags = append(tags, &model.Tag{
|
tags = append(tags, &model.Tag{
|
||||||
Key: t.Key,
|
Key: t.Key,
|
||||||
Name: t.Name,
|
Translations: string(translations),
|
||||||
Sort: t.Sort,
|
Sort: t.Sort,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
oldApps, err := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote))
|
oldApps, err := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote))
|
||||||
|
@ -99,6 +99,8 @@ func Init() {
|
|||||||
migrations.AddAutoRestart,
|
migrations.AddAutoRestart,
|
||||||
migrations.AddApiInterfaceConfig,
|
migrations.AddApiInterfaceConfig,
|
||||||
migrations.AddApiKeyValidityTime,
|
migrations.AddApiKeyValidityTime,
|
||||||
|
|
||||||
|
migrations.UpdateAppTag,
|
||||||
})
|
})
|
||||||
if err := m.Migrate(); err != nil {
|
if err := m.Migrate(); err != nil {
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
|
@ -360,3 +360,13 @@ var AddApiKeyValidityTime = &gormigrate.Migration{
|
|||||||
return nil
|
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
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
:type="activeTag === item.key ? 'primary' : ''"
|
:type="activeTag === item.key ? 'primary' : ''"
|
||||||
:plain="activeTag !== item.key"
|
:plain="activeTag !== item.key"
|
||||||
>
|
>
|
||||||
{{ language == 'zh' || language == 'tw' ? item.name : item.key }}
|
{{ item.name }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="inline">
|
<div class="inline">
|
||||||
@ -42,7 +42,7 @@
|
|||||||
@click="changeTag(item.key)"
|
@click="changeTag(item.key)"
|
||||||
:key="item.key"
|
:key="item.key"
|
||||||
>
|
>
|
||||||
{{ language == 'zh' || language == 'tw' ? item.name : item.key }}
|
{{ item.name }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
@ -139,7 +139,7 @@
|
|||||||
<div class="app-tag">
|
<div class="app-tag">
|
||||||
<el-tag v-for="(tag, ind) in app.tags" :key="ind" class="p-mr-5">
|
<el-tag v-for="(tag, ind) in app.tags" :key="ind" class="p-mr-5">
|
||||||
<span>
|
<span>
|
||||||
{{ language == 'zh' || language == 'tw' ? tag.name : tag.key }}
|
{{ tag.name }}
|
||||||
</span>
|
</span>
|
||||||
</el-tag>
|
</el-tag>
|
||||||
<el-tag v-if="app.status === 'TakeDown'" class="p-mr-5">
|
<el-tag v-if="app.status === 'TakeDown'" class="p-mr-5">
|
||||||
@ -270,7 +270,7 @@ const changeTag = (key: string) => {
|
|||||||
const getTagValue = (key: string) => {
|
const getTagValue = (key: string) => {
|
||||||
const tag = tags.value.find((tag) => tag.key === key);
|
const tag = tags.value.find((tag) => tag.key === key);
|
||||||
if (tag) {
|
if (tag) {
|
||||||
return language == 'zh' || language == 'tw' ? tag.name : tag.key;
|
return tag.name;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
:type="activeTag === item.key ? 'primary' : ''"
|
:type="activeTag === item.key ? 'primary' : ''"
|
||||||
:plain="activeTag !== item.key"
|
:plain="activeTag !== item.key"
|
||||||
>
|
>
|
||||||
{{ language == 'zh' || language == 'tw' ? item.name : item.key }}
|
{{ item.name }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="inline">
|
<div class="inline">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user