mirror of
https://github.com/spf13/cobra
synced 2024-11-24 22:57:12 +00:00
feat(i18n): add translations for args validation
This commit is contained in:
parent
2e90e51710
commit
d6ed0816a9
4 changed files with 155 additions and 8 deletions
14
args.go
14
args.go
|
@ -33,7 +33,7 @@ func legacyArgs(cmd *Command, args []string) error {
|
||||||
|
|
||||||
// root command with subcommands, do subcommand checking.
|
// root command with subcommands, do subcommand checking.
|
||||||
if !cmd.HasParent() && len(args) > 0 {
|
if !cmd.HasParent() && len(args) > 0 {
|
||||||
return fmt.Errorf("unknown command %q for %q%s", args[0], cmd.CommandPath(), cmd.findSuggestions(args[0]))
|
return fmt.Errorf(i18nLegacyArgsValidationError(), args[0], cmd.CommandPath(), cmd.findSuggestions(args[0]))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ func legacyArgs(cmd *Command, args []string) error {
|
||||||
// NoArgs returns an error if any args are included.
|
// NoArgs returns an error if any args are included.
|
||||||
func NoArgs(cmd *Command, args []string) error {
|
func NoArgs(cmd *Command, args []string) error {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath())
|
return fmt.Errorf(i18nNoArgsValidationError(), args[0], cmd.CommandPath())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ func OnlyValidArgs(cmd *Command, args []string) error {
|
||||||
}
|
}
|
||||||
for _, v := range args {
|
for _, v := range args {
|
||||||
if !stringInSlice(v, validArgs) {
|
if !stringInSlice(v, validArgs) {
|
||||||
return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0]))
|
return fmt.Errorf(i18nOnlyValidArgsValidationError(), v, cmd.CommandPath(), cmd.findSuggestions(args[0]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ func ArbitraryArgs(cmd *Command, args []string) error {
|
||||||
func MinimumNArgs(n int) PositionalArgs {
|
func MinimumNArgs(n int) PositionalArgs {
|
||||||
return func(cmd *Command, args []string) error {
|
return func(cmd *Command, args []string) error {
|
||||||
if len(args) < n {
|
if len(args) < n {
|
||||||
return fmt.Errorf("requires at least %d arg(s), only received %d", n, len(args))
|
return fmt.Errorf(i18nMinimumNArgsValidationError(n), n, len(args))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ func MinimumNArgs(n int) PositionalArgs {
|
||||||
func MaximumNArgs(n int) PositionalArgs {
|
func MaximumNArgs(n int) PositionalArgs {
|
||||||
return func(cmd *Command, args []string) error {
|
return func(cmd *Command, args []string) error {
|
||||||
if len(args) > n {
|
if len(args) > n {
|
||||||
return fmt.Errorf("accepts at most %d arg(s), received %d", n, len(args))
|
return fmt.Errorf(i18nMaximumNArgsValidationError(n), n, len(args))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ func MaximumNArgs(n int) PositionalArgs {
|
||||||
func ExactArgs(n int) PositionalArgs {
|
func ExactArgs(n int) PositionalArgs {
|
||||||
return func(cmd *Command, args []string) error {
|
return func(cmd *Command, args []string) error {
|
||||||
if len(args) != n {
|
if len(args) != n {
|
||||||
return fmt.Errorf("accepts %d arg(s), received %d", n, len(args))
|
return fmt.Errorf(i18nExactArgsValidationError(n), n, len(args))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ func ExactArgs(n int) PositionalArgs {
|
||||||
func RangeArgs(min int, max int) PositionalArgs {
|
func RangeArgs(min int, max int) PositionalArgs {
|
||||||
return func(cmd *Command, args []string) error {
|
return func(cmd *Command, args []string) error {
|
||||||
if len(args) < min || len(args) > max {
|
if len(args) < min || len(args) > max {
|
||||||
return fmt.Errorf("accepts between %d and %d arg(s), received %d", min, max, len(args))
|
return fmt.Errorf(i18nRangeArgsValidationError(max), min, max, len(args))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
78
localizer.go
78
localizer.go
|
@ -35,6 +35,66 @@ func i18nError() string {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func i18nLegacyArgsValidationError() string {
|
||||||
|
return localizeMessage(&i18n.Message{
|
||||||
|
ID: "LegacyArgsValidationError",
|
||||||
|
Description: "error shown when args are not understood (subcmd, cmd, suggestion)",
|
||||||
|
Other: "unknown command %q for %q%s",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func i18nNoArgsValidationError() string {
|
||||||
|
return localizeMessage(&i18n.Message{
|
||||||
|
ID: "NoArgsValidationError",
|
||||||
|
Description: "error shown when args are present but should not (subcmd, cmd)",
|
||||||
|
Other: "unknown command %q for %q",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func i18nOnlyValidArgsValidationError() string {
|
||||||
|
return localizeMessage(&i18n.Message{
|
||||||
|
ID: "OnlyValidArgsValidationError",
|
||||||
|
Description: "error shown when arg is invalid (arg, cmd, suggestion)",
|
||||||
|
Other: "invalid argument %q for %q%s",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func i18nMinimumNArgsValidationError(amountRequired int) string {
|
||||||
|
return localizeMessageWithPlural(&i18n.Message{
|
||||||
|
ID: "MinimumNArgsValidationError",
|
||||||
|
Description: "error shown when arg count is too low (expected amount, actual amount)",
|
||||||
|
Other: "requires at least %d args, only received %d",
|
||||||
|
One: "requires at least %d arg, only received %d",
|
||||||
|
}, amountRequired)
|
||||||
|
}
|
||||||
|
|
||||||
|
func i18nMaximumNArgsValidationError(amountRequired int) string {
|
||||||
|
return localizeMessageWithPlural(&i18n.Message{
|
||||||
|
ID: "MaximumNArgsValidationError",
|
||||||
|
Description: "error shown when arg count is too low (expected amount, actual amount)",
|
||||||
|
Other: "accepts at most %d args, received %d",
|
||||||
|
One: "accepts at most %d arg, received %d",
|
||||||
|
}, amountRequired)
|
||||||
|
}
|
||||||
|
|
||||||
|
func i18nExactArgsValidationError(amountRequired int) string {
|
||||||
|
return localizeMessageWithPlural(&i18n.Message{
|
||||||
|
ID: "ExactArgsValidationError",
|
||||||
|
Description: "error shown when arg count is not exact (expected amount, actual amount)",
|
||||||
|
Other: "accepts %d args, received %d",
|
||||||
|
One: "accepts %d arg, received %d",
|
||||||
|
}, amountRequired)
|
||||||
|
}
|
||||||
|
|
||||||
|
func i18nRangeArgsValidationError(amountMax int) string {
|
||||||
|
return localizeMessageWithPlural(&i18n.Message{
|
||||||
|
ID: "RangeArgsValidationError",
|
||||||
|
Description: "error shown when arg count is not in range (expected min, expected max, actual amount)",
|
||||||
|
Other: "accepts between %d and %d args, received %d",
|
||||||
|
One: "accepts between %d and %d arg, received %d",
|
||||||
|
}, amountMax)
|
||||||
|
}
|
||||||
|
|
||||||
func i18nRunHelpTip() string {
|
func i18nRunHelpTip() string {
|
||||||
return localizeMessage(&i18n.Message{
|
return localizeMessage(&i18n.Message{
|
||||||
ID: "RunHelpTip",
|
ID: "RunHelpTip",
|
||||||
|
@ -64,6 +124,18 @@ func localizeMessage(message *i18n.Message) string {
|
||||||
return localizedValue
|
return localizedValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func localizeMessageWithPlural(message *i18n.Message, pluralCount int) string {
|
||||||
|
localizedValue, err := localizer.Localize(&i18n.LocalizeConfig{
|
||||||
|
PluralCount: pluralCount,
|
||||||
|
DefaultMessage: message,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return message.Other
|
||||||
|
}
|
||||||
|
|
||||||
|
return localizedValue
|
||||||
|
}
|
||||||
|
|
||||||
func loadTranslationFiles(bundle *i18n.Bundle, langs []string) {
|
func loadTranslationFiles(bundle *i18n.Bundle, langs []string) {
|
||||||
for _, lang := range langs {
|
for _, lang := range langs {
|
||||||
_, _ = bundle.LoadMessageFileFS(localeFS, fmt.Sprintf("translations/active.%s.toml", lang))
|
_, _ = bundle.LoadMessageFileFS(localeFS, fmt.Sprintf("translations/active.%s.toml", lang))
|
||||||
|
@ -92,7 +164,7 @@ func appendLang(langs *[]string, lang language.Tag) {
|
||||||
*langs = append(*langs, langBase.String())
|
*langs = append(*langs, langBase.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func setupLocalizer() {
|
||||||
bundle := i18n.NewBundle(defaultLanguage)
|
bundle := i18n.NewBundle(defaultLanguage)
|
||||||
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
|
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
|
||||||
detectedLangs := detectLangs()
|
detectedLangs := detectLangs()
|
||||||
|
@ -100,3 +172,7 @@ func init() {
|
||||||
loadTranslationFiles(bundle, detectedLangs)
|
loadTranslationFiles(bundle, detectedLangs)
|
||||||
localizer = i18n.NewLocalizer(bundle, detectedLangs...)
|
localizer = i18n.NewLocalizer(bundle, detectedLangs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
setupLocalizer() // FIXME: perhaps hook this somewhere else? (not init)
|
||||||
|
}
|
||||||
|
|
|
@ -2,10 +2,42 @@
|
||||||
description = "prefix of error messages"
|
description = "prefix of error messages"
|
||||||
other = "Error"
|
other = "Error"
|
||||||
|
|
||||||
|
[ExactArgsValidationError]
|
||||||
|
description = "error shown when arg count is not exact (expected amount, actual amount)"
|
||||||
|
one = "accepts %d arg, received %d"
|
||||||
|
other = "accepts %d args, received %d"
|
||||||
|
|
||||||
[ExclusiveFlagsValidationError]
|
[ExclusiveFlagsValidationError]
|
||||||
description = "error shown when multiple exclusive flags are provided (group flags, offending flags)"
|
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"
|
other = "if any flags in the group [%v] are set none of the others can be; %v were all set"
|
||||||
|
|
||||||
|
[LegacyArgsValidationError]
|
||||||
|
description = "error shown when args are not understood (subcmd, cmd, suggestion)"
|
||||||
|
other = "unknown command %q for %q%s"
|
||||||
|
|
||||||
|
[MaximumNArgsValidationError]
|
||||||
|
description = "error shown when arg count is too low (expected amount, actual amount)"
|
||||||
|
one = "accepts at most %d arg, received %d"
|
||||||
|
other = "accepts at most %d args, received %d"
|
||||||
|
|
||||||
|
[MinimumNArgsValidationError]
|
||||||
|
description = "error shown when arg count is too low (expected amount, actual amount)"
|
||||||
|
one = "requires at least %d arg, only received %d"
|
||||||
|
other = "requires at least %d args, only received %d"
|
||||||
|
|
||||||
|
[NoArgsValidationError]
|
||||||
|
description = "error shown when args are present but should not (subcmd, cmd)"
|
||||||
|
other = "unknown command %q for %q"
|
||||||
|
|
||||||
|
[OnlyValidArgsValidationError]
|
||||||
|
description = "error shown when arg is invalid (arg, cmd, suggestion)"
|
||||||
|
other = "invalid argument %q for %q%s"
|
||||||
|
|
||||||
|
[RangeArgsValidationError]
|
||||||
|
description = "error shown when arg count is not in range (expected min, expected max, actual amount)"
|
||||||
|
one = "accepts between %d and %d arg, received %d"
|
||||||
|
other = "accepts between %d and %d args, received %d"
|
||||||
|
|
||||||
[RunHelpTip]
|
[RunHelpTip]
|
||||||
description = "tip shown when a command fails (command path)"
|
description = "tip shown when a command fails (command path)"
|
||||||
other = "Run '%v --help' for usage."
|
other = "Run '%v --help' for usage."
|
||||||
|
|
|
@ -3,11 +3,50 @@ description = "prefix of error messages"
|
||||||
hash = "sha1-7dcb56355a3ddc7ff7e5ccd6522507999ca7f238"
|
hash = "sha1-7dcb56355a3ddc7ff7e5ccd6522507999ca7f238"
|
||||||
other = "Erreur"
|
other = "Erreur"
|
||||||
|
|
||||||
|
[ExactArgsValidationError]
|
||||||
|
description = "error shown when arg count is not exact (expected amount, actual amount)"
|
||||||
|
hash = "sha1-207d771f1d5dc4ed5c4094dcd29a4c80e31a6260"
|
||||||
|
one = "accepte %d arg, mais en a reçu %d"
|
||||||
|
other = "accepte %d args, mais en en reçu %d"
|
||||||
|
|
||||||
[ExclusiveFlagsValidationError]
|
[ExclusiveFlagsValidationError]
|
||||||
description = "error shown when multiple exclusive flags are provided (group flags, offending flags)"
|
description = "error shown when multiple exclusive flags are provided (group flags, offending flags)"
|
||||||
hash = "sha1-221b98bada52cfc2932f9aa5142b653b46baded6"
|
hash = "sha1-221b98bada52cfc2932f9aa5142b653b46baded6"
|
||||||
other = "les options [%v] sont exclusives, mais les options %v ont été fournies"
|
other = "les options [%v] sont exclusives, mais les options %v ont été fournies"
|
||||||
|
|
||||||
|
[LegacyArgsValidationError]
|
||||||
|
description = "error shown when args are not understood (subcmd, cmd, suggestion)"
|
||||||
|
hash = "sha1-c601c68bdcb9687109e793112b789b1858953b15"
|
||||||
|
other = "commande %q inconnue pour %q%s"
|
||||||
|
|
||||||
|
[MaximumNArgsValidationError]
|
||||||
|
description = "error shown when arg count is too low (expected amount, actual amount)"
|
||||||
|
hash = "sha1-86d71b8bc054ea8aad7006808bc9d96551052ab4"
|
||||||
|
one = "accepte au plus %d arg, mais en a reçu %d"
|
||||||
|
other = "accepte au plus %d args, mais en a reçu %d"
|
||||||
|
|
||||||
|
[MinimumNArgsValidationError]
|
||||||
|
description = "error shown when arg count is too low (expected amount, actual amount)"
|
||||||
|
hash = "sha1-7cc9093bf167d6f0601dd0763a8d3f10d71c8889"
|
||||||
|
one = "requiert au moins %d arg, mais en a reçu %d"
|
||||||
|
other = "requiert au moins %d args, mais en a reçu %d"
|
||||||
|
|
||||||
|
[NoArgsValidationError]
|
||||||
|
description = "error shown when args are present but should not (subcmd, cmd)"
|
||||||
|
hash = "sha1-551d8d237dc2ab9a853fcfbe7ef85318a0f78720"
|
||||||
|
other = "commande %q inconnue pour %q"
|
||||||
|
|
||||||
|
[OnlyValidArgsValidationError]
|
||||||
|
description = "error shown when arg is invalid (arg, cmd, suggestion)"
|
||||||
|
hash = "sha1-60b40e5782dd252c78ef3d585065cb99197ec22e"
|
||||||
|
other = "argument %q invalide pour %q%s"
|
||||||
|
|
||||||
|
[RangeArgsValidationError]
|
||||||
|
description = "error shown when arg count is not in range (expected min, expected max, actual amount)"
|
||||||
|
hash = "sha1-aa81e0aee17a3439b479cdf47169eb194706cd14"
|
||||||
|
one = "accepte entre %d et %d arg, mais en a reçu %d"
|
||||||
|
other = "accepte entre %d et %d args, mais en a reçu %d"
|
||||||
|
|
||||||
[RunHelpTip]
|
[RunHelpTip]
|
||||||
description = "tip shown when a command fails (command path)"
|
description = "tip shown when a command fails (command path)"
|
||||||
hash = "sha1-e1d2c4cccd484df365c3249347d5172981929b88"
|
hash = "sha1-e1d2c4cccd484df365c3249347d5172981929b88"
|
||||||
|
|
Loading…
Reference in a new issue