Skip to content
This repository was archived by the owner on Nov 2, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,6 @@ ENV/


.idea/
.vscode/
.vscode/

.DS_Store
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
test:
python3 -m unittest discover -v . "*Test.py"
135 changes: 132 additions & 3 deletions pyhokchew/convert.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from .models.CikLinSyllable import CikLinSyllable
from .models.FoochowRomanized import FoochowRomanizedSyllable

from .models.historical.CikLinSyllable import CikLinSyllable
from .models.historical.FoochowRomanized import FoochowRomanizedSyllable
from .models.historical.HectorScheme import HectorSyllable
from .models.concurrent.matsu import WuyixingSyllable
from .models.concurrent.minjiang import MinjiangSyllable
from .models.yngping.YngPingTwo import YngPingSyllable

def foochow_romanized_to_ciklin(f):
ciklin_syllable = CikLinSyllable(f.initial,f.final,f.tone)
Expand All @@ -18,3 +21,129 @@ def ciklin_to_foochow_romanized_string(cInitial, cFinal, cTone):
:return: The converted Foochow Romanized string.
"""
return ciklin_to_foochow_romanized(CikLinSyllable.from_ciklin_string(cInitial+cFinal,cTone)).get_string()

def foochow_romanized_to_yngping(f: FoochowRomanizedSyllable):
INITIAL_MAPPING = ['l', 'b', 'g', 'k', 'd',
'p', 't', 'z', 'n', 's',
'' , 'm','ng','c', 'h']
FINAL_MAPPING = [
# 1 2 3 4 5 7 8 FR
# 55 33 212 23 53 242 5 YP
['ung', 'ung', 'oung', 'ouk', 'ung', 'oung', 'uk'], # 春
['ua', 'ua', 'ua', 'uah', 'ua', 'ua', 'uah'], # 花
['yong', 'yong','yong', 'yok', 'yong', 'yong', 'yok'], # 香
['iu', 'iu', 'iu', 'iuh', 'iu', 'iu', None], # 秋
['ang', 'ang', 'ang', 'ak', 'ang', 'ang', 'ak'], # 山
['ai', 'ai', 'ai', 'aih', 'ai', 'ai', 'aih'], # 開
['a', 'a', 'a', 'ah', 'a', 'a', 'ah'], # 嘉
['ing', 'ing', 'eing', 'eik', 'ing', 'eing', 'ik'], # 賓
['uang', 'uang','uang', 'uak', 'uang', 'uang', 'uak'], # 歡
['o', 'o', 'o', 'oh', 'o', 'o', 'oh'], # 歌
['y', 'y', 'oey', 'oeyk','y', 'oey', 'yk'], # 須
['ui', 'ui', 'ui', 'uih', 'ui', 'ui', None], # 杯
['u', 'u', 'ou', 'ouh', 'u', 'ou', 'uh'], # 孤
['eing', 'eing','aing', 'aik', 'eing', 'aing', 'eik'], # 燈
['uong', 'uong','uong', 'uok', 'uong', 'uong', 'uok'], # 光
['ui', 'ui', 'ui', 'uih', 'ui', 'ui', 'uih'], # 輝
['iu', 'iu', 'iu', 'iuh', 'iu', 'iu', None], # 燒
['yng', 'yng', 'oeyng','oeyk','yng', 'oeyng','yk'], # 銀
['oung', 'oung','aung', 'auk', 'oung', 'aung', 'ouk'], # 缸
['i', 'i', 'ei', 'eih', 'i', 'ei', 'ih'], # 之
['oeyng','oeyng','oyng','oyk', 'oeyng','oyng', 'oeyk'],# 東
['au', 'au', 'au', 'auh' ,'au', 'au', 'auh'], # 郊
['uo', 'uo', 'uo', 'uoh', 'uo', 'uo', 'uoh'], # 過
['e', 'e', 'a', 'ah', 'e', 'a', 'eh'], # 西
['yo', 'yo', 'yo', 'yoh', 'yo', 'yo', 'yoh'], # 橋
['ie', 'ie', 'ie', 'ieh', 'ie', 'ie', 'ieh'], # 鷄
['iang', 'iang','iang', 'iak', 'iang', 'iang', 'iak'], # 聲
['oey', 'oey', 'oy', 'oyh', 'oey', 'oy', 'oeyh'],# 催
['oe', 'oe', 'o', 'oeh', 'oe', 'o', 'oeh'], # 初
['ieng', 'ieng','ieng', 'iek', 'ieng', 'ieng', 'iek'], # 天
['ia', 'ia', 'ia', 'ieh', 'ia', 'ia', 'ieh'], # 奇
['uai', 'uai', 'uai', 'uaih','uai', 'uai', 'uaih'],# 歪
['eu', 'eu', 'au', 'auh', 'eu', 'au', 'euh'] # 溝
]
FINAL_MAPPING_IO_UO = {
24: ['uo', 'uo', 'uo', 'uoh', 'uo', 'uo', 'uoh'],
2: ['uong', 'uong','uong', 'uok', 'uong', 'uong', 'uok']
}
TONE_MAPPING = {
1: "55",
2: "33",
3: "212",
4: "23",
5: "53",
6: "33",
7: "242",
8: "5"
}
ypInitial = INITIAL_MAPPING[f.initial]
toneIndex = FoochowRomanizedSyllable.TONE_MAPPING[f.tone]
if ypInitial not in ['','g','k','h','ng'] and f.final in [2, 24]: #香 / 橋
# 漳泉亂
ypFinal = FINAL_MAPPING_IO_UO[f.final][toneIndex]
else:
ypFinal = FINAL_MAPPING[f.final][toneIndex]
ypTone = TONE_MAPPING[f.tone]
return YngPingSyllable(ypInitial, ypFinal, ypTone)

def hector_to_foochow_romanized(s):
h = HectorSyllable.from_string(s)
return FoochowRomanizedSyllable(h.initial,h.final,h.tone)

def hector_to_foochow_romanized_string(s):
return hector_to_foochow_romanized(s).get_string()

def hector_to_yngping(s):
f = hector_to_foochow_romanized(s)
return foochow_romanized_to_yngping(f).to_typing()

def foochow_romanized_to_yngping_string(s, allow_omit_ingbing=False):
return foochow_romanized_to_yngping(FoochowRomanizedSyllable.from_string(s,allow_omit_ingbing)).to_typing()

def wuyixing_to_yngping(s):
"""從烏衣行轉換爲榕拼方案
"""
wyx = WuyixingSyllable.from_string(s)
INITIAL_MAPPING = {
'p': 'b',
'ph':'p',
't' :'d',
'th':'t',
'ts': 'z',
'tsh': 'c',
'k':'g',
'kh':'k',
}

FINAL_MAPPING = {
# TODO: 榕拼無?
'ieu': 'iu'
}

return YngPingSyllable(
INITIAL_MAPPING[wyx.initial] if wyx.initial in INITIAL_MAPPING.keys() else wyx.initial,
FINAL_MAPPING[wyx.final] if wyx.final in FINAL_MAPPING.keys() else wyx.final,
wyx.tone).to_typing()


def minjiang_to_yngping(s):
"""從閩江學院轉換爲榕拼方案
"""
mj = MinjiangSyllable.from_string(s)

VOWEL_MAPPING = {
'ë': 'oe',
'ü': 'y'
}

final = mj.final
for v in VOWEL_MAPPING.keys():
nv = VOWEL_MAPPING[v]
final = final.replace(v,nv)

return YngPingSyllable(
mj.initial,
final,
mj.tone).to_typing()

107 changes: 107 additions & 0 deletions pyhokchew/models/concurrent/matsu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@

from ...utils import normalise

WYX_CONSONANTS = ['p', 'ph', 'm', 't', 'th', 'n', 'l', 'ts', 'tsh', 's', 'k', 'kh', 'ng', 'h']

WYX_VOWELS = ['a', 'o', 'e', 'oe', 'i', 'u', 'y']

WYX_CODAS = ['ng', 'h', 'k', '']

WYX_INITIALS = WYX_CONSONANTS + ['']


# Tones
# 55
# 53 s
# 33 f
# 212 v
# 242 x
# 23 z
# 5

class WuyixingSyllable:
"""烏衣行馬祖話輸入法的拼音方案
"""

def __init__(self, initial, final, tone):
"""
"""
if initial not in set(WYX_INITIALS):
raise Exception('Unknown initial: %s' % initial)
self.initial = initial
self.final = final
self.tone = tone

def __str__(self):
return 'WuyixingSyllable Initial=%s Final=%s Tone=%s' % (self.initial, self.final, self.tone)

def __repr__(self):
return self.__str__()

@classmethod
def from_string(cls, s):
s = normalise(s).strip().lower()

# 需要先 match 較長的
sorted_initials = sorted(WYX_INITIALS, reverse=True, key=lambda x: len(x))
initial = None
for i in sorted_initials:
if s.startswith(i):
initial = i
s = s[len(i):]
break

if initial is None:
raise Exception('No matching initial')

rime = None
sorted_vowels = sorted(WYX_VOWELS, reverse=True, key=lambda x: len(x))

while True:
found = False
for v in sorted_vowels:
if s.startswith(v):
rime = v if rime is None else rime + v
s = s[len(v):]
found = True
break
if not found:
break

if rime is None:
raise Exception('No matching final')

coda = None

for c in WYX_CODAS:
if s.startswith(c):
coda = c
s = s[len(c):]
break

if coda is None:
raise Exception('No matching final')

# the rest is the tone
tone = None
if s == "":
if coda in ['h', 'k']:
tone = "5"
else:
tone = "55"
elif s == "s":
tone = "53"
elif s == "f":
tone = "33"
elif s == "v":
tone = "212"
elif s == "x":
tone = "242"
elif s == "z":
if coda in ['h', 'k']:
tone = "23"

if tone is None:
raise Exception('No matching tone.')

return WuyixingSyllable(initial, rime+coda, tone)
109 changes: 109 additions & 0 deletions pyhokchew/models/concurrent/minjiang.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
from ...utils import normalise

MJ_CONSONANTS = ['b', 'p', 'm', 'd', 't', 'n', 'l', 'z', 'c', 's', 'g', 'k', 'ng', 'h']

MJ_VOWELS = ['a', 'o', 'e', 'ë', 'i', 'u', 'ü']

MJ_CODAS = ['ng', 'h', 'k', '']

MJ_INITIALS = MJ_CONSONANTS + ['']

TONE_MAPPINGS = {
"1": "55",
"2": "53",
"3": "33",
"4": "212",
"5": "242",
"6": "23",
"7": "5"
}

MJ_TONES = list(TONE_MAPPINGS.keys())

def normalise_mj(s):
# 正規化閩江學院的奇怪字符
s = normalise(s).strip().lower()
s = s.replace('ɑ','a').replace('ê','e').replace('ɡ','g')
return s

# Tones
# 55 1
# 53 2
# 33 3
# 212 4
# 242 5
# 23 6
# 5 7

class MinjiangSyllable:
"""閩江學院的拼音方案
"""

def __init__(self, initial, final, tone):
"""
"""
if initial not in set(MJ_INITIALS):
raise Exception('Unknown initial: %s' % initial)
self.initial = initial
self.final = final
self.tone = tone

def __str__(self):
return 'MinjiangSyllable Initial=%s Final=%s Tone=%s' % (self.initial, self.final, self.tone)

def __repr__(self):
return self.__str__()

@classmethod
def from_string(cls, s):
s = normalise_mj(s)

# 需要先 match 較長的
sorted_initials = sorted(MJ_INITIALS, reverse=True, key=lambda x: len(x))
initial = None
for i in sorted_initials:
if s.startswith(i):
initial = i
s = s[len(i):]
break

if initial is None:
raise Exception('No matching initial')

rime = None
sorted_vowels = sorted(MJ_VOWELS, reverse=True, key=lambda x: len(x))

while True:
found = False
for v in sorted_vowels:
if s.startswith(v):
rime = v if rime is None else rime + v
s = s[len(v):]
found = True
break
if not found:
break

if rime is None:
raise Exception('No matching final')

coda = None

for c in MJ_CODAS:
if s.startswith(c):
coda = c
s = s[len(c):]
break

if coda is None:
raise Exception('No matching final')

# the rest is the tone
tone = None
if s in MJ_TONES:
tone = TONE_MAPPINGS[s]

if tone is None:
raise Exception('No matching tone.')

return MinjiangSyllable(initial, rime+coda, tone)
Loading