Python将维吾尔语从 ULY 到 UEY 的自动转换
前言
上一篇文章介绍了使用PySide6调用OpenAI的Whisper模型进行语音ASR转写,Whisper支持多种语言的语音转写(ASR),但是对于小语种的支持较少,可以根据需要自己去训练模型。
项目中需要用到维吾尔语语音转写功能,正好在huggingface
上找到一个使用 THUYG20基于Whisper训练的维吾尔语ASR模型,可以直接拿来使用。
但是集成到项目中,转写输出来的维吾尔语通常是维吾尔语的拉丁转写(ULY,Uyghur Latin Yëziqi),而很多场景中希望获得维吾尔语阿拉伯脚本(UEY,Uyghur Ereb Yëziqi)的标准写法。本文将系统介绍两种书写风格的差异、常见映射规则、标点处理,并给出可直接使用的 ULY→UEY 转换函数及项目集成示例,然后把识别结果自动规范为标准维文阿拉伯脚本。
ULY 与 UEY 的写法概览
-
ULY(拉丁转写)
- 采用拉丁字母表示维文音系,常见元音:a e i o u ö ü é
- 常见辅音及二字母组合(digraphs):gh、ng、sh、ch、zh 等
- 标点通常是英文逗号 “,” 与句号 “.”
- 方便在不支持阿拉伯字母的系统中输入与检索
-
UEY(阿拉伯脚本)
- 使用阿拉伯字母及维文专用字母(例如 “ئ”、“ۆ”、“ۈ”、“ې”、“ڭ” 等)
- 词首元音通常以“ئ”起始(即所谓“词首隔音符”,类似加上一个“hamza”)
- 标点采用阿拉伯逗号 “،” 与句号 “۔”(也可见混用中文逗号 “,”)
- 显示为右到左(RTL)方向,注意在 UI 中的字体与排版支持
常见差异与映射规则
为实现 ULY→UEY 的转换,通常需要以下规则:
-
元音映射
- a → ا
- e → ە
- i → ى
- o → و
- u → ۋ 或 ئۇ(实际书写中更常见 “ۇ” 表示 /u/ 音,这里我们使用 “ۇ”,并通过规则保持一致)
- ö → ئۆ(这里直接映射为 “ۆ”)
- ü → ئۈ(这里映射为 “ۈ”)
- é → ې
-
辅音与二字母组合(digraphs)
- gh → غ
- ng → ڭ
- sh → ش
- ch → چ
- zh → ژ
- 其它单字母辅音常见映射:b→ب, p→پ, t→ت, j→ج, x→خ, d→د, r→ر, z→ز, s→س, f→ف, q→ق, k→ك, g→گ, h→ھ, y→ي, w→ۋ, l→ل, m→م, n→ن
-
词首元音加“ئ”
- 如果一个“词”(连续的字母序列)以元音开头,则在该词首补上“ئ”,例如 “emun” 转为 “ئىمۇن”(示例,仅为说明效果)
-
保留非字母字符
- 数字、空白、括号、连字符、其它标点等原样保留
-
大小写
- 维文 UEY 不区分大小写。转换时统一按小写处理,保留原字符串中的非字母字符
以上为实用的基础规则,能够覆盖绝大多数普通文本。需要注意的是,维文存在更复杂的形态与正词法约定,真实文本可能需要更丰富的规则或词典级处理。
- 维文 UEY 不区分大小写。转换时统一按小写处理,保留原字符串中的非字母字符
转换实现思路
- 将整段文本按字符遍历,遇到连续的字母序列视为一个“词”
- 对每个词:
- 优先匹配二字母组合(digraphs),例如 gh、ng、sh、ch、zh
- 再逐字映射剩余字符(元音与辅音)
- 如果词首为元音,额外在前面加 “ئ”
- 遇到非字母字符(空格、标点等),则结束当前词、原样输出该字符
- 将所有片段拼接为转换后的 UEY 文本
ULY→UEY 转换函数代码
可以直接在项目中使用下面的 Python 函数。它与当前项目中集成的类方法逻辑一致,只是以独立函数形式呈现,更便于理解与复用。
def convert_uyghur_uly_to_uey(text: str) -> str:"""将维吾尔语的拉丁转写(ULY)转换为阿拉伯文(UEY)。规则:- 优先匹配二字母组合(gh/sh/ch/zh/ng)- 词首元音加“ئ”- 保留数字/标点/空白等非字母字符"""vowels = {'a':'ا','e':'ە','i':'ى','o':'و','u':'ۇ','ö':'ۆ','ü':'ۈ','é':'ې'}digraphs = {'ng':'ڭ','gh':'غ','sh':'ش','ch':'چ','zh':'ژ'}letters = {'b':'ب','p':'پ','t':'ت','j':'ج','x':'خ','d':'د','r':'ر','z':'ز','s':'س','f':'ف','q':'ق','k':'ك','g':'گ','h':'ھ','y':'ي','w':'ۋ','l':'ل','m':'م','n':'ن'}def convert_word(w: str) -> str:if not w:return wlower = w.lower()res = []i = 0# 词首元音加 'ئ'if lower and lower[0] in vowels:res.append('ئ')while i < len(lower):# 二字母优先if i + 1 < len(lower):pair = lower[i:i+2]if pair in digraphs:res.append(digraphs[pair])i += 2continuech = lower[i]if ch in vowels:res.append(vowels[ch])i += 1continueif ch in letters:res.append(letters[ch])i += 1continue# 未知字符原样保留(数字/标点等)res.append(w[i])i += 1return ''.join(res)out = []buf = ''for ch in text:if ch.isalpha() or ch in ['ö','ü','é']:buf += chelse:if buf:out.append(convert_word(buf))buf = ''out.append(ch)if buf:out.append(convert_word(buf))return ''.join(out)
说明:
- 该函数覆盖了常见的字母与二字母组合映射,并处理词首元音 “ئ”
- 对不认识的符号(如数字、波浪线、特殊符号)保持原样
- 如需更严格的正词处理,可在此基础上增加更精细的规则或词典校对
维吾尔语的阿拉伯标点选择(逗号/句号)
识别时还会按语言选择合适的逗号和句号,以匹配维文阿拉伯脚本习惯:
def choose_comma(lang: str, sample: str) -> str:# 维语 '،';中文 ',';否则 ','if lang == "维吾尔语":return '،'# 简单判断是否包含中文字符,以决定使用中文逗号if any('\u4e00' <= ch <= '\u9fff' for ch in sample):return ','return ','def choose_period(lang: str, sample: str) -> str:# 维语 '۔';中文 '。';否则 '.'if lang == "维吾尔语":return '۔'if any('\u4e00' <= ch <= '\u9fff' for ch in sample):return '。'return '.'
为了避免重复标点,我们在实时片段追加时会先检查片段末尾是否已经包含终止/逗号标点(包括 “،” 与 “۔” 等),只有在未包含时才补逗号。最终在转录完成时,再把末尾逗号替换为对应语言句号或补句号。
测试示例与效果对比
以下是一些简化的示例,说明转换效果(仅为示例,实际语料可能更复杂):
- 示例 1
- ULY 输入:
uning kökrek taghqaq béliklirige ya oqa sanjilghan idi
- UEY 输出(示意):
ئۇنىڭ كۆكرەك تاغقاق بېلىكلىرىگە يا ئوقا سانجىلغان ئىدى
- ULY 输入:
- 示例 2
- ULY 输入:
men öyde ish qilimen, lekin bugün charchap qaldim.
- UEY 输出(示意):
مەن ئۆيدە ئىش قىلىمەن، لېكىن بۈگۈن چارچاپ قالدىم۔
- ULY 输入:
- 示例 3(带标点)
- ULY:
bu yaxshi, lekin yene tekshürmek kerek
- UEY:
بۇ ياخشى، لېكىن يەنە تەكشۈرمەک كېرەك
- ULY:
提醒:
1.示例仅用于展示规则映射,不保证每个词都符合最严格的正词法。真实文本中请结合语境与词典进行校正
2.如果你的语料中混用了中文标点或英文标点,转换后也可以选择统一为阿拉伯标点或保留原样