Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOC two-phase parsing for initializing locale (was: Option capable of setting help locale) #1326

Closed
pedrolamarao opened this issue Feb 17, 2021 · 9 comments
Milestone

Comments

@pedrolamarao
Copy link

First, thank you for this excellent project!
We have made an effort to implement our requirements with picocli and with little effort have mostly succeeded!

Unfortunately, we are stuck in a single requirement on locales.
We have confirmed that picocli is localizable and we have successfully used ResourceBundles.
But we require that option locale must change the default locale, affecting also the tool's help.

In our own tool suite, we do that by setting Locale.setDefault as early as possible.
With picocli, we have attempted the following:

static final class LocaleNamePreprocessor implements IParameterPreprocessor
{
  public boolean preprocess (Stack<String> args, CommandSpec commandSpec, ArgSpec argSpec, Map<String, Object> info)
  {
    final String arg = args.peek();
    Locale.setDefault(new Locale(arg));
    return false;
  }
}

@Option(names = { "-l", "--locale" }, descriptionKey = "locale for messages", preprocessor = LocaleNamePreprocessor.class)
private String localeName;

but for reasons we don't understand the code above does not cause the locale for help to change even if locale is the very first option in the command line.
Is the above expected to cause the locale used by picocli to change?

@pedrolamarao pedrolamarao changed the title Option capable of settings help locale Option capable of setting --help locale Feb 17, 2021
@pedrolamarao pedrolamarao changed the title Option capable of setting --help locale Option capable of setting help locale Feb 17, 2021
@remkop
Copy link
Owner

remkop commented Feb 18, 2021

It looks like ResourceBundles are resolved and loaded before the preprocessors are run, which explains the behaviour you are seeing.

One idea is to use a two-phase approach to parsing in the application:

  1. During the first phase, we only look for the presence of the --locale option, and update the default locale as needed.
  2. In the second phase, we run the remaining business logic.

Something like this:

class InitLocale {
    @Option(names = { "-l", "--locale" }, descriptionKey = "locale for messages", paramLabel = "<name>")
    void setLocale(String locale) {
        Locale.setDefault(new Locale(locale));
    }

    @Unmatched
    List<String> remainder; // ignore any other parameters and options in the first parsing phase
}

@Command(name = "myapp", resourceBundle = "mybundle")
class ActualApplication implements Runnable {
    @Option(names = { "-l", "--locale" }, descriptionKey = "locale for messages", paramLabel = "<name>")
    private String ignored;

    @Option(names = { "-x", "--other-option" }, descriptionKey = "some other option")
    private String value;

    public void run() { // business logic here
    }

    public static void main(String[] args) {
        // first phase: configure locale
        new CommandLine(new InitLocale()).parseArgs(args);

        // second phase: parse all args (ignoring --locale) and run the app
        new CommandLine(new ActualApplication()).execute(args);
    }
}

@remkop
Copy link
Owner

remkop commented Feb 18, 2021

I imagine that your use case is a common requirement for localized CLI apps.

Generally speaking, this two-phase parsing approach can be an elegant and simple solution to a certain category of problems.
It would be good to have an example of this approach in the picocli user manual, and your use case is a very appealing one.

Would you be interested in providing a pull request to add this example (or something like it, after you verified that it actually works 😄 ) to the documentation (and the picocli-examples module)?

@pedrolamarao
Copy link
Author

Would you be interested in providing a pull request to add this example (or something like it, after you verified that it actually works 😄 ) to the documentation (and the picocli-examples module)?

Yes!

I can also contribute our reasoning on this. We have two: both having in common inter-locale human relationships.

The user is not using a system configured for his native locale. It may be that they are (say) operating some remote thin container, or some server where nobody cared about this during installation. Or it may be that company policy requires that all systems are configured to the same locale, but that is different from the "native" locale for this particular person. I personally think this is of low impact.

The user has a system confortably configured for himself, but, not for some other person with whom she is interacting. For example, the user may need to share an error message with (say) Stack Overflow. But sharing such messages localized will effectively impede communication. I personally think this is of high impact -- this is the hard reason we adopt the requirement.

@pedrolamarao
Copy link
Author

pedrolamarao commented Feb 18, 2021

About the first story above, an anecdote: the company used to mandate every system must be localized to en with the purpose of forcing people to learn english.

@remkop remkop changed the title Option capable of setting help locale DOC two-phase parsing for initializing locale (was: Option capable of setting help locale) Feb 19, 2021
@remkop
Copy link
Owner

remkop commented Feb 19, 2021

Would you be interested in providing a pull request to add this example (or something like it, after you verified that it actually works 😄 ) to the documentation (and the picocli-examples module)?

Yes!

Great, thank you in advance! I modified the issue title accordingly.

The file to modify is index.adoc. The HTML gets generated from that file and will be published with the next release.

After running the gradlew asci task, the generated documentation appears in build/docs.

I am thinking it may be good to add a new subsection "Controlling the Locale" at the end of the "Internationalization" section. Let me know what you think.

@pedrolamarao
Copy link
Author

The technique you suggested seems to work well.
I will further validate this by porting one of our tools to picocli and see what happens.

@remkop
Copy link
Owner

remkop commented Feb 19, 2021

Excellent! Glad to hear that.

@pedrolamarao
Copy link
Author

Sorry for not contributing this in time. Thank you for your hard work!

@remkop
Copy link
Owner

remkop commented Mar 18, 2021

All credit goes to @deining! 😄

MarkoMackic pushed a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic pushed a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic pushed a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic added a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic added a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic added a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic added a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic added a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic added a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants