最近在製作專案時,使用了一個名為 Vosk 的語音辨識,但目前 Vosk 沒有繁中的模型,只能夠輸出簡體中文,所以我便簡單的土炮了一個簡轉繁的 C# 程式,方便專案使用。
(P.S. 如果你問我為什麼不用 WhisperCpp,這邊直接回答各位,主要是因為在手機上 WhisperCpp 跑起來還是太慢,辨識結果輸出不夠即時)
完整程式 & 使用方法
程式碼
這邊先給上完整的程式,但由於程式中間的字典部分太長,所以要直接下載完整的程式,可以點下方的下載按鈕下載。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
using System.Collections;
using System.Collections.Generic;
using System.Text;
public class zhSimplify2Traditional
{
Dictionary<char, char> map;
public zhSimplify2Traditional(){
map = new Dictionary<char, char>{
{'一', '一'},
{'七', '七'},
{'万', '萬'},
{'丈', '丈'},
{'三', '三'},
{'上', '上'},
{'下', '下'},
// 後面還有很多字...
};
}
public string convert(string simplify){
StringBuilder traditional = new StringBuilder();
foreach(char c in simplify){
if(map.ContainsKey(c)){
traditional.Append(map[c]);
}else{
traditional.Append(c);
}
}
return traditional.ToString();
}
}
|
使用範例
以下使用 Unity 來做範例,在其他 C# 程式中也一樣是通用的。
在使用時,我們只需要創建一個新的 zhSimplify2Traditional 物件,便可以直接呼叫其中的 convert 函式,來將簡體中文轉為繁體。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
using System;
using UnityEngine;
using UnityEngine.UI;
public class convertTest : MonoBehaviour
{
zhSimplify2Traditional converter = new zhSimplify2Traditional();
string simplified = "这是简体中文";
void Start(){
Debug.Log(converter.convert(simplified)); //輸出: 這是簡體中文
}
}
|

原理簡介
今天我使用的方法,理論上絕對不會是最好的,只是在概念上最容易實作。
我所使用的方法,是使用 C# 裡的 Dictionary 製作簡體與繁體的對應表,將輸入函式中的字串遍歷,分別找到對應的繁體中文。

之所以使用 Dictionary 而不是用陣列,是根據微軟所述,Dictionary 會實作為雜湊表,查找時的時間複雜度理論上為 O(1)。當 Dictionary 擴充到很多字的時候,性能上幾乎不會有影響,所以便採用此方法。

微軟文件 Dictionary<TKey,TValue> 類別:
https://learn.microsoft.com/zh-tw/dotnet/api/system.collections.generic.dictionary-2?view=net-7.0#remarks
開始製作
首先,我們先創一個新的 Class,命名為 zhSimplify2Traditional。
裡面包含該 Class 的 Constructor 以及一個函式 convert。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
using System.Collections;
using System.Collections.Generic;
using System.Text;
public class zhSimplify2Traditional
{
public zhSimplify2Traditional(){
}
public string convert(string simplify){
}
}
|
接著我們宣告一個 Dictionary 變數命名為 map,並在 Constructor 內建立物件,製作簡轉繁的字典,Dictionary 的兩個型別皆使用 char
至於字典內的資料這邊我先隨便填入幾筆,文章後面在跟大家介紹如何製作字典內的資料。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
using System.Collections;
using System.Collections.Generic;
using System.Text;
public class zhSimplify2Traditional
{
Dictionary<char, char> map;
public zhSimplify2Traditional(){
map = new Dictionary<char, char>{
{'一', '一'},
{'七', '七'},
{'万', '萬'},
{'丈', '丈'},
{'三', '三'},
{'上', '上'},
{'下', '下'},
// 後面還有很多字...
};
}
public string convert(string simplify){
}
}
|
創完字典,我們就可以來寫查表轉換的部分了。
以下是程式:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public string convert(string simplify){
StringBuilder traditional = new StringBuilder();
foreach(char c in simplify){ //遍歷輸入字串
if(map.ContainsKey(c)){ //判斷字典中是否有該簡體字
traditional.Append(map[c]); //有的話就使用該簡體字作為key 將字典中對應的繁體字加到 StringBuilder 中
}else{
traditional.Append(c); //沒有的話就原封不動的加到 StringBuilder 中
}
}
return traditional.ToString(); //最後將 StringBuilder 轉為字串回傳
}
|
這邊我使用 StringBuilder 來組合字元,在效率上會比直接用【+】號來連接好。
整體上就是直接遍歷輸入字串,判斷每個字是否有作為 key 存在於字典中,有的話就取出值加入 StringBuilder,沒有的話舊原封不動的加入 StringBuilder。
最後在將 StringBuilder 轉為字串回傳,便完成了程式的功能撰寫。
再貼一次完整程式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
using System.Collections;
using System.Collections.Generic;
using System.Text;
public class zhSimplify2Traditional
{
Dictionary<char, char> map;
public zhSimplify2Traditional(){
map = new Dictionary<char, char>{
{'一', '一'},
{'七', '七'},
{'万', '萬'},
// 這邊放簡體與繁體的字元對照表...
};
}
public string convert(string simplify){
StringBuilder traditional = new StringBuilder();
foreach(char c in simplify){
if(map.ContainsKey(c)){
traditional.Append(map[c]);
}else{
traditional.Append(c);
}
}
return traditional.ToString();
}
}
|
如何製作字典的資料
字典資料的部分,如果不想要使用我目前製作好的檔案,可以試著從維基百科上抓,
維基百科:中文繁簡體對照表
https://zh.wikipedia.org/zh-tw/Wikipedia:%E4%B8%AD%E6%96%87%E7%B9%81%E7%AE%80%E4%BD%93%E5%AF%B9%E7%85%A7%E8%A1%A8

我這邊是直接複製維基百科上的中文繁簡體對照表,然後寫一個簡單的 Python 程式處理一下格式,便可以複製到程式中的字典裡。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
output = ""
keys = []
with open("simplify2Traditional.txt", 'r', encoding='utf-8') as fr:
lines = fr.readlines()
for text in lines:
text = text.replace("\n", "")
text = text.replace(" ", "")
temp = text.split("→")
if temp[1] in keys:
continue
output += "{" + f"\'{temp[1]}\', \'{temp[0]}\'" + "},\n"
keys.append(temp[1])
with open("simplify2TraditionalMap.txt", 'w', encoding='utf-8') as fr:
fr.write(output)
|
