Skip to content

Command line switch to specify language on startup (#10044)#10089

Closed
JulienCochuyt wants to merge 4 commits intonvaccess:masterfrom
accessolutions:i10044-cmdLineLanguage
Closed

Command line switch to specify language on startup (#10044)#10089
JulienCochuyt wants to merge 4 commits intonvaccess:masterfrom
accessolutions:i10044-cmdLineLanguage

Conversation

@JulienCochuyt
Copy link
Copy Markdown
Contributor

Link to issue number:

Fixes #10044

Summary of the issue:

There currently is no command line option to override the NVDA language configuration.
As @ScottChesworth pointed out, in the event of a user error, getting back on one's feet can be tricky.

Description of how this pull request fixes the issue:

Add a new --lang command line parameter.
It accepts either "Windows" or the usual "en" / "de_CH" codes, with a little tolerance regarding to case and dashes.
The supplied value gets saved along with the configuration, and is maintained over configuration resets.
The parameter is however removed from sys.argv upon restarting if the configuration has been changed to allow for switching language.

Note: Resetting the NVDA configuration does not historically properly switch language. This PR does not change this fact.

Testing performed:

Ensure the configuration is impacted by the new parameter when it gets saved.
Ensure the new parameter is maintained on configuration reset.
Ensure the new parameter is maintained on restart when the configured language was not manually changed.
Ensure the new parameter is forgotten on restart when the configured language was manually changed.

Known issues with pull request:

If the new parameter is provided and the configured language is manually changed and configuration is not set to be saved upon exit and NVDA is restarted, then the new parameter is lost and NVDA restarts with the language set in the original configuration.
To workaround this limitation, I guess I could somehow check that the configured language is "dirty" (not saved). Anyone knows how to do this?

Change log entry:

Section: New features

The new --lang command line parameter allows to override the configured NVDA language.

@DrSooom
Copy link
Copy Markdown

DrSooom commented Aug 14, 2019

@JulienCochuyt: I'm not so sure if this this PR fully fixes #10044. It is still a problem if the current TTS isn't able to read the current used GUI language correctly. Just change the GUI language to German and the eSpeak NG language to French and then try to change both back to English. Therefore a second command line flag for eSpeak NG could help here. Then you can start NVDA with the English GUI as well as with the English eSpeak NG voice at once.

@LeonarddeR
Copy link
Copy Markdown
Collaborator

If the new parameter is provided and the configured language is manually changed and configuration is not set to be saved upon exit and NVDA is restarted, then the new parameter is lost and NVDA restarts with the language set in the original configuration.

What happens if you don't provide the parameter and change the language when save on exit is disabled? Is it then properly updated?

lang = config.conf["general"]["language"]
lang = globalVars.appArgs.cmdLineLanguage
if lang:
# Ensure the language specified on the command line will be saved with the config.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I"m not sure whether this is what people expect from command line arguments. They are most of the time only seen as temporary overrides. I think I prefer the language setting to be that way as well, i.e. it should only be effective to the current session of NVDA, until there is a restart triggered from outside that resets the params. It should not touch the configuration at all.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if you don't provide the parameter and change the language when save on exit is disabled? Is it then properly updated?

(Before and after this PR, same process)
If one changes the language and answers "No" when asked to restart right away, the change is - as expected - lost when restarting if the configuration has not been saved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not touch the configuration at all.

The original poster of #10144 accidentally changed language to Hebrew, a language which he cannot understand. To get him back on his feet, we need a way to change this setting.

The point is: If the language specified on the command line is different from the configuration, what should the settings dialog present as the selected language?

I see four options here:

  1. The language specified on the command line. Hence, if the configuration is saved (manually or automatically upon exit), the new language is applied. This is the approach I took.
  2. The original language of the configuration, which does not reflect the state NVDA is currently in. I felt it was quite awkward when testing.
  3. The language specified on the command line suffixed with "forced from command line". This is explicit, but also requires greater impact and I felt it was uselessly cumbersome.
  4. The original language of the configuration, but in a disabled drop-down preceded by a message explaining another language was specified on the command line and a button to allow for changing this setting. This is explicit, but also requires the greatest impact and I felt it was uselessly cumbersome.

What do you think? Would you prefer option 2?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other situations where we override from the command-line we disable the control so that we avoid this confusion. That, of course, defeats the purpose of this PR.

My preference would be to insert a new item in the language list (at index 0) with something like command line option: en_au or similar.

  • If the user leaves this option, they can safely change other options and save their config without accidentally changing their language.
  • If the user explicitly changes the language to en_au then we know they wish to make it permanent.

source/nvda.pyw Outdated
'--lang',
dest='cmdLineLanguage',
default=None,
type=str,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of str, you can provide a function that does further parsing and normalization of the name. See the stringToBool function as an example. Could you also have a look at locale.normalize? I think that does pretty much what you're doing manually now. If it is not sufficient, I think I'd like to see a comment why not.

Copy link
Copy Markdown
Contributor Author

@JulienCochuyt JulienCochuyt Sep 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of str, you can provide a function that does further parsing and normalization of the name. See the stringToBool function as an example.

I'll have a look.
EDIT: Done as of a852fa6.

Could you also have a look at locale.normalize? I think that does pretty much what you're doing manually now. If it is not sufficient, I think I'd like to see a comment why not.

>>>locale.normalize("en")
'en_US.ISO8859-1'

This is not the kind of output we need.

languageHandler.normalizeLanguage does not fit either as it requires a dialect to be specified.

sys.argv.remove("--ease-of-access")
except ValueError:
pass
if globalVars.appArgs.cmdLineLanguage:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think cmdLanguage can just be language. globalVars.appArgs already implies that we're dealing with a command line argument here. Having said that, I note that some magic is happening with the configPath, but that could be considered confusing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think cmdLanguage can just be language. globalVars.appArgs already implies that we're dealing with a command line argument here.

If i'm not wrong, other members of globalVars.appArgs convey their default value if not specified from the command line. This one is different as, if not specified on the command line, it would not be set to the value in the configuration. Thus, I chose that name to be extra explicit and ensure no one mistakes the intent behind this member.
Let me know if you feel like my reasoning is wrong here and I will rename it as you suggest.

Having said that, I note that some magic is happening with the configPath, but that could be considered confusing.

I don't get your point here. Could you please elaborate?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having said that, I note that some magic is happening with the configPath, but that could be considered confusing.

I don't get your point here. Could you please elaborate?

If you do not start NVDA with the --config-path parameter, globalVars.appArgs.configPath is still populated with the actual config path. It is also widely used throughout the code base to refer to the config path. A similar thing could happen with globalVars.appArgs.language in that if it is not overridden using the command line, can be set to the actual language.

Just a suggestion: Isn't it possible to show up a simple question on startup if NVDA was started with a command line flag?

I think this suggestion makes sense, as it will address the concern about what is displayed in the general settings panel for the language.

@XLTechie
Copy link
Copy Markdown
Collaborator

XLTechie commented Aug 29, 2019 via email

@DrSooom
Copy link
Copy Markdown

DrSooom commented Sep 7, 2019

Just a suggestion: Isn't it possible to show up a simple question on startup if NVDA was started with a command line flag?

  • [Text] NVDA was started in [language] due to a command line flag. The chosen language in the saved NVDA configuration is [language]. Do you want to overwrite this setting? If you press "Yes", NVDA will always start in [language] unless the language was manually changed via the General NVDA Settings again.
  • [Button] Yes, No

@XLTechie
Copy link
Copy Markdown
Collaborator

XLTechie commented Sep 11, 2019 via email

@lukaszgo1
Copy link
Copy Markdown
Contributor

I am not sure that this PR really addresses the referenced issue. For most user command line arguments are just black magic. Blind people are perhaps used to them more than statistical computer user as some programmes require them to be usable when not conventionally accessible, but still for the majority they are something completely unknown. The situation in which someone changes NVDA language unintentionally is most often an beginner error, and for such user specifying language on the command line is simply not doable. Having such ability is still useful for advanced users, but we should also look for the more beginner friendly solution.
I tried coming up with something reasonable and I see three things that might improve the situation.

  1. First of all it makes sense to document in the user guide that the last position in the language list is the system default language - that way user can open general settings press End and Enter twice.
  2. We may consider adding button that resets current section to default - something similar to the button present in the advanced category and assign a keyboard shortcut to it Ctrl+r comes to mint as a reasonable combination.
  3. While not ideal adding 'reset to factory default' shortcut to the NVDA group in the start menu also makes sense. It would be in the language in which NVDA was installed (we can safely assume that user understands it) and would also be discoverable. Loss of all settings is never ideal, but for most users it would be the easiest solution.

@DrSooom
Copy link
Copy Markdown

DrSooom commented Sep 12, 2019

@lukaszgo1: Regarding you third suggestion: Wouldn't it better just to add an additional shortcut in the start menu called "Start NVDA in the System Language"?

And regarding your second suggestion: NVDA+CTRL+R pressing twice isn't allocated yet. After pressing it, the following could appear:

  • [Text] Do you want to restart NVDA in the language of the operating system?
  • [Buttons] Yes (default), No

Finally the end user just has to press NVDA+CTRL+R twice following by the Enter key to restart NVDA with that command flag. And additionally we could also add that command flag option to the Exit Dialog at the end of the list. Then the end user only has to press NVDA+Q following by the End and the Enter key. Now these two methods should be simple enough to be performed by most of the end users.

@lukaszgo1
Copy link
Copy Markdown
Contributor

@DrSooom wrote:

you third suggestion: Wouldn't it better just to add an additional shortcut in the start menu called "Start NVDA in the System Language"?

Makes sense.

And regarding your second suggestion: NVDA+CTRL+R pressing twice isn't allocated yet. After pressing it, the following could appear:

* [Text] Do you want to restart NVDA in the language of the operating system?

* [Buttons] Yes (default), No

Finally the end user just has to press NVDA+CTRL+R twice following by the Enter key to restart NVDA with that command flag. And additionally we could also add that command flag option to the Exit Dialog at the end of the list. Then the end user only has to press NVDA+Q following by the End and the Enter key. Now these two methods should be simple enough to be performed by most of the end users.

How many users are aware of this shortcut? Inn my opinion not to many. Accessing this from exit dialog is possible only when you ahven't disabled it, and when language is changed unintentionally it it too late to enable it again.

@DrSooom
Copy link
Copy Markdown

DrSooom commented Sep 12, 2019

  • NVDA+N » ArrowUp » Enter = Opens the Exit Dialog via the NVDA menu:
  • NVDA+Q = Opens the Exit Dialog directly.

Furthermore NVDA+Q is listed directly below NVDA+1 within the same table in the User Guide. But you're right with your point regarding a disabled "Show exit options when exiting NVDA" option.

In the meantime I also thought about a little batch similar exe file, which only searches the "nvda.ini" file, opens it and just changes the "language" parameter to "Windows". But I don't think that this is really a good idea. First of all you have to know that this file exists. Then you have to be able to move totally blind to that file in the Windows Explorer. And finally such a batch file must work for an installed and a portable version of NVDA exactly the same. A command line flag and an additional shortcut within the program folder (keyword: portable version) and in the start menu program folder could be the better solution here.

@XLTechie
Copy link
Copy Markdown
Collaborator

XLTechie commented Sep 13, 2019 via email

@DrSooom
Copy link
Copy Markdown

DrSooom commented Sep 13, 2019

Maybe we should move the "Language" combobox in the General NVDA Settings at the very last position – and no longer keep it at the very first one.

lang = config.conf["general"]["language"]
lang = globalVars.appArgs.cmdLineLanguage
if lang:
# Ensure the language specified on the command line will be saved with the config.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other situations where we override from the command-line we disable the control so that we avoid this confusion. That, of course, defeats the purpose of this PR.

My preference would be to insert a new item in the language list (at index 0) with something like command line option: en_au or similar.

  • If the user leaves this option, they can safely change other options and save their config without accidentally changing their language.
  • If the user explicitly changes the language to en_au then we know they wish to make it permanent.

dialect = value.split("_")[1].upper() if "_" in value else None
# Validating the size of the codes.
# Further validation would require L{languageHandler} to be initialized.
if len(lang) != 2 or (dialect and len(dialect) != 2):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if this could check that the lang and dialect is in the list of supported languages. These errors could include the available languages.

@LeonarddeR
Copy link
Copy Markdown
Collaborator

@JulienCochuyt is this on your radar still?

@CyrilleB79
Copy link
Copy Markdown
Contributor

CyrilleB79 commented Jan 8, 2021

Hi
Another use case to consider for this PR is for NVDA dev, translators or testers:

  1. As a tester, I want to fill in GitHub issue. I need to change my language to English, save it and restart NVDA to describe accurately the options and controls names in the steps to reproduce the issue. Then I need to make the same changes again to turn back to French (my usual language).
  2. As a developer / translator, I may have to check quickly how things are written in NVDA interface for English or another language than mine.

@CyrilleB79
Copy link
Copy Markdown
Contributor

@feerrenrut wrote:

My preference would be to insert a new item in the language list (at index 0) with something like command line option: en_au or similar.

  • If the user leaves this option, they can safely change other options and save their config without accidentally changing their language.
  • If the user explicitly changes the language to en_au then we know they wish to make it permanent.

I fully agree with this proposal. This allows to indicate clearly in the UI that the selected language is the one from the command line (without having a greyed out option). In the current version of this code, the UI does not indicate clearly that the selected language is the one of the command line.

Also errors on the command line parameter need to be checked more robustly. e.g. presently, the following invalid parameters can be passed to the --lang flag and saved in the config file:

  • --lang zz
  • --lang fr-zz

Presently, in both cases, the selected choice in the language list of the UI is empty.

Also in the present version of this PR there are issues for the following languages:

  • af: NVDA starts in Afrikaans but the selected choice in the language list is blank since only af_ZA exists in the language list.
  • ckb, kmr: error message at startup whereas these two Kurdish languages are valid language codes for NVDA
  • nb: NVDA starts in Norwegian but the selected choice in the language list is blank since only nb_NO exists in the language list, not nb alone.
  • nn: NVDA starts in Norwegian but the selected choice in the language list is blank since only nn_NO exists in the language list, not nn alone.
  • pt: NVDA starts in Portuguese (don't know if it is pt_BR or pt_PT) but the selected choice in the language list is blank since only pt_BR and pt_PT exists in the language list, not pt alone.
  • zh: NVDA starts in Chinese (don't know which one) but the selected choice in the language list is blank since only zh_CN, zh_HK and zh_TW exists in the language list, not zh alone.

@feerrenrut
Copy link
Copy Markdown
Contributor

@CyrilleB79 Would you be interested in taking on this PR and addressing those concerns? If so, please feel free to create a new PR based on this one.

@lukaszgo1
Copy link
Copy Markdown
Contributor

@JulienCochuyt Given this had no activity for year and a half I've decided to take this on and created #12958 based on your work. Hope you do not mint.

@seanbudd
Copy link
Copy Markdown
Member

Closing as it's been superseded by #12958 - thank you @JulienCochuyt and @lukaszgo1 for your work on this

@seanbudd seanbudd closed this Oct 19, 2021
michaelDCurran pushed a commit that referenced this pull request Nov 21, 2021
…er after abandoned #10089) (#12958)

Fixes #10044
Supersedes #10089

Summary of the issue:
It can sometimes be useful to specify NVDA's language from the CLI. One use case which has been mentioned in #10044 is when language has been accidentally changed to a foreign one. This can also be useful for developers (it would certainly be a welcome addition for me when working on #12250 and #12753).

Description of how this pull request fixes the issue:
Add a new --lang command line parameter.
It accepts either "Windows" or the usual "en" / "de_CH" codes, with a little tolerance regarding to case and dashes.
As discussed during the review in #10089 the parameter is treated as a temporary override (i.e. it does not affect configuration at all and is effective only until NVDA is restarted).
As a bonus this PR adds unit tests for languageHandler.normalizeLanguage and languageHandler.getAvailableLanguages (tests for the former were necessary to confirm it provides us with normalization we need, and since I had to split the latter one into two functions added tests made it possible to confirm that current behavior has not changed).
seanbudd added a commit that referenced this pull request Nov 23, 2021
… provided from the command line or not. (#13082)

Follow up of #10089 and #12958

Summary of the issue:
PR #12958 introduced additional command line parameter which allows to set NVDA's language. The currently set language is stored in globalVars.appArgs.language however when it is not overridden from the CLI this variable is set to None. TO improve consistency with globalVars.appArgs.configPath it makes sense to store current NVDA's language in globalVars regardless of where it comes from.

Description of how this pull request fixes the issue:
Current NVDA language is now stored in globalVars.appArgs.language - it still can be accessed via languageHandler.getLanguage which is a recommended way to get its value for add-ons developers. To make this work for nvda_slave it has been necessary to provide a 'fake' implementation of globalVars.appArgs which is used in cases where command line arguments are not available or not yet parsed. This also provides type hints for values of appArgs so I'd say it is beneficial regardless.

* Use `languageHandler.getLanguage` when querying current NVDA's language rather than accessing `curLang` directly.
* Store current NVDA's language in `globalVars`
* Set `globalVarrs.appArgs` to a fake implementation by default.
* update changes

Co-authored-by: buddsean <sean@nvaccess.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked/merge-conflicts Merge conflicts exist on this PR feature ux

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Command line switch to specify language on startup

8 participants