Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 39 additions & 13 deletions docs/plugin_developer_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,28 @@ IBM Cloud CLI SDK provides a set of APIs to register and manage plug-ins. It als
Build: 0,
},
MinCliVersion: plugin.VersionType{
Major: 0,
Major: 2,
Minor: 0,
Build: 1,
Build: 0,
},

PrivateEndpointSupported: true,

IsCobraPlugin: true,

Namespaces: []plugin.Namespace{
{
Name: "demo-plugin",
}
},

Commands: []plugin.Command{
{
Namespace: "demo-plugin",
Name: "echo",
Alias: "ec",
Aliases: []{"ec"},
Description: "Echo a message on terminal.",
Usage: "ibmcloud echo MESSAGE [-u]",
Usage: "ibmcloud demo-plugin echo MESSAGE [-u]",
Flags: []plugin.Flag{
{
Name: "u",
Expand All @@ -73,18 +80,37 @@ IBM Cloud CLI SDK provides a set of APIs to register and manage plug-ins. It als
```

**Understanding the fields in this `plugin.PluginMetadata` struct:**
- _Name_: The name of plug-in. It will be displayed when using `ibmcloud plugin list` command or can be used to uninstall the plug-in through `ibmcloud plugin uninstall` command.
- _Name_ (**required**): The name of plug-in. It will be displayed when using `ibmcloud plugin list` command or can be used to uninstall the plug-in through `ibmcloud plugin uninstall` command.
- It is **strongly** encouraged to use a name that best describes the service the plug-in provides.
- _Aliases_: A list of short names of the plug-in that can be used as a stand-in for installing, updating, uninstalling and using the plug-in.
- _Aliases_ (*optional*): A list of short names of the plug-in that can be used as a stand-in for installing, updating, uninstalling and using the plug-in.
- It is strongly recommended that you have at least one alias to improve the usability of the plug-in.
- _Version_: The version of plug-in.
- _MinCliVersion_: The minimal version of IBM Cloud CLI required by the plug-in.
- _PrivateEndpointSupported_: Indicates if the plug-in is designed to also be used over the private network.
- _IsCobraPlugin_: Indicates if the plug-in is built using the Cobra framework.
- _Version_ (**required**): The version of plug-in.
- _MinCliVersion_ (**required**): The minimal version of IBM Cloud CLI required by the plug-in.
- _PrivateEndpointSupported_ (*optional*): Indicates if the plug-in is designed to also be used over the private network.
- _IsCobraPlugin_ (*optional*): Indicates if the plug-in is built using the Cobra framework.
- It is **strongly** recommended that you use this framework to build your plug-in.
- _Commands_: The array of `plugin.Commands` to register the plug-in commands.
- _Alias_: Alias of the Alias usually is a short name of the command.
- _Command.Flags_: The command flags (options) which will be displayed as a part of help output of the command.
- _Alias_ (*optional*): Alias of the Alias usually is a short name of the command.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alias of the Alias does not make sense. This pre-existed this PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah let me fix that here.

- _Namespaces[]_ (**required**): The list of namespaces / categories that group commands of similar functionality. A command under a namespace is run using `ibmcloud [namespace] [command]`. Visit [1.2 Namespaces](#12-namespace) for more information.
- _Namespaces[].ParentName_ (*optional*): The fully qualified name of the parent namespace
- _Namespaces[].Name_ (**required**): The base name of the namespace
- _Namespaces[].Aliases_ (*optional*): A list of aliases for the namespace
- _Namespaces[].Description_ (*optional*): The description of the namespace
- _Namespaces[].Stage_ (*optional*): The stage of the commands in the namespace
- _Commands[]_ (**required**): The array of `plugin.Commands` to register the plug-in commands. At least one command must be registered.
- _Commands[].Name_ (**required**): The name of the command
- _Commands[].Aliases[]_ (*optional*): A list of short names to be used as a stand-in for calling the command.
- _Commands[].Description_ (**required**): A short description of the command. Details on flags and arguments should be placed in **Usage** below.
- _Commands[].Usage_ (**required**): The usage text to be displayed in the command help
- _Commands[].Flags_(*optional*): The command flags (options) which will be displayed as a part of help output of the command.
- _Commands[].Flags[].Name_ (**required**): The name of the optional flag
- _Commands[].Flags[].Description_ (**required**): The description of the optional flag
- _Commands[].Flags[].HasValue_ (*optional*): True, if the optional flag requires a value (eg.`--description "foobar"`)
- _Commands[].Flags[].Hidden_ (optional): True, to hide the optional flag should be hidden in the command help
- _Commands[].Hidden_ (*optional*): True, to hide the command in the root namespace help command
- _Commands[].Stage_ (*optional*): The stage of the command




4. Add the logic of plug-in command process in `Run` method, for example:

Expand Down
18 changes: 12 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
module github.com/IBM-Cloud/ibm-cloud-cli-sdk

go 1.23.0
go 1.24.0

toolchain go1.24.4

require (
github.com/Masterminds/semver v1.5.0
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Callout: Used to validate against the provided min CLI version defined in the metadata and the allowed min CLI version. The package is used in the core CLI.

github.com/fatih/color v1.7.1-0.20180516100307-2d684516a886
github.com/fatih/structs v1.0.1-0.20171020064819-f5faa72e7309
github.com/go-playground/validator/v10 v10.28.0
Copy link
Collaborator Author

@Aerex Aerex Oct 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Callout: This package is validation library to support validation using struct tags.

Widely used package under the MIT license. Over 200+ contributors and the last release was 4 days ago.

github.com/gofrs/flock v0.8.1
github.com/google/uuid v1.6.0
github.com/jedib0t/go-pretty/v6 v6.6.1
Expand All @@ -17,22 +19,26 @@ require (
github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4
golang.org/x/crypto v0.36.0
golang.org/x/term v0.30.0
golang.org/x/text v0.23.0
golang.org/x/crypto v0.42.0
golang.org/x/term v0.35.0
golang.org/x/text v0.29.0
gopkg.in/cheggaaa/pb.v1 v1.0.15
gopkg.in/yaml.v2 v2.4.0
)

require (
github.com/BurntSushi/toml v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/sys v0.36.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
38 changes: 26 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.7.1-0.20180516100307-2d684516a886 h1:NAFoy+QgUpERgK3y1xiVh5HcOvSeZHpXTTo5qnvnuK4=
github.com/fatih/color v1.7.1-0.20180516100307-2d684516a886/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v1.0.1-0.20171020064819-f5faa72e7309 h1:e3z/5nE0uPKuqOc75vXcdV513niF/KDgDddVC8eF9MM=
github.com/fatih/structs v1.0.1-0.20171020064819-f5faa72e7309/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
Expand All @@ -24,6 +36,8 @@ github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7P
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jedib0t/go-pretty/v6 v6.6.1 h1:iJ65Xjb680rHcikRj6DSIbzCex2huitmc7bDtxYVWyc=
github.com/jedib0t/go-pretty/v6 v6.6.1/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-colorable v0.0.0-20160210001857-9fdad7c47650 h1:pwtfAm8Do0gwFJ2J+iUrEVR9qI03BpDSuDQCIqbd6iY=
github.com/mattn/go-colorable v0.0.0-20160210001857-9fdad7c47650/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035 h1:USWjF42jDCSEeikX/G1g40ZWnsPXN5WkZ4jMHZWyBK4=
Expand All @@ -47,20 +61,20 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.15 h1:1WP0I1XIkfylrOuo3YeOAt4QXsvESM1enkg3vH6FDmI=
Expand Down
44 changes: 36 additions & 8 deletions i18n/resources/all.de_DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,40 @@
},
{
"id": "Could not read from input: ",
"translation": "Could not read from input: "
"translation": "Lesen der Eingabedaten nicht möglich: "
},
{
"id": "Elapsed:",
"translation": "Verstrichen:"
},
{
"id": "External authentication failed. Error code: {{.ErrorCode}}, message: {{.Message}}",
"translation": "External authentication failed. Error code: {{.ErrorCode}}, message: {{.Message}}"
"translation": "Die externe Authentifizierung ist fehlgeschlagen. Fehlercode: {{.ErrorCode}}, Meldung: {{.Message}}"
},
{
"id": "FAILED",
"translation": "FEHLGESCHLAGEN"
},
{
"id": "Failed, header could not convert to csv format",
"translation": "Failed, header could not convert to csv format"
"translation": "Fehlgeschlagen, Header konnte nicht in das csv-Format konvertiert werden"
},
{
"id": "Failed, rows could not convert to csv format",
"translation": "Failed, rows could not convert to csv format"
"translation": "Fehlgeschlagen, Zeilen konnten nicht in das csv-Format konvertiert werden"
},
{
"id": "Invalid grant type: ",
"translation": "Invalid grant type: "
"translation": "Ungültiger Grant-Typ: "
},
{
"id": "Invalid token: ",
"translation": "Ungültiges Token: "
},
{
"id": "MinCliVersion ({{.ProvidedMinVersion}}) is lower than the allowed minimum {{.AllowedMinimum}}",
"translation": "MinCliVersion ( {{.ProvidedMinVersion}} ) niedriger ist als das zulässige Minimum {{.AllowedMinimum}}"
},
{
"id": "OK",
"translation": "OK"
Expand Down Expand Up @@ -83,12 +87,36 @@
"id": "Remote server error. Status code: {{.StatusCode}}, error code: {{.ErrorCode}}, message: {{.Message}}",
"translation": "Fehler auf dem fernen Server. Statuscode: {{.StatusCode}}, Fehlercode: {{.ErrorCode}}, Nachricht: {{.Message}}"
},
{
"id": "Session inactive: ",
"translation": "Sitzung inaktiv: "
},
{
"id": "Unable to save plugin config: ",
"translation": "Speichern der Plug-in-Konfiguration nicht möglich: "
},
{
"id": "Session inactive: ",
"translation": "Session inactive: "
"id": "Usage contains placeholder arguments/flags",
"translation": "Verwendung enthält Platzhalterargumente/Flags"
},
{
"id": "Usage contains unclosed {{.UnclosedGroup}} between indicies {{.Indicies}}",
"translation": "Die Verwendung enthält nicht geschlossene {{.UnclosedGroup}} zwischen den Indikatoren {{.Indicies}}"
},
{
"id": "{{.Field}} contains the following forbidden characters: {{.Chars}}",
"translation": "{{.Field}} enthält die folgenden verbotenen Zeichen: {{.Chars}}"
},
{
"id": "{{.Field}} is required",
"translation": "{{.Field}} ist erforderlich"
},
{
"id": "{{.Field}} must contain at least {{.Param}} element",
"translation": "{{.Field}} muss mindestens das Element {{.Param}} enthalten"
},
{
"id": "{{.Field}} must not equal '{{.Param}}'",
"translation": "{{.Field}} darf nicht gleich ' {{.Param}} ' sein"
}
]
]
34 changes: 31 additions & 3 deletions i18n/resources/all.en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
"id": "Invalid token: ",
"translation": "Invalid token: "
},
{
"id": "MinCliVersion ({{.ProvidedMinVersion}}) is lower than the allowed minimum {{.AllowedMinimum}}",
"translation": "MinCliVersion ({{.ProvidedMinVersion}}) is lower than the allowed minimum {{.AllowedMinimum}}"
},
{
"id": "OK",
"translation": "OK"
Expand Down Expand Up @@ -83,12 +87,36 @@
"id": "Remote server error. Status code: {{.StatusCode}}, error code: {{.ErrorCode}}, message: {{.Message}}",
"translation": "Remote server error. Status code: {{.StatusCode}}, error code: {{.ErrorCode}}, message: {{.Message}}"
},
{
"id": "Session inactive: ",
"translation": "Session inactive: "
},
{
"id": "Unable to save plugin config: ",
"translation": "Unable to save plugin config: "
},
{
"id": "Session inactive: ",
"translation": "Session inactive: "
"id": "Usage contains placeholder arguments/flags",
"translation": "Usage contains placeholder arguments/flags"
},
{
"id": "Usage contains unclosed {{.UnclosedGroup}} between indicies {{.Indicies}}",
"translation": "Usage contains unclosed {{.UnclosedGroup}} between indicies {{.Indicies}}"
},
{
"id": "{{.Field}} contains the following forbidden characters: {{.Chars}}",
"translation": "{{.Field}} contains the following forbidden characters: {{.Chars}}"
},
{
"id": "{{.Field}} is required",
"translation": "{{.Field}} is required"
},
{
"id": "{{.Field}} must contain at least {{.Param}} element",
"translation": "{{.Field}} must contain at least {{.Param}} element"
},
{
"id": "{{.Field}} must not equal '{{.Param}}'",
"translation": "{{.Field}} must not equal '{{.Param}}'"
}
]
]
Loading