package util import ( "encoding/base64" "strings" "unicode" "github.com/mozillazg/go-pinyin" ) // StringSegment 表示字符串片段及其类型 type StringSegment struct { Text string StrType int // 0: 英文/数字, 1: 中文, 2: 其他语言 } // SplitRuneString 将字符串切割成不同类型的片段 func SplitRuneString(s string) []StringSegment { var segments []StringSegment var builder strings.Builder var currentType int // 当前正在构建的片段类型 // 获取字符类型 getCharType := func(r rune) int { switch { case unicode.Is(unicode.Han, r): return 1 // 中文 case unicode.Is(unicode.Hiragana, r) || unicode.Is(unicode.Katakana, r): return 2 // 日语假名 case unicode.Is(unicode.Hangul, r): return 2 // 韩语 case unicode.Is(unicode.Thai, r): return 2 // 泰语 case unicode.IsLetter(r) || unicode.IsDigit(r): return 0 // 英文或数字 default: // 其他 Unicode 字符,如果不是空格或标点,也认为是其他语言 if !unicode.IsSpace(r) && !unicode.IsPunct(r) { return 2 } // 对于空格和标点,跟随当前类型 return currentType } } // 添加当前片段到结果中 addSegment := func() { if builder.Len() > 0 { segments = append(segments, StringSegment{ Text: builder.String(), StrType: currentType, }) builder.Reset() } } runes := []rune(s) if len(runes) == 0 { return segments } // 初始化第一个字符 firstChar := runes[0] currentType = getCharType(firstChar) builder.WriteRune(firstChar) // 处理剩余字符 for i := 1; i < len(runes); i++ { currentChar := runes[i] charType := getCharType(currentChar) // 如果字符类型发生变化,添加新片段 if charType != currentType { addSegment() currentType = charType } builder.WriteRune(currentChar) } // 添加最后一个片段 addSegment() return segments } // ConvertRuneToEn 将字符串中的中文转换为拼音,其他语言转换为 base64 func ConvertRuneToEn(s string) string { segments := SplitRuneString(s) var result strings.Builder a := pinyin.NewArgs() for i, seg := range segments { switch seg.StrType { case 0: // 英文/数字 result.WriteString(seg.Text) case 1: // 中文 pinyinSlice := pinyin.LazyPinyin(seg.Text, a) result.WriteString(strings.Join(pinyinSlice, "")) case 2: // 其他语言,使用 base64 编码(不带填充) result.WriteString(base64.RawURLEncoding.EncodeToString([]byte(seg.Text))) } // 如果不是最后一个片段,且下一个片段类型不同,添加空格 if i < len(segments)-1 && segments[i+1].StrType != seg.StrType { result.WriteString("") } } return result.String() }