diff --git a/core/utils/layout_converter.py b/core/utils/layout_converter.py new file mode 100644 index 0000000..bc9992e --- /dev/null +++ b/core/utils/layout_converter.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +""" +Конвертер раскладки клавиатуры: определяет, в какой раскладке (русской или английской) +набран текст, и при необходимости переключает её. +Используется для исправления сообщений, набранных по ошибке не в той раскладке. +""" + +import logging + +logger = logging.getLogger(__name__) + + +def convert_layout(text: str) -> str: + """ + Определяет, в какой раскладке набран текст, и переключает, если нужно. + Команды (начинающиеся с ! или /) и ссылки (http://) не трогает. + + Алгоритм: + 1. Если текст начинается с http://, https://, ! или / – возвращается без изменений. + 2. Составляем таблицы перевода: английские символы -> русские и наоборот. + 3. Если в тексте есть и русские, и английские символы – считаем, что всё правильно (не переключаем). + 4. Считаем количество гласных букв в английской и русской раскладках для исходного текста + и для его переведённых вариантов. + 5. Выбираем вариант с наибольшим количеством гласных (вероятная правильная раскладка). + 6. Если гласных поровну или нет ни одной, возвращаем исходный текст. + """ + if not text: + return text + + # Не трогаем команды и ссылки + if text.startswith('http') or text.startswith(('!', '/')): + return text + + # Таблицы соответствия символов (раскладка QWERTY / ЙЦУКЕН) + en_chars = "qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?~" + ru_chars = "йцукенгшщзхъфывапролджэячсмитьбю.ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,Ё" + to_ru = str.maketrans(en_chars, ru_chars) # таблица для перевода английской раскладки в русскую + to_en = str.maketrans(ru_chars, en_chars) # таблица для перевода русской раскладки в английскую + + # Проверяем, есть ли символы обеих раскладок в тексте + has_russian = any('а' <= c <= 'я' or 'А' <= c <= 'Я' for c in text) + has_english = any('a' <= c <= 'z' or 'A' <= c <= 'Z' for c in text) + if has_russian and has_english: + # Смесь – вероятно, уже правильно + return text + + # Гласные буквы для подсчёта (в английской и русской раскладках) + eng_vowels = "aeiouyAEIOUY" + ru_vowels = "аеёиоуыэюяАЕЁИОУЫЭЮЯ" + + orig_en_vowels = sum(1 for c in text if c in eng_vowels) + orig_ru_vowels = sum(1 for c in text if c in ru_vowels) + + # Переводим текст в другую раскладку + translated_en = text.translate(to_en) # русская -> английская + translated_ru = text.translate(to_ru) # английская -> русская + + trans_en_vowels = sum(1 for c in translated_en if c in eng_vowels) + trans_ru_vowels = sum(1 for c in translated_ru if c in ru_vowels) + + # Если в исходном тексте нет русских символов, но при переводе в русскую раскладку + # появляется больше гласных, значит, текст был набран в английской раскладке. + if not has_russian and trans_ru_vowels > orig_en_vowels: + return translated_ru + + # Если в исходном тексте нет английских символов, но при переводе в английскую раскладку + # появляется больше гласных, значит, текст был набран в русской раскладке. + if has_russian and trans_en_vowels > orig_ru_vowels: + return translated_en + + return text \ No newline at end of file