@whiteslove/parsing-lexicon 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +137 -0
  3. package/index.d.ts +375 -0
  4. package/package.json +75 -0
  5. package/src/central-asia-locations.js +211 -0
  6. package/src/central-asia.js +233 -0
  7. package/src/contact.d.ts +44 -0
  8. package/src/contact.js +159 -0
  9. package/src/countries.js +175 -0
  10. package/src/country-context.d.ts +10 -0
  11. package/src/country-context.js +22 -0
  12. package/src/currency.d.ts +14 -0
  13. package/src/currency.js +66 -0
  14. package/src/geo.js +169 -0
  15. package/src/geography-central-asia.js +42 -0
  16. package/src/geography-detection.d.ts +14 -0
  17. package/src/geography-detection.js +64 -0
  18. package/src/geography-display.d.ts +13 -0
  19. package/src/geography-display.js +113 -0
  20. package/src/geography.js +210 -0
  21. package/src/hiring-advanced.js +147 -0
  22. package/src/hiring-candidate-fields.d.ts +9 -0
  23. package/src/hiring-candidate-fields.js +92 -0
  24. package/src/hiring-context.d.ts +64 -0
  25. package/src/hiring-context.js +412 -0
  26. package/src/hiring-language-extensions.d.ts +19 -0
  27. package/src/hiring-language-extensions.js +139 -0
  28. package/src/hiring-languages.js +135 -0
  29. package/src/hiring-location-fields.d.ts +3 -0
  30. package/src/hiring-location-fields.js +53 -0
  31. package/src/hiring-professions-ro.js +191 -0
  32. package/src/hiring-professions.js +437 -0
  33. package/src/hiring-requirements.d.ts +16 -0
  34. package/src/hiring-requirements.js +170 -0
  35. package/src/hiring-salary-context.d.ts +27 -0
  36. package/src/hiring-salary-context.js +76 -0
  37. package/src/hiring-semantics.d.ts +29 -0
  38. package/src/hiring-semantics.js +218 -0
  39. package/src/hiring-skills.d.ts +21 -0
  40. package/src/hiring-skills.js +315 -0
  41. package/src/hiring-source-aliases.d.ts +32 -0
  42. package/src/hiring-source-aliases.js +186 -0
  43. package/src/hiring-source-semantics.d.ts +31 -0
  44. package/src/hiring-source-semantics.js +293 -0
  45. package/src/hiring-temporal.d.ts +15 -0
  46. package/src/hiring-temporal.js +67 -0
  47. package/src/hiring-vacancy-fields.d.ts +5 -0
  48. package/src/hiring-vacancy-fields.js +23 -0
  49. package/src/hiring-work-semantics.d.ts +34 -0
  50. package/src/hiring-work-semantics.js +72 -0
  51. package/src/hiring.js +180 -0
  52. package/src/housing-address.d.ts +18 -0
  53. package/src/housing-address.js +210 -0
  54. package/src/housing-context.d.ts +36 -0
  55. package/src/housing-context.js +183 -0
  56. package/src/housing-features.js +30 -0
  57. package/src/housing-intent.d.ts +9 -0
  58. package/src/housing-intent.js +132 -0
  59. package/src/housing-listing-fields.js +131 -0
  60. package/src/housing-money.d.ts +7 -0
  61. package/src/housing-money.js +102 -0
  62. package/src/housing-source-aliases.d.ts +8 -0
  63. package/src/housing-source-aliases.js +51 -0
  64. package/src/housing-structured.d.ts +55 -0
  65. package/src/housing-structured.js +219 -0
  66. package/src/housing.js +200 -0
  67. package/src/index.js +44 -0
  68. package/src/kz-location-extensions.js +307 -0
  69. package/src/landmarks.js +21 -0
  70. package/src/lexicon-core.js +58 -0
  71. package/src/location-merge.js +106 -0
  72. package/src/locations.js +456 -0
  73. package/src/money-core.d.ts +10 -0
  74. package/src/money-core.js +81 -0
  75. package/src/money-lexicon.d.ts +5 -0
  76. package/src/money-lexicon.js +79 -0
  77. package/src/money.js +154 -0
  78. package/src/normalization.js +384 -0
  79. package/src/odesa-metropolitan.js +145 -0
  80. package/src/romania-geography.js +47 -0
  81. package/src/tashkent-colloquial.js +72 -0
  82. package/src/tashkent-housing-geography.d.ts +38 -0
  83. package/src/tashkent-housing-geography.js +211 -0
  84. package/src/tashkent-pois.js +215 -0
  85. package/src/tashkent-residential-complexes.js +272 -0
  86. package/src/ua-location-extensions-major.js +118 -0
  87. package/src/ua-location-extensions-metro.js +9 -0
  88. package/src/ua-location-extensions-regional.js +246 -0
  89. package/src/ua-secondary-cities.d.ts +2 -0
  90. package/src/ua-secondary-cities.js +57 -0
  91. package/src/ukraine.js +75 -0
  92. package/src/uz-location-extensions.js +259 -0
