Skip to content

Commit 5d4b179

Browse files
committed
Switch the voice when the language changes -- try #2. The SpeechStyle wasn't being set properly all the time. Also a bug with regional variants and zip files.
Fixes #81 q
1 parent 0f2589d commit 5d4b179

File tree

2 files changed

+85
-49
lines changed

2 files changed

+85
-49
lines changed

addon/globalPlugins/MathCAT/MathCAT.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def ConvertSSMLTextForNVDA(text: str) -> list:
121121
log.error(e)
122122
language = getLanguageToUse()
123123
nvdaLanguage = getCurrentLanguage().replace("_", "-")
124-
log.info(f"mathCATLanguageSetting={mathCATLanguageSetting}, lang={language}, NVDA={nvdaLanguage}")
124+
# log.info(f"mathCATLanguageSetting={mathCATLanguageSetting}, lang={language}, NVDA={nvdaLanguage}")
125125

126126
synth = getSynth()
127127
_monkeyPatchESpeak()

addon/globalPlugins/MathCAT/MathCATPreferences.py

Lines changed: 84 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def path_to_braille_folder():
9090
return os.path.expanduser("~") + "\\AppData\\Roaming\\nvda\\addons\\mathCAT\\globalPlugins\\MathCAT\\Rules\\Braille"
9191

