Merge pull request #919 from trheyi/main
feat: Enhance Pinyin processing with additional options and tests
This commit is contained in:
commit
5d18e12999
3 changed files with 135 additions and 9 deletions
|
|
@ -56,12 +56,26 @@ const uuid = Process("utils.str.UUID");
|
||||||
const pinyin = Process("utils.str.Pinyin", "你好");
|
const pinyin = Process("utils.str.Pinyin", "你好");
|
||||||
// Returns: "ni hao"
|
// Returns: "ni hao"
|
||||||
|
|
||||||
// With options
|
// With tone marks
|
||||||
const pinyinWithTone = Process("utils.str.Pinyin", "你好", {
|
const pinyinWithTone = Process("utils.str.Pinyin", "你好", {
|
||||||
tone: true,
|
tone: true,
|
||||||
separator: "-",
|
separator: "-",
|
||||||
});
|
});
|
||||||
|
// Returns: "nǐ-hǎo"
|
||||||
|
|
||||||
|
// With tone numbers
|
||||||
|
const pinyinWithToneNumbers = Process("utils.str.Pinyin", "你好", {
|
||||||
|
tone: "number",
|
||||||
|
separator: "-",
|
||||||
|
});
|
||||||
// Returns: "ni3-hao3"
|
// Returns: "ni3-hao3"
|
||||||
|
|
||||||
|
// With multiple pronunciations for characters (heteronym mode)
|
||||||
|
const pinyinWithHeteronym = Process("utils.str.Pinyin", "中国", {
|
||||||
|
heteronym: true,
|
||||||
|
tone: true,
|
||||||
|
});
|
||||||
|
// Returns: "zhōng|zhòng guó"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Convert hex to string
|
#### Convert hex to string
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,8 @@ func ProcessUUID(process *process.Process) interface{} {
|
||||||
// - arg[0]: string, the Chinese characters to convert
|
// - arg[0]: string, the Chinese characters to convert
|
||||||
// - arg[1]: map (optional) configuration options
|
// - arg[1]: map (optional) configuration options
|
||||||
// {
|
// {
|
||||||
// "tone": bool, // whether to include tone marks, default: false
|
// "tone": bool or string, // true or "mark" for tone marks, "number" for numeric tones, false or "none" for no tones
|
||||||
|
// "heteronym": bool, // whether to return multiple pronunciations for characters, default: false
|
||||||
// "separator": string // separator between pinyin, default: " "
|
// "separator": string // separator between pinyin, default: " "
|
||||||
// }
|
// }
|
||||||
func ProcessPinyin(process *process.Process) interface{} {
|
func ProcessPinyin(process *process.Process) interface{} {
|
||||||
|
|
@ -55,17 +56,39 @@ func ProcessPinyin(process *process.Process) interface{} {
|
||||||
a := pinyin.NewArgs()
|
a := pinyin.NewArgs()
|
||||||
a.Style = pinyin.Normal // default style
|
a.Style = pinyin.Normal // default style
|
||||||
separator := " " // default separator
|
separator := " " // default separator
|
||||||
|
useToneNumber := false // flag to track if we need to convert to tone numbers
|
||||||
|
|
||||||
// Apply custom settings if provided
|
// Apply custom settings if provided
|
||||||
if process.NumOfArgs() > 1 {
|
if process.NumOfArgs() > 1 {
|
||||||
confMap := process.ArgsMap(1, maps.MapStrAny{})
|
confMap := process.ArgsMap(1, maps.MapStrAny{})
|
||||||
|
|
||||||
// Check if tone is enabled
|
// Check tone style
|
||||||
toneVal, hasTone := confMap["tone"]
|
toneVal, hasTone := confMap["tone"]
|
||||||
|
|
||||||
if hasTone {
|
if hasTone {
|
||||||
if tone, ok := toneVal.(bool); ok && tone {
|
// Handle different types of tone parameter
|
||||||
a.Style = pinyin.Tone
|
switch v := toneVal.(type) {
|
||||||
|
case bool:
|
||||||
|
// Boolean: true = mark tones, false = no tones
|
||||||
|
if v {
|
||||||
|
a.Style = pinyin.Tone
|
||||||
|
}
|
||||||
|
case string:
|
||||||
|
// String: "mark" = mark tones, "number" = numeric tones, "none" = no tones
|
||||||
|
switch v {
|
||||||
|
case "mark":
|
||||||
|
a.Style = pinyin.Tone
|
||||||
|
case "number":
|
||||||
|
a.Style = pinyin.Tone2
|
||||||
|
useToneNumber = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if heteronym is enabled
|
||||||
|
heteronymVal, hasHeteronym := confMap["heteronym"]
|
||||||
|
if hasHeteronym {
|
||||||
|
if heteronym, ok := heteronymVal.(bool); ok && heteronym {
|
||||||
|
a.Heteronym = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,14 +101,47 @@ func ProcessPinyin(process *process.Process) interface{} {
|
||||||
// Convert to Pinyin
|
// Convert to Pinyin
|
||||||
result := pinyin.Pinyin(seed, a)
|
result := pinyin.Pinyin(seed, a)
|
||||||
|
|
||||||
// Convert 2D array to 1D array
|
// Fix the tone number position if needed (to handle "ha3o" -> "hao3")
|
||||||
|
if useToneNumber {
|
||||||
|
for i, pys := range result {
|
||||||
|
for j, py := range pys {
|
||||||
|
// This is a hacky fix to move the tone number to the end
|
||||||
|
// since the library puts it after the vowel
|
||||||
|
result[i][j] = fixToneNumberPosition(py)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the pinyin results
|
||||||
pinyinStr := make([]string, 0, len(result))
|
pinyinStr := make([]string, 0, len(result))
|
||||||
for _, py := range result {
|
for _, py := range result {
|
||||||
if len(py) > 0 {
|
if len(py) > 0 {
|
||||||
pinyinStr = append(pinyinStr, py[0])
|
if a.Heteronym && len(py) > 1 {
|
||||||
|
// For heteronyms, use a pipe separator between different pronunciations
|
||||||
|
charPinyins := strings.Join(py, "|")
|
||||||
|
pinyinStr = append(pinyinStr, charPinyins)
|
||||||
|
} else {
|
||||||
|
pinyinStr = append(pinyinStr, py[0])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final := strings.Join(pinyinStr, separator)
|
final := strings.Join(pinyinStr, separator)
|
||||||
return final
|
return final
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fixToneNumberPosition moves the tone number from after the vowel to the end of the syllable
|
||||||
|
func fixToneNumberPosition(s string) string {
|
||||||
|
// Find the position of the first digit in the string
|
||||||
|
for i, c := range s {
|
||||||
|
if c >= '0' && c <= '9' {
|
||||||
|
// If the digit is at the end already, return as is
|
||||||
|
if i == len(s)-1 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
// Move the digit to the end
|
||||||
|
return s[:i] + s[i+1:] + string(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s // No digit found, return as is
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,14 +57,70 @@ func TestProcessPinyin(t *testing.T) {
|
||||||
res := process.New("utils.str.Pinyin", "你好世界").Run().(string)
|
res := process.New("utils.str.Pinyin", "你好世界").Run().(string)
|
||||||
assert.Equal(t, "ni hao shi jie", res)
|
assert.Equal(t, "ni hao shi jie", res)
|
||||||
|
|
||||||
// Test with tone enabled and custom separator
|
// Test with tone enabled (boolean true)
|
||||||
config := map[string]interface{}{
|
config := map[string]interface{}{
|
||||||
|
"tone": true,
|
||||||
|
}
|
||||||
|
res = process.New("utils.str.Pinyin", "你好世界", config).Run().(string)
|
||||||
|
assert.Equal(t, "nǐ hǎo shì jiè", res)
|
||||||
|
|
||||||
|
// Test with tone as string "mark"
|
||||||
|
config = map[string]interface{}{
|
||||||
|
"tone": "mark",
|
||||||
|
}
|
||||||
|
res = process.New("utils.str.Pinyin", "你好世界", config).Run().(string)
|
||||||
|
assert.Equal(t, "nǐ hǎo shì jiè", res)
|
||||||
|
|
||||||
|
// Test with tone as string "number"
|
||||||
|
config = map[string]interface{}{
|
||||||
|
"tone": "number",
|
||||||
|
}
|
||||||
|
res = process.New("utils.str.Pinyin", "你好世界", config).Run().(string)
|
||||||
|
assert.Equal(t, "ni3 hao3 shi4 jie4", res)
|
||||||
|
|
||||||
|
// Test with tone enabled (boolean true) and custom separator
|
||||||
|
config = map[string]interface{}{
|
||||||
"tone": true,
|
"tone": true,
|
||||||
"separator": "-",
|
"separator": "-",
|
||||||
}
|
}
|
||||||
res = process.New("utils.str.Pinyin", "你好世界", config).Run().(string)
|
res = process.New("utils.str.Pinyin", "你好世界", config).Run().(string)
|
||||||
assert.Equal(t, "nǐ-hǎo-shì-jiè", res)
|
assert.Equal(t, "nǐ-hǎo-shì-jiè", res)
|
||||||
|
|
||||||
|
// Test with tone "number" and custom separator
|
||||||
|
config = map[string]interface{}{
|
||||||
|
"tone": "number",
|
||||||
|
"separator": "-",
|
||||||
|
}
|
||||||
|
res = process.New("utils.str.Pinyin", "你好世界", config).Run().(string)
|
||||||
|
assert.Equal(t, "ni3-hao3-shi4-jie4", res)
|
||||||
|
|
||||||
|
// Test with heteronym enabled
|
||||||
|
config = map[string]interface{}{
|
||||||
|
"heteronym": true,
|
||||||
|
}
|
||||||
|
res = process.New("utils.str.Pinyin", "中国", config).Run().(string)
|
||||||
|
assert.Contains(t, res, "zhong")
|
||||||
|
assert.Contains(t, res, "guo")
|
||||||
|
|
||||||
|
// Test with heteronym and tone enabled
|
||||||
|
config = map[string]interface{}{
|
||||||
|
"heteronym": true,
|
||||||
|
"tone": true,
|
||||||
|
}
|
||||||
|
res = process.New("utils.str.Pinyin", "中国", config).Run().(string)
|
||||||
|
assert.Contains(t, res, "zhōng")
|
||||||
|
assert.Contains(t, res, "guó")
|
||||||
|
|
||||||
|
// Test with heteronym and tone number
|
||||||
|
config = map[string]interface{}{
|
||||||
|
"heteronym": true,
|
||||||
|
"tone": "number",
|
||||||
|
}
|
||||||
|
res = process.New("utils.str.Pinyin", "中国", config).Run().(string)
|
||||||
|
assert.Contains(t, res, "zhong1")
|
||||||
|
assert.NotContains(t, res, "zho1ng")
|
||||||
|
assert.Contains(t, res, "guo2")
|
||||||
|
|
||||||
// Test with only custom separator
|
// Test with only custom separator
|
||||||
config = map[string]interface{}{
|
config = map[string]interface{}{
|
||||||
"separator": "_",
|
"separator": "_",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue