diff --git a/builtin/myplugin/command/dothing.go b/builtin/myplugin/command/dothing.go index 0496092ae..0662e7dc3 100644 --- a/builtin/myplugin/command/dothing.go +++ b/builtin/myplugin/command/dothing.go @@ -3,7 +3,10 @@ package command import ( "github.com/hashicorp/vagrant-plugin-sdk/component" "github.com/hashicorp/vagrant-plugin-sdk/docs" + "github.com/hashicorp/vagrant-plugin-sdk/localizer" "github.com/hashicorp/vagrant-plugin-sdk/terminal" + "github.com/hashicorp/vagrant/builtin/myplugin/locales" + "golang.org/x/text/language" ) // DoThing is a Command implementation for myplugin @@ -79,8 +82,35 @@ func (c *DoThing) Flags() component.CommandFlags { } func (c *DoThing) Execute(trm terminal.UI, params *component.CommandParams) int32 { - trm.Output("Tricked ya! I actually do nothing :P") - trm.Output("You gave me the stringflag: " + params.Flags["stringflag"].(string)) + localeDataEN, err := locales.Asset("locales/assets/en.json") + if err != nil { + return 1 + } + localeDataES, err := locales.Asset("locales/assets/es.json") + if err != nil { + return 1 + } + d := []localizer.LocaleData{ + { + LocaleData: localeDataEN, + LocalePath: "locales/assets/en.json", + Languages: []language.Tag{language.English, language.AmericanEnglish, language.BritishEnglish}, + }, + { + LocaleData: localeDataES, + LocalePath: "locales/assets/es.json", + Languages: []language.Tag{language.Spanish}, + }, + } + l, err := localizer.NewPluginLocalizer(trm, d...) + if err != nil { + return 1 + } + err = l.Output("dothing", nil) + if err != nil { + trm.Output(err.Error()) + return 1 + } return 0 } diff --git a/builtin/myplugin/locales/assets/en.json b/builtin/myplugin/locales/assets/en.json new file mode 100644 index 000000000..b93885e87 --- /dev/null +++ b/builtin/myplugin/locales/assets/en.json @@ -0,0 +1,3 @@ +{ + "dothing": "Tricked ya! I actually do nothing :P" +} diff --git a/builtin/myplugin/locales/assets/es.json b/builtin/myplugin/locales/assets/es.json new file mode 100644 index 000000000..deaa93fe5 --- /dev/null +++ b/builtin/myplugin/locales/assets/es.json @@ -0,0 +1,3 @@ +{ + "dothing": "¡Te engañé! en realidad no hago nada :P" +} diff --git a/builtin/myplugin/locales/locales.go b/builtin/myplugin/locales/locales.go new file mode 100644 index 000000000..65a6cf7b2 --- /dev/null +++ b/builtin/myplugin/locales/locales.go @@ -0,0 +1,271 @@ +// Code generated for package locales by go-bindata DO NOT EDIT. (@generated) +// sources: +// locales/assets/en.json +// locales/assets/es.json +package locales + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// Mode return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _localesAssetsEnJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xaa\xe6\x52\x50\x50\x4a\xc9\x2f\xc9\xc8\xcc\x4b\x57\xb2\x52\x50\x0a\x29\xca\x4c\xce\x4e\x4d\x51\xa8\x4c\x54\x54\xf0\x54\x48\x4c\x2e\x29\x4d\xcc\xc9\xa9\x54\x48\xc9\x57\xc8\x83\x28\x52\xb0\x0a\x50\xe2\xaa\xe5\x02\x04\x00\x00\xff\xff\xae\xf3\xa3\xbd\x38\x00\x00\x00") + +func localesAssetsEnJsonBytes() ([]byte, error) { + return bindataRead( + _localesAssetsEnJson, + "locales/assets/en.json", + ) +} + +func localesAssetsEnJson() (*asset, error) { + bytes, err := localesAssetsEnJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "locales/assets/en.json", size: 56, mode: os.FileMode(420), modTime: time.Unix(1651259149, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _localesAssetsEsJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xaa\xe6\x52\x50\x50\x4a\xc9\x2f\xc9\xc8\xcc\x4b\x57\xb2\x52\x50\x3a\xb4\x30\x24\x55\x21\x35\x2f\x3d\xf1\xf0\xc6\xc3\x2b\x15\x15\x52\xf3\x14\x8a\x52\x13\x73\x32\x53\x12\x53\x14\xf2\xf2\x15\x32\x12\xd3\xf3\x15\xf2\x12\x53\x12\x15\xac\x02\x94\xb8\x6a\xb9\x00\x01\x00\x00\xff\xff\xe5\x85\x54\x9c\x3e\x00\x00\x00") + +func localesAssetsEsJsonBytes() ([]byte, error) { + return bindataRead( + _localesAssetsEsJson, + "locales/assets/es.json", + ) +} + +func localesAssetsEsJson() (*asset, error) { + bytes, err := localesAssetsEsJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "locales/assets/es.json", size: 62, mode: os.FileMode(420), modTime: time.Unix(1651262545, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "locales/assets/en.json": localesAssetsEnJson, + "locales/assets/es.json": localesAssetsEsJson, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "locales": &bintree{nil, map[string]*bintree{ + "assets": &bintree{nil, map[string]*bintree{ + "en.json": &bintree{localesAssetsEnJson, map[string]*bintree{}}, + "es.json": &bintree{localesAssetsEsJson, map[string]*bintree{}}, + }}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/builtin/myplugin/main.go b/builtin/myplugin/main.go index 97ff56e8b..a20c91851 100644 --- a/builtin/myplugin/main.go +++ b/builtin/myplugin/main.go @@ -10,6 +10,9 @@ import ( //go:generate protoc -I ../../.. --go_opt=plugins=grpc --go_out=../../.. vagrant-ruby/builtin/myplugin/proto/plugin.proto +// Locales data bundling +//go:generate go-bindata -o ./locales/locales.go -pkg locales locales/assets + // Options are the SDK options to use for instantiation. var CommandOptions = []sdk.Option{ sdk.WithComponents( diff --git a/builtin/myplugin/proto/plugin.pb.go b/builtin/myplugin/proto/plugin.pb.go index 6518fd246..0b2273210 100644 --- a/builtin/myplugin/proto/plugin.pb.go +++ b/builtin/myplugin/proto/plugin.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.15.8 +// protoc v3.19.4 // source: vagrant-ruby/builtin/myplugin/proto/plugin.proto package proto diff --git a/go.mod b/go.mod index 0090bc5a7..7faf31bbf 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl/v2 v2.7.1-0.20201023000745-3de61ecba298 github.com/hashicorp/nomad/api v0.0.0-20200814140818-42de70466a9d - github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220429182128-d57b4f4e1606 + github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220513172229-62750f6e1ce7 github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce // indirect github.com/imdario/mergo v0.3.11 github.com/improbable-eng/grpc-web v0.13.0 @@ -84,12 +84,12 @@ require ( golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c + golang.org/x/text v0.3.7 golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect google.golang.org/api v0.60.0 // indirect google.golang.org/genproto v0.0.0-20211116182654-e63d96a377c4 google.golang.org/grpc v1.42.0 google.golang.org/protobuf v1.27.1 - gopkg.in/yaml.v2 v2.3.0 // indirect gotest.tools/v3 v3.0.2 // indirect k8s.io/api v0.18.0 k8s.io/apimachinery v0.18.0 diff --git a/go.sum b/go.sum index 0a2baefe6..17acc5449 100644 --- a/go.sum +++ b/go.sum @@ -49,6 +49,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= +github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/LK4D4/joincontext v0.0.0-20171026170139-1724345da6d5 h1:U7q69tqXiCf6m097GRlNQB0/6SI1qWIOHYHhCEvDxF4= @@ -353,18 +355,8 @@ github.com/hashicorp/hcl/v2 v2.7.1-0.20201023000745-3de61ecba298 h1:pLsdnvAlWuZ9 github.com/hashicorp/hcl/v2 v2.7.1-0.20201023000745-3de61ecba298/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY= github.com/hashicorp/nomad/api v0.0.0-20200814140818-42de70466a9d h1:afuZ/KNbxwUgjEzq2NXO2bRKZgsIJQgFxgIRGETF0/A= github.com/hashicorp/nomad/api v0.0.0-20200814140818-42de70466a9d/go.mod h1:DCi2k47yuUDzf2qWAK8E1RVmWgz/lc0jZQeEnICTxmY= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220413221234-5a2ea827c231 h1:sav2Rd47P0b7Q1QTL3ptGkLqUph8z3OAcG6FzxAN8gk= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220413221234-5a2ea827c231/go.mod h1:AagbbSR/HMGxUYevXHeUxi2mRoBptRG1gtJnR/qnxt4= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220415142437-b1ba1997074b h1:nFiqe4GaqFvAF3erknpFc/Yn/KYdaqjiOL+dOE/oF60= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220415142437-b1ba1997074b/go.mod h1:AagbbSR/HMGxUYevXHeUxi2mRoBptRG1gtJnR/qnxt4= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220421183549-595b2c45b428 h1:EMa9XxpBROw+UEbCIDcS+HmyboU2HB/KvB4F8FoEPdA= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220421183549-595b2c45b428/go.mod h1:AagbbSR/HMGxUYevXHeUxi2mRoBptRG1gtJnR/qnxt4= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220425220513-71bbd1c1237a h1:8nvqkl3fl88gjPlL+ygPO8lEiaeslk+fNpod1KDyRDc= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220425220513-71bbd1c1237a/go.mod h1:AagbbSR/HMGxUYevXHeUxi2mRoBptRG1gtJnR/qnxt4= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220428165417-47b0f98908ec h1:Xrn9wsDaoqjBcfWitoISlt0r1e3ZA+hroNi2i7dlrh0= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220428165417-47b0f98908ec/go.mod h1:xOBGSu24lRHmLlm459L6lrQKge92IGwJiOcXkC6WM74= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220429182128-d57b4f4e1606 h1:+vvXuMpYW3AE0fZMJFSe8kZmlrQclyIVuq2lTv0OYag= -github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220429182128-d57b4f4e1606/go.mod h1:xOBGSu24lRHmLlm459L6lrQKge92IGwJiOcXkC6WM74= +github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220513172229-62750f6e1ce7 h1:4d/nNs0gKLHkm9Ra/bdQTvxWSz0ctvwaOUFrZD/4pN4= +github.com/hashicorp/vagrant-plugin-sdk v0.0.0-20220513172229-62750f6e1ce7/go.mod h1:KWfWOiotOWKiAqdroXVc7GUFnuOzlzhnRkGTV9Js7/s= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce h1:7UnVY3T/ZnHUrfviiAgIUjg2PXxsQfs5bphsG8F7Keo= github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= @@ -476,6 +468,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/natefinch/atomic v0.0.0-20200526193002-18c0533a5b09 h1:DXR0VtCesBD2ss3toN9OEeXszpQmW9dc3SvUbUfiBC0= github.com/natefinch/atomic v0.0.0-20200526193002-18c0533a5b09/go.mod h1:1rLVY/DWf3U6vSZgH16S7pymfrhK2lcUlXjgGglw/lY= +github.com/nicksnyder/go-i18n/v2 v2.2.0 h1:MNXbyPvd141JJqlU6gJKrczThxJy+kdCNivxZpBQFkw= +github.com/nicksnyder/go-i18n/v2 v2.2.0/go.mod h1:4OtLfzqyAxsscyCb//3gfqSvBc81gImX91LrZzczN1o= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=