From 2991bc5df946b97256de9a61dc2357983c31ade1 Mon Sep 17 00:00:00 2001 From: yuryleb Date: Thu, 6 Apr 2017 19:01:09 +0300 Subject: [PATCH 1/2] Add grammar support for Russian way names --- CHANGELOG.md | 6 +- Grammar.md | 53 ++ Readme.md | 4 + index.js | 37 +- languages.js | 12 +- languages/grammar/ru.json | 960 +++++++++++++++++++++++++++++++++ languages/overrides/ru.js | 35 ++ languages/translations/ru.json | 150 +++--- test/grammar_test.js | 117 ++++ 9 files changed, 1291 insertions(+), 83 deletions(-) create mode 100644 Grammar.md create mode 100644 languages/grammar/ru.json create mode 100644 languages/overrides/ru.js create mode 100644 test/grammar_test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ae2a223c..e5df975d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. For change log formatting, see http://keepachangelog.com/ +## master + +- Added grammatical cases support for Russian way names [#102](https://github.com/Project-OSRM/osrm-text-instructions/pull/102) + ## 0.7.1 2017-09-26 - Added Castilian Spanish localization. [#163](https://github.com/Project-OSRM/osrm-text-instructions/pull/163) @@ -73,7 +77,7 @@ All notable changes to this project will be documented in this file. For change ## 0.1.0 2016-11-17 -- Improve chinese translation +- Improve Chinese translation - Standardize capitalizeFirstLetter meta key - Change instructions object customization to options.hooks.tokenizedInstruction diff --git a/Grammar.md b/Grammar.md new file mode 100644 index 000000000..8a6d8874d --- /dev/null +++ b/Grammar.md @@ -0,0 +1,53 @@ +## Grammar support + +Many languages - all Slavic (Russian, Ukrainian, Polish, Bulgarian, etc), Finnic (Finnish, Estonian) and others - have [grammatical case feature](https://en.wikipedia.org/wiki/Grammatical_case) that could be supported in OSRM Text Instructions too. +Originally street names are being inserted into instructions as they're in OSM map - in [nominative case](https://en.wikipedia.org/wiki/Nominative_case). +To be grammatically correct, street names should be changed according to target language rules and instruction context before insertion. + +Actually grammatical case applying is not the simple and obvious task due to real-life languages complexity. +It even looks so hard so, for example, all known native Russian navigation systems don't speak street names in their pronounceable route instructions at all. + +But fortunately street names have restricted lexicon and naming rules and so this task could be relatively easily solved for this particular case. + +### Implementation details + +The quite universal and simplier solution is the changing street names with the prepared set of regular expressions grouped by required grammatical case. +The required grammatical case should be specified right in instruction's substitution variables: + +- `{way_name}` and `{rotary_name}` variables in translated instructions should be appended with required grammar case name after colon: `{way_name:accusative}` for example +- [languages/grammar](languages/grammar/) folder should contain language-specific JSON file with regular expressions for specified grammar case: +```json +{ + "v5": { + "accusative": [ + ["^ (\\S+)ая-(\\S+)ая [Уу]лица ", " $1ую-$2ую улицу "], + ["^ (\\S+)ая [Уу]лица ", " $1ую улицу "], + ... +``` +- All such JSON files should be registered in common [languages.js](languages.js) +- Instruction text formatter ([index.js](index.js) in this module) should: + - check `{way_name}` and `{rotary_name}` variables for optional grammar case after colon: `{way_name:accusative}` + - find appropriate regular expressions block for target language and specified grammar case + - call standard [string replace with regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace) for each expression in block passing result from previous call to the next; the first call should enclose original street name with whitespaces to make parsing words in names a bit simplier. +- Strings replacement with regular expression is available in almost all other programming language and so this should not be the problem for other code used OSRM Text Instructions' data only. +- If there is no regular expression matched source name (that's for names from foreign country for example), original name is returned without changes. This is also expected behavior of standard [string replace with regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace). And the same behavior is expected in case of missing grammar JSON file or grammar case inside it. + +### Example + +Russian _"Большая Монетная улица"_ street from St Petersburg (_Big Monetary Street_ in rough translation) after processing with [Russian grammar rules](languages/grammar/ru.json) will look in following instructions as: +- _"Turn left onto `{way_name}`"_ => `ru`:_"Поверните налево на `{way_name:accusative}`"_ => _"Поверните налево на Большую Монетную улицу"_ +- _"Continue onto `{way_name}`"_ => `ru`:_"Продолжите движение по `{way_name:dative}`"_ => _"Продолжите движение по Большой Монетной улице"_ +- _"Make a U-turn onto `{way_name}` at the end of the road"_ => `ru`:_"Развернитесь в конце `{way_name:genitive}`"_ => _"Развернитесь в конце Большой Монетной улицы"_ +- _"Make a U-turn onto `{way_name}`"_ => `ru`:_"Развернитесь на `{way_name:prepositional}`"_ => _"Развернитесь на Большой Монетной улице"_ + +### Design goals + +- __Cross platform__ - uses the same data-driven approach as OSRM Text Instructions +- __Test suite__ - has [prepared test](test/grammar_tests.js) to check available expressions automatically and has easily extendable language-specific names testing pattern +- __Customization__ - could be easily extended for other languages with adding new regular expressions blocks into [grammar support](languages/grammar/) folder and modifying `{way_name}` and other variables in translated instructions only with necessary grammatical case labels + +### Notes + +- Russian regular expressions are based on [Garmin Russian TTS voices update](https://github.com/yuryleb/garmin-russian-tts-voices) project; see [file with regular expressions to apply to source text before pronouncing by TTS](https://github.com/yuryleb/garmin-russian-tts-voices/blob/master/src/Pycckuu__Milena%202.10/RULESET.TXT). +- There is another grammar-supporting module - [jquery.i18n](https://github.com/wikimedia/jquery.i18n) - but unfortunately it has very poor implementation in part of grammatical case applying and is supposed to work with single words only. +- Actually it would be great to get street names also in target language not from default OSM `name` only - there are several multi-lingual countries supporting several `name:` names for streets. But this the subject to address to [OSRM engine](https://github.com/Project-OSRM/osrm-backend) first. diff --git a/Readme.md b/Readme.md index 43a897be3..3a29d3eb3 100644 --- a/Readme.md +++ b/Readme.md @@ -8,6 +8,10 @@ OSRM Text Instructions transforms [OSRM](http://www.project-osrm.org/) route res OSRM Text Instructions has been translated into [several languages](https://github.com/Project-OSRM/osrm-text-instructions/tree/master/languages/translations/). Please help us add support for the languages you speak [using Transifex](https://www.transifex.com/project-osrm/osrm-text-instructions/). +OSRM Text Instructions could support [grammatical cases](https://github.com/Project-OSRM/osrm-text-instructions/tree/master/Grammar.md) for street names for [some languages](https://github.com/Project-OSRM/osrm-text-instructions/tree/languages/grammar/). + +Grammatical cases and other translated strings customization after [Transifex](https://www.transifex.com/project-osrm/osrm-text-instructions/) is handled by [override scripts](https://github.com/Project-OSRM/osrm-text-instructions/tree/master/languages/overrides/). + [![NPM](https://nodei.co/npm/osrm-text-instructions.png)](https://npmjs.org/package/osrm-text-instructions/) ### Design goals diff --git a/index.js b/index.js index db49110e5..e886eb22b 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,6 @@ var languages = require('./languages'); var instructions = languages.instructions; +var grammars = languages.grammars; module.exports = function(version, _options) { var opts = {}; @@ -104,7 +105,6 @@ module.exports = function(version, _options) { switch (type) { case 'use lane': laneInstruction = instructions[language][version].constants.lanes[this.laneConfig(step)]; - if (!laneInstruction) { // If the lane combination is not found, default to continue straight instructionObject = instructions[language][version]['use lane'].no_lanes; @@ -136,8 +136,9 @@ module.exports = function(version, _options) { // if both are the same we assume that there used to be an empty name, with the ref being filled in for it // we only need to retain the ref then name = ''; + } else { + name = name.replace(' (' + step.ref + ')', ''); } - name = name.replace(' (' + step.ref + ')', ''); // In attempt to avoid using the highway name of a way, // check and see if the step has a class which should signal @@ -199,10 +200,36 @@ module.exports = function(version, _options) { return this.tokenize(language, instruction, replaceTokens); }, + grammarize: function(language, name, grammar) { + // Process way/rotary name with applying grammar rules if any + if (name && grammar && grammars && grammars[language] && grammars[language][version]) { + var rules = grammars[language][version][grammar]; + if (rules) { + // Pass original name to rules' regular expressions enclosed with spaces for simplier parsing + var n = ' ' + name + ' '; + rules.forEach(function(rule) { + var re = new RegExp(rule[0]); + n = n.replace(re, rule[1]); + }); + + return n.trim(); + } + } + + return name; + }, tokenize: function(language, instruction, tokens) { - var output = Object.keys(tokens).reduce(function(memo, token) { - return memo.replace('{' + token + '}', tokens[token]); - }, instruction) + // Keep this function context to use in inline function below (no arrow functions in ES4) + var that = this; + var output = instruction.replace(/\{(\w+):?(\w+)?\}/g, function(token, tag, grammar) { + var name = tokens[tag]; + if (typeof name !== 'undefined') { + return that.grammarize(language, name, grammar); + } + + // Return unknown token unchanged + return token; + }) .replace(/ {2}/g, ' '); // remove excess spaces if (instructions[language].meta.capitalizeFirstLetter) { diff --git a/languages.js b/languages.js index d11741fc3..d5d0f59b6 100755 --- a/languages.js +++ b/languages.js @@ -1,4 +1,4 @@ -// Load all language files excplicitely to allow integration +// Load all language files explicitly to allow integration // with bundling tools like webpack and browserify var instructionsDe = require('./languages/translations/de.json'); var instructionsEn = require('./languages/translations/en.json'); @@ -19,6 +19,8 @@ var instructionsUk = require('./languages/translations/uk.json'); var instructionsVi = require('./languages/translations/vi.json'); var instructionsZhHans = require('./languages/translations/zh-Hans.json'); +// Load all grammar files +var grammarRu = require('./languages/grammar/ru.json'); // Create a list of supported codes var instructions = { @@ -42,7 +44,13 @@ var instructions = { 'zh-Hans': instructionsZhHans }; +// Create list of supported grammar +var grammars = { + 'ru': grammarRu +}; + module.exports = { supportedCodes: Object.keys(instructions), - instructions: instructions + instructions: instructions, + grammars: grammars }; diff --git a/languages/grammar/ru.json b/languages/grammar/ru.json new file mode 100644 index 000000000..354727404 --- /dev/null +++ b/languages/grammar/ru.json @@ -0,0 +1,960 @@ +{ + "v5": { + "accusative": [ + ["^ (\\S+)ая [Аа]ллея ", " $1ую аллею "], + ["^ (\\S+)ья [Аа]ллея ", " $1ью аллею "], + ["^ (\\S+)яя [Аа]ллея ", " $1юю аллею "], + ["^ (\\d+)-я (\\S+)ая [Аа]ллея ", " $1-ю $2ую аллею "], + ["^ [Аа]ллея ", " аллею "], + + ["^ (\\S+)ая-(\\S+)ая [Уу]лица ", " $1ую-$2ую улицу "], + ["^ (\\S+)ая [Уу]лица ", " $1ую улицу "], + ["^ (\\S+)ья [Уу]лица ", " $1ью улицу "], + ["^ (\\S+)яя [Уу]лица ", " $1юю улицу "], + ["^ (\\d+)-я (\\S+)ая [Уу]лица ", " $1-ю $2ую улицу "], + ["^ (\\S+)ая (\\S+)ая [Уу]лица ", " $1ую $2ую улицу "], + ["^ (\\S+[вн])а [Уу]лица ", " $1у улицу "], + ["^ (\\S+)ая (\\S+[вн])а [Уу]лица ", " $1ую $2у улицу "], + ["^ Даньславля [Уу]лица ", " Даньславлю улицу "], + ["^ Добрыня [Уу]лица ", " Добрыню улицу "], + ["^ Людогоща [Уу]лица ", " Людогощу улицу "], + ["^ [Уу]лица ", " улицу "], + + ["^ (\\d+)-я [Лл]иния ", " $1-ю линию "], + ["^ (\\d+)-(\\d+)-я [Лл]иния ", " $1-$2-ю линию "], + ["^ (\\S+)ая [Лл]иния ", " $1ую линию "], + ["^ (\\S+)ья [Лл]иния ", " $1ью линию "], + ["^ (\\S+)яя [Лл]иния ", " $1юю линию "], + ["^ (\\d+)-я (\\S+)ая [Лл]иния ", " $1-ю $2ую линию "], + ["^ [Лл]иния ", " линию "], + + ["^ (\\d+)-(\\d+)-я [Лл]инии ", " $1-$2-ю линии "], + + ["^ (\\S+)ая [Нн]абережная ", " $1ую набережную "], + ["^ (\\S+)ья [Нн]абережная ", " $1ью набережную "], + ["^ (\\S+)яя [Нн]абережная ", " $1юю набережную "], + ["^ (\\d+)-я (\\S+)ая [Нн]абережная ", " $1-ю $2ую набережную "], + ["^ [Нн]абережная ", " набережную "], + + ["^ (\\S+)ая [Пп]лощадь ", " $1ую площадь "], + ["^ (\\S+)ья [Пп]лощадь ", " $1ью площадь "], + ["^ (\\S+)яя [Пп]лощадь ", " $1юю площадь "], + ["^ (\\S+[вн])а [Пп]лощадь ", " $1у площадь "], + ["^ (\\d+)-я (\\S+)ая [Пп]лощадь ", " $1-ю $2ую площадь "], + ["^ [Пп]лощадь ", " площадь "], + + ["^ (\\S+)ая [Ээ]стакада ", " $1ую эстакаду "], + ["^ (\\S+)ья [Ээ]стакада ", " $1ью эстакаду "], + ["^ (\\S+)яя [Ээ]стакада ", " $1юю эстакаду "], + ["^ (\\d+)-я (\\S+)ая [Ээ]стакада ", " $1-ю $2ую эстакаду "], + ["^ [Ээ]стакада ", " эстакаду "], + + ["^ (\\S+)ая [Мм]агистраль ", " $1ую магистраль "], + ["^ (\\S+)ья [Мм]агистраль ", " $1ью магистраль "], + ["^ (\\S+)яя [Мм]агистраль ", " $1юю магистраль "], + ["^ (\\d+)-я (\\S+)ая [Мм]агистраль ", " $1-ю $2ую магистраль "], + ["^ [Мм]агистраль ", " магистраль "], + + ["^ (\\S+)ая [Рр]азвязка ", " $1ую развязку "], + ["^ (\\S+)ья [Рр]азвязка ", " $1ью развязку "], + ["^ (\\S+)яя [Рр]азвязка ", " $1юю развязку "], + ["^ (\\d+)-я (\\S+)ая [Рр]азвязка ", " $1-ю $2ую развязку "], + ["^ [Рр]азвязка ", " развязку "], + + ["^ (\\S+)ая [Тт]расса ", " $1ую трассу "], + ["^ (\\S+)ья [Тт]расса ", " $1ью трассу "], + ["^ (\\S+)яя [Тт]расса ", " $1юю трассу "], + ["^ (\\d+)-я (\\S+)ая [Тт]расса ", " $1-ю $2ую трассу "], + ["^ [Тт]расса ", " трассу "], + + ["^ (\\S+)ая ([Аа]вто)?[Дд]орога ", " $1ую $2дорогу "], + ["^ (\\S+)ья ([Аа]вто)?[Дд]орога ", " $1ью $2дорогу "], + ["^ (\\S+)яя ([Аа]вто)?[Дд]орога ", " $1юю $2дорогу "], + ["^ (\\d+)-я (\\S+)ая ([Аа]вто)?[Дд]орога ", " $1-ю $2ую $3дорогу "], + ["^ ([Аа]вто)?[Дд]орога ", " $1дорогу "], + + ["^ (\\S+)ая [Дд]орожка ", " $1ую дорожку "], + ["^ (\\S+)ья [Дд]орожка ", " $1ью дорожку "], + ["^ (\\S+)яя [Дд]орожка ", " $1юю дорожку "], + ["^ (\\d+)-я (\\S+)ая [Дд]орожка ", " $1-ю $2ую дорожку "], + ["^ [Дд]орожка ", " дорожку "], + + ["^ (\\S+)ая [Кк]оса ", " $1ую косу "] + ], + "dative": [ + ["^ (\\S+)ая [Аа]ллея ", " $1ой аллее "], + ["^ (\\S+)ья [Аа]ллея ", " $1ьей аллее "], + ["^ (\\S+)яя [Аа]ллея ", " $1ей аллее "], + ["^ (\\d+)-я (\\S+)ая [Аа]ллея ", " $1-й $2ой аллее "], + ["^ [Аа]ллея ", " аллее "], + + ["^ (\\S+)ая-(\\S+)ая [Уу]лица ", " $1ой-$2ой улице "], + ["^ (\\S+)ая [Уу]лица ", " $1ой улице "], + ["^ (\\S+)ья [Уу]лица ", " $1ьей улице "], + ["^ (\\S+)яя [Уу]лица ", " $1ей улице "], + ["^ (\\d+)-я (\\S+)ая [Уу]лица ", " $1-й $2ой улице "], + ["^ (\\S+)ая (\\S+)ая [Уу]лица ", " $1ой $2ой улице "], + ["^ (\\S+[вн])а [Уу]лица ", " $1ой улице "], + ["^ (\\S+)ая (\\S+[вн])а [Уу]лица ", " $1ой $2ой улице "], + ["^ Даньславля [Уу]лица ", " Даньславлей улице "], + ["^ Добрыня [Уу]лица ", " Добрыней улице "], + ["^ Людогоща [Уу]лица ", " Людогощей улице "], + ["^ [Уу]лица ", " улице "], + + ["^ (\\d+)-я [Лл]иния ", " $1-й линии "], + ["^ (\\d+)-(\\d+)-я [Лл]иния ", " $1-$2-й линии "], + ["^ (\\S+)ая [Лл]иния ", " $1ой линии "], + ["^ (\\S+)ья [Лл]иния ", " $1ьей линии "], + ["^ (\\S+)яя [Лл]иния ", " $1ей линии "], + ["^ (\\d+)-я (\\S+)ая [Лл]иния ", " $1-й $2ой линии "], + ["^ [Лл]иния ", " линии "], + + ["^ (\\d+)-(\\d+)-я [Лл]инии ", " $1-$2-й линиям "], + + ["^ (\\S+)ая [Нн]абережная ", " $1ой набережной "], + ["^ (\\S+)ья [Нн]абережная ", " $1ьей набережной "], + ["^ (\\S+)яя [Нн]абережная ", " $1ей набережной "], + ["^ (\\d+)-я (\\S+)ая [Нн]абережная ", " $1-й $2ой набережной "], + ["^ [Нн]абережная ", " набережной "], + + ["^ (\\S+)ая [Пп]лощадь ", " $1ой площади "], + ["^ (\\S+)ья [Пп]лощадь ", " $1ьей площади "], + ["^ (\\S+)яя [Пп]лощадь ", " $1ей площади "], + ["^ (\\S+[вн])а [Пп]лощадь ", " $1ой площади "], + ["^ (\\d+)-я (\\S+)ая [Пп]лощадь ", " $1-й $2ой площади "], + ["^ [Пп]лощадь ", " площади "], + + ["^ (\\S+)ая [Ээ]стакада ", " $1ой эстакаде "], + ["^ (\\S+)ья [Ээ]стакада ", " $1ьей эстакаде "], + ["^ (\\S+)яя [Ээ]стакада ", " $1ей эстакаде "], + ["^ (\\d+)-я (\\S+)ая [Ээ]стакада ", " $1-й $2ой эстакаде "], + ["^ [Ээ]стакада ", " эстакаде "], + + ["^ (\\S+)ая [Мм]агистраль ", " $1ой магистрали "], + ["^ (\\S+)ья [Мм]агистраль ", " $1ьей магистрали "], + ["^ (\\S+)яя [Мм]агистраль ", " $1ей магистрали "], + ["^ (\\d+)-я (\\S+)ая [Мм]агистраль ", " $1-й $2ой магистрали "], + ["^ [Мм]агистраль ", " магистрали "], + + ["^ (\\S+)ая [Рр]азвязка ", " $1ой развязке "], + ["^ (\\S+)ья [Рр]азвязка ", " $1ьей развязке "], + ["^ (\\S+)яя [Рр]азвязка ", " $1ей развязке "], + ["^ (\\d+)-я (\\S+)ая [Рр]азвязка ", " $1-й $2ой развязке "], + ["^ [Рр]азвязка ", " развязке "], + + ["^ (\\S+)ая [Тт]расса ", " $1ой трассе "], + ["^ (\\S+)ья [Тт]расса ", " $1ьей трассе "], + ["^ (\\S+)яя [Тт]расса ", " $1ей трассе "], + ["^ (\\d+)-я (\\S+)ая [Тт]расса ", " $1-й $2ой трассе "], + ["^ [Тт]расса ", " трассе "], + + ["^ (\\S+)ая ([Аа]вто)?[Дд]орога ", " $1ой $2дороге "], + ["^ (\\S+)ья ([Аа]вто)?[Дд]орога ", " $1ьей $2дороге "], + ["^ (\\S+)яя ([Аа]вто)?[Дд]орога ", " $1ей $2дороге "], + ["^ (\\d+)-я (\\S+)ая ([Аа]вто)?[Дд]орога ", " $1-й $2ой $3дороге "], + ["^ ([Аа]вто)?[Дд]орога ", " $1дороге "], + + ["^ (\\S+)ая [Дд]орожка ", " $1ой дорожке "], + ["^ (\\S+)ья [Дд]орожка ", " $1ьей дорожке "], + ["^ (\\S+)яя [Дд]орожка ", " $1ей дорожке "], + ["^ (\\d+)-я (\\S+)ая [Дд]орожка ", " $1-й $2ой дорожке "], + ["^ [Дд]орожка ", " дорожке "], + + ["^ (\\S+)во [Пп]оле ", " $1ву полю "], + ["^ (\\S+)ая [Кк]оса ", " $1ой косе "], + ["^ (\\S+)[иоы]й [Пп]роток ", " $1ому протоку "], + + ["^ (\\S+н)ий [Бб]ульвар ", " $1ему бульвару "], + ["^ (\\S+)[иоы]й [Бб]ульвар ", " $1ому бульвару "], + ["^ (\\S+[иы]н) [Бб]ульвар ", " $1у бульвару "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Бб]ульвар ", " $1ому $2ему бульвару "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Бб]ульвар ", " $1ему $2ому бульвару "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Бб]ульвар ", " $1ому $2ому бульвару "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Бб]ульвар ", " $1ому $2у бульвару "], + ["^ (\\d+)-й (\\S+н)ий [Бб]ульвар ", " $1-му $2ему бульвару "], + ["^ (\\d+)-й (\\S+)[иоы]й [Бб]ульвар ", " $1-му $2ому бульвару "], + ["^ (\\d+)-й (\\S+[иы]н) [Бб]ульвар ", " $1-му $2у бульвару "], + ["^ [Бб]ульвар ", " бульвару "], + + ["^ [Дд]убл[её]р ", " дублёру "], + + ["^ (\\S+н)ий [Зз]аезд ", " $1ему заезду "], + ["^ (\\S+)[иоы]й [Зз]аезд ", " $1ому заезду "], + ["^ (\\S+[еёо]в) [Зз]аезд ", " $1у заезду "], + ["^ (\\S+[иы]н) [Зз]аезд ", " $1у заезду "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Зз]аезд ", " $1ому $2ему заезду "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Зз]аезд ", " $1ему $2ому заезду "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Зз]аезд ", " $1ому $2ому заезду "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Зз]аезд ", " $1ому $2у заезду "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Зз]аезд ", " $1ому $2у заезду "], + ["^ (\\d+)-й (\\S+н)ий [Зз]аезд ", " $1-му $2ему заезду "], + ["^ (\\d+)-й (\\S+)[иоы]й [Зз]аезд ", " $1-му $2ому заезду "], + ["^ (\\d+)-й (\\S+[еёо]в) [Зз]аезд ", " $1-му $2у заезду "], + ["^ (\\d+)-й (\\S+[иы]н) [Зз]аезд ", " $1-му $2у заезду "], + ["^ [Зз]аезд ", " заезду "], + + ["^ (\\S+н)ий [Мм]ост ", " $1ему мосту "], + ["^ (\\S+)[иоы]й [Мм]ост ", " $1ому мосту "], + ["^ (\\S+[еёо]в) [Мм]ост ", " $1у мосту "], + ["^ (\\S+[иы]н) [Мм]ост ", " $1у мосту "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Мм]ост ", " $1ому $2ему мосту "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Мм]ост ", " $1ему $2ому мосту "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Мм]ост ", " $1ому $2ому мосту "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Мм]ост ", " $1ому $2у мосту "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Мм]ост ", " $1ому $2у мосту "], + ["^ (\\d+)-й (\\S+н)ий [Мм]ост ", " $1-му $2ему мосту "], + ["^ (\\d+)-й (\\S+)[иоы]й [Мм]ост ", " $1-му $2ому мосту "], + ["^ (\\d+)-й (\\S+[еёо]в) [Мм]ост ", " $1-му $2у мосту "], + ["^ (\\d+)-й (\\S+[иы]н) [Мм]ост ", " $1-му $2у мосту "], + ["^ [Мм]ост ", " мосту "], + + ["^ (\\S+н)ий [Оо]бход ", " $1ему обходу "], + ["^ (\\S+)[иоы]й [Оо]бход ", " $1ому обходу "], + ["^ [Оо]бход ", " обходу "], + + ["^ (\\S+н)ий [Пп]арк ", " $1ему парку "], + ["^ (\\S+)[иоы]й [Пп]арк ", " $1ому парку "], + ["^ (\\S+[иы]н) [Пп]арк ", " $1у парку "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]арк ", " $1ому $2ему парку "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]арк ", " $1ему $2ому парку "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]арк ", " $1ому $2ому парку "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]арк ", " $1ому $2у парку "], + ["^ (\\d+)-й (\\S+н)ий [Пп]арк ", " $1-му $2ему парку "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]арк ", " $1-му $2ому парку "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]арк ", " $1-му $2у парку "], + ["^ [Пп]арк ", " парку "], + + ["^ (\\S+)[иоы]й-(\\S+)[иоы]й [Пп]ереулок ", " $1ому-$2ому переулку "], + ["^ (\\d+)-й (\\S+)[иоы]й-(\\S+)[иоы]й [Пп]ереулок ", " $1-му $2ому-$3ому переулку "], + ["^ (\\S+н)ий [Пп]ереулок ", " $1ему переулку "], + ["^ (\\S+)[иоы]й [Пп]ереулок ", " $1ому переулку "], + ["^ (\\S+[еёо]в) [Пп]ереулок ", " $1у переулку "], + ["^ (\\S+[иы]н) [Пп]ереулок ", " $1у переулку "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]ереулок ", " $1ому $2ему переулку "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]ереулок ", " $1ему $2ому переулку "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]ереулок ", " $1ому $2ому переулку "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Пп]ереулок ", " $1ому $2у переулку "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]ереулок ", " $1ому $2у переулку "], + ["^ (\\d+)-й (\\S+н)ий [Пп]ереулок ", " $1-му $2ему переулку "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]ереулок ", " $1-му $2ому переулку "], + ["^ (\\d+)-й (\\S+[еёо]в) [Пп]ереулок ", " $1-му $2у переулку "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]ереулок ", " $1-му $2у переулку "], + ["^ [Пп]ереулок ", " переулку "], + + ["^ [Пп]одъезд ", " подъезду "], + + ["^ (\\S+[еёо]в)-(\\S+)[иоы]й [Пп]роезд ", " $1у-$2ому проезду "], + ["^ (\\S+н)ий [Пп]роезд ", " $1ему проезду "], + ["^ (\\S+)[иоы]й [Пп]роезд ", " $1ому проезду "], + ["^ (\\S+[еёо]в) [Пп]роезд ", " $1у проезду "], + ["^ (\\S+[иы]н) [Пп]роезд ", " $1у проезду "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]роезд ", " $1ому $2ему проезду "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]роезд ", " $1ему $2ому проезду "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]роезд ", " $1ому $2ому проезду "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Пп]роезд ", " $1ому $2у проезду "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]роезд ", " $1ому $2у проезду "], + ["^ (\\d+)-й (\\S+н)ий [Пп]роезд ", " $1-му $2ему проезду "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]роезд ", " $1-му $2ому проезду "], + ["^ (\\d+)-й (\\S+[еёо]в) [Пп]роезд ", " $1-му $2у проезду "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]роезд ", " $1-му $2у проезду "], + ["^ [Пп]роезд ", " проезду "], + + ["^ (\\S+н)ий [Пп]роспект ", " $1ему проспекту "], + ["^ (\\S+)[иоы]й [Пп]роспект ", " $1ому проспекту "], + ["^ (\\S+[иы]н) [Пп]роспект ", " $1у проспекту "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]роспект ", " $1ому $2ему проспекту "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]роспект ", " $1ему $2ому проспекту "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]роспект ", " $1ому $2ому проспекту "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]роспект ", " $1ому $2у проспекту "], + ["^ (\\d+)-й (\\S+н)ий [Пп]роспект ", " $1-му $2ему проспекту "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]роспект ", " $1-му $2ому проспекту "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]роспект ", " $1-му $2у проспекту "], + ["^ [Пп]роспект ", " проспекту "], + + ["^ (\\S+н)ий [Пп]утепровод ", " $1ему путепроводу "], + ["^ (\\S+)[иоы]й [Пп]утепровод ", " $1ому путепроводу "], + ["^ (\\S+[иы]н) [Пп]утепровод ", " $1у путепроводу "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]утепровод ", " $1ому $2ему путепроводу "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]утепровод ", " $1ему $2ому путепроводу "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]утепровод ", " $1ому $2ому путепроводу "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]утепровод ", " $1ому $2у путепроводу "], + ["^ (\\d+)-й (\\S+н)ий [Пп]утепровод ", " $1-му $2ему путепроводу "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]утепровод ", " $1-му $2ому путепроводу "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]утепровод ", " $1-му $2у путепроводу "], + ["^ [Пп]утепровод ", " путепроводу "], + + ["^ (\\S+н)ий [Сс]пуск ", " $1ему спуску "], + ["^ (\\S+)[иоы]й [Сс]пуск ", " $1ому спуску "], + ["^ (\\S+[еёо]в) [Сс]пуск ", " $1у спуску "], + ["^ (\\S+[иы]н) [Сс]пуск ", " $1у спуску "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Сс]пуск ", " $1ому $2ему спуску "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Сс]пуск ", " $1ему $2ому спуску "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Сс]пуск ", " $1ому $2ому спуску "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Сс]пуск ", " $1ому $2у спуску "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Сс]пуск ", " $1ому $2у спуску "], + ["^ (\\d+)-й (\\S+н)ий [Сс]пуск ", " $1-му $2ему спуску "], + ["^ (\\d+)-й (\\S+)[иоы]й [Сс]пуск ", " $1-му $2ому спуску "], + ["^ (\\d+)-й (\\S+[еёо]в) [Сс]пуск ", " $1-му $2у спуску "], + ["^ (\\d+)-й (\\S+[иы]н) [Сс]пуск ", " $1-му $2у спуску "], + ["^ [Сс]пуск ", " спуску "], + + ["^ (\\S+н)ий [Сс]ъезд ", " $1ему съезду "], + ["^ (\\S+)[иоы]й [Сс]ъезд ", " $1ому съезду "], + ["^ (\\S+[иы]н) [Сс]ъезд ", " $1у съезду "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Сс]ъезд ", " $1ому $2ему съезду "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Сс]ъезд ", " $1ему $2ому съезду "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Сс]ъезд ", " $1ому $2ому съезду "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Сс]ъезд ", " $1ому $2у съезду "], + ["^ (\\d+)-й (\\S+н)ий [Сс]ъезд ", " $1-му $2ему съезду "], + ["^ (\\d+)-й (\\S+)[иоы]й [Сс]ъезд ", " $1-му $2ому съезду "], + ["^ (\\d+)-й (\\S+[иы]н) [Сс]ъезд ", " $1-му $2у съезду "], + ["^ [Сс]ъезд ", " съезду "], + + ["^ (\\S+н)ий [Тт][уо]ннель ", " $1ему тоннелю "], + ["^ (\\S+)[иоы]й [Тт][уо]ннель ", " $1ому тоннелю "], + ["^ (\\S+[иы]н) [Тт][уо]ннель ", " $1у тоннелю "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Тт][уо]ннель ", " $1ому $2ему тоннелю "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Тт][уо]ннель ", " $1ему $2ому тоннелю "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Тт][уо]ннель ", " $1ому $2ому тоннелю "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Тт][уо]ннель ", " $1ому $2у тоннелю "], + ["^ (\\d+)-й (\\S+н)ий [Тт][уо]ннель ", " $1-му $2ему тоннелю "], + ["^ (\\d+)-й (\\S+)[иоы]й [Тт][уо]ннель ", " $1-му $2ому тоннелю "], + ["^ (\\d+)-й (\\S+[иы]н) [Тт][уо]ннель ", " $1-му $2у тоннелю "], + ["^ [Тт][уо]ннель ", " тоннелю "], + + ["^ (\\S+н)ий [Тт]ракт ", " $1ему тракту "], + ["^ (\\S+)[иоы]й [Тт]ракт ", " $1ому тракту "], + ["^ (\\S+[еёо]в) [Тт]ракт ", " $1у тракту "], + ["^ (\\S+[иы]н) [Тт]ракт ", " $1у тракту "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Тт]ракт ", " $1ому $2ему тракту "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Тт]ракт ", " $1ему $2ому тракту "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Тт]ракт ", " $1ому $2ому тракту "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Тт]ракт ", " $1ому $2у тракту "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Тт]ракт ", " $1ому $2у тракту "], + ["^ (\\d+)-й (\\S+н)ий [Тт]ракт ", " $1-му $2ему тракту "], + ["^ (\\d+)-й (\\S+)[иоы]й [Тт]ракт ", " $1-му $2ому тракту "], + ["^ (\\d+)-й (\\S+[еёо]в) [Тт]ракт ", " $1-му $2у тракту "], + ["^ (\\d+)-й (\\S+[иы]н) [Тт]ракт ", " $1-му $2у тракту "], + ["^ [Тт]ракт ", " тракту "], + + ["^ (\\S+н)ий [Тт]упик ", " $1ему тупику "], + ["^ (\\S+)[иоы]й [Тт]упик ", " $1ому тупику "], + ["^ (\\S+[еёо]в) [Тт]упик ", " $1у тупику "], + ["^ (\\S+[иы]н) [Тт]упик ", " $1у тупику "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Тт]упик ", " $1ому $2ему тупику "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Тт]упик ", " $1ему $2ому тупику "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Тт]упик ", " $1ому $2ому тупику "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Тт]упик ", " $1ому $2у тупику "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Тт]упик ", " $1ому $2у тупику "], + ["^ (\\d+)-й (\\S+н)ий [Тт]упик ", " $1-му $2ему тупику "], + ["^ (\\d+)-й (\\S+)[иоы]й [Тт]упик ", " $1-му $2ому тупику "], + ["^ (\\d+)-й (\\S+[еёо]в) [Тт]упик ", " $1-му $2у тупику "], + ["^ (\\d+)-й (\\S+[иы]н) [Тт]упик ", " $1-му $2у тупику "], + ["^ [Тт]упик ", " тупику "], + + ["^ (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1му $2кольцу "], + ["^ (\\S+ье) ([Пп]олу)?[Кк]ольцо ", " $1му $2кольцу "], + ["^ (\\S+[ео])е (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1му $2му $3кольцу "], + ["^ (\\S+ье) (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1му $2му $3кольцу "], + ["^ (\\d+)-е (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1му $2му $3кольцу "], + ["^ (\\d+)-е (\\S+ье) ([Пп]олу)?[Кк]ольцо ", " $1му $2му $3кольцу "], + ["^ ([Пп]олу)?[Кк]ольцо ", " $1кольцу "], + + ["^ (\\S+[ео])е [Шш]оссе ", " $1му шоссе "], + ["^ (\\S+ье) [Шш]оссе ", " $1му шоссе "], + ["^ (\\S+[ео])е (\\S+[ео])е [Шш]оссе ", " $1му $2му шоссе "], + ["^ (\\S+ье) (\\S+[ео])е [Шш]оссе ", " $1му $2му шоссе "], + ["^ (\\d+)-е (\\S+[ео])е [Шш]оссе ", " $1му $2му шоссе "], + ["^ (\\d+)-е (\\S+ье) [Шш]оссе ", " $1му $2му шоссе "], + + [" Третому ", " Третьему "], + [" третому ", " третьему "], + ["жому ", "жьему "], + ["жой ", "жей "], + ["чому ", "чьему "], + ["чой ", "чей "] + ], + "genitive": [ + ["^ (\\S+)ая [Аа]ллея ", " $1ой аллеи "], + ["^ (\\S+)ья [Аа]ллея ", " $1ьей аллеи "], + ["^ (\\S+)яя [Аа]ллея ", " $1ей аллеи "], + ["^ (\\d+)-я (\\S+)ая [Аа]ллея ", " $1-й $2ой аллеи "], + ["^ [Аа]ллея ", " аллеи "], + + ["^ (\\S+)ая-(\\S+)ая [Уу]лица ", " $1ой-$2ой улицы "], + ["^ (\\S+)ая [Уу]лица ", " $1ой улицы "], + ["^ (\\S+)ья [Уу]лица ", " $1ьей улицы "], + ["^ (\\S+)яя [Уу]лица ", " $1ей улицы "], + ["^ (\\d+)-я (\\S+)ая [Уу]лица ", " $1-й $2ой улицы "], + ["^ (\\S+)ая (\\S+)ая [Уу]лица ", " $1ой $2ой улицы "], + ["^ (\\S+[вн])а [Уу]лица ", " $1ой улицы "], + ["^ (\\S+)ая (\\S+[вн])а [Уу]лица ", " $1ой $2ой улицы "], + ["^ Даньславля [Уу]лица ", " Даньславлей улицы "], + ["^ Добрыня [Уу]лица ", " Добрыней улицы "], + ["^ Людогоща [Уу]лица ", " Людогощей улицы "], + ["^ [Уу]лица ", " улицы "], + + ["^ (\\d+)-я [Лл]иния ", " $1-й линии "], + ["^ (\\d+)-(\\d+)-я [Лл]иния ", " $1-$2-й линии "], + ["^ (\\S+)ая [Лл]иния ", " $1ой линии "], + ["^ (\\S+)ья [Лл]иния ", " $1ьей линии "], + ["^ (\\S+)яя [Лл]иния ", " $1ей линии "], + ["^ (\\d+)-я (\\S+)ая [Лл]иния ", " $1-й $2ой линии "], + ["^ [Лл]иния ", " линии "], + + ["^ (\\d+)-(\\d+)-я [Лл]инии ", " $1-$2-й линий "], + + ["^ (\\S+)ая [Нн]абережная ", " $1ой набережной "], + ["^ (\\S+)ья [Нн]абережная ", " $1ьей набережной "], + ["^ (\\S+)яя [Нн]абережная ", " $1ей набережной "], + ["^ (\\d+)-я (\\S+)ая [Нн]абережная ", " $1-й $2ой набережной "], + ["^ [Нн]абережная ", " набережной "], + + ["^ (\\S+)ая [Пп]лощадь ", " $1ой площади "], + ["^ (\\S+)ья [Пп]лощадь ", " $1ьей площади "], + ["^ (\\S+)яя [Пп]лощадь ", " $1ей площади "], + ["^ (\\S+[вн])а [Пп]лощадь ", " $1ой площади "], + ["^ (\\d+)-я (\\S+)ая [Пп]лощадь ", " $1-й $2ой площади "], + ["^ [Пп]лощадь ", " площади "], + + ["^ (\\S+)ая [Ээ]стакада ", " $1ой эстакады "], + ["^ (\\S+)ья [Ээ]стакада ", " $1ьей эстакады "], + ["^ (\\S+)яя [Ээ]стакада ", " $1ей эстакады "], + ["^ (\\d+)-я (\\S+)ая [Ээ]стакада ", " $1-й $2ой эстакады "], + ["^ [Ээ]стакада ", " эстакады "], + + ["^ (\\S+)ая [Мм]агистраль ", " $1ой магистрали "], + ["^ (\\S+)ья [Мм]агистраль ", " $1ьей магистрали "], + ["^ (\\S+)яя [Мм]агистраль ", " $1ей магистрали "], + ["^ (\\d+)-я (\\S+)ая [Мм]агистраль ", " $1-й $2ой магистрали "], + ["^ [Мм]агистраль ", " магистрали "], + + ["^ (\\S+)ая [Рр]азвязка ", " $1ой развязки "], + ["^ (\\S+)ья [Рр]азвязка ", " $1ьей развязки "], + ["^ (\\S+)яя [Рр]азвязка ", " $1ей развязки "], + ["^ (\\d+)-я (\\S+)ая [Рр]азвязка ", " $1-й $2ой развязки "], + ["^ [Рр]азвязка ", " развязки "], + + ["^ (\\S+)ая [Тт]расса ", " $1ой трассы "], + ["^ (\\S+)ья [Тт]расса ", " $1ьей трассы "], + ["^ (\\S+)яя [Тт]расса ", " $1ей трассы "], + ["^ (\\d+)-я (\\S+)ая [Тт]расса ", " $1-й $2ой трассы "], + ["^ [Тт]расса ", " трассы "], + + ["^ (\\S+)ая ([Аа]вто)?[Дд]орога ", " $1ой $2дороги "], + ["^ (\\S+)ья ([Аа]вто)?[Дд]орога ", " $1ьей $2дороги "], + ["^ (\\S+)яя ([Аа]вто)?[Дд]орога ", " $1ей $2дороги "], + ["^ (\\d+)-я (\\S+)ая ([Аа]вто)?[Дд]орога ", " $1-й $2ой $3дороги "], + ["^ ([Аа]вто)?[Дд]орога ", " $1дороги "], + + ["^ (\\S+)ая [Дд]орожка ", " $1ой дорожки "], + ["^ (\\S+)ья [Дд]орожка ", " $1ьей дорожки "], + ["^ (\\S+)яя [Дд]орожка ", " $1ей дорожки "], + ["^ (\\d+)-я (\\S+)ая [Дд]орожка ", " $1-й $2ой дорожки "], + ["^ [Дд]орожка ", " дорожки "], + + ["^ (\\S+)во [Пп]оле ", " $1ва поля "], + ["^ (\\S+)ая [Кк]оса ", " $1ой косы "], + ["^ (\\S+)[иоы]й [Пп]роток ", " $1ого протока "], + + ["^ (\\S+н)ий [Бб]ульвар ", " $1его бульвара "], + ["^ (\\S+)[иоы]й [Бб]ульвар ", " $1ого бульвара "], + ["^ (\\S+[иы]н) [Бб]ульвар ", " $1ого бульвара "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Бб]ульвар ", " $1ого $2его бульвара "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Бб]ульвар ", " $1его $2ого бульвара "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Бб]ульвар ", " $1ого $2ого бульвара "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Бб]ульвар ", " $1ого $2ого бульвара "], + ["^ (\\d+)-й (\\S+н)ий [Бб]ульвар ", " $1-го $2его бульвара "], + ["^ (\\d+)-й (\\S+)[иоы]й [Бб]ульвар ", " $1-го $2ого бульвара "], + ["^ (\\d+)-й (\\S+[иы]н) [Бб]ульвар ", " $1-го $2ого бульвара "], + ["^ [Бб]ульвар ", " бульвара "], + + ["^ [Дд]убл[её]р ", " дублёра "], + + ["^ (\\S+н)ий [Зз]аезд ", " $1его заезда "], + ["^ (\\S+)[иоы]й [Зз]аезд ", " $1ого заезда "], + ["^ (\\S+[еёо]в) [Зз]аезд ", " $1а заезда "], + ["^ (\\S+[иы]н) [Зз]аезд ", " $1а заезда "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Зз]аезд ", " $1ого $2его заезда "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Зз]аезд ", " $1его $2ого заезда "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Зз]аезд ", " $1ого $2ого заезда "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Зз]аезд ", " $1ого $2а заезда "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Зз]аезд ", " $1ого $2а заезда "], + ["^ (\\d+)-й (\\S+н)ий [Зз]аезд ", " $1-го $2его заезда "], + ["^ (\\d+)-й (\\S+)[иоы]й [Зз]аезд ", " $1-го $2ого заезда "], + ["^ (\\d+)-й (\\S+[еёо]в) [Зз]аезд ", " $1-го $2а заезда "], + ["^ (\\d+)-й (\\S+[иы]н) [Зз]аезд ", " $1-го $2а заезда "], + ["^ [Зз]аезд ", " заезда "], + + ["^ (\\S+н)ий [Мм]ост ", " $1его моста "], + ["^ (\\S+)[иоы]й [Мм]ост ", " $1ого моста "], + ["^ (\\S+[еёо]в) [Мм]ост ", " $1а моста "], + ["^ (\\S+[иы]н) [Мм]ост ", " $1а моста "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Мм]ост ", " $1ого $2его моста "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Мм]ост ", " $1его $2ого моста "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Мм]ост ", " $1ого $2ого моста "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Мм]ост ", " $1ого $2а моста "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Мм]ост ", " $1ого $2а моста "], + ["^ (\\d+)-й (\\S+н)ий [Мм]ост ", " $1-го $2его моста "], + ["^ (\\d+)-й (\\S+)[иоы]й [Мм]ост ", " $1-го $2ого моста "], + ["^ (\\d+)-й (\\S+[еёо]в) [Мм]ост ", " $1-го $2а моста "], + ["^ (\\d+)-й (\\S+[иы]н) [Мм]ост ", " $1-го $2а моста "], + ["^ [Мм]ост ", " моста "], + + ["^ (\\S+н)ий [Оо]бход ", " $1его обхода "], + ["^ (\\S+)[иоы]й [Оо]бход ", " $1ого обхода "], + ["^ [Оо]бход ", " обхода "], + + ["^ (\\S+н)ий [Пп]арк ", " $1его парка "], + ["^ (\\S+)[иоы]й [Пп]арк ", " $1ого парка "], + ["^ (\\S+[иы]н) [Пп]арк ", " $1ого парка "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]арк ", " $1ого $2его парка "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]арк ", " $1его $2ого парка "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]арк ", " $1ого $2ого парка "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]арк ", " $1ого $2ого парка "], + ["^ (\\d+)-й (\\S+н)ий [Пп]арк ", " $1-го $2его парка "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]арк ", " $1-го $2ого парка "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]арк ", " $1-го $2ого парка "], + ["^ [Пп]арк ", " парка "], + + ["^ (\\S+)[иоы]й-(\\S+)[иоы]й [Пп]ереулок ", " $1ого-$2ого переулка "], + ["^ (\\d+)-й (\\S+)[иоы]й-(\\S+)[иоы]й [Пп]ереулок ", " $1-го $2ого-$3ого переулка "], + ["^ (\\S+н)ий [Пп]ереулок ", " $1его переулка "], + ["^ (\\S+)[иоы]й [Пп]ереулок ", " $1ого переулка "], + ["^ (\\S+[еёо]в) [Пп]ереулок ", " $1а переулка "], + ["^ (\\S+[иы]н) [Пп]ереулок ", " $1а переулка "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]ереулок ", " $1ого $2его переулка "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]ереулок ", " $1его $2ого переулка "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]ереулок ", " $1ого $2ого переулка "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Пп]ереулок ", " $1ого $2а переулка "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]ереулок ", " $1ого $2а переулка "], + ["^ (\\d+)-й (\\S+н)ий [Пп]ереулок ", " $1-го $2его переулка "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]ереулок ", " $1-го $2ого переулка "], + ["^ (\\d+)-й (\\S+[еёо]в) [Пп]ереулок ", " $1-го $2а переулка "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]ереулок ", " $1-го $2а переулка "], + ["^ [Пп]ереулок ", " переулка "], + + ["^ [Пп]одъезд ", " подъезда "], + + ["^ (\\S+[еёо]в)-(\\S+)[иоы]й [Пп]роезд ", " $1а-$2ого проезда "], + ["^ (\\S+н)ий [Пп]роезд ", " $1его проезда "], + ["^ (\\S+)[иоы]й [Пп]роезд ", " $1ого проезда "], + ["^ (\\S+[еёо]в) [Пп]роезд ", " $1а проезда "], + ["^ (\\S+[иы]н) [Пп]роезд ", " $1а проезда "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]роезд ", " $1ого $2его проезда "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]роезд ", " $1его $2ого проезда "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]роезд ", " $1ого $2ого проезда "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Пп]роезд ", " $1ого $2а проезда "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]роезд ", " $1ого $2а проезда "], + ["^ (\\d+)-й (\\S+н)ий [Пп]роезд ", " $1-го $2его проезда "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]роезд ", " $1-го $2ого проезда "], + ["^ (\\d+)-й (\\S+[еёо]в) [Пп]роезд ", " $1-го $2а проезда "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]роезд ", " $1-го $2а проезда "], + ["^ [Пп]роезд ", " проезда "], + + ["^ (\\S+н)ий [Пп]роспект ", " $1его проспекта "], + ["^ (\\S+)[иоы]й [Пп]роспект ", " $1ого проспекта "], + ["^ (\\S+[иы]н) [Пп]роспект ", " $1ого проспекта "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]роспект ", " $1ого $2его проспекта "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]роспект ", " $1его $2ого проспекта "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]роспект ", " $1ого $2ого проспекта "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]роспект ", " $1ого $2ого проспекта "], + ["^ (\\d+)-й (\\S+н)ий [Пп]роспект ", " $1-го $2его проспекта "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]роспект ", " $1-го $2ого проспекта "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]роспект ", " $1-го $2ого проспекта "], + ["^ [Пп]роспект ", " проспекта "], + + ["^ (\\S+н)ий [Пп]утепровод ", " $1его путепровода "], + ["^ (\\S+)[иоы]й [Пп]утепровод ", " $1ого путепровода "], + ["^ (\\S+[иы]н) [Пп]утепровод ", " $1ого путепровода "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]утепровод ", " $1ого $2его путепровода "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]утепровод ", " $1его $2ого путепровода "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]утепровод ", " $1ого $2ого путепровода "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]утепровод ", " $1ого $2ого путепровода "], + ["^ (\\d+)-й (\\S+н)ий [Пп]утепровод ", " $1-го $2его путепровода "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]утепровод ", " $1-го $2ого путепровода "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]утепровод ", " $1-го $2ого путепровода "], + ["^ [Пп]утепровод ", " путепровода "], + + ["^ (\\S+н)ий [Сс]пуск ", " $1его спуска "], + ["^ (\\S+)[иоы]й [Сс]пуск ", " $1ого спуска "], + ["^ (\\S+[еёо]в) [Сс]пуск ", " $1а спуска "], + ["^ (\\S+[иы]н) [Сс]пуск ", " $1а спуска "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Сс]пуск ", " $1ого $2его спуска "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Сс]пуск ", " $1его $2ого спуска "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Сс]пуск ", " $1ого $2ого спуска "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Сс]пуск ", " $1ого $2а спуска "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Сс]пуск ", " $1ого $2а спуска "], + ["^ (\\d+)-й (\\S+н)ий [Сс]пуск ", " $1-го $2его спуска "], + ["^ (\\d+)-й (\\S+)[иоы]й [Сс]пуск ", " $1-го $2ого спуска "], + ["^ (\\d+)-й (\\S+[еёо]в) [Сс]пуск ", " $1-го $2а спуска "], + ["^ (\\d+)-й (\\S+[иы]н) [Сс]пуск ", " $1-го $2а спуска "], + ["^ [Сс]пуск ", " спуска "], + + ["^ (\\S+н)ий [Сс]ъезд ", " $1его съезда "], + ["^ (\\S+)[иоы]й [Сс]ъезд ", " $1ого съезда "], + ["^ (\\S+[иы]н) [Сс]ъезд ", " $1ого съезда "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Сс]ъезд ", " $1ого $2его съезда "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Сс]ъезд ", " $1его $2ого съезда "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Сс]ъезд ", " $1ого $2ого съезда "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Сс]ъезд ", " $1ого $2ого съезда "], + ["^ (\\d+)-й (\\S+н)ий [Сс]ъезд ", " $1-го $2его съезда "], + ["^ (\\d+)-й (\\S+)[иоы]й [Сс]ъезд ", " $1-го $2ого съезда "], + ["^ (\\d+)-й (\\S+[иы]н) [Сс]ъезд ", " $1-го $2ого съезда "], + ["^ [Сс]ъезд ", " съезда "], + + ["^ (\\S+н)ий [Тт][уо]ннель ", " $1его тоннеля "], + ["^ (\\S+)[иоы]й [Тт][уо]ннель ", " $1ого тоннеля "], + ["^ (\\S+[иы]н) [Тт][уо]ннель ", " $1ого тоннеля "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Тт][уо]ннель ", " $1ого $2его тоннеля "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Тт][уо]ннель ", " $1его $2ого тоннеля "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Тт][уо]ннель ", " $1ого $2ого тоннеля "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Тт][уо]ннель ", " $1ого $2ого тоннеля "], + ["^ (\\d+)-й (\\S+н)ий [Тт][уо]ннель ", " $1-го $2его тоннеля "], + ["^ (\\d+)-й (\\S+)[иоы]й [Тт][уо]ннель ", " $1-го $2ого тоннеля "], + ["^ (\\d+)-й (\\S+[иы]н) [Тт][уо]ннель ", " $1-го $2ого тоннеля "], + ["^ [Тт][уо]ннель ", " тоннеля "], + + ["^ (\\S+н)ий [Тт]ракт ", " $1ем тракта "], + ["^ (\\S+)[иоы]й [Тт]ракт ", " $1ого тракта "], + ["^ (\\S+[еёо]в) [Тт]ракт ", " $1а тракта "], + ["^ (\\S+[иы]н) [Тт]ракт ", " $1а тракта "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Тт]ракт ", " $1ого $2его тракта "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Тт]ракт ", " $1его $2ого тракта "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Тт]ракт ", " $1ого $2ого тракта "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Тт]ракт ", " $1ого $2а тракта "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Тт]ракт ", " $1ого $2а тракта "], + ["^ (\\d+)-й (\\S+н)ий [Тт]ракт ", " $1-го $2его тракта "], + ["^ (\\d+)-й (\\S+)[иоы]й [Тт]ракт ", " $1-го $2ого тракта "], + ["^ (\\d+)-й (\\S+[еёо]в) [Тт]ракт ", " $1-го $2а тракта "], + ["^ (\\d+)-й (\\S+[иы]н) [Тт]ракт ", " $1-го $2а тракта "], + ["^ [Тт]ракт ", " тракта "], + + ["^ (\\S+н)ий [Тт]упик ", " $1его тупика "], + ["^ (\\S+)[иоы]й [Тт]упик ", " $1ого тупика "], + ["^ (\\S+[еёо]в) [Тт]упик ", " $1а тупика "], + ["^ (\\S+[иы]н) [Тт]упик ", " $1а тупика "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Тт]упик ", " $1ого $2его тупика "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Тт]упик ", " $1его $2ого тупика "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Тт]упик ", " $1ого $2ого тупика "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Тт]упик ", " $1ого $2а тупика "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Тт]упик ", " $1ого $2а тупика "], + ["^ (\\d+)-й (\\S+н)ий [Тт]упик ", " $1-го $2его тупика "], + ["^ (\\d+)-й (\\S+)[иоы]й [Тт]упик ", " $1-го $2ого тупика "], + ["^ (\\d+)-й (\\S+[еёо]в) [Тт]упик ", " $1-го $2а тупика "], + ["^ (\\d+)-й (\\S+[иы]н) [Тт]упик ", " $1-го $2а тупика "], + ["^ [Тт]упик ", " тупика "], + + ["^ (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1го $2кольца "], + ["^ (\\S+ье) ([Пп]олу)?[Кк]ольцо ", " $1го $2кольца "], + ["^ (\\S+[ео])е (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1го $2го $3кольца "], + ["^ (\\S+ье) (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1го $2го $3кольца "], + ["^ (\\d+)-е (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1го $2го $3кольца "], + ["^ (\\d+)-е (\\S+ье) ([Пп]олу)?[Кк]ольцо ", " $1го $2го $3кольца "], + ["^ ([Пп]олу)?[Кк]ольцо ", " $1кольца "], + + ["^ (\\S+[ео])е [Шш]оссе ", " $1го шоссе "], + ["^ (\\S+ье) [Шш]оссе ", " $1го шоссе "], + ["^ (\\S+[ео])е (\\S+[ео])е [Шш]оссе ", " $1го $2го шоссе "], + ["^ (\\S+ье) (\\S+[ео])е [Шш]оссе ", " $1го $2го шоссе "], + ["^ (\\d+)-е (\\S+[ео])е [Шш]оссе ", " $1го $2го шоссе "], + ["^ (\\d+)-е (\\S+ье) [Шш]оссе ", " $1го $2го шоссе "], + + [" Третого ", " Третьего "], + [" третого ", " третьего "], + ["жого ", "жьего "], + ["чого ", "чьего "] + ], + "prepositional": [ + ["^ (\\S+)ая [Аа]ллея ", " $1ой аллее "], + ["^ (\\S+)ья [Аа]ллея ", " $1ьей аллее "], + ["^ (\\S+)яя [Аа]ллея ", " $1ей аллее "], + ["^ (\\d+)-я (\\S+)ая [Аа]ллея ", " $1-й $2ой аллее "], + ["^ [Аа]ллея ", " аллее "], + + ["^ (\\S+)ая-(\\S+)ая [Уу]лица ", " $1ой-$2ой улице "], + ["^ (\\S+)ая [Уу]лица ", " $1ой улице "], + ["^ (\\S+)ья [Уу]лица ", " $1ьей улице "], + ["^ (\\S+)яя [Уу]лица ", " $1ей улице "], + ["^ (\\d+)-я (\\S+)ая [Уу]лица ", " $1-й $2ой улице "], + ["^ (\\S+)ая (\\S+)ая [Уу]лица ", " $1ой $2ой улице "], + ["^ (\\S+[вн])а [Уу]лица ", " $1ой улице "], + ["^ (\\S+)ая (\\S+[вн])а [Уу]лица ", " $1ой $2ой улице "], + ["^ Даньславля [Уу]лица ", " Даньславлей улице "], + ["^ Добрыня [Уу]лица ", " Добрыней улице "], + ["^ Людогоща [Уу]лица ", " Людогощей улице "], + ["^ [Уу]лица ", " улице "], + + ["^ (\\d+)-я [Лл]иния ", " $1-й линии "], + ["^ (\\d+)-(\\d+)-я [Лл]иния ", " $1-$2-й линии "], + ["^ (\\S+)ая [Лл]иния ", " $1ой линии "], + ["^ (\\S+)ья [Лл]иния ", " $1ьей линии "], + ["^ (\\S+)яя [Лл]иния ", " $1ей линии "], + ["^ (\\d+)-я (\\S+)ая [Лл]иния ", " $1-й $2ой линии "], + ["^ [Лл]иния ", " линии "], + + ["^ (\\d+)-(\\d+)-я [Лл]инии ", " $1-$2-й линиях "], + + ["^ (\\S+)ая [Нн]абережная ", " $1ой набережной "], + ["^ (\\S+)ья [Нн]абережная ", " $1ьей набережной "], + ["^ (\\S+)яя [Нн]абережная ", " $1ей набережной "], + ["^ (\\d+)-я (\\S+)ая [Нн]абережная ", " $1-й $2ой набережной "], + ["^ [Нн]абережная ", " набережной "], + + ["^ (\\S+)ая [Пп]лощадь ", " $1ой площади "], + ["^ (\\S+)ья [Пп]лощадь ", " $1ьей площади "], + ["^ (\\S+)яя [Пп]лощадь ", " $1ей площади "], + ["^ (\\S+[вн])а [Пп]лощадь ", " $1ой площади "], + ["^ (\\d+)-я (\\S+)ая [Пп]лощадь ", " $1-й $2ой площади "], + ["^ [Пп]лощадь ", " площади "], + + ["^ (\\S+)ая [Ээ]стакада ", " $1ой эстакаде "], + ["^ (\\S+)ья [Ээ]стакада ", " $1ьей эстакаде "], + ["^ (\\S+)яя [Ээ]стакада ", " $1ей эстакаде "], + ["^ (\\d+)-я (\\S+)ая [Ээ]стакада ", " $1-й $2ой эстакаде "], + ["^ [Ээ]стакада ", " эстакаде "], + + ["^ (\\S+)ая [Мм]агистраль ", " $1ой магистрали "], + ["^ (\\S+)ья [Мм]агистраль ", " $1ьей магистрали "], + ["^ (\\S+)яя [Мм]агистраль ", " $1ей магистрали "], + ["^ (\\d+)-я (\\S+)ая [Мм]агистраль ", " $1-й $2ой магистрали "], + ["^ [Мм]агистраль ", " магистрали "], + + ["^ (\\S+)ая [Рр]азвязка ", " $1ой развязке "], + ["^ (\\S+)ья [Рр]азвязка ", " $1ьей развязке "], + ["^ (\\S+)яя [Рр]азвязка ", " $1ей развязке "], + ["^ (\\d+)-я (\\S+)ая [Рр]азвязка ", " $1-й $2ой развязке "], + ["^ [Рр]азвязка ", " развязке "], + + ["^ (\\S+)ая [Тт]расса ", " $1ой трассе "], + ["^ (\\S+)ья [Тт]расса ", " $1ьей трассе "], + ["^ (\\S+)яя [Тт]расса ", " $1ей трассе "], + ["^ (\\d+)-я (\\S+)ая [Тт]расса ", " $1-й $2ой трассе "], + ["^ [Тт]расса ", " трассе "], + + ["^ (\\S+)ая ([Аа]вто)?[Дд]орога ", " $1ой $2дороге "], + ["^ (\\S+)ья ([Аа]вто)?[Дд]орога ", " $1ьей $2дороге "], + ["^ (\\S+)яя ([Аа]вто)?[Дд]орога ", " $1ей $2дороге "], + ["^ (\\d+)-я (\\S+)ая ([Аа]вто)?[Дд]орога ", " $1-й $2ой $3дороге "], + ["^ ([Аа]вто)?[Дд]орога ", " $1дороге "], + + ["^ (\\S+)ая [Дд]орожка ", " $1ой дорожке "], + ["^ (\\S+)ья [Дд]орожка ", " $1ьей дорожке "], + ["^ (\\S+)яя [Дд]орожка ", " $1ей дорожке "], + ["^ (\\d+)-я (\\S+)ая [Дд]орожка ", " $1-й $2ой дорожке "], + ["^ [Дд]орожка ", " дорожке "], + + ["^ (\\S+)во [Пп]оле ", " $1ве поле "], + ["^ (\\S+)ая [Кк]оса ", " $1ой косе "], + ["^ (\\S+)[иоы]й [Пп]роток ", " $1ом протоке "], + + ["^ (\\S+н)ий [Бб]ульвар ", " $1ем бульваре "], + ["^ (\\S+)[иоы]й [Бб]ульвар ", " $1ом бульваре "], + ["^ (\\S+[иы]н) [Бб]ульвар ", " $1ом бульваре "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Бб]ульвар ", " $1ом $2ем бульваре "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Бб]ульвар ", " $1ем $2ом бульваре "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Бб]ульвар ", " $1ом $2ом бульваре "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Бб]ульвар ", " $1ом $2ом бульваре "], + ["^ (\\d+)-й (\\S+н)ий [Бб]ульвар ", " $1-м $2ем бульваре "], + ["^ (\\d+)-й (\\S+)[иоы]й [Бб]ульвар ", " $1-м $2ом бульваре "], + ["^ (\\d+)-й (\\S+[иы]н) [Бб]ульвар ", " $1-м $2ом бульваре "], + ["^ [Бб]ульвар ", " бульваре "], + + ["^ [Дд]убл[её]р ", " дублёре "], + + ["^ (\\S+н)ий [Зз]аезд ", " $1ем заезде "], + ["^ (\\S+)[иоы]й [Зз]аезд ", " $1ом заезде "], + ["^ (\\S+[еёо]в) [Зз]аезд ", " $1ом заезде "], + ["^ (\\S+[иы]н) [Зз]аезд ", " $1ом заезде "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Зз]аезд ", " $1ом $2ем заезде "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Зз]аезд ", " $1ем $2ом заезде "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Зз]аезд ", " $1ом $2ом заезде "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Зз]аезд ", " $1ом $2ом заезде "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Зз]аезд ", " $1ом $2ом заезде "], + ["^ (\\d+)-й (\\S+н)ий [Зз]аезд ", " $1-м $2ем заезде "], + ["^ (\\d+)-й (\\S+)[иоы]й [Зз]аезд ", " $1-м $2ом заезде "], + ["^ (\\d+)-й (\\S+[еёо]в) [Зз]аезд ", " $1-м $2ом заезде "], + ["^ (\\d+)-й (\\S+[иы]н) [Зз]аезд ", " $1-м $2ом заезде "], + ["^ [Зз]аезд ", " заезде "], + + ["^ (\\S+н)ий [Мм]ост ", " $1ем мосту "], + ["^ (\\S+)[иоы]й [Мм]ост ", " $1ом мосту "], + ["^ (\\S+[еёо]в) [Мм]ост ", " $1ом мосту "], + ["^ (\\S+[иы]н) [Мм]ост ", " $1ом мосту "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Мм]ост ", " $1ом $2ем мосту "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Мм]ост ", " $1ем $2ом мосту "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Мм]ост ", " $1ом $2ом мосту "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Мм]ост ", " $1ом $2ом мосту "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Мм]ост ", " $1ом $2ом мосту "], + ["^ (\\d+)-й (\\S+н)ий [Мм]ост ", " $1-м $2ем мосту "], + ["^ (\\d+)-й (\\S+)[иоы]й [Мм]ост ", " $1-м $2ом мосту "], + ["^ (\\d+)-й (\\S+[еёо]в) [Мм]ост ", " $1-м $2ом мосту "], + ["^ (\\d+)-й (\\S+[иы]н) [Мм]ост ", " $1-м $2ом мосту "], + ["^ [Мм]ост ", " мосту "], + + ["^ (\\S+н)ий [Оо]бход ", " $1ем обходе "], + ["^ (\\S+)[иоы]й [Оо]бход ", " $1ом обходе "], + ["^ [Оо]бход ", " обходе "], + + ["^ (\\S+н)ий [Пп]арк ", " $1ем парке "], + ["^ (\\S+)[иоы]й [Пп]арк ", " $1ом парке "], + ["^ (\\S+[иы]н) [Пп]арк ", " $1ом парке "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]арк ", " $1ом $2ем парке "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]арк ", " $1ем $2ом парке "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]арк ", " $1ом $2ом парке "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]арк ", " $1ом $2ом парке "], + ["^ (\\d+)-й (\\S+н)ий [Пп]арк ", " $1-м $2ем парке "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]арк ", " $1-м $2ом парке "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]арк ", " $1-м $2ом парке "], + ["^ [Пп]арк ", " парке "], + + ["^ (\\S+)[иоы]й-(\\S+)[иоы]й [Пп]ереулок ", " $1ом-$2ом переулке "], + ["^ (\\d+)-й (\\S+)[иоы]й-(\\S+)[иоы]й [Пп]ереулок ", " $1-м $2ом-$3ом переулке "], + ["^ (\\S+н)ий [Пп]ереулок ", " $1ем переулке "], + ["^ (\\S+)[иоы]й [Пп]ереулок ", " $1ом переулке "], + ["^ (\\S+[еёо]в) [Пп]ереулок ", " $1ом переулке "], + ["^ (\\S+[иы]н) [Пп]ереулок ", " $1ом переулке "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]ереулок ", " $1ом $2ем переулке "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]ереулок ", " $1ем $2ом переулке "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]ереулок ", " $1ом $2ом переулке "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Пп]ереулок ", " $1ом $2ом переулке "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]ереулок ", " $1ом $2ом переулке "], + ["^ (\\d+)-й (\\S+н)ий [Пп]ереулок ", " $1-м $2ем переулке "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]ереулок ", " $1-м $2ом переулке "], + ["^ (\\d+)-й (\\S+[еёо]в) [Пп]ереулок ", " $1-м $2ом переулке "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]ереулок ", " $1-м $2ом переулке "], + ["^ [Пп]ереулок ", " переулке "], + + ["^ [Пп]одъезд ", " подъезде "], + + ["^ (\\S+[еёо]в)-(\\S+)[иоы]й [Пп]роезд ", " $1ом-$2ом проезде "], + ["^ (\\S+н)ий [Пп]роезд ", " $1ем проезде "], + ["^ (\\S+)[иоы]й [Пп]роезд ", " $1ом проезде "], + ["^ (\\S+[еёо]в) [Пп]роезд ", " $1ом проезде "], + ["^ (\\S+[иы]н) [Пп]роезд ", " $1ом проезде "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]роезд ", " $1ом $2ем проезде "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]роезд ", " $1ем $2ом проезде "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]роезд ", " $1ом $2ом проезде "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Пп]роезд ", " $1ом $2ом проезде "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]роезд ", " $1ом $2ом проезде "], + ["^ (\\d+)-й (\\S+н)ий [Пп]роезд ", " $1-м $2ем проезде "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]роезд ", " $1-м $2ом проезде "], + ["^ (\\d+)-й (\\S+[еёо]в) [Пп]роезд ", " $1-м $2ом проезде "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]роезд ", " $1-м $2ом проезде "], + ["^ [Пп]роезд ", " проезде "], + + ["^ (\\S+н)ий [Пп]роспект ", " $1ем проспекте "], + ["^ (\\S+)[иоы]й [Пп]роспект ", " $1ом проспекте "], + ["^ (\\S+[иы]н) [Пп]роспект ", " $1ом проспекте "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]роспект ", " $1ом $2ем проспекте "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]роспект ", " $1ем $2ом проспекте "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]роспект ", " $1ом $2ом проспекте "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]роспект ", " $1ом $2ом проспекте "], + ["^ (\\d+)-й (\\S+н)ий [Пп]роспект ", " $1-м $2ем проспекте "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]роспект ", " $1-м $2ом проспекте "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]роспект ", " $1-м $2ом проспекте "], + ["^ [Пп]роспект ", " проспекте "], + + ["^ (\\S+н)ий [Пп]утепровод ", " $1ем путепроводе "], + ["^ (\\S+)[иоы]й [Пп]утепровод ", " $1ом путепроводе "], + ["^ (\\S+[иы]н) [Пп]утепровод ", " $1ом путепроводе "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Пп]утепровод ", " $1ом $2ем путепроводе "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Пп]утепровод ", " $1ем $2ом путепроводе "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Пп]утепровод ", " $1ом $2ом путепроводе "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Пп]утепровод ", " $1ом $2ом путепроводе "], + ["^ (\\d+)-й (\\S+н)ий [Пп]утепровод ", " $1-м $2ем путепроводе "], + ["^ (\\d+)-й (\\S+)[иоы]й [Пп]утепровод ", " $1-м $2ом путепроводе "], + ["^ (\\d+)-й (\\S+[иы]н) [Пп]утепровод ", " $1-м $2ом путепроводе "], + ["^ [Пп]утепровод ", " путепроводе "], + + ["^ (\\S+н)ий [Сс]пуск ", " $1ем спуске "], + ["^ (\\S+)[иоы]й [Сс]пуск ", " $1ом спуске "], + ["^ (\\S+[еёо]в) [Сс]пуск ", " $1ом спуске "], + ["^ (\\S+[иы]н) [Сс]пуск ", " $1ом спуске "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Сс]пуск ", " $1ом $2ем спуске "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Сс]пуск ", " $1ем $2ом спуске "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Сс]пуск ", " $1ом $2ом спуске "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Сс]пуск ", " $1ом $2ом спуске "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Сс]пуск ", " $1ом $2ом спуске "], + ["^ (\\d+)-й (\\S+н)ий [Сс]пуск ", " $1-м $2ем спуске "], + ["^ (\\d+)-й (\\S+)[иоы]й [Сс]пуск ", " $1-м $2ом спуске "], + ["^ (\\d+)-й (\\S+[еёо]в) [Сс]пуск ", " $1-м $2ом спуске "], + ["^ (\\d+)-й (\\S+[иы]н) [Сс]пуск ", " $1-м $2ом спуске "], + ["^ [Сс]пуск ", " спуске "], + + ["^ (\\S+н)ий [Сс]ъезд ", " $1ем съезде "], + ["^ (\\S+)[иоы]й [Сс]ъезд ", " $1ом съезде "], + ["^ (\\S+[иы]н) [Сс]ъезд ", " $1ом съезде "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Сс]ъезд ", " $1ом $2ем съезде "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Сс]ъезд ", " $1ем $2ом съезде "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Сс]ъезд ", " $1ом $2ом съезде "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Сс]ъезд ", " $1ом $2ом съезде "], + ["^ (\\d+)-й (\\S+н)ий [Сс]ъезд ", " $1-м $2ем съезде "], + ["^ (\\d+)-й (\\S+)[иоы]й [Сс]ъезд ", " $1-м $2ом съезде "], + ["^ (\\d+)-й (\\S+[иы]н) [Сс]ъезд ", " $1-м $2ом съезде "], + ["^ [Сс]ъезд ", " съезде "], + + ["^ (\\S+н)ий [Тт][уо]ннель ", " $1ем тоннеле "], + ["^ (\\S+)[иоы]й [Тт][уо]ннель ", " $1ом тоннеле "], + ["^ (\\S+[иы]н) [Тт][уо]ннель ", " $1ом тоннеле "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Тт][уо]ннель ", " $1ом $2ем тоннеле "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Тт][уо]ннель ", " $1ем $2ом тоннеле "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Тт][уо]ннель ", " $1ом $2ом тоннеле "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Тт][уо]ннель ", " $1ом $2ом тоннеле "], + ["^ (\\d+)-й (\\S+н)ий [Тт][уо]ннель ", " $1-м $2ем тоннеле "], + ["^ (\\d+)-й (\\S+)[иоы]й [Тт][уо]ннель ", " $1-м $2ом тоннеле "], + ["^ (\\d+)-й (\\S+[иы]н) [Тт][уо]ннель ", " $1-м $2ом тоннеле "], + ["^ [Тт][уо]ннель ", " тоннеле "], + + ["^ (\\S+н)ий [Тт]ракт ", " $1ем тракте "], + ["^ (\\S+)[иоы]й [Тт]ракт ", " $1ом тракте "], + ["^ (\\S+[еёо]в) [Тт]ракт ", " $1ом тракте "], + ["^ (\\S+[иы]н) [Тт]ракт ", " $1ом тракте "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Тт]ракт ", " $1ом $2ем тракте "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Тт]ракт ", " $1ем $2ом тракте "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Тт]ракт ", " $1ом $2ом тракте "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Тт]ракт ", " $1ом $2ом тракте "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Тт]ракт ", " $1ом $2ом тракте "], + ["^ (\\d+)-й (\\S+н)ий [Тт]ракт ", " $1-м $2ем тракте "], + ["^ (\\d+)-й (\\S+)[иоы]й [Тт]ракт ", " $1-м $2ом тракте "], + ["^ (\\d+)-й (\\S+[еёо]в) [Тт]ракт ", " $1-м $2ом тракте "], + ["^ (\\d+)-й (\\S+[иы]н) [Тт]ракт ", " $1-м $2ом тракте "], + ["^ [Тт]ракт ", " тракте "], + + ["^ (\\S+н)ий [Тт]упик ", " $1ем тупике "], + ["^ (\\S+)[иоы]й [Тт]упик ", " $1ом тупике "], + ["^ (\\S+[еёо]в) [Тт]упик ", " $1ом тупике "], + ["^ (\\S+[иы]н) [Тт]упик ", " $1ом тупике "], + ["^ (\\S+)[иоы]й (\\S+н)ий [Тт]упик ", " $1ом $2ем тупике "], + ["^ (\\S+н)ий (\\S+)[иоы]й [Тт]упик ", " $1ем $2ом тупике "], + ["^ (\\S+)[иоы]й (\\S+)[иоы]й [Тт]упик ", " $1ом $2ом тупике "], + ["^ (\\S+)[иоы]й (\\S+[еёо]в) [Тт]упик ", " $1ом $2ом тупике "], + ["^ (\\S+)[иоы]й (\\S+[иы]н) [Тт]упик ", " $1ом $2ом тупике "], + ["^ (\\d+)-й (\\S+н)ий [Тт]упик ", " $1-м $2ем тупике "], + ["^ (\\d+)-й (\\S+)[иоы]й [Тт]упик ", " $1-м $2ом тупике "], + ["^ (\\d+)-й (\\S+[еёо]в) [Тт]упик ", " $1-м $2ом тупике "], + ["^ (\\d+)-й (\\S+[иы]н) [Тт]упик ", " $1-м $2ом тупике "], + ["^ [Тт]упик ", " тупике "], + + ["^ (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1м $2кольце "], + ["^ (\\S+ье) ([Пп]олу)?[Кк]ольцо ", " $1м $2кольце "], + ["^ (\\S+[ео])е (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1м $2м $3кольце "], + ["^ (\\S+ье) (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1м $2м $3кольце "], + ["^ (\\d+)-е (\\S+[ео])е ([Пп]олу)?[Кк]ольцо ", " $1м $2м $3кольце "], + ["^ (\\d+)-е (\\S+ье) ([Пп]олу)?[Кк]ольцо ", " $1м $2м $3кольце "], + ["^ ([Пп]олу)?[Кк]ольцо ", " $1кольце "], + + ["^ (\\S+[ео])е [Шш]оссе ", " $1м шоссе "], + ["^ (\\S+ье) [Шш]оссе ", " $1м шоссе "], + ["^ (\\S+[ео])е (\\S+[ео])е [Шш]оссе ", " $1м $2м шоссе "], + ["^ (\\S+ье) (\\S+[ео])е [Шш]оссе ", " $1м $2м шоссе "], + ["^ (\\d+)-е (\\S+[ео])е [Шш]оссе ", " $1м $2м шоссе "], + ["^ (\\d+)-е (\\S+ье) [Шш]оссе ", " $1м $2м шоссе "], + + [" Третом ", " Третьем "], + [" третом ", " третьем "], + ["жом ", "жьем "], + ["чом ", "чьем "] + ] + } +} diff --git a/languages/overrides/ru.js b/languages/overrides/ru.js new file mode 100644 index 000000000..e477b63b3 --- /dev/null +++ b/languages/overrides/ru.js @@ -0,0 +1,35 @@ +// Add grammar option to {way_name} and {rotary_name} depending on phrase context + +var replaces = [ + ['(развернитесь +на) +\{((way_name)|(rotary_name))\}', '$1 {$2:prepositional}'], + ['(на) +\{((way_name)|(rotary_name))\} +с +', '$1 {$2:prepositional} с '], + ['(в +конце) +\{((way_name)|(rotary_name))\}', '$1 {$2:genitive}'], + ['(по) +\{((way_name)|(rotary_name))\}', '$1 {$2:dative}'], + ['(на) +\{((way_name)|(rotary_name))\}', '$1 {$2:accusative}'] +]; + +function optionize(phrase) { + var result = phrase; + replaces.forEach(function(pattern) { + var re = new RegExp(pattern[0], 'gi'); + result = result.replace(re, pattern[1]); + }); + return result; +}; + +function iterate(values) { + Object.keys(values).forEach(function (key) { + var value = values[key]; + if (typeof value === 'string') { + values[key] = optionize(value); + } else if (typeof value === 'object') { + iterate(value); + } + }); +}; + +module.exports = function(content) { + // Iterate all string values recursively + iterate(content); + return content; +}; diff --git a/languages/translations/ru.json b/languages/translations/ru.json index 4c443be59..5d17f3e6e 100644 --- a/languages/translations/ru.json +++ b/languages/translations/ru.json @@ -85,225 +85,225 @@ "continue": { "default": { "default": "Двигайтесь {modifier}", - "name": "Двигайтесь {modifier} по {way_name}", + "name": "Двигайтесь {modifier} по {way_name:dative}", "destination": "Двигайтесь {modifier} в направлении {destination}", - "exit": "Двигайтесь {modifier} на {way_name}" + "exit": "Двигайтесь {modifier} на {way_name:accusative}" }, "straight": { "default": "Двигайтесь прямо", - "name": "Продолжите движение по {way_name}", + "name": "Продолжите движение по {way_name:dative}", "destination": "Продолжите движение в направлении {destination}", "distance": "Двигайтесь прямо {distance}", - "namedistance": "Двигайтесь прямо {distance} по {way_name}" + "namedistance": "Двигайтесь прямо {distance} по {way_name:dative}" }, "sharp left": { "default": "Резко поверните налево", - "name": "Резко поверните налево на {way_name}", + "name": "Резко поверните налево на {way_name:accusative}", "destination": "Резко поверните налево в направлении {destination}" }, "sharp right": { "default": "Резко поверните направо", - "name": "Резко поверните направо на {way_name}", + "name": "Резко поверните направо на {way_name:accusative}", "destination": "Резко поверните направо в направлении {destination}" }, "slight left": { "default": "Плавно поверните налево", - "name": "Плавно поверните налево на {way_name}", + "name": "Плавно поверните налево на {way_name:accusative}", "destination": "Плавно поверните налево в направлении {destination}" }, "slight right": { "default": "Плавно поверните направо", - "name": "Плавно поверните направо на {way_name}", + "name": "Плавно поверните направо на {way_name:accusative}", "destination": "Плавно поверните направо в направлении {destination}" }, "uturn": { "default": "Развернитесь", - "name": "Развернитесь и продолжите движение по {way_name}", + "name": "Развернитесь и продолжите движение по {way_name:dative}", "destination": "Развернитесь в направлении {destination}" } }, "depart": { "default": { "default": "Двигайтесь в {direction} направлении", - "name": "Двигайтесь в {direction} направлении по {way_name}" + "name": "Двигайтесь в {direction} направлении по {way_name:dative}" } }, "end of road": { "default": { "default": "Поверните {modifier}", - "name": "Поверните {modifier} на {way_name}", + "name": "Поверните {modifier} на {way_name:accusative}", "destination": "Поверните {modifier} в направлении {destination}" }, "straight": { "default": "Двигайтесь прямо", - "name": "Двигайтесь прямо по {way_name}", + "name": "Двигайтесь прямо по {way_name:dative}", "destination": "Двигайтесь прямо в направлении {destination}" }, "uturn": { "default": "В конце дороги развернитесь", - "name": "Развернитесь в конце {way_name}", + "name": "Развернитесь в конце {way_name:genitive}", "destination": "В конце дороги развернитесь в направлении {destination}" } }, "fork": { "default": { "default": "На развилке двигайтесь {modifier}", - "name": "На развилке двигайтесь {modifier} на {way_name}", + "name": "На развилке двигайтесь {modifier} на {way_name:accusative}", "destination": "На развилке двигайтесь {modifier} в направлении {destination}" }, "slight left": { "default": "На развилке держитесь левее", - "name": "На развилке держитесь левее на {way_name}", + "name": "На развилке держитесь левее на {way_name:accusative}", "destination": "На развилке держитесь левее и продолжите движение в направлении {destination}" }, "slight right": { "default": "На развилке держитесь правее", - "name": "На развилке держитесь правее на {way_name}", + "name": "На развилке держитесь правее на {way_name:accusative}", "destination": "На развилке держитесь правее и продолжите движение в направлении {destination}" }, "sharp left": { "default": "На развилке резко поверните налево", - "name": "На развилке резко поверните налево на {way_name}", + "name": "На развилке резко поверните налево на {way_name:accusative}", "destination": "На развилке резко поверните налево и продолжите движение в направлении {destination}" }, "sharp right": { "default": "На развилке резко поверните направо", - "name": "На развилке резко поверните направо на {way_name}", + "name": "На развилке резко поверните направо на {way_name:accusative}", "destination": "На развилке резко поверните направо и продолжите движение в направлении {destination}" }, "uturn": { "default": "На развилке развернитесь", - "name": "На развилке развернитесь на {way_name}", + "name": "На развилке развернитесь на {way_name:prepositional}", "destination": "На развилке развернитесь и продолжите движение в направлении {destination}" } }, "merge": { "default": { "default": "Перестройтесь {modifier}", - "name": "Перестройтесь {modifier} на {way_name}", + "name": "Перестройтесь {modifier} на {way_name:accusative}", "destination": "Перестройтесь {modifier} в направлении {destination}" }, "slight left": { "default": "Перестройтесь левее", - "name": "Перестройтесь левее на {way_name}", + "name": "Перестройтесь левее на {way_name:accusative}", "destination": "Перестройтесь левее в направлении {destination}" }, "slight right": { "default": "Перестройтесь правее", - "name": "Перестройтесь правее на {way_name}", + "name": "Перестройтесь правее на {way_name:accusative}", "destination": "Перестройтесь правее в направлении {destination}" }, "sharp left": { "default": "Перестраивайтесь левее", - "name": "Перестраивайтесь левее на {way_name}", + "name": "Перестраивайтесь левее на {way_name:accusative}", "destination": "Перестраивайтесь левее в направлении {destination}" }, "sharp right": { "default": "Перестраивайтесь правее", - "name": "Перестраивайтесь правее на {way_name}", + "name": "Перестраивайтесь правее на {way_name:accusative}", "destination": "Перестраивайтесь правее в направлении {destination}" }, "uturn": { "default": "Развернитесь", - "name": "Развернитесь на {way_name}", + "name": "Развернитесь на {way_name:prepositional}", "destination": "Развернитесь в направлении {destination}" } }, "new name": { "default": { "default": "Двигайтесь {modifier}", - "name": "Двигайтесь {modifier} на {way_name}", + "name": "Двигайтесь {modifier} на {way_name:accusative}", "destination": "Двигайтесь {modifier} в направлении {destination}" }, "straight": { "default": "Двигайтесь прямо", - "name": "Продолжите движение по {way_name}", + "name": "Продолжите движение по {way_name:dative}", "destination": "Продолжите движение в направлении {destination}" }, "sharp left": { "default": "Резко поверните налево", - "name": "Резко поверните налево на {way_name}", + "name": "Резко поверните налево на {way_name:accusative}", "destination": "Резко поверните налево и продолжите движение в направлении {destination}" }, "sharp right": { "default": "Резко поверните направо", - "name": "Резко поверните направо на {way_name}", + "name": "Резко поверните направо на {way_name:accusative}", "destination": "Резко поверните направо и продолжите движение в направлении {destination}" }, "slight left": { "default": "Плавно поверните налево", - "name": "Плавно поверните налево на {way_name}", + "name": "Плавно поверните налево на {way_name:accusative}", "destination": "Плавно поверните налево в направлении {destination}" }, "slight right": { "default": "Плавно поверните направо", - "name": "Плавно поверните направо на {way_name}", + "name": "Плавно поверните направо на {way_name:accusative}", "destination": "Плавно поверните направо в направлении {destination}" }, "uturn": { "default": "Развернитесь", - "name": "Развернитесь на {way_name}", + "name": "Развернитесь на {way_name:prepositional}", "destination": "Развернитесь и продолжите движение в направлении {destination}" } }, "notification": { "default": { "default": "Двигайтесь {modifier}", - "name": "Двигайтесь {modifier} по {way_name}", + "name": "Двигайтесь {modifier} по {way_name:dative}", "destination": "Двигайтесь {modifier} в направлении {destination}" }, "uturn": { "default": "Развернитесь", - "name": "Развернитесь на {way_name}", + "name": "Развернитесь на {way_name:prepositional}", "destination": "Развернитесь и продолжите движение в направлении {destination}" } }, "off ramp": { "default": { "default": "Сверните на съезд", - "name": "Сверните на съезд на {way_name}", + "name": "Сверните на съезд на {way_name:accusative}", "destination": "Сверните на съезд в направлении {destination}", "exit": "Сверните на съезд {exit}", "exit_destination": "Сверните на съезд {exit} в направлении {destination}" }, "left": { "default": "Сверните на левый съезд", - "name": "Сверните на левый съезд на {way_name}", + "name": "Сверните на левый съезд на {way_name:accusative}", "destination": "Сверните на левый съезд в направлении {destination}", "exit": "Сверните на съезд {exit} слева", "exit_destination": "Сверните на съезд {exit} слева в направлении {destination}" }, "right": { "default": "Сверните на правый съезд", - "name": "Сверните на правый съезд на {way_name}", + "name": "Сверните на правый съезд на {way_name:accusative}", "destination": "Сверните на правый съезд в направлении {destination}", "exit": "Сверните на съезд {exit} справа", "exit_destination": "Сверните на съезд {exit} справа в направлении {destination}" }, "sharp left": { "default": "Поверните налево на съезд", - "name": "Поверните налево на съезд на {way_name}", + "name": "Поверните налево на съезд на {way_name:accusative}", "destination": "Поверните налево на съезд в направлении {destination}", "exit": "Поверните налево на съезд {exit}", "exit_destination": "Поверните налево на съезд {exit} в направлении {destination}" }, "sharp right": { "default": "Поверните направо на съезд", - "name": "Поверните направо на съезд на {way_name}", + "name": "Поверните направо на съезд на {way_name:accusative}", "destination": "Поверните направо на съезд в направлении {destination}", "exit": "Поверните направо на съезд {exit}", "exit_destination": "Поверните направо на съезд {exit} в направлении {destination}" }, "slight left": { "default": "Перестройтесь левее на съезд", - "name": "Перестройтесь левее на съезд на {way_name}", + "name": "Перестройтесь левее на съезд на {way_name:accusative}", "destination": "Перестройтесь левее на съезд в направлении {destination}", "exit": "Перестройтесь левее на {exit}", "exit_destination": "Перестройтесь левее на съезд {exit} в направлении {destination}" }, "slight right": { "default": "Перестройтесь правее на съезд", - "name": "Перестройтесь правее на съезд на {way_name}", + "name": "Перестройтесь правее на съезд на {way_name:accusative}", "destination": "Перестройтесь правее на съезд в направлении {destination}", "exit": "Перестройтесь правее на съезд {exit}", "exit_destination": "Перестройтесь правее на съезд {exit} в направлении {destination}" @@ -312,37 +312,37 @@ "on ramp": { "default": { "default": "Сверните на автомагистраль", - "name": "Сверните на въезд на {way_name}", + "name": "Сверните на въезд на {way_name:accusative}", "destination": "Сверните на въезд на автомагистраль в направлении {destination}" }, "left": { "default": "Сверните на левый въезд на автомагистраль", - "name": "Сверните на левый въезд на {way_name}", + "name": "Сверните на левый въезд на {way_name:accusative}", "destination": "Сверните на левый въезд на автомагистраль в направлении {destination}" }, "right": { "default": "Сверните на правый въезд на автомагистраль", - "name": "Сверните на правый въезд на {way_name}", + "name": "Сверните на правый въезд на {way_name:accusative}", "destination": "Сверните на правый въезд на автомагистраль в направлении {destination}" }, "sharp left": { "default": "Поверните на левый въезд на автомагистраль", - "name": "Поверните на левый въезд на {way_name}", + "name": "Поверните на левый въезд на {way_name:accusative}", "destination": "Поверните на левый въезд на автомагистраль в направлении {destination}" }, "sharp right": { "default": "Поверните на правый въезд на автомагистраль", - "name": "Поверните на правый въезд на {way_name}", + "name": "Поверните на правый въезд на {way_name:accusative}", "destination": "Поверните на правый въезд на автомагистраль в направлении {destination}" }, "slight left": { "default": "Перестройтесь левее на въезд на автомагистраль", - "name": "Перестройтесь левее на {way_name}", + "name": "Перестройтесь левее на {way_name:accusative}", "destination": "Перестройтесь левее на автомагистраль в направлении {destination}" }, "slight right": { "default": "Перестройтесь правее на въезд на автомагистраль", - "name": "Перестройтесь правее на {way_name}", + "name": "Перестройтесь правее на {way_name:accusative}", "destination": "Перестройтесь правее на автомагистраль в направлении {destination}" } }, @@ -350,23 +350,23 @@ "default": { "default": { "default": "Продолжите движение по круговой развязке", - "name": "На круговой развязке сверните на {way_name}", + "name": "На круговой развязке сверните на {way_name:accusative}", "destination": "На круговой развязке сверните в направлении {destination}" }, "name": { - "default": "Продолжите движение по {rotary_name} с круговым движением", - "name": "На {rotary_name} с круговым движением сверните на {way_name}", - "destination": "На {rotary_name} с круговым движением сверните в направлении {destination}" + "default": "Продолжите движение по {rotary_name:dative} с круговым движением", + "name": "На {rotary_name:prepositional} с круговым движением сверните на {way_name:accusative}", + "destination": "На {rotary_name:prepositional} с круговым движением сверните в направлении {destination}" }, "exit": { "default": "На круговой развязке сверните на {exit_number} съезд", - "name": "На круговой развязке сверните на {exit_number} съезд на {way_name}", + "name": "На круговой развязке сверните на {exit_number} съезд на {way_name:accusative}", "destination": "На круговой развязке сверните на {exit_number} съезд в направлении {destination}" }, "name_exit": { - "default": "На {rotary_name} с круговым движением сверните на {exit_number} съезд", - "name": "На {rotary_name} с круговым движением сверните на {exit_number} съезд на {way_name}", - "destination": "На {rotary_name} с круговым движением сверните на {exit_number} съезд в направлении {destination}" + "default": "На {rotary_name:prepositional} с круговым движением сверните на {exit_number} съезд", + "name": "На {rotary_name:prepositional} с круговым движением сверните на {exit_number} съезд на {way_name:accusative}", + "destination": "На {rotary_name:prepositional} с круговым движением сверните на {exit_number} съезд в направлении {destination}" } } }, @@ -374,12 +374,12 @@ "default": { "exit": { "default": "На круговой развязке сверните на {exit_number} съезд", - "name": "На круговой развязке сверните на {exit_number} съезд на {way_name}", + "name": "На круговой развязке сверните на {exit_number} съезд на {way_name:accusative}", "destination": "На круговой развязке сверните на {exit_number} съезд в направлении {destination}" }, "default": { "default": "Продолжите движение по круговой развязке", - "name": "На круговой развязке сверните на {way_name}", + "name": "На круговой развязке сверните на {way_name:accusative}", "destination": "На круговой развязке сверните в направлении {destination}" } } @@ -387,88 +387,88 @@ "roundabout turn": { "default": { "default": "На круговой развязке двигайтесь {modifier}", - "name": "На круговой развязке двигайтесь {modifier} на {way_name}", + "name": "На круговой развязке двигайтесь {modifier} на {way_name:accusative}", "destination": "На круговой развязке двигайтесь {modifier} в направлении {destination}" }, "left": { "default": "На круговой развязке сверните налево", - "name": "На круговой развязке сверните налево на {way_name}", + "name": "На круговой развязке сверните налево на {way_name:accusative}", "destination": "На круговой развязке сверните налево в направлении {destination}" }, "right": { "default": "На круговой развязке сверните направо", - "name": "На круговой развязке сверните направо на {way_name}", + "name": "На круговой развязке сверните направо на {way_name:accusative}", "destination": "На круговой развязке сверните направо в направлении {destination}" }, "straight": { "default": "На круговой развязке двигайтесь прямо", - "name": "На круговой развязке двигайтесь по {way_name}", + "name": "На круговой развязке двигайтесь по {way_name:dative}", "destination": "На круговой развязке двигайтесь в направлении {destination}" } }, "exit roundabout": { "default": { "default": "Двигайтесь {modifier}", - "name": "Двигайтесь {modifier} на {way_name}", + "name": "Двигайтесь {modifier} на {way_name:accusative}", "destination": "Двигайтесь {modifier} в направлении {destination}" }, "left": { "default": "Сверните налево", - "name": "Сверните налево на {way_name}", + "name": "Сверните налево на {way_name:accusative}", "destination": "Сверните налево в направлении {destination}" }, "right": { "default": "Сверните направо", - "name": "Сверните направо на {way_name}", + "name": "Сверните направо на {way_name:accusative}", "destination": "Сверните направо в направлении {destination}" }, "straight": { "default": "Двигайтесь прямо", - "name": "Двигайтесь по {way_name}", + "name": "Двигайтесь по {way_name:dative}", "destination": "Двигайтесь в направлении {destination}" } }, "exit rotary": { "default": { "default": "Двигайтесь {modifier}", - "name": "Двигайтесь {modifier} на {way_name}", + "name": "Двигайтесь {modifier} на {way_name:accusative}", "destination": "Двигайтесь {modifier} в направлении {destination}" }, "left": { "default": "Сверните налево", - "name": "Сверните налево на {way_name}", + "name": "Сверните налево на {way_name:accusative}", "destination": "Сверните налево в направлении {destination}" }, "right": { "default": "Сверните направо", - "name": "Сверните направо на {way_name}", + "name": "Сверните направо на {way_name:accusative}", "destination": "Сверните направо в направлении {destination}" }, "straight": { "default": "Двигайтесь прямо", - "name": "Двигайтесь по {way_name}", + "name": "Двигайтесь по {way_name:dative}", "destination": "Двигайтесь в направлении {destination}" } }, "turn": { "default": { "default": "Двигайтесь {modifier}", - "name": "Двигайтесь {modifier} на {way_name}", + "name": "Двигайтесь {modifier} на {way_name:accusative}", "destination": "Двигайтесь {modifier} в направлении {destination}" }, "left": { "default": "Поверните налево", - "name": "Поверните налево на {way_name}", + "name": "Поверните налево на {way_name:accusative}", "destination": "Поверните налево в направлении {destination}" }, "right": { "default": "Поверните направо", - "name": "Поверните направо на {way_name}", + "name": "Поверните направо на {way_name:accusative}", "destination": "Поверните направо в направлении {destination}" }, "straight": { "default": "Двигайтесь прямо", - "name": "Двигайтесь по {way_name}", + "name": "Двигайтесь по {way_name:dative}", "destination": "Двигайтесь в направлении {destination}" } }, @@ -481,4 +481,4 @@ } } } -} \ No newline at end of file +} diff --git a/test/grammar_test.js b/test/grammar_test.js new file mode 100644 index 000000000..e61421741 --- /dev/null +++ b/test/grammar_test.js @@ -0,0 +1,117 @@ +var tape = require('tape'); + +var instructions = require('../index.js'); +var languages = require('../languages.js'); + +const grammarTests = { + 'ru': [ + ['Бармалеева улица', 'accusative', 'Бармалееву улицу'], + ['Бармалеева улица', 'dative', 'Бармалеевой улице'], + ['Бармалеева улица', 'genitive', 'Бармалеевой улицы'], + ['Бармалеева улица', 'prepositional', 'Бармалеевой улице'], + ['Большая Монетная улица', 'accusative', 'Большую Монетную улицу'], + ['Большая Монетная улица', 'dative', 'Большой Монетной улице'], + ['Большая Монетная улица', 'genitive', 'Большой Монетной улицы'], + ['Большая Монетная улица', 'prepositional', 'Большой Монетной улице'], + ['Малая Зеленина улица', 'accusative', 'Малую Зеленину улицу'], + ['Малая Зеленина улица', 'dative', 'Малой Зелениной улице'], + ['Малая Зеленина улица', 'genitive', 'Малой Зелениной улицы'], + ['Малая Зеленина улица', 'prepositional', 'Малой Зелениной улице'], + ['22-23-я линии В.О.', 'accusative', '22-23-ю линии В.О.'], + ['22-23-я линии В.О.', 'dative', '22-23-й линиям В.О.'], + ['22-23-я линии В.О.', 'genitive', '22-23-й линий В.О.'], + ['22-23-я линии В.О.', 'prepositional', '22-23-й линиях В.О.'], + ['Австрийская площадь', 'accusative', 'Австрийскую площадь'], + ['Австрийская площадь', 'dative', 'Австрийской площади'], + ['Австрийская площадь', 'genitive', 'Австрийской площади'], + ['Австрийская площадь', 'prepositional', 'Австрийской площади'], + ['Лялина площадь', 'accusative', 'Лялину площадь'], + ['Лялина площадь', 'dative', 'Лялиной площади'], + ['Лялина площадь', 'genitive', 'Лялиной площади'], + ['Лялина площадь', 'prepositional', 'Лялиной площади'], + ['1-й Тверской-Ямской переулок', 'accusative', '1-й Тверской-Ямской переулок'], + ['1-й Тверской-Ямской переулок', 'dative', '1-му Тверскому-Ямскому переулку'], + ['1-й Тверской-Ямской переулок', 'genitive', '1-го Тверского-Ямского переулка'], + ['1-й Тверской-Ямской переулок', 'prepositional', '1-м Тверском-Ямском переулке'], + ['Большой Сампсониевский проспект', 'accusative', 'Большой Сампсониевский проспект'], + ['Большой Сампсониевский проспект', 'dative', 'Большому Сампсониевскому проспекту'], + ['Большой Сампсониевский проспект', 'genitive', 'Большого Сампсониевского проспекта'], + ['Большой Сампсониевский проспект', 'prepositional', 'Большом Сампсониевском проспекте'], + ['Нижний Лебяжий мост', 'accusative', 'Нижний Лебяжий мост'], + ['Нижний Лебяжий мост', 'dative', 'Нижнему Лебяжьему мосту'], + ['Нижний Лебяжий мост', 'genitive', 'Нижнего Лебяжьего моста'], + ['Нижний Лебяжий мост', 'prepositional', 'Нижнем Лебяжьем мосту'], + ['Старо-Калинкин мост', 'accusative', 'Старо-Калинкин мост'], + ['Старо-Калинкин мост', 'dative', 'Старо-Калинкину мосту'], + ['Старо-Калинкин мост', 'genitive', 'Старо-Калинкина моста'], + ['Старо-Калинкин мост', 'prepositional', 'Старо-Калинкином мосту'], + ['Тучков мост', 'accusative', 'Тучков мост'], + ['Тучков мост', 'dative', 'Тучкову мосту'], + ['Тучков мост', 'genitive', 'Тучкова моста'], + ['Тучков мост', 'prepositional', 'Тучковом мосту'], + ['Пыхов-Церковный проезд', 'accusative', 'Пыхов-Церковный проезд'], + ['Пыхов-Церковный проезд', 'dative', 'Пыхову-Церковному проезду'], + ['Пыхов-Церковный проезд', 'genitive', 'Пыхова-Церковного проезда'], + ['Пыхов-Церковный проезд', 'prepositional', 'Пыховом-Церковном проезде'], + ['Третье Транспортное кольцо', 'accusative', 'Третье Транспортное кольцо'], + ['Третье Транспортное кольцо', 'dative', 'Третьему Транспортному кольцу'], + ['Третье Транспортное кольцо', 'genitive', 'Третьего Транспортного кольца'], + ['Третье Транспортное кольцо', 'prepositional', 'Третьем Транспортном кольце'] + ] + // TODO add your language grammar tests to call grammarize() and check result +}; + +tape.test('verify grammar files structure', function(assert) { + // check that grammar files have proper structure as: + // { + // "v5": { + // "grammar name": [ + // ["regular expression", "replace string"], + // ... + // } + // } + + Object.keys(languages.grammars).forEach((l) => { + var grammar = languages.grammars[l]; + + assert.ok(grammar.v5, l + ' grammar has v5 version'); + + Object.keys(grammar.v5).forEach((g) => { + // check each grammar case + var r = grammar.v5[g]; + assert.ok(Array.isArray(r), l + ' grammar has rules array for ' + g); + + var i = 0; + r.forEach((e) => { + i++; // eslint-disable-line no-plusplus + assert.doesNotThrow(() => { + var b = Array.isArray(e) && e.length === 2; + if (b) { + // all regular expressions from grammar should not match empty string + r = new RegExp(e[0]); + b = ''.replace(r, e[1]) === ''; + } + + return b; + }, true, l + ' grammar has correct rule #' + i + ' for ' + g); + }); + }); + }); + + assert.end(); +}); + +tape.test('check grammar test data with grammarize()', function(assert) { + // check that grammar works properly with test data + + Object.keys(grammarTests).forEach((l) => { + var v5Instructions = instructions('v5'); + + grammarTests[l].forEach((t) => { + assert.equal(v5Instructions.grammarize(l, t[0], t[1]), t[2], + l + ' grammar passed for "' + t[2] + '" in ' + t[1]); + }); + }); + + assert.end(); +}); From 044836a4329bf9b73b79785c251fd381c9a0a501 Mon Sep 17 00:00:00 2001 From: Yury Lebedev Date: Wed, 4 Oct 2017 10:48:48 +0300 Subject: [PATCH 2/2] Extend grammar JSON with meta.regExpFlags option --- index.js | 6 +++--- languages/grammar/ru.json | 3 +++ languages/overrides/ru.js | 4 ++-- test/grammar_test.js | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index e886eb22b..c6ec7770c 100644 --- a/index.js +++ b/index.js @@ -136,9 +136,8 @@ module.exports = function(version, _options) { // if both are the same we assume that there used to be an empty name, with the ref being filled in for it // we only need to retain the ref then name = ''; - } else { - name = name.replace(' (' + step.ref + ')', ''); } + name = name.replace(' (' + step.ref + ')', ''); // In attempt to avoid using the highway name of a way, // check and see if the step has a class which should signal @@ -207,8 +206,9 @@ module.exports = function(version, _options) { if (rules) { // Pass original name to rules' regular expressions enclosed with spaces for simplier parsing var n = ' ' + name + ' '; + var flags = grammars[language].meta.regExpFlags || ''; rules.forEach(function(rule) { - var re = new RegExp(rule[0]); + var re = new RegExp(rule[0], flags); n = n.replace(re, rule[1]); }); diff --git a/languages/grammar/ru.json b/languages/grammar/ru.json index 354727404..91e69485b 100644 --- a/languages/grammar/ru.json +++ b/languages/grammar/ru.json @@ -1,4 +1,7 @@ { + "meta": { + "regExpFlags": "" + }, "v5": { "accusative": [ ["^ (\\S+)ая [Аа]ллея ", " $1ую аллею "], diff --git a/languages/overrides/ru.js b/languages/overrides/ru.js index e477b63b3..6a23897d3 100644 --- a/languages/overrides/ru.js +++ b/languages/overrides/ru.js @@ -29,7 +29,7 @@ function iterate(values) { }; module.exports = function(content) { - // Iterate all string values recursively - iterate(content); + // Iterate all content string values recursively + iterate(content.v5); return content; }; diff --git a/test/grammar_test.js b/test/grammar_test.js index e61421741..acf5bb029 100644 --- a/test/grammar_test.js +++ b/test/grammar_test.js @@ -88,7 +88,7 @@ tape.test('verify grammar files structure', function(assert) { var b = Array.isArray(e) && e.length === 2; if (b) { // all regular expressions from grammar should not match empty string - r = new RegExp(e[0]); + r = new RegExp(e[0], grammar.meta.regExpFlags); b = ''.replace(r, e[1]) === ''; }