substring check

This commit is contained in:
dazedanon 2026-03-04 23:55:45 -06:00
parent b6df17d30b
commit 973b3322a9
2 changed files with 27 additions and 4 deletions

View file

@ -2536,7 +2536,7 @@ def searchCodes(page, pbar, jobList, filename):
# Patterns: (regex, multiline) - multiline=True means it spans 355 + following 655 codes # Patterns: (regex, multiline) - multiline=True means it spans 355 + following 655 codes
patterns = { patterns = {
# "テキスト-": (r"テキスト-(.+)", False), "テキスト-": (r"テキスト-(.+)", False),
# "=": (r'=\s?(.*)",', False), # "=": (r'=\s?(.*)",', False),
# "var text": (r"var\stext\d+\s=\s\"(.+)\"", False), # "var text": (r"var\stext\d+\s=\s\"(.+)\"", False),
# "logtxt = ": (r"logtxt\s=\s'(.+)'", False), # "logtxt = ": (r"logtxt\s=\s'(.+)'", False),
@ -2554,7 +2554,7 @@ def searchCodes(page, pbar, jobList, filename):
# "this.Menu_SexTxtSet(": (r'"(.+)"', True), # "this.Menu_SexTxtSet(": (r'"(.+)"', True),
# "Rn_RsltTxtArr": (r'"(.+)"', True), # "Rn_RsltTxtArr": (r'"(.+)"', True),
# "_章切り替えStart": (r'_章切り替えStart\(\s*\\?"\s?,?.+?\\?"\s?,?\s?\\?"(.+?)\\?"', False), # "_章切り替えStart": (r'_章切り替えStart\(\s*\\?"\s?,?.+?\\?"\s?,?\s?\\?"(.+?)\\?"', False),
"SkillLogAdd": (r'SkillLogAdd\((?:.+?\+\s*)?\\?"(?:\\\\+[A-Za-z]\[\d+\])?(.+?)\\?"', False), # "SkillLogAdd": (r'SkillLogAdd\((?:.+?\+\s*)?\\?"(?:\\\\+[A-Za-z]\[\d+\])?(.+?)\\?"', False),
# "MobNameSet": (r'MobNameSet\(\\?"(.+?)\\?"\)', False), # "MobNameSet": (r'MobNameSet\(\\?"(.+?)\\?"\)', False),
# "AddAddress": (r'AddAddress\(\d+,\s*\\?"(.+?)\\?"', False), # "AddAddress": (r'AddAddress\(\d+,\s*\\?"(.+?)\\?"', False),

View file

@ -574,6 +574,29 @@ def parseVocabWithCategories(vocabText):
return pairs return pairs
def _japanese_term_in_text(term, text):
"""
Check if a Japanese term appears in text as a standalone word, not as a
substring of a longer run of the same script (katakana/hiragana/kanji).
E.g. 'キス' will NOT match inside 'テキスト' because both neighbours are katakana.
Falls back to plain substring check for non-Japanese or mixed terms.
"""
if term not in text:
return False
KATAKANA = r'ァ-ヴーヲ-゚'
HIRAGANA = r'ぁ-ゔ'
KANJI = r'一-龠'
if re.search(rf'[{KATAKANA}]', term) and not re.search(rf'[{HIRAGANA}{KANJI}]', term):
pattern = rf'(?<![{KATAKANA}]){re.escape(term)}(?![{KATAKANA}])'
elif re.search(rf'[{HIRAGANA}]', term) and not re.search(rf'[{KATAKANA}{KANJI}]', term):
pattern = rf'(?<![{HIRAGANA}]){re.escape(term)}(?![{HIRAGANA}])'
elif re.search(rf'[{KANJI}]', term) and not re.search(rf'[{KATAKANA}{HIRAGANA}]', term):
pattern = rf'(?<![{KANJI}]){re.escape(term)}(?![{KANJI}])'
else:
return True # mixed-script term: plain substring match already confirmed above
return bool(re.search(pattern, text))
def buildMatchedVocabText(vocabPairs, subbedText, history=None): def buildMatchedVocabText(vocabPairs, subbedText, history=None):
"""Build formatted vocabulary text with matched terms organized by category.""" """Build formatted vocabulary text with matched terms organized by category."""
matchedCategories = {} matchedCategories = {}
@ -593,11 +616,11 @@ def buildMatchedVocabText(vocabPairs, subbedText, history=None):
if isinstance(term, tuple): if isinstance(term, tuple):
# Check both Japanese and English terms # Check both Japanese and English terms
japanese_term, english_term = term japanese_term, english_term = term
if japanese_term in textToSearch or english_term in textToSearch: if _japanese_term_in_text(japanese_term, textToSearch) or english_term in textToSearch:
term_found = True term_found = True
else: else:
# Single term check # Single term check
if term in textToSearch: if _japanese_term_in_text(term, textToSearch) if re.search(r'[一-龠ぁ-ゔァ-ヴーヲ-゚。-゚]', str(term)) else term in textToSearch:
term_found = True term_found = True
# Always include "# Game Characters" category and all its terms regardless of matches # Always include "# Game Characters" category and all its terms regardless of matches