Фуригана
Фуригана – японская помощь в чтении для Кандзи, которая первоначально приходила из китайца.
Есть много Реализации, подобные этому Для вставки Фуриганы в японский текст в Интернет с помощью форматирования Ruby, но в этом посте мы рассмотрим формат ANKI.
Формат Фуриганы Анки
Формат Фуриганы Анки более читабелен и короче, что облегчает редактирование, а также экономит дисковое пространство. Он используется на ANKI, но довольно просто преобразовать его в формат Ruby для Интернета.
Вот примеры для 辞 めたい и 辿 り 着 く :
Рубин формат:
Формат ANKI: 辞 [や] めたい
Рубин формат:
Формат ANKI: 辿 [たど] り 着 [つ] く
В настоящее время двумя преобладающими инструментами для вставки Furigana в ANKI являются Японская поддержка аддон и Мигаку Японский добавить.
Однако есть некоторые проблемы с этими инструментами, так как они терпят неудачу по одной или нескольким из этих проблем.
- Хирагана посреди слова
- Специальные японские иероглифы и диапазон знаков препинания
- Пользовательский отображение для конкретных слов с несколькими показаниями, а также именами и местами.
Мы рассмотрим эти проблемы в этом проекте.
Судачи для сегментации текста
Текстовая сегментация – это метод разбить предложение на более мелкие куски, называемые морфемы Анкет Это позволит нам искать индивидуальные показания каждой морфемы и при необходимости применить чтение Фуриганы.
Вместо Mecab для общего сегментации, этот проект будет использовать Судачи , который имеет несколько режимов сегментации текста, а также поиск Furigana.
Мы также будем использовать Ванакана Пакет для Python Для основных японских текстовых манипуляций.
pip install sudachipy sudachidict_small wanakana-python
Режимы сегментации Судачи
Есть три режима сегментации в Судачи – A, B и C.
Мы будем использовать режим C, чтобы получить чтение самых длинных записей в предложении.
from sudachipy import tokenizer from sudachipy import dictionary tokenizer_obj = dictionary.Dictionary(dict_type="small").create() def add_furigana(text): tokens = [m for m in tokenizer_obj.tokenize(text, tokenizer.Tokenizer.SplitMode.C)] parsed = '' # ... return parsed
Пропустить пунктуацию и специальные персонажи
Нам также необходимо определить определенных не японских персонажей (но считается японскими символами библиотекой Ванаканы:
from wanakana import to_hiragana, is_japanese, is_katakana, is_hiragana import string JAPANESE_PUNCTUATION = ' 〜!?。、():「」『』0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' def is_japanese_extended(text): return is_japanese(text) and text not in string.punctuation and text not in JAPANESE_PUNCTUATION
Затем мы можем добавить логику в наш метод вставки Фуригана. to_parse это только Истинный Если (морфем) токен содержит японские персонажи с кандзи. Другими словами, это ЛОЖЬ Если текст является чисто Хирагана или Катакана.
Специальные персонажи, такие как 〜 должны быть выделены, так как они привязаны к жетонам в Судачи.
SPECIAL_CHARACTERS = '〜' def add_furigana(text): tokens = [m for m in tokenizer_obj.tokenize(text, tokenizer.Tokenizer.SplitMode.C)] parsed = '' for index, token in enumerate(tokens): to_parse = is_japanese_extended(token.surface()) and not is_katakana(token.surface()) and not is_hiragana(token.surface()) if to_parse: if token.surface()[-1] in SPECIAL_CHARACTERS: parsed += add_furigana(token.surface()[:-1]) + token.surface()[-1] else: if index > 0: parsed += ' ' reading = to_hiragana(token.reading_form()) # ... else: parsed += token.surface() return parsed
Есть несколько методов в токеновом элементе. Мы используем метод Surface () для получения исходной строки, и Reading_form (), чтобы получить чтение Furigana Morpheme.
Важным примечанием является то, что метод Reading_form () возвращает чтение в Катакане, которое необходимо преобразовать в Хирагану и может быть достигнут с помощью Ванаканы to_hiragana () метод
Пользовательское отображение и анализ
Мы можем создать небольшой словарь, чтобы отобразить индивидуальные элементы, которые мы хотим выполнить собственное отображение. Это может быть все, от использования более распространенных показаний ( 私 Возвращает чтение わたく し вместо わたし ) к именам, как 優 那 [ゆう な] который неверно анализирует Судачи по 優 [ゆう] 那 [].
KANJI_READING_MAPPING = { '私': '私[わたし]', '貴女': '貴女[あなた]', '何が': '何[なに]が', '何を': '何[なに]を', '我国': '我国[わがくに]', '行き来': '行[い]き 来[き]', '外宇宙': '外宇宙[がいうちゅう]', '異星人': '異星人[いせいじん]', '優那': '優那[ゆうな]', '菜々美': '菜々美[ななみ]' }
Мы также можем использовать Json Файл для более легкого управления данными, но здесь мы будем хранить его в файле Python.
Чтобы отобразить их вручную, проверяем, если их поверхность Форма является одним из ключей нашего Kanji_reading_mapping и добавить соответствующее значение к нашему проанализированному результату.
Иногда ключевое слово может охватывать 2 токены, например, 異星人 разбиваются на токены 異星 [いせい] и 人 [にん] и 優 那 в токены 優 [ゆう] и 那 []. Вот почему мы также проверяем, есть ли комбинированный термин текущего токена и следующий токен token.surface () + tokens [index + 1] .surface ()
Также являются ключом в нашем картирующем словаре.
token_indexes_to_skip = [] for index, token in enumerate(tokens): if index in token_indexes_to_skip: continue # ... if index < len(tokens)-1 and token.surface() + tokens[index+1].surface() in KANJI_READING_MAPPING: parsed += KANJI_READING_MAPPING[tokens[index].surface() + tokens[index+1].surface()] token_indexes_to_skip.append(index+1) elif token.surface() in KANJI_READING_MAPPING: parsed += KANJI_READING_MAPPING[token.surface()] else: # ...
Добавляем список token_indexes_to_skip хранить Индекс+1 токены, которые уже используются для пользовательского картирования. Таким образом, мы можем пропустить его в следующей итерации.
Хирагана посреди слова
Мы устанавливаем два указателя , Surface_index Пройти через каждого персонажа Поверхностная форма и Reading_index Для * Чтение Анкет
Например, поверхностная форма 教える имеет форму считывания オシエル и впоследствии おしえる после преобразования Хирагана.
Если персонажем является Хирагана или Катакана, мы напрямую добавляем его в проанализированную строку и увеличиваем оба указателя.
Если это кандзи, мы находим чтение для кандзи, используя временную переменную Reading_index_tail и увеличьте это, пока мы не достигнем конца строки считывания или до тех пор, пока следующий символ чтения не соответствует следующему символу Hiragana в поверхностной строке.
Сопоставлением え в おし え る до 教 え る Мы можем проанализировать чтение 教 до おし. Reading_index Значение 0 и Reading_index_tail Значение 1
Мы также добавим дополнительное условие, чтобы переместить указатель считывания, если последующий символ Хирагана совпадает с текущим.
Например, 可愛い анализируется как 可愛 [かわい] い вместо 可愛 [かわ] いい. Проверив повторение финального い, мы могли бы заставить первого い быть включенным в чтение.
surface_index = 0 reading_index = 0 while len(token.surface()) > surface_index: if is_hiragana(token.surface()[surface_index]) or is_katakana(token.surface()[surface_index]): parsed += token.surface()[surface_index] reading_index += 1 surface_index += 1 else: next_index = -1 for token_index in range(surface_index, len(token.surface())): if is_hiragana(token.surface()[token_index]) or is_katakana(token.surface()[token_index]): next_index = token_index break if next_index < 0: parsed += to_anki_format( index=surface_index, kanji=token.surface()[surface_index:], reading=reading[reading_index:]) break else: reading_index_tail = reading_index while reading[reading_index_tail] != token.surface()[next_index] or (reading_index_tail < len(reading)-1 and reading[reading_index_tail] == reading[reading_index_tail+1]): reading_index_tail += 1 parsed += to_anki_format( index = surface_index, kanji = token.surface()[surface_index:next_index], reading = reading[reading_index:reading_index_tail]) reading_index = reading_index_tail reading_length = next_index - surface_index if reading_length > 0: surface_index += reading_length else: break
Формат Анки
Формат ANKI довольно прост. Вначале мы добавляем дополнительное пространство, если проанализированный кандзи находится в середине предложения.
def to_anki_format(index, kanji, reading): return '{}{}[{}]'.format(' ' if index > 0 else '', kanji, reading)
Собрать это вместе
Было намного больше шагов и условной проверки, но в конце концов наш анализатор мог бы справиться с гораздо большим количеством случаев и быть очень настраиваемым.
Примечание. Чтобы запустить этот пример, вам может потребоваться запустить PIP установить SUDACHIDICT_SMALL
в оболочке реплики, чтобы установить словарь Судачи.
Дополнительный
Анки
До сих пор мы рассмотрели, как добавить Furigana к японскому тексту в формате ANKI, но мы не рассмотрели, как сделать аддон ANKI (плагин). Это может быть простой управление горячими классами, чтобы преобразовать поле в японское с Фуриганой, или это может быть аддон для пакетной вставки Furigana в существующую колоду ANKI. Мы оставим это на другой пост.
Веб –
Предположим, что у вас есть реляционная база данных японского текста, и вы добавили дополнительный столбец для хранения всего текста с вставленной Furigana. Вам нужно будет получить данные и показать их в Интернете в формате Ruby.
Вам нужно будет написать простую функцию форматирования текста. Нет необходимости в библиотеках сегментации здесь. Вы можете взглянуть на мой Реагировать реализацию JS Если вам нужна помощь.
Оригинал: “https://dev.to/mathewthe2/python-text-parsing-project-furigana-inserter-for-anki-2jo”