Skip to content
This repository has been archived by the owner on Jan 1, 2022. It is now read-only.

Support or document localization of messages and flags #63

Open
epage opened this issue Dec 6, 2021 · 15 comments
Open

Support or document localization of messages and flags #63

epage opened this issue Dec 6, 2021 · 15 comments

Comments

@epage
Copy link
Owner

epage commented Dec 6, 2021

Issue by kamalmarhubi
Tuesday Jan 12, 2016 at 16:57 GMT
Originally opened as clap-rs/clap#380


Make it easy for developers to support translations of their projects.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by kbknapp
Wednesday Jan 13, 2016 at 07:10 GMT


This is something I'm interested in doing, but it will take some thought on how to best go about this. I'm putting it on the issue tracker, but let's get some discussion going on ways about this!

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by kbknapp
Monday Jan 25, 2016 at 15:05 GMT


@kamalmarhubi I was thinking about this today, and would the YAML feature allow this? I.e. I'm thinking having a differente yaml file for each translation, and depending on which language/translation is compiled via features, you pick a different yaml file.

Example:

# Cargo.toml

[features]
default = ["en_US"]
en_US = []
es_ES = []
# en_US.yml
name: My Application
version: 1.0
about: An example using many languages
author: Kevin K. <[email protected]>
args:
    - opt:
        help: an example option
        short: o
        long: option
        multiple: true
        takes_value: true
    - pos:
        help: example positional with possible values
        index: 1
        possible_values:
            - fast
            - slow
# es_ES.yml
name: Mi Aplicacion
version: 1.0
about: Un ejamlo util muy idiomas
author: Kevin K. <[email protected]>
args:
    - opt:
        help: un ejamplo de un opcion
        short: o
        long: opcion
        multiple: true
        takes_value: true
    - pos:
        help: un ejamplo de un posicion con valores posible
        index: 1
        possible_values:
            - rapido
            - lento
// main.rs
#[cfg(feature = "en_US")]
const TRANSLATION: &'static str = "en_US.yml";

#[cfg(feature = "es_ES"]
const TRANSLATION: &'static str = "es_ES.yml";

fn main() {
    let yml = load_yaml!(TRANSLATION);
    let m = App::from_yaml(yml).get_matches();
}

Then depending on if you compile with --features en_US or --features es_ES it will set the translation. Does this work for you?

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by kamalmarhubi
Tuesday Feb 02, 2016 at 22:13 GMT


Then depending on if you compile with --features en_US or --features es_ES it will set the translation. Does this work for you?

It's not me I'm thinking about, just something a user-facing system should allow for. :-)

And as for the solution, it would be much better to allow the user's locale settings to dictate the language in help. Requiring users to compile the tool with their language is non-ideal. Hooking into gettext or l20n would be a nice approach, as there's tooling for people to work on translations, and they can live outside of the binary.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by kamalmarhubi
Tuesday Feb 02, 2016 at 22:16 GMT


Though I guess there's a question of whether the options should be translated, or just the help... which comes up in your example. Thanks for that by the way, concrete is always good to look at!

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by joshtriplett
Thursday Jun 23, 2016 at 21:38 GMT


I've never seen a program that translates long option names; those are API, much like the names of functions in a library. Translating the help is a great idea, though.

I'd definitely agree with hooking into gettext, to work with the massive amount of translation infrastructure and tooling built around that, rather than creating a new translation format.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by hoodie
Monday Feb 06, 2017 at 11:54 GMT


I am currently trying to localize my app using crowbook-intl which is pretty nice. Unfortunately, the fact that AppMeta etc don't want to own the description strings makes it extremely hard to use dynamic strings in .about() and .help() methods. Do you have an idea to work around that? Could the next implementation perhaps own these strings?

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by kbknapp
Monday Feb 06, 2017 at 20:07 GMT


@hoodie the strings only need to live as long as the App instance, so long as the localized strings are owned somewhere it shouldn't be an issue.

Can you paste some code that's giving issues and I can either see if there's a workaround or consider fixes if appropriate.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by hoodie
Saturday Feb 25, 2017 at 15:18 GMT


infact you are right, it's just a bit tricky dealing with the lifetime constraints. I built so that app is immediately passed to a closure now.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by pksunkara
Tuesday Feb 04, 2020 at 07:47 GMT


This would also include localization of clap strings such Usage, Flags, etc..

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by alerque
Friday May 01, 2020 at 20:35 GMT


I've come very close to achieving a localized CLI interface using Clap & Fluent. However there are a couple points that are a bit hackish and could use some first class support.

The main ugly bit about my solution is I have to parse args twice. I have a -l/--language parameter that can override any detected locale (not appropriate for most CLIs, useful for my case because my CLI generated other resources that have to be localized and uses that flag. In order to get any help messages localized to match I have to pre-parse to scrape out the language, then re-parse with Clap to get everything else.

The most useful improvement I can see would be for the derive variant of Clap (formerly StructOpt), where the documentation strings are relied on. Adding top level support for a macro that would call a function to get strings rather than using the doc strings would allow both pretty and functional setup.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by kbknapp
Friday May 01, 2020 at 21:00 GMT


@alerque See #1880 and if something like that would fit your use case if we implement it.

The most useful improvement I can see would be for the derive variant of Clap (formerly StructOpt), where the documentation strings are relied on. Adding top level support for a macro that would call a function to get strings rather than using the doc strings would allow both pretty and functional setup.

This might be useful outside of i18n context. I'm imagining a help_with(Fn). However, a few non-trivial questions would be need to be ironed out to make it general enough for inclusion:

  • Should the Fn accept a context? I.e. an ArgMatches, Id, or a String perhaps? No context makes it easier to implement, but then means consumers are relying on out of band global state to make decisions.
  • Would this be App level (applied to all Args), or Arg level?
  • Should the short/long help be different, or the same Fn (kinda goes back to the Context question above).

I personally think it might be a little too much to bite off on by the 3.0 release, but there isn't any reasons we couldn't address it post 3.0 as a feature to add if everything can be fleshed out and the complexity/maint burden isn't too high.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by alerque
Friday May 01, 2020 at 21:23 GMT


@kbknapp

  1. I'm not sure my understanding of Rust is developed enough to meaningfully address this question. I think the answer is having a context would introduce many more possibilities, but it would be useful even without — but I'm still struggling with Rust's variable lifetimes (I'm about 4 days in teaching myself through a pet project that I'm RIIR).

    Note that for my usage I've had to move the #[derive(Clap)] struct Cli {} and all related definitions out of the top level scope and into my fn main(). This is so that I can do a a few early initialization things like make a guess at the locale and pre-parse some arguments¹ before I can properly setup and run using Clap.

  2. Arg probably. Of course you have to set it on the app too (#[clap(about = "<my value>")] needs to be set), but there might be reasons to use different functions or otherwise customize how an argument setup. An App level default callback function with Arg level customization would be my preference.

  3. I'm of the opinion that the short/long options should be fixed because scripting with a program that changes it's API based on locale is a nightmare, only the descriptive about, help, etc would change in my implementation. I know there are people that feel like option names should be localized too, but it wouldn't suit my use case.

No worries about the 3.0 release, I want to see that go out the door with the baked in derive stuff sooner rather than later. But of course I'd love to see a follow up with the tooling for localized interfaces.

¹ Thanks for the link to #1880, that is exactly what I've needed and was hacking up by hand and messing with lighter weight argp parsing crates to handle a first pass to extract things needed for a full instantiation with Clap.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by kbknapp
Friday May 01, 2020 at 21:29 GMT


@alerque no worres, I should have been more clear. I wasn't posing those questions for you to have to answer. They were more abstract thoughts, primarily for the other maintainers of clap 😉

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by alerque
Thursday Jul 29, 2021 at 14:38 GMT


The recent Rust 1.54.0 release includes a bit I think might have a huge impact on how hard this is to implement:

You can now use macros for values in built-in attribute macros.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by luojia65
Thursday Nov 25, 2021 at 09:23 GMT


Is it possible to read and use current operating system's working locale settings (languages, money unit, etc.) in clap generated help messages? For example, on given operating system, users use --help and it shows help messages in current locale. Clap can provide a default way to define locales in command line, or remains to users to define them. It would be more nice if this can be implemented, as users in different culture could use the clap based applications more freely.
In this way we should (maybe) provide a way to write localized strings by locale setting input. Clap only provided as-is, it does not parse the locale setting string, but provide them to user to choose which locale page clap should use.
There would be two ways to implement them:

  1. Use localization index in current clap help messages, and translate them using another table. For example, the desctiption of clap app may be myapp.ui.description, but there is another table to translate myapp.ui.description and en_US into 'My Awesome App!'.
  2. Use a page based locale strings. There could be multiple ways to achieve this, but it requires large scale of code reformat to clap project.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant