@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,211 @@
1
+ import { LOCATION_DICTIONARIES } from './locations.js';
2
+ import { LOCATION_LIST_KEYS, mergeLocationCountries } from './location-merge.js';
3
+ import { aliasesOf, aliasesToRegex, normalizeForMatch } from './normalization.js';
4
+ import {
5
+ KZ_CITY_CATALOG,
6
+ UZ_CITY_CATALOG,
7
+ canonicalKazakhstanCity,
8
+ canonicalUzbekistanCity,
9
+ } from './central-asia.js';
10
+ import { KZ_AMBIGUOUS_LOCAL_NAMES, KZ_LOCATION_EXTENSIONS, KZ_SEARCH_CLUSTERS } from './kz-location-extensions.js';
11
+ import { UZ_AMBIGUOUS_LOCAL_NAMES, UZ_LOCATION_EXTENSIONS } from './uz-location-extensions.js';
12
+
13
+ export const KZ_EXPANDED_LOCATION_DICTIONARIES = mergeLocationCountries(
14
+ LOCATION_DICTIONARIES.KZ || {},
15
+ KZ_LOCATION_EXTENSIONS,
16
+ );
17
+
18
+ export const UZ_EXPANDED_LOCATION_DICTIONARIES = mergeLocationCountries(
19
+ LOCATION_DICTIONARIES.UZ || {},
20
+ UZ_LOCATION_EXTENSIONS,
21
+ );
22
+
23
+ export const CENTRAL_ASIA_LOCATION_DICTIONARIES = Object.freeze({
24
+ KZ: KZ_EXPANDED_LOCATION_DICTIONARIES,
25
+ UZ: UZ_EXPANDED_LOCATION_DICTIONARIES,
26
+ });
27
+
28
+ const TYPE_BY_KEY = Object.freeze({
29
+ districts: 'district',
30
+ microdistricts: 'microdistrict',
31
+ mahallas: 'mahalla',
32
+ localAreas: 'local_area',
33
+ suburbs: 'suburb',
34
+ settlements: 'settlement',
35
+ metro: 'metro',
36
+ residentialComplexes: 'residential_complex',
37
+ streets: 'street',
38
+ landmarks: 'poi',
39
+ pois: 'poi',
40
+ searchClusters: 'search_cluster',
41
+ });
42
+
43
+ const GENERIC_AMBIGUOUS = new Set([
44
+ 'center', 'old city', 'new city', 'airport', 'railway station area', 'university area',
45
+ 'central park', 'embankment', 'bazaar', 'market', 'north', 'east', 'south west',
46
+ ]);
47
+
48
+ const KZ_AMBIGUOUS = new Set(KZ_AMBIGUOUS_LOCAL_NAMES.map(normalizeForMatch));
49
+ const UZ_AMBIGUOUS = new Set(UZ_AMBIGUOUS_LOCAL_NAMES.map(normalizeForMatch));
50
+
51
+ function cityCatalog(countryCode) {
52
+ return countryCode === 'KZ' ? KZ_CITY_CATALOG : countryCode === 'UZ' ? UZ_CITY_CATALOG : [];
53
+ }
54
+
55
+ function dictionaries(countryCode) {
56
+ return CENTRAL_ASIA_LOCATION_DICTIONARIES[countryCode] || {};
57
+ }
58
+
59
+ function canonicalCity(value, countryCode) {
60
+ return countryCode === 'KZ'
61
+ ? canonicalKazakhstanCity(value)
62
+ : countryCode === 'UZ'
63
+ ? canonicalUzbekistanCity(value)
64
+ : null;
65
+ }
66
+
67
+ const cityRegexCache = new Map();
68
+ function cityRegex(item) {
69
+ const key = `${item.country}:${item.canonical}`;
70
+ if (!cityRegexCache.has(key)) {
71
+ cityRegexCache.set(key, aliasesToRegex([item.canonical, ...aliasesOf(item)]));
72
+ }
73
+ return cityRegexCache.get(key);
74
+ }
75
+
76
+ function explicitCityFromText(text, countryCode) {
77
+ const value = String(text || '');
78
+ const matches = [];
79
+ for (const item of cityCatalog(countryCode)) {
80
+ const match = value.match(cityRegex(item));
81
+ if (!match) continue;
82
+ if (item.contextRequired) {
83
+ const start = match.index || 0;
84
+ const before = value.slice(Math.max(0, start - 40), start);
85
+ const after = value.slice(start + match[0].length, start + match[0].length + 48);
86
+ if (!/(?:shahri|город|viloyati|область|andijon|андижан)/iu.test(`${before} ${after}`)) continue;
87
+ }
88
+ matches.push({ item, length: normalizeForMatch(match[0]).length });
89
+ }
90
+ matches.sort((a, b) => b.length - a.length);
91
+ return matches[0]?.item?.canonical || null;
92
+ }
93
+
94
+ function isExplicitMetroContext(value, match) {
95
+ const start = match.index ?? 0;
96
+ const end = start + match[0].length;
97
+ const before = value.slice(Math.max(0, start - 36), start);
98
+ const after = value.slice(end, end + 36);
99
+ return /(?:метро|metro|станц(?:ия|ии)?|station|ст\.?\s*м\.?|м\.)\s*[:\-–—]?\s*$/iu.test(before)
100
+ || /^\s*(?:метро|metro|station|станц(?:ия|ии)?)(?=$|[^\p{L}\p{N}_])/iu.test(after);
101
+ }
102
+
103
+ function metroOverlapsArea(item, data) {
104
+ const itemKeys = new Set([item.name, ...(item.aliases || [])].map(normalizeForMatch).filter(Boolean));
105
+ return ['microdistricts', 'localAreas'].some((key) => (data?.[key] || []).some((area) =>
106
+ [area.name, ...(area.aliases || [])].map(normalizeForMatch).some((value) => itemKeys.has(value)),
107
+ ));
108
+ }
109
+
110
+ function findEntryMatches(text, cityName, data) {
111
+ const value = String(text || '');
112
+ const matches = [];
113
+ for (const key of LOCATION_LIST_KEYS) {
114
+ for (const item of data?.[key] || []) {
115
+ const match = value.match(item?.re);
116
+ if (!match) continue;
117
+ if (key === 'metro' && metroOverlapsArea(item, data) && !isExplicitMetroContext(value, match)) continue;
118
+ matches.push(Object.freeze({
119
+ country: item.country || null,
120
+ city: cityName,
121
+ type: item.entityType || TYPE_BY_KEY[key] || key,
122
+ key,
123
+ name: item.name,
124
+ aliases: item.aliases || [],
125
+ district: item.district || null,
126
+ parent: item.parent || item.district || null,
127
+ confidence: item.confidence || null,
128
+ language: item.language || null,
129
+ }));
130
+ }
131
+ }
132
+ return matches;
133
+ }
134
+
135
+ function isAmbiguousMatch(match, countryCode) {
136
+ const keys = [match.name, ...(match.aliases || [])].map(normalizeForMatch).filter(Boolean);
137
+ if (keys.some((key) => GENERIC_AMBIGUOUS.has(key))) return true;
138
+ if (countryCode === 'KZ' && keys.some((key) => KZ_AMBIGUOUS.has(key))) return true;
139
+ if (countryCode === 'UZ' && keys.some((key) => UZ_AMBIGUOUS.has(key))) return true;
140
+ return false;
141
+ }
142
+
143
+ function clusterMatches(matches, countryCode) {
144
+ if (countryCode !== 'KZ') return [];
145
+ const names = new Set(matches.map((item) => normalizeForMatch(item.name)));
146
+ return KZ_SEARCH_CLUSTERS.filter((cluster) => cluster.members.some((member) => names.has(normalizeForMatch(member))));
147
+ }
148
+
149
+ export function centralAsiaLocationCities(countryCode) {
150
+ return dictionaries(countryCode);
151
+ }
152
+
153
+ export function centralAsiaLocationCity(countryCode, city) {
154
+ const canonical = canonicalCity(city, countryCode) || city;
155
+ return dictionaries(countryCode)[canonical] || null;
156
+ }
157
+
158
+ export function matchCentralAsiaLocationEntities(text, countryCode, preferredCity = null) {
159
+ if (!text || !['KZ', 'UZ'].includes(countryCode)) {
160
+ return Object.freeze({ city: null, matches: Object.freeze([]), searchClusters: Object.freeze([]), candidates: Object.freeze([]) });
161
+ }
162
+
163
+ const country = dictionaries(countryCode);
164
+ const preferred = canonicalCity(preferredCity, countryCode) || preferredCity;
165
+ const explicit = explicitCityFromText(text, countryCode);
166
+ const scopedCity = preferred && country[preferred] ? preferred : explicit && country[explicit] ? explicit : null;
167
+
168
+ if (scopedCity) {
169
+ const matches = findEntryMatches(text, scopedCity, country[scopedCity]);
170
+ const clusters = clusterMatches(matches, countryCode);
171
+ return Object.freeze({ city: scopedCity, matches: Object.freeze(matches), searchClusters: Object.freeze(clusters), candidates: Object.freeze([]) });
172
+ }
173
+
174
+ const byCity = [];
175
+ for (const [cityName, data] of Object.entries(country)) {
176
+ const matches = findEntryMatches(text, cityName, data);
177
+ if (matches.length) byCity.push({ city: cityName, matches });
178
+ }
179
+
180
+ if (!byCity.length) {
181
+ return Object.freeze({ city: null, matches: Object.freeze([]), searchClusters: Object.freeze([]), candidates: Object.freeze([]) });
182
+ }
183
+
184
+ // Numeric microdistricts and common names such as Samal/Center occur in many
185
+ // cities. Without an explicit/structured city we must not silently assign a
186
+ // parent. Prefer a city only when it owns at least one non-ambiguous match
187
+ // that no other city matched.
188
+ const strong = byCity.filter((candidate) => candidate.matches.some((match) => !isAmbiguousMatch(match, countryCode)));
189
+ const selected = strong.length === 1
190
+ ? strong[0]
191
+ : byCity.length === 1 && byCity[0].matches.some((match) => !isAmbiguousMatch(match, countryCode))
192
+ ? byCity[0]
193
+ : null;
194
+
195
+ if (!selected) {
196
+ return Object.freeze({
197
+ city: null,
198
+ matches: Object.freeze([]),
199
+ searchClusters: Object.freeze([]),
200
+ candidates: Object.freeze(byCity.map((candidate) => Object.freeze({ city: candidate.city, matches: Object.freeze(candidate.matches) }))),
201
+ });
202
+ }
203
+
204
+ const clusters = clusterMatches(selected.matches, countryCode);
205
+ return Object.freeze({ city: selected.city, matches: Object.freeze(selected.matches), searchClusters: Object.freeze(clusters), candidates: Object.freeze([]) });
206
+ }
207
+
208
+ export function matchCentralAsiaLocationEntity(text, countryCode, preferredCity = null, type = null) {
209
+ const result = matchCentralAsiaLocationEntities(text, countryCode, preferredCity);
210
+ return result.matches.find((item) => !type || item.type === type || item.key === type) || null;
211
+ }
@@ -0,0 +1,233 @@
1
+ import { KZ_CITIES, UZ_CITIES } from './geo.js';
2
+ import { aliasesOf, findCanonical, normalizeForMatch } from './normalization.js';
3
+
4
+ const freezeAliases = (aliases = {}) => Object.freeze(Object.fromEntries(
5
+ Object.entries(aliases).map(([lang, values]) => {
6
+ const seen = new Set();
7
+ const deduped = (values || []).filter((alias) => {
8
+ const key = normalizeForMatch(alias);
9
+ if (!key || seen.has(key)) return false;
10
+ seen.add(key);
11
+ return true;
12
+ });
13
+ return [lang, Object.freeze(deduped)];
14
+ }),
15
+ ));
16
+
17
+ const city = (canonical, aliases, extra = {}) => Object.freeze({
18
+ ...extra,
19
+ canonical,
20
+ aliases: freezeAliases(aliases),
21
+ });
22
+
23
+ function mergeCatalog(base, additions) {
24
+ const order = [];
25
+ const byCanonical = new Map();
26
+ for (const item of [...base, ...additions]) {
27
+ if (!item?.canonical) continue;
28
+ if (!byCanonical.has(item.canonical)) order.push(item.canonical);
29
+ const previous = byCanonical.get(item.canonical);
30
+ if (!previous) {
31
+ byCanonical.set(item.canonical, item);
32
+ continue;
33
+ }
34
+ const languages = [...new Set([...Object.keys(previous.aliases || {}), ...Object.keys(item.aliases || {})])];
35
+ const aliases = Object.fromEntries(languages.map((lang) => {
36
+ const seen = new Set();
37
+ const values = [...(previous.aliases?.[lang] || []), ...(item.aliases?.[lang] || [])].filter((alias) => {
38
+ const key = normalizeForMatch(alias);
39
+ if (!key || seen.has(key)) return false;
40
+ seen.add(key);
41
+ return true;
42
+ });
43
+ return [lang, values];
44
+ }));
45
+ const { aliases: _previousAliases, ...previousMeta } = previous;
46
+ const { aliases: _itemAliases, ...itemMeta } = item;
47
+ byCanonical.set(item.canonical, city(item.canonical, aliases, { ...previousMeta, ...itemMeta }));
48
+ }
49
+ return Object.freeze(order.map((name) => byCanonical.get(name)));
50
+ }
51
+
52
+ export const KZ_CITY_ADDITIONS = Object.freeze([
53
+ city('Almaty', { kk: ['Алматы'], ru: ['Алма-Ата', 'Алма Ата', 'Верный'], en: ['Alma-Ata', 'Alma Ata', 'Verny'] }, { country: 'KZ', priority: 'P0' }),
54
+ city('Astana', { kk: ['Астана', 'Нұр-Сұлтан', 'Нұр Сұлтан', 'Ақмола'], ru: ['Астана', 'Нур-Султан', 'Нур Султан', 'Акмолинск', 'Акмола', 'Целиноград'], en: ['Astana', 'Nur-Sultan', 'Nur Sultan', 'Akmolinsk', 'Aqmola', 'Tselinograd'] }, { country: 'KZ', priority: 'P0' }),
55
+ city('Shymkent', { kk: ['Шымкент'], ru: ['Шымкент', 'Чимкент', 'Чымкент'], en: ['Shymkent', 'Chimkent'] }, { country: 'KZ', priority: 'P0' }),
56
+ city('Karaganda', { kk: ['Қарағанды'], ru: ['Караганда', 'Караганды'], en: ['Karaganda', 'Qaragandy', 'Karagandy'] }, { country: 'KZ', priority: 'P1' }),
57
+ city('Aktobe', { kk: ['Ақтөбе'], ru: ['Актобе', 'Актюбинск'], en: ['Aktobe', 'Aqtobe', 'Aktyubinsk'] }, { country: 'KZ', priority: 'P1' }),
58
+ city('Taraz', { kk: ['Тараз', 'Жамбыл', 'Әулие-Ата'], ru: ['Тараз', 'Джамбул', 'Жамбыл', 'Аулие-Ата'], en: ['Taraz', 'Dzhambul', 'Jambyl', 'Aulie-Ata'] }, { country: 'KZ', priority: 'P1' }),
59
+ city('Pavlodar', { kk: ['Павлодар'], ru: ['Павлодар'], en: ['Pavlodar'] }, { country: 'KZ', priority: 'P1' }),
60
+ city('Oskemen', { kk: ['Өскемен'], ru: ['Усть-Каменогорск', 'Усть Каменогорск', 'Оскемен'], en: ['Oskemen', 'Ust-Kamenogorsk', 'Ust Kamenogorsk'] }, { country: 'KZ', priority: 'P1' }),
61
+ city('Semey', { kk: ['Семей'], ru: ['Семей', 'Семипалатинск'], en: ['Semey', 'Semipalatinsk'] }, { country: 'KZ', priority: 'P1' }),
62
+ city('Atyrau', { kk: ['Атырау'], ru: ['Атырау', 'Гурьев'], en: ['Atyrau', 'Guryev', 'Guriev'] }, { country: 'KZ', priority: 'P1' }),
63
+ city('Aktau', { kk: ['Ақтау'], ru: ['Актау', 'Шевченко'], en: ['Aktau', 'Aqtau', 'Shevchenko'] }, { country: 'KZ', priority: 'P1' }),
64
+ city('Kostanay', { kk: ['Қостанай'], ru: ['Костанай', 'Кустанай'], en: ['Kostanay', 'Qostanay', 'Kustanay'] }, { country: 'KZ', priority: 'P2' }),
65
+ city('Kyzylorda', { kk: ['Қызылорда', 'Ақмешіт'], ru: ['Кызылорда', 'Ак-Мечеть', 'Перовск'], en: ['Kyzylorda', 'Qyzylorda', 'Kzyl-Orda', 'Ak-Mechet', 'Perovsk'] }, { country: 'KZ', priority: 'P2' }),
66
+ city('Oral', { kk: ['Орал'], ru: ['Орал', 'Уральск'], en: ['Oral', 'Uralsk'] }, { country: 'KZ', priority: 'P2' }),
67
+ city('Petropavl', { kk: ['Петропавл'], ru: ['Петропавловск', 'Петропавл'], en: ['Petropavl', 'Petropavlovsk'] }, { country: 'KZ', priority: 'P2' }),
68
+ city('Taldykorgan', { kk: ['Талдықорған'], ru: ['Талдыкорган', 'Талды-Курган'], en: ['Taldykorgan', 'Taldyqorgan', 'Taldy-Kurgan'] }, { country: 'KZ', priority: 'P2' }),
69
+ city('Turkistan', { kk: ['Түркістан'], ru: ['Туркестан'], en: ['Turkistan', 'Turkestan'] }, { country: 'KZ', priority: 'P2' }),
70
+ city('Kokshetau', { kk: ['Көкшетау'], ru: ['Кокшетау', 'Кокчетав'], en: ['Kokshetau', 'Kokchetav'] }, { country: 'KZ', priority: 'P2' }),
71
+ city('Temirtau', { kk: ['Теміртау'], ru: ['Темиртау'], en: ['Temirtau'] }, { country: 'KZ', priority: 'P3' }),
72
+ city('Ekibastuz', { kk: ['Екібастұз'], ru: ['Экибастуз'], en: ['Ekibastuz'] }, { country: 'KZ', priority: 'P3' }),
73
+ city('Rudny', { kk: ['Рудный'], ru: ['Рудный'], en: ['Rudny', 'Rudnyi'] }, { country: 'KZ', priority: 'P3' }),
74
+ city('Zhezkazgan', { kk: ['Жезқазған'], ru: ['Жезказган'], en: ['Zhezkazgan', 'Jezkazgan', 'Dzhezkazgan'] }, { country: 'KZ', priority: 'P3' }),
75
+ city('Balkhash', { kk: ['Балқаш'], ru: ['Балхаш'], en: ['Balkhash', 'Balqash'] }, { country: 'KZ', priority: 'P3' }),
76
+ city('Konaev', { kk: ['Қонаев', 'Қапшағай'], ru: ['Конаев', 'Капчагай'], en: ['Konaev', 'Qonaev', 'Kapshagay', 'Kapchagai', 'Qapshagai'] }, { country: 'KZ', priority: 'P3' }),
77
+ city('Zhanaozen', { kk: ['Жаңаөзен'], ru: ['Жанаозен'], en: ['Zhanaozen', 'Zhanaözen', 'New Uzen'] }, { country: 'KZ', priority: 'P3' }),
78
+ city('Satbayev', { kk: ['Сәтбаев'], ru: ['Сатпаев', 'Никольский'], en: ['Satbayev', 'Satpaev', 'Nikolsky'] }, { country: 'KZ', priority: 'P3' }),
79
+ city('Kosshy', { kk: ['Қосшы'], ru: ['Косшы'], en: ['Kosshy', 'Qosshy', 'Koschi'] }, { country: 'KZ', priority: 'P3' }),
80
+ city('Arys', { kk: ['Арыс'], ru: ['Арыс'], en: ['Arys'] }, { country: 'KZ', priority: 'P3' }),
81
+ city('Kentau', { kk: ['Кентау'], ru: ['Кентау'], en: ['Kentau'] }, { country: 'KZ', priority: 'P3' }),
82
+ city('Saryagash', { kk: ['Сарыағаш'], ru: ['Сарыагаш'], en: ['Saryagash'] }, { country: 'KZ', priority: 'P3' }),
83
+ city('Stepnogorsk', { kk: ['Степногорск'], ru: ['Степногорск'], en: ['Stepnogorsk'] }, { country: 'KZ', priority: 'P4' }),
84
+ city('Atbasar', { kk: ['Атбасар'], ru: ['Атбасар'], en: ['Atbasar'] }, { country: 'KZ', priority: 'P4' }),
85
+ city('Shchuchinsk', { kk: ['Щучинск'], ru: ['Щучинск'], en: ['Shchuchinsk'] }, { country: 'KZ', priority: 'P4' }),
86
+ city('Makinsk', { kk: ['Макинск'], ru: ['Макинск'], en: ['Makinsk'] }, { country: 'KZ', priority: 'P4' }),
87
+ city('Ereymentau', { kk: ['Ерейментау'], ru: ['Ерейментау'], en: ['Ereymentau'] }, { country: 'KZ', priority: 'P4' }),
88
+ city('Akkol', { kk: ['Ақкөл'], ru: ['Акколь'], en: ['Akkol', 'Aqkol'] }, { country: 'KZ', priority: 'P4' }),
89
+ city('Kaskelen', { kk: ['Қаскелең'], ru: ['Каскелен'], en: ['Kaskelen'] }, { country: 'KZ', priority: 'P4' }),
90
+ city('Talgar', { kk: ['Талғар'], ru: ['Талгар'], en: ['Talgar'] }, { country: 'KZ', priority: 'P4' }),
91
+ city('Esik', { kk: ['Есік'], ru: ['Есик'], en: ['Esik', 'Issyk'] }, { country: 'KZ', priority: 'P4' }),
92
+ city('Shelek', { kk: ['Шелек'], ru: ['Шелек'], en: ['Shelek'] }, { country: 'KZ', priority: 'P4' }),
93
+ city('Uzynagash', { kk: ['Ұзынағаш'], ru: ['Узынагаш'], en: ['Uzynagash'] }, { country: 'KZ', priority: 'P4' }),
94
+ city('Zharkent', { kk: ['Жаркент'], ru: ['Жаркент'], en: ['Zharkent'] }, { country: 'KZ', priority: 'P4' }),
95
+ city('Tekeli', { kk: ['Текелі'], ru: ['Текели'], en: ['Tekeli'] }, { country: 'KZ', priority: 'P4' }),
96
+ city('Usharal', { kk: ['Үшарал'], ru: ['Ушарал'], en: ['Usharal'] }, { country: 'KZ', priority: 'P4' }),
97
+ city('Saran', { kk: ['Саран'], ru: ['Сарань'], en: ['Saran'] }, { country: 'KZ', priority: 'P4' }),
98
+ city('Shakhtinsk', { kk: ['Шахтинск'], ru: ['Шахтинск'], en: ['Shakhtinsk'] }, { country: 'KZ', priority: 'P4' }),
99
+ city('Abai', { kk: ['Абай'], ru: ['Абай'], en: ['Abai'] }, { country: 'KZ', priority: 'P4' }),
100
+ city('Priozersk', { kk: ['Приозерск'], ru: ['Приозёрск'], en: ['Priozersk'] }, { country: 'KZ', priority: 'P4' }),
101
+ city('Karkaralinsk', { kk: ['Қарқаралы'], ru: ['Каркаралинск'], en: ['Karkaralinsk', 'Karkaraly'] }, { country: 'KZ', priority: 'P4' }),
102
+ city('Aksu', { kk: ['Ақсу'], ru: ['Аксу'], en: ['Aksu', 'Aqsu'] }, { country: 'KZ', priority: 'P4' }),
103
+ city('Ridder', { kk: ['Риддер'], ru: ['Риддер'], en: ['Ridder'] }, { country: 'KZ', priority: 'P4' }),
104
+ city('Altai', { kk: ['Алтай'], ru: ['Алтай', 'Зыряновск'], en: ['Altai', 'Zyryanovsk'] }, { country: 'KZ', priority: 'P4' }),
105
+ city('Serebryansk', { kk: ['Серебрянск'], ru: ['Серебрянск'], en: ['Serebryansk'] }, { country: 'KZ', priority: 'P4' }),
106
+ city('Shemonaikha', { kk: ['Шемонаиха'], ru: ['Шемонаиха'], en: ['Shemonaikha'] }, { country: 'KZ', priority: 'P4' }),
107
+ city('Kurchatov', { kk: ['Курчатов'], ru: ['Курчатов'], en: ['Kurchatov'] }, { country: 'KZ', priority: 'P4' }),
108
+ city('Ayagoz', { kk: ['Аягөз'], ru: ['Аягоз'], en: ['Ayagoz'] }, { country: 'KZ', priority: 'P4' }),
109
+ city('Khromtau', { kk: ['Хромтау'], ru: ['Хромтау'], en: ['Khromtau'] }, { country: 'KZ', priority: 'P4' }),
110
+ city('Alga', { kk: ['Алға'], ru: ['Алга'], en: ['Alga'] }, { country: 'KZ', priority: 'P4' }),
111
+ city('Kandyagash', { kk: ['Қандыағаш'], ru: ['Кандыагаш'], en: ['Kandyagash'] }, { country: 'KZ', priority: 'P4' }),
112
+ city('Shalkar', { kk: ['Шалқар'], ru: ['Шалкар'], en: ['Shalkar'] }, { country: 'KZ', priority: 'P4' }),
113
+ city('Kulsary', { kk: ['Құлсары'], ru: ['Кульсары'], en: ['Kulsary'] }, { country: 'KZ', priority: 'P4' }),
114
+ city('Dossor', { kk: ['Доссор'], ru: ['Доссор'], en: ['Dossor'] }, { country: 'KZ', priority: 'P4' }),
115
+ city('Fort-Shevchenko', { kk: ['Форт-Шевченко'], ru: ['Форт-Шевченко'], en: ['Fort-Shevchenko'] }, { country: 'KZ', priority: 'P4' }),
116
+ city('Lisakovsk', { kk: ['Лисаковск'], ru: ['Лисаковск'], en: ['Lisakovsk'] }, { country: 'KZ', priority: 'P4' }),
117
+ city('Arkalyk', { kk: ['Арқалық'], ru: ['Аркалык'], en: ['Arkalyk'] }, { country: 'KZ', priority: 'P4' }),
118
+ city('Tobyl', { kk: ['Тобыл'], ru: ['Тобыл'], en: ['Tobyl'] }, { country: 'KZ', priority: 'P4' }),
119
+ city('Zhitikara', { kk: ['Жітіқара'], ru: ['Житикара'], en: ['Zhitikara'] }, { country: 'KZ', priority: 'P4' }),
120
+ city('Aksai', { kk: ['Ақсай'], ru: ['Аксай'], en: ['Aksai'] }, { country: 'KZ', priority: 'P4' }),
121
+ city('Baikonur', { kk: ['Байқоңыр'], ru: ['Байконур'], en: ['Baikonur'] }, { country: 'KZ', priority: 'P4', type: 'special_status_city' }),
122
+ city('Aral', { kk: ['Арал'], ru: ['Аральск', 'Арал'], en: ['Aral', 'Aralsk'] }, { country: 'KZ', priority: 'P4' }),
123
+ city('Kazaly', { kk: ['Қазалы'], ru: ['Казалинск', 'Казалы'], en: ['Kazaly', 'Kazalinsk'] }, { country: 'KZ', priority: 'P4' }),
124
+ city('Shu', { kk: ['Шу'], ru: ['Шу'], en: ['Shu'] }, { country: 'KZ', priority: 'P4' }),
125
+ city('Karatau', { kk: ['Қаратау'], ru: ['Каратау'], en: ['Karatau'] }, { country: 'KZ', priority: 'P4' }),
126
+ city('Zhanatas', { kk: ['Жаңатас'], ru: ['Жанатас'], en: ['Zhanatas'] }, { country: 'KZ', priority: 'P4' }),
127
+ city('Merke', { kk: ['Мерке'], ru: ['Мерке'], en: ['Merke'] }, { country: 'KZ', priority: 'P4' }),
128
+ city('Zhetysai', { kk: ['Жетісай'], ru: ['Жетысай'], en: ['Zhetysai'] }, { country: 'KZ', priority: 'P4' }),
129
+ city('Lenger', { kk: ['Леңгір'], ru: ['Ленгер'], en: ['Lenger'] }, { country: 'KZ', priority: 'P4' }),
130
+ city('Shardara', { kk: ['Шардара'], ru: ['Шардара'], en: ['Shardara'] }, { country: 'KZ', priority: 'P4' }),
131
+ ]);
132
+
133
+ export const KZ_CITY_CATALOG = mergeCatalog(KZ_CITIES, KZ_CITY_ADDITIONS);
134
+
135
+ export const KZ_SEARCH_TARGETS = Object.freeze([
136
+ city('Burabay', { kk: ['Бурабай'], ru: ['Бурабай', 'Боровое'], en: ['Burabay', 'Borovoe'] }, { country: 'KZ', type: 'resort', priority: 'P4' }),
137
+ city('Zerenda', { kk: ['Зеренді'], ru: ['Зеренда'], en: ['Zerenda'] }, { country: 'KZ', type: 'resort', priority: 'P4' }),
138
+ city('Bayanaul', { kk: ['Баянауыл'], ru: ['Баянаул'], en: ['Bayanaul'] }, { country: 'KZ', type: 'resort', priority: 'P4' }),
139
+ ]);
140
+
141
+ export const UZ_CITY_ADDITIONS = Object.freeze([
142
+ city('Tashkent', { uzLatn: ['Toshkent', 'Toshkent shahri'], uzCyrl: ['Тошкент', 'Тошкент шаҳри'], ru: ['Ташкент', 'город Ташкент'], en: ['Tashkent'] }, { country: 'UZ', priority: 'P0' }),
143
+ city('Samarkand', { uzLatn: ['Samarqand', 'Samarqand shahri'], uzCyrl: ['Самарқанд'], ru: ['Самарканд', 'г. Самарканд'], en: ['Samarkand', 'Samarqand'] }, { country: 'UZ', priority: 'P0', localCanonical: 'Samarqand' }),
144
+ city('Namangan', { uzLatn: ['Namangan', 'Namangan shahri'], uzCyrl: ['Наманган шаҳри'], ru: ['Наманган'], en: ['Namangan'] }, { country: 'UZ', priority: 'P0' }),
145
+ city('Andijan', { uzLatn: ['Andijon', 'Andijon shahri', 'Andijan', 'Andizhan'], uzCyrl: ['Андижон'], ru: ['Андижан'], en: ['Andijan', 'Andizhan'] }, { country: 'UZ', priority: 'P0', localCanonical: 'Andijon' }),
146
+ city('Fergana', { uzLatn: ["Farg'ona", 'Fargona', "Farg'ona shahri"], uzCyrl: ['Фарғона', 'Фаргона'], ru: ['Фергана'], en: ['Fergana', 'Ferghana'] }, { country: 'UZ', priority: 'P0', localCanonical: "Farg'ona" }),
147
+ city('Bukhara', { uzLatn: ['Buxoro', 'Buxoro shahri'], uzCyrl: ['Бухоро'], ru: ['Бухара'], en: ['Bukhara', 'Buchara'] }, { country: 'UZ', priority: 'P0', localCanonical: 'Buxoro' }),
148
+ city('Qarshi', { uzLatn: ['Qarshi', 'Qarshi shahri', 'Karshi'], uzCyrl: ['Қарши'], ru: ['Карши'], en: ['Qarshi', 'Karshi'] }, { country: 'UZ', priority: 'P0' }),
149
+ city('Nukus', { uzLatn: ['Nukus', 'Nukus shahri'], uzCyrl: ['Нукус'], kaaLat: ['Nókis'], kaaCyrl: ['Нөкис', 'Нөкис қаласы'], ru: ['Нукус'], en: ['Nukus'] }, { country: 'UZ', priority: 'P0', region: "Qoraqalpog'iston" }),
150
+ city('Urgench', { uzLatn: ['Urganch', 'Urganch shahri', 'Urgench'], uzCyrl: ['Урганч'], ru: ['Ургенч'], en: ['Urgench', 'Urganch'] }, { country: 'UZ', priority: 'P0', localCanonical: 'Urganch' }),
151
+ city('Kokand', { uzLatn: ["Qo'qon", 'Qo‘qon', 'Qoqon'], uzCyrl: ['Қўқон'], ru: ['Коканд'], en: ['Kokand', 'Kokon'] }, { country: 'UZ', priority: 'P1', localCanonical: "Qo'qon" }),
152
+ city('Margilan', { uzLatn: ["Marg'ilon", 'Marg‘ilon', 'Margilon'], uzCyrl: ['Марғилон'], ru: ['Маргилан'], en: ['Margilan', 'Marghelan'] }, { country: 'UZ', priority: 'P1', localCanonical: "Marg'ilon" }),
153
+ city('Jizzakh', { uzLatn: ['Jizzax', 'Jizzakh'], uzCyrl: ['Жиззах'], ru: ['Джизак'], en: ['Jizzakh', 'Djizak'] }, { country: 'UZ', priority: 'P1', localCanonical: 'Jizzax' }),
154
+ city('Navoiy', { uzLatn: ['Navoiy', 'Navoi'], uzCyrl: ['Навоий'], ru: ['Навои'], en: ['Navoiy', 'Navoi'] }, { country: 'UZ', priority: 'P1' }),
155
+ city('Termez', { uzLatn: ['Termiz', 'Termiz shahri'], uzCyrl: ['Термиз'], ru: ['Термез'], en: ['Termez', 'Termiz'] }, { country: 'UZ', priority: 'P1', localCanonical: 'Termiz' }),
156
+ city('Gulistan', { uzLatn: ['Guliston', 'Gulistan'], uzCyrl: ['Гулистон'], ru: ['Гулистан'], en: ['Gulistan', 'Guliston'] }, { country: 'UZ', priority: 'P1', localCanonical: 'Guliston' }),
157
+ city('Chirchiq', { uzLatn: ['Chirchiq', 'Chirchik'], uzCyrl: ['Чирчиқ'], ru: ['Чирчик'], en: ['Chirchiq', 'Chirchik'] }, { country: 'UZ', priority: 'P1' }),
158
+ city('Almalyk', { uzLatn: ['Olmaliq', 'Almalyk'], uzCyrl: ['Олмалиқ'], ru: ['Алмалык'], en: ['Almalyk', 'Olmaliq'] }, { country: 'UZ', priority: 'P1', localCanonical: 'Olmaliq' }),
159
+ city('Angren', { uzLatn: ['Angren'], uzCyrl: ['Ангрен'], ru: ['Ангрен'], en: ['Angren'] }, { country: 'UZ', priority: 'P1' }),
160
+ city('Bekabad', { uzLatn: ['Bekobod', 'Bekabad'], uzCyrl: ['Бекобод'], ru: ['Бекабад', 'Бекобод'], en: ['Bekabad', 'Bekobod'] }, { country: 'UZ', priority: 'P1', localCanonical: 'Bekobod' }),
161
+ city('Shakhrisabz', { uzLatn: ['Shahrisabz', 'Shakhrisabz', 'Shahr-i Sabz'], uzCyrl: ['Шаҳрисабз'], ru: ['Шахрисабз'], en: ['Shakhrisabz', 'Shahrisabz'] }, { country: 'UZ', priority: 'P2', localCanonical: 'Shahrisabz' }),
162
+ city('Khiva', { uzLatn: ['Xiva', 'Khiva'], uzCyrl: ['Хива'], ru: ['Хива'], en: ['Khiva', 'Chiwa'] }, { country: 'UZ', priority: 'P2', localCanonical: 'Xiva' }),
163
+ city('Denov', { uzLatn: ['Denov', 'Denau'], uzCyrl: ['Денов'], ru: ['Денау', 'Денов'], en: ['Denov', 'Denau'] }, { country: 'UZ', priority: 'P2' }),
164
+ city('Asaka', { uzLatn: ['Asaka', 'Assaka'], uzCyrl: ['Асака'], ru: ['Асака'], en: ['Asaka'] }, { country: 'UZ', priority: 'P2' }),
165
+ city('Kogon', { uzLatn: ['Kogon', 'Yangi Buxoro'], uzCyrl: ['Когон'], ru: ['Каган', 'Когон', 'Новая Бухара'], en: ['Kogon', 'Kagan'] }, { country: 'UZ', priority: 'P2' }),
166
+ city('Kattakurgan', { uzLatn: ["Kattaqo'rg'on", 'Kattaqo‘rg‘on', 'Kattakurgan'], uzCyrl: ['Каттақўрғон'], ru: ['Каттакурган'], en: ['Kattakurgan'] }, { country: 'UZ', priority: 'P2', localCanonical: "Kattaqo'rg'on" }),
167
+ city('Urgut', { uzLatn: ['Urgut', 'Urgut shahri'], uzCyrl: ['Ургут'], ru: ['Ургут'], en: ['Urgut'] }, { country: 'UZ', priority: 'P2' }),
168
+ city('Yangiyol', { uzLatn: ["Yangiyo'l", 'Yangiyo‘l', 'Yangiyul'], uzCyrl: ['Янги йўл', 'Янгийўл'], ru: ['Янгиюль'], en: ['Yangiyol', 'Yangiyul'] }, { country: 'UZ', priority: 'P2', localCanonical: "Yangiyo'l" }),
169
+ city('Chust', { uzLatn: ['Chust'], uzCyrl: ['Чуст'], ru: ['Чуст'], en: ['Chust'] }, { country: 'UZ', priority: 'P3' }),
170
+ city('Chartak', { uzLatn: ['Chortoq', 'Chartak'], uzCyrl: ['Чортоқ'], ru: ['Чартак'], en: ['Chartak', 'Chortoq'] }, { country: 'UZ', priority: 'P3', localCanonical: 'Chortoq' }),
171
+ city('Kosonsoy', { uzLatn: ['Kosonsoy', 'Kasansay'], uzCyrl: ['Косонсой'], ru: ['Касансай', 'Косонсой'], en: ['Kosonsoy', 'Kasansay'] }, { country: 'UZ', priority: 'P3' }),
172
+ city('Shahrixon', { uzLatn: ['Shahrixon', 'Shahrikhan'], uzCyrl: ['Шаҳрихон'], ru: ['Шахрихан'], en: ['Shahrixon', 'Shahrikhan'] }, { country: 'UZ', priority: 'P3' }),
173
+ city('Xonobod', { uzLatn: ['Xonobod', 'Xonobod shahri'], uzCyrl: ['Хонобод'], ru: ['Ханабад', 'Хонобод'], en: ['Khanabad', 'Xonobod'] }, { country: 'UZ', priority: 'P3', contextRequired: true }),
174
+ city('Khojeyli', { uzLatn: ["Xo'jayli", 'Xojayli'], uzCyrl: ['Хўжайли'], kaaLat: ['Xojeli'], ru: ['Ходжейли'], en: ['Khojeyli', 'Khodzheyli'] }, { country: 'UZ', priority: 'P3', region: "Qoraqalpog'iston" }),
175
+ city('Takhiatash', { uzLatn: ['Taxiatosh'], uzCyrl: ['Тахиатош'], kaaLat: ['Taxiatas'], ru: ['Тахиаташ'], en: ['Takhiatash', 'Tahiatash'] }, { country: 'UZ', priority: 'P3', region: "Qoraqalpog'iston" }),
176
+ city('Kungrad', { uzLatn: ["Qo'ng'irot", 'Qo‘ng‘irot'], uzCyrl: ['Қўнғирот'], kaaLat: ['Qońırat'], ru: ['Кунград'], en: ['Kungrad', 'Kongirat'] }, { country: 'UZ', priority: 'P3', region: "Qoraqalpog'iston" }),
177
+ city('Beruniy', { uzLatn: ['Beruniy'], uzCyrl: ['Беруний'], ru: ['Беруни'], en: ['Beruniy', 'Biruni'] }, { country: 'UZ', priority: 'P3', region: "Qoraqalpog'iston" }),
178
+ city('Turtkul', { uzLatn: ["To'rtko'l", 'To‘rtko‘l'], uzCyrl: ['Тўрткўл'], kaaLat: ['Tórtkúl'], ru: ['Турткуль'], en: ['Turtkul', 'Tortkul'] }, { country: 'UZ', priority: 'P3', region: "Qoraqalpog'iston" }),
179
+ city('Yangiyer', { uzLatn: ['Yangiyer', 'Yangi Yer'], uzCyrl: ['Янгиер'], ru: ['Янгиер'], en: ['Yangiyer'] }, { country: 'UZ', priority: 'P3' }),
180
+ city('Shirin', { uzLatn: ['Shirin'], uzCyrl: ['Ширин'], ru: ['Ширин'], en: ['Shirin'] }, { country: 'UZ', priority: 'P3' }),
181
+ city('Gazalkent', { uzLatn: ["G'azalkent", 'Gazalkent'], uzCyrl: ['Ғазалкент'], ru: ['Газалкент'], en: ['Gazalkent'] }, { country: 'UZ', priority: 'P3', localCanonical: "G'azalkent" }),
182
+ city('Muynak', { uzLatn: ["Mo'ynoq", 'Moynaq'], uzCyrl: ['Мўйноқ'], kaaLat: ['Moynaq'], ru: ['Муйнак'], en: ['Muynak', 'Moynak'] }, { country: 'UZ', priority: 'P4', region: "Qoraqalpog'iston" }),
183
+ ]);
184
+
185
+ export const UZ_CITY_CATALOG = mergeCatalog(UZ_CITIES, UZ_CITY_ADDITIONS);
186
+
187
+ export const UZ_SEARCH_TARGETS = Object.freeze([
188
+ city('Chorvoq', { uzLatn: ['Chorvoq', 'Charvak'], ru: ['Чарвак'], en: ['Chorvoq', 'Charvak'] }, { country: 'UZ', type: 'tourism_target', priority: 'P4' }),
189
+ city('Beldersoy', { uzLatn: ['Beldersoy'], ru: ['Бельдерсай'], en: ['Beldersoy'] }, { country: 'UZ', type: 'tourism_target', priority: 'P4' }),
190
+ city('Chimgan', { uzLatn: ['Chimgan'], ru: ['Чимган'], en: ['Chimgan'] }, { country: 'UZ', type: 'tourism_target', priority: 'P4' }),
191
+ city('Zomin', { uzLatn: ['Zomin', 'Zaamin'], ru: ['Заамин', 'Зомин'], en: ['Zomin', 'Zaamin'] }, { country: 'UZ', type: 'tourism_target', priority: 'P4' }),
192
+ city('Boysun', { uzLatn: ['Boysun'], ru: ['Байсун'], en: ['Boysun'] }, { country: 'UZ', type: 'tourism_target', priority: 'P4' }),
193
+ city('Rishton', { uzLatn: ['Rishton'], ru: ['Риштан'], en: ['Rishton'] }, { country: 'UZ', type: 'tourism_target', priority: 'P4' }),
194
+ city('Gijduvon', { uzLatn: ["G'ijduvon", 'Gijduvon'], ru: ['Гиждуван'], en: ['Gijduvan'] }, { country: 'UZ', type: 'search_target', priority: 'P4' }),
195
+ city('Vobkent', { uzLatn: ['Vobkent'], ru: ['Вабкент'], en: ['Vobkent'] }, { country: 'UZ', type: 'search_target', priority: 'P4' }),
196
+ city('Hazorasp', { uzLatn: ['Hazorasp'], ru: ['Хазарасп'], en: ['Hazorasp'] }, { country: 'UZ', type: 'search_target', priority: 'P4' }),
197
+ city("Ellikqal'a", { uzLatn: ["Ellikqal'a", 'Ellikkala'], kaaLat: ['Elliqala'], ru: ['Элликкала'], en: ['Ellikkala'] }, { country: 'UZ', type: 'search_target', priority: 'P4', region: "Qoraqalpog'iston" }),
198
+ ]);
199
+
200
+ export const KZ_LOCATION_TERMS = Object.freeze({
201
+ microdistrict: Object.freeze(['микрорайон', 'микр.', 'микр', 'мкр.', 'мкр', 'м-н', 'мкр-н', 'ықшамаудан', 'ықш.ауд.', 'ықш']),
202
+ residentialArea: Object.freeze(['жилой массив', 'жилмассив', 'ж/м', 'ж.м.', 'тұрғын алабы', 'тұрғын массиві', 'массив']),
203
+ district: Object.freeze(['район', 'р-н', 'рн', 'аудан', 'ауд.', 'district']),
204
+ residentialComplex: Object.freeze(['ЖК', 'жк', 'жилой комплекс', 'тұрғын үй кешені', 'ТҮК', 'residence', 'residential complex', 'residential quarter']),
205
+ });
206
+
207
+ export const UZ_LOCATION_TERMS = Object.freeze({
208
+ city: Object.freeze(['shahar', 'shahri', 'город', 'г.']),
209
+ district: Object.freeze(['tuman', 'tumani', 'район', 'р-н']),
210
+ mahalla: Object.freeze(['MFY', 'M.F.Y.', 'mfy', 'mahalla', "mahalla fuqarolar yig'ini", "mahalla fuqarolari yig'ini", 'маҳалла', 'маҳалла фуқаролар йиғини', 'махалля', 'махалла']),
211
+ microdistrict: Object.freeze(['mikrorayon', 'микрорайон', 'мкр', 'мкр.']),
212
+ residentialComplex: Object.freeze(['ЖК', 'жк', 'turar joy majmuasi', 'residential complex', 'residence']),
213
+ });
214
+
215
+ export function canonicalKazakhstanCity(value) {
216
+ return findCanonical(value, KZ_CITY_CATALOG)?.canonical || null;
217
+ }
218
+
219
+ export function canonicalUzbekistanCity(value) {
220
+ return findCanonical(value, UZ_CITY_CATALOG)?.canonical || null;
221
+ }
222
+
223
+ export function canonicalCentralAsiaCity(value, country = null) {
224
+ if (country === 'KZ') return canonicalKazakhstanCity(value);
225
+ if (country === 'UZ') return canonicalUzbekistanCity(value);
226
+ return canonicalKazakhstanCity(value) || canonicalUzbekistanCity(value);
227
+ }
228
+
229
+ export function centralAsiaCityAliases(canonical, country) {
230
+ const catalog = country === 'KZ' ? KZ_CITY_CATALOG : country === 'UZ' ? UZ_CITY_CATALOG : [...KZ_CITY_CATALOG, ...UZ_CITY_CATALOG];
231
+ const item = catalog.find((entry) => entry.canonical === canonical);
232
+ return item ? Object.freeze([...new Set([item.canonical, ...aliasesOf(item)])]) : Object.freeze([]);
233
+ }
@@ -0,0 +1,44 @@
1
+ export type PhoneLikeSpan = Readonly<{
2
+ start: number;
3
+ end: number;
4
+ raw: string;
5
+ digits: string;
6
+ }>;
7
+
8
+ export type ParsedPhoneNumber = Readonly<{
9
+ start: number;
10
+ end: number;
11
+ raw: string;
12
+ digits: string;
13
+ number: string;
14
+ nationalNumber: string;
15
+ national: string;
16
+ international: string;
17
+ country: string | null;
18
+ countryCallingCode: string;
19
+ extension: string | null;
20
+ valid: boolean;
21
+ possible: boolean;
22
+ }>;
23
+
24
+ export type ParsePhoneOptions = Readonly<{
25
+ countryHint?: string | null;
26
+ includePossible?: boolean;
27
+ }>;
28
+
29
+ export type TelegramContact = Readonly<{
30
+ start: number;
31
+ end: number;
32
+ raw: string;
33
+ username: string;
34
+ handle: string;
35
+ url: string;
36
+ source: 'mention' | 'url' | 'tg';
37
+ }>;
38
+
39
+ export function findPhoneLikeSpans(value: unknown): readonly PhoneLikeSpan[];
40
+ export function maskPhoneLikeSpans(value: unknown, replacement?: string): string;
41
+ export function parsePhoneNumbers(value: unknown, options?: ParsePhoneOptions): readonly ParsedPhoneNumber[];
42
+ export function normalizePhone(value: unknown, options?: ParsePhoneOptions): ParsedPhoneNumber | null;
43
+ export function findTelegramContacts(value: unknown): readonly TelegramContact[];
44
+ export function normalizeTelegramContact(value: unknown): TelegramContact | null;