-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Support or document localization of messages and flags #380
Comments
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! |
@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 |
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. |
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! |
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. |
I am currently trying to localize my app using crowbook-intl which is pretty nice. Unfortunately, the fact that |
@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. |
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. |
This would also include localization of clap strings such |
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 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. |
@alerque See #1880 and if something like that would fit your use case if we implement it.
This might be useful outside of i18n context. I'm imagining a
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. |
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. |
@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 😉 |
The recent Rust 1.54.0 release includes a bit I think might have a huge impact on how hard this is to implement:
|
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
|
In discussing this with someone on reddit, I think users can get something working, even if it isn't streamlined yet
Would some users be willing to experiment with this within their applications and report on the results and what can be changed / improved? |
I just tried it in one of my small projects and everything worked well :) I was happy when I found that, on top of the listed methods for In my case, I had to include the If I get to do more experiments, I will comment on them. One thing that clap does well and I ended up doing by hand is formatting the (localized) help message. |
Hi, I really want to have the help strings of my program translated, and this seems to be the issue about it. |
@mleduque As my comment alludes to, I've never tried this out and don't have good use cases for trying it out and am looking for someone to pioneer this. I did update my comment with some more explicit steps. |
I've read your comment once again but I don't find where to start from. |
It sounds like some more basic information is needed and this issue is not a good place for us to have that conversation. I will also say that this isn't my focus area at this time and I'm only able to provide limited support. The one thing I will point out is that all builder methods are exposed as attributes in the derive (see reference). So you can take |
The use case it, well, the most classic there is :
Which is probably a minimum for any CLI program. |
@epage wrote:
I have experimented with this in str4d/rage#442, and successfully localized my usage and help text! See str4d/rage@b3de9b9 specifically for the localization changes (relative to what I was able to do previously before using The first issue I ran into was that passing localized
I didn't test this, as my app doesn't use subcommands.
I didn't test this, as my app doesn't use subcommands. However I did use
This was a little confusing to get working: just setting
This was somewhat confusing, as the
The help template hard-codes the "Usage" string inside the clap/clap_builder/src/output/help_template.rs Lines 199 to 206 in 2ab48b2
I copied in the contents of
I have not yet tested this, but I was already doing something similar for my own app's errors (for invalid flag combinations etc) prior to using The only other hard-coded string I noticed was the clap/clap_builder/src/output/usage.rs Lines 173 to 180 in 2ab48b2
This can be localized with |
Thanks for the detailed report! It seems the biggest issue is Options
|
Hello, could you please tell me what the current demand for localization is? Can clap support it? |
@bin-ly I've updated the issue post with the current localization instructions based on the work of str4d |
Hey all, I made a draft PR of an approach to enabling internationlization clap: #5853 Take a look and let me know what you think. It's just a minimal example to demonstrate the approach, but if it looks good I'd be happy to put in some time to polish it up. |
From #5852
As shown in this issue, we are most of the way there to allowing people to override existing strings inside of clap. |
Yes, lets please not move towards a besoke YAML key/value based localization system. It is easy to get off the ground that way but in will quickly become a problem for projects wanting to do a better job or with more complex needs. Good localization is hard even for relatively simple cases, and there is good tooling out there for it. This should be refactored to use Fluent (or possibly one of the Fluent based systems that allow generating static localizations), or just provide an interface that people can bring their own localization framework). Any project localizing their CLI args probably also has other localization needs and probably already has Fluent assets or some other framework that can be leveraged for this purpose. |
Make it easy for developers to support translations of their projects.
Current steps:
cargo add clap -F string
#[arg(value_name = ...)]
Commands:
header with a localized value viaCommand::subcommand_help_heading
<COMMAND>
value name with a localized value viaCommand::subcommand_value_name
Arguments
andOptions:
headers with localized values viaCommand::next_help_heading
and/orArg::help_heading
Command::disable_help_flag(false)
andCommand::disable_version_flag(false)
) and provide your own versions (withArgAction::Help
,ArgAction::Version
) with localizedArg::help
Usage
) with a localized version viaCommand::help_template
Usage
manually[]
messages with Arg::hide_default_value, Arg::hide_possible_values, Arg::hide_envclap::error::RichFormatter
, replacing any hard coded strings with localized values. UseError::apply
to swap the formatter (e.g. useParser::try_parse
to get the error, callapply
, and thenerr.exit()
)[OPTIONS]
by providing a custom usage withCommand::override_usage
Unresolved:
--help
in errors, see How to make custom -h achieve the same effect as default -h #5409Past examples:
clap
, and localize usage & help text str4d/rage#442The text was updated successfully, but these errors were encountered: