From c86598e60c3c6f0a02b8a3105400cf63dde10a14 Mon Sep 17 00:00:00 2001 From: hu xiaotong <416314413@163.com> Date: Mon, 14 Jul 2025 12:36:07 +0800 Subject: [PATCH] =?UTF-8?q?i18n=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/cmd/cmd.go | 14 + internal/logic/cron/third_party_sync.go | 12 +- internal/logic/i18n/i18n.go | 428 +++++++++++++++++ internal/util/i18n.go | 610 ------------------------ 4 files changed, 451 insertions(+), 613 deletions(-) create mode 100644 internal/logic/i18n/i18n.go delete mode 100644 internal/util/i18n.go diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index de87696..32f550a 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -4,7 +4,9 @@ import ( "context" "epic/internal/controller/cron" "epic/internal/controller/hero" + "epic/internal/logic/i18n" "epic/internal/service" + "epic/internal/util" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gcmd" @@ -24,6 +26,9 @@ var ( Usage: "main", Brief: "start http server", Func: func(ctx context.Context, parser *gcmd.Parser) (err error) { + // 初始化i18n服务 + InitI18nService(ctx) + // 启动定时任务 if err := service.Cron().StartAllJobs(ctx); err != nil { g.Log().Error(ctx, "Failed to start cron jobs:", err) @@ -68,3 +73,12 @@ func setupGracefulShutdown(ctx context.Context) { os.Exit(0) }() } + +// InitI18nService 初始化i18n服务 +func InitI18nService(ctx context.Context) { + // 启动i18n自动刷新 + i18nLogic := i18n.New() + i18nLogic.StartAutoRefresh(ctx) + + util.Info(ctx, "i18n服务初始化完成") +} diff --git a/internal/logic/cron/third_party_sync.go b/internal/logic/cron/third_party_sync.go index a2d2418..9d4888a 100644 --- a/internal/logic/cron/third_party_sync.go +++ b/internal/logic/cron/third_party_sync.go @@ -5,6 +5,7 @@ import ( "encoding/json" "epic/internal/consts" "epic/internal/dao" + "epic/internal/logic/i18n" "epic/internal/model/dto" "epic/internal/model/entity" "epic/internal/util" @@ -224,9 +225,14 @@ func (t *ThirdPartyDataSync) saveHeroData(ctx context.Context, hero *dto.ThirdPa status60 := hero.CalculatedStatus["Lv60SixStarFullyAwakened"] status60json, _ := gjson.EncodeString(status60) heroJson, _ := gjson.EncodeString(hero) + // 使用i18n服务转换字段 + zhHeroName := i18n.GetZh(ctx, hero.Name) + zhRole := i18n.GetZh(ctx, hero.Role) + zhAttribute := i18n.GetZh(ctx, hero.Attribute) + newHero := &entity.EpicHeroInfo{ Id: 0, - HeroName: "", + HeroName: zhHeroName, HeroCode: hero.Code, HeroAttrLv60: status60json, Creator: "", @@ -236,10 +242,10 @@ func (t *ThirdPartyDataSync) saveHeroData(ctx context.Context, hero *dto.ThirdPa Deleted: false, NickName: "", Rarity: strconv.Itoa(hero.Rarity), - Role: hero.Role, + Role: zhRole, Zodiac: "", HeadImgUrl: "", - Attribute: "", + Attribute: zhAttribute, Remark: "", RawJson: heroJson, } diff --git a/internal/logic/i18n/i18n.go b/internal/logic/i18n/i18n.go new file mode 100644 index 0000000..a5ce45b --- /dev/null +++ b/internal/logic/i18n/i18n.go @@ -0,0 +1,428 @@ +package i18n + +import ( + "context" + "epic/internal/dao" + "epic/internal/model/entity" + "epic/internal/util" + "fmt" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" + "sync" + "time" +) + +// I18nEnToZh 英文->中文映射表(示例) +var I18nEnToZh = map[string]string{ + // 英雄名称示例 + "Achates": "雅卡泰丝", + "Adin": "艾庭", + "Angelica": "安洁莉卡", + "Bellona": "维尔萝娜", + "Charles": "查尔斯", + "Charlotte": "夏绿蒂", + + // 职业示例 + "knight": "骑士", + "warrior": "战士", + "assassin": "潜行者", + "mage": "魔导士", + "ranger": "射手", + "manauser": "精灵师", + + // 属性示例 + "fire": "火", + "wind": "木", + "ice": "水", + "dark": "暗", + "light": "光", + + // 星座示例 + "scales": "天秤座", + "lion": "狮子座", + "waterbearer": "水瓶座", + "archer": "射手座", + "crab": "巨蟹座", + "twins": "双子座", + "bull": "金牛座", + "fish": "双鱼座", + "maiden": "处女座", + "goat": "摩羯座", + "scorpion": "天蝎座", + "ram": "白羊座", + + // 这里可以继续添加你的完整映射... +} + +// I18nZhToEn 中文->英文映射表(自动生成) +var I18nZhToEn = func() map[string]string { + m := make(map[string]string, len(I18nEnToZh)) + for k, v := range I18nEnToZh { + m[v] = k + } + return m +}() + +type Logic struct { + cache map[string]map[string]string // lang -> key -> value + mutex sync.RWMutex +} + +func New() *Logic { + return &Logic{ + cache: make(map[string]map[string]string), + } +} + +// 全局i18n实例 +var globalI18nLogic *Logic +var globalI18nMutex sync.RWMutex + +func init() { + globalI18nLogic = New() +} + +// GetI18nLogic 获取全局i18n实例 +func GetI18nLogic() *Logic { + globalI18nMutex.RLock() + defer globalI18nMutex.RUnlock() + return globalI18nLogic +} + +// LoadFromDB 从数据库加载所有翻译到缓存 +func (l *Logic) LoadFromDB(ctx context.Context) error { + var mappings []*entity.EpicI18NMappings + + err := dao.EpicI18NMappings.Ctx(ctx). + Where(dao.EpicI18NMappings.Columns().Status, 1). + Where(dao.EpicI18NMappings.Columns().Deleted, 0). + Scan(&mappings) + if err != nil { + return fmt.Errorf("加载i18n数据失败: %v", err) + } + + l.mutex.Lock() + defer l.mutex.Unlock() + + // 重新构建缓存 + l.cache = make(map[string]map[string]string) + for _, m := range mappings { + if l.cache[m.Language] == nil { + l.cache[m.Language] = make(map[string]string) + } + l.cache[m.Language][m.KeyName] = m.Value + } + + util.Info(ctx, "i18n缓存加载完成,共", len(mappings), "条记录") + return nil +} + +// Get 获取指定key的指定语言翻译 +func (l *Logic) Get(ctx context.Context, lang, key string) string { + l.mutex.RLock() + defer l.mutex.RUnlock() + + if m, ok := l.cache[lang]; ok { + if v, ok := m[key]; ok { + return v + } + } + return key // 找不到返回原文 +} + +// GetBatch 批量获取翻译 +func (l *Logic) GetBatch(ctx context.Context, lang string, keys []string) map[string]string { + l.mutex.RLock() + defer l.mutex.RUnlock() + + result := make(map[string]string) + if m, ok := l.cache[lang]; ok { + for _, key := range keys { + if v, ok := m[key]; ok { + result[key] = v + } else { + result[key] = key // 找不到返回原文 + } + } + } else { + // 语言不存在,全部返回原文 + for _, key := range keys { + result[key] = key + } + } + return result +} + +// Refresh 刷新缓存 +func (l *Logic) Refresh(ctx context.Context) error { + return l.LoadFromDB(ctx) +} + +// Add 添加翻译 +func (l *Logic) Add(ctx context.Context, key, lang, value, category string) error { + // 先保存到数据库 + _, err := dao.EpicI18NMappings.Ctx(ctx).Data(g.Map{ + dao.EpicI18NMappings.Columns().KeyName: key, + dao.EpicI18NMappings.Columns().Language: lang, + dao.EpicI18NMappings.Columns().Value: value, + dao.EpicI18NMappings.Columns().Category: category, + dao.EpicI18NMappings.Columns().Status: 1, + dao.EpicI18NMappings.Columns().CreateTime: gtime.Now(), + dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(), + }).OnDuplicate("value", value).Insert() + + if err != nil { + return fmt.Errorf("添加翻译失败: %v", err) + } + + // 更新缓存 + l.mutex.Lock() + defer l.mutex.Unlock() + + if l.cache[lang] == nil { + l.cache[lang] = make(map[string]string) + } + l.cache[lang][key] = value + + util.Info(ctx, "添加翻译:", lang, key, "->", value) + return nil +} + +// Update 更新翻译 +func (l *Logic) Update(ctx context.Context, key, lang, value string) error { + // 更新数据库 + _, err := dao.EpicI18NMappings.Ctx(ctx). + Where(dao.EpicI18NMappings.Columns().KeyName, key). + Where(dao.EpicI18NMappings.Columns().Language, lang). + Data(g.Map{ + dao.EpicI18NMappings.Columns().Value: value, + dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(), + }).Update() + + if err != nil { + return fmt.Errorf("更新翻译失败: %v", err) + } + + // 更新缓存 + l.mutex.Lock() + defer l.mutex.Unlock() + + if l.cache[lang] == nil { + l.cache[lang] = make(map[string]string) + } + l.cache[lang][key] = value + + util.Info(ctx, "更新翻译:", lang, key, "->", value) + return nil +} + +// Delete 删除翻译 +func (l *Logic) Delete(ctx context.Context, key, lang string) error { + // 软删除数据库记录 + _, err := dao.EpicI18NMappings.Ctx(ctx). + Where(dao.EpicI18NMappings.Columns().KeyName, key). + Where(dao.EpicI18NMappings.Columns().Language, lang). + Data(g.Map{ + dao.EpicI18NMappings.Columns().Deleted: 1, + dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(), + }).Update() + + if err != nil { + return fmt.Errorf("删除翻译失败: %v", err) + } + + // 从缓存中删除 + l.mutex.Lock() + defer l.mutex.Unlock() + + if m, ok := l.cache[lang]; ok { + delete(m, key) + } + + util.Info(ctx, "删除翻译:", lang, key) + return nil +} + +// GetByCategory 根据分类获取翻译 +func (l *Logic) GetByCategory(ctx context.Context, lang, category string) (map[string]string, error) { + var mappings []*entity.EpicI18NMappings + + err := dao.EpicI18NMappings.Ctx(ctx). + Where(dao.EpicI18NMappings.Columns().Language, lang). + Where(dao.EpicI18NMappings.Columns().Category, category). + Where(dao.EpicI18NMappings.Columns().Status, 1). + Where(dao.EpicI18NMappings.Columns().Deleted, 0). + Scan(&mappings) + + if err != nil { + return nil, fmt.Errorf("获取分类翻译失败: %v", err) + } + + result := make(map[string]string) + for _, m := range mappings { + result[m.KeyName] = m.Value + } + + return result, nil +} + +// ImportFromMap 从map批量导入翻译 +func (l *Logic) ImportFromMap(ctx context.Context, lang string, mappings map[string]string, category string) error { + if len(mappings) == 0 { + return nil + } + + // 批量插入数据库 + var data []g.Map + for key, value := range mappings { + data = append(data, g.Map{ + dao.EpicI18NMappings.Columns().KeyName: key, + dao.EpicI18NMappings.Columns().Language: lang, + dao.EpicI18NMappings.Columns().Value: value, + dao.EpicI18NMappings.Columns().Category: category, + dao.EpicI18NMappings.Columns().Status: 1, + dao.EpicI18NMappings.Columns().CreateTime: gtime.Now(), + dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(), + }) + } + + _, err := dao.EpicI18NMappings.Ctx(ctx).Data(data).OnDuplicate("value", g.Map{ + dao.EpicI18NMappings.Columns().Value: g.Map{"value": "VALUES(value)"}, + dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(), + }).Insert() + + if err != nil { + return fmt.Errorf("批量导入翻译失败: %v", err) + } + + // 更新缓存 + l.mutex.Lock() + defer l.mutex.Unlock() + + if l.cache[lang] == nil { + l.cache[lang] = make(map[string]string) + } + for key, value := range mappings { + l.cache[lang][key] = value + } + + util.Info(ctx, "批量导入翻译完成:", lang, category, "共", len(mappings), "条") + return nil +} + +// StartAutoRefresh 启动自动刷新 +func (l *Logic) StartAutoRefresh(ctx context.Context) { + // 启动时加载 + if err := l.LoadFromDB(ctx); err != nil { + util.Error(ctx, "初始加载i18n缓存失败:", err) + } + + // 定时刷新(每小时) + go func() { + ticker := time.NewTicker(1 * time.Hour) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + if err := l.Refresh(ctx); err != nil { + util.Error(ctx, "定时刷新i18n缓存失败:", err) + } + case <-ctx.Done(): + return + } + } + }() +} + +// En2Zh 英文转中文(静态映射) +func En2Zh(s string) string { + if v, ok := I18nEnToZh[s]; ok { + return v + } + return s +} + +// Zh2En 中文转英文(静态映射) +func Zh2En(s string) string { + if v, ok := I18nZhToEn[s]; ok { + return v + } + return s +} + +// GetI18n 获取指定key的指定语言翻译(优先使用数据库,找不到则使用静态映射) +func GetI18n(ctx context.Context, lang, key string) string { + // 优先使用数据库服务 + if logic := GetI18nLogic(); logic != nil { + result := logic.Get(ctx, lang, key) + if result != key { + return result + } + } + + // 数据库找不到,使用静态映射(仅支持中英文) + if lang == "zh" { + return En2Zh(key) + } + + return key +} + +// GetZh 获取中文翻译(便捷方法) +func GetZh(ctx context.Context, key string) string { + return GetI18n(ctx, "zh", key) +} + +// GetEn 获取英文翻译(便捷方法) +func GetEn(ctx context.Context, key string) string { + return GetI18n(ctx, "en", key) +} + +// GetI18nBatch 批量获取翻译 +func GetI18nBatch(ctx context.Context, lang string, keys []string) map[string]string { + if logic := GetI18nLogic(); logic != nil { + return logic.GetBatch(ctx, lang, keys) + } + + // 降级到静态映射 + result := make(map[string]string) + for _, key := range keys { + result[key] = GetI18n(ctx, lang, key) + } + return result +} + +// GetZhBatch 批量获取中文翻译(便捷方法) +func GetZhBatch(ctx context.Context, keys []string) map[string]string { + return GetI18nBatch(ctx, "zh", keys) +} + +// GetEnBatch 批量获取英文翻译(便捷方法) +func GetEnBatch(ctx context.Context, keys []string) map[string]string { + return GetI18nBatch(ctx, "en", keys) +} + +// RefreshI18n 刷新i18n缓存 +func RefreshI18n(ctx context.Context) error { + if logic := GetI18nLogic(); logic != nil { + return logic.Refresh(ctx) + } + return nil +} + +// AddI18n 添加翻译 +func AddI18n(ctx context.Context, key, lang, value, category string) error { + if logic := GetI18nLogic(); logic != nil { + return logic.Add(ctx, key, lang, value, category) + } + return nil +} + +// ImportI18nFromMap 从map批量导入翻译 +func ImportI18nFromMap(ctx context.Context, lang string, mappings map[string]string, category string) error { + if logic := GetI18nLogic(); logic != nil { + return logic.ImportFromMap(ctx, lang, mappings, category) + } + return nil +} diff --git a/internal/util/i18n.go b/internal/util/i18n.go deleted file mode 100644 index 93b7e12..0000000 --- a/internal/util/i18n.go +++ /dev/null @@ -1,610 +0,0 @@ -package util - -// I18nEnToZh 英文->中文映射表 -var I18nEnToZh = map[string]string{ - // ... 这里粘贴你的完整映射 ... - "A Little Queen's Huge Crown": "小小女王的巨大王冠", - "A Song for Everybody": "献给你和这个世界的歌曲", - "A Symbol of Unity": "团结的象征", - "Abyssal Crown": "深渊王冠", - "Achates": "雅卡泰丝", - "Adamant Shield": "金刚石盾牌", - "Adin": "艾庭", - "Adlay": "亚迪赖", - "Adventurer Ras": "冒险家拉斯", - "Ainos": "艾诺斯", - "Ains": "艾因兹", - "Air-to-Surface Missile: MISHA": "空地导弹:美莎 ", - "Aither": "埃德勒", - "Alabastron": "雪花石膏瓶", - "Alencia": "艾莲西雅", - "Alencinox's Wrath": "艾莲西诺克斯的逆鳞", - "Alexa": "雅莉莎", - "Alexa's Basket": "雅莉莎的提篮", - "All-Rounder Wanda": "疑难杂症专家汪达", - "Alsacian Spear": "艾尔赛斯之矛", - "Ambitious Tywin": "野心分子泰温", - "Ambrote": "安布罗泰", - "Ancient Dragon's Legacy": "古龙遗产", - "Ancient Sheath": "古代剑鞘", - "Andre's Crossbow": "安德烈斯之弩", - "Angel of Light Angelica": "光之天使安洁莉卡", - "Angelic Montmorancy": "守护天使蒙茉朗西", - "Angelica": "安洁莉卡", - "Anti-Magic Mask": "抗魔面具", - "Apocalypse Ravi": "末日萝菲", - "Aqua Rose": "水玫瑰", - "Aramintha": "雅拉敏塔", - "Arbiter Vildred": "执行官维德瑞", - "Archdemon's Shadow": "魔神的暗影", - "Armin": "亚敏", - "Arowell": "雅洛薇", - "Ascending Axe": "参天斧", - "Assassin Cartuja": "杀手卡尔图哈", - "Assassin Cidd": "杀手席德", - "Assassin Coli": "杀手可丽", - "Atma's Portal": "亚特玛的传送门", - "Aurius": "亚乌利斯", - "Auxiliary Lots": "辅助型拉兹", - "Azalea": "亚洁理亚", - "Azure Comet": "青光彗星", - "Abyssal Yufine": "深渊优芬妮", - "Amiki": "雅蜜琪", - "Baal & Sezan": "巴尔&塞尚", - "Baiken": "梅喧", - "Barthez's Orbuculum": "巴泰斯的水晶球", - "Basar": "巴萨尔", - "Bask": "巴思克", - "Bastion of Hope": "希望的堡垒", - "Bastion of Perlutia": "波鲁迪亚的堡垒", - "Batisse": "巴托斯", - "Belian": "伯里安", - "Bellona": "维尔萝娜", - "Benevolent Romann": "仁慈的洛曼", - "Biting Wind Star": "寒风飞镖", - "Black Hand of the Goddess": "女神的黑手", - "Blaze Dingo": "烈火汀果", - "Blessings of Camaraderie": "友情祝福", - "Blood Blade Karin": "血剑卡琳", - "Blood Moon Haste": "赤月贵族海斯特", - "Blood-Seared Moon": "血染之月", - "Bloodbead Dagger": "血诛短剑", - "Bloodstone": "血玉髓", - "Bloody Rose": "血玫瑰", - "Bloody Warhammer": "血腥战锤", - "Bomb Model Kanna": "爆击型卡农", - "Border Coin": "孤注一掷", - "Briar Witch Iseria": "灰光森林的伊赛丽亚", - "Broken Will of the Priest": "残破的祭司长意志", - "Butcher Corps Inquisitor": "屠杀部队员", - "Butterfly Mandolin": "蝴蝶的曼陀林", - "Blooming Lidica": "花园丽迪卡", - "Byblis": "维波里丝", - "Beguiling Wings": "迷惑羽翼", - "Camilla": "卡蜜拉", - "Captain Rikoris": "先锋队长里科黎司", - "Card of Small Miracles": "小小奇迹贺年卡", - "Carmainerose": "卡麦萝兹", - "Carrot": "卡萝", - "Cartuja": "卡尔图哈", - "Cecilia": "赛西莉亚", - "Celeste": "赛雷斯特", - "Celestial Mercedes": "外太空的玫勒赛德丝", - "Celestial Spear": "天空之矛", - "Celestine": "天青石", - "Celine": "瑟琳", - "Cerise": "赛瑞丝", - "Cermia": "洁若米亚", - "Challenger Dominiel": "挑战者多米妮尔", - "Champion Zerato": "终结者杰拉图", - "Champion's Trophy": "优胜者奖杯", - "Chaos Inquisitor": "混沌教屠杀追击者", - "Chaos Sect Axe": "混沌教巨斧大将军", - "Charles": "查尔斯", - "Charlotte": "夏绿蒂", - "Chatty": "柴迪", - "Chloe": "克萝爱", - "Choux": "小泡芙", - "Christy": "克莉丝媞", - "Church of Ilryos Axe": "伊利欧斯教斧兵", - "Cidd": "席德", - "Circus Fantasia": "奇幻马戏团", - "Clarissa": "克莱莉莎", - "Closer Charles": "末日指挥官查尔斯", - "Coli": "可丽", - "Command Model Laika": "指挥型莱伊卡", - "Commander Lorina": "指挥官萝里娜", - "Conqueror Lilias": "支配者莉莉亚斯", - "Corvus": "科尔布思", - "Cradle of Life": "生命摇篮", - "Creation & Destruction": "创造之福&破坏之颂", - "Crescent Moon Rin": "新月舞姬铃儿", - "Crimson Armin": "红焰亚敏", - "Crimson Moon of Nightmares": "红色噩梦之月", - "Crimson Seed": "红焰种子", - "Crown of Glory": "荣耀之冠", - "Crozet": "克罗泽", - "Cruel Mischief": "残酷的玩笑", - "Cursed Compass": "诅咒的罗盘", - "Claudia": "克劳蒂亚", - "Dark Corvus": "黑暗的科尔布思", - "Daydream Joker": "白日梦小丑", - "Days of Destiny": "命中注定的相遇", - "Deadly Sword": "必杀大剑", - "Demon's Pistol": "恶魔手枪", - "Desert Jewel Basar": "沙漠宝石巴萨尔", - "Designer Lilibet": "设计师莉莉贝", - "Destina": "戴丝蒂娜", - "Devil's Brand": "恶魔烙印", - "Diene": "迪埃妮", - "Dignus Orb": "尊严宝珠", - "Dingo": "汀果", - "Dizzy": "蒂姬", - "Doctor's Bag": "急救包", - "Doll Maker Pearlhorizon": "制偶师波萝莱珍", - "Dominiel": "多米妮尔", - "Doris": "朵莉思", - "Double-Edged Decrescent": "双刃下弦月", - "Draco Plate": "龙族板甲", - "Dream Scroll": "梦之卷轴", - "Durandal": "杜兰月", - "Dust Devil": "尘埃恶魔", - "Dux Noctis": "暗夜指挥者", - "Dragon King Sharun": "龙王莎伦", - "Eaton": "伊顿", - "Eda": "艾妲", - "Egg of Delusion": "迷惑之蛋", - "El's Fist": "艾尔之拳", - "Elbris Ritual Sword": "埃布利斯的宝剑", - "Elena": "艾蕾娜", - "Elf's Bow": "妖精之弓", - "Elphelt": "爱尔菲特", - "Elson": "艾尔森", - "Elyha's Knife": "埃里哈刀", - "Emilia": "爱蜜莉雅", - "Enhanced Gauntlet": "强化拳套", - "Enott": "艾诺特", - "Envoy's Pipe": "死神烟斗", - "Ervalen": "艾尔巴伦", - "Eternus": "埃特诺斯", - "Etica's Scepter": "艾帝嘉权杖", - "Exorcist's Tonfa": "斗鬼的拐棍", - "Elvira": "艾碧拉", - "Eternal Wanderer Ludwig": "永劫漂流者鲁特比", - "Ezra": "艾自拉", - "Fairy Tale for a Nightmare": "噩梦童话", - "Fairy's Grimoire": "妖精的魔法书", - "Fairytale Tenebria": "童话泰妮布里雅", - "Faithless Lidica": "无神论者丽迪卡", - "Falconer Kluri": "鹰猎人可露莉", - "Fallen Cecilia": "堕落的赛西莉亚", - "Fighter Maya": "战斗型玛雅", - "Firm Shield": "坚定之盾", - "Flan": "芙兰", - "Flawless Garments": "天衣无缝", - "Flower Shower": "洒花", - "Forest Totem": "绿林图腾", - "Free Spirit Tieria": "永恒不变的黛莉亚", - "Furious": "尤贝乌斯", - "Fumyr": "芙米尔", - "General Purrgis": "大将法济斯", - "Glenn": "格伦", - "Gloomyrain": "格鲁美兰", - "Goblin's Lamp": "鬼怪明灯", - "Godmother": "教母", - "Golden Cocoa Cookie": "黄金可可豆饼干", - "Grail of Blood": "鲜血圣杯", - "Great Chief Khawana": "大族长卡瓦娜", - "Guardian Ice Crystals": "守护的冰封碎片", - "Guide to a Decision": "选择的指标", - "Guider Aither": "求道者埃德勒", - "Guiding Light": "引导之光", - "Gunther": "坤特", - "Haste": "海斯特", - "Hataan": "哈坦", - "Hazel": "海兹", - "Helen": "海伦", - "Helga": "赫尔嘉", - "Hell Cutter": "地狱切割机", - "Hilag Lance": "锡拉革骑士长矛", - "Holiday Yufine": "度假风优芬妮", - "Holy Sacrifice": "神圣牺牲", - "Hurado": "修拉杜", - "Ian": "伊安", - "Idol's Cheer": "歌姬助阵", - "Iela Violin": "依埃萝小提琴", - "Ilynav": "伊莉娜芙", - "Inferno Khawazu": "烈焰的卡瓦朱", - "Infinity Basket": "无限提篮", - "Iron Fan": "铁扇", - "Iseria": "伊赛丽亚", - "Jecht": "杰克托", - "Jena": "捷娜", - "Judge Kise": "审判者绮世", - "Judith": "茱迪丝", - "Junkyard Dog": "Junkyard Dog", - "Justice for All": "为众人的正义", - "Kal'adra": "嘉拉特拉", - "Karin": "卡琳", - "Kawerik": "卡威利", - "Kayron": "凯隆", - "Ken": "肯恩", - "Khawana": "卡瓦娜", - "Khawazu": "卡瓦朱", - "Kikirat v2": "奇奇拉特V.2", - "Kiris": "奇丽丝", - "Kise": "绮世", - "Kitty Clarissa": "猫咪克莱莉莎", - "Kizuna AI": "绊爱", - "Kluri": "可露莉", - "Knowledge Seed": "知识种子", - "Krau": "克劳乌", - "Kane": "该隐", - "Labyrinth Cube": "迷宫的方块", - "Landy": "兰蒂", - "Last Rider Krau": "最后的骑士克劳乌", - "Last Teatime": "最后的下午茶", - "Lena": "雷娜", - "Leo": "雷欧", - "Lidica": "丽迪卡", - "Lilias": "莉莉亚斯", - "Lilibet": "莉莉贝", - "Little Queen Charlotte": "年轻的女王夏绿蒂", - "Lorina": "萝里娜", - "Lots": "拉兹", - "Love Potion": "爱情灵丹", - "Lucy": "露西", - "Ludwig": "鲁特比", - "Luluca": "璐璐卡", - "Luna": "露娜", - "Leah": "蕾娅", - "Magaraha's Tome": "玛姬拉哈的魔法古书", - "Magic Scholar Doris": "魔法学者朵莉思", - "Maid Chloe": "仆人克萝爱", - "Manica of Control": "控制的护臂", - "Manifu": "玛尼普", - "Martial Artist Ken": "武斗家肯恩", - "Mascot Hazel": "吉祥物海兹", - "Maya": "玛雅", - "Mediator Kawerik": "协调者卡威利", - "Melany": "玫拉妮", - "Melissa": "梅丽莎", - "Mercedes": "玫勒赛德丝", - "Mercenary Helga": "自由自在的佣兵赫尔嘉", - "Merciless Glutton": "无情的大食客", - "Midnight Bloom": "月夜之花", - "Mighty Scout": "侦查兵玛伊堤", - "Mighty Yaksha": "金刚夜叉", - "Milim": "蜜莉姆", - "Mirsa": "米勒莎", - "Mistychain": "美丝缇彩", - "Montmorancy": "蒙茉朗西", - "Moonlight Dreamblade": "皎月梦夜", - "Moonlight's Vestige": "月光之痕", - "Mort": "魔勒", - "Ms. Confille": "Miss Confile", - "Mucacha": "穆卡察", - "Mui": "缪伊", - "Muse Rima": "缪斯黎玛", - "Necro & Undine": "恶魔&天使", - "Nemunas": "尼姆拉斯", - "New Year Cookies": "蕴含幸福的岁末饼干", - "Noble Oath": "高洁的誓言", - "Oath Key": "誓约钥匙", - "Official Levulin Beach Volleyball": "里柏林沙滩排球指定用球", - "One Year of Gratitude": "心存感谢的一年", - "Operator Sigret": "操作员赛珂兰特", - "Otherworldly Machinery": "异界的机械", - "Otillie": "奥缇莉尔", - "Old Gardening Shears": "老旧园艺剪刀", - "Pavel": "帕贝尔", - "Pearlhorizon": "波萝莱珍", - "Penelope": "潘尼罗佩", - "Politis": "佛里蒂丝", - "Portrait of the Saviors": "救援者们的画像", - "Proof of Valor": "勇猛证据", - "Prophetic Candlestick": "预视的烛台", - "Pure White Trust": "纯白的信赖", - "Purrgis": "法济斯", - "Pyllis": "费莉丝", - "Radiant Forever": "灿烂的永恒", - "Rainbow Scale": "人鱼公主的鳞片", - "Ram": "拉姆", - "Ran": "岚", - "Ranon's Memorandum": "拉农的备忘录", - "Ras": "拉斯", - "Ravi": "萝菲", - "Ray": "雷伊", - "Reingar's Special Drink": "雷茵格尔特调饮料", - "Rem": "雷姆", - "Remnant Violet": "残影的菲奥雷托", - "Requiemroar": "雷奎姆洛", - "Researcher Carrot": "研究者卡萝", - "Resolute Soldier Series": "坚毅的战士", - "Rhianna & Luciella": "里安娜&路西艾拉", - "Righteous Thief Roozid": "义贼鲁兹德", - "Rikoris": "里科黎司", - "Rima": "黎玛", - "Rimuru": "利姆路", - "Rin": "铃儿", - "Rise of a Monarch": "王的诞生", - "Roaming Warrior Leo": "流浪勇士雷欧", - "Roana": "罗安纳", - "Rod of Amaryllis": "孤挺花之杖", - "Romann": "洛曼", - "Roozid": "鲁兹德", - "Rosa Hargana": "罗沙哈勒戈纳", - "Rose": "萝季", - "Ruby Essence": "红玉精髓", - "Ruele of Light": "光之瑞儿", - "Sage Baal & Sezan": "贤者巴尔&塞尚", - "Samsara Prayer Beads": "循环念珠", - "Santa Muerte": "死亡圣神", - "Sashe Ithanes": "香袋伊妲涅斯", - "Schuri": "修里", - "Seaside Bellona": "海边的维尔萝娜", - "Secret Art - Storm Sword": "秘笈:雷天一剑", - "Senya": "赛娜", - "Sepulcrum": "塞弗克鲁姆", - "Serila": "塞丽拉", - "Severed Horn Wand": "被截断的犄角手杖", - "Sez": "赛兹", - "Shadow Knight Pyllis": "黑骑士费莉丝", - "Shadow Rose": "暗影萝季", - "Shepherd of the Hollow": "无为的引导者", - "Shepherds of Chaos": "混沌的引导者们", - "Shimadra Staff": "席玛德拉的手杖", - "Shooting Star Achates": "流星雅卡泰丝", - "Shuna": "朱菜", - "Sigret": "赛珂兰特", - "Sigurd Scythe": "席格勒赛斯", - "Silk": "席可", - "Silver Blade Aramintha": "白银刀刃的雅拉敏塔", - "Silver Rain": "银光骤雨", - "Sinful Angelica": "罪戾的安洁莉卡", - "Sira-Ren": "席拉-莲", - "Snow Crystal": "白雪水晶", - "Sol": "索尔", - "Solitaria of the Snow": "雪国的苏莉塔妮亚", - "Song of Stars": "星辰之歌", - "Sonia": "苏尼娅", - "Spear of a New Dawn": "开辟之枪", - "Specimen Sez": "实验体赛兹", - "Specter Tenebria": "幻影的泰妮布里雅", - "Spirit Eye Celine": "灵眼的瑟琳", - "Spirit's Breath": "精灵气息", - "Spooky Solayu Stories": "奇闻轶事录", - "Staff of Wisdom": "智慧的手杖", - "Star of the Deep Sea": "深海漂浮之星", - "Star Piercer": "破星者", - "Steadfast Gatekeeper": "坚定的看守者", - "Stella Harpa": "星之竖琴", - "Strak Gauntlet": "史特雷克拳套", - "Straze": "史瑞杰思", - "Succubus Mirror": "魅魔之镜", - "Summertime Iseria": "南国的伊赛丽亚", - "Super Duper Water Gun Shooter": "至尊水枪", - "Surin": "苏琳", - "Sven": "史宾", - "Sword of Ezera": "伊杰拉的圣剑", - "Sword of Holy Light": "圣光之剑", - "Sword of Judgment": "审判之剑", - "Sword of Summer Twilight": "夏夜闪刀", - "Sword of the Morning": "黎明剑", - "Sword of the Sun": "太阳之剑", - "Sword of Winter Shadow": "冬晷切刀", - "Silvertide Christy": "银波克莉丝媞", - "Seductive Flower": "诱惑之花", - "Tagehel's Ancient Book": "塔克赫尔古书", - "Tamarinne": "塔玛林尔", - "Taranor Guard": "塔拉诺尔禁卫队员", - "Taranor Royal Guard": "塔拉诺尔王宫士兵", - "Tear of the Desert": "沙漠之泪", - "Tempest Surin": "风云苏琳", - "Tenebria": "泰妮布里雅", - "The Guardian Star's Blessing": "守护星的祝福", - "Tieria": "黛莉亚", - "Time Matter": "时间的物质", - "Timeless Anchor": "永劫之锚", - "To a New World": "致崭新的时代", - "Top Model Luluca": "最强模特儿璐璐卡", - "Torn Sleeve": "撕裂的右衣袖", - "Touch of Rekos": "列科斯的救援", - "Troublemaker Crozet": "不法之徒克罗泽", - "Twilight Calamity": "落日之灾", - "Tywin": "泰温", - "Tyrant's Descent": "暴君的血统", - "Uberius's Tooth": "尤贝里乌斯的臼齿", - "Unfading Memories": "不凋零的回忆", - "Unseen Observer": "隐形的观察者", - "Upgraded Dragon Knuckles": "改良型龙指虎", - "Umbral Keystones": "暗影源石", - "Venus Orb": "金星宝珠", - "Victorious Flag": "胜战旗帜", - "Vildred": "维德瑞", - "Violet Talisman": "紫色护身符", - "Violet": "菲奥雷托", - "Vivian": "薇薇安", - "Wall of Order": "秩序护墙", - "Wanda": "汪达", - "Wanderer Silk": "流浪者席可", - "War Horn": "进攻号角", - "Watcher Schuri": "注视者修里", - "Water's Origin": "波涛的祈愿", - "Wild Angara": "野生安卡拉", - "Wind Rider": "乘风者", - "Wings of Light and Shadow": "明暗双翼", - "Wondrous Potion Vial": "灵药的试管", - "XIII. Death": "XIII. Death", - "XIV. Temperance": "XIV. Temperance", - "XVI. The Tower": "XVI. The Tower", - "XVIII. The Moon": "XVIII. The Moon", - "Yufine": "优芬妮", - "Yuna": "尤娜", - "Zahhak": "札哈克", - "Zealot Carmainerose": "传道者卡麦萝兹", - "Zeno": "杰诺", - "Zerato": "杰拉图", - "An Offer You Can't Refuse": "无法拒绝的提议", - "Benimaru's Tachi": "红丸之刀", - "Blazing Full Moon Trophy": "燃烧的满月奖杯", - "Brilliant Confidence": "闪耀的自信", - "Cutie Pando": "小可爱胖嘟", - "Fan of Light and Dark": "昏明之扇", - "Fullmetals Automail": "钢铁机械铠", - "Glo-Wings 21": "光辉羽翼21", - "Goblet of Oath": "誓言之杯", - "Golden Rose": "金玫瑰", - "Ignition Cloth Gloves": "发火布手套", - "Indestructible Gaiters": "金刚绑腿", - "Jack-O's Symbol": "洁克·欧的象征", - "Magic for Friends": "为了朋友的魔法", - "Mature Sunglasses": "成熟的墨镜", - "Nostalgic Music Box": "悲恋音乐盒", - "Prayer of Solitude": "孤独祈祷", - "Prelude to a New Era": "新时代的序幕", - "Records of Unity": "团结的记录", - "Sacred Tree Branch": "神木树枝", - "Scroll of Shadows": "暗影之书", - "Seal of Capture": "束缚之印", - "Sharpshooters Handgun": "神枪手的手枪", - "Sole Consolation": "唯一的慰藉", - "Spatiotemporal Fan": "时空折扇", - "Spear of Purification": "破邪之矛", - "Sphere of Inferno": "焚灭之球", - "Sphere of Sadism": "嗜虐之球", - "Sword of Autumn Eclipse": "秋端染刀", - "Sword of Cycling Seasons": "循环之剑", - "Aria": "艾莉雅", - "Abigail": "雅碧凯", - "Ainos 2.0": "艾诺斯 2.0", - "Amid": "雅咪德", - "Architect Laika": "策划者莱伊卡", - "Arunka": "亚露嘉", - "Astromancer Elena": "星辰的神谕艾蕾娜", - "Bad Cat Armin": "坏猫猫亚敏", - "Beehoo": "雨修", - "Benimaru": "红丸", - "Brieg": "布里克", - "Commander Pavel": "司令官帕贝尔", - "Death Dealer Ray": "死亡探究者雷伊", - "Edward Elric": "爱德华·艾力克", - "Eligos": "艾利戈斯", - "Hasol": "夏率", - "Holy Flame Adin": "圣炎的艾庭", - "Hwayoung": "和英", - "Infinite Horizon Achates": "未知可能性雅卡泰丝", - "Jack-O": "洁克·欧", - "Januta": "扎怒塔", - "Juni": "珠妮", - "Last Piece Karin": "最后的碎片卡琳", - "Lethe": "丽希", - "Lilka": "莉珈", - "Lionheart Cermia": "狮心王洁若米亚", - "Lone Crescent Bellona": "一轮孤月维尔萝娜", - "Lua": "路雅", - "Moon Bunny Dominiel": "月兔多米尼尔", - "Muwi": "武蔚", - "Navy Captain Landy": "海军上校兰蒂", - "Ocean Breeze Luluca": "海洋香气璐璐卡", - "Orte": "奥乐缇", - "Peacemaker Furious": "平衡的尤贝乌斯", - "Peira": "沛伊拉", - "Pirate Captain Flan": "海盗船长芙兰", - "Requiem Roana": "镇魂萝安纳", - "Riza Hawkeye": "莉莎·霍克爱", - "Roy Mustang": "罗伊·马斯坦古", - "Savior Adin": "救援者艾庭", - "Serene Purity Adin": "清玄的艾庭", - "Sharun": "莎伦", - "Shepherd Jena": "引导者捷娜", - "Summer Break Charlotte": "暑假夏绿蒂", - "Summer's Disciple Alexa": "夏日学生雅莉莎", - "Suthan": "斯坦", - "Sylvan Sage Vivian": "森之贤者薇薇安", - "Taeyou": "太悟", - "Talaz": "达拉士", - "Talia": "达黎儿", - "Twisted Eidolon Kayron": "扭曲亡灵凯隆", - "Unbound Knight Arowell": "自由骑士雅洛薇", - "Verdant Adin": "新绿的艾庭", - "Veronica": "贝洛妮卡", - "Vigilante Leader Glenn": "自卫队队长格伦", - "Yoonryoung": "尹凌", - "Yulha": "律荷", - "Zio": "智武", - "Midnight Gala Lilias": "夜宴莉莉亚斯", - "Urban Shadow Choux": "都市暗影小泡芙", - "Hostess of the Banquet": "宴会之主", - "Nahkwol": "落月", - "ae-GISELLE": "ae-GISELLE", - "ae-KARINA": "ae-KARINA", - "ae-NINGNING": "ae-NINGNING", - "ae-WINTER": "ae-WINTER", - "Laia": "莱雅", - "Elegiac Candles": "慰灵烛光", - "_comment_1": "角色神器结束", - - "scales": "天秤座", - "lion": "狮子座", - "waterbearer": "水瓶座", - "archer": "射手座", - "crab": "巨蟹座", - "twins": "双子座", - "bull": "金牛座", - "fish": "双鱼座", - "maiden": "处女座", - "goat": "摩羯座", - "scorpion": "天蝎座", - "ram": "白羊座", - - "knight": "骑士", - "warrior": "战士", - "assassin": "潜行者", - "mage": "魔导士", - "ranger": "射手", - "manauser": "精灵师", - - "fire": "火", - "wind": "木", - "ice": "水", - "dark": "暗", - "light": "光", - - "cp": "战斗力", - "atk": "战斗力", - "hp": "战斗力", - "spd": "战斗力", - "def": "战斗力", - "chc": "战斗力", - "chd": "战斗力", - "dac": "战斗力", - "eff": "战斗力", - "efr": "", - // ... 其余映射请粘贴完整 ... -} - -// I18nZhToEn 中文->英文映射表(自动生成) -var I18nZhToEn = func() map[string]string { - m := make(map[string]string, len(I18nEnToZh)) - for k, v := range I18nEnToZh { - m[v] = k - } - return m -}() - -// En2Zh 英文转中文 -func En2Zh(s string) string { - if v, ok := I18nEnToZh[s]; ok { - return v - } - return s -} - -// Zh2En 中文转英文 -func Zh2En(s string) string { - if v, ok := I18nZhToEn[s]; ok { - return v - } - return s -}