@@ -0,0 +1,307 @@
1
+ import { aliasesToRegex } from './normalization.js';
2
+
3
+ function entry(name, aliases = [], meta = {}) {
4
+ const all = [...new Set([name, ...aliases].filter(Boolean))];
5
+ return Object.freeze({ ...meta, canonical: name, name, type: meta.type || meta.entityType, aliases: Object.freeze(all), re: aliasesToRegex(all) });
6
+ }
7
+
8
+ function entries(rows = [], defaults = {}) {
9
+ return Object.freeze(rows.map((row) => {
10
+ if (Array.isArray(row)) return entry(row[0], row.slice(1), defaults);
11
+ return entry(row.name, row.aliases || [], { ...defaults, ...row });
12
+ }));
13
+ }
14
+
15
+ function city({ districts = [], microdistricts = [], residentialComplexes = [], landmarks = [], suburbs = [], localAreas = [] }) {
16
+ return Object.freeze({
17
+ ...(districts.length ? { districts: entries(districts, { entityType: 'district', country: 'KZ' }) } : {}),
18
+ ...(microdistricts.length ? { microdistricts: entries(microdistricts, { entityType: 'microdistrict', country: 'KZ' }) } : {}),
19
+ ...(localAreas.length ? { localAreas: entries(localAreas, { entityType: 'local_area', country: 'KZ' }) } : {}),
20
+ ...(residentialComplexes.length ? { residentialComplexes: entries(residentialComplexes, { entityType: 'residential_complex', country: 'KZ' }) } : {}),
21
+ ...(landmarks.length ? { landmarks: entries(landmarks, { entityType: 'poi', country: 'KZ' }) } : {}),
22
+ ...(suburbs.length ? { suburbs: entries(suburbs, { entityType: 'suburb', country: 'KZ' }) } : {}),
23
+ });
24
+ }
25
+
26
+ const range = (from, to) => Array.from({ length: to - from + 1 }, (_, i) => from + i);
27
+ const numberedMicrodistrict = (n, suffix = '') => {
28
+ const id = `${n}${suffix}`;
29
+ return [
30
+ `${id} microdistrict`,
31
+ `${id} микрорайон`, `${id} мкр`, `${id} мкр.`, `${id}мкр`, `${id} м-н`, `${id} м-н.`, `${id} микро`, `${id}-й мкр`, `${id} мкр-н`, `${id} ықшамаудан`,
32
+ ];
33
+ };
34
+
35
+ export const KZ_LOCATION_EXTENSIONS = Object.freeze({
36
+ Almaty: city({
37
+ districts: [
38
+ ['Alatau', 'Алатауский район', 'Алатау', 'Алатау ауданы'],
39
+ ['Almaly', 'Алмалинский район', 'Алмалы', 'Алмалы ауданы'],
40
+ ['Auezov', 'Ауэзовский район', 'Әуезов', 'Әуезов ауданы'],
41
+ ['Bostandyk', 'Бостандыкский район', 'Бостандық', 'Бостандық ауданы'],
42
+ ['Zhetysu', 'Жетысуский район', 'Жетісу', 'Жетісу ауданы'],
43
+ ['Medeu', 'Медеуский район', 'Медеу', 'Медеу ауданы'],
44
+ ['Nauryzbay', 'Наурызбайский район', 'Наурызбай', 'Наурызбай ауданы'],
45
+ ['Turksib', 'Турксибский район', 'Түрксіб', 'Түрксіб ауданы'],
46
+ ],
47
+ microdistricts: [
48
+ { name: 'Center', aliases: ['Центр', 'Старый центр', 'Старый город', 'Золотой квадрат', 'Golden Square', 'Тихий центр', 'Арбат', 'Жибек Жолы'], district: 'Almaly' },
49
+ ...['Тастак','Тастақ','Тастак-1','Тастак-2','Тастак-3','Тастак-4'].map((x) => ({ name: x.replace('Тастақ','Тастак'), aliases: [x], district: 'Almaly' })),
50
+ { name: 'Sairan', aliases: ['Сайран'], district: 'Almaly' },
51
+ { name: 'Moskva Mall area', aliases: ['ТЦ Москва', 'Москва ТЦ'], district: 'Almaly', entityType: 'local_area' },
52
+ { name: 'ADK area', aliases: ['АДК', 'ADK'], district: 'Almaly', entityType: 'local_area' },
53
+ ...['Орбита','Орбита-1','Орбита-2','Орбита-3','Орбита-4'].map((x) => ({ name: x.replace('Орбита','Orbita'), aliases: [x], district: 'Bostandyk' })),
54
+ ...['Коктем','Көктем','Коктем-1','Коктем-2','Коктем-3','Коктем-4'].map((x) => ({ name: x.replace('Көктем','Koktem').replace('Коктем','Koktem'), aliases: [x], district: 'Bostandyk' })),
55
+ { name: 'Almagul', aliases: ['Алмагуль', 'Алмагүл'], district: 'Bostandyk' },
56
+ { name: 'Kazakhfilm', aliases: ['Казахфильм', 'Kazakhfilm'], district: 'Bostandyk' },
57
+ { name: 'Miras', aliases: ['Мирас'], district: 'Bostandyk' },
58
+ { name: 'Nurlytau', aliases: ['Нурлытау', 'Нұрлытау'], district: 'Bostandyk' },
59
+ { name: 'Ermensai', aliases: ['Ерменсай'], district: 'Bostandyk' },
60
+ { name: 'Baganashyl', aliases: ['Баганашыл', 'Бағанашыл'], district: 'Bostandyk' },
61
+ { name: 'Khan Tengri', aliases: ['Хан-Тенгри', 'Хан Тенгри', 'Хан Тәңірі'], district: 'Bostandyk' },
62
+ { name: 'Remizovka', aliases: ['Ремизовка'], district: 'Bostandyk' },
63
+ { name: 'Nur Alatau', aliases: ['Нур Алатау', 'Нұр Алатау'], district: 'Bostandyk' },
64
+ { name: 'Gornyi Gigant', aliases: ['Горный Гигант'], district: 'Bostandyk' },
65
+ ...['Самал','Самал-1','Самал-2','Самал-3'].map((x) => ({ name: x.replace('Самал','Samal'), aliases: [x], district: 'Medeu' })),
66
+ ...['Думан','Думан-1','Думан-2'].map((x) => ({ name: x.replace('Думан','Duman'), aliases: [x], district: 'Medeu' })),
67
+ { name: 'Kok-Tobe', aliases: ['Кок-Тобе', 'Көктөбе', 'Коктобе'], district: 'Medeu' },
68
+ { name: 'Butakovka', aliases: ['Бутаковка'], district: 'Medeu' },
69
+ { name: 'Medeu', aliases: ['Медеу'], district: 'Medeu' },
70
+ { name: 'Kamenskoye Plato', aliases: ['Каменское плато'], district: 'Medeu' },
71
+ ...['Кенсай','Кенсай-1','Кенсай-2','Кенсай-3'].map((x) => ({ name: x.replace('Кенсай','Kensai'), aliases: [x], district: 'Medeu' })),
72
+ { name: 'Tatarka', aliases: ['Татарка'], district: 'Medeu' },
73
+ { name: 'Malaya Stanitsa', aliases: ['Малая станица'], district: 'Medeu' },
74
+ ...['Аксай','Ақсай','Аксай-1','Аксай-1А','Аксай-2','Аксай-2А','Аксай-3','Аксай-3А','Аксай-4'].map((x) => ({ name: x.replace('Ақсай','Aksai').replace('Аксай','Aksai'), aliases: [x], district: 'Auezov' })),
75
+ ...range(1,7).map((n) => ({ name: `Mamyr-${n}`, aliases: [`Мамыр-${n}`, `Мамыр ${n}`], district: 'Auezov' })),
76
+ { name: 'Mamyr', aliases: ['Мамыр'], district: 'Auezov' },
77
+ ...range(1,3).map((n) => ({ name: `Zhetysu-${n}`, aliases: [`Жетысу-${n}`, `Жетісу-${n}`], district: 'Auezov' })),
78
+ { name: 'Zhetysu', aliases: ['Жетысу', 'Жетісу'], district: 'Auezov' },
79
+ ...range(1,3).map((n) => ({ name: `Taugul-${n}`, aliases: [`Таугуль-${n}`, `Таугүл-${n}`], district: 'Auezov' })),
80
+ { name: 'Taugul', aliases: ['Таугуль', 'Таугүл'], district: 'Auezov' },
81
+ { name: 'Sairan', aliases: ['Сайран'], district: 'Auezov' },
82
+ { name: 'Akkent', aliases: ['Аккент', 'Ақкент', 'Aqqent'], district: 'Alatau' },
83
+ { name: 'Sayaly', aliases: ['Саялы'], district: 'Alatau' },
84
+ ...['Шанырак','Шаңырақ','Шанырак-1','Шанырак-2'].map((x) => ({ name: x.replace('Шаңырақ','Shanyrak').replace('Шанырак','Shanyrak'), aliases: [x], district: 'Alatau' })),
85
+ ...['Улжан','Ұлжан','Улжан-1','Улжан-2'].map((x) => ({ name: x.replace('Ұлжан','Ulzhan').replace('Улжан','Ulzhan'), aliases: [x], district: 'Alatau' })),
86
+ { name: 'Ozhet', aliases: ['Ожет', 'Өжет'], district: 'Alatau' },
87
+ { name: 'Darkhan', aliases: ['Дархан'], district: 'Alatau' },
88
+ { name: 'Tomiris', aliases: ['Томирис'], district: 'Alatau' },
89
+ { name: 'Terekty', aliases: ['Теректы', 'Теректі'], district: 'Alatau' },
90
+ { name: 'Rakhat', aliases: ['Рахат'], district: 'Alatau' },
91
+ { name: 'Kurylysshy', aliases: ['Курылысшы', 'Құрылысшы'], district: 'Alatau' },
92
+ { name: 'Madeniet', aliases: ['Мадениет', 'Мәдениет'], district: 'Alatau' },
93
+ { name: 'Algabas', aliases: ['Алгабас', 'Алғабас'], district: 'Alatau' },
94
+ { name: 'Shugyla', aliases: ['Шугыла', 'Шұғыла'], district: 'Nauryzbay' },
95
+ ...['Калкаман','Қалқаман','Калкаман-1','Калкаман-2'].map((x) => ({ name: x.replace('Қалқаман','Kalkaman').replace('Калкаман','Kalkaman'), aliases: [x], district: 'Nauryzbay' })),
96
+ { name: 'Kargaly', aliases: ['Каргалы', 'Қарғалы'], district: 'Nauryzbay' },
97
+ { name: 'Tausamaly', aliases: ['Таусамалы'], district: 'Nauryzbay' },
98
+ { name: 'Tastybulak', aliases: ['Тастыбулак', 'Тастыбұлақ'], district: 'Nauryzbay' },
99
+ { name: 'Abai Dachas', aliases: ['Абайские дачи'], district: 'Nauryzbay' },
100
+ { name: 'Kamenka', aliases: ['Каменка'], district: 'Nauryzbay' },
101
+ { name: 'Kuramys', aliases: ['Курамыс', 'Құрамыс'], district: 'Nauryzbay' },
102
+ { name: 'Akzhar', aliases: ['Акжар', 'Ақжар'], district: 'Nauryzbay' },
103
+ { name: 'Karagaily', aliases: ['Карагайлы', 'Қарағайлы'], district: 'Nauryzbay' },
104
+ { name: 'Zhailau', aliases: ['Жайлау'], district: 'Nauryzbay' },
105
+ ...range(1,4).map((n) => ({ name: `Ainabulak-${n}`, aliases: [`Айнабулак-${n}`, `Айнабұлақ-${n}`], district: 'Zhetysu' })),
106
+ { name: 'Ainabulak', aliases: ['Айнабулак', 'Айнабұлақ'], district: 'Zhetysu' },
107
+ { name: 'Kulager', aliases: ['Кулагер', 'Құлагер'], district: 'Zhetysu' },
108
+ { name: 'Kokzhiek', aliases: ['Кокжиек', 'Көкжиек'], district: 'Zhetysu' },
109
+ { name: 'Pervomayka', aliases: ['Первомайка'], district: 'Zhetysu' },
110
+ { name: 'Dorozhnik', aliases: ['Дорожник'], district: 'Zhetysu' },
111
+ { name: 'Nizhnyaya Pyatiletka', aliases: ['Нижняя Пятилетка'], district: 'Zhetysu' },
112
+ { name: 'Zhuldyz', aliases: ['Жулдыз', 'Жұлдыз'], district: 'Turksib' },
113
+ ...[1,2].map((n) => ({ name: `Zhuldyz-${n}`, aliases: [`Жулдыз-${n}`, `Жұлдыз-${n}`], district: 'Turksib' })),
114
+ { name: 'Mayak', aliases: ['Маяк'], district: 'Turksib' },
115
+ { name: 'Almerek', aliases: ['Альмерек', 'Әлмерек'], district: 'Turksib' },
116
+ { name: 'Kairat', aliases: ['Кайрат', 'Қайрат'], district: 'Turksib' },
117
+ { name: 'Turksib', aliases: ['Турксиб'], district: 'Turksib' },
118
+ { name: 'Nizhnyaya Pyatiletka', aliases: ['Нижняя Пятилетка'], district: 'Turksib' },
119
+ { name: 'Airport', aliases: ['Аэропорт'], district: 'Turksib' },
120
+ { name: 'Almaty-1', aliases: ['Станция Алматы-1', 'Алматы-1'], district: 'Turksib' },
121
+ { name: 'Zhas Kanat', aliases: ['Жас Канат', 'Жас Қанат'], district: 'Turksib' },
122
+ ],
123
+ localAreas: [
124
+ ['Golden Square', 'Золотой квадрат', 'Золотой Квадрат'], ['Quiet Center', 'Тихий центр'], ['VDNKh', 'ВДНХ'], ['Atakent area', 'Атакент', 'Atakent'],
125
+ ['Kompot', 'Компот'], ['Old Square', 'Старая площадь'], ['New Square', 'Новая площадь'], ['Arbat', 'Арбат'],
126
+ ],
127
+ residentialComplexes: [
128
+ ['Esentai City'],['Esentai Apartments'],['Esentai Park'],['Apple Town'],['Apple City'],['Mega Towers','Mega Tower'],['Metropole','Metropole Residence'],
129
+ ['Central Avenue','Central Avenue Residence'],['Dostyk Residence'],['Dostyk Plaza Residence'],['Exclusive Star'],['Exclusive Time'],['Exclusive Residence'],
130
+ ['Rams City','RAMS City'],['RAMS Garden'],['RAMS Beyond'],['RAMS Signature'],['Koktobe City'],['Koktobe Hills'],['Mountain Drive'],['Mountain Park'],
131
+ ['Remizovka'],['Gagarin Park'],['Gagarin Terrace'],['Green City'],['Green Plaza'],['Braun','Braun Residence'],['Presidents Park',"President's Park",'President Park'],
132
+ ['4YOU'],['4YOU Business'],['4YOU Comfort'],['Orion','Orion Residence'],['Alma City'],['Alma City 5'],['Alma City 6'],['Alma City 7'],
133
+ ['Akbulak Hills','Ақбұлақ'],['AFD Plaza'],['Symphony'],['Symphony 3'],['Hyde Park'],['Park Avenue'],['Avenue'],['Terracotta'],['Terracotta Park'],
134
+ ],
135
+ landmarks: [
136
+ ['Medeu','Медеу'],['Shymbulak','Шымбулак','Чимбулак'],['Kok-Tobe','Кок-Тобе','Көктөбе','Kok Tobe'],['Big Almaty Lake','Большое Алматинское озеро','БАО'],
137
+ ['Panfilov Park','парк 28 панфиловцев'],['Gorky Park','Парк Горького','Центральный парк'],['Botanical Garden','Ботанический сад'],['Atakent','Атакент'],
138
+ ['Republic Square','площадь Республики','Республика алаңы'],['Palace of the Republic','Дворец Республики'],['Arbat','Арбат','Жибек Жолы'],['Green Bazaar','Зеленый базар','Зелёный базар','Көк базар'],
139
+ ['Almaty Arena'],['Halyk Arena'],['Central Stadium','Центральный стадион'],['MEGA Alma-Ata','MEGA Center Alma-Ata'],['MEGA Park'],['Dostyk Plaza'],['Esentai Mall'],
140
+ ['Forum Almaty','Forum'],['Atakent Mall'],['Aport Mall','Aport','Aport East'],['Moskva Mall','Moskva','Москва'],['Grand Park'],['Globus'],['ADK','АДК'],
141
+ ],
142
+ suburbs: [
143
+ ['Besagash','Бесагаш','Бесағаш','Бесагаш Алматы'],['Talgar','Талғар','Талгар'],['Kaskelen','Қаскелең','Каскелен'],['Irgeli','Іргелі','Иргели'],
144
+ ['Otegen Batyr','Өтеген батыр','Отеген Батыр','Энергетический','Энергетический посёлок'],['Boraldai','Боралдай','Бурундай','Burundai'],
145
+ ['Kyrgauyldy','Қырғауылды','Кыргауылды'],['Tuzdybastau','Тұздыбастау','Туздыбастау','Калинино'],['Almalybak','Алмалыбақ','Алмалыбак'],
146
+ ['Kemertogan','Кемертоған','Кемертоган'],['Guldala','Гүлдала','Гульдала'],['Baiserke','Байсерке'],['Raiymbek','Райымбек'],
147
+ ],
148
+ }),
149
+
150
+ Astana: city({
151
+ districts: [
152
+ ['Almaty','Алматы район','Алматы ауданы'],['Baikonur','Байконур','Байқоңыр','Байқоңыр ауданы'],['Esil','Есиль','Есіл','Есіл ауданы'],
153
+ ['Nura','Нура','Нұра','Нұра ауданы'],['Saraishyk','Сарайшык','Сарайшық','Сарайшық ауданы'],['Saryarka','Сарыарка','Сарыарқа','Сарыарқа ауданы'],
154
+ ],
155
+ microdistricts: [
156
+ ['South-East','Юго-Восток'],['South-East Right','Юго-Восток правая сторона'],['South-East Left','Юго-Восток левая сторона'],['Old City','Старый город','Старый центр'],
157
+ ['New Center','Новый центр','Административный центр'],['Left Bank','Левый берег','Левобережье','Сол жағалау'],['Right Bank','Правый берег','Правобережье','Оң жағалау'],
158
+ ['Chubary','Чубары','Шубар','Шұбар'],['Komsomolsky','Комсомольский'],['Koktal','Коктал','Көктал'],['Koktal-1','Коктал-1'],['Koktal-2','Коктал-2'],
159
+ ['Urker','Уркер','Үркер'],['Ondiris','Ондирис','Өндіріс'],['Industrial','Промышленный'],['Zheleznodorozhny','Железнодорожный','Железнодорожный жилой массив'],
160
+ ['International','Интернациональный'],['Michurino','Мичурино'],['Kuigenzhar','Куйгенжар','Күйгенжар'],['Prigorodny','Пригородный','Пригородный жилой массив'],
161
+ ['Telmana','Тельмана'],['Ilyinka','Ильинка'],['Zarechny','Заречный','Заречный жилой массив'],['Agrogorodok','Агро-городок','Агрогородок'],
162
+ ['Molodezhny','Молодежный','Молодёжный'],['Tselinny','Целинный','Целинный микрорайон'],['Kirpichny','Кирпичный'],['Kazgorodok','Казгородок'],
163
+ ['EXPO area','EXPO','Экспо'],['Botanical Garden area','Ботанический сад'],['Green Quarter area','Зеленый квартал','Зелёный квартал'],
164
+ ['Millennium Alley','Аллея Тысячелетия','Аллея Мыңжылдық','Мынжылдык','Мыңжылдық'],['Turan area','Туран'],['Mangilik El area','Мәңгілік Ел'],['Saraychik area','Сарайшык','Сарайшық'],
165
+ ],
166
+ residentialComplexes: [
167
+ ['Highvill','Highvill Astana'],['Highvill Ishim'],['Highvill Park'],['Grand Alatau'],['Northern Lights','Северное сияние'],['Lazurny Kvartal','Лазурный квартал'],
168
+ ['Triumph','Триумфальный','Триумф Астаны'],['Talan Towers'],['Abu Dhabi Plaza'],['Green Quarter','Зеленый квартал','Зелёный квартал'],['Expo Boulevard'],['Expo Residence'],
169
+ ['Expo Town'],['Promenade Expo'],['Nova City','Nova City на Туране'],['Sezim Qala','Сезім Қала'],['Sat City'],['Sat City K7'],['Apple City'],['Millennium Park'],['Millennium Alley'],
170
+ ['Family Town'],['Family Village'],['Athletic City'],['Capital Park'],['Sensata Park'],['Sensata City'],['BI City'],['BI Village'],['Jetisu'],['Jetisu Park'],['Aq-Didar','Ak Didar'],
171
+ ['Arai Apartments'],['Manhattan','Manhattan Astana'],['Sarmat'],['Sarmat 2'],['Inju City'],['Inju Promenade'],['Inju Arena'],['Tokyo','Tokyo Residence'],['London','London Residence'],
172
+ ['Paris','Paris Residence'],['Monaco'],['Florence'],['Vienna'],['Venice'],['Gagarin Park'],['Gagarin Terrace'],['Akbulak Riviera','Акбулак','Ақбұлақ'],['Akbulak Life'],['Jagalau','Жагалау'],
173
+ ],
174
+ landmarks: [
175
+ ['Baiterek','Байтерек','Бәйтерек'],['Khan Shatyr','Хан Шатыр'],['EXPO','Экспо'],['Nur Alem','Нур Алем','Нұр Әлем'],['Hazret Sultan Mosque','Мечеть Хазрет Султан','Әзірет Сұлтан'],
176
+ ['Astana Grand Mosque','Главная мечеть'],['Ak Orda','Ак Орда','Ақорда'],['Palace of Peace and Reconciliation','Дворец мира и согласия','Пирамида'],['Ishim Embankment','Набережная Ишима','Есиль','Ishim'],
177
+ ['Astana Botanical Garden','Ботанический сад'],['Central Park','Центральный парк'],['Triathlon Park','Триатлон парк'],['Presidential Park','Президентский парк'],['Astana Arena','Астана Арена'],['Barys Arena','Барыс Арена'],
178
+ ['Mega Silk Way','MEGA Silk Way'],['Keruen','Керуен'],['KeruenCity'],['Asia Park'],['Abu Dhabi Plaza'],['Saryarka Mall','Saryarka','Сарыарка'],['Eurasia','Евразия'],
179
+ ],
180
+ suburbs: [
181
+ ['Kosshy','Қосшы','Косшы','Qosshy','Косшы Астана','пригород Астаны'],['Lesnaya Polyana','Лесная Поляна','Лесная поляна','Орманды','Kosshy Лесная Поляна'],
182
+ ['Taitobe','Тайтөбе','Тайтобе','Taytobe'],['Karaotkel','Қараөткел','Караоткель'],['Ilyinka','Ильинка','Ильинка Астана'],['Koyandy','Қоянды','Коянды'],['Talapker','Талапкер'],['Karazhar','Қаражар','Каражар'],
183
+ ],
184
+ }),
185
+
186
+ Shymkent: city({
187
+ districts: [['Abai','Абайский','Абай'],['Al-Farabi','Аль-Фарабийский','Әл-Фараби'],['Enbekshi','Енбекшинский','Еңбекші'],['Karatau','Каратауский','Қаратау'],['Turan','Туранский','Тұран']],
188
+ microdistricts: [
189
+ ['Nursat','Нурсат','Нұрсәт'],['Turan','Туран','Тұран'],['Shymcity','Шымсити','Shymkent City'],['Akzhaiyk','Акжайык','Ақжайық'],['Bozaryk','Бозарык','Бозарық'],['Samal','Самал'],
190
+ ['Saule','Сәуле','Сауле'],['Kazygurt','Казыгурт','Қазығұрт'],['Turlan','Турлан','Тұрлан'],['Badam','Бадам'],['Badam-1','Бадам-1'],['Badam-2','Бадам-2'],['Akzhar','Акжар','Ақжар'],
191
+ ['Kulager','Кулагер','Құлагер'],['Kokbulak','Кокбулак','Көкбұлақ'],['Karabastau','Карабастау','Қарабастау'],['Kursai','Курсай','Құрсай'],['Sairam','Сайрам'],['Asar','Асар'],['Asar-1','Асар-1'],['Asar-2','Асар-2'],
192
+ ['Dostyk','Достык','Достық'],['Kaitpas','Кайтпас','Қайтпас'],['Kaitpas-1','Кайтпас-1'],['Kaitpas-2','Кайтпас-2'],['Tassai','Тассай'],['Tasken','Таскен'],['Zabadam','Забадам'],['Yntymak','Ынтымак','Ынтымақ'],
193
+ ['Kyzylzhar','Кызылжар','Қызылжар'],['Otyrar','Отырар'],['North','Север','Северный'],['East','Восток','Восточный'],['North-West','Северо-Запад'],
194
+ ...[11,12,16,17,18,19,20,21,22,23,24].map((n) => numberedMicrodistrict(n)),
195
+ ],
196
+ residentialComplexes: [['Otau City'],['Otau City 2'],['Shymkent City'],['Tulpar City'],['Nursat'],['Nursat City'],['Arman City'],['Arman Qala'],['Tumar Apartments'],['Tumar Residence'],['Royal Park'],['Royal Residence'],['Grand Park'],['Grand City'],['Capital City'],['Family Park'],['Al-Farabi'],['Al-Farabi Residence'],['Tauke Khan'],['Tauke Khan Residence']],
197
+ landmarks: [['Shymkent Dendropark','Дендропарк','Шымкентский дендропарк'],['Abai Park','парк Абая'],['Independence Park','парк Независимости','Тәуелсіздік саябағы'],['Ordabasy Square','площадь Ордабасы','Ордабасы'],['Shymkent Arbat','Арбат'],['Shymqala Citadel','Цитадель','Shymqala','Шымкала'],['Shymkent Zoo','Зоопарк'],['Nauryz Park','Наурыз парк'],['Baidibek Bi','Байдибек би','Байдібек би']],
198
+ }),
199
+
200
+ Karaganda: city({
201
+ districts: [['Kazybek Bi','Казыбек би','Қазыбек би'],['Alikhan Bokeikhan','Алихан Бокейхан','Әлихан Бөкейхан','Октябрьский район']],
202
+ microdistricts: [
203
+ ['Center','Центр'],['New City','Новый город'],['South-East','Юго-Восток'],['South-East-1','Юго-Восток-1'],['South-East-2','Юго-Восток-2'],
204
+ ...range(1,4).map((n) => [`Stepnoy-${n}`,`Степной-${n}`]),['Stepnoy','Степной'],['Gulder','Гульдер','Гүлдер'],['Gulder-1','Гульдер-1'],['Gulder-2','Гульдер-2'],
205
+ ['Orbita','Орбита'],['Orbita-1','Орбита-1'],['Orbita-2','Орбита-2'],['Vostok','Восток'],['Vostok-1','Восток-1'],['Vostok-2','Восток-2'],['Vostok-3','Восток-3'],
206
+ ['Golubye Prudy','Голубые Пруды','Голубые пруды'],['Fedorovka','Федоровка'],['Mikhailovka','Михайловка'],['Maikuduk','Майкудук','Майқұдық'],['Prishakhtinsk','Пришахтинск'],['Sortirovka','Сортировка'],
207
+ ['Old City','Старый город'],['Finskiy','Финский'],['Berlin','Берлин'],['Kirzavod','Кирзавод'],['Kuryanovsky','Курьяновский'],['Novaya Tikhonovka','Новая Тихоновка'],['Tikhonovka','Тихоновка'],
208
+ ...['11А','12','13','14','15','16','17','18','19','20','23'].map((n) => numberedMicrodistrict(n)),
209
+ ],
210
+ residentialComplexes: [['Green City'],['Senator Park'],['Senator'],['Oasis'],['Oasis City'],['Triumf','Триумф'],['Keremet','Керемет'],['Arman','Арман'],['British Quarter','Британский квартал'],['London','London Residence'],['French House','Французский дом']],
211
+ landmarks: [['Central Park','Центральный парк'],['Victory Park','парк Победы'],['Miners Palace','Дворец шахтеров','Дворец шахтёров'],['Shakhter Stadium','Шахтёр'],['Buketov University','КарГУ','Букетов университет'],['Anet Baba Mosque','мечеть Анета баба'],['Karaganda Railway Station','вокзал Караганда']],
212
+ }),
213
+
214
+ Aktobe: city({
215
+ districts: [['Astana','Астана район'],['Almaty','Алматы район']],
216
+ microdistricts: [
217
+ ['Center','Центр'],['Old City','Старый город'],['New City','Новый город'],['Zhilgorodok','Жилгородок'],['Aviagorodok','Авиагородок'],['Moskva','Москва'],['Bolashak','Болашак','Болашақ'],
218
+ ['Batys','Батыс'],['Batys-1','Батыс-1'],['Batys-2','Батыс-2'],['Batys-3','Батыс-3'],['Nur Aktobe','Нур Актобе','Нұр Ақтөбе'],['Kargaly','Каргалы','Қарғалы'],
219
+ ['Zarechny','Заречный'],['Zarechny-1','Заречный-1'],['Zarechny-2','Заречный-2'],['Zarechny-3','Заречный-3'],['Kirpichny','Кирпичный'],['Sazdy','Сазды'],['Kurashasai','Курашасай'],['Akzhar','Акжар','Ақжар'],['Kyzylzhar','Кызылжар','Қызылжар'],
220
+ ...['5','8','11','12','12А','15'].map((n) => numberedMicrodistrict(n)),
221
+ ],
222
+ residentialComplexes: [['Green Land'],['Green Park'],['Aktobe City'],['Aktobe Azhary','Ақтөбе Ажары'],['Bavaria','Bavaria Residence'],['Royal','Royal Park'],['Family Park'],['Capital'],['Grand','Grand City'],['Avenue','Avenue 5'],['Central Park']],
223
+ landmarks: [['First President Park','парк Первого Президента'],['Central Park','Центральный парк'],['Nur Gasyr Mosque','Нур Гасыр','Нұр Ғасыр','мечеть Нур Гасыр'],['Aktobe Arena','Актобе Арена'],['Mega Aktobe']],
224
+ }),
225
+
226
+ Aktau: city({
227
+ microdistricts: [
228
+ ...range(1,41).filter((n) => n !== 0).map((n) => numberedMicrodistrict(n)),
229
+ numberedMicrodistrict(3,'A'),numberedMicrodistrict(12,'A'),numberedMicrodistrict(31,'A'),numberedMicrodistrict(32,'A'),
230
+ ],
231
+ suburbs: [['Baskudyk','Баскудык','Басқұдық'],['Atameken','Атамекен'],['Munaily','Мунайлы','Мұнайлы'],['Mangystau','Мангистау','Маңғыстау'],['Batyr','Батыр'],['Daulet','Даулет','Дәулет'],['KyzylTobe','Кызылтобе','Қызылтөбе'],['Umirzak','Умирзак','Өмірзақ']],
232
+ residentialComplexes: [['Green Plaza'],['Green Park'],['Aktau Riviera'],['Riviera'],['Florence','Florence Residence'],['Caspian Riviera'],['Caspian Palace'],['Caspian Tower'],['Aktau Towers'],['Aktau City'],['Grand Nur Plaza'],['Grand Victory'],['President','President Residence'],['Family Town'],['Prime Park'],['Prime Residence']],
233
+ landmarks: [['Caspian Sea','Каспийское море','Каспий'],['Rock Trail','Скальная тропа'],['Embankment','набережная'],['Lighthouse','Маяк'],['TRK Aktau','ТРК Актау'],['Aktau Mall'],['Halyk Arena'],['Botanical Garden','Ботанический сад']],
234
+ }),
235
+
236
+ Atyrau: city({
237
+ microdistricts: [['Center','Центр'],['Old City','Старый город'],...range(1,4).map((n) => [`Avangard-${n}`,`Авангард-${n}`]),['Avangard','Авангард'],['Nursaya','Нурсая','Нұрсая'],['Samal','Самал'],['Sarykamys','Сарыкамыс','Сарықамыс'],['Zhilgorodok','Жилгородок'],['Privokzalny','Привокзальный'],['Privokzalny-1','Привокзальный-1'],['Privokzalny-2','Привокзальный-2'],['Balykshi','Балыкши','Балықшы'],['Almagul','Алмагуль','Алмагүл'],['Kokarna','Кокарна','Көкарна'],['Bereke','Береке'],['Zhumysker','Жумыскер','Жұмыскер'],['Tomarly','Томарлы'],['Erkinkala','Еркинкала','Еркінқала'],['Geolog','Геолог'],['Khimpeselok','Химпоселок','Химпосёлок'],['Leskhoz','Лесхоз'],['Kurilkino','Курилкино']],
238
+ residentialComplexes: [['Riviera Residence'],['Riverside'],['River Park'],['Infinity','Infinity Residence'],['French Quarter','Французский квартал'],['Grand Atyrau'],['Grand Park'],['Family Town'],['Talan','Talan Residence'],['Zaman','Zaman Residence'],['Caspian','Caspian Residence'],['Nursaya','Nursaya City']],
239
+ landmarks: [['Ural River','река Урал','Жайық'],['Pedestrian Bridge','пешеходный мост'],['Embankment','набережная'],['Isatay-Makhambet Square','площадь Исатая-Махамбета'],['Imangali Mosque','мечеть Имангали'],['Atyrau Bridge'],['Baizaar'],['Infinity Mall']],
240
+ }),
241
+
242
+ Pavlodar: city({
243
+ microdistricts: [['Center','Центр'],['Usolka','Усолка','Усольский'],['Dachny','Дачный'],['Vtoroy Pavlodar','Второй Павлодар'],['Vtoroy Pavlodar-1','Второй Павлодар-1'],['Vostochny','Восточный'],['Vostochny-1','Восточный-1'],['Vostochny-2','Восточный-2'],['Zelenstroy','Зеленстрой'],['KhimGorodki','Химгородки','Химгородок'],['Lesozavod','Лесозавод'],['Radiozavod','Радиозавод'],['Alyuminstroy','Алюминстрой'],['MDS','МДС'],['Saryarka','Сарыарка','Сарыарқа'],['Dostyk','Достык','Достық'],['Zhana Aul','Жана Ауыл','Жаңа ауыл'],['Ladozhskaya','Ладожская'],['Kamzina','Камзина'],['Nazarbayeva','Назарбаева'],['Torgovy Gorod','Торговый город']],
244
+ residentialComplexes: [['Dostyk','Достык'],['Saryarka','Сарыарка'],['Ertis','Ертіс','Irtysh'],['Grand','Grand Avenue'],['Riverside'],['River Park'],['Family','Family Town']],
245
+ landmarks: [['Irtysh Embankment','набережная Иртыша','Ертіс','Irtysh'],['Gagarin Park','парк Гагарина'],['Annunciation Cathedral','Благовещенский собор'],['Mashkhur Zhusup Mosque','мечеть Машхур Жусуп'],['Batyr Mall'],['Pavlodar Railway Station','Павлодар вокзал']],
246
+ }),
247
+
248
+ Oskemen: city({
249
+ microdistricts: [['Center','Центр'],['KShT','КШТ','КШТ район'],['Ablaketka','Аблакетка'],['Zashchita','Защита'],['Sogra','Согра'],['Novaya Sogra','Новая Согра'],['Staraya Sogra','Старая Согра'],['Menovnoe','Меновное'],['Akhmerovo','Ахмерово'],['Prokhladnaya','Прохладная'],['Strelka','Стрелка'],['DKM','ДКМ'],['Pristan','Пристань'],['Mirny','Мирный'],['Metallurg','Металлург'],['Babkina Melnitsa','Бабкина мельница'],['Zaulbinka','Заульбинка'],['Oktyabrsky','Октябрьский'],['Central Market','Центральный рынок'],['Ulba','Ульбинский','Үлбі']],
250
+ residentialComplexes: [['Grand City'],['Riviera'],['Ertis','Irtysh'],['Green Park'],['Altai','Altay'],['Central'],['Panorama','Panorama Park']],
251
+ landmarks: [['Irtysh','Иртыш','Ертіс'],['Ulba','Ульба','Үлбі'],['Strelka','Стрелка'],['Zhastar Park','парк Жастар'],['Ethnopark','этнопарк'],['Sports Palace','Дворец спорта'],['Oskemen Railway Station','Усть-Каменогорский вокзал'],['Oskemen Airport']],
252
+ }),
253
+
254
+ Semey: city({
255
+ microdistricts: [['Center','Центр','Центральный'],['Zarya','Заря'],['Vostochny','Восточный'],['Karagaily','Карагайлы','Қарағайлы'],['Energetik','Энергетик'],['Tsempeselok','Цемпоселок','Цемпосёлок'],['Novostroyka','Новостройка'],['Krasny Kordon','Красный Кордон','Красный кордон'],['Yunost','Юность'],['Mirny','Мирный'],['Vodny','Водный'],['Bobrovka','Бобровка'],['Zaton','Затон'],['Pristan','Пристань'],['343 Quarter','343 квартал'],['72 Quarter','72 квартал'],['35 Quarter','35 квартал'],['Stepnoy','Степной'],['Tatarsky Krai','Татарский край']],
256
+ residentialComplexes: [['Karagai','Қарағайлы'],['Semey City'],['Ertis','Irtysh'],['Grand'],['Family']],
257
+ landmarks: [['Irtysh','Иртыш','Ертіс'],['Semey Bridge','подвесной мост','Семейский мост'],['Polkovnichiy Island','остров Полковничий'],['Abai Museum','музей Абая','Абай музейі'],['Nevzorov Museum','Невзоров музейі','музей Невзоровых']],
258
+ }),
259
+
260
+ Kostanay: city({
261
+ microdistricts: [['Center','Центр'],['KSK','КСК'],['KZhBI','КЖБИ'],['Airport','Аэропорт'],['Nauryz','Наурыз'],['Yubileiny','Юбилейный'],['North-West','Северо-Западный','Северо-Запад'],['Bereke','Береке'],['Amangeldy','Амангельды','Амангелді'],['Druzhba','Дружба'],['Kievsky','Киевский'],['Uzkaya Koleya','Узкая колея'],['Military Town','Военный городок'],['Bus Station','Автовокзал'],['Narimanovsky Market','Наримановский рынок'],['Kostanay-2','Костанай-2']],
262
+ residentialComplexes: [['Riviera'],['Arman','Арман'],['Sultan','Султан'],['Family','Family Park'],['City','City Park'],['Grand']],
263
+ }),
264
+
265
+ Kyzylorda: city({
266
+ microdistricts: [['Center','Центр'],['Akmeshit','Акмешит','Ақмешіт'],['Arai','Арай'],['Shugyla','Шугыла','Шұғыла'],['Titov','Титов'],['Merei','Мерей'],['Saulet','Саулет','Сәулет'],['Syrdarya','Сырдарья','Сырдария'],['KBI','КБИ'],['Komsomol','Комсомол'],['Gagarina','Гагарина'],['SPMK-70','СПМК-70'],['Shanghai','Шанхай'],['Kyzylzharma','Кызылжарма','Қызылжарма'],['Tasboget','Тасбогет','Тасбөгет'],['Belkol','Белкуль','Белкөл']],
267
+ residentialComplexes: [['Syrdariya','Сырдария'],['Orda','Орда'],['Akmeshit','Ақмешіт'],['Arai','Арай'],['Zaman','Заман']],
268
+ landmarks: [['Syr Darya','Сырдарья'],['Central Square','Центральная площадь'],['First President Park','парк Первого Президента'],['Korkyt Ata','Коркыт Ата','Қорқыт Ата'],['Aray City Mall']],
269
+ }),
270
+
271
+ Oral: city({
272
+ microdistricts: [['Center','Центр'],['Old City','Старый город'],['North-East','Северо-Восток'],['North-East-1','Северо-Восток-1'],['North-East-2','Северо-Восток-2'],['North-East-2A','Северо-Восток-2А'],['North-East-3','Северо-Восток-3'],['Stroitel','Строитель'],['Omega','Омега'],['Zachagansk','Зачаганск'],['Zhana Orda','Жана Орда','Жаңа Орда'],['Sarytau','Сарытау'],['Samal','Самал'],['Derkul','Деркул'],['Krugloozernoe','Круглоозёрное','Круглоозерное'],['Ptitsefabrika','Птицефабрика'],['Old Airport','Старый аэропорт'],['New Airport','Новый аэропорт'],['Railway Station','ЖД вокзал']],
273
+ residentialComplexes: [['Zhana Orda','Жана Орда','Жаңа Орда'],['Samal','Самал'],['Grand','Grand City'],['Family','Family Park'],['Riverside','River Park'],['Zaman']],
274
+ landmarks: [['Ural River','Урал','Жайық'],['Chagan','Чаган','Шаған'],['Abai Square','площадь Абая'],['Kirov Park','парк Кирова'],['First President Park','парк Первого Президента'],['Asia Mall']],
275
+ }),
276
+
277
+ Taraz: city({
278
+ microdistricts: [['Center','Центр'],['Asa','Аса'],['Zhansaya','Жансая'],['Samal','Самал'],['Karatau','Каратау','Қаратау'],['Talas','Талас'],['Zhailau','Жайлау'],['Saltanat','Салтанат'],['Mynbulak','Мынбулак','Мыңбұлақ'],['Arai','Арай'],['Baiterek','Бәйтерек'],['Baryskhan','Барысхан'],['Kumshagal','Кумшагал','Құмшағал'],['Sholdala','Шолдала','Шөлдала']],
279
+ landmarks: [['Tekturmas','Тектурмас'],['Karakhan Mausoleum','мавзолей Карахана'],['Aisha Bibi','Айша-Биби'],['Babaji Khatun','Бабаджа-хатун'],['First President Park','парк Первого Президента'],['Central Park','Центральный парк'],['Mart'],['Taraz Arena','Тараз Арена']],
280
+ }),
281
+
282
+ Petropavl: city({ microdistricts: [['Center','Центр'],...['19','20'].map((n)=>numberedMicrodistrict(n)),['Bereke','Береке'],['Zhas Orken','Жас Оркен','Жас Өркен'],['Podgora','Подгора'],['Benzostroy','Бензострой'],['Rabochiy','Рабочий'],['Privokzalny','Привокзальный'],['Cheremushki','Черемушки'],['Zarechny','Заречный'],['Novy Svet','Новый свет'],['Solnechny','Солнечный']] }),
283
+ Taldykorgan: city({ microdistricts: [['Center','Центр'],['Karatal','Каратал','Қаратал'],['Zhastar','Жастар'],['Samal','Самал'],['Koktem','Көктем'],['Vostochny','Восточный'],['South-West','Юго-Западный'],['Musheltoy','Мушелтой','Мүшелтой'],['Erkin','Еркин'],['Otenai','Өтенай','Отенай']] }),
284
+ Temirtau: city({ microdistricts: [['Center','Центр'],['Old City','Старый город'],['New City','Новый город'],['Vostok','Восток'],['Sotsgorod','Соцгород'],...range(6,9).map((n)=>numberedMicrodistrict(n)),['Metallurg','Металлург'],['Right Bank','Правый берег']], landmarks: [['Qarmet','Кармет','АрселорМиттал Темиртау','металлургический комбинат']] }),
285
+ Ekibastuz: city({ microdistricts: [['Center','Центр'],...range(5,15).map((n)=>numberedMicrodistrict(n)),numberedMicrodistrict(18),['Shakhtersky','Шахтерский'],['Gornyak','Горняк']], landmarks: [['GRES-1','ГРЭС-1','Экибастузская ГРЭС-1'],['GRES-2','ГРЭС-2'],['Bogatyr','Богатырь','разрез Богатырь']] }),
286
+ Rudny: city({ microdistricts: [['Center','Центр'],['Old City','Старый город'],...range(1,11).map((n)=>numberedMicrodistrict(n)),numberedMicrodistrict(13),numberedMicrodistrict(14),numberedMicrodistrict(15)], landmarks: [['SSGPO','ССГПО','Соколовско-Сарбайское'],['Gornyak','Горняк']] }),
287
+ Zhezkazgan: city({ microdistricts: [['Center','Центр'],['Vostochny','Восточный'],['Zapadny','Западный'],['Rybachiy','Рыбачий'],['Kombinatsky','Комбинатский'],['Geologichesky','Геологический'],...range(1,5).map((n)=>numberedMicrodistrict(n))] }),
288
+ Balkhash: city({ microdistricts: [['Center','Центр'],['Old City','Старый город'],['Pristantsionny','Пристанционный'],['Konyrat','Конырат','Қоңырат'],['Rembaza','Рембаза'],['Vostochny','Восточный'],['BGMK','БГМК']], landmarks: [['Lake Balkhash','озеро Балхаш','Балқаш көлі'],['Embankment','набережная'],['BGMK','БГМК']] }),
289
+ Turkistan: city({ microdistricts: [['Center','Центр'],['Old Turkistan','Старый Туркестан'],['New City','Новый город','Новый Туркестан','Жана кала','Жаңа қала'],['Otyrar','Отырар'],['Yassy','Яссы','Yassy'],['Bekzat','Бекзат']], landmarks: [['Khoja Ahmed Yasawi Mausoleum','мавзолей Ходжи Ахмеда Ясави','Қожа Ахмет Ясауи'],['Keruen Saray','Керуен Сарай','Karavansaray Turkistan'],['Turkistan Arena'],['New Administrative Center','Новый административный центр']] }),
290
+ Kokshetau: city({ microdistricts: [['Center','Центр'],['Borovskoy','Боровской'],['Vasilkovsky','Васильковский'],['Saryarka','Сарыарка'],['Koktem','Коктем'],['Zhailau','Жайлау'],['Yubileiny','Юбилейный'],['Zastantsionny','Застанционный'],['Old Airport','Старый аэропорт']] }),
291
+ Konaev: city({ microdistricts: [['Center','Центр'],...range(1,5).map((n)=>numberedMicrodistrict(n))], landmarks: [['Kapshagay Reservoir','Капчагайское водохранилище','Қапшағай су қоймасы'],['City Beach','городской пляж'],['Embankment','набережная'],['Gaming Zone','казино','игорная зона']] }),
292
+ Zhanaozen: city({ microdistricts: [['Center','Центр'],['Samal','Самал'],['Shugyla','Шугыла','Шұғыла'],['Arai','Арай'],['Orken','Оркен','Өркен'],['Rakhat','Рахат'],['Zhuldyz','Жулдыз','Жұлдыз'],['Munaily','Мунайлы','Мұнайлы']] }),
293
+ Satbayev: city({ microdistricts: [['Center','Центр']] }),
294
+ Arys: city({ localAreas: [['Center','Центр'],['Railway Station','Вокзал','железнодорожный'],['Ontam','Онтам'],['Syrdarya','Сырдарья'],['Montaitas','Монтайтас']] }),
295
+ Kentau: city({ localAreas: [['Center','Центр'],['Gornyak','Горняк'],['Ashysai','Ащысай'],['Baiyldyr','Байылдыр'],['Khantagi','Хантаги','Қантағы']] }),
296
+ Saryagash: city({ landmarks: [['Saryagash Resort','курорт Сарыагаш','санаторий Сарыагаш'],['Border','граница'],['Zhibek Zholy','Жибек Жолы','Жібек жолы']] }),
297
+ Kosshy: city({ localAreas: [['Lesnaya Polyana','Лесная поляна','Лесная Поляна','Орманды'],['Green Park'],['Taitobe','Тайтобе','Тайтөбе']] }),
298
+ });
299
+
300
+ export const KZ_SEARCH_CLUSTERS = Object.freeze([
301
+ Object.freeze({ name: 'Almaty metropolitan area', type: 'search_cluster', administrative: false, country: 'KZ', city: 'Almaty', members: Object.freeze(['Besagash','Talgar','Kaskelen','Irgeli','Otegen Batyr','Boraldai','Kyrgauyldy','Tuzdybastau','Almalybak','Kemertogan','Guldala','Baiserke','Raiymbek']) }),
302
+ Object.freeze({ name: 'Astana metropolitan area', type: 'search_cluster', administrative: false, country: 'KZ', city: 'Astana', members: Object.freeze(['Kosshy','Lesnaya Polyana','Taitobe','Karaotkel','Ilyinka','Koyandy','Talapker','Karazhar']) }),
303
+ ]);
304
+
305
+ export const KZ_AMBIGUOUS_LOCAL_NAMES = Object.freeze([
306
+ 'Center','Samal','Dostyk','Aksai','Akzhar','Koktem','Nursat','Arai','Bereke','Vostochny','South-East','Zarechny','Zhuldyz','Shugyla','Saryarka','Nursaya','Almagul',
307
+ ]);
@@ -0,0 +1,21 @@
1
+ import { lexiconEntity } from './lexicon-core.js';
2
+ const group = (canonical, aliases) => lexiconEntity(canonical, aliases);
3
+
4
+ export const GENERIC_LANDMARK_TERMS = Object.freeze([
5
+ group('Park', { ru: ['парк'], en: ['park'], uk: ['парк'], ro: ['parc'], uzLatn: ["bog'", 'bog‘', 'bogʻ', 'park'], uzCyrl: ['боғ', 'парк'], kk: ['саябақ', 'парк'] }),
6
+ group('Metro', { ru: ['метро', 'станция метро'], en: ['metro', 'subway station'], uk: ['метро', 'станція метро'], ro: ['metrou', 'stație de metrou'], uzLatn: ['metro', 'metro bekati'], uzCyrl: ['метро', 'метро бекати'], kk: ['метро', 'метро станциясы'] }),
7
+ group('Bus stop', { ru: ['автобусная остановка', 'остановка автобуса', 'конечная автобуса'], en: ['bus stop', 'bus station'], uk: ['автобусна зупинка', 'зупинка автобуса'], ro: ['stație de autobuz', 'statie de autobuz'], uzLatn: ['avtobus bekati', 'avtobus kanichka', 'avtobus kanichkasi', 'avtobus konichka', 'avtobus konichkasi'], uzCyrl: ['автобус бекати'], kk: ['автобус аялдамасы'] }),
8
+ group('Clinic', { ru: ['поликлиника', 'клиника'], en: ['clinic', 'polyclinic'], uk: ['поліклініка', 'клініка'], ro: ['clinică', 'clinica', 'policlinică', 'policlinica'], uzLatn: ['poliklinika', 'poleklinika', 'klinika'], uzCyrl: ['поликлиника', 'клиника'], kk: ['емхана', 'клиника'] }),
9
+ group('Hospital', { ru: ['больница', 'госпиталь'], en: ['hospital'], uk: ['лікарня', 'госпіталь'], ro: ['spital'], uzLatn: ['shifoxona', 'kasalxona'], uzCyrl: ['шифохона', 'касалхона'], kk: ['аурухана'] }),
10
+ group('School', { ru: ['школа', 'школы', 'школу', 'школе'], en: ['school'], uk: ['школа', 'школи', 'школу'], ro: ['școală', 'scoala'], uzLatn: ['maktab'], uzCyrl: ['мактаб'], kk: ['мектеп'] }),
11
+ group('Kindergarten', { ru: ['детский сад', 'садик'], en: ['kindergarten', 'nursery'], uk: ['дитячий садок', 'садочок'], ro: ['grădiniță', 'gradinita'], uzLatn: ["bolalar bog'chasi", 'bolalar bog‘chasi', 'bogcha'], uzCyrl: ['болалар боғчаси', 'боғча'], kk: ['балабақша'] }),
12
+ group('University', { ru: ['университет', 'институт'], en: ['university', 'institute'], uk: ['університет', 'інститут'], ro: ['universitate', 'institut'], uzLatn: ['universitet', 'institut'], uzCyrl: ['университет', 'институт'], kk: ['университет', 'институт'] }),
13
+ group('Shopping center', { ru: ['тц', 'трц', 'торговый центр'], en: ['shopping center', 'shopping centre', 'mall'], uk: ['тц', 'трц', 'торговий центр'], ro: ['centru comercial', 'mall'], uzLatn: ['savdo markazi', 'mall'], uzCyrl: ['савдо маркази'], kk: ['сауда орталығы', 'сауда үйі'] }),
14
+ group('Supermarket', { ru: ['супермаркет', 'гипермаркет'], en: ['supermarket', 'hypermarket'], uk: ['супермаркет', 'гіпермаркет'], ro: ['supermarket', 'hipermarket'], uzLatn: ['supermarket', 'gipermarket'], uzCyrl: ['супермаркет', 'гипермаркет'], kk: ['супермаркет', 'гипермаркет'] }),
15
+ group('Market', { ru: ['рынок', 'базар'], en: ['market', 'bazaar'], uk: ['ринок', 'базар'], ro: ['piață', 'piata', 'bazar'], uzLatn: ['bozor', 'bazar'], uzCyrl: ['бозор', 'базар'], kk: ['базар', 'нарық'] }),
16
+ group('Pharmacy', { ru: ['аптека'], en: ['pharmacy', 'drugstore'], uk: ['аптека'], ro: ['farmacie'], uzLatn: ['dorixona', 'apteka'], uzCyrl: ['дорихона', 'аптека'], kk: ['дәріхана', 'аптека'] }),
17
+ group('Mosque', { ru: ['мечеть'], en: ['mosque'], uk: ['мечеть'], ro: ['moschee'], uzLatn: ['masjid'], uzCyrl: ['масжид'], kk: ['мешіт'] }),
18
+ group('Church', { ru: ['церковь', 'храм'], en: ['church', 'cathedral'], uk: ['церква', 'храм', 'собор'], ro: ['biserică', 'biserica', 'catedrală', 'catedrala'], uzLatn: ['cherkov', 'ibodatxona'], uzCyrl: ['черков'], kk: ['шіркеу', 'собор'] }),
19
+ group('Railway station', { ru: ['вокзал', 'железнодорожный вокзал'], en: ['railway station', 'train station'], uk: ['вокзал', 'залізничний вокзал'], ro: ['gară', 'gara', 'gară feroviară', 'gara feroviara'], uzLatn: ['vokzal', 'temir yol vokzali', "temir yo'l vokzali"], uzCyrl: ['вокзал', 'темир йўл вокзали'], kk: ['теміржол вокзалы', 'вокзал'] }),
20
+ group('Airport', { ru: ['аэропорт'], en: ['airport'], uk: ['аеропорт'], ro: ['aeroport'], uzLatn: ['aeroport'], uzCyrl: ['аэропорт'], kk: ['әуежай', 'аэропорт'] }),
21
+ ]);
@@ -0,0 +1,58 @@
1
+ export const LEXICON_LANGUAGES = Object.freeze([
2
+ 'all',
3
+ 'ru',
4
+ 'en',
5
+ 'uk',
6
+ 'ro',
7
+ 'uzLatn',
8
+ 'uzCyrl',
9
+ 'kaaLat',
10
+ 'kaaCyrl',
11
+ 'kk',
12
+ ]);
13
+
14
+ export const COUNTRY_CODES = Object.freeze(['UZ', 'KZ', 'UA', 'RO', 'KG']);
15
+
16
+ export function deepFreeze(value, seen = new WeakSet()) {
17
+ if (value == null || (typeof value !== 'object' && typeof value !== 'function')) return value;
18
+ if (seen.has(value)) return value;
19
+ seen.add(value);
20
+
21
+ // Freezing Map/Set objects does not make their entries immutable, so they are
22
+ // intentionally not used as public mutable lexicon indexes. Freeze ordinary
23
+ // nested objects/arrays/regexes only.
24
+ if (value instanceof Map || value instanceof Set) return value;
25
+
26
+ for (const key of Reflect.ownKeys(value)) {
27
+ const child = value[key];
28
+ if (child && (typeof child === 'object' || typeof child === 'function')) deepFreeze(child, seen);
29
+ }
30
+ return Object.freeze(value);
31
+ }
32
+
33
+ export function freezeAliases(aliases = {}) {
34
+ if (Array.isArray(aliases)) return Object.freeze([...aliases]);
35
+ return Object.freeze(Object.fromEntries(
36
+ Object.entries(aliases).map(([language, values]) => [
37
+ language,
38
+ Object.freeze(Array.isArray(values) ? [...values] : []),
39
+ ]),
40
+ ));
41
+ }
42
+
43
+ export function lexiconEntity(canonical, aliases = {}, extra = {}) {
44
+ return deepFreeze({
45
+ ...extra,
46
+ canonical,
47
+ aliases: freezeAliases(aliases),
48
+ });
49
+ }
50
+
51
+ export function locationEntity(canonical, aliases = [], extra = {}) {
52
+ return deepFreeze({
53
+ ...extra,
54
+ canonical,
55
+ name: canonical,
56
+ aliases: Object.freeze([...aliases]),
57
+ });
58
+ }
@@ -0,0 +1,106 @@
1
+ import { aliasesToRegex, normalizeForMatch } from './normalization.js';
2
+
3
+ export const LOCATION_LIST_KEYS = Object.freeze([
4
+ 'districts',
5
+ 'microdistricts',
6
+ 'mahallas',
7
+ 'localAreas',
8
+ 'suburbs',
9
+ 'settlements',
10
+ 'metro',
11
+ 'residentialComplexes',
12
+ 'streets',
13
+ 'landmarks',
14
+ 'pois',
15
+ 'searchClusters',
16
+ ]);
17
+
18
+ export function locationEntry(name, ...aliases) {
19
+ const all = [...new Set([name, ...aliases].flat().filter(Boolean))];
20
+ return Object.freeze({ canonical: name, name, aliases: Object.freeze(all), re: aliasesToRegex(all) });
21
+ }
22
+
23
+ export function locationEntries(rows = []) {
24
+ return Object.freeze(rows.map(([name, ...aliases]) => locationEntry(name, ...aliases)));
25
+ }
26
+
27
+ function mergeEntry(existing, incoming) {
28
+ const aliases = [...new Set([
29
+ ...(existing?.aliases || []),
30
+ ...(incoming?.aliases || []),
31
+ existing?.name,
32
+ incoming?.name,
33
+ ].filter(Boolean))];
34
+ const base = { ...(existing || {}), ...(incoming || {}) };
35
+ return Object.freeze({ ...base, canonical: base.canonical || base.name, type: base.type || base.entityType, aliases: Object.freeze(aliases), re: aliasesToRegex(aliases) });
36
+ }
37
+
38
+ function parentKey(entry) {
39
+ return normalizeForMatch(entry?.parent || entry?.district || '');
40
+ }
41
+
42
+ export function mergeLocationEntries(...lists) {
43
+ const groups = new Map();
44
+ const order = [];
45
+
46
+ for (const list of lists) {
47
+ for (const entry of list || []) {
48
+ if (!entry?.name) continue;
49
+ const canonical = normalizeForMatch(entry.name);
50
+ if (!groups.has(canonical)) {
51
+ groups.set(canonical, []);
52
+ order.push(canonical);
53
+ }
54
+ groups.get(canonical).push(entry);
55
+ }
56
+ }
57
+
58
+ const result = [];
59
+ for (const canonical of order) {
60
+ const group = groups.get(canonical) || [];
61
+ const scopedParents = [...new Set(group.map(parentKey).filter(Boolean))];
62
+
63
+ if (scopedParents.length <= 1) {
64
+ result.push(group.reduce((merged, entry) => mergeEntry(merged, entry), null));
65
+ continue;
66
+ }
67
+
68
+ // A market name can legitimately exist under multiple parents inside one
69
+ // city (for example Sairan in adjacent Almaty districts). Keep each scoped
70
+ // entity. Unscoped/base aliases are merged into every scoped variant so
71
+ // older dictionaries enrich rather than erase parent information.
72
+ const unscoped = group.filter((entry) => !parentKey(entry));
73
+ for (const parent of scopedParents) {
74
+ const scoped = group.filter((entry) => parentKey(entry) === parent);
75
+ result.push([...unscoped, ...scoped].reduce((merged, entry) => mergeEntry(merged, entry), null));
76
+ }
77
+ }
78
+
79
+ return Object.freeze(result);
80
+ }
81
+
82
+ export function mergeLocationCityDictionaries(...dictionaries) {
83
+ const result = {};
84
+ for (const key of LOCATION_LIST_KEYS) {
85
+ const lists = dictionaries.map((dictionary) => dictionary?.[key]).filter(Boolean);
86
+ if (lists.length) result[key] = mergeLocationEntries(...lists);
87
+ }
88
+
89
+ for (const dictionary of dictionaries) {
90
+ if (!dictionary) continue;
91
+ for (const [key, value] of Object.entries(dictionary)) {
92
+ if (LOCATION_LIST_KEYS.includes(key) || value == null) continue;
93
+ result[key] = value;
94
+ }
95
+ }
96
+
97
+ return Object.freeze(result);
98
+ }
99
+
100
+ export function mergeLocationCountries(...countries) {
101
+ const cityNames = [...new Set(countries.flatMap((country) => Object.keys(country || {})))];
102
+ return Object.freeze(Object.fromEntries(cityNames.map((city) => [
103
+ city,
104
+ mergeLocationCityDictionaries(...countries.map((country) => country?.[city]).filter(Boolean)),
105
+ ])));
106
+ }