feat(pages): add multi-language support for landing pages
Implement internationalization system for landing pages: - Database model for storing language-specific translations - Language configuration with default and enabled languages - Language switcher in navigation across all templates - Translation management UI in settings - Support for 15 languages including English, Spanish, German, French, Japanese, Chinese - Auto-detection and manual language selection - AI-powered translation generation capability
This commit is contained in:
@@ -441,6 +441,7 @@ func prepareMigrationTasks() []*migration {
|
||||
newMigration(364, "Add view_count to blog_post", v1_26.AddViewCountToBlogPost),
|
||||
newMigration(365, "Add public_app_integration to repository", v1_26.AddPublicAppIntegrationToRepository),
|
||||
newMigration(366, "Add page experiment tables for A/B testing", v1_26.AddPageExperimentTables),
|
||||
newMigration(367, "Add pages translation table for multi-language support", v1_26.AddPagesTranslationTable),
|
||||
}
|
||||
return preparedMigrations
|
||||
}
|
||||
|
||||
24
models/migrations/v1_26/v367.go
Normal file
24
models/migrations/v1_26/v367.go
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2026 MarketAlly. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_26
|
||||
|
||||
import (
|
||||
"code.gitcaddy.com/server/v3/modules/timeutil"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AddPagesTranslationTable(x *xorm.Engine) error {
|
||||
type Translation struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX NOT NULL"`
|
||||
Lang string `xorm:"VARCHAR(10) NOT NULL"`
|
||||
ConfigJSON string `xorm:"TEXT"`
|
||||
AutoGenerated bool `xorm:"NOT NULL DEFAULT false"`
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
||||
}
|
||||
|
||||
return x.Sync(new(Translation))
|
||||
}
|
||||
70
models/pages/translation.go
Normal file
70
models/pages/translation.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2026 MarketAlly. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package pages
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitcaddy.com/server/v3/models/db"
|
||||
"code.gitcaddy.com/server/v3/modules/timeutil"
|
||||
)
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(Translation))
|
||||
}
|
||||
|
||||
// Translation stores a language-specific translation overlay for a landing page.
|
||||
type Translation struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX NOT NULL"`
|
||||
Lang string `xorm:"VARCHAR(10) NOT NULL"`
|
||||
ConfigJSON string `xorm:"TEXT"`
|
||||
AutoGenerated bool `xorm:"NOT NULL DEFAULT false"`
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
||||
}
|
||||
|
||||
// TableName returns the table name for Translation.
|
||||
func (t *Translation) TableName() string {
|
||||
return "pages_translation"
|
||||
}
|
||||
|
||||
// GetTranslationsByRepoID returns all translations for a repository.
|
||||
func GetTranslationsByRepoID(ctx context.Context, repoID int64) ([]*Translation, error) {
|
||||
translations := make([]*Translation, 0, 10)
|
||||
return translations, db.GetEngine(ctx).Where("repo_id = ?", repoID).
|
||||
Asc("lang").Find(&translations)
|
||||
}
|
||||
|
||||
// GetTranslation returns a specific language translation for a repository.
|
||||
func GetTranslation(ctx context.Context, repoID int64, lang string) (*Translation, error) {
|
||||
t := new(Translation)
|
||||
has, err := db.GetEngine(ctx).Where("repo_id = ? AND lang = ?", repoID, lang).Get(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !has {
|
||||
return nil, nil
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// CreateTranslation creates a new translation.
|
||||
func CreateTranslation(ctx context.Context, t *Translation) error {
|
||||
_, err := db.GetEngine(ctx).Insert(t)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateTranslation updates an existing translation.
|
||||
func UpdateTranslation(ctx context.Context, t *Translation) error {
|
||||
_, err := db.GetEngine(ctx).ID(t.ID).Cols("config_json", "auto_generated").Update(t)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteTranslation deletes a translation by repo ID and language.
|
||||
func DeleteTranslation(ctx context.Context, repoID int64, lang string) error {
|
||||
_, err := db.GetEngine(ctx).Where("repo_id = ? AND lang = ?", repoID, lang).
|
||||
Delete(new(Translation))
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user