|
37 | 37 | LangChangeCommand, |
38 | 38 | BeepCommand, |
39 | 39 | EndUtteranceCommand, |
| 40 | + SuppressUnicodeNormalizationCommand, |
40 | 41 | CharacterModeCommand, |
41 | 42 | ) |
42 | 43 | from .shortcutKeys import getKeyboardShortcutsSpeech |
@@ -160,11 +161,16 @@ def isBlank(text): |
160 | 161 | RE_CONVERT_WHITESPACE = re.compile("[\0\r\n]") |
161 | 162 |
|
162 | 163 |
|
163 | | -def processText(locale: str, text: str, symbolLevel: characterProcessing.SymbolLevel) -> str: |
| 164 | +def processText( |
| 165 | + locale: str, |
| 166 | + text: str, |
| 167 | + symbolLevel: characterProcessing.SymbolLevel, |
| 168 | + normalize: bool = False |
| 169 | +) -> str: |
164 | 170 | text = speechDictHandler.processText(text) |
165 | 171 | text = characterProcessing.processSpeechSymbols(locale, text, symbolLevel) |
166 | 172 | text = RE_CONVERT_WHITESPACE.sub(" ", text) |
167 | | - if config.conf["speech"]["unicodeNormalization"]: |
| 173 | + if normalize: |
168 | 174 | text = unicodeNormalize(text) |
169 | 175 | return text.strip() |
170 | 176 |
|
@@ -508,19 +514,28 @@ def getSpellingSpeech( |
508 | 514 | capPitchChange = synthConfig["capPitchChange"] |
509 | 515 | else: |
510 | 516 | capPitchChange = 0 |
| 517 | + unicodeNormalization = ( |
| 518 | + not useCharacterDescriptions |
| 519 | + and bool(config.conf["speech"]["unicodeNormalization"]) |
| 520 | + ) |
511 | 521 | seq = _getSpellingSpeechWithoutCharMode( |
512 | 522 | text, |
513 | 523 | locale, |
514 | 524 | useCharacterDescriptions, |
515 | 525 | sayCapForCapitals=synthConfig["sayCapForCapitals"], |
516 | 526 | capPitchChange=capPitchChange, |
517 | 527 | beepForCapitals=synthConfig["beepForCapitals"], |
518 | | - unicodeNormalization=bool(config.conf["speech"]["unicodeNormalization"]), |
| 528 | + unicodeNormalization=unicodeNormalization, |
519 | 529 | reportNormalizedForCharacterNavigation=config.conf["speech"]["reportNormalizedForCharacterNavigation"], |
520 | 530 | ) |
521 | 531 | if synthConfig["useSpellingFunctionality"]: |
522 | 532 | seq = _getSpellingSpeechAddCharMode(seq) |
| 533 | + # This function applies Unicode normalization as appropriate. |
| 534 | + # Therefore, suppress the global normalization that might still occur |
| 535 | + # (i.e. when speak calls the processText function). |
| 536 | + yield SuppressUnicodeNormalizationCommand(True) |
523 | 537 | yield from seq |
| 538 | + yield SuppressUnicodeNormalizationCommand(False) |
524 | 539 |
|
525 | 540 |
|
526 | 541 | def getCharDescListFromText(text,locale): |
@@ -1036,6 +1051,7 @@ def speak( # noqa: C901 |
1036 | 1051 | curLanguage=defaultLanguage=getCurrentLanguage() |
1037 | 1052 | prevLanguage=None |
1038 | 1053 | defaultLanguageRoot=defaultLanguage.split('_')[0] |
| 1054 | + unicodeNormalization = initialUnicodeNormalization = config.conf["speech"]["unicodeNormalization"] |
1039 | 1055 | oldSpeechSequence=speechSequence |
1040 | 1056 | speechSequence=[] |
1041 | 1057 | for item in oldSpeechSequence: |
@@ -1065,12 +1081,19 @@ def speak( # noqa: C901 |
1065 | 1081 | inCharacterMode=False |
1066 | 1082 | for index in range(len(speechSequence)): |
1067 | 1083 | item=speechSequence[index] |
1068 | | - if isinstance(item,CharacterModeCommand): |
| 1084 | + if isinstance(item, CharacterModeCommand): |
1069 | 1085 | inCharacterMode=item.state |
1070 | | - if autoLanguageSwitching and isinstance(item,LangChangeCommand): |
| 1086 | + elif autoLanguageSwitching and isinstance(item, LangChangeCommand): |
1071 | 1087 | curLanguage=item.lang |
1072 | | - if isinstance(item,str): |
1073 | | - speechSequence[index]=processText(curLanguage,item,symbolLevel) |
| 1088 | + elif isinstance(item, SuppressUnicodeNormalizationCommand): |
| 1089 | + unicodeNormalization = initialUnicodeNormalization and item.state |
| 1090 | + elif isinstance(item,str): |
| 1091 | + speechSequence[index]=processText( |
| 1092 | + curLanguage, |
| 1093 | + item, |
| 1094 | + symbolLevel, |
| 1095 | + normalize=unicodeNormalization |
| 1096 | + ) |
1074 | 1097 | if not inCharacterMode: |
1075 | 1098 | speechSequence[index]+=CHUNK_SEPARATOR |
1076 | 1099 | _manager.speak(speechSequence, priority) |
|
0 commit comments