Expand ordinal suffix handling

This commit is contained in:
2026-02-05 17:15:09 +03:00
parent 875ff7d2c4
commit bb3133a1c0

View File

@@ -94,6 +94,35 @@ MONTHS_GENITIVE = [
# Леммы единиц времени (для корректного падежа числительных) # Леммы единиц времени (для корректного падежа числительных)
TIME_UNIT_LEMMAS = {"час", "минута", "секунда"} TIME_UNIT_LEMMAS = {"час", "минута", "секунда"}
# Суффиксы порядковых числительных для формата "1968-й", "1968-го", "1968-му", "1968-м" и т.п.
_ORDINAL_SUFFIX_MAP = {
# Masculine
"ого": ("genitive", "m"),
"его": ("genitive", "m"),
"ому": ("dative", "m"),
"ему": ("dative", "m"),
"ым": ("instrumental", "m"),
"им": ("instrumental", "m"),
"ом": ("prepositional", "m"),
"ем": ("prepositional", "m"),
"ый": ("nominative", "m"),
"ий": ("nominative", "m"),
"й": ("nominative", "m"),
"го": ("genitive", "m"),
"му": ("dative", "m"),
"м": ("prepositional", "m"),
# Feminine
"ая": ("nominative", "f"),
"яя": ("nominative", "f"),
"ую": ("accusative", "f"),
"юю": ("accusative", "f"),
"ой": ("genitive", "f"),
"ей": ("genitive", "f"),
# Neuter
"ое": ("nominative", "n"),
"ее": ("nominative", "n"),
}
def get_case_from_preposition(prep_token): def get_case_from_preposition(prep_token):
"""Определяет падеж по предлогу.""" """Определяет падеж по предлогу."""
@@ -128,16 +157,40 @@ def numbers_to_words(text: str) -> str:
if not text: if not text:
return "" return ""
# 0. Обработка короткой записи годов с суффиксом: "1968-м", "в 1968-м году" preps_list = "|".join(map(re.escape, PREPOSITION_CASES.keys()))
# 0. Обработка короткой записи годов с суффиксом: "1968-й", "1968-го", "1968-му", "1968-м", "в 1968-м году"
def replace_year_suffix_match(match): def replace_year_suffix_match(match):
prep = match.group(1) # Предлог (в, во, о...) prep = match.group(1) # Предлог (в, во, о...)
year_str = match.group(2) # Само число year_str = match.group(2) # Само число
year_word = match.group(3) # Слово "год", "году" и т.д. (опционально) suffix = match.group(3) # Суффикс порядкового числительного
year_word = match.group(4) # Слово "год", "году" и т.д. (опционально)
# Суффикс "-м/-ом" обычно соответствует предложному падежу case = None
words = convert_number( gender = None
year_str, context_type="ordinal", case="prepositional", gender="m"
) if prep:
morph_case = get_case_from_preposition(prep.strip().lower())
if morph_case:
case = PYMORPHY_TO_NUM2WORDS.get(morph_case)
suffix_key = suffix.lower()
suffix_case, suffix_gender = _ORDINAL_SUFFIX_MAP.get(suffix_key, (None, None))
if not case and suffix_case:
case = suffix_case
if year_word:
gender = "m"
elif suffix_gender:
gender = suffix_gender
if not case:
case = "nominative"
if not gender:
gender = "m"
words = convert_number(year_str, context_type="ordinal", case=case, gender=gender)
prefix = f"{prep} " if prep else "" prefix = f"{prep} " if prep else ""
if year_word: if year_word:
@@ -145,7 +198,9 @@ def numbers_to_words(text: str) -> str:
return f"{prefix}{words}" return f"{prefix}{words}"
text = re.sub( text = re.sub(
r"(?i)\b((?:в|во|о|об|обо|при)\s+)?(\d{3,4})[-‑–—](?:м|ом)\b(?:\s+(год[а-я]*))?", rf"(?i)\b((?:{preps_list})\s+)?(\d{{3,4}})[-‑–—]"
r"(ого|его|ому|ему|ым|им|ом|ем|ый|ий|ая|яя|ую|юю|ой|ей|ое|ее|й|го|му|м)\b"
r"(?:\s+(год[а-я]*))?",
replace_year_suffix_match, replace_year_suffix_match,
text, text,
) )
@@ -270,7 +325,6 @@ def numbers_to_words(text: str) -> str:
# Регулярка теперь захватывает (опционально) следующее слово для определения рода # Регулярка теперь захватывает (опционально) следующее слово для определения рода
preps_list = "|".join(map(re.escape, PREPOSITION_CASES.keys()))
text = re.sub( text = re.sub(
rf"(?i)(?<!\w)((?:{preps_list})\s+)?([+-]?\d+(?:[.,]\d+)?)(?=(\s+[а-яА-ЯёЁ]+))?\b", rf"(?i)(?<!\w)((?:{preps_list})\s+)?([+-]?\d+(?:[.,]\d+)?)(?=(\s+[а-яА-ЯёЁ]+))?\b",
replace_cardinal_match, replace_cardinal_match,