Command line switch to specify language on startup (#10044)#10089
Command line switch to specify language on startup (#10044)#10089JulienCochuyt wants to merge 4 commits intonvaccess:masterfrom
Conversation
|
@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. |
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. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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:
- 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.
- The original language of the configuration, which does not reflect the state NVDA is currently in. I felt it was quite awkward when testing.
- 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.
- 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?
There was a problem hiding this comment.
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_authen we know they wish to make it permanent.
source/nvda.pyw
Outdated
| '--lang', | ||
| dest='cmdLineLanguage', | ||
| default=None, | ||
| type=str, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
|
Leonard de Ruijter wrote:
+ # Ensure the language specified on the command line will be saved with the config.
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.
I think a user would expect whatever language was in effect at the time the
configuration is saved, to be the language saved, no matter the source of that
language selection. Otherwise don't save the configuration.
The only alternate behavior I can think of as reasonable, is that if the CLI
specifies a language, use it exclusively--ignore all language changes for that
session, keep the language set under general that was in the config, and only
save changes if they are made under general. But not only should that be
documented, it should be documented to the user with a warning window when NVDA
starts, and maybe again when entering settings to possibly change the language.
That would achieve the goal of the PR though.
|
|
Just a suggestion: Isn't it possible to show up a simple question on startup if NVDA was started with a command line flag?
|
|
A better dialog might be:
NVDA was started in [language], but this is not the language selected in the
NVDA configuration. Would you like to make [language] the new default
language?
This can always be changed later in NVDA settings under general.
[Button: make new default] [Button: keep existing default]
|
|
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.
|
|
@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:
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. |
|
@DrSooom wrote:
Makes sense.
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. |
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. |
|
Daniel Mayr wrote:
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"
How is that any better (in my mind it is quite a bit worse) than just providing
a batch file that fires NVDA with a commandline flag to initiate default system
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.
True with any such solution, except that there is narrator now.
And finally such a batch file must work for an installed and a portable
version of NVDA exactly the same.
Not everything else does. For example, the installed copy has an uninstall.exe.
So does a portable. However the effect in a portable version is not at all what
a user expects (as recently discussed with a new user on a user list).
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.
I agree about the flag, but how is that any better than the batch file method as
far as a user finding it?
The user still has to know its there, and be competent enough to run it.
It seems to me that:
1. We are trying too hard to cover every base for a probably rare problem; and
2. *Any* solution that is implemented here is probably going to involve the user
asking somewhere for help because NVDA is stuck in a foreign language. At that
point, a simple commandline flag, with an associated batch file in the program
directory only, is sufficient--the user can be told to do Windows+R,
%appdata%\nvda\syslangstartup, enter; and be done with it.
I think we could go a long way to fixing this by providing the original commandline
option as the PR tried to do; and making the language harder to change in the
first place.
For example, why is it easier to change language, than it is to change speech
synth? Surely language is a more distructive change, and should require a
confirmation dialog before it takes effect.
Shouldn't the first step here, be to make the troublesome circumstance harder to
get into? That will make the solutions even less likely to be necessary, which
in turn will make the need for covering all possible levels of user ignorance
less of a curly problem.
|
|
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. |
There was a problem hiding this comment.
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_authen 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): |
There was a problem hiding this comment.
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.
|
@JulienCochuyt is this on your radar still? |
|
Hi
|
|
@feerrenrut wrote:
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
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:
|
|
@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. |
|
@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. |
|
Closing as it's been superseded by #12958 - thank you @JulienCochuyt and @lukaszgo1 for your work on this |
…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).
… 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>
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
--langcommand 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.argvupon 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
--langcommand line parameter allows to override the configured NVDA language.