Skip to content

Commit

Permalink
改善【人工手動輸入音標/注音】
Browse files Browse the repository at this point in the history
  • Loading branch information
AlanJui committed Nov 10, 2024
1 parent 51f5d9f commit 02de88a
Show file tree
Hide file tree
Showing 8 changed files with 411 additions and 26 deletions.
81 changes: 81 additions & 0 deletions Documents/URS_003_解構方音符號.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# URS-003 解構方音符號

## 摘要

將【方音符號】解構成:【聲母】、【韻母】、【調符】。

如:

1. 歸:ㄍㄨㄧ
- 聲母:ㄍ
- 韻母:ㄨㄧ
- 調符:1

2. 己:ㄧˋ
- 聲母:
- 韻母:ㄧ
- 調符:2

3. 敬:ㄍㄧㄥ˪
- 聲母:ㄍ
- 韻母:ㄧㄥ
- 調符:3

4. 覺:ㄍㄚㆻ
- 聲母:ㄍ
- 韻母:ㄚㆻ
- 調符:4

5. 來:ㄌㄞˊ
- 聲母:ㄌ
- 韻母:ㄞ
- 調符:5

7. 是:ㄒㄧ˫
- 聲母:ㄒ
- 韻母:ㄧ
- 調符:7

8. 獨:ㄉㄚㆻ˙
- 聲母:ㄉ
- 韻母:ㄚㆻ
- 調符:7


## 拆解流程

1. 檢查輸入之【方音符號】的最尾一個字元是否為【方音調符】。若有,對映成【調號】。

檢查用之 pattern 。

```python
HongImTiauHu = re.compile(r"ˋ|˪|ˊ|˫|\u02D9", re.I)
```

透過 Dictionary 對映,將【方音調號】對映成【調號】。

```python
Hong_Im_Tiau_Hu_Dict = {
"ˋ" : 2,
"˪" : 3,
"ˊ" : 5,
"˫" : 7,
"\u02D9": 8,
}
```

2. 判斷沒有【方音調符】的【方音符號】,是第一聲?還是第四聲?

若是【方音符號】最尾端的字元為:ㆴ、ㆵ、ㆻ、ㆷ,則表示為第四聲(陰入);
若否,則為第一聲(陰平)。

3. 將【方音符號】剔除【方音調符】成為:【無調符方音符號】。

如:

- 【方音符號】:ㄒㄧ˫ ==> 【無調符方音符號】: ㄒㄧ
- 【方音符號】:ㄉㄧㆲ˪ ==> 【無調符方音符號】: ㄉㄧㆲ

4. 將【無調符方音符號】的第一個字元抽出當【聲母】;餘下的【無調符方音符號】
當作【韻母】。

Binary file modified Ho_Lok_Ue.db
Binary file not shown.
222 changes: 221 additions & 1 deletion mod_標音.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,61 @@
import re
import sqlite3

# 上標數字與普通數字的映射字典
superscript_digit_mapping = {
'⁰': '0',
'¹': '1',
'²': '2',
'³': '3',
'⁴': '4',
'⁵': '5',
'⁶': '6',
'⁷': '7',
'⁸': '8',
'⁹': '9',
}

def replace_superscript_digits(input_str):
return ''.join(superscript_digit_mapping.get(char, char) for char in input_str)


def choose_piau_im_method(piau_im, zu_im_huat, siann_bu, un_bu, tiau_ho):
"""選擇並執行對應的注音方法"""
if zu_im_huat == "十五音":
return piau_im.SNI_piau_im(siann_bu, un_bu, tiau_ho)
elif zu_im_huat == "白話字":
return piau_im.POJ_piau_im(siann_bu, un_bu, tiau_ho)
elif zu_im_huat == "台羅拼音":
return piau_im.TL_piau_im(siann_bu, un_bu, tiau_ho)
elif zu_im_huat == "閩拼方案":
return piau_im.BP_piau_im(siann_bu, un_bu, tiau_ho)
elif zu_im_huat == "方音符號":
return piau_im.TPS_piau_im(siann_bu, un_bu, tiau_ho)
elif zu_im_huat == "台語音標":
siann = piau_im.Siann_Bu_Dict[siann_bu]["台語音標"] or ""
un = piau_im.Un_Bu_Dict[un_bu]["台語音標"]
return f"{siann}{un}{tiau_ho}"
return ""


# ==========================================================
# 台語音標轉換為【漢字標音】之注音符號或羅馬字音標
# ==========================================================
def tlpa_tng_han_ji_piau_im(piau_im, piau_im_huat, tai_gi_im_piau):
siann_bu, un_bu, tiau_ho = split_tai_gi_im_piau(tai_gi_im_piau)

if siann_bu == "" or siann_bu == None:
siann_bu = "Ø"

han_ji_piau_im = choose_piau_im_method(
piau_im,
piau_im_huat,
siann_bu,
un_bu,
tiau_ho
)
return han_ji_piau_im


# =========================================================
# 判斷是否為標點符號的輔助函數
Expand Down Expand Up @@ -38,6 +93,105 @@ def is_valid_han_ji(char):
# for tai_loo, tai_gi in tai_loo_to_tai_gi_mapping.items():
# tai_gi_im = tai_gi_im.replace(tai_loo, tai_gi)
# ==========================================================

# ----------------------------------------------------------
# 自「台語音標+」,分析出:聲母、韻母、聲調
# ----------------------------------------------------------
def split_tai_gi_im_piau(im_piau):
# 聲母相容性轉換處理(將 tsh 轉換為 c;將 ts 轉換為 z)
# zu_im = zu_im.replace("tsh", "c") # 將 tsh 轉換為 c
# zu_im = zu_im.replace("ts", "z") # 將 ts 轉換為 z
if im_piau.startswith("tsh") or im_piau.startswith("ch"):
im_piau = im_piau.replace("tsh", "c", 1).replace("ch", "c", 1) # 將 tsh, ch 轉換為 c
elif im_piau.startswith("ts") or im_piau.startswith("c"):
im_piau = im_piau.replace("ts", "z", 1).replace("c", "z", 1) # 將 ts, c 轉換為 z

# 定義聲母的正規表示式,包括常見的聲母,但不包括 m 和 ng
siann_bu_pattern = re.compile(r"(b|c|z|g|h|j|kh|k|l|m(?!\d)|ng(?!\d)|n|ph|p|s|th|t|Ø)")

# 韻母為 m 或 ng 這種情況的正規表示式 (m\d 或 ng\d)
un_bu_as_m_or_ng_pattern = re.compile(r"(m|ng)\d")

result = []

# 首先檢查是否是 m 或 ng 當作韻母的特殊情況
if un_bu_as_m_or_ng_pattern.match(im_piau):
siann_bu = "" # 沒有聲母
un_bu = im_piau[:-1] # 韻母是 m 或 ng
tiau = im_piau[-1] # 聲調是最後一個字符
else:
# 使用正規表示式來匹配聲母
siann_bu_match = siann_bu_pattern.match(im_piau)
if siann_bu_match:
siann_bu = siann_bu_match.group() # 找到聲母
un_bu = im_piau[len(siann_bu):-1] # 韻母部分
else:
siann_bu = "" # 沒有匹配到聲母,聲母為空字串
un_bu = im_piau[:-1] # 韻母是剩下的部分,去掉最後的聲調

tiau = im_piau[-1] # 最後一個字符是聲調

# 將上標數字替換為普通數字
tiau = replace_superscript_digits(str(tiau))
# tiau = 7 if int(tiau_ho) == 6 else int(tiau)

result += [siann_bu]
result += [un_bu]
result += [tiau]
return result


def split_hong_im_hu_ho(hong_im_hu_ho):
# 定義調符對應的字典
Hong_Im_Tiau_Hu_Dict = {
"ˋ": 2,
"˪": 3,
"ˊ": 5,
"˫": 7,
"\u02D9": 8, # '˙'
}

