add: Финальные сокращения ('т.д.', 'т.п.', 'др.' и 'пр.')
This commit is contained in:
@@ -625,7 +625,7 @@ def get_encode_map():
|
||||
# === КОНСТАНТЫ ДЛЯ ЕДИНИЦ ИЗМЕРЕНИЯ ===
|
||||
# ТОЛЬКО АТОМАРНЫЕ единицы измерения: 'г', 'м', 'с', 'км', 'кв', 'куб', 'ч' и так далее.
|
||||
# Никаких сложных и составных, типа: 'кв.м.', 'км/ч' или "до н.э." ...
|
||||
# Пост-позиционные (10 км).
|
||||
# Пост-позиционные (можно ставить точку после, но не обязательно) (км, г., с.)
|
||||
DEFAULT_POST_UNITS = [
|
||||
# Русские
|
||||
# --- Время и эпохи ---
|
||||
@@ -637,11 +637,11 @@ DEFAULT_POST_UNITS = [
|
||||
# --- Финансы и количество ---
|
||||
'руб', 'коп', 'тыс', 'млн', 'млрд', 'трлн', 'трлрд', 'шт', 'об', 'ящ', 'уп', 'кор', 'пар', 'комп',
|
||||
# --- Издательское дело ---
|
||||
'пп', 'стр', 'рис', 'табл', 'гл', 'п', 'пт', 'гл', 'том', 'т.', 'кн', 'кн.', 'илл', 'ред', 'изд', 'пер',
|
||||
'пп', 'стр', 'рис', 'гр', 'табл', 'гл', 'п', 'пт', 'гл', 'том', 'т.', 'кн', 'илл', 'ред', 'изд', 'пер',
|
||||
# --- Физические и технические ---
|
||||
'дБ', 'Вт', 'кВт', 'МВт', 'ГВт', 'А', 'В', 'Ом', 'Па', 'кПа', 'МПа', 'Бар', 'кБар', 'Гц', 'кГц', 'МГц', 'ГГц',
|
||||
'рад', 'К', '°C', '°F', '%', 'мкм', 'нм', 'А°', 'эВ', 'Дж', 'кДж', 'МДж', 'пкФ', 'нФ', 'мкФ', 'мФ', 'Ф',
|
||||
'Гн', 'мГн', 'мкГн', 'Тл', 'Гс', 'эрг', 'бит', 'байт', 'Кб', 'Мб', 'Гб', 'Тб', 'Пб', 'Эб', 'кал', 'ккал',
|
||||
'Гн', 'мГн', 'мкГн', 'Тл', 'Гс', 'эрг', 'бод', 'бит', 'байт', 'Кб', 'Мб', 'Гб', 'Тб', 'Пб', 'Эб', 'кал', 'ккал',
|
||||
# Английские
|
||||
# --- Издательское дело ---
|
||||
'pp', 'p', 'para', 'sect', 'fig', 'vol', 'ed', 'rev', 'dpi',
|
||||
@@ -649,8 +649,19 @@ DEFAULT_POST_UNITS = [
|
||||
'in', 'ft', 'yd', 'mi', 'oz', 'lb', 'st', 'pt', 'qt', 'gal', 'mph', 'rpm', 'hp', 'psi', 'cal',
|
||||
]
|
||||
# Пред-позиционные (№ 5, $ 10)
|
||||
DEFAULT_PRE_UNITS = ['№', '$', '€', '£', '₽', '#']
|
||||
DEFAULT_PRE_UNITS = ['№', '$', '€', '£', '₽', '#', '§']
|
||||
|
||||
# Операторы, которые могут стоять между единицами измерения (км/ч)
|
||||
# Сложение и вычитание здесь намеренно отсутствуют.
|
||||
UNIT_MATH_OPERATORS = ['/', '*', '×', CHAR_MIDDOT, '÷']
|
||||
UNIT_MATH_OPERATORS = ['/', '*', '×', CHAR_MIDDOT, '÷']
|
||||
|
||||
# === КОНСТАНТЫ ДЛЯ ФИНАЛЬНЫХ СОКРАЩЕНИЙ ===
|
||||
# Эти сокращения (обычно в конце фразы) будут "склеены" тонкой шпацией, а перед ними будет поставлен неразрывный пробел.
|
||||
# Важно, чтобы многосложные сокращения (типа "и т. д.") были в списке с разделителем пробелом (иначе мы не сможем их найти).
|
||||
ABBR_COMMON_FINAL = [
|
||||
'т. д.', 'т. п.', 'др.', 'пр.',
|
||||
]
|
||||
|
||||
ABBR_COMMON_PREPOSITION = [
|
||||
'т.е.', 'т.к.', 'т.о.', 'и.о.', 'ио', 'вр.и.о.', 'врио'
|
||||
]
|
@@ -3,10 +3,14 @@
|
||||
|
||||
import regex
|
||||
import logging
|
||||
from etpgrf.config import (LANG_RU, LANG_EN, CHAR_NBSP, CHAR_THIN_SP, CHAR_NDASH, CHAR_MDASH, CHAR_HELLIP, CHAR_UNIT_SEPARATOR,
|
||||
DEFAULT_POST_UNITS, DEFAULT_PRE_UNITS, UNIT_MATH_OPERATORS)
|
||||
from etpgrf.config import (LANG_RU, LANG_EN, CHAR_NBSP, CHAR_THIN_SP, CHAR_NDASH, CHAR_MDASH, CHAR_HELLIP,
|
||||
CHAR_UNIT_SEPARATOR, DEFAULT_POST_UNITS, DEFAULT_PRE_UNITS, UNIT_MATH_OPERATORS,
|
||||
ABBR_COMMON_FINAL)
|
||||
|
||||
from etpgrf.comutil import parse_and_validate_langs
|
||||
|
||||
|
||||
|
||||
# --
|
||||
|
||||
# --- Настройки логирования ---
|
||||
@@ -60,11 +64,13 @@ class LayoutProcessor:
|
||||
self._initial_to_initial_ns_pattern = regex.compile(r'(\p{Lu}\.)(?=\p{Lu}\.)')
|
||||
self._initial_to_surname_ns_pattern = regex.compile(r'(\p{Lu}\.)(?=\p{Lu}\p{L}{1,})')
|
||||
|
||||
# Паттерн, описывающий "число" - арабское (включая дроби) ИЛИ римское.
|
||||
# Вся логика обработки финальных сокращений перенесена в метод process для надежной итеративной обработки
|
||||
|
||||
# 6. Паттерн, описывающий "число" - арабское (включая десятичные дроби через запятую или точку) ИЛИ римское.
|
||||
# Для римских цифр используется \b, чтобы не спутать 'I' с частью слова.
|
||||
self._NUMBER_PATTERN = r'(?:\d[\d.,]*|\b[IVXLCDM]+\b)'
|
||||
|
||||
# 5. Паттерны для единиц измерения (простые и составные).
|
||||
# 7. Паттерны для единиц измерения (простые и составные).
|
||||
self._post_units_pattern = None
|
||||
self._pre_units_pattern = None
|
||||
self._complex_unit_pattern = None
|
||||
@@ -133,7 +139,26 @@ class LayoutProcessor:
|
||||
# 3. Обработка пробела перед отрицательными числами/минусом.
|
||||
processed_text = self._negative_number_pattern.sub(f'{CHAR_NBSP}-\\1', processed_text)
|
||||
|
||||
# 4. Обработка инициалов (если включено).
|
||||
# 4. Обработка финальных сокращений (т.д., т.п. и т.д.)
|
||||
# Шаг 1: "Склеиваем" многосоставные сокращения временным разделителем.
|
||||
temp_processed_text = processed_text
|
||||
for abbr in ABBR_COMMON_FINAL:
|
||||
if ' ' in abbr: # Обрабатываем только многосоставные
|
||||
pattern = regex.escape(abbr).replace(r'\ ', r'\s*')
|
||||
replacement = abbr.replace(' ', CHAR_UNIT_SEPARATOR)
|
||||
temp_processed_text = regex.sub(pattern, replacement, temp_processed_text, flags=regex.IGNORECASE)
|
||||
|
||||
# Шаг 2: Ставим неразрывный пробел перед всеми финальными сокращениями (уже "склеенными").
|
||||
# Создаем паттерн из всех вариантов - и простых, и "склеенных".
|
||||
glued_abbrs = [a.replace(' ', CHAR_UNIT_SEPARATOR) for a in ABBR_COMMON_FINAL]
|
||||
all_final_abbrs_pattern = '|'.join(map(regex.escape, sorted(glued_abbrs, key=len, reverse=True)))
|
||||
nbsp_pattern = regex.compile(r'(\s)(' + all_final_abbrs_pattern + r')(?=[.,!?]|\s|$)', flags=regex.IGNORECASE)
|
||||
processed_text = nbsp_pattern.sub(fr'{CHAR_NBSP}\2', temp_processed_text)
|
||||
|
||||
# Шаг 3: Заменяем временный разделитель на правильную тонкую шпацию.
|
||||
processed_text = processed_text.replace(CHAR_UNIT_SEPARATOR, CHAR_THIN_SP)
|
||||
|
||||
# 5. Обработка инициалов и акронимов (если включено).
|
||||
if self.process_initials_and_acronyms:
|
||||
# Сначала вставляем тонкие пробелы там, где пробелов не было.
|
||||
processed_text = self._initial_to_initial_ns_pattern.sub(f'\\1{CHAR_THIN_SP}', processed_text)
|
||||
@@ -144,7 +169,7 @@ class LayoutProcessor:
|
||||
processed_text = self._initial_to_surname_ws_pattern.sub(f'\\1{CHAR_NBSP}', processed_text)
|
||||
processed_text = self._surname_to_initial_ws_pattern.sub(f'\\1{CHAR_NBSP}', processed_text)
|
||||
|
||||
# 5. Обработка единиц измерения (если включено).
|
||||
# 6. Обработка единиц измерения (если включено).
|
||||
if self.process_units:
|
||||
if self._complex_unit_pattern:
|
||||
# Шаг 1: "Склеиваем" все составные единицы с помощью временного разделителя.
|
||||
|
@@ -104,6 +104,7 @@ LAYOUT_TEST_CASES = [
|
||||
('ru+en', "Доплата за багаж $ 45.50", f"Доплата за багаж ${CHAR_NBSP}45.50"),
|
||||
('ru+en', "Инвестиции составили $2.5 млн.", f"Инвестиции составили $2.5{CHAR_NBSP}млн."),
|
||||
('ru+en', "Инвестиции составили $ 2.5 млн.", f"Инвестиции составили ${CHAR_NBSP}2.5{CHAR_NBSP}млн."),
|
||||
('ru', "За окном -5 °C", f"За окном{CHAR_NBSP}-5{CHAR_NBSP}°C"),
|
||||
# Сложные единицы (склеиваются тонкой шпацией, привязываются к числу неразрывным пробелом)
|
||||
# ('ru', "Дом 120 кв.м. / Участок 6 сот.", f"Дом 120{CHAR_NBSP}кв.м. / Участок 6{CHAR_NBSP}сот."),
|
||||
# ('ru', "Гробик кладут в ямку 2 кв. м.", f"Гробик кладут в ямку 2 кв. м."),
|
||||
@@ -126,6 +127,14 @@ LAYOUT_TEST_CASES = [
|
||||
('ru', "За окном 15 °C", f"За окном 15{CHAR_NBSP}°C"),
|
||||
('ru', "HiFi 20 Гц - 20 кГц", f"HiFi 20{CHAR_NBSP}Гц - 20{CHAR_NBSP}кГц"),
|
||||
|
||||
# Финальные сокращения
|
||||
('ru', "1 и т.д.", f"1 и{CHAR_NBSP}т.{CHAR_THIN_SP}д."),
|
||||
('ru', "2 и т. д.", f"2 и{CHAR_NBSP}т.{CHAR_THIN_SP}д."),
|
||||
('ru', "3 и т.д., и др.", f"3 и{CHAR_NBSP}т.{CHAR_THIN_SP}д., и{CHAR_NBSP}др."), # Слитное написание
|
||||
('ru', "4 и т.п., и пр.", f"4 и{CHAR_NBSP}т.{CHAR_THIN_SP}п., и{CHAR_NBSP}пр."), # Слитное написание
|
||||
('ru', "5 и т. п., и т.п., и пр.", f"5 и{CHAR_NBSP}т.{CHAR_THIN_SP}п., и{CHAR_NBSP}т.{CHAR_THIN_SP}п., и{CHAR_NBSP}пр."), # Слитное и раздельное написание
|
||||
|
||||
|
||||
# Сложные единицы (склеиваются тонкой шпацией, привязываются к числу неразрывным пробелом)
|
||||
('ru', "Дом 120 кв.м. / Участок 6 сот.", f"Дом 120{CHAR_NBSP}кв.{CHAR_THIN_SP}м. / Участок 6{CHAR_NBSP}сот."),
|
||||
# ('ru', "Гробик кладут в ямку 2 кв. м.", f"Гробик кладут в ямку 2 кв. м."),
|
||||
|
Reference in New Issue
Block a user