123 lines
3.7 KiB
Go
123 lines
3.7 KiB
Go
package utils
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"os"
|
||
"path/filepath"
|
||
|
||
"github.com/goravel/framework/facades"
|
||
|
||
"goravel/lang"
|
||
)
|
||
|
||
// loadLangMessages 加载语言文件的 messages 对象(内部辅助函数)
|
||
// 优先从文件系统读取,失败时从 embed FS 读取(支持生产环境)
|
||
// 返回 messages map 和是否成功加载
|
||
func loadLangMessages(langCode string) (map[string]any, bool) {
|
||
var langData []byte
|
||
var err error
|
||
|
||
// 获取语言文件路径(使用框架配置的路径)
|
||
langPath := facades.Config().GetString("app.lang_path", "lang")
|
||
langFile := filepath.Join(langPath, fmt.Sprintf("%s.json", langCode))
|
||
|
||
// 优先尝试从文件系统读取
|
||
langData, err = os.ReadFile(langFile)
|
||
if err != nil {
|
||
// 文件系统读取失败,尝试从 embed FS 读取
|
||
embedFile := fmt.Sprintf("%s.json", langCode)
|
||
langData, err = lang.FS.ReadFile(embedFile)
|
||
if err != nil {
|
||
facades.Log().Debugf("读取语言文件失败: %s, embed: %s, error=%v", langFile, embedFile, err)
|
||
return nil, false
|
||
}
|
||
}
|
||
|
||
// 解析 JSON
|
||
var langMap map[string]any
|
||
if err := json.Unmarshal(langData, &langMap); err != nil {
|
||
facades.Log().Debugf("解析语言文件失败: lang=%s, error=%v", langCode, err)
|
||
return nil, false
|
||
}
|
||
|
||
// 获取 messages 对象(使用类型辅助函数)
|
||
messages, ok := GetMap(langMap, "messages")
|
||
if !ok {
|
||
facades.Log().Debugf("语言文件中没有 messages 对象: lang=%s", langCode)
|
||
return nil, false
|
||
}
|
||
|
||
return messages, true
|
||
}
|
||
|
||
// TranslateHeaders 翻译表头(直接读取语言文件)
|
||
// 这是一个通用函数,可以被任何需要翻译表头的 job 使用
|
||
//
|
||
// 参数:
|
||
// - headerKeys: 需要翻译的键列表(如 ["export_header_id", "export_header_order_no"])
|
||
// - lang: 语言代码(如 "cn" 或 "en")
|
||
//
|
||
// 返回:
|
||
// - []string: 翻译后的表头列表,如果翻译失败则返回原始键
|
||
//
|
||
// 示例:
|
||
//
|
||
// headerKeys := []string{"export_header_id", "export_header_order_no"}
|
||
// headers := utils.TranslateHeaders(headerKeys, "cn")
|
||
func TranslateHeaders(headerKeys []string, lang string) []string {
|
||
headers := make([]string, len(headerKeys))
|
||
|
||
// 加载语言文件的 messages 对象
|
||
messages, ok := loadLangMessages(lang)
|
||
if !ok {
|
||
// 如果读取失败,使用原始键
|
||
facades.Log().Warningf("加载语言文件失败: lang=%s, 使用原始键", lang)
|
||
return append([]string(nil), headerKeys...)
|
||
}
|
||
|
||
// 翻译每个键(使用泛型辅助函数)
|
||
for i, key := range headerKeys {
|
||
fullKey := "messages." + key
|
||
if value, ok := GetString(messages, key); ok && value != "" {
|
||
headers[i] = value
|
||
} else {
|
||
// 如果翻译失败,使用原始键
|
||
headers[i] = key
|
||
facades.Log().Debugf("翻译键未找到: %s (语言: %s)", fullKey, lang)
|
||
}
|
||
}
|
||
|
||
return headers
|
||
}
|
||
|
||
// TranslateKey 翻译单个键(从语言文件读取,支持文件系统和embed FS)
|
||
// 这是一个通用函数,可以被任何需要翻译单个键的地方使用(包括Job等无http.Context的场景)
|
||
//
|
||
// 参数:
|
||
// - key: 需要翻译的键(如 "export_order_status_pending")
|
||
// - lang: 语言代码(如 "cn" 或 "en")
|
||
// - defaultValue: 如果翻译失败时返回的默认值(通常为原始键)
|
||
//
|
||
// 返回:
|
||
// - string: 翻译后的文本,如果翻译失败则返回 defaultValue
|
||
//
|
||
// 示例:
|
||
//
|
||
// statusText := utils.TranslateKey("export_order_status_pending", "cn", "pending")
|
||
func TranslateKey(key, lang, defaultValue string) string {
|
||
// 加载语言文件的 messages 对象(支持文件系统和embed FS)
|
||
messages, ok := loadLangMessages(lang)
|
||
if !ok {
|
||
return defaultValue
|
||
}
|
||
|
||
// 尝试获取翻译值
|
||
if value, ok := GetString(messages, key); ok && value != "" {
|
||
return value
|
||
}
|
||
|
||
// 如果翻译失败,返回默认值
|
||
return defaultValue
|
||
}
|