# 編譯調符的正則表達式模式
HongImTiauHu = re.compile(r"[ˋ˪ˊ˫˙]", re.I)

# 定義表示第四聲的尾字元集合
tone_4_endings = {'ㆴ', 'ㆵ', 'ㆻ', 'ㆷ'}

# 定義聲母的集合
sheng_mu_ji = {
'ㄅ', 'ㄆ', 'ㆠ', 'ㄇ',
'ㄉ', 'ㄊ', 'ㄋ', 'ㄌ',
'ㄍ', 'ㄎ', 'ㆣ', 'ㄏ', 'ㄫ',
'ㄗ', 'ㄘ', 'ㆡ', 'ㄙ',
'ㄐ', 'ㄑ', 'ㆢ', 'ㄒ',
'ㄓ', 'ㄔ', 'ㄕ', 'ㄖ',
'ㄭ', 'ㄪ', 'ㄬ', 'ㄈ',
}

# 步驟一:檢查最後一個字元是否為調符
if HongImTiauHu.match(hong_im_hu_ho[-1]):
tiau_fu = hong_im_hu_ho[-1]
tiau_hao = Hong_Im_Tiau_Hu_Dict[tiau_fu]
# 移除調符,獲得無調符的方音符號
wu_tiau_fu_hong_im_hu_ho = hong_im_hu_ho[:-1]
else:
# 最後沒有調符,判斷是第一聲還是第四聲
if hong_im_hu_ho[-1] in tone_4_endings:
tiau_hao = 4
else:
tiau_hao = 1
wu_tiau_fu_hong_im_hu_ho = hong_im_hu_ho

# 步驟四:提取聲母和韻母
if wu_tiau_fu_hong_im_hu_ho and wu_tiau_fu_hong_im_hu_ho[0] in sheng_mu_ji:
sheng_mu = wu_tiau_fu_hong_im_hu_ho[0]
yun_mu = wu_tiau_fu_hong_im_hu_ho[1:]
else:
sheng_mu = ''
yun_mu = wu_tiau_fu_hong_im_hu_ho

return [sheng_mu, yun_mu, str(tiau_hao)]

def split_zu_im(zu_im):
# 聲母相容性轉換處理(將 tsh 轉換為 c;將 ts 轉換為 z)
# zu_im = zu_im.replace("tsh", "c") # 將 tsh 轉換為 c
Expand Down Expand Up @@ -77,6 +231,48 @@ def split_zu_im(zu_im):
result += [tiau]
return result

# 方音符號轉換為【台語音標】
def hong_im_tng_tai_gi_im_piau(siann, un, tiau, cursor):
"""
根據傳入的方音符號聲母、韻母、聲調,轉換成對應的台語音標
:param siann: 聲母 (方音符號)
:param un: 韻母 (方音符號)
:param tiau: 聲調 (方音符號)
:param cursor: 數據庫游標
:return: 包含台語音標的字典
"""
# 查詢聲母表,將方音符號的聲母轉換成台語音標
cursor.execute("SELECT 台語音標 FROM 聲母對照表 WHERE 方音符號 = ?", (siann,))
siann_result = cursor.fetchone()
if siann_result:
tai_gi_siann = siann_result[0] # 取得台語音標
else:
tai_gi_siann = '' # 無聲母的情況

# 查詢韻母表,將方音符號的韻母轉換成台語音標
cursor.execute("SELECT 台語音標 FROM 韻母對照表 WHERE 方音符號 = ?", (un,))
un_result = cursor.fetchone()
if un_result:
tai_gi_un = un_result[0] # 取得台語音標
else:
tai_gi_un = ''

