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