-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Multi-language support for CLIs? #1134
Comments
Are you talking about if there is multi-language support for default help message in Cobra? |
Yes and I've already checked the source code, where strings are encapsulated in the UsageTemplate. The way to go seems to change the usage template with SetUsageTemplate. If I have enough time, would it be of interest to include a small example in the docs? |
This issue is being marked as stale due to a long period of inactivity |
@thomasgloe I'd be interested to see a PR for this if you wanted to take a shot at it. |
This issue is being marked as stale due to a long period of inactivity |
This issue is being marked as stale due to a long period of inactivity |
I use |
I've reviewed cobra these past days (using it for git spend), and I've come to the conclusion that cobra itself should have some form of i18n for default content. I'm glad you're not against it for arcane reasons :) – it's just work, and this I understand. There are some decisions that are best discussed beforehand, though. Choosing a translation file formatI'm partial to Embedding
|
Here's a draft of what it would look like:
package cobra
import (
"embed"
"fmt"
"github.com/BurntSushi/toml"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/text/language"
)
var defaultLanguage = language.English
// localeFS points to an embedded filesystem of TOML translation files
//
//go:embed translations/*.toml
var localeFS embed.FS
// Localizer can be used to fetch localized messages
var localizer *i18n.Localizer
func i18nError() string {
return localizeMessage(&i18n.Message{
ID: "Error",
Description: "prefix of error messages",
Other: "Error",
})
}
func i18nExclusiveFlagsValidationError() string {
return localizeMessage(&i18n.Message{
ID: "ExclusiveFlagsValidationError",
Description: "error shown when multiple exclusive flags are provided (group flags, offending flags)",
Other: "if any flags in the group [%v] are set none of the others can be; %v were all set",
})
}
// … lots more translations here
func localizeMessage(message *i18n.Message) string {
localizedValue, err := localizer.Localize(&i18n.LocalizeConfig{
DefaultMessage: message,
})
if err != nil {
return message.Other
}
return localizedValue
}
func loadTranslationFiles(bundle *i18n.Bundle, langs []string) {
for _, lang := range langs {
_, _ = bundle.LoadMessageFileFS(localeFS, fmt.Sprintf("translations/main.%s.toml", lang))
}
}
func init() {
bundle := i18n.NewBundle(defaultLanguage)
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
// FIXME: detect lang(s) from env (LANGUAGE > LC_ALL > LANG)
detectedLangs := []string{
"fr",
"en",
}
loadTranslationFiles(bundle, detectedLangs)
localizer = i18n.NewLocalizer(bundle, detectedLangs...)
}
|
Draft continues in the
|
What about using gotext instead? It does not as verbose code as go-i18n, and you can use a simple wrapper function like you have show and gotext still manages to extract the texts. Translation foles are JSON, not TOML, though. But I think they are still rather easy to handle. |
Thanks for the suggestion, @phw . Here's what the goi18n lib says it provides :
All in all, I don't mind ditching the goi18n lib, but :
|
Just to avoid confusion further down (@Goutte understood me correctly): I was referring to
There will be a translation string like It is limited to the JSON format though, and it also has this a bit convoluted concept with separate If you want to go the gettext route have a look at https://github.com/leonelquinteros/gotext . This is also a gettext implementation. Pure go, so no actual dependency on gettext libraries. It also provides an extraction tool github.com/leonelquinteros/gotext/cli/xgotext . I haven't used it yet, but it looks nice. What originally discouraged me from using it was that it does not directly provide the option to load the translation files from go:embed. But according to the discussion at leonelquinteros/gotext#52 the library's API is flexible enough to allow this. With gettext you definitely get the best tooling for translators. What I really dislike about github.com/nicksnyder/go-i18n is the verbosity it requires for each translatable string without the ability to add an abstraction over this that fits your application (at least not without breaking string extraction, which I consider mandatory to have). |
Just saw that this is actually using github.com/leonelquinteros/gotext, but adds the ability to embed the translation files on top. |
Thanks @phw for the clarifications ! I think you're right, it's worth implementing this your way. I'll start another branch with the ubuntu lib, unless you want to hack around and kickstart things. One thing I really don't understand about If I understand correctly, those are essentially removed at compile-time since nothing will link to them, but still... Does not feel right. |
Ooops. The ubuntu lib requires Go I'll try to shoot straight for https://github.com/leonelquinteros/gotext and some glue for embedded PO files. |
A few notes after hacking around with
|
I would like to support multiple languages for my CLI using cobra. Implementation for commands is no problem, but is it correct that there is currently no support for the text output generated by cobra itself (e.g., "Usage", "Flags", "Use "mycmd [command] --help" for more information about a command.")?
The text was updated successfully, but these errors were encountered: