خذ الكلمة الإنجليزية “read”. مكتوبةً، لا تخبرك كيف تُنطَق. فجملتا “I read the book yesterday” و”I read the book every day” تستخدمان الأحرف الخمسة نفسها لصوتين مختلفين — أحدهما يقفّي مع “red”، والآخر مع “reed”. لا يستطيع قارئ شاشة، ولا مساعد صوتي، ولا مربّع بحث ينظر فقط إلى التهجئة أن يصيب هذا. إنه يحتاج إلى التفكير في النطق، لا في النص فقط.
تلك المشكلة الاستدلالية — تحويل الكلمات المكتوبة إلى الأصوات التي تمثّلها — هي ما تحلّه منظومة الصوتيات لدينا. هذا المقال خريطة لكيفية اتّساق أجزائها معًا، من الترميز الخام صعودًا إلى محركات النطق الخاصة بكل لغة والبحث القائم على الصوت.
بعض المصطلحات، مُعرَّفة ببساطة
كلمات قليلة تتكرر عبر المقال:
- الحرف الكتابي (grapheme): رمز مكتوب — حرف، أو تركيبة أحرف مثل “ch”.
- الفونيم (phoneme): وحدة صوتية متمايزة في لغة ما، كصوت “k” في “cat”.
- IPA (الأبجدية الصوتية الدولية): أبجدية معيارية لكتابة الأصوات بدقّة، بمعزل عن تهجئة أي لغة. تُكتَب “Cat” بصيغة
kætفي IPA. - G2P (تحويل الحرف إلى الفونيم): المشكلة العامة لتحويل التهجئة إلى صوت.
- الألوفون (allophone): تحقّق مختلف للفونيم نفسه حسب السياق — الـ”t” في “top” والـ”t” في “stop” هما الفونيم نفسه في الإنجليزية لكن يُنطَقان بشكل مختلف قليلًا.
- التقطيع المقطعي (syllabification): تقسيم كلمة إلى مقاطع، مثل “extraordinário” إلى
ex-tra-or-di-ná-ri-o. - المتشابه الخطي (homograph): كلمتان مكتوبتان بالشكل نفسه لكن بمعنيين مختلفين؛ والمتشابه الخطي غير المتجانس صوتيًا (أو heterophone) هو متشابه خطي يُنطَق بشكل مختلف حسب المعنى المقصود، مثل “read”/“read” أعلاه.
- الصرف (morphology): البنية الداخلية للكلمات — البادئات، والجذور، واللواحق، والتصريفات.
- وسم أجزاء الكلام (POS tagging): تصنيف كل كلمة في جملة بوصفها اسمًا أو فعلًا أو صفة، وهكذا.
المشكلة الجوهرية
التهجئة ترميز فاقد لجزء من الصوت. ثلاثة أمور منفصلة تجعل عكسه صعبًا:
- الغموض. يمكن للأحرف نفسها أن ترتبط بأصوات مختلفة حسب المعنى، أو القواعد، أو مجرد شذوذ (“read” أعلاه؛ الإنجليزية مليئة بهذا).
- اللهجة. الكلمة نفسها، في اللغة نفسها، تُنطَق بشكل مختلف حسب مصدر المتحدث. تتشارك البرتغالية الأوروبية والبرازيلية التهجئة لكن لا الحركات.
- التغطية. لا تملك معظم لغات العالم أي معجم نطقي احترافي منظّم أصلًا. نظام G2P يعمل فقط عبر جدول بحث هو نظام يعمل فقط لحفنة من اللغات.
أي محاولة جادة لتحويل النص إلى كلام، أو بيانات تدريب للتعرّف على الكلام، أو بحث واعٍ صوتيًا يجب أن تتعامل مع الأمور الثلاثة جميعًا.
لماذا المنظومة طبقات
تقسّم المنظومة المشكلة إلى طبقات لا تحتاج إلى معرفة بعضها البعض:
- الترميز — التحويل بين الأبجديات الصوتية والكتابات. لا علاقة لهذا بصوتيات أي لغة معيّنة؛ إنه ترجمة رموز.
- الصوتيات — ربط التهجئة بـ IPA للغة معيّنة، باستخدام مواصفة لنظامها الصوتي.
- معالجة الاستثناءات الخاصة باللغة — الكلمات الشاذة، ونزوات اللهجة، والمتشابهات الخطية، والبنية الصرفية التي لا يستطيع محرك عام استنتاجها من قواعد التهجئة وحدها.
الإبقاء على هذه منفصلة قرار تصميمي، لا مصادفة، وله مردود مباشر: إضافة لغة جديدة تعني كتابة مواصفة (بيانات تصف نظامها الصوتي)، لا برنامجًا جديدًا. المحرك الذي يستهلك المواصفة، وبحث الشبكة، والمُقطِّع، ومقاييس المسافة — لا شيء من ذلك يُعاد كتابته. طبقة الترميز أسفلها مشتركة بين كل لغة، بما فيها لغات لم يسمع بها محرك الصوتيات قط.
طبقة الترميز: scriptconv
scriptconv نواة بلا اعتماديات للترميز الصوتي ومعالجة الكتابات: كشف الكتابة وفق ISO-15924، وتحويلات IPA من وإلى ARPABET وX-SAMPA وLexique وKirshenbaum وCotovía وترميز RFE، وترجمة Buckwalter الصوتية للعربية، وتفكيك Hangul إلى jamo، ومعالجة الكانا. لا شيء من هذا يحتاج إلى معرفة اللغة التي تنتمي إليها كلمة ما — تتحوّل سلسلة فونيمات بصيغة IPA إلى ARPABET بالطريقة نفسها بصرف النظر عن اللغة المصدر:
>>> import scriptconv as s
>>> s.ipa_to_arpa("kæt")
'K AE T'
>>> s.ipa_to_xsampa("kæt")
'k{t'
كل طبقة فوق هذه يمكنها أن تفترض أن تحويل الترميز محلول أصلًا.
المحرك: orthography2ipa
orthography2ipa هو المحرك العابر للغات. يأخذ مواصفة لغة — وصفًا تصريحيًا لقواعد تحويل الحرف إلى الفونيم لتلك اللغة — وقطعة نص، وينتج IPA. عند كتابة هذه السطور، يشحن مواصفات تغطي 820 لغة (تعيد available_codes() على الحزمة المُثبَّتة قائمة بهذا الطول؛ اعتبر الرقم الدقيق هدفًا متحركًا، إذ تُضاف مواصفات مع الوقت).
>>> import orthography2ipa as o
>>> len(o.available_codes())
820
المحرك نفسه لا يحتوي شيفرة خاصة بأي لغة. اللغة الجديدة هي ملف مواصفة جديد، يُتحقَّق منه وفق المخطط نفسه الذي يُتحقَّق به من كل مواصفة أخرى.
الشبكة: مرشّحون مُرتَّبون، لا تخمين واحد
بالنظر إلى مشكلة الغموض أعلاه، فإن الالتزام بمخرج واحد لكل كلمة غالبًا خطأ. ينتج orthography2ipa بدلًا من ذلك شبكة (lattice) — مجموعة من النطق المرشّح المُرتَّب — ويترك للطبقات الأعلى تضييقها باستخدام سياق لا يملكه المحرك نفسه (المعنى، جزء الكلام، مدخل معجمي).
خذ “read” مجددًا:
>>> from orthography2ipa import G2P
>>> g = G2P("en")
>>> g.transcribe("read")
'ɹiːd'
>>> g.candidates("read")
[IPAPath('ɹiːd', score=0.0), IPAPath('ɹɛd', score=1.0)]
دون سياق إضافي، يعيد المحرك أفضل تخمين له (زمن مضارع، تكلفة أقل) لكنه يبقي البديل (زمن ماضٍ) على الشبكة مع تكلفته المرفقة. يستطيع مكوّن أسفل المصب يعرف أن الجملة بصيغة الماضي أن يختار المرشّح الثاني بدلًا من الأول. هذه هي الفكرة نفسها المستخدَمة، على نطاق أوسع، من قِبَل bifonia (أدناه) للمتشابهات الخطية البرتغالية غير المتجانسة صوتيًا: شبكة عامة الغرض توفّر المرشحين، وطبقة أضيق وأفضل اطّلاعًا تختار من بينهم.
اللهجات مواطنون من الدرجة الأولى
يستطيع متحدّثان بلغة واحدة نطق الجملة نفسها بشكل مختلف، ومنظومة صوتيات تعامل “البرتغالية” بوصفها نظامًا صوتيًا ثابتًا واحدًا ستخطئ في كل اللهجات إلا واحدة. يكشف orthography2ipa عن معالجة اللهجات مباشرةً — تسرد available_profiles() على الحزمة المُثبَّتة ملفات لهجات مثل lisbon وporto وestremenho وgalician وغيرها — ويقوم tugaphone، الواجهة الأمامية البرتغالية المبنية عليه، بتصويت الجملة نفسها عبر التنوعات اللوسوفونية. إليك جملة واحدة عبر كل اللهجات الخمس المدعومة:
| اللهجة | المخرج |
|---|---|
| pt-PT (البرتغال) | ˈbõ ˈdiɐ ˈkomu eˈʃta vɔˈse |
| pt-BR (البرازيل) | ˈbõ ˈdʒiɐ ˈkɔ̃mʊ eˈsta voˈse |
| pt-AO (أنغولا) | ˈbõ ˈdiɐ ˈkomʊ eˈsta vɔˈse |
| pt-MZ (موزمبيق) | ˈbõ ˈdiɐ ˈkomu eˈsta vɔˈse |
| pt-TL (تيمور الشرقية) | ˈbõ ˈdiə ˈkoɔmʊ eˈsta vɔˈse |
(“Bom dia, como está você?” — “صباح الخير، كيف حالك؟”) يبقى هيكل الصوامت قابلًا للتمييز عبر الخمسة جميعًا، لكن علامتين معروفتين تفصلهما فورًا. ففي “dia”، تحوّل البرتغالية البرازيلية الـd قبل i إلى dʒ، الصوت في بداية الإنجليزية “jam” — بينما تبقي البقية على d عادية. وفي “está”، تنطق البرتغالية الأوروبية الـs في نهاية المقطع كـʃ، صوت “sh” في “shoe”، بينما يبقي كل تنوّع آخر على s. المعجم النطقي المبني على قواعد لهجة واحدة يخطئ في كلتا العلامتين لمستمع أي لهجة أخرى.
يفعل euskaphone الشيء نفسه للهجات الباسكية، مبنيًا مباشرةً على شبكة orthography2ipa بدلًا من محرك منفصل:
>>> from euskaphone import EuskaPhonemizer
>>> EuskaPhonemizer().phonemize_sentence("Kaixo, zer moduz zaude?")
'kai̯ʃo s̻er modus̻ s̻au̯de'
الواجهات الأمامية الخاصة باللغة
فوق المحرك المشترك تقبع واجهات أمامية تضيف ما لا تستطيع مواصفة عامة إضافته: الكلمات الشاذة، ومعجم منتقى، والسندهي (تغيّرات صوتية عند حدود الكلمات)، وتجاوزات خاصة باللهجة.
-
tugaphone — البرتغالية، عبر pt-PT وpt-BR وpt-AO وpt-MZ وpt-TL، تجمع بين معجم منتقى ولجوء قائم على القواعد (مبيَّن أعلاه).
-
euskaphone — الباسكية، واعية باللهجة، مبنية على الشبكة نفسها (مبيَّن أعلاه).
-
mwl_phonemizer — الميرانديزية، لغة أستورليونية من تيرّا دي ميراندا، البرتغال، بسندهي بين الكلمات وألوفونات ونبر:
>>> from mwl_phonemizer import phonemize >>> phonemize("Falo la lhéngua mirandesa.") 'ˈfalu lɐ ˈʎɛŋɡwa miɾɐˈndez̺ɐ.' -
g2p_barranquenho — أول G2P مفتوح للبرانكينهو، لغة الاتصال الإيبيرية الرومانسية في بارانكوس، على الحدود البرتغالية الإسبانية. انظر نقدّم أول محوّل صوتي للبرانكينهو لمعرفة كيف اشتُقّت قواعده من الاتفاقية الإملائية الخاصة بالبلدية.
-
arbtok — العربية، مبنية على شبكة orthography2ipa، تضيف تشكيلًا واعيًا باللهجة وتغطي الفصحى الحديثة والفصحى التراثية وعددًا من التنويعات الإقليمية. عادةً ما تحذف الكتابة العربية علامات الحركات القصيرة التي يحتاجها المُصوِّت، لذا فإن مهمة arbtok الرئيسية هي استرجاعها قبل تسليم النتيجة إلى المحرك المشترك. يصونها شخص لا يتحدث العربية كلغة أم، لذا عامله كعمل قيد التطوير النشط لا كمرجع منجز راجعه ناطقون أصليون — مفيد، لكن هذا هو المكان الذي ينبغي أن تراجع فيه المخرجات مع ناطق أصلي قبل شحنها في أي شيء يواجه المستخدم.
كل واحدة من هذه الواجهات الأمامية طبقة رفيعة من المنطق الخاص باللغة فوق محرك الشبكة المشترك نفسه وطبقة الترميز المشتركة نفسها أسفله. لا واحدة منها تعيد تنفيذ تحويل IPA أو بحث الشبكة.
أدوات برتغالية مساندة
تملك البرتغالية أعمق منظومة، لأن النطق البرتغالي يعتمد على أكثر من قواعد التهجئة: يعتمد على بنية المقطع، وصنف الكلمة، وأحيانًا على المعنى المجرّد.
-
silabificador يقسّم الكلمات إلى مقاطع باستخدام قواعد مصنوعة يدويًا:
>>> from silabificador import syllabify >>> syllabify("extraordinário") ['ex', 'tra', 'or', 'di', 'ná', 'ri', 'o'] -
tugalex هو المعجم خلف tugaphone: نصوص IPA، وبيانات مقطعية، وقواعد إملائية لكلمات حقيقية، بحيث لا يُعاد اشتقاق المفردات الشائعة والشاذة من التهجئة في كل مرة.
-
tugatagger يغلّف عدة واجهات خلفية لوسم أجزاء الكلام (spaCy وStanza ووسم بأسلوب Brill ولجوء استدلالي بلا اعتماديات) خلف واجهة واحدة، بحيث يمكن لأدوات أخرى أن تسأل “ما جزء الكلام لهذه الكلمة” دون الالتزام بواجهة خلفية واحدة محددة.
-
tugamorph محلّل صرفي قائم على القواعد: يقسّم الكلمة إلى بادئة، وجذر، ولاحقة، وتصريف، وأداة اتصال (clitic)، باستخدام مكتبة بايثون القياسية فقط، ويُحسَّن اختياريًا بواسطة silabificador وtugatagger.
-
bifonia يحلّ المتشابهات الخطية غير المتجانسة صوتيًا في البرتغالية الأوروبية — كلمات مثل “sede” (عطش،
ˈsedɨ، مقابل مقر،ˈsɛdɨ) حيث يعتمد النطق الصحيح على المعنى، لا القواعد. انظر النطق الصحيح: إزالة اللبس عن المتشابهات الخطية البرتغالية غير المتجانسة صوتيًا من أجل TTS لمعرفة كيف بُني وقُيِّم. هذه هي الحالة الملموسة خلف فكرة الشبكة أعلاه: يستطيع orthography2ipa توفير قراءتين مرشّحتين لـ”sede”، لكن طبقة واعية بالمعنى مثل bifonia فقط تستطيع الاختيار بينهما.
لمزيد حول كيف يعمل silabificador وtugaphone معًا يوميًا، انظر معالجة اللغة الطبيعية الكلاسيكية للبرتغالية: التقطيع المقطعي وتحويل الحروف إلى فونيمات، وللمحرك الأوسع أسفل كل هذا، تحويل الحروف الكتابية إلى IPA لـ 820 لغة.
البحث القائم على الصوت: phonematcher
كل ما سبق يحوّل النص إلى صوت. يعمل phonematcher مع تمثيلات الصوت نفسها: يحسب المسافة الصوتية بين رموز IPA ويجري بحثًا ضبابيًا فوق قوائم كلمات استنادًا إلى كيف تُنطَق الكلمات لا كيف تُكتَب.
>>> from phonematcher.distance import phonetic_distance
>>> phonetic_distance('b', 'p') # voiced vs. voiceless bilabial stop — very similar
0.043478260869565216
>>> phonetic_distance('p', 'k') # bilabial vs. velar stop — less similar
0.34782608695652173
>>> phonetic_distance('a', 'k') # vowel vs. consonant — maximally different
1.0
مقياس المسافة هذا مفيد في موقفين ملموسين: البحث في فهرس كلمات أو أسماء بحسب كيف يُنطَق شيء ما لا تهجئته الدقيقة (مفيد لواجهات صوتية متسامحة مع الأخطاء الإملائية ولمطابقة الكلمات المستعارة عبر أنظمة كتابة مختلفة)، ومقارنة مدى قرب لهجتين متقاربتين صوتيًا — نوع المقارنة نفسه الذي يجريه جدول اللهجات أعلاه بالعين، لكن محسوبًا لا مُقدَّرًا بصريًا. phonematcher ليس على PyPI؛ يُثبَّت من المصدر (pip install -e . مقابل نسخة GitHub، إضافةً إلى rapidfuzz).
حدود صادقة
التغطية عبر 820 مواصفة لغة متفاوتة بطبيعة البناء: اللغات ذات الأدبيات الصوتية الراسخة والمعجم تحصل على مخرجات أفضل من اللغات ذات المواصفة الرقيقة المُستنتَجة أساسًا من اصطلاحات إملائية عامة. الجودة هي الأفضل باستمرار حيث يوجد معجم منتقى — البرتغالية، المدعومة بـ tugalex، هي أقوى حالة في المنظومة؛ أما اللغات المعتمِدة فقط على قواعد المواصفة دون معجم فستُسيء معالجة المفردات الشاذة والمستعارة.
بعض المكوّنات ليست صراحةً مراجع مُنجَزة وراجعها ناطقون أصليون: يصون arbtok شخص لا يتحدث العربية كلغة أم وينبغي التحقق منه بحكم ناطق أصلي قبل استخدامه في أي شيء يواجه المستخدم. الواجهات الأمامية المبنية على مواصفات رقيقة ترث تلك الرقّة — فالواجهة الأمامية بجودة المواصفة والمعجم أسفلها فقط.
لماذا يهم هذا إن كانت لغتك بلا أدوات صوتية
لا تملك معظم لغات العالم صوت TTS تجاريًا، ولا نموذج STT تجاريًا، ولا معجم نطقي مُصان احترافيًا. التصميم الطبقي أعلاه يعني أن تلك الفجوة لا تحتاج بناء محرك صوتيات من الصفر: تحتاج كتابة مواصفة لنظام صوت اللغة المستهدفة، وحيث أمكن، معجمًا لكلماتها الشاذة. محرك الشبكة، وتحويلات الترميز، وأدوات البحث موجودة أصلًا. إن كانت لغتك، أو لهجتك، أو منتجك يحتاج دعم نطق غير موجود بعد، فهذا هو نوع العمل الذي نتولاه — انظر خدماتنا أو تواصل معنا.