Anki: Flag Cards without Kanji

I have recently decided, that I wanted to, as much as it is possible, have the one question per example sentence. I delete all the duplicate reading clozes - and stop making them, once the first one reaches the interval of one year. And I check for the meaning duplicate clozes, after every episode, that I add in Anki.

Even so, I still have many cards, where there are multiple clozes on the cards, and I have some, that have ten or even more than that. There is one sentence from Code Geass, that I still have 15 clozes on it. There are a lot of other series with sentences in 10+ cloze cards: No Game No Life, Magic Kaito 1412, Re:Zero, 盾の勇者 (Shield Hero), 本好きの下克上 (Ascendance of a Bookworm), Sword Art Online and some more.

Because of the multiple possible meanings, I do have some problems with the meaning cards, that are written in kana only in the sentences. There are also not that many, less than 300 in more than 5000 cloze meaning cards, that I currently have.

Below is the code, that I have used for this. The JAPANESE_NOTES constant is my Japanese note id - or more specifically, how to search for the cards with this note id. MEANING_CLOZE_FIELD is the field, where I have my meaning clozes. I have my reading clozes in a different field.

import re
from aqt import mw
from aqt.qt import QAction
from anki.hooks import addHook

JAPANESE_NOTES = "mid:1582842175358"

def add_deck_button(browser):
    deckButton = QAction("Flag meaning cards without kanji", browser)

def get_cloze_answer(sentence, cloze_number):
    cloze_answers = re.findall(r"{{c" + str(cloze_number) + "::(.+?)::.+?}}", sentence)
    return [answer for answer in cloze_answers]

def flag_non_kanji():
    cards_ids = [card_id for card_id in mw.col.find_cards(JAPANESE_NOTES)]
    for card_id in cards_ids:
        card = mw.col.getCard(card_id)
        meaning_field = card.note()[MEANING_CLOZE_FIELD]
        card_cloze_number = card.ord + 1
        answers = get_cloze_answer(meaning_field, card_cloze_number)
        if not len(answers):
        for answer in answers:
            kanji_characters = [char for char in answer if char >= "一"]
            if len(kanji_characters):
            card.flags = 3

addHook("browser.setupMenus", add_deck_button)

the addHook line and the add_deck_button function are a way to add the button on the Editor window. These can be accessed by going to the Edit menu and finding it there.

The get_cloze_answer function is also something I used in my other code. It is a way to get the answer from the cloze card, if the field text and the cloze number are known.

The flag_non_kanji function is the one, where most of the work happens. First we get all the cards with this note type. For each card we check, if the cloze answer exists in the meaning field. If it does, then we check for kanji characters, and if they do not exist, flag the card.

I like the trick, that I have found. When sorting the Japanese characters, the kana is before kanji, and kanji starts with the kanji for one (一). So if I check, if the character is smaller than 一, then I know for sure, that it is not a kanji. There is a chance, that there are characters beside kanji, that are higher - but for my case, this is exact enough. Since I am not using emoji or other non-Latin non-Japanese characters in my sentences.

In order for me to make it work, I also needed to import this in the file. This is mostly, since I keep all my Anki code in one add-on folder. Simply add the from . import file_name_without_py.