# 查詢聲調表,將方音符號的聲調轉換成台語音標
# cursor.execute("SELECT 方音符號調符 FROM 聲調對照表 WHERE 台羅調號 = ?", (tiau,))
# tiau_result = cursor.fetchone()
# if tiau_result:
# tai_gi_tiau = tiau_result[0] # 取得台語音標
# else:
# tai_gi_tiau = ''
tai_gi_tiau = tiau

return {
'台語音標': f"{tai_gi_siann}{tai_gi_un}{tai_gi_tiau}",
'聲母': tai_gi_siann,
'韻母': tai_gi_un,
'聲調': tai_gi_tiau,
}


# 台語音標轉換為方音符號
def TL_Tng_Zu_Im(siann_bu, un_bu, siann_tiau, cursor):
Expand Down Expand Up @@ -263,6 +459,14 @@ class PiauIm:
}
}

Hong_Im_Tiau_Hu_Dict = {
"ˋ" : 2,
"˪" : 3,
"ˊ" : 5,
"˫" : 7,
"\u02D9": 8,
}

def __init__(self, han_ji_khoo):
self.Siann_Bu_Dict = None
self.Un_Bu_Dict = None
Expand All @@ -271,6 +475,7 @@ def __init__(self, han_ji_khoo):
self.TL_pattern2 = re.compile(r"(o|e|a|u|i|n|m)", re.I)
self.POJ_pattern1 = re.compile(r"(oai|oan|oah|oeh|ee|ei)", re.I)
self.POJ_pattern2 = re.compile(r"(o|e|a|u|i|n|m)", re.I)
self.HongImTiauHu = re.compile(r"ˋ|˪|ˊ|˫|\u02D9", re.I)

def _init_siann_bu_dict(self, cursor):
# 執行 SQL 查詢
Expand Down Expand Up @@ -371,6 +576,10 @@ def bp_un_bu_ga_tiau_ho(self, guan_im, tiau):
def TL_piau_im(self, siann_bu, un_bu, tiau_ho):
piau_im_huat = "台羅拼音"

# 將上標數字替換為普通數字
tiau_ho = replace_superscript_digits(str(tiau_ho))
tiau_ho = 7 if int(tiau_ho) == 6 else int(tiau_ho)

if siann_bu == None or siann_bu == "Ø":
siann = ""
else:
Expand Down Expand Up @@ -415,6 +624,10 @@ def TL_piau_im(self, siann_bu, un_bu, tiau_ho):
def POJ_piau_im(self, siann_bu, un_bu, tiau_ho):
piau_im_huat = "白話字"

# 將上標數字替換為普通數字
tiau_ho = replace_superscript_digits(str(tiau_ho))
tiau_ho = 7 if int(tiau_ho) == 6 else int(tiau_ho)

if siann_bu == None or siann_bu == "Ø":
siann = ""
else:
Expand Down Expand Up @@ -474,6 +687,10 @@ def BP_piau_im(self, siann_bu, un_bu, tiau_ho):
8: 8, # 陽入:4?
}

# 將上標數字替換為普通數字
tiau_ho = replace_superscript_digits(str(tiau_ho))
tiau_ho = 7 if int(tiau_ho) == 6 else int(tiau_ho)

if siann_bu == None or siann_bu == "Ø":
siann = ""
else:
Expand Down Expand Up @@ -540,9 +757,12 @@ def TPS_piau_im(self, siann_bu, un_bu, tiau_ho):
"ㆡㄧ": "ㆢㄧ",
}

# 將上標數字替換為普通數字
tiau_ho = replace_superscript_digits(str(tiau_ho))
tiau_ho = 7 if int(tiau_ho) == 6 else int(tiau_ho)

siann = self.Siann_Bu_Dict[siann_bu][piau_im_huat]
un = self.Un_Bu_Dict[un_bu][piau_im_huat]
tiau_ho = 7 if int(tiau_ho) == 6 else int(tiau_ho)
tiau = self.TONE_MARKS[piau_im_huat][tiau_ho]
piau_im = f"{siann}{un}{tiau}"

Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit 02de88a

Please sign in to comment.