15 private const WB =
'\b'; #
default word boundary; may be updated in the future
18 private array $Cyrl2LatnExceptions = [];
20 private array $Latn2CyrlExceptions = [];
23 private array $Cyrl2LatnPatterns = [];
25 private array $Latn2CyrlPatterns = [];
28 private array $lc2uc = [];
30 private array $uc2lc = [];
32 private function initLcUc(
string $lcChars,
string $ucChars,
bool $reinit =
false ) {
33 # bail if we've already done this, unless we are re-initializing
34 if ( !$reinit && $this->lc2uc && $this->uc2lc ) {
38 # split up the lc and uc lists in a unicode-friendly way
40 preg_match_all(
'/./u', $lcChars, $myLc );
44 preg_match_all(
'/./u', $ucChars, $myUc );
47 # map lc to uc and vice versa
48 $this->lc2uc = array_combine( array_values( $myLc ), array_values( $myUc ) );
49 $this->uc2lc = array_combine( array_values( $myUc ), array_values( $myLc ) );
52 private function myLc(
string $string ):
string {
53 return strtr( $string, $this->uc2lc );
56 private function myUc(
string $string ):
string {
57 return strtr( $string, $this->lc2uc );
60 private function myUcWord(
string $string ):
string {
61 return $this->myUc( mb_substr( $string, 0, 1 ) ) . $this->myLc( mb_substr( $string, 1 ) );
64 private function addMappings(
65 array $mapArray, array &$A2B, array &$B2A,
bool $exactCase =
false,
string $prePat =
'',
string $postPat =
''
67 foreach ( $mapArray as $WordA => $WordB ) {
69 $ucA = $this->myUc( $WordA );
70 $ucWordA = $this->myUcWord( $WordA );
71 $ucB = $this->myUc( $WordB );
72 $ucWordB = $this->myUcWord( $WordB );
75 # if there are regexes, only map toward backregs
76 if ( !preg_match(
'/\$[1-9]/', $WordA ) ) {
77 $A2B[ $prePat . $WordA . $postPat ] = $WordB;
80 $A2B[ $prePat . $ucWordA . $postPat ] = $ucWordB;
82 $A2B[ $prePat . $ucA . $postPat ] = $ucB;
86 if ( !preg_match(
'/\$[1-9]/', $WordB ) ) {
87 $B2A[ $prePat . $WordB . $postPat ] = $WordA;
90 $B2A[ $prePat . $ucWordB . $postPat ] = $ucWordA;
92 $B2A[ $prePat . $ucB . $postPat ] = $ucA;
99 # init lc and uc, as needed
100 $this->initLcUc( $lcChars, $ucChars );
102 # no regex prefix/suffix needed
103 $this->addMappings( self::MANY_TO_ONE_C2L_MAPPINGS,
105 $this->Latn2CyrlExceptions, $this->Cyrl2LatnExceptions );
106 $this->addMappings( self::MULTI_CASE_MAPPINGS,
107 $this->Cyrl2LatnExceptions, $this->Latn2CyrlExceptions );
108 $this->addMappings( self::EXACT_CASE_MAPPINGS,
109 $this->Cyrl2LatnExceptions, $this->Latn2CyrlExceptions,
true );
111 # load C2L and L2C bidirectional affix mappings
112 $this->addMappings( self::PREFIX_MAPPING,
113 $this->Cyrl2LatnPatterns, $this->Latn2CyrlPatterns,
false,
'/' . self::WB,
'/u' );
114 $this->addMappings( self::SUFFIX_MAPPING,
115 $this->Cyrl2LatnPatterns, $this->Latn2CyrlPatterns,
false,
'/', self::WB .
'/u' );
117 # tack on one-way mappings to the ends of the prefix and suffix patterns
118 $this->Cyrl2LatnPatterns += self::CYRL_TO_LATN_REGEXES;
119 $this->Latn2CyrlPatterns += self::LATN_TO_CYRL_REGEXES;
121 return [ $this->Cyrl2LatnExceptions, $this->Latn2CyrlExceptions, $this->Cyrl2LatnPatterns,
122 $this->Latn2CyrlPatterns, self::CYRL_CLEAN_UP_REGEXES ];
129 private const MANY_TO_ONE_C2L_MAPPINGS = [
130 # Carefully ordered many-to-one mapping.
131 # These are ordered so that the C2L is correct (the later Latin one).
132 # See also the L2C mappings below
133 'fevqülade' =>
'февкъульаде',
'fevqulade' =>
'февкъульаде',
134 'beyude' =>
'бейуде',
'beyüde' =>
'бейуде',
135 'curat' =>
'джурьат',
'cürat' =>
'джурьат',
136 'mesul' =>
'месуль',
'mesül' =>
'месуль',
143 private const MULTI_CASE_MAPPINGS = [
144 #### Cyrillic to Latin
145 'аджыумер' =>
'acıümer',
'аджыусеин' =>
'acıüsein',
'алейкум' =>
'aleyküm',
146 'бозтюс' =>
'boztüs',
'боливия' =>
'boliviya',
'большевик' =>
'bolşevik',
'борис' =>
'boris',
147 'борнен' =>
'bornen',
'бублик' =>
'bublik',
'буддизм' =>
'buddizm',
'буддист' =>
'buddist',
148 'буженина' =>
'bujenina',
'бузкесен' =>
'buzkesen',
'букинист' =>
'bukinist',
149 'буксир' =>
'buksir',
'бульбул' =>
'bülbül',
'бульвар' =>
'bulvar',
'бульдог' =>
'buldog',
150 'бульдозер' =>
'buldozer',
'бульон' =>
'bulyon',
'бумеранг' =>
'bumerang',
151 'бунен' =>
'bunen',
'буннен' =>
'bunnen',
'бус-бутюн' =>
'büs-bütün',
152 'бутерброд' =>
'buterbrod',
'бутилен' =>
'butilen',
'бутилир' =>
'butilir',
153 'буфер' =>
'bufer',
'буфет' =>
'bufet',
'гобелен' =>
'gobelen',
'гомео' =>
'gomeo',
154 'горизонт' =>
'gorizont',
'госпитал' =>
'gospital',
'готтентот' =>
'gottentot',
155 'гофрир' =>
'gofrir',
'губерн' =>
'gubern',
'гуверн' =>
'guvern',
'гугенот' =>
'gugenot',
156 'гуливер' =>
'guliver',
'гуна' =>
'güna',
'гунях' =>
'günâh',
'гургуль' =>
'gürgül',
157 'гуя' =>
'güya',
'дёрткуль' =>
'dörtkül',
'джуньджу' =>
'cüncü',
'ёлнен' =>
'yolnen',
158 'зумбуль' =>
'zümbül',
'ильи' =>
'ilyi',
'ишунь' =>
'işün',
'ковер' =>
'kover',
'код' =>
'kod',
159 'койлю' =>
'köylü',
'кокагъач' =>
'kökağaç',
'кокбаштанкъара' =>
'kökbaştanqara',
160 'кокгогерджин' =>
'kökgögercin',
'кокдогъан' =>
'kökdoğan',
'коккозю' =>
'kökközü',
161 'коккъузгъун' =>
'kökquzğun',
'коклюш' =>
'koklüş',
'кокташ' =>
'köktaş',
162 'коктогъан' =>
'köktoğan',
'коктотай' =>
'köktotay',
'коллег' =>
'kolleg',
163 'коллект' =>
'kollekt',
'коллекц' =>
'kollekts',
'колье' =>
'kolye',
'кольраби' =>
'kolrabi',
164 'кольцов' =>
'koltsov',
'комби' =>
'kombi',
'комеди' =>
'komedi',
'коменда' =>
'komenda',
165 'комета' =>
'kometa',
'комив' =>
'komiv',
'комис' =>
'komis',
'комит' =>
'komit',
166 'комм' =>
'komm',
'коммент' =>
'komment',
'коммерс' =>
'kommers',
'коммерц' =>
'kommerts',
167 'комп' =>
'komp',
'конве' =>
'konve',
'конгени' =>
'kongeni',
'конденс' =>
'kondens',
168 'кондил' =>
'kondil',
'кондитер' =>
'konditer',
'кондиц' =>
'kondits',
'коник' =>
'konik',
169 'конкис' =>
'konkis',
'консерв' =>
'konserv',
'конси' =>
'konsi',
'контейнер' =>
'konteyner',
170 'конти' =>
'konti',
'конфе' =>
'konfe',
'конфи' =>
'konfi',
'конце' =>
'kontse',
171 'конъю' =>
'konyu',
'коньки' =>
'konki',
'коньяк' =>
'konyak',
'копирле' =>
'kopirle',
172 'копия' =>
'kopiya',
'корде' =>
'korde',
'кореиз' =>
'koreiz',
'коренн' =>
'korenn',
173 'корея' =>
'koreya',
'кориа' =>
'koria',
'коридор' =>
'koridor',
'корне' =>
'korne',
174 'корнеев' =>
'korneyev',
'корни' =>
'korni',
'корре' =>
'korre',
'косме' =>
'kosme',
175 'космик' =>
'kosmik',
'костюм' =>
'kostüm',
'котельн' =>
'koteln',
'котир' =>
'kotir',
176 'котлет' =>
'kotlet',
'кочерг' =>
'koçerg',
'коше' =>
'köşe',
'куби' =>
'kubi',
177 'кудрин' =>
'kudrin',
'кузнец' =>
'kuznets',
'кулинар' =>
'kulinar',
'кулич' =>
'kuliç',
178 'кульмин' =>
'kulmin',
'культаш' =>
'kültaş',
'культе' =>
'külte',
'культ' =>
'kult',
179 'куркулет' =>
'kürkület',
'курсив' =>
'kursiv',
'кушет' =>
'kuşet',
'кушку' =>
'küşkü',
180 'куюк' =>
'küyük',
'къолязма' =>
'qolyazma',
'къуртумер' =>
'qurtümer',
181 'къуртусеин' =>
'qurtüsein',
'медьюн' =>
'medyun',
'месули' =>
'mesüli',
182 'мефкуре' =>
'mefküre',
'могедек' =>
'mögedek',
'мумиё' =>
'mumiyo',
'мумиф' =>
'mumif',
183 'муче' =>
'müçe',
'муюз' =>
'müyüz',
'нумюне' =>
'nümüne',
'обел' =>
'obel',
'обер' =>
'ober',
184 'обли' =>
'obli',
'обсе' =>
'obse',
'обт' =>
'obt',
'огне' =>
'ogne',
'одеколон' =>
'odekolon',
185 'одеса' =>
'odesa',
'одесса' =>
'odessa',
'озерки' =>
'ozerki',
'озерн' =>
'ozern',
186 'озёрн' =>
'ozörn',
'озюя' =>
'özüya',
'океан' =>
'okean',
'окси' =>
'oksi',
187 'октет' =>
'oktet',
'олеа' =>
'olea',
'олеи' =>
'olei',
'оленев' =>
'olenev',
'олив' =>
'oliv',
188 'олиг' =>
'olig',
'олимп' =>
'olimp',
'олиф' =>
'olif',
'ольчер' =>
'ölçer',
'омле' =>
'omle',
189 'онен' =>
'onen',
'оннен' =>
'onnen',
'опера' =>
'opera',
'опере' =>
'opere',
190 'оптим' =>
'optim',
'опци' =>
'optsi',
'орби' =>
'orbi',
'орден' =>
'orden',
191 'ордер' =>
'order',
'ордин' =>
'ordin',
'ореа' =>
'orea',
'орех' =>
'oreh',
192 'ориент' =>
'oriyent',
'оркестр' =>
'orkestr',
'орлин' =>
'orlin',
'орни' =>
'orni',
193 'орхи' =>
'orhi',
'осци' =>
'ostsi',
'офис' =>
'ofis',
'офиц' =>
'ofits',
'офсет' =>
'ofset',
194 'очерк' =>
'oçerk',
'оюннен' =>
'oyunnen',
'побед' =>
'pobed',
'полево' =>
'polevo',
195 'поли' =>
'poli',
'полюшко' =>
'polüşko',
'помидор' =>
'pomidor',
'пониз' =>
'poniz',
196 'порфир' =>
'porfir',
'потелов' =>
'potelov',
'потюк' =>
'pötük',
'почетн' =>
'poçetn',
197 'почётн' =>
'poçötn',
'пукле' =>
'pükle',
'пуркю' =>
'pürkü',
'пурумют' =>
'purümüt',
198 'пускул' =>
'püskül',
'пускур' =>
'püskür',
'пусюр' =>
'püsür',
'пуфле' =>
'püfle',
199 'сейитумер' =>
'seyitümer',
'сейитусеин' =>
'seyitüsein',
'сейитягъя' =>
'seyityağya',
200 'сейитягья' =>
'seyityagya',
'сейитяхья' =>
'seyityahya',
'сейитяя' =>
'seyityaya',
201 'сеитумер' =>
'seitümer',
'сеитусеин' =>
'seitüsein',
'сеитягъя' =>
'seityağya',
202 'сеитягья' =>
'seityagya',
'сеитяхья' =>
'seityahya',
'сеитяя' =>
'seityaya',
203 'сурет' =>
'süret',
'увертюра' =>
'uvertüra',
'угле' =>
'ugle',
'узвий' =>
'uzviy',
204 'улица' =>
'ulitsa',
'ультимат' =>
'ultimat',
'ультра' =>
'ultra',
'ульянов' =>
'ulyanov',
205 'универ' =>
'univer',
'уник' =>
'unik',
'унис' =>
'unis',
'унит' =>
'unit',
'униф' =>
'unif',
206 'унтер' =>
'unter',
'урьян' =>
'uryan',
'утил' =>
'util',
'уткин' =>
'utkin',
207 'учебн' =>
'uçebn',
'шовини' =>
'şovini',
'шоссе' =>
'şosse',
'шубин' =>
'şubin',
208 'шунен' =>
'şunen',
'шуннен' =>
'şunnen',
'шунчюн' =>
'şunçün',
'щёлкино' =>
'şçolkino',
209 'эмирусеин' =>
'emirüsein',
'юзбашы' =>
'yüzbaşı',
'юзйыл' =>
'yüzyıl',
'юртер' =>
'yurter',
210 'ющенко' =>
'yuşçenko',
212 ### Carefully ordered many-to-one mappings
213 # these are ordered so L2C is correct (the later Cyrillic one)
214 # see also self::MANY_TO_ONE_C2L_MAPPINGS above for C2L
215 'шофер' =>
'şoför',
'шофёр' =>
'şoför',
216 'бугун' =>
'bugün',
'бугунь' =>
'bugün',
217 'демирёл' =>
'demiryol',
'демиръёл' =>
'demiryol',
218 'гонъюл' =>
'göñül',
'гонъюль' =>
'göñül',
219 'коккоз' =>
'kökköz',
'коккозь' =>
'kökköz',
220 'корбекул' =>
'körbekül',
'корьбекул' =>
'körbekül',
'корьбекуль' =>
'körbekül',
221 'муур' =>
'müür',
'муурь' =>
'müür',
222 'оригинал' =>
'original',
'оригиналь' =>
'original',
223 'пускю' =>
'püskü',
'пуськю' =>
'püskü',
224 'къарагоз' =>
'qaragöz',
'къарагозь' =>
'qaragöz',
226 #### Latin to Cyrillic (deduped from above)
230 'актуаль' =>
'aktual',
'диагональ' =>
'diagonal',
'документаль' =>
'dokumental',
231 'эмсаль' =>
'emsal',
'фааль' =>
'faal',
'феодаль' =>
'feodal',
'фестиваль' =>
'festival',
232 'горизонталь' =>
'gorizontal',
'хроникаль' =>
'hronikal',
'идеаль' =>
'ideal',
233 'инструменталь' =>
'instrumental',
'икъмаль' =>
'iqmal',
'икъбаль' =>
'iqbal',
234 'истикъбаль' =>
'istiqbal',
'истикъляль' =>
'istiqlâl',
'италия' =>
'italiya',
235 'италья' =>
'italya',
'ишгъаль' =>
'işğal',
'кафедраль' =>
'kafedral',
'казуаль' =>
'kazual',
236 'коллегиаль' =>
'kollegial',
'колоссаль' =>
'kolossal',
'коммуналь' =>
'kommunal',
237 'кординаль' =>
'kordinal',
'криминаль' =>
'kriminal',
'легаль' =>
'legal',
238 'леталь' =>
'letal',
'либераль' =>
'liberal',
'локаль' =>
'lokal',
239 'магистраль' =>
'magistral',
'материаль' =>
'material',
'машиналь' =>
'maşinal',
240 'меаль' =>
'meal',
'медальон' =>
'medalyon',
'медаль' =>
'medal',
241 'меридиональ' =>
'meridional',
'мешъаль' =>
'meşal',
'минераль' =>
'mineral',
242 'минималь' =>
'minimal',
'мисаль' =>
'misal',
'модаль' =>
'modal',
'музыкаль' =>
'muzıkal',
243 'номиналь' =>
'nominal',
'нормаль' =>
'normal',
'оптималь' =>
'optimal',
244 'орбиталь' =>
'orbital',
'педаль' =>
'pedal',
'пропорциональ' =>
'proportsional',
245 'профессиональ' =>
'professional',
'радикаль' =>
'radikal',
'рациональ' =>
'ratsional',
246 'реаль' =>
'real',
'региональ' =>
'regional',
'суаль' =>
'sual',
'шималь' =>
'şimal',
247 'территориаль' =>
'territorial',
'тимсаль' =>
'timsal',
'тоталь' =>
'total',
248 'уникаль' =>
'unikal',
'универсаль' =>
'universal',
'вертикаль' =>
'vertikal',
249 'виртуаль' =>
'virtual',
'визуаль' =>
'vizual',
'вуаль' =>
'vual',
'зональ' =>
'zonal',
250 'зуаль' =>
'zual',
'италь' =>
'ital',
252 # слова с мягким знаком перед а, о, у, э
253 # Words with a soft sign before а, о, у, э
254 'бильакис' =>
'bilakis',
'маальэсеф' =>
'maalesef',
'мельун' =>
'melun',
'озьара' =>
'özara',
255 'вельасыл' =>
'velasıl',
'ельаякъ' =>
'yelayaq',
257 # другие слова с мягким знаком
258 # Other words with a soft sign
259 'альбатрос' =>
'albatros',
'альбинос' =>
'albinos',
'альбом' =>
'albom',
260 'альбумин' =>
'albumin',
'алфавит' =>
'alfavit',
'альфа' =>
'alfa',
'альманах' =>
'almanah',
261 'альпинист' =>
'alpinist',
'альтерн' =>
'altern',
'альтру' =>
'altru',
262 'альвеола' =>
'alveola',
'ансамбль' =>
'ansambl',
'аньане' =>
'anane',
'асфальт' =>
'asfalt',
263 'бальнео' =>
'balneo',
'баарь' =>
'baar',
'базальт' =>
'bazalt',
'бинокль' =>
'binokl',
264 'девальв' =>
'devalv',
'факульт' =>
'fakult',
'фальсиф' =>
'falsif',
'фольклор' =>
'folklor',
265 'гальван' =>
'galvan',
'геральд' =>
'gerald',
'женьшень' =>
'jenşen',
266 'инвентарь' =>
'inventar',
'кальк' =>
'kalk',
'кальмар' =>
'kalmar',
'консульт' =>
'konsult',
267 'контроль' =>
'kontrol',
'культур' =>
'kultur',
'лагерь' =>
'lager',
'макъбуль' =>
'maqbul',
268 'макъуль' =>
'maqul',
'мальт' =>
'malt',
'мальземе' =>
'malzeme',
'меджуль' =>
'mecul',
269 'мешгуль' =>
'meşgül',
'мешгъуль' =>
'meşğul',
'мульти' =>
'multi',
270 'мусульман' =>
'musulman',
'нефть' =>
'neft',
'пальто' =>
'palto',
'пароль' =>
'parol',
271 'патруль' =>
'patrul',
'пенальти' =>
'penalti',
'къальби' =>
'qalbi',
'къальпке' =>
'qalpke',
272 'къальплер' =>
'qalpler',
'къальпни' =>
'qalpni',
'къальпте' =>
'qalpte',
'къаарь' =>
'qaar',
273 'ресуль' =>
'resul',
'рыцарь' =>
'rıtsar',
'рояль' =>
'royal',
'саарь' =>
'saar',
274 'спираль' =>
'spiral',
'сульх' =>
'sulh',
'сумбуль' =>
'sumbul',
'суньий' =>
'suniy',
275 'темаюль' =>
'temayul',
'шампунь' =>
'şampun',
'вальс' =>
'vals',
'вальц' =>
'valts',
276 'ведомость' =>
'vedomost',
'зулькъарнейн' =>
'zulqarneyn',
'январь' =>
'yanvar',
277 'февраль' =>
'fevral',
'июнь' =>
'iyün',
'сентябрь' =>
'sentâbr',
'октябрь' =>
'oktâbr',
278 'ноябрь' =>
'noyabr',
'декабрь' =>
'dekabr',
280 # слова с твёрдым знаком
281 # Words with a solid sign
282 'бидъат' =>
'bidat',
'бузъюрек' =>
'buzyürek',
'атешъюрек' =>
'ateşyürek',
283 'алъянакъ' =>
'alyanaq',
'инъекц' =>
'inyekts',
'мефъум' =>
'mefum',
'мешъум' =>
'meşum',
284 'объект' =>
'obyekt',
'разъезд' =>
'razyezd',
'субъект' =>
'subyekt',
'хавъяр' =>
'havyar',
289 'ящик' =>
'yaşçik',
'мещан' =>
'meşçan',
293 'акциз' =>
'aktsiz',
'ацет' =>
'atset',
'блиц' =>
'blits',
'бруцеллёз' =>
'brutsellöz',
294 'доцент' =>
'dotsent',
'фармацевт' =>
'farmatsevt',
'глицер' =>
'glitser',
295 'люцерна' =>
'lütserna',
'лицей' =>
'litsey',
'меццо' =>
'metstso',
'наци' =>
'natsi',
296 'проце' =>
'protse',
'рецеп' =>
'retsep',
'реценз' =>
'retsenz',
'теплица' =>
'teplitsa',
297 'вице' =>
'vitse',
'швейцар' =>
'şveytsar',
'богородиц' =>
'bogorodits',
298 'бруцел' =>
'brutsel',
'дацюк' =>
'datsük',
'доницетти' =>
'donitsetti',
299 'драцена' =>
'dratsena',
'контрацеп' =>
'kontratsep',
'коцюб' =>
'kotsüb',
300 'меценат' =>
'metsenat',
'мицел' =>
'mitsel',
'моцарт' =>
'motsart',
'плац' =>
'plats',
301 'плацен' =>
'platsen',
'прецедент' =>
'pretsedent',
'прецес' =>
'pretses',
302 'прицеп' =>
'pritsep',
'спец' =>
'spets',
'троиц' =>
'troits',
'шприц' =>
'şprits',
303 'эпицентр' =>
'epitsentr',
'яценюк' =>
'yatsenük',
307 'агъартс' =>
'ağarts',
'агъыртс' =>
'ağırts',
'бильдиртс' =>
'bildirts',
'битсин' =>
'bitsin',
308 'буюльтс' =>
'büyülts',
'буютс' =>
'büyüts',
'гебертс' =>
'geberts',
'делиртс' =>
'delirts',
309 'эгрильтс' =>
'egrilts',
'эксильтс' =>
'eksilts',
'эшитс' =>
'eşits',
'иритс' =>
'irits',
310 'иситс' =>
'isits',
'ичиртс' =>
'içirts',
'кертсин' =>
'kertsin',
'кенишлетс' =>
'kenişlets',
311 'кийсетс' =>
'kiysets',
'копюртс' =>
'köpürts',
'косьтертс' =>
'kösterts',
312 'кучертс' =>
'küçerts',
'кучюльтс' =>
'küçülts',
'пертсин' =>
'pertsin',
'къайтс' =>
'qayts',
313 'къутсуз' =>
'qutsuz',
'орьтс' =>
'örts',
'отьс' =>
'öts',
'тартс' =>
'tarts',
314 'тутсун' =>
'tutsun',
'тюнъюльтс' =>
'tüñülts',
'тюртс' =>
'türts',
'янъартс' =>
'yañarts',
315 'ебертс' =>
'yeberts',
'ешертс' =>
'yeşerts',
'йиритс' =>
'yirits',
318 # different exceptions
319 'бюджет' =>
'bücet',
'бюллет' =>
'büllet',
'бюро' =>
'büro',
'бюст' =>
'büst',
320 'диалог' =>
'dialog',
'ханымэфенди' =>
'hanımefendi',
'каньон' =>
'kanyon',
321 'кирил' =>
'kiril',
'кирилл' =>
'kirill',
'кёрджа' =>
'körca',
'коy' =>
'köy',
322 'кулеръюзь' =>
'küleryüz',
'маалле' =>
'маальle',
'майор' =>
'mayor',
'маниал' =>
'manиаль',
323 'нормала' =>
'нормальa',
'проект' =>
'proekt',
'район' =>
'rayon',
'сойады' =>
'soyadı',
324 'спортсмен' =>
'sportsmen',
'услюп' =>
'üslüp',
'услюб' =>
'üslüb',
'вакъиал' =>
'vaqиаль',
325 'юзйыллыкъ' =>
'yüzyıllıq',
'койот' =>
'koyot',
329 'адольф' =>
'adolf',
'альберт' =>
'albert',
'бешуй' =>
'beşüy',
'флотск' =>
'flotsk',
330 'гайана' =>
'gayana',
'грэсовский' =>
'gresovskiy',
'гриц' =>
'grits',
'гурджи' =>
'gürci',
331 'игорь' =>
'igor',
'ильич' =>
'ilyiç',
'ильин' =>
'ilyin',
'исмаил' =>
'ismail',
332 'киттс' =>
'kitts',
'комсомольск' =>
'komsomolsk',
'корьбекулю' =>
'körbekülü',
333 'куницын' =>
'kunitsın',
'львив' =>
'lviv',
'львов' =>
'lvov',
'марьино' =>
'maryino',
334 'махульдюр' =>
'mahuldür',
'павел' =>
'pavel',
'пантикапейон' =>
'pantikapeyon',
335 'къуртсейит' =>
'qurtseyit',
'къуртсеит' =>
'qurtseit',
'смаил' =>
'smail',
336 'советск' =>
'sovetsk',
'шемьи-заде' =>
'şemi-zade',
'тсвана' =>
'tsvana',
337 'учьэвли' =>
'üçevli',
'йохан' =>
'yohan',
'йорк' =>
'york',
'винныця' =>
'vinnıtsâ',
338 'винница' =>
'vinnitsa',
'хмельницк' =>
'hmelnitsk',
'хмельныцк' =>
'hmelnıtsk',
339 'зайце' =>
'zaytse',
'чистеньк' =>
'çistenk',
'кольчуг' =>
'kolçug',
'ручьи' =>
'ruçyi',
340 'ботсвана' =>
'botsvana',
'большой' =>
'bolşoy',
'большое' =>
'bolşoye',
341 'большая' =>
'bolşaya',
'ущелье' =>
'uşçelye',
'ущельное' =>
'uşçelnoye',
342 'предущельное' =>
'preduşçelnoye',
'новенькое' =>
'novenkoye',
'новосельц' =>
'novoselts',
343 'мелко' =>
'melko',
'овощ' =>
'ovoşç',
'перепёлк' =>
'perepölk',
'рощин' =>
'roşçin',
344 'братск' =>
'bratsk',
'краснофлотск' =>
'krasnoflotsk',
'синицин' =>
'sinitsin',
345 'синицын' =>
'sinitsın',
'льгов' =>
'lgov',
'желто' =>
'jelto',
'жёлт' =>
'jölt',
346 'пермь' =>
'perm',
'солдатск' =>
'soldatsk',
'кольцо' =>
'koltso',
'шелко' =>
'şelko',
347 'охотск' =>
'ohotsk',
'марий эл' =>
'mariy el',
'мариуполь' =>
'mariupol',
348 'белгород' =>
'belgorod',
'иркутск' =>
'irkutsk',
'Иркутск' =>
'İrkutsk',
'орёл' =>
'oröl',
349 'рязанск' =>
'râzansk',
'рязань' =>
'râzan',
'тверск' =>
'tversk',
'тверь' =>
'tver',
350 'ярославль' =>
'yaroslavl',
'благовеще' =>
'blagoveşçe',
'мальдив' =>
'maldiv',
351 'бальбек' =>
'balbek',
'альчик' =>
'alçik',
'харьков' =>
'harkov',
'волынск' =>
'volınsk',
359 private const EXACT_CASE_MAPPINGS = [
362 'ОБСЕ' =>
'OBSE',
'КъМДж' =>
'QMC',
'КъДж' =>
'QC',
'КъАЭ' =>
'QAE',
'ГъСМК' =>
'ĞSMK',
363 'ШСДжБ' =>
'ŞSCB',
'КъМШСДж' =>
'QMŞSC',
'КъАССР' =>
'QASSR',
'КъДМПУ' =>
'QDMPU',
374 private const SUFFIX_MAPPING = [
376 'иаль' =>
'ial',
'нуль' =>
'nul',
'кой' =>
'köy',
'койнинъ' =>
'köyniñ',
'койни' =>
'köyni',
377 'койге' =>
'köyge',
'койде' =>
'köyde',
'койдеки' =>
'köydeki',
'койден' =>
'köyden',
378 'козь' =>
'köz',
'-юнджи' =>
'-ünci',
'-юнджиде' =>
'-üncide',
'-юнджиден' =>
'-ünciden',
380 # originally L2C, here swapped
381 'льная' =>
'lnaya',
'льное' =>
'lnoye',
'льный' =>
'lnıy',
'льний' =>
'lniy',
382 'льская' =>
'lskaya',
'льский' =>
'lskiy',
'льское' =>
'lskoye',
'ополь' =>
'opol',
383 'щее' =>
'şçeye',
'щий' =>
'şçiy',
'щая' =>
'şçaya',
'цепс' =>
'tseps',
392 private const PREFIX_MAPPING = [
394 'буюк([^ъ])' =>
'büyük$1',
'бую([гдйлмнпрстчшc])(и)' =>
'büyü$1$2',
395 'буют([^ыа])' =>
'büyüt$1',
'джонк([^ъ])' =>
'cönk$1',
'коюм' =>
'köyüm',
'коюнъ' =>
'köyüñ',
396 'коюн([ди])' =>
'köyün$1',
'куе' =>
'küye',
'куркке' =>
'kürkke',
'куркни' =>
'kürkni',
397 'куркте' =>
'kürkte',
'куркчю' =>
'kürkçü',
'кою' =>
'köyü',
400 # арабизмы на муи- муэ- / Arabic муи- муэ-
401 'му([иэИЭ])' =>
'mü$1',
403 # originally L2C, here swapped
404 'роль$1' =>
'rol([^ü]|' . self::WB .
')',
405 'усть$1' =>
'üst([^ü]|' . self::WB .
')',
408 'ком-кок' =>
'köm-kök',
411 private const CYRL_TO_LATN_REGEXES = [
412 # относятся ко всему слову
418 '/' . self::WB .
'КъЮШ' . self::WB .
'/u' =>
'QYŞ',
419 '/' . self::WB .
'ЮШ' . self::WB .
'/u' =>
'YŞ',
421 '/' . self::WB .
'кок' . self::WB .
'/u' =>
'kök',
422 '/' . self::WB .
'Кок' . self::WB .
'/u' =>
'Kök',
423 '/' . self::WB .
'КОК' . self::WB .
'/u' =>
'KÖK',
424 '/' . self::WB .
'ком-кок' . self::WB .
'/u' =>
'köm-kök',
425 '/' . self::WB .
'Ком-кок' . self::WB .
'/u' =>
'Köm-kök',
426 '/' . self::WB .
'КОМ-КОК' . self::WB .
'/u' =>
'KÖM-KÖK',
428 '/' . self::WB .
'коп' . self::WB .
'/u' =>
'köp',
429 '/' . self::WB .
'Коп' . self::WB .
'/u' =>
'Köp',
430 '/' . self::WB .
'КОП' . self::WB .
'/u' =>
'KÖP',
432 '/' . self::WB .
'курк' . self::WB .
'/u' =>
'kürk',
433 '/' . self::WB .
'Курк' . self::WB .
'/u' =>
'Kürk',
434 '/' . self::WB .
'КУРК' . self::WB .
'/u' =>
'KÜRK',
436 '/' . self::WB .
'ог' . self::WB .
'/u' =>
'ög',
437 '/' . self::WB .
'Ог' . self::WB .
'/u' =>
'Ög',
438 '/' . self::WB .
'ОГ' . self::WB .
'/u' =>
'ÖG',
440 '/' . self::WB .
'юрип' . self::WB .
'/u' =>
'yürip',
441 '/' . self::WB .
'Юрип' . self::WB .
'/u' =>
'Yürip',
442 '/' . self::WB .
'ЮРИП' . self::WB .
'/u' =>
'YÜRİP',
444 '/' . self::WB .
'юз' . self::WB .
'/u' =>
'yüz',
445 '/' . self::WB .
'Юз' . self::WB .
'/u' =>
'Yüz',
446 '/' . self::WB .
'ЮЗ' . self::WB .
'/u' =>
'YÜZ',
448 '/' . self::WB .
'юк' . self::WB .
'/u' =>
'yük',
449 '/' . self::WB .
'Юк' . self::WB .
'/u' =>
'Yük',
450 '/' . self::WB .
'ЮК' . self::WB .
'/u' =>
'YÜK',
452 '/' . self::WB .
'буюп' . self::WB .
'/u' =>
'büyüp',
453 '/' . self::WB .
'Буюп' . self::WB .
'/u' =>
'Büyüp',
454 '/' . self::WB .
'БУЮП' . self::WB .
'/u' =>
'BÜYÜP',
456 '/' . self::WB .
'буюк' . self::WB .
'/u' =>
'büyük',
457 '/' . self::WB .
'Буюк' . self::WB .
'/u' =>
'Büyük',
458 '/' . self::WB .
'БУЮК' . self::WB .
'/u' =>
'BÜYÜK',
460 '/' . self::WB .
'джонк' . self::WB .
'/u' =>
'cönk',
461 '/' . self::WB .
'Джонк' . self::WB .
'/u' =>
'Cönk',
462 '/' . self::WB .
'ДЖОНК' . self::WB .
'/u' =>
'CÖNK',
463 '/' . self::WB .
'джонкю' . self::WB .
'/u' =>
'cönkü',
464 '/' . self::WB .
'Джонкю' . self::WB .
'/u' =>
'Cönkü',
465 '/' . self::WB .
'ДЖОНКЮ' . self::WB .
'/u' =>
'CÖNKÜ',
467 '/' . self::WB .
'куркчи/u' =>
'kürkçi',
468 '/' . self::WB .
'Куркчи/u' =>
'Kürkçi',
469 '/' . self::WB .
'КУРКЧИ/u' =>
'KÜRKÇI',
471 '/' . self::WB .
'устке' . self::WB .
'/u' =>
'üstke',
472 '/' . self::WB .
'Устке' . self::WB .
'/u' =>
'Üstke',
473 '/' . self::WB .
'УСТКЕ' . self::WB .
'/u' =>
'ÜSTKE',
474 '/' . self::WB .
'устте' . self::WB .
'/u' =>
'üstte',
475 '/' . self::WB .
'Устте' . self::WB .
'/u' =>
'Üstte',
476 '/' . self::WB .
'УСТТЕ' . self::WB .
'/u' =>
'ÜSTTE',
477 '/' . self::WB .
'усттен' . self::WB .
'/u' =>
'üstten',
478 '/' . self::WB .
'Усттен' . self::WB .
'/u' =>
'Üstten',
479 '/' . self::WB .
'УСТТЕН' . self::WB .
'/u' =>
'ÜSTTEN',
481 # отдельно стоящие Ё и Я
482 # stand-alone Ё and Я
483 '/' . self::WB .
'Я' . self::WB .
'/u' =>
'Ya',
484 '/' . self::WB .
'Ё' . self::WB .
'/u' =>
'Yo',
486 # относятся к началу слова
488 '/' . self::WB .
'КъЮШн/u' =>
'QYŞn',
489 '/' . self::WB .
'ЮШн/u' =>
'YŞn',
491 # need to convert digraphs (гъ, къ, нъ, дж) now to match patterns
511 '/' . self::WB .
'о([' .
Crh::C_CONS .
'])([еиэюьü])/u' =>
'ö$1$2',
513 '/' . self::WB .
'О([' .
Crh::C_CONS .
'])([еиэюьüЕИЭЮЬÜ])/u' =>
'Ö$1$2',
519 '/' . self::WB .
'ё([' .
Crh::C_CONS .
'])([ьеюü])/u' =>
'yö$1$2',
520 '/' . self::WB .
'Ё([' .
Crh::C_CONS_LC .
'])([ьеюü])/u' =>
'Yö$1$2',
521 '/' . self::WB .
'Ё([' .
Crh::C_CONS_UC .
'])([ЬЕЮÜ])/u' =>
'YÖ$1$2',
535 '/' . self::WB .
'у([' .
Crh::C_CONS .
'])([еиэюьü])/u' =>
'ü$1$2',
536 '/' . self::WB .
'ую([' .
Crh::C_CONS .
'])([еиэюьü])/u' =>
'üyü$1$2',
538 '/' . self::WB .
'У([' .
Crh::C_CONS .
'])([еиэюьüЕИЭЮЬÜ])/u' =>
'Ü$1$2',
539 '/' . self::WB .
'Ую([' .
Crh::C_CONS .
'])([еиэюьü])/u' =>
'Üyü$1$2',
540 '/' . self::WB .
'УЮ([' .
Crh::C_CONS .
'])([еиэюьü])/u' =>
'ÜYÜ$1$2',
549 '/' . self::WB .
'([аыоуеиёюАЫОУЕИЁЮ]?)ю([' .
Crh::C_CONS .
'])([ьеюü])/u' =>
'$1yü$2$3',
550 '/' . self::WB .
'([АЫОУЕИЁЮ]?)Ю([' .
Crh::C_CONS_LC .
'])([ьеюü])/u' =>
'$1Yü$2$3',
551 '/' . self::WB .
'([АЫОУЕИЁЮ]?)Ю([' .
Crh::C_CONS_UC .
'])([ЬЕЮÜ])/u' =>
'$1YÜ$2$3',
554 '/' . self::WB .
'е/u' =>
'ye',
555 '/' . self::WB .
'Е([' .
Crh::C_LC .
'cğñqöü])/u' =>
'Ye$1',
556 '/' . self::WB .
'Е([' .
Crh::C_UC .
'CĞÑQÖÜ])/u' =>
'YE$1',
557 '/' . self::WB .
'я/u' =>
'ya',
558 '/' . self::WB .
'Я([' .
Crh::C_LC .
'cğñqöü])/u' =>
'Ya$1',
559 '/' . self::WB .
'Я([' .
Crh::C_UC .
'CĞÑQÖÜ])/u' =>
'YA$1',
560 '/([аеёиоуыэюяйьъaeöüАЕЁИОУЫЭЮЯЙЬЪAEÖÜ])е/u' =>
'$1ye',
561 '/([аеёиоуыэюяйьъaeöüАЕЁИОУЫЭЮЯЙЬЪAEÖÜ])Е([' .
Crh::C_LC .
'cğñqöü])/u' =>
'$1Ye$2',
562 '/([аеёиоуыэюяйьъaeöüАЕЁИОУЫЭЮЯЙЬЪAEÖÜ])Е([' .
Crh::C_UC .
'CĞÑQÖÜ])/u' =>
'$1YE$2',
563 '/([аеёиоуыэюяйьъaeöüğqАЕЁИОУЫЭЮЯЙЬЪAEÖÜĞQ])я/u' =>
'$1ya',
564 '/([аеёиоуыэюяйьъaeöüğqАЕЁИОУЫЭЮЯЙЬЪAEÖÜĞQ])Я([' .
Crh::C_LC .
'cğñqöü])/u' =>
'$1Ya$2',
565 '/([аеёиоуыэюяйьъaeöüğqАЕЁИОУЫЭЮЯЙЬЪAEÖÜĞQ])Я([' .
Crh::C_UC .
'CĞÑQÖÜ])/u' =>
'$1YA$2',
567 # не зависят от места в слове
568 # position independent
575 '/козь([^я])/u' =>
'köz$1',
576 '/Козь([^я])/u' =>
'Köz$1',
577 '/КОЗЬ([^Я])/u' =>
'KÖZ$1',
579 # Ö, Ü 1-й заход: ё, ю после согласных > ö, ü
580 # Ö, Ü 1st instance: ё, ю after consonants > ö, ü
586 # остальные вхождения о, у, ё, ю
587 # other occurrences of о, у, ё, ю
588 '/Ё([' .
Crh::C_UC .
'CĞÑQÖÜ])/u' =>
'YO$1',
589 '/Ю([' .
Crh::C_UC .
'CĞÑQÖÜ])/u' =>
'YU$1',
592 '/Ц([' .
Crh::C_UC .
'CĞÑQÖÜ])/u' =>
'TS$1',
593 '/Щ([' .
Crh::C_UC .
'CĞÑQÖÜ])/u' =>
'ŞÇ$1',
596 private const LATN_TO_CYRL_REGEXES = [
600 '/' . self::WB .
'an' . self::WB .
'/u' =>
'ань',
601 '/' . self::WB .
'An' . self::WB .
'/u' =>
'Ань',
602 '/' . self::WB .
'AN' . self::WB .
'/u' =>
'АНЬ',
603 '/' . self::WB .
'ange' . self::WB .
'/u' =>
'аньге',
604 '/' . self::WB .
'Ange' . self::WB .
'/u' =>
'Аньге',
605 '/' . self::WB .
'ANGE' . self::WB .
'/u' =>
'АНЬГЕ',
606 '/' . self::WB .
'ande' . self::WB .
'/u' =>
'аньде',
607 '/' . self::WB .
'Ande' . self::WB .
'/u' =>
'Аньде',
608 '/' . self::WB .
'ANDE' . self::WB .
'/u' =>
'АНЬДЕ',
609 '/' . self::WB .
'anki' . self::WB .
'/u' =>
'аньки',
610 '/' . self::WB .
'Anki' . self::WB .
'/u' =>
'Аньки',
611 '/' . self::WB .
'ANKİ' . self::WB .
'/u' =>
'АНЬКИ',
612 '/' . self::WB .
'deral' . self::WB .
'/u' =>
'деръал',
613 '/' . self::WB .
'Deral' . self::WB .
'/u' =>
'Деръал',
614 '/' . self::WB .
'DERAL' . self::WB .
'/u' =>
'ДЕРЪАЛ',
615 '/' . self::WB .
'kör' . self::WB .
'/u' =>
'кёр',
616 '/' . self::WB .
'Kör' . self::WB .
'/u' =>
'Кёр',
617 '/' . self::WB .
'KÖR' . self::WB .
'/u' =>
'КЁР',
618 '/' . self::WB .
'mer' . self::WB .
'/u' =>
'мэр',
619 '/' . self::WB .
'Mer' . self::WB .
'/u' =>
'Мэр',
620 '/' . self::WB .
'MER' . self::WB .
'/u' =>
'МЭР',
622 '/' . self::WB .
'cönk/u' =>
'джонк',
623 '/' . self::WB .
'Cönk/u' =>
'Джонк',
624 '/' . self::WB .
'CÖNK/u' =>
'ДЖОНК',
626 # (y)etsin -> етсин/этсин
627 # note that target starts with CYRILLIC е/Е!
628 '/yetsin/u' =>
'етсин',
629 '/Yetsin/u' =>
'Етсин',
630 '/YETSİN/u' =>
'ЕТСИН',
632 # note that target starts with LATIN e/E!
633 # (other transformations will determine CYRILLIC е/э as needed)
634 '/etsin/u' =>
'eтсин',
635 '/Etsin/u' =>
'Eтсин',
636 '/ETSİN/u' =>
'EТСИН',
638 # буква Ё - первый заход
639 # расставляем Ь после согласных
644 '/' . self::WB .
'AQŞ([^AEI]|' . self::WB .
')/u' =>
'АКъШ$1',
646 # буква Ю - первый заход
647 # расставляем Ь после согласных
662 # ö и ü в начале слова
663 # случаи, когда нужен Ь
671 '/ts' . self::WB .
'/u' =>
'ц',
672 '/şç' . self::WB .
'/u' =>
'щ',
673 '/Ş[çÇ]' . self::WB .
'/u' =>
'Щ',
674 '/T[sS]' . self::WB .
'/u' =>
'Ц',
681 # относятся к началу слова
682 '/' . self::WB .
'ts/u' =>
'ц',
683 '/' . self::WB .
'T[sS]/u' =>
'Ц',
685 '/' . self::WB .
'şç/u' =>
'щ',
686 '/' . self::WB .
'Ş[çÇ]/u' =>
'Щ',
689 '/(' . self::WB .
'|[' .
Crh::L_VOW .
'аеэяАЕЭЯ])e/u' =>
'$1э',
690 '/(' . self::WB .
'|[' .
Crh::L_VOW_UC .
'АЕЭЯ])E/u' =>
'$1Э',
697 '/' . self::WB .
'ö/u' =>
'о',
698 '/' . self::WB .
'Ö/u' =>
'О',
699 '/' . self::WB .
'ü/u' =>
'у',
700 '/' . self::WB .
'Ü/u' =>
'У',
702 # некоторые исключения
704 '/maal([^e])/u' =>
'мааль$1',
705 '/Maal([^e])/u' =>
'Мааль$1',
706 '/MAAL([^E])/u' =>
'МААЛЬ$1',
707 '/küf([^eü])/u' =>
'куфь$1',
708 '/Küf([^eü])/u' =>
'Куфь$1',
709 '/KÜF([^EÜ])/u' =>
'КУФЬ$1',
710 '/köz([^eü])/u' =>
'козь$1',
711 '/Köz([^eü])/u' =>
'Козь$1',
712 '/KÖZ([^EÜ])/u' =>
'КОЗЬ$1',
717 # некоторые случаи употребления Ц
718 '/tsi([^zñ])/u' =>
'ци$1',
719 '/T[sS][iİ]([^zZñÑ])/u' =>
'ЦИ$1',
720 '/ts([ou])/u' =>
'ц$1',
721 '/T[sS]([oOuU])/u' =>
'Ц$1',
726 '/tsиал/u' =>
'циал',
727 '/TSИАЛ/u' =>
'ЦИАЛ',
730 # remove ьi (note Cyrillic ь and Latin i)
731 '/[ьЬ]([iİ])/u' =>
'$1',
739 # расставляем Ь перед Ё
740 # place Ь in front of Ё
743 # оставшиеся вхождения yo и yö
744 # remaining occurrences of yo and yö
746 '/[yY][oOöÖ]/u' =>
'Ё',
748 # расставляем Ь перед Ю
749 # place Ь in front of Ю
752 # оставшиеся вхождения yu и yü
753 # remaining occurrences of yu and yü
755 '/[yY][uUüÜ]/u' =>
'Ю',
758 # remove ьa (note Cyrillic ь and Latin a)
759 '/[ьЬ]([aA])/u' =>
'$1',
777 private const CYRL_CLEAN_UP_REGEXES = [
778 '/([клнрст])ь\1/u' =>
'$1$1',
779 '/([КЛНРСТ])Ь\1/u' =>
'$1$1',
791 '/[ьЬ]([гдклмнпрстчшГДКЛМНПРСТЧШ])ы/u' =>
'$1ы',
792 '/Ь([гдклмнпрстчшГДКЛМНПРСТЧШ])Ы/u' =>
'$1Ы',
793 '/[ьЬ]([гкнГКН])([ъЪ])ы/u' =>
'$1$2ы',
794 '/Ь([ГКН])ЪЫ/u' =>
'$1ЪЫ',
801 # частичное решение проблемы слова юз - 100
802 # Partial solution to the problem of the word юз ("100")
803 # notice that these are cross-word patterns
804 '/эки юзь/u' =>
'эки юз',
'/Эки юзь/u' =>
'Эки юз',
'/ЭКИ ЮЗЬ/u' =>
'ЭКИ ЮЗ',
805 '/учь юзь/u' =>
'учь юз',
'/Учь юзь/u' =>
'Учь юз',
'/УЧЬ ЮЗЬ/u' =>
'УЧЬ ЮЗ',
806 '/дёрт юзь/u' =>
'дёрт юз',
'/Дёрт юзь/u' =>
'Дёрт юз',
'/ДЁРТ ЮЗЬ/u' =>
'ДЁРТ ЮЗ',
807 '/беш юзь/u' =>
'беш юз',
'/Беш юзь/u' =>
'Беш юз',
'/БЕШ ЮЗЬ/u' =>
'БЕШ ЮЗ',
808 '/алты юзь/u' =>
'алты юз',
'/Алты юзь/u' =>
'Алты юз',
'/АЛТЫ ЮЗЬ/u' =>
'АЛТЫ ЮЗ',
809 '/еди юзь/u' =>
'еди юз',
'/Еди юзь/u' =>
'Еди юз',
'/ЕДИ ЮЗЬ/u' =>
'ЕДИ ЮЗ',
810 '/секиз юзь/u' =>
'секиз юз',
'/Секиз юзь/u' =>
'Секиз юз',
'/СЕКИЗ ЮЗЬ/u' =>
'СЕКИЗ ЮЗ',
811 '/докъуз юзь/u' =>
'докъуз юз',
'/Докъуз юзь/u' =>
'Докъуз юз',
'/ДОКЪУЗ ЮЗЬ/u' =>
'ДОКЪУЗ ЮЗ',