package utils import ( "fmt" "strings" "github.com/mozillazg/go-pinyin" ) // reportTypeTranslations locale 到 数据报告/竞品报告 翻译的映射 var reportTypeTranslations = map[string]map[string]string{ "zh-CN": { "数据报告": "数据报告", "竞品报告": "竞品报告", }, "zh-TW": { "数据报告": "數據報告", "竞品报告": "競合報告", }, "EN": { "数据报告": "Data Report", "竞品报告": "Competitor Report", }, "de-DE": { "数据报告": "Datenbericht", "竞品报告": "Wettbewerbsanalyse", }, "ja-JP": { "数据报告": "データレポート", "竞品报告": "競合分析レポート", }, } // pinyinTitles 中文称谓"老师"对应的拼音形式(用于检测) var pinyinTitles = []string{"lao shi", "laoshi"} // ConvertNameToPinyin 将中文姓名转换为拼音,单词首字母大写,单词间用空格分隔。 // 对于非中文 locale,会去除"老师"称谓。 // 示例:"王旗老师" -> "Wang Qi" func ConvertNameToPinyin(name string) string { args := pinyin.NewArgs() slices := pinyin.Pinyin(name, args) var result []string for _, s := range slices { if len(s) > 0 { // 首字母大写 runes := []rune(s[0]) if len(runes) > 0 { uppered := string([]rune{runes[0] - 32}) + string(runes[1:]) result = append(result, uppered) } } } pinyinName := joinWithSpace(result) // 对于非中文 locale,去除拼音 "Lao Shi" lowerName := strings.ToLower(pinyinName) for _, pt := range pinyinTitles { if strings.HasSuffix(lowerName, pt) { // 提取去掉称谓后的姓名部分 nameWithoutTitle := strings.TrimSuffix(pinyinName, " Lao Shi") nameWithoutTitle = strings.TrimSuffix(nameWithoutTitle, " Laoshi") return nameWithoutTitle } } return pinyinName } // joinWithSpace 用空格连接字符串,过滤空字符串 func joinWithSpace(parts []string) string { var nonEmpty []string for _, p := range parts { if p != "" { nonEmpty = append(nonEmpty, p) } } if len(nonEmpty) == 0 { return "" } result := nonEmpty[0] for i := 1; i < len(nonEmpty); i++ { result += " " + nonEmpty[i] } return result } // ConvertReportName 将报告名转换为指定语言版本。 // prefix: YYYY-MM 格式,如 "2026-03" // personName: 中文姓名,如 "王旗老师" // reportType: "数据报告" 或 "竞品报告" // locale: "zh-CN", "zh-TW", "EN", "de-DE", 或 "ja-JP" func ConvertReportName(prefix, personName, reportType, locale string) string { reportTypeTrans, ok := reportTypeTranslations[locale] if !ok { reportTypeTrans = reportTypeTranslations["zh-CN"] } translatedReportType, ok := reportTypeTrans[reportType] if !ok { translatedReportType = reportType } // 对于中文 locale(zh-CN, zh-TW),保持原样 if locale == "zh-CN" || locale == "zh-TW" { displayName := personName if locale == "zh-TW" { // zh-TW 去掉"老师",繁体报告类型已通过 translatedReportType 获取 displayName = strings.ReplaceAll(personName, "老师", "") } return fmt.Sprintf("%s%s%s", prefix, displayName, translatedReportType) } // 对于其他 locale,转换为拼音 pinyinName := ConvertNameToPinyin(personName) return fmt.Sprintf("%s %s %s", prefix, pinyinName, translatedReportType) } // isValidPrefix 校验 prefix 是否为 YYYY-MM 格式(年份和月份都是数字) func isValidPrefix(prefix string) bool { if len(prefix) != 7 || prefix[4] != '-' { return false } for i := 0; i < 4; i++ { if prefix[i] < '0' || prefix[i] > '9' { return false } } if prefix[5] < '0' || prefix[5] > '9' || prefix[6] < '0' || prefix[6] > '9' { return false } return true } // ConvertTitleByLocale 将报告标题根据 locale 进行翻译转换。 // title: 原始中文标题,格式为 "YYYY-MM" + 姓名 + "数据报告"/"竞品报告",如 "2026-03王旗老师数据报告" // locale: "zh-CN", "zh-TW", "EN", "de-DE", "ja-JP" 或其他 Accept-Language 值 // 返回翻译后的标题,如果格式不符则返回原标题。 func ConvertTitleByLocale(title, locale string) string { if len(title) < 7 { return title } prefix := title[:7] // YYYY-MM if !isValidPrefix(prefix) { return title } var reportType string if strings.HasSuffix(title, "数据报告") { reportType = "数据报告" } else if strings.HasSuffix(title, "竞品报告") { reportType = "竞品报告" } else { return title } personName := title[7 : len(title)-len(reportType)] return ConvertReportName(prefix, personName, reportType, locale) } // ParseLocaleHeader 解析 Accept-Language 请求头,返回规范化的 locale 字符串。 // zh-CN / zh / ZhCN 无需翻译,返回 "";其余值规范化后返回,不支持的语言同样返回 ""。 func ParseLocaleHeader(header string) string { if header == "zh-CN" || header == "zh" || header == "ZhCN" { return "" } switch header { case "zh-TW", "ZhTW": return "zh-TW" case "en", "EN": return "EN" case "de-DE", "ja-JP": return header default: return "" } }