9292
@staticmethod
93-
def LanguagesDict():
93+
def LanguagesDict() -> Dict[str, str]:
9494
languages = {
9595
"aa": "Afar",
9696
"ab": "Аҧсуа",
@@ -268,8 +268,30 @@ def LanguagesDict():
268268
return languages
269269

270270
def GetLanguages(self):
271+
272+
def addRegionalLanguages(subDir: str, language: str) -> bool:
273+
# the language variants are in folders named using ISO 3166-1 alpha-2
274+
# codes https://en.wikipedia.org/wiki/ISO_3166-2
275+
# check if there are language variants in the language folder
276+
if subDir != "SharedRules":
277+
languagesDict = UserInterface.LanguagesDict()
278+
# add to the listbox the text for this language variant together with the code
279+
if languagesDict.get(language + "-" + subDir.upper(), "missing") != "missing":
280+
self.m_choiceLanguage.Append(
281+
languagesDict[language + "-" + subDir.upper()] + " (" + language + "-" + subDir + ")"
282+
)
283+
elif languagesDict.get(language, "missing") != "missing":
284+
self.m_choiceLanguage.Append(
285+
languagesDict[language] + " (" + language + "-" + subDir + ")"
286+
)
287+
else:
288+
self.m_choiceLanguage.Append(
289+
language + " (" + language + "-" + subDir + ")"
290+
)
291+
return subDir != "SharedRules"
292+
271293
# initialise the language list
272-
languages_dict = UserInterface.LanguagesDict()
294+
languagesDict = UserInterface.LanguagesDict()
273295
# clear the language names in the dialog
274296
self.m_choiceLanguage.Clear()
275297
# Translators: menu item -- use the language of the voice chosen in the NVDA speech settings dialog
@@ -279,40 +301,31 @@ def GetLanguages(self):
279301
# the implemented languages are in folders named using the relevant ISO 639-1
280302
# code https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
281303
for language in os.listdir(UserInterface.path_to_languages_folder()):
282-
if os.path.isdir(os.path.join(UserInterface.path_to_languages_folder(), language)):
283-
path_to_language_folder = os.path.join(UserInterface.path_to_languages_folder(), language)
304+
pathToLanguageDir = os.path.join(UserInterface.path_to_languages_folder(), language)
305+
if os.path.isdir(pathToLanguageDir):
284306
# only add this language if there is a xxx_Rules.yaml file
285-
files = glob.glob(os.path.join(path_to_language_folder, "*_Rules.yaml"))
286-
if len(files) == 0:
287-
# look in the .zip file for the style files -- it might not have been unzipped
288-
zip_file = ZipFile(f"{path_to_language_folder}\\{language}.zip", "r")
289-
files = [name for name in zip_file.namelist() if name.endswith('_Rules.yaml')]
290-
if files:
307+
ruleFilesWereFound = len(glob.glob(os.path.join(pathToLanguageDir, "*_Rules.yaml"))) > 0
308+
for dir in os.listdir(pathToLanguageDir):
309+
if os.path.isdir(os.path.join(pathToLanguageDir, dir)):
310+
ruleFilesWereFound |= addRegionalLanguages(dir, language)
311+
312+
if not ruleFilesWereFound:
313+
# look in the .zip file for the style files, including regional subdirs -- it might not have been unzipped
314+
try:
315+
zip_file = ZipFile(f"{pathToLanguageDir}\\{language}.zip", "r")
316+
for file in zip_file.namelist():
317+
if file.endswith('_Rules.yaml'):
318+
ruleFilesWereFound = True
319+
elif zip_file.getinfo(file).is_dir():
320+
ruleFilesWereFound |= addRegionalLanguages(dir, language)
321+
except Exception as e:
322+
log.debugWarning(f"MathCAT Dialog: didn't find zip file {zip_file}. Error: {e}")
323+
if ruleFilesWereFound:
291324
# add to the listbox the text for this language together with the code
292-
if languages_dict.get(language, "missing") != "missing":
293-
self.m_choiceLanguage.Append(languages_dict[language] + " (" + language + ")")
325+
if languagesDict.get(language, "missing") != "missing":
326+
self.m_choiceLanguage.Append(languagesDict[language] + " (" + language + ")")
294327
else:
295328
self.m_choiceLanguage.Append(language + " (" + language + ")")
296-
# the language variants are in folders named using ISO 3166-1 alpha-2
297-
# codes https://en.wikipedia.org/wiki/ISO_3166-2
298-
# check if there are language variants in the language folder
299-
for variant in os.listdir(path_to_language_folder):
300-
if os.path.isdir(os.path.join(path_to_language_folder, variant)):
301-
if variant != "SharedRules":
302-
# add to the listbox the text for this language variant together with the code
303-
if languages_dict.get(language + "-" + variant.upper(), "missing") != "missing":
304-
self.m_choiceLanguage.Append(
305-
languages_dict[language + "-" + variant.upper()] + " (" + language + "-" + variant + ")"
306-
)
307-
else:
308-
if languages_dict.get(language, "missing") != "missing":
309-
self.m_choiceLanguage.Append(
310-
languages_dict[language] + " (" + language + "-" + variant + ")"
311-
)
312-
else:
313-
self.m_choiceLanguage.Append(
314-
language + " (" + language + "-" + variant + ")"
315-
)
316329

317330
def GetLanguageCode(self):
318331
lang_selection = self.m_choiceLanguage.GetStringSelection()
@@ -322,37 +335,60 @@ def GetLanguageCode(self):
322335
return lang_code
323336

324337
def GetSpeechStyles(self, this_SpeechStyle: str):
338+
"""Get all the speech styles for the current language.
339+
This sets the SpeechStyles dialog entry"""
325340
from speech import getCurrentLanguage
326341

342+
def getSpeechStyleFromDirectory(dir: str, lang: str) -> list[str]:
343+
r"""Get the speech styles from any regional dialog, from the main language, dir and if there isn't from the zip file.
344+
The 'lang', if it has a region dialect, is of the form 'en\uk'
345+
The returned list is sorted alphabetically"""
346+
# start with the regional dialect, then add on any (unique) styles in the main dir
347+
main_lang = lang.split("\\")[0] # does the right thing even if there is no regional directory
348+
all_style_files = []
349+
if lang.find("\\") >= 0:
350+
all_style_files = [os.path.basename(name) for name in glob.glob(dir + lang + "\\*_Rules.yaml")]
351+
all_style_files.extend(
352+
[os.path.basename(name) for name in glob.glob(dir + main_lang + "\\*_Rules.yaml")]
353+
)
354+
all_style_files = list(set(all_style_files)) # make them unique
355+
if len(all_style_files) == 0:
356+
# look in the .zip file for the style files -- this will have regional variants, but also have that dir
357+
try:
358+
zip_file = dir + main_lang + "\\" + main_lang + ".zip"
359+
zip_file = ZipFile(zip_file, "r") # file might not exist
360+
all_style_files = [name.split("/")[-1] for name in zip_file.namelist() if name.endswith('_Rules.yaml')]
361+
except Exception as e:
362+
log.debugWarning(f"MathCAT Dialog: didn't find zip file {zip_file}. Error: {e}")
363+
all_style_files.sort()
364+
return all_style_files
365+
327366
# clear the SpeechStyle choices
328367
self.m_choiceSpeechStyle.Clear()
329368
# get the currently selected language code
330-
this_language_code = UserInterface.GetLanguageCode(self)
369+
languageCode = UserInterface.GetLanguageCode(self)
331370

332-
if this_language_code == "Auto":
371+
if languageCode == "Auto":
333372
# list the speech styles for the current voice rather than have none listed
334-
this_language_code = getCurrentLanguage().lower().replace("_", "-")
335-
# FIX: when dialog is aware of regional dialects, remove this next line that removes the dialect part
336-
this_language_code = this_language_code.split("-")[0] # grab the first part
373+
languageCode = getCurrentLanguage().lower().replace("_", "-")
374+
languageCode = languageCode.replace("-", "\\")
337375

338-
this_language_path = (
376+
languagePath = (
339377
os.path.expanduser("~")
340378
+ "\\AppData\\Roaming\\nvda\\addons\\MathCAT\\globalPlugins\\MathCAT\\Rules\\Languages\\"
341-
+ this_language_code
342379
)
343-
this_path = this_language_path + "\\*_Rules.yaml"
344380
# populate the m_choiceSpeechStyle choices
345-
# start with listing unzipped dirs
346-
all_style_files = [os.path.basename(name) for name in glob.glob(this_path)]
347-
if len(all_style_files) == 0:
348-
# look in the .zip file for the style files
349-
zip_file = ZipFile(f"{this_language_path}\\{this_language_code}.zip", "r")
350-
all_style_files = [name for name in zip_file.namelist() if name.endswith('_Rules.yaml')]
381+
all_style_files = [
382+
# remove "_Rules.yaml" from the list
383+
name[: name.find("_Rules.yaml")] for name in getSpeechStyleFromDirectory(languagePath, languageCode)
384+
]
351385
for name in all_style_files:
352-
self.m_choiceSpeechStyle.Append((name[: name.find("_Rules.yaml")]))
386+
self.m_choiceSpeechStyle.Append((name))
353387
try:
354388
# set the SpeechStyle to the same as previous
355-
self.m_choiceSpeechStyle.SetStringSelection(this_SpeechStyle)
389+
self.m_choiceSpeechStyle.SetStringSelection(
390+
this_SpeechStyle if this_SpeechStyle in all_style_files else all_style_files[0]
391+
)
356392
except Exception as e:
357393
log.error(f"MathCAT: An exception occurred in GetSpeechStyles evaluating set SetStringSelection: {e}")
358394
# that didn't work, choose the first in the list

0 commit comments

Comments
 (0)