Module:bg-pronunciation
Appearance
- The following documentation is located at Module:bg-pronunciation/documentation. [edit] Categories were auto-generated by Module:module categorization. [edit]
- Useful links: subpage list • links • transclusions • testcases • sandbox
This module automatically converts Bulgarian orthography to a phonetic transcription in the International Phonetic Alphabet. It also generates hyphenations and syllabifications.
Testcases
All tests passed. (refresh)
Text | Expected | Actual | |
---|---|---|---|
![]() | височина (visočina) | ви‧со‧чи‧на | ви‧со‧чи‧на |
![]() | сестра (sestra) | сес‧тра | сес‧тра |
![]() | пленник (plennik) | плен‧ник | плен‧ник |
![]() | преодолея (preodoleja) | пре‧одо‧лея | пре‧одо‧лея |
![]() | маоизъм (maoizǎm) | мао‧изъм | мао‧изъм |
![]() | майка (majka) | май‧ка | май‧ка |
![]() | айс.берг (ajs.berg) | айс‧берг | айс‧берг |
![]() | майор (major) | ма‧йор | ма‧йор |
![]() | фризьор (frizjor) | фри‧зьор | фри‧зьор |
![]() | суджук (sudžuk) | су‧джук | су‧джук |
![]() | над.живея (nad.živeja) | над‧жи‧вея | над‧жи‧вея |
![]() | сестра (sestra) | сес‧тра | сес‧тра |
![]() | потури (poturi) | по‧ту‧ри | по‧ту‧ри |
![]() | сланина (slanina) | сла‧ни‧на | сла‧ни‧на |
![]() | пража (praža) | пра‧жа | пра‧жа |
![]() | спринцовка (sprincovka) | сприн‧цов‧ка | сприн‧цов‧ка |
![]() | пържа (pǎrža) | пър‧жа | пър‧жа |
![]() | яркост (jarkost) | яр‧кост | яр‧кост |
![]() | рало (ralo) | ра‧ло | ра‧ло |
![]() | белило (belilo) | бе‧ли‧ло | бе‧ли‧ло |
![]() | шевица (ševica) | ше‧ви‧ца | ше‧ви‧ца |
![]() | доило (doilo) | до‧ило | до‧ило |
![]() | начало (načalo) | на‧ча‧ло | на‧ча‧ло |
![]() | хитрост (hitrost) | хит‧рост | хит‧рост |
![]() | хитър (hitǎr) | хи‧тър | хи‧тър |
![]() | шевица (ševica) | ше‧ви‧ца | ше‧ви‧ца |
![]() | вдлъбна (vdlǎbna) | вдлъб‧на | вдлъб‧на |
![]() | размахам (razmaham) | раз‧ма‧хам | раз‧ма‧хам |
![]() | укор (ukor) | укор | укор |
![]() | упорит (uporit) | упо‧рит | упо‧рит |
![]() | осем (osem) | осем | осем |
![]() | оценка (ocenka) | оцен‧ка | оцен‧ка |
![]() | лея (leja) | лея | лея |
![]() | аз (az) | аз | аз |
![]() | тя (tja) | тя | тя |
![]() | е (e) | е | е |
![]() | мен (men) | мен | мен |
![]() | страст (strast) | страст | страст |
![]() | пръст (prǎst) | пръст | пръст |
![]() | шофьор (šofjor) | шо‧фьор | шо‧фьор |
![]() | фотьойл (fotjojl) | фо‧тьойл | фо‧тьойл |
![]() | бельо (beljo) | бе‧льо | бе‧льо |
![]() | шедьовър (šedjovǎr) | ше‧дьо‧вър | ше‧дьо‧вър |
![]() | мениджър (menidžǎr) | ме‧ни‧джър | ме‧ни‧джър |
![]() | джудже (džudže) | джу‧дже | джу‧дже |
![]() | жар-птица (žar-ptica) | жар-пти‧ца | жар-пти‧ца |
![]() | морално-нравствен (moralno-nravstven) | мо‧рал‧но-нрав‧ствен | мо‧рал‧но-нрав‧ствен |
![]() | кандидат-студент (kandidat-student) | кан‧ди‧дат-сту‧дент | кан‧ди‧дат-сту‧дент |
![]() | министър-председател (ministǎr-predsedatel) | ми‧нис‧тър-пред‧се‧да‧тел | ми‧нис‧тър-пред‧се‧да‧тел |
![]() | член-кореспондент (člen-korespondent) | член-ко‧рес‧пон‧дент | член-ко‧рес‧пон‧дент |
![]() | бизнес администрация (biznes administracija) | биз‧нес ад‧ми‧нис‧тра‧ция | биз‧нес ад‧ми‧нис‧тра‧ция |
![]() | екшън герой (ekšǎn geroj) | ек‧шън ге‧рой | ек‧шън ге‧рой |
![]() | тенис корт (tenis kort) | те‧нис корт | те‧нис корт |
![]() | заместник министър-председател (zamestnik ministǎr-predsedatel) | за‧мес‧тник ми‧нис‧тър-пред‧се‧да‧тел | за‧мес‧тник ми‧нис‧тър-пред‧се‧да‧тел |
![]() | заместник началник-управление (zamestnik načalnik-upravlenie) | за‧мес‧тник на‧чал‧ник-уп‧рав‧ле‧ние | за‧мес‧тник на‧чал‧ник-уп‧рав‧ле‧ние |
![]() | SIM карта (SIM karta) | SIM кар‧та | SIM кар‧та |
![]() | VIP зона (VIP zona) | VIP зо‧на | VIP зо‧на |
Text | Expected | Actual | |
---|---|---|---|
![]() | къ́ща (kǎ́šta) | ˈkɤʃtɐ | ˈkɤʃtɐ |
![]() | сгъстя́ се (sgǎstjá se), endschwa=true | zɡɐˈstʲɤ̟ sɛ | zɡɐˈstʲɤ̟ sɛ |
![]() | сгъстя́ се (sgǎstjá se) (respelled сгъстя̣́ се) | zɡɐˈstʲɤ̟ sɛ | zɡɐˈstʲɤ̟ sɛ |
![]() | а̀бдики́ращ (àbdikírašt) | ˌabdiˈkirɐʃt | ˌabdiˈkirɐʃt |
![]() | безшу́мен (bezšúmen) | bɛʃˈʃu̟mɛn | bɛʃˈʃu̟mɛn |
![]() | щастли́в (štastlív) | ʃtɐˈslif | ʃtɐˈslif |
![]() | народността́ (narodnosttá) | nɐrodnoˈsta | nɐrodnoˈsta |
![]() | я (ja) | ja̟ | ja̟ |
![]() | юг (jug) | ju̟k | ju̟k |
![]() | яйце́ (jajcé) | jɐjˈt͡sɛ | jɐjˈt͡sɛ |
![]() | учи́лище (učílište) | oˈt͡ʃiliʃtɛ | oˈt͡ʃiliʃtɛ |
![]() | чорбаджи́я (čorbadžíja) | t͡ʃo̟rbɐˈdʒijɐ | t͡ʃo̟rbɐˈdʒijɐ |
![]() | уби́йца (ubíjca) | oˈbijt͡sɐ | oˈbijt͡sɐ |
![]() | безбра́чие (bezbráčie) | bɛzˈbrat͡ʃiɛ | bɛzˈbrat͡ʃiɛ |
![]() | измра́ (izmrá) (respelled из.мра́) | izˈmra | izˈmra |
![]() | сала́та (saláta) | sɐˈɫatɐ | sɐˈɫatɐ |
![]() | шега́ (šegá) | ʃɛˈɡa | ʃɛˈɡa |
![]() | жена́ (žená) | ʒɛˈna | ʒɛˈna |
![]() | инти́мен (intímen) | inˈtimɛn | inˈtimɛn |
![]() | посо́лство (posólstvo) | poˈsɔɫstvo | poˈsɔɫstvo |
![]() | ъ́гъл (ǎ́gǎl) | ˈɤɡɐɫ | ˈɤɡɐɫ |
![]() | усу́квам (usúkvam) | oˈsukvɐm | oˈsukvɐm |
![]() | ле́ща (léšta) | ˈlɛʃtɐ | ˈlɛʃtɐ |
![]() | липа́ (lipá) | liˈpa | liˈpa |
![]() | океа́н (okeán) | okɛˈan | okɛˈan |
![]() | меки́ца (mekíca) | mɛˈkit͡sɐ | mɛˈkit͡sɐ |
![]() | ла́гер (láger) | ˈɫaɡɛr | ˈɫaɡɛr |
![]() | маги́я (magíja) | mɐˈɡijɐ | mɐˈɡijɐ |
![]() | хем (hem) | xɛm | xɛm |
![]() | химн (himn) | ximn | ximn |
![]() | тулу́п (tulúp) | toˈɫup | toˈɫup |
![]() | жа̀р-пти́ца (žàr-ptíca) | ˌʒa̟r-pˈtit͡sɐ | ˌʒa̟r-pˈtit͡sɐ |
![]() | в о́фис (v ófis) | f ˈɔfis | f ˈɔfis |
![]() | във Фра́нция (vǎv Fráncija) | vɐf ˈfrant͡sijɐ | vɐf ˈfrant͡sijɐ |
![]() | ня́колко (njákolko) | ˈnʲa̟koɫko | ˈnʲa̟koɫko |
![]() | в Япо́ния (v Japónija) | f jɐˈpɔnijɐ | f jɐˈpɔnijɐ |
![]() | автоплу́г (avtoplúg) | ɐftoˈpɫuk | ɐftoˈpɫuk |
![]() | уе́бса́йт (uébsájt) (respelled ўе́бса́йт) | ˈwɛpˈsajt | ˈwɛpˈsajt |
![]() | уе́лски (uélski) (respelled ўе́лски) | ˈwɛɫski | ˈwɛɫski |
![]() | уе́стърн (uéstǎrn) (respelled ўе́стърн) | ˈwɛstɐrn | ˈwɛstɐrn |
![]() | О́уен (Óuen) (respelled О́ўен) | ˈɔwɛn | ˈɔwɛn |
![]() | но́ухау (nóuhau) (respelled но́ўхаў) | ˈnɔwxɐw | ˈnɔwxɐw |
![]() | Джо́узеф (Džóuzef) (respelled Джо́ўзеф) | ˈdʒɔwzɛf | ˈdʒɔwzɛf |
![]() | бо́улинг (bóuling) (respelled бо́ўлинг) | ˈbɔwliŋk | ˈbɔwliŋk |
![]() | даунло́уд (daunlóud) (respelled даўнло́ўд) | dɐwnˈɫɔwt | dɐwnˈɫɔwt |
![]() | уи́ски (uíski) (respelled ўи́ски) | ˈwiski | ˈwiski |
![]() | уи́кенд (uíkend) (respelled ўи́кенд) | ˈwikɛnt | ˈwikɛnt |
![]() | Уо́руик (Uóruik) (respelled Ўо́рўик) | ˈwɔrwik | ˈwɔrwik |
![]() | Хе́лоуин (Hélouin) (respelled Хе́лоўин) | ˈxɛɫowin | ˈxɛɫowin |
Text | Expected | Actual | |
---|---|---|---|
![]() | а (a) | а | а |
![]() | в (v) | в | в |
![]() | е (e) | е | е |
![]() | и (i) | и | и |
![]() | ѝ (ì) | ѝ | ѝ |
![]() | о (o) | о | о |
![]() | с (s) | с | с |
![]() | у (u) | у | у |
![]() | аз (az) | аз | аз |
![]() | ти (ti) | ти | ти |
![]() | той (toj) | той | той |
![]() | тя (tja) | тя | тя |
![]() | във (vǎv) | във | във |
![]() | със (sǎs) | със | със |
![]() | принц (princ) | принц | принц |
![]() | спринт (sprint) | спринт | спринт |
![]() | глист (glist) | глист | глист |
![]() | скункс (skunks) | скункс | скункс |
![]() | ами (ami) | а‧ми | а‧ми |
![]() | ала (ala) | а‧ла | а‧ла |
![]() | ако (ako) | а‧ко | а‧ко |
![]() | уви (uvi) | у‧ви | у‧ви |
![]() | или (ili) | и‧ли | и‧ли |
![]() | саламура (salamura) | са‧ла‧му‧ра | са‧ла‧му‧ра |
![]() | барабан (baraban) | ба‧ра‧бан | ба‧ра‧бан |
![]() | сполука (spoluka) | спо‧лу‧ка | спо‧лу‧ка |
![]() | щавя (štavja) | ща‧вя | ща‧вя |
![]() | стрина (strina) | стри‧на | стри‧на |
![]() | когато (kogato) | ко‧га‧то | ко‧га‧то |
![]() | старицата (staricata) | ста‧ри‧ца‧та | ста‧ри‧ца‧та |
![]() | получените (polučenite) | по‧лу‧че‧ни‧те | по‧лу‧че‧ни‧те |
![]() | подобаващите (podobavaštite) | по‧до‧ба‧ва‧щи‧те | по‧до‧ба‧ва‧щи‧те |
![]() | обучаващите (obučavaštite) | о‧бу‧ча‧ва‧щи‧те | о‧бу‧ча‧ва‧щи‧те |
![]() | джудже (džudže) | джу‧дже | джу‧дже |
![]() | суджук (sudžuk) | су‧джук | су‧джук |
![]() | дамаджана (damadžana) | да‧ма‧джа‧на | да‧ма‧джа‧на |
![]() | джаджите (džadžite) | джа‧джи‧те | джа‧джи‧те |
![]() | койот (kojot) | ко‧йот | ко‧йот |
![]() | майонеза (majoneza) | ма‧йо‧не‧за | ма‧йо‧не‧за |
![]() | пейоративен (pejorativen) | пе‧йо‧ра‧ти‧вен | пе‧йо‧ра‧ти‧вен |
![]() | майор (major) | ма‧йор | ма‧йор |
![]() | безименен (bezimenen) | бе‧зи‧ме‧нен | бе‧зи‧ме‧нен |
![]() | изопачавам (izopačavam) | и‧зо‧па‧ча‧вам | и‧зо‧па‧ча‧вам |
![]() | отивам (otivam) | о‧ти‧вам | о‧ти‧вам |
![]() | разоран (razoran) | ра‧зо‧ран | ра‧зо‧ран |
![]() | бульон (buljon) | бу‧льон | бу‧льон |
![]() | фризьор (frizjor) | фри‧зьор | фри‧зьор |
![]() | шедьовър (šedjovǎr) | ше‧дьо‧вър | ше‧дьо‧вър |
![]() | гьозум (gjozum) | гьо‧зум | гьо‧зум |
![]() | ликьор (likjor) | ли‧кьор | ли‧кьор |
![]() | воал (voal) | во‧ал | во‧ал |
![]() | маоизъм (maoizǎm) | ма‧о‧и‧зъм | ма‧о‧и‧зъм |
![]() | феерия (feerija) | фе‧е‧ри‧я | фе‧е‧ри‧я |
![]() | воайор (voajor) | во‧а‧йор | во‧а‧йор |
![]() | миокард (miokard) | ми‧о‧кард | ми‧о‧кард |
![]() | кьопоолу (kjopoolu) | кьо‧по‧о‧лу | кьо‧по‧о‧лу |
![]() | аятолах (ajatolah) | а‧я‧то‧лах | а‧я‧то‧лах |
![]() | авария (avarija) | а‧ва‧ри‧я | а‧ва‧ри‧я |
![]() | позиции (pozicii) | по‧зи‧ци‧и | по‧зи‧ци‧и |
![]() | хазяи (hazjai) | ха‧зя‧и | ха‧зя‧и |
![]() | дерибеи (deribei) | де‧ри‧бе‧и | де‧ри‧бе‧и |
![]() | преодолея (preodoleja) | пре‧о‧до‧ле‧я | пре‧о‧до‧ле‧я |
![]() | нащрек (naštrek) | на‧щрек | на‧щрек |
![]() | поощрявам (pooštrjavam) | по‧о‧щря‧вам | по‧о‧щря‧вам |
![]() | защриховам (zaštrihovam) | за‧щри‧хо‧вам | за‧щри‧хо‧вам |
![]() | поощрителен (pooštritelen) | по‧о‧щри‧те‧лен | по‧о‧щри‧те‧лен |
![]() | изщракване (izštrakvane) | из‧щрак‧ва‧не | из‧щрак‧ва‧не |
![]() | Вайерщрас (Vajerštras) | Ва‧йер‧щрас | Ва‧йер‧щрас |
![]() | Кьонигщрасе (Kjonigštrase) | Кьо‧ниг‧щра‧се | Кьо‧ниг‧щра‧се |
![]() | общност (obštnost) | общ‧ност | общ‧ност |
![]() | всъщност (vsǎštnost) | всъщ‧ност | всъщ‧ност |
![]() | помощник (pomoštnik) | по‧мощ‧ник | по‧мощ‧ник |
![]() | чорапогащник (čorapogaštnik) | чо‧ра‧по‧гащ‧ник | чо‧ра‧по‧гащ‧ник |
![]() | нощница (noštnica) | нощ‧ни‧ца | нощ‧ни‧ца |
![]() | чудовищност (čudovištnost) | чу‧до‧вищ‧ност | чу‧до‧вищ‧ност |
![]() | немощливо (nemoštlivo) | не‧мощ‧ли‧во | не‧мощ‧ли‧во |
![]() | съобщавам (sǎobštavam) | съ‧об‧ща‧вам | съ‧об‧ща‧вам |
![]() | въобще (vǎobšte) | въ‧об‧ще | въ‧об‧ще |
![]() | манджа (mandža) | ман‧джа | ман‧джа |
![]() | калайджия (kalajdžija) | ка‧лай‧джи‧я | ка‧лай‧джи‧я |
![]() | авджия (avdžija) | ав‧джи‧я | ав‧джи‧я |
![]() | изджвака (izdžvaka) | из‧джва‧ка | из‧джва‧ка |
![]() | пленник (plennik) | плен‧ник | плен‧ник |
![]() | майка (majka) | май‧ка | май‧ка |
![]() | профашистки (profašistki) | про‧фа‧шист‧ки | про‧фа‧шист‧ки |
![]() | гледка (gledka) | глед‧ка | глед‧ка |
![]() | крачка (kračka) | крач‧ка | крач‧ка |
![]() | цедка (cedka) | цед‧ка | цед‧ка |
![]() | звезда (zvezda) | звез‧да | звез‧да |
![]() | спринцовка (sprincovka) | сприн‧цов‧ка | сприн‧цов‧ка |
![]() | бързо (bǎrzo) | бър‧зо | бър‧зо |
![]() | малко (malko) | мал‧ко | мал‧ко |
![]() | после (posle) | по‧сле | по‧сле |
![]() | партия (partija) | пар‧ти‧я | пар‧ти‧я |
![]() | гланцов (glancov) | глан‧цов | глан‧цов |
![]() | пепелник (pepelnik) | пе‧пел‧ник | пе‧пел‧ник |
![]() | пилци (pilci) | пил‧ци | пил‧ци |
![]() | аншоа (anšoa) | ан‧шо‧а | ан‧шо‧а |
![]() | ядро (jadro) | я‧дро | я‧дро |
![]() | ироничност (ironičnost) | и‧ро‧нич‧ност | и‧ро‧нич‧ност |
![]() | профилактична (profilaktična) | про‧фи‧лак‧тич‧на | про‧фи‧лак‧тич‧на |
![]() | боцна (bocna) | боц‧на | боц‧на |
![]() | спецна (specna) | спец‧на | спец‧на |
![]() | бичме (bičme) | бич‧ме | бич‧ме |
![]() | кръчма (krǎčma) | кръч‧ма | кръч‧ма |
![]() | боцман (bocman) | боц‧ман | боц‧ман |
![]() | сачма (sačma) | сач‧ма | сач‧ма |
![]() | Ричмънд (Ričmǎnd) | Рич‧мънд | Рич‧мънд |
![]() | мичман (mičman) | мич‧ман | мич‧ман |
![]() | разчеша (razčeša) | раз‧че‧ша | раз‧че‧ша |
![]() | пецма (pecma) | пец‧ма | пец‧ма |
![]() | сестра (sestra) | се‧стра | се‧стра |
![]() | царство (carstvo) | цар‧ство | цар‧ство |
![]() | нравствен (nravstven) | нрав‧ствен | нрав‧ствен |
![]() | мандраджия (mandradžija) | ман‧дра‧джи‧я | ман‧дра‧джи‧я |
![]() | мизансцен (mizanscen) | ми‧зан‧сцен | ми‧зан‧сцен |
![]() | странство (stranstvo) | стран‧ство | стран‧ство |
![]() | пространство (prostranstvo) | про‧стран‧ство | про‧стран‧ство |
![]() | робство (robstvo) | роб‧ство | роб‧ство |
![]() | транспорт (transport) | тран‧спорт | тран‧спорт |
![]() | посвикна (posvikna) | по‧свик‧на | по‧свик‧на |
![]() | скръндза (skrǎndza) | скрън‧дза | скрън‧дза |
![]() | годзила (godzila) | год‧зи‧ла | год‧зи‧ла |
![]() | камикадзе (kamikadze) | ка‧ми‧кад‧зе | ка‧ми‧кад‧зе |
![]() | надживея (nadživeja) | на‧джи‧ве‧я | на‧джи‧ве‧я |
![]() | скрън.дза (skrǎn.dza) | скрън‧дза | скрън‧дза |
![]() | го.дзила (go.dzila) | го‧дзи‧ла | го‧дзи‧ла |
![]() | камика.дзе (kamika.dze) | ка‧ми‧ка‧дзе | ка‧ми‧ка‧дзе |
![]() | над.живея (nad.živeja) | над‧жи‧ве‧я | над‧жи‧ве‧я |
![]() | безсилен (bezsilen) | без‧си‧лен | без‧си‧лен |
![]() | безшумен (bezšumen) | без‧шу‧мен | без‧шу‧мен |
![]() | безвъзвратен (bezvǎzvraten) | без‧въз‧вра‧тен | без‧въз‧вра‧тен |
![]() | безхаберен (bezhaberen) | без‧ха‧бе‧рен | без‧ха‧бе‧рен |
![]() | безстрашен (bezstrašen) | без‧стра‧шен | без‧стра‧шен |
![]() | безхлебна (bezhlebna) | без‧хле‧бна | без‧хле‧бна |
![]() | безвремие (bezvremie) | без‧вре‧ми‧е | без‧вре‧ми‧е |
![]() | безмерен (bezmeren) | без‧ме‧рен | без‧ме‧рен |
![]() | безличен (bezličen) | без‧ли‧чен | без‧ли‧чен |
![]() | безнаказан (beznakazan) | без‧на‧ка‧зан | без‧на‧ка‧зан |
![]() | безразборен (bezrazboren) | без‧раз‧бо‧рен | без‧раз‧бо‧рен |
![]() | бездетен (bezdeten) | без‧де‧тен | без‧де‧тен |
![]() | безпардонен (bezpardonen) | без‧пар‧до‧нен | без‧пар‧до‧нен |
![]() | безтелесен (beztelesen) | без‧те‧ле‧сен | без‧те‧ле‧сен |
![]() | безглав (bezglav) | без‧глав | без‧глав |
![]() | безчестен (bezčesten) | без‧че‧стен | без‧че‧стен |
![]() | безпризорен (bezprizoren) | без‧при‧зо‧рен | без‧при‧зо‧рен |
![]() | безгрешен (bezgrešen) | без‧гре‧шен | без‧гре‧шен |
![]() | безкраен (bezkraen) | без‧кра‧ен | без‧кра‧ен |
![]() | безбрежен (bezbrežen) | без‧бре‧жен | без‧бре‧жен |
![]() | бездна (bezdna) | безд‧на | безд‧на |
![]() | изхвърлям (izhvǎrljam) | из‧хвър‧лям | из‧хвър‧лям |
![]() | изстена (izstena) | из‧сте‧на | из‧сте‧на |
![]() | извор (izvor) | из‧вор | из‧вор |
![]() | извозвам (izvozvam) | из‧воз‧вам | из‧воз‧вам |
![]() | извлача (izvlača) | из‧вла‧ча | из‧вла‧ча |
![]() | изхрачване (izhračvane) | из‧храч‧ва‧не | из‧храч‧ва‧не |
![]() | изшмугна (izšmugna) | из‧шмуг‧на | из‧шмуг‧на |
![]() | изживяното (izživjanoto) | из‧жи‧вя‧но‧то | из‧жи‧вя‧но‧то |
![]() | изненада (iznenada) | из‧не‧на‧да | из‧не‧на‧да |
![]() | излъгах (izlǎgah) | из‧лъ‧гах | из‧лъ‧гах |
![]() | измяна (izmjana) | из‧мя‧на | из‧мя‧на |
![]() | изрод (izrod) | из‧род | из‧род |
![]() | изтрезвително (iztrezvitelno) | из‧трез‧ви‧тел‧но | из‧трез‧ви‧тел‧но |
![]() | изпроставял (izprostavjal) | из‧про‧ста‧вял | из‧про‧ста‧вял |
![]() | изключвам (izključvam) | из‧ключ‧вам | из‧ключ‧вам |
![]() | изблиза (izbliza) | из‧бли‧за | из‧бли‧за |
![]() | надслов (nadslov) | над‧слов | над‧слов |
![]() | надхвърлен (nadhvǎrlen) | над‧хвър‧лен | над‧хвър‧лен |
![]() | надвиквам (nadvikvam) | над‧вик‧вам | над‧вик‧вам |
![]() | надве (nadve) | над‧ве | над‧ве |
![]() | надгробен (nadgroben) | над‧гро‧бен | над‧гро‧бен |
![]() | надпис (nadpis) | над‧пис | над‧пис |
![]() | надценявам (nadcenjavam) | над‧це‧ня‧вам | над‧це‧ня‧вам |
![]() | надделея (naddeleja) | над‧де‧ле‧я | над‧де‧ле‧я |
![]() | над.раствам (nad.rastvam) | над‧ра‧ствам | над‧ра‧ствам |
![]() | надмощие (nadmoštie) | над‧мо‧щи‧е | над‧мо‧щи‧е |
![]() | ненадминат (nenadminat) | не‧над‧ми‧нат | не‧над‧ми‧нат |
![]() | безнадзорен (beznadzoren) | без‧над‧зо‧рен | без‧над‧зо‧рен |
![]() | надница (nadnica) | над‧ни‧ца | над‧ни‧ца |
![]() | надменност (nadmennost) | над‧мен‧ност | над‧мен‧ност |
![]() | на.длъж (na.dlǎž) | на‧длъж | на‧длъж |
![]() | надробен (nadroben) | на‧дро‧бен | на‧дро‧бен |
![]() | надрънкам (nadrǎnkam) | на‧дрън‧кам | на‧дрън‧кам |
![]() | надраскам (nadraskam) | на‧дра‧скам | на‧дра‧скам |
![]() | надрусам (nadrusam) | на‧дру‧сам | на‧дру‧сам |
![]() | надран (nadran) | на‧дран | на‧дран |
![]() | подстрекател (podstrekatel) | под‧стре‧ка‧тел | под‧стре‧ка‧тел |
![]() | подход (podhod) | под‧ход | под‧ход |
![]() | подвижен (podvižen) | под‧ви‧жен | под‧ви‧жен |
![]() | подзаглавие (podzaglavie) | под‧за‧гла‧ви‧е | под‧за‧гла‧ви‧е |
![]() | подклаждам (podklaždam) | под‧клаж‧дам | под‧клаж‧дам |
![]() | подбор (podbor) | под‧бор | под‧бор |
![]() | подпирам (podpiram) | под‧пи‧рам | под‧пи‧рам |
![]() | подценявам (podcenjavam) | под‧це‧ня‧вам | под‧це‧ня‧вам |
![]() | подновявам (podnovjavam) | под‧но‧вя‧вам | под‧но‧вя‧вам |
![]() | подмамвам (podmamvam) | под‧мам‧вам | под‧мам‧вам |
![]() | подлост (podlost) | под‧лост | под‧лост |
![]() | под.разделение (pod.razdelenie) | под‧раз‧де‧ле‧ни‧е | под‧раз‧де‧ле‧ни‧е |
![]() | подробен (podroben) | по‧дро‧бен | по‧дро‧бен |
![]() | подражавам (podražavam) | по‧дра‧жа‧вам | по‧дра‧жа‧вам |
![]() | подремя (podremja) | по‧дре‧мя | по‧дре‧мя |
![]() | подрусам (podrusam) | по‧дру‧сам | по‧дру‧сам |
![]() | безизразен (bezizrazen) | бе‧зиз‧ра‧зен | бе‧зиз‧ра‧зен |
![]() | безизразност (bezizraznost) | бе‧зиз‧ра‧зност | бе‧зиз‧ра‧зност |
![]() | безвъзмезден (bezvǎzmezden) | без‧въз‧мез‧ден | без‧въз‧мез‧ден |
![]() | безвъздушен (bezvǎzdušen) | без‧въз‧ду‧шен | без‧въз‧ду‧шен |
![]() | безразличен (bezrazličen) | без‧раз‧ли‧чен | без‧раз‧ли‧чен |
![]() | безразборност (bezrazbornost) | без‧раз‧бор‧ност | без‧раз‧бор‧ност |
![]() | безпредметен (bezpredmeten) | без‧пред‧ме‧тен | без‧пред‧ме‧тен |
![]() | поизправя (poizpravja) | по‧из‧пра‧вя | по‧из‧пра‧вя |
![]() | поизмъча (poizmǎča) | по‧из‧мъ‧ча | по‧из‧мъ‧ча |
![]() | поизгладя (poizgladja) | по‧из‧гла‧дя | по‧из‧гла‧дя |
![]() | произношение (proiznošenie) | про‧из‧но‧ше‧ни‧е | про‧из‧но‧ше‧ни‧е |
![]() | произтича (proiztiča) | про‧из‧ти‧ча | про‧из‧ти‧ча |
![]() | наизмислил (naizmislil) | на‧из‧ми‧слил | на‧из‧ми‧слил |
![]() | наизлезлите (naizlezlite) | на‧из‧ле‧зли‧те | на‧из‧ле‧зли‧те |
![]() | предразположение (predrazpoloženie) | пред‧раз‧по‧ло‧же‧ни‧е | пред‧раз‧по‧ло‧же‧ни‧е |
![]() | преразглеждане (prerazgleždane) | пре‧раз‧глеж‧да‧не | пре‧раз‧глеж‧да‧не |
![]() | преразпределение (prerazpredelenie) | пре‧раз‧пре‧де‧ле‧ни‧е | пре‧раз‧пре‧де‧ле‧ни‧е |
![]() | преразказ (prerazkaz) | пре‧раз‧каз | пре‧раз‧каз |
![]() | превъзмогна (prevǎzmogna) | пре‧въз‧мог‧на | пре‧въз‧мог‧на |
![]() | превъзпитание (prevǎzpitanie) | пре‧въз‧пи‧та‧ни‧е | пре‧въз‧пи‧та‧ни‧е |
![]() | преиздавам (preizdavam) | пре‧из‧да‧вам | пре‧из‧да‧вам |
![]() | преизбирам (preizbiram) | пре‧из‧би‧рам | пре‧из‧би‧рам |
![]() | невъзможен (nevǎzmožen) | не‧въз‧мо‧жен | не‧въз‧мо‧жен |
![]() | невъзпитан (nevǎzpitan) | не‧въз‧пи‧тан | не‧въз‧пи‧тан |
![]() | неизбежен (neizbežen) | не‧из‧бе‧жен | не‧из‧бе‧жен |
![]() | неизменност (neizmennost) | не‧из‧мен‧ност | не‧из‧мен‧ност |
![]() | неразделен (nerazdelen) | не‧раз‧де‧лен | не‧раз‧де‧лен |
![]() | неразположение (nerazpoloženie) | не‧раз‧по‧ло‧же‧ни‧е | не‧раз‧по‧ло‧же‧ни‧е |
![]() | поразмисля (porazmislja) | по‧раз‧ми‧сля | по‧раз‧ми‧сля |
![]() | пораздрусам (porazdrusam) | по‧раз‧дру‧сам | по‧раз‧дру‧сам |
![]() | наразказах (narazkazah) | на‧раз‧ка‧зах | на‧раз‧ка‧зах |
![]() | наразлепил (narazlepil) | на‧раз‧ле‧пил | на‧раз‧ле‧пил |
![]() | неотложен (neotložen) | не‧от‧ло‧жен | не‧от‧ло‧жен |
![]() | неотменим (neotmenim) | не‧от‧ме‧ним | не‧от‧ме‧ним |
![]() | поотложа (pootloža) | по‧от‧ло‧жа | по‧от‧ло‧жа |
![]() | поотмина (pootmina) | по‧от‧ми‧на | по‧от‧ми‧на |
![]() | уелски (uelski) | у‧ел‧ски | у‧ел‧ски |
![]() | уебсайт (uebsajt) | у‧еб‧сайт | у‧еб‧сайт |
![]() | уестърн (uestǎrn) | у‧е‧стърн | у‧е‧стърн |
![]() | Оуен (Ouen) | О‧у‧ен | О‧у‧ен |
![]() | ноухау (nouhau) | но‧у‧ха‧у | но‧у‧ха‧у |
![]() | Джоузеф (Džouzef) | Джо‧у‧зеф | Джо‧у‧зеф |
![]() | боулинг (bouling) | бо‧у‧линг | бо‧у‧линг |
![]() | даунлоуд (daunloud) | да‧ун‧ло‧уд | да‧ун‧ло‧уд |
![]() | уиски (uiski) | у‧и‧ски | у‧и‧ски |
![]() | уикенд (uikend) | у‧и‧кенд | у‧и‧кенд |
![]() | Уоруик (Uoruik) | У‧о‧ру‧ик | У‧о‧ру‧ик |
![]() | Хелоуин (Helouin) | Хе‧ло‧у‧ин | Хе‧ло‧у‧ин |
![]() | ўелски | уел‧ски | уел‧ски |
![]() | ўебсайт | уеб‧сайт | уеб‧сайт |
![]() | ўестърн | уе‧стърн | уе‧стърн |
![]() | Оўен | О‧уен | О‧уен |
![]() | ноўхаў | ноу‧хау | ноу‧хау |
![]() | Джоўзеф | Джоу‧зеф | Джоу‧зеф |
![]() | боўлинг | боу‧линг | боу‧линг |
![]() | даўн.лоўд | даун‧лоуд | даун‧лоуд |
![]() | ўиски | уи‧ски | уи‧ски |
![]() | ўикенд | уи‧кенд | уи‧кенд |
![]() | Ўорўик | Уор‧уик | Уор‧уик |
![]() | Хелоўин | Хе‧ло‧уин | Хе‧ло‧уин |
![]() | разни хора-разни вкусове (razni hora-razni vkusove) | раз‧ни хо‧ра-раз‧ни вку‧со‧ве | раз‧ни хо‧ра-раз‧ни вку‧со‧ве |
![]() | акушер-гинеколог (akušer-ginekolog) | а‧ку‧шер-ги‧не‧ко‧лог | а‧ку‧шер-ги‧не‧ко‧лог |
![]() | най-напред (naj-napred) | най-на‧пред | най-на‧пред |
![]() | ампер-час (amper-čas) | ам‧пер-час | ам‧пер-час |
![]() | га-га (ga-ga) | га-га | га-га |
![]() | пи-пи (pi-pi) | пи-пи | пи-пи |
![]() | Гвинея-Бисау (Gvineja-Bisau) | Гви‧не‧я-Би‧са‧у | Гви‧не‧я-Би‧са‧у |
![]() | шам-фъстък (šam-fǎstǎk) | шам-фъ‧стък | шам-фъ‧стък |
![]() | вълна-убиец (vǎlna-ubiec) | въл‧на-у‧би‧ец | въл‧на-у‧би‧ец |
![]() | акушер-гинеколог (akušer-ginekolog) | а‧ку‧шер-ги‧не‧ко‧лог | а‧ку‧шер-ги‧не‧ко‧лог |
![]() | по-добре късно, отколкото никога (po-dobre kǎsno, otkolkoto nikoga) | по-до‧бре къ‧сно, от‧кол‧ко‧то ни‧ко‧га | по-до‧бре къ‧сно, от‧кол‧ко‧то ни‧ко‧га |
![]() | зенитно-ракетен (zenitno-raketen) | зе‧нит‧но-ра‧ке‧тен | зе‧нит‧но-ра‧ке‧тен |
![]() | горе-долу (gore-dolu) | го‧ре-до‧лу | го‧ре-до‧лу |
![]() | най-после (naj-posle) | най-по‧сле | най-по‧сле |
![]() | чик-чирик (čik-čirik) | чик-чи‧рик | чик-чи‧рик |
![]() | среден род (sreden rod) | сре‧ден род | сре‧ден род |
![]() | божа кравичка (boža kravička) | бо‧жа кра‧вич‧ка | бо‧жа кра‧вич‧ка |
![]() | Съединени американски щати (Sǎedineni amerikanski štati) | Съ‧е‧ди‧не‧ни а‧ме‧ри‧кан‧ски ща‧ти | Съ‧е‧ди‧не‧ни а‧ме‧ри‧кан‧ски ща‧ти |
![]() | от младих до старих (ot mladih do starih) | от мла‧дих до ста‧рих | от мла‧дих до ста‧рих |
![]() | со кротце, со благо и со малко кютек (so krotce, so blago i so malko kjutek) | со крот‧це, со бла‧го и со мал‧ко кю‧тек | со крот‧це, со бла‧го и со мал‧ко кю‧тек |
References
- Тилков, Димитър, Бояджиев, Тодор, Георгиева, Елена, Пенчев, Йордан, Станков, Валентин (1998) Граматика на съвременния български книжовен език (in Bulgarian), 3rd edition, volume 1, Sofia: ABAGAR
local export = {}
local substring = mw.ustring.sub
local rsubn = mw.ustring.gsub
local rmatch = mw.ustring.match
local rsplit = mw.text.split
local U = require("Module:string/char")
local lang = require("Module:languages").getByCode("bg")
local script = require("Module:scripts").getByCode("Cyrl")
local GRAVE = U(0x300)
local ACUTE = U(0x301)
local BREVE = U(0x306)
local PRIMARY = U(0x2C8)
local SECONDARY = U(0x2CC)
local TIE = U(0x361)
local FRONTED = U(0x31F)
local DOTUNDER = U(0x323)
local HYPH = U(0x2027)
local BREAK_MARKER = "."
local vowels = "aɤɔuɛiɐo"
local vowels_c = "[" .. vowels .. "]"
local cons = "bvɡdʒzjklwmnprstfxʃɣʲ" .. TIE
local cons_c = "[" .. cons .. "]"
local voiced_cons = "bvɡdʒzɣ" .. TIE
local voiced_cons_c = "[" .. voiced_cons .. "]"
local hcons_c = "[бвгджзйклмнпрстфхшщьчц#БВГДЖЗЙКЛМНПРСТФХШЩЬЧЦ=]"
local hvowels_c = "[аъоуеияѝюАЪОУЕИЯЍЮ]"
local accents = PRIMARY .. SECONDARY
local accents_c = "[" .. accents .. "]"
-- single characters that map to IPA sounds
local phonetic_chars_map = {
["а"] = "a",
["б"] = "b",
["в"] = "v",
["г"] = "ɡ",
["д"] = "d",
["е"] = "ɛ",
["ж"] = "ʒ",
["з"] = "z",
["и"] = "i",
["й"] = "j",
["к"] = "k",
["л"] = "l",
["м"] = "m",
["н"] = "n",
["о"] = "ɔ",
["п"] = "p",
["р"] = "r",
["с"] = "s",
["т"] = "t",
["у"] = "u",
["ў"] = "w",
["ф"] = "f",
["х"] = "x",
["ц"] = "t" .. TIE .. "s",
["ч"] = "t" .. TIE .. "ʃ",
["ш"] = "ʃ",
["щ"] = "ʃt",
["ъ"] = "ɤ",
["ь"] = "ʲ",
["ю"] = "ʲu",
["я"] = "ʲa",
[GRAVE] = SECONDARY,
[ACUTE] = PRIMARY
}
local devoicing = {
["b"] = "p", ["d"] = "t", ["ɡ"] = "k",
["z"] = "s", ["ʒ"] = "ʃ",
["v"] = "f"
}
local voicing = {
["p"] = "b", ["t"] = "d", ["k"] = "ɡ",
["s"] = "z", ["ʃ"] = "ʒ", ["x"] = "ɣ",
["f"] = "v"
}
-- Prefixes where, if they occur at the beginning of the word and the stress is on the next syllable, we place the
-- syllable division directly after the prefix. For example, the default syllable-breaking algorithm would convert
-- безбра́чие to беˈзбрачие; but because it begins with без-, we convert it to безˈбрачие. Note that we don't (yet?)
-- convert измра́ to изˈмра instead of default измˈра, although we probably should.
--
-- Think twice before putting prefixes like на-, пре- and от- here, because of the existence of над-, пред-, and о-,
-- which are also prefixes.
local IPA_prefixes = {"bɛz", "vɤz", "vɤzproiz", "iz", "naiz", "poiz", "prɛvɤz", "proiz", "raz"}
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
-- apply rsub() repeatedly until no change
local function rsub_repeatedly(term, foo, bar)
while true do
local new_term = rsub(term, foo, bar)
if new_term == term then
return term
end
term = new_term
end
end
local function char_at(str, index)
return substring(str, index, index)
end
local function starts_with(str, substr)
return substring(str, 1, mw.ustring.len(substr)) == substr
end
local function count_vowels(word)
local _, vowel_count = mw.ustring.gsub(word, hvowels_c, "")
return vowel_count
end
function export.remove_pron_notations(text, remove_grave)
text = rsub(text, "[." .. DOTUNDER .. "]", "")
text = rsub(text, "ў", "у")
text = rsub(text, "Ў", "У")
-- Remove grave accents from annotations but maybe not from phonetic respelling
if remove_grave then
text = mw.ustring.toNFC(rsub(mw.ustring.toNFD(text), GRAVE, ""))
end
return text
end
function export.toIPA(term, endschwa)
if type(term) == "table" then -- called from a template or a bot
endschwa = term.args.endschwa
term = term.args[1]
end
local origterm = term
term = mw.ustring.toNFD(mw.ustring.lower(term))
term = rsub(term, "у" .. BREVE, "ў") -- recompose ў
term = rsub(term, "и" .. BREVE, "й") -- recompose й
if term:find(GRAVE) and not term:find(ACUTE) then
error("Use acute accent, not grave accent, for primary stress: " .. origterm)
end
-- allow DOTUNDER to signal same as endschwa=1
term = rsub(term, "а(" .. accents_c .. "?)" .. DOTUNDER, "ъ%1")
term = rsub(term, "я(" .. accents_c .. "?)" .. DOTUNDER, "ʲɤ%1")
term = rsub(term, ".", phonetic_chars_map)
-- Mark word boundaries
term = rsub(term, "(%s+)", "#%1#")
term = "#" .. term .. "#"
-- Convert verbal and definite endings
if endschwa then
term = rsub(term, "a(" .. PRIMARY .. "t?#)", "ɤ%1")
end
-- Change ʲ to j after vowels or word-initially
term = rsub(term, "([" .. vowels .. "#]" .. accents_c .. "?)ʲ", "%1j")
-------------------- Move stress ---------------
-- First, move leftwards over the vowel.
term = rsub(term, "(" .. vowels_c .. ")(" .. accents_c .. ")", "%2%1")
-- Then, move leftwards over j or soft sign.
term = rsub(term, "([jʲ])(" .. accents_c .. ")", "%2%1")
-- Then, move leftwards over a single consonant.
term = rsub(term, "(" .. cons_c .. ")(" .. accents_c .. ")", "%2%1")
-- Then, move leftwards over Cl/Cr combinations where C is an obstruent (NOTE: IPA ɡ).
term = rsub(term, "([bdɡptkxfv]" .. ")(" .. accents_c .. ")([rl])", "%2%1%3")
-- Then, move leftwards over kv/gv (NOTE: IPA ɡ).
term = rsub(term, "([kɡ]" .. ")(" .. accents_c .. ")(v)", "%2%1%3")
-- Then, move leftwards over sC combinations, where C is a stop or resonant (NOTE: IPA ɡ).
term = rsub(term, "([sz]" .. ")(" .. accents_c .. ")([bdɡptkvlrmn])", "%2%1%3")
-- Then, move leftwards over affricates not followed by a consonant.
term = rsub(term, "([td]" .. TIE .. "?)(" .. accents_c .. ")([szʃʒ][" .. vowels .. "ʲ])", "%2%1%3")
-- If we ended up in the middle of a tied affricate, move to its right.
term = rsub(term, "(" .. TIE .. ")(" .. accents_c .. ")(" .. cons_c .. ")", "%1%3%2")
-- Then, move leftwards over any remaining consonants at the beginning of a word.
term = rsub(term, "#(" .. cons_c .. "*)(" .. accents_c .. ")", "#%2%1")
-- Then correct for known prefixes.
for _, prefix in ipairs(IPA_prefixes) do
prefix_prefix, prefix_final_cons = rmatch(prefix, "^(.-)(" .. cons_c .. "*)$")
if prefix_final_cons then
-- Check for accent moved too far to the left into a prefix, e.g. безбрачие accented as беˈзбрачие instead
-- of безˈбрачие
term = rsub(term, "#(" .. prefix_prefix .. ")(" .. accents_c .. ")(" .. prefix_final_cons .. ")", "#%1%3%2")
end
end
-- Finally, if there is an explicit syllable boundary in the cluster of consonants where the stress is, put it there.
-- First check for accent to the right of the explicit syllable boundary.
term = rsub(term, "(" .. cons_c .. "*)%.(" .. cons_c .. "*)(" .. accents_c .. ")(" .. cons_c .. "*)", "%1%3%2%4")
-- Then check for accent to the left of the explicit syllable boundary.
term = rsub(term, "(" .. cons_c .. "*)(" .. accents_c .. ")(" .. cons_c .. "*)%.(" .. cons_c .. "*)", "%1%3%2%4")
-- Finally, remove any remaining syllable boundaries.
term = rsub(term, "%.", "")
-------------------- Vowel reduction (in unstressed syllables) ---------------
local function reduce_vowel(vowel)
return rsub(vowel, "[aɔɤu]", { ["a"] = "ɐ", ["ɔ"] = "o", ["ɤ"] = "ɐ", ["u"] = "o" })
end
-- Reduce all vowels before the stress, except if the word has no accent at all. (FIXME: This is presumably
-- intended for single-syllable words without accents, but if the word is multisyllabic without accents,
-- presumably all vowels should be reduced.)
term = rsub(term, "(#[^#" .. accents .. "]*)(.-#)", function(a, b)
if count_vowels(origterm) <= 1 then
return a .. b
else
return reduce_vowel(a) .. b
end
end)
-- Reduce all vowels after the accent except the first vowel after the accent mark (which is stressed).
term = rsub(term, "(" .. accents_c .. "[^aɛiɔuɤ#]*[aɛiɔuɤ])([^#" .. accents .. "]*)", function(a, b)
return a .. reduce_vowel(b)
end)
-------------------- Vowel assimilation to adjacent consonants (fronting/raising) ---------------
term = rsub(term, "([ʃʒʲj])([aouɤ])", "%1%2" .. FRONTED)
-- Hard l
term = rsub_repeatedly(term, "l([^ʲɛi])", "ɫ%1")
-- Voicing assimilation
term = rsub(term, "([bdɡzʒv" .. TIE .. "]*)(" .. accents_c .. "?[ptksʃfx#])", function(a, b)
return rsub(a, ".", devoicing) .. b end)
term = rsub(term, "([ptksʃfx" .. TIE .. "]*)(" .. accents_c .. "?[bdɡzʒ])", function(a, b)
return rsub(a, ".", voicing) .. b end)
term = rsub(term, "n(" .. accents_c .. "?[ɡk]+)", "ŋ%1")
term = rsub(term, "m(" .. accents_c .. "?[fv]+)", "ɱ%1")
-- -- Correct for clitic pronunciation of с and в
-- term = rsub(term, "#s# #(.)", "#s" .. TIE .. "%1")
-- term = rsub(term, "#f# #(.)", "#f" .. TIE .. "%1")
-- term = rsub(term, "([sfzv]" .. TIE .. ")" .. "(" .. accents_c .. ")", "%2%1")
-- term = rsub(term, "s" .. TIE .. "(" .. voiced_cons_c .. ")", "z" .. TIE .. "%1")
-- term = rsub(term, "f" .. TIE .. "(" .. voiced_cons_c .. ")", "v" .. TIE .. "%1")
-- Sibilant assimilation
term = rsub(term, "[sz](" .. accents_c .. "?[td]?" .. TIE .. "?)([ʃʒ])", "%2%1%2")
-- Reduce consonant clusters
term = rsub(term, "([szʃʒ])[td](" .. accents_c .. "?)([tdknml])", "%2%1%3")
-- Strip hashes
term = rsub(term, "#", "")
return term
end
----Syllabification code----
-- Authorship: Chernorizets
-- Lua port: Kiril Kovachev
local function set_of(t)
local out = {}
for _, v in pairs(t) do
out[v] = true
end
return out
end
local function in_set(set, value)
return set[value] == true
end
-- Classification of letters by phonetic category
local vowels_syllab = set_of {"а", "ъ", "о", "у", "е", "и", "ю", "я"}
local sonorants = set_of { "л", "м", "н", "р", "й", "ў"}
local stops = set_of {"б", "п", "г", "к", "д", "т"}
local fricatives = set_of {"в", "ф", "ж", "ш", "з", "с", "х"}
local affricates = set_of {"ч", "ц"}
local function is_vowel(ch)
return in_set(vowels_syllab, ch)
end
local function is_consonant(ch)
return ch == 'щ' or is_sonorant(ch) or is_stop(ch) or is_fricative(ch) or is_affricate(ch)
end
local function is_palatalizer(ch)
return ch == 'ь'
end
local function is_sonorant(ch)
return in_set(sonorants, ch)
end
-- Opposite of sonorant.
local function is_obstruent(ch)
return is_stop(ch) or is_fricative(ch) or is_affricate(ch)
end
local function is_stop(ch)
return in_set(stops, ch)
end
local function is_fricative(ch)
return in_set(fricatives, ch)
end
local function is_affricate(ch)
return in_set(affricates, ch)
end
--[===[
Sonority objects:
Sonority objects take the form of a table with the following attributes:
{
rank (int): the numerical value representing the position of the sound in the sonority hierarchy;
first_index (int): the index of the first letter that makes up the sound within the word.
The index of the first letter in a word with this sonority rank.
The affricates "дж" and "дз" are represented by two letters each, but
for sonority purposes they function as a "unit", hence we just need
the index of the first letter of the affricate.
}
]===]
local function new_sonority(rank, first_index)
return {
["rank"] = rank,
["first_index"] = first_index
}
end
local function get_sonority_rank(ch)
if is_fricative(ch) then
return 1
end
if is_stop(ch) or is_affricate(ch) then
return 2
end
if is_sonorant(ch) then
return 3
end
if is_vowel(ch) then
return 4
end
return 0
end
-- Get the representation of a word as a list of sequential sonority objects, stored in a table.
-- Their representation is just {[1] = (sonority object #1), [2] = (sonority object #2)} etc.
-- Please see above for description of sonority objects' layout.
local function get_sonority_model(word, start_idx, end_idx)
local sonorities = {}
word = mw.ustring.lower(word)
local i = start_idx
while i < end_idx do
local curr = char_at(word, i)
if curr == "щ" then
-- One letter representing 2 sounds - decompose it.
table.insert(sonorities, new_sonority(get_sonority_rank("ш"), i))
table.insert(sonorities, new_sonority(get_sonority_rank("т"), i));
elseif curr == "д" then
-- Handle affricates with 'д' - only 'дж' here for illustration.
local next_char = (i == end_idx - 1 and " ") or char_at(word, i+1)
local should_skip = false
if next_char == "ж" then
table.insert(sonorities, new_sonority(2, i)) -- 2 = affricate sonority rank
i = i + 1 -- Skip over the 'ж'
should_skip = true
end
if not should_skip then table.insert(sonorities, new_sonority(get_sonority_rank("д"), i)) end
elseif not is_palatalizer(curr) then
-- Skip over 'ь' since it doesn't change the sonority.
table.insert(sonorities, new_sonority(get_sonority_rank(curr), i))
end
i = i + 1
end
return sonorities
end
-- Forced breaks when the user inputs a break marker into the input string
-- word: string; start and end are integers indexing the string
local function find_forced_break(word, range_start, range_end)
if range_start >= range_end then return -1 end
local marker_pos = mw.ustring.find(word, BREAK_MARKER, range_start, true) or -1
return marker_pos >= range_end and -1 or marker_pos
end
local function strip_forced_breaks(segment)
return rsub(segment, "[.]", "");
end
---- Morphological prefix handling
--[==[
This code brings morphological prefix awareness to syllabification.
This is necessary, because following the principle of rising sonority
alone fails to determine syllable boundaries correctly in some cases
— that is, when certain prefixes should be kept together as a first syllable.
]==]
--[==[
Affected prefixes. Each of them ends in a consonant that can be followed
by another consonant of a higher sonority in some words. In such cases,
naive syllable breaking would chop off the prefix's last consonant, and
glue it to the onset of the next syllable.
]==]
local prefixes = {
-- без- family
"без",
-- из- family
"безиз", "наиз", "поиз", "произ", "преиз", "неиз", "из",
-- въз- family
"безвъз", "превъз", "невъз", "въз",
-- раз- family
"безраз", "предраз", "пораз", "нараз", "прераз", "нераз", "раз",
-- от- family
"неот", "поот", "от",
-- ending in fricatives
"екс", "таз", "дис",
-- ending in stops
"пред"
}
--[==[
Finds the (zero-based) separation point between a
morphological prefix and the rest of the word.
By convention, that's the index of the first character
after the prefix.
word: the word to check for prefixes
return -1 if no prefix found, or if the separation point
is handled by the sonority model. A non-zero index otherwise.
]==]
-- prefix, word are both strings
local function followed_by_higher_sonority_cons(prefix, word)
prefix = mw.ustring.lower(prefix)
word = mw.ustring.lower(word)
local prefix_last_char = char_at(prefix, mw.ustring.len(prefix))
local first_char_after_prefix = char_at(word, mw.ustring.len(prefix) + 1)
-- Prefixes followed by vowels do, in fact, get broken up.
if is_vowel(first_char_after_prefix) then return false end
return get_sonority_rank(prefix_last_char) < get_sonority_rank(first_char_after_prefix)
end
local function find_separation_points(word)
local matching_prefixes = {}
word = mw.ustring.lower(word)
for _, prefix in pairs(prefixes) do
if starts_with(word, prefix) and followed_by_higher_sonority_cons(prefix, word) then
table.insert(matching_prefixes, mw.ustring.len(prefix) + 1)
end
end
return matching_prefixes
end
---- Main syllabification code
---Context objects:
--[==[ encoded as a table like
{
word (string),
prefix_separation_points (table[int])
}
]==]
local function new_context(word, pos)
return {
["word"] = word,
["prefix_separation_points"] = pos
}
end
--[==[
Consonant clusters that exhibit rising sonority, but should be
broken up regardless to produce natural-sounding syllables.
The breakpoint for clusters of 3 or more consonants can vary -
here we provide a zero-based offset within the cluster for each.
]==]
local sonority_exception_break = {
["км"] = 1, ["гм"] = 1, ["дм"] = 1, ["вм"] = 1,
["зм"] = 1, ["цм"] = 1, ["чм"] = 1,
["дн"] = 1, ["вн"] = 1, ["тн"] = 1, ["чн"] = 1,
["кн"] = 1, ["гн"] = 1, ["цн"] = 1,
["зд"] = 1, ["зч"] = 1, ["зц"] = 1,
["вк"] = 1, ["вг"] = 1, ["дл"] = 1, ["жд"] = 1,
["згн"] = 1, ["здн"] = 2, ["вдж"] = 1
}
local sonority_exception_keep = {
"ств", "св", "вс"
}
local function normalize_word(word)
if word == nil then return "" end
word = rsub(rsub(word, "^\\s+", ""), "\\s+^", "") -- Strip spaces
return word
end
local function normalize_syllable(syllable)
local normalized = strip_forced_breaks(syllable)
normalized = rsub(normalized, "ў", "у")
normalized = rsub(normalized, "Ў", "У")
return normalized
end
local function find_rising_sonority_break(sonorities)
local prev_rank = -1;
for _, curr in pairs(sonorities) do
if curr.rank <= prev_rank then
-- Found a break.
return curr.first_index
end
prev_rank = curr.rank
end
-- There was no rising sonority break. Start syllable at first index.
return sonorities[1].first_index
end
local function matches(str, substr, start_idx, end_idx)
local strlen = end_idx - start_idx
if strlen ~= mw.ustring.len(substr) then return false end
str = mw.ustring.lower(str)
substr = mw.ustring.lower(substr)
local i = start_idx
local j = 1
while i < end_idx do
if char_at(str, i) ~= char_at(substr, j) then return false end
i = i + 1
j = j + 1
end
return true
end
-- ctx: context object
-- left and right vowels: integers
-- sonority break: integer
local function fixup_syllable_onset(ctx, left_vowel, sonority_break, right_vowel)
local word = mw.ustring.lower(ctx.word)
-- 'щр' is a syllable onset when in front of a vowel.
-- Although 'щ' + sonorant technically follows rising sonority, syllables
-- like щнV, щлV etc. are unnatural and incorrect. In such cases, we treat
-- the sonorant as the onset of the next syllable.
if char_at(word, right_vowel - 2) == "щ" then
local penult = char_at(word, right_vowel - 1)
if penult == "р" then return (right_vowel - 2) end
if is_sonorant(penult) then return (right_vowel - 1) end
end
-- Check for situations where we shouldn't break the cluster.
local match_found = false
for _, cluster in pairs(sonority_exception_keep) do
if matches(word, cluster, left_vowel + 1, right_vowel) then
match_found = true
break
end
end
if (match_found) then return left_vowel + 1 end -- syllable onset == beginning of cluster
-- Check for situations where we should break the cluster even if
-- it obeys the principle of rising sonority.
local maybe_cluster = nil
for cluster, _ in pairs(sonority_exception_break) do
if matches(word, cluster, left_vowel + 1, right_vowel) then
maybe_cluster = cluster
break
end
end
if maybe_cluster ~= nil then
local offset = sonority_exception_break[maybe_cluster]
return left_vowel + 1 + offset
end
local separation_points = ctx.prefix_separation_points
local separation_match = nil
for _, pos in pairs(separation_points) do
if pos > left_vowel and pos < right_vowel then
separation_match = pos
break
end
end
if separation_match ~= nil then return separation_match else return sonority_break end
end
-- ctx: context object
-- left/right vowels: integers
local function find_next_syllable_onset(ctx, left_vowel, right_vowel)
local n_cons = right_vowel - left_vowel - 1
-- No consonants - syllable starts on rightVowel
if n_cons == 0 then return right_vowel end
-- Check for forced breaks
local break_pos = find_forced_break(ctx.word, left_vowel + 1, right_vowel)
if break_pos ~= -1 then return break_pos + 1 end
-- Single consonant between two vowels - starts a syllable
if n_cons == 1 then return left_vowel + 1 end
-- Two or more consonants between the vowels. Find the point (if any)
-- where we break from rising sonority, and treat it as the tentative
-- onset of a new syllable.
local sonorities = get_sonority_model(ctx.word, left_vowel + 1, right_vowel)
local sonority_break = find_rising_sonority_break(sonorities)
-- Apply exceptions to the rising sonority principle to avoid
-- unnatural-sounding syllables.
return fixup_syllable_onset(ctx, left_vowel, sonority_break, right_vowel)
end
-- Returns a table of strings (list)
local function syllabify_poly(word)
local syllables = {}
local ctx = new_context(word, find_separation_points(word))
local prev_vowel = -1
local prev_onset = 1;
for i = 1, mw.ustring.len(word) do
if is_vowel(mw.ustring.lower(char_at(word, i))) then
-- A vowel, yay!
local should_skip = false
if prev_vowel == -1 then
prev_vowel = i
should_skip = true;
end
-- This is not the first vowel we've seen. In-between
-- the previous vowel and this one, there is a syllable
-- break, and the first character after the break starts
-- a new syllable.
if not should_skip then
local next_onset = find_next_syllable_onset(ctx, prev_vowel, i)
table.insert(syllables, substring(word, prev_onset, next_onset - 1))
prev_vowel = i
prev_onset = next_onset
end
end
end
-- Add the last syllable
table.insert(syllables, substring(word, prev_onset))
return syllables
end
function export.syllabify_word(word)
local norm = normalize_word(word)
if mw.ustring.len(norm) == 0 then return "" end;
local n_vowels = count_vowels(norm)
local syllables = n_vowels <= 1 and {norm} or syllabify_poly(norm)
local out = {}
for k, v in pairs(syllables) do
out[k] = normalize_syllable(v)
end
return table.concat(out, HYPH)
end
function tokenize_words(term)
local out = {}
local prev_index = 1
for i = 1, mw.ustring.len(term) do
local current_char = char_at(term, i)
if current_char == "-" or current_char == " " then
table.insert(out, substring(term, prev_index, i))
prev_index = i + 1
end
end
table.insert(out, substring(term, prev_index, i))
return out
end
function export.syllabify(term)
local words = tokenize_words(term)
local out = {}
for _, word in pairs(words) do
table.insert(out, export.syllabify_word(word))
end
return table.concat(out, "")
end
---Hyphenation
-- Hyphenate a word from its existing syllabification
function export.hyphenate(syllabification)
-- Source: http://logic.fmi.uni-sofia.bg/hyphenation/hyph-bg.html#hyphenation-rules-between-1983-and-2012
-- Also note: the rules from 2012 onward, which encode the modern standard, are entirely
-- backwards-compatible with the previous standard. Thus our code can generate valid 2012
-- hyphenations despite following the older rules.
---Pre-processing----
word = rsub(syllabification, "[" .. GRAVE .. ACUTE .. "]", "") -- Remove accent marks
word = rsub_repeatedly(word, HYPH .. "дж", HYPH .. "#")
word = rsub_repeatedly(word, "дж$", "#")
word = rsub_repeatedly(word, "^дж", "#")
word = rsub_repeatedly(word, "(" .. hvowels_c .. ")" .. HYPH .. "(" .. hcons_c .. ")(" .. rsub(hcons_c, '[ьЬ]', '') .. "+)", "%1%2" .. HYPH .. "%3")
word = rsub_repeatedly(word, "(" .. rsub(hcons_c, "[йЙ]", "") .. ")(" .. hcons_c .. "+)" .. HYPH, "%1" .. HYPH .. "%2")
word = rsub_repeatedly(word, "^(" .. hvowels_c .. ")" .. HYPH, "%1")
word = rsub_repeatedly(word, HYPH .. "(" .. hvowels_c .. ")$", "%1")
word = rsub_repeatedly(word, "(" .. hvowels_c .. ")" .. HYPH .. "(" .. hvowels_c .. ")" .. HYPH .. "(" .. hvowels_c .. ")", "%1%2" .. HYPH .. "%3")
word = rsub_repeatedly(word, HYPH .. "(" .. hvowels_c .. ")" .. HYPH .. "(" .. hcons_c .. ")", HYPH .. "%1%2")
word = rsub_repeatedly(word, "#", "дж")
return word
end
-- Hyphenate a word directly, no need to calculate its syllabification beforehand
function export.hyphenate_total(word)
syllabification = export.syllabify(word)
return export.hyphenate(syllabification)
end
local function get_anntext(term, ann)
if ann == "1" or ann == "y" then
-- remove secondary stress annotations
anntext = "'''" .. export.remove_pron_notations(term, true) .. "''': "
elseif ann then
anntext = "'''" .. ann .. "''': "
else
anntext = ""
end
return anntext
end
local HYPHENATION_LABEL = "Hyphenation<sup>([[Appendix:Bulgarian hyphenation#Hyphenation|key]])</sup>"
local SYLLABIFICATION_LABEL = "Syllabification<sup>([[Appendix:Bulgarian hyphenation#Syllabification|key]])</sup>"
local function format_hyphenation(hyphenation, label)
local syllables = rsplit(hyphenation, HYPH)
label = label or HYPHENATION_LABEL
return require("Module:hyphenation").format_hyphenations {
lang = lang,
hyphs = { { hyph = syllables } },
sc = script,
caption = label,
}
end
-- Entry point to {{bg-hyph}}
function export.show_hyphenation(frame)
local params = {
[1] = {},
}
local title = mw.title.getCurrentTitle()
local args = require("Module:parameters").process(frame:getParent().args, params)
local term = args[1] or title.nsText == "Template" and "при́мер" or title.text
local syllabification = export.syllabify(term)
syllabification = rsub(syllabification, "[" .. ACUTE .. GRAVE .. "]", "")
local hyphenation = export.hyphenate(syllabification)
local out
-- Users must put a * before the template usage
if syllabification == hyphenation then
out = format_hyphenation(syllabification)
else
local syllabification_text = format_hyphenation(syllabification, SYLLABIFICATION_LABEL)
local hyphenation_text = format_hyphenation(hyphenation)
out = syllabification_text .. "\n* " .. hyphenation_text
end
return out
end
function export.show(frame)
local params = {
[1] = {},
["endschwa"] = { type = "boolean" },
["ann"] = {},
["q"] = { type = "qualifier" },
["qq"] = { type = "qualifier" },
["a"] = { type = "labels" },
["aa"] = { type = "labels" },
["pagename"] = {},
}
local args = require("Module:parameters").process(frame:getParent().args, params)
local term = args[1] or args.pagename or mw.title.getCurrentTitle().nsText == "Template" and "при́мер" or
mw.loadData("Module:headword/data").pagename
local ipa = export.toIPA(term, args.endschwa)
ipa = "[" .. ipa .. "]"
local ipa_data = {
lang = lang,
items = {{ pron = ipa }},
q = args.q,
qq = args.qq,
a = args.a,
aa = args.aa,
}
local ipa_text = require("Module:IPA").format_IPA_full(ipa_data)
local anntext = get_anntext(term, args.ann)
return anntext .. ipa_text
end
return export