mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 18:28:13 +00:00 
			
		
		
		
	Switch to v1.0.2 of github.com/chai2010/gettext-go
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
This commit is contained in:
		
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							| @@ -148,7 +148,7 @@ require ( | ||||
| 	github.com/beorn7/perks v1.0.1 // indirect | ||||
| 	github.com/boltdb/bolt v1.3.1 // indirect | ||||
| 	github.com/cespare/xxhash/v2 v2.1.2 // indirect | ||||
| 	github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect | ||||
| 	github.com/chai2010/gettext-go v1.0.2 // indirect | ||||
| 	github.com/checkpoint-restore/go-criu/v5 v5.3.0 // indirect | ||||
| 	github.com/cilium/ebpf v0.7.0 // indirect | ||||
| 	github.com/containerd/cgroups v1.0.1 // indirect | ||||
| @@ -306,7 +306,7 @@ replace ( | ||||
| 	github.com/census-instrumentation/opencensus-proto => github.com/census-instrumentation/opencensus-proto v0.2.1 | ||||
| 	github.com/certifi/gocertifi => github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 | ||||
| 	github.com/cespare/xxhash/v2 => github.com/cespare/xxhash/v2 v2.1.2 | ||||
| 	github.com/chai2010/gettext-go => github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 | ||||
| 	github.com/chai2010/gettext-go => github.com/chai2010/gettext-go v1.0.2 | ||||
| 	github.com/checkpoint-restore/go-criu/v5 => github.com/checkpoint-restore/go-criu/v5 v5.3.0 | ||||
| 	github.com/chzyer/logex => github.com/chzyer/logex v1.1.10 | ||||
| 	github.com/chzyer/readline => github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e | ||||
|   | ||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							| @@ -76,8 +76,8 @@ github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5P | ||||
| github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= | ||||
| github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= | ||||
| github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | ||||
| github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= | ||||
| github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= | ||||
| github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= | ||||
| github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= | ||||
| github.com/checkpoint-restore/go-criu/v5 v5.3.0 h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8= | ||||
| github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= | ||||
| github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= | ||||
|   | ||||
| @@ -6,7 +6,7 @@ go 1.18 | ||||
|  | ||||
| require ( | ||||
| 	github.com/MakeNowJust/heredoc v1.0.0 | ||||
| 	github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 | ||||
| 	github.com/chai2010/gettext-go v1.0.2 | ||||
| 	github.com/davecgh/go-spew v1.1.1 | ||||
| 	github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd | ||||
| 	github.com/docker/distribution v2.8.1+incompatible | ||||
|   | ||||
							
								
								
									
										4
									
								
								staging/src/k8s.io/kubectl/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								staging/src/k8s.io/kubectl/go.sum
									
									
									
										generated
									
									
									
								
							| @@ -58,8 +58,8 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l | ||||
| github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= | ||||
| github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= | ||||
| github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= | ||||
| github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= | ||||
| github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= | ||||
| github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= | ||||
| github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= | ||||
| github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= | ||||
| github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= | ||||
| github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= | ||||
|   | ||||
| @@ -25,7 +25,7 @@ import ( | ||||
| 	"os" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/chai2010/gettext-go/gettext" | ||||
| 	gettext "github.com/chai2010/gettext-go" | ||||
| 	"k8s.io/klog/v2" | ||||
| ) | ||||
|  | ||||
|   | ||||
							
								
								
									
										5
									
								
								vendor/github.com/chai2010/gettext-go/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/chai2010/gettext-go/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| language: go | ||||
|  | ||||
| go: | ||||
|   - "1.14" | ||||
|   - tip | ||||
							
								
								
									
										191
									
								
								vendor/github.com/chai2010/gettext-go/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/chai2010/gettext-go/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| - *赞助 BTC: 1Cbd6oGAUUyBi7X7MaR4np4nTmQZXVgkCW* | ||||
| - *赞助 ETH: 0x623A3C3a72186A6336C79b18Ac1eD36e1c71A8a6* | ||||
| - *Go语言付费QQ群: 1055927514* | ||||
|  | ||||
| ---- | ||||
|  | ||||
| # gettext-go: GNU gettext for Go ([Imported By Kubernetes](https://pkg.go.dev/github.com/chai2010/gettext-go@v0.1.0/gettext?tab=importedby)) | ||||
|  | ||||
| - PkgDoc: [http://godoc.org/github.com/chai2010/gettext-go](http://godoc.org/github.com/chai2010/gettext-go) | ||||
| - PkgDoc: [http://pkg.go.dev/github.com/chai2010/gettext-go](http://pkg.go.dev/github.com/chai2010/gettext-go) | ||||
|  | ||||
| ## Install | ||||
|  | ||||
| 1. `go get github.com/chai2010/gettext-go` | ||||
| 2. `go run hello.go` | ||||
|  | ||||
| The godoc.org or go.dev has more information. | ||||
|  | ||||
| ## Examples | ||||
|  | ||||
| ```Go | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/chai2010/gettext-go" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	gettext := gettext.New("hello", "./examples/locale").SetLanguage("zh_CN") | ||||
| 	fmt.Println(gettext.Gettext("Hello, world!")) | ||||
|  | ||||
| 	// Output: 你好, 世界! | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```Go | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/chai2010/gettext-go" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	gettext.SetLanguage("zh_CN") | ||||
| 	gettext.BindLocale(gettext.New("hello", "locale")) | ||||
|  | ||||
| 	// gettext.BindLocale("hello", "locale")              // from locale dir | ||||
| 	// gettext.BindLocale("hello", "locale.zip")          // from locale zip file | ||||
| 	// gettext.BindLocale("hello", "locale.zip", zipData) // from embedded zip data | ||||
|  | ||||
| 	// translate source text | ||||
| 	fmt.Println(gettext.Gettext("Hello, world!")) | ||||
| 	// Output: 你好, 世界! | ||||
|  | ||||
| 	// if no msgctxt in PO file (only msgid and msgstr), | ||||
| 	// specify context as "" by | ||||
| 	fmt.Println(gettext.PGettext("", "Hello, world!")) | ||||
| 	// Output: 你好, 世界! | ||||
|  | ||||
| 	// translate resource | ||||
| 	fmt.Println(string(gettext.Getdata("poems.txt")))) | ||||
| 	// Output: ... | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Go file: [hello.go](https://github.com/chai2010/gettext-go/blob/master/examples/hello.go); PO file: [hello.po](https://github.com/chai2010/gettext-go/blob/master/examples/locale/default/LC_MESSAGES/hello.po); | ||||
|  | ||||
| ---- | ||||
|  | ||||
| ## API Changes (v0.1.0 vs v1.0.0) | ||||
|  | ||||
| ### Renamed package path | ||||
|  | ||||
| | v0.1.0 (old)                                    | v1.0.0 (new)                            | | ||||
| | ----------------------------------------------- | --------------------------------------- | | ||||
| | `github.com/chai2010/gettext-go/gettext`        | `github.com/chai2010/gettext-go`        | | ||||
| | `github.com/chai2010/gettext-go/gettext/po`     | `github.com/chai2010/gettext-go/po`     | | ||||
| | `github.com/chai2010/gettext-go/gettext/mo`     | `github.com/chai2010/gettext-go/mo`     | | ||||
| | `github.com/chai2010/gettext-go/gettext/plural` | `github.com/chai2010/gettext-go/plural` | | ||||
|  | ||||
| ### Renamed functions | ||||
|  | ||||
| | v0.1.0 (old)                       | v1.0.0 (new)                | | ||||
| | ---------------------------------- | --------------------------- | | ||||
| | `gettext-go/gettext.*`             | `gettext-go.*`              | | ||||
| | `gettext-go/gettext.DefaultLocal`  | `gettext-go.DefaultLanguage`| | ||||
| | `gettext-go/gettext.BindTextdomain`| `gettext-go.BindLocale`     | | ||||
| | `gettext-go/gettext.Textdomain`    | `gettext-go.SetDomain`      | | ||||
| | `gettext-go/gettext.SetLocale`     | `gettext-go.SetLanguage`    | | ||||
| | `gettext-go/gettext/po.Load`       | `gettext-go/po.LoadFile`    | | ||||
| | `gettext-go/gettext/po.LoadData`   | `gettext-go/po.Load`        | | ||||
| | `gettext-go/gettext/mo.Load`       | `gettext-go/mo.LoadFile`    | | ||||
| | `gettext-go/gettext/mo.LoadData`   | `gettext-go/mo.Load`        | | ||||
|  | ||||
| ### Use empty string as the default context for `gettext.Gettext` | ||||
|  | ||||
| ```go | ||||
| package main | ||||
|  | ||||
| // v0.1.0 | ||||
| // if the **context** missing, use `callerName(2)` as the context: | ||||
|  | ||||
| // v1.0.0 | ||||
| // if the **context** missing, use empty string as the context: | ||||
|  | ||||
| func main() { | ||||
| 	gettext.Gettext("hello")           | ||||
| 	// v0.1.0 => gettext.PGettext("main.main", "hello") | ||||
| 	// v1.0.0 => gettext.PGettext("", "hello") | ||||
|  | ||||
| 	gettext.DGettext("domain", "hello") | ||||
| 	// v0.1.0 => gettext.DPGettext("domain", "main.main", "hello") | ||||
| 	// v1.0.0 => gettext.DPGettext("domain", "", "hello") | ||||
|  | ||||
| 	gettext.NGettext("domain", "hello", "hello2", n) | ||||
| 	// v0.1.0 => gettext.PNGettext("domain", "main.main", "hello", "hello2", n) | ||||
| 	// v1.0.0 => gettext.PNGettext("domain", "", "hello", "hello2", n) | ||||
|  | ||||
| 	gettext.DNGettext("domain", "hello", "hello2", n) | ||||
| 	// v0.1.0 => gettext.DPNGettext("domain", "main.main", "hello", "hello2", n) | ||||
| 	// v1.0.0 => gettext.DPNGettext("domain", "", "hello", "hello2", n) | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### `BindLocale` support `FileSystem` interface | ||||
|  | ||||
| ```go | ||||
| // Use FileSystem: | ||||
| //	BindLocale(New("poedit", "name", OS("path/to/dir"))) // bind "poedit" domain | ||||
| //	BindLocale(New("poedit", "name", OS("path/to.zip"))) // bind "poedit" domain | ||||
| ``` | ||||
|  | ||||
| ## New API in v1.0.0 | ||||
|  | ||||
| `Gettexter` interface: | ||||
|  | ||||
| ```go | ||||
| type Gettexter interface { | ||||
| 	FileSystem() FileSystem | ||||
|  | ||||
| 	GetDomain() string | ||||
| 	SetDomain(domain string) Gettexter | ||||
|  | ||||
| 	GetLanguage() string | ||||
| 	SetLanguage(lang string) Gettexter | ||||
|  | ||||
| 	Gettext(msgid string) string | ||||
| 	PGettext(msgctxt, msgid string) string | ||||
|  | ||||
| 	NGettext(msgid, msgidPlural string, n int) string | ||||
| 	PNGettext(msgctxt, msgid, msgidPlural string, n int) string | ||||
|  | ||||
| 	DGettext(domain, msgid string) string | ||||
| 	DPGettext(domain, msgctxt, msgid string) string | ||||
| 	DNGettext(domain, msgid, msgidPlural string, n int) string | ||||
| 	DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string | ||||
|  | ||||
| 	Getdata(name string) []byte | ||||
| 	DGetdata(domain, name string) []byte | ||||
| } | ||||
|  | ||||
| func New(domain, path string, data ...interface{}) Gettexter | ||||
| ``` | ||||
|  | ||||
| `FileSystem` interface: | ||||
|  | ||||
| ```go | ||||
| type FileSystem interface { | ||||
| 	LocaleList() []string | ||||
| 	LoadMessagesFile(domain, lang, ext string) ([]byte, error) | ||||
| 	LoadResourceFile(domain, lang, name string) ([]byte, error) | ||||
| 	String() string | ||||
| } | ||||
|  | ||||
| func NewFS(name string, x interface{}) FileSystem | ||||
| func OS(root string) FileSystem | ||||
| func ZipFS(r *zip.Reader, name string) FileSystem | ||||
| func NilFS(name string) FileSystem | ||||
| ``` | ||||
|  | ||||
| ---- | ||||
|  | ||||
| ## BUGS | ||||
|  | ||||
| Please report bugs to <chaishushan@gmail.com>. | ||||
|  | ||||
| Thanks! | ||||
| @@ -7,18 +7,17 @@ Package gettext implements a basic GNU's gettext library. | ||||
| 
 | ||||
| Example: | ||||
| 	import ( | ||||
| 		"github.com/chai2010/gettext-go/gettext" | ||||
| 		"github.com/chai2010/gettext-go" | ||||
| 	) | ||||
| 
 | ||||
| 	func main() { | ||||
| 		gettext.SetLocale("zh_CN") | ||||
| 		gettext.Textdomain("hello") | ||||
| 		gettext.SetLanguage("zh_CN") | ||||
| 
 | ||||
| 		// gettext.BindTextdomain("hello", "local", nil)         // from local dir | ||||
| 		// gettext.BindTextdomain("hello", "local.zip", nil)     // from local zip file | ||||
| 		// gettext.BindTextdomain("hello", "local.zip", zipData) // from embedded zip data | ||||
| 		// gettext.BindLocale(gettext.New("hello", "locale"))              // from locale dir | ||||
| 		// gettext.BindLocale(gettext.New("hello", "locale.zip"))          // from locale zip file | ||||
| 		// gettext.BindLocale(gettext.New("hello", "locale.zip", zipData)) // from embedded zip data | ||||
| 
 | ||||
| 		gettext.BindTextdomain("hello", "local", nil) | ||||
| 		gettext.BindLocale(gettext.New("hello", "locale")) | ||||
| 
 | ||||
| 		// translate source text | ||||
| 		fmt.Println(gettext.Gettext("Hello, world!")) | ||||
| @@ -29,28 +28,30 @@ Example: | ||||
| 		// Output: ... | ||||
| 	} | ||||
| 
 | ||||
| Translate directory struct("../examples/local.zip"): | ||||
| Translate directory struct("./examples/locale.zip"): | ||||
| 
 | ||||
| 	Root: "path" or "file.zip/zipBaseName" | ||||
| 	 +-default                 # local: $(LC_MESSAGES) or $(LANG) or "default" | ||||
| 	 +-default                 # locale: $(LC_MESSAGES) or $(LANG) or "default" | ||||
| 	 |  +-LC_MESSAGES            # just for `gettext.Gettext` | ||||
| 	 |  |   +-hello.mo             # $(Root)/$(local)/LC_MESSAGES/$(domain).mo | ||||
| 	 |  |   \-hello.po             # $(Root)/$(local)/LC_MESSAGES/$(domain).mo | ||||
| 	 |  |   +-hello.mo             # $(Root)/$(lang)/LC_MESSAGES/$(domain).mo | ||||
| 	 |  |   +-hello.po             # $(Root)/$(lang)/LC_MESSAGES/$(domain).po | ||||
| 	 |  |   \-hello.json           # $(Root)/$(lang)/LC_MESSAGES/$(domain).json | ||||
| 	 |  | | ||||
| 	 |  \-LC_RESOURCE            # just for `gettext.Getdata` | ||||
| 	 |      +-hello                # domain map a dir in resource translate | ||||
| 	 |         +-favicon.ico       # $(Root)/$(local)/LC_RESOURCE/$(domain)/$(filename) | ||||
| 	 |         +-favicon.ico       # $(Root)/$(lang)/LC_RESOURCE/$(domain)/$(filename) | ||||
| 	 |         \-poems.txt | ||||
| 	 | | ||||
| 	 \-zh_CN                   # simple chinese translate | ||||
| 	    +-LC_MESSAGES | ||||
| 	    |   +-hello.mo             # try "$(domain).mo" first | ||||
| 	    |   \-hello.po             # try "$(domain).po" second | ||||
| 	    |   +-hello.po             # try "$(domain).po" first | ||||
| 	    |   +-hello.mo             # try "$(domain).mo" second | ||||
| 	    |   \-hello.json           # try "$(domain).json" third | ||||
| 	    | | ||||
| 	    \-LC_RESOURCE | ||||
| 	        +-hello | ||||
| 	           +-favicon.ico       # try "$(local)/$(domain)/file" first | ||||
| 	           \-poems.txt         # try "default/$(domain)/file" second | ||||
| 	           +-favicon.ico       # $(lang)/$(domain)/favicon.ico | ||||
| 	           \-poems.txt         # $(lang)/$(domain)/poems.txt | ||||
| 
 | ||||
| See: | ||||
| 	http://en.wikipedia.org/wiki/Gettext | ||||
							
								
								
									
										84
									
								
								vendor/github.com/chai2010/gettext-go/fs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								vendor/github.com/chai2010/gettext-go/fs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| // Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package gettext | ||||
|  | ||||
| import ( | ||||
| 	"archive/zip" | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| ) | ||||
|  | ||||
| type FileSystem interface { | ||||
| 	LocaleList() []string | ||||
| 	LoadMessagesFile(domain, lang, ext string) ([]byte, error) | ||||
| 	LoadResourceFile(domain, lang, name string) ([]byte, error) | ||||
| 	String() string | ||||
| } | ||||
|  | ||||
| func NewFS(name string, x interface{}) FileSystem { | ||||
| 	if x == nil { | ||||
| 		if name != "" { | ||||
| 			return OS(name) | ||||
| 		} | ||||
| 		return NilFS(name) | ||||
| 	} | ||||
|  | ||||
| 	switch x := x.(type) { | ||||
| 	case []byte: | ||||
| 		if len(x) == 0 { | ||||
| 			return OS(name) | ||||
| 		} | ||||
| 		if r, err := zip.NewReader(bytes.NewReader(x), int64(len(x))); err == nil { | ||||
| 			return ZipFS(r, name) | ||||
| 		} | ||||
| 		if fs, err := newJson(x, name); err == nil { | ||||
| 			return fs | ||||
| 		} | ||||
| 	case string: | ||||
| 		if len(x) == 0 { | ||||
| 			return OS(name) | ||||
| 		} | ||||
| 		if r, err := zip.NewReader(bytes.NewReader([]byte(x)), int64(len(x))); err == nil { | ||||
| 			return ZipFS(r, name) | ||||
| 		} | ||||
| 		if fs, err := newJson([]byte(x), name); err == nil { | ||||
| 			return fs | ||||
| 		} | ||||
| 	case FileSystem: | ||||
| 		return x | ||||
| 	} | ||||
|  | ||||
| 	return NilFS(name) | ||||
| } | ||||
|  | ||||
| func OS(root string) FileSystem { | ||||
| 	return newOsFS(root) | ||||
| } | ||||
|  | ||||
| func ZipFS(r *zip.Reader, name string) FileSystem { | ||||
| 	return newZipFS(r, name) | ||||
| } | ||||
|  | ||||
| func NilFS(name string) FileSystem { | ||||
| 	return &nilFS{name} | ||||
| } | ||||
|  | ||||
| type nilFS struct { | ||||
| 	name string | ||||
| } | ||||
|  | ||||
| func (p *nilFS) LocaleList() []string { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *nilFS) LoadMessagesFile(domain, lang, ext string) ([]byte, error) { | ||||
| 	return nil, fmt.Errorf("not found") | ||||
| } | ||||
| func (p *nilFS) LoadResourceFile(domain, lang, name string) ([]byte, error) { | ||||
| 	return nil, fmt.Errorf("not found") | ||||
| } | ||||
| func (p *nilFS) String() string { | ||||
| 	return "gettext.nilfs(" + p.name + ")" | ||||
| } | ||||
							
								
								
									
										66
									
								
								vendor/github.com/chai2010/gettext-go/fs_json.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								vendor/github.com/chai2010/gettext-go/fs_json.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| // Copyright 2020 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package gettext | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"sort" | ||||
| ) | ||||
|  | ||||
| type jsonFS struct { | ||||
| 	name string | ||||
| 	x    map[string]struct { | ||||
| 		LC_MESSAGES map[string][]struct { | ||||
| 			MsgContext  string   `json:"msgctxt"`      // msgctxt context | ||||
| 			MsgId       string   `json:"msgid"`        // msgid untranslated-string | ||||
| 			MsgIdPlural string   `json:"msgid_plural"` // msgid_plural untranslated-string-plural | ||||
| 			MsgStr      []string `json:"msgstr"`       // msgstr translated-string | ||||
| 		} | ||||
| 		LC_RESOURCE map[string]map[string]string | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func isJsonData() bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func newJson(jsonData []byte, name string) (*jsonFS, error) { | ||||
| 	p := &jsonFS{name: name} | ||||
| 	if err := json.Unmarshal(jsonData, &p.x); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return p, nil | ||||
| } | ||||
|  | ||||
| func (p *jsonFS) LocaleList() []string { | ||||
| 	var ss []string | ||||
| 	for lang := range p.x { | ||||
| 		ss = append(ss, lang) | ||||
| 	} | ||||
| 	sort.Strings(ss) | ||||
| 	return ss | ||||
| } | ||||
|  | ||||
| func (p *jsonFS) LoadMessagesFile(domain, lang, ext string) ([]byte, error) { | ||||
| 	if v, ok := p.x[lang]; ok { | ||||
| 		if v, ok := v.LC_MESSAGES[domain+ext]; ok { | ||||
| 			return json.Marshal(v) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, fmt.Errorf("not found") | ||||
| } | ||||
| func (p *jsonFS) LoadResourceFile(domain, lang, name string) ([]byte, error) { | ||||
| 	if v, ok := p.x[lang]; ok { | ||||
| 		if v, ok := v.LC_RESOURCE[domain]; ok { | ||||
| 			return []byte(v[name]), nil | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, fmt.Errorf("not found") | ||||
| } | ||||
| func (p *jsonFS) String() string { | ||||
| 	return "gettext.nilfs(" + p.name + ")" | ||||
| } | ||||
							
								
								
									
										91
									
								
								vendor/github.com/chai2010/gettext-go/fs_os.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								vendor/github.com/chai2010/gettext-go/fs_os.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| // Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package gettext | ||||
|  | ||||
| import ( | ||||
| 	"archive/zip" | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type osFS struct { | ||||
| 	root string | ||||
| } | ||||
|  | ||||
| func newOsFS(root string) FileSystem { | ||||
| 	// locale zip file | ||||
| 	if fi, err := os.Stat(root); err == nil && !fi.IsDir() { | ||||
| 		if strings.HasSuffix(strings.ToLower(root), ".zip") { | ||||
| 			if x, err := ioutil.ReadFile(root); err == nil { | ||||
| 				if r, err := zip.NewReader(bytes.NewReader(x), int64(len(x))); err == nil { | ||||
| 					return ZipFS(r, root) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if strings.HasSuffix(strings.ToLower(root), ".json") { | ||||
| 			if x, err := ioutil.ReadFile(root); err == nil { | ||||
| 				if fs, err := newJson(x, root); err == nil { | ||||
| 					return fs | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// locale dir | ||||
| 	return &osFS{root: root} | ||||
| } | ||||
|  | ||||
| func (p *osFS) LocaleList() []string { | ||||
| 	list, err := ioutil.ReadDir(p.root) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	ssMap := make(map[string]bool) | ||||
| 	for _, dir := range list { | ||||
| 		if dir.IsDir() { | ||||
| 			ssMap[dir.Name()] = true | ||||
| 		} | ||||
| 	} | ||||
| 	var locales = make([]string, 0, len(ssMap)) | ||||
| 	for s := range ssMap { | ||||
| 		locales = append(locales, s) | ||||
| 	} | ||||
| 	sort.Strings(locales) | ||||
| 	return locales | ||||
| } | ||||
|  | ||||
| func (p *osFS) LoadMessagesFile(domain, locale, ext string) ([]byte, error) { | ||||
| 	trName := p.makeMessagesFileName(domain, locale, ext) | ||||
| 	rcData, err := ioutil.ReadFile(trName) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return rcData, nil | ||||
| } | ||||
|  | ||||
| func (p *osFS) LoadResourceFile(domain, locale, name string) ([]byte, error) { | ||||
| 	rcName := p.makeResourceFileName(domain, locale, name) | ||||
| 	rcData, err := ioutil.ReadFile(rcName) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return rcData, nil | ||||
| } | ||||
|  | ||||
| func (p *osFS) String() string { | ||||
| 	return "gettext.localfs(" + p.root + ")" | ||||
| } | ||||
|  | ||||
| func (p *osFS) makeMessagesFileName(domain, lang, ext string) string { | ||||
| 	return fmt.Sprintf("%s/%s/LC_MESSAGES/%s%s", p.root, lang, domain, ext) | ||||
| } | ||||
|  | ||||
| func (p *osFS) makeResourceFileName(domain, lang, name string) string { | ||||
| 	return fmt.Sprintf("%s/%s/LC_RESOURCE/%s/%s", p.root, lang, domain, name) | ||||
| } | ||||
							
								
								
									
										142
									
								
								vendor/github.com/chai2010/gettext-go/fs_zip.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								vendor/github.com/chai2010/gettext-go/fs_zip.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | ||||
| // Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package gettext | ||||
|  | ||||
| import ( | ||||
| 	"archive/zip" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type zipFS struct { | ||||
| 	root string | ||||
| 	name string | ||||
| 	r    *zip.Reader | ||||
| } | ||||
|  | ||||
| func newZipFS(r *zip.Reader, name string) *zipFS { | ||||
| 	fs := &zipFS{r: r, name: name} | ||||
| 	fs.root = fs.zipRoot() | ||||
| 	return fs | ||||
| } | ||||
|  | ||||
| func (p *zipFS) zipName() string { | ||||
| 	name := p.name | ||||
| 	if x := strings.LastIndexAny(name, `\/`); x != -1 { | ||||
| 		name = name[x+1:] | ||||
| 	} | ||||
| 	name = strings.TrimSuffix(name, ".zip") | ||||
| 	return name | ||||
| } | ||||
|  | ||||
| func (p *zipFS) zipRoot() string { | ||||
| 	var somepath string | ||||
| 	for _, f := range p.r.File { | ||||
| 		if x := strings.Index(f.Name, "LC_MESSAGES"); x != -1 { | ||||
| 			somepath = f.Name | ||||
| 		} | ||||
| 		if x := strings.Index(f.Name, "LC_RESOURCE"); x != -1 { | ||||
| 			somepath = f.Name | ||||
| 		} | ||||
| 	} | ||||
| 	if somepath == "" { | ||||
| 		return p.zipName() | ||||
| 	} | ||||
|  | ||||
| 	ss := strings.Split(somepath, "/") | ||||
| 	for i, s := range ss { | ||||
| 		// $(root)/$(lang)/LC_MESSAGES | ||||
| 		// $(root)/$(lang)/LC_RESOURCE | ||||
| 		if (s == "LC_MESSAGES" || s == "LC_RESOURCE") && i >= 2 { | ||||
| 			return strings.Join(ss[:i-1], "/") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return p.zipName() | ||||
| } | ||||
|  | ||||
| func (p *zipFS) LocaleList() []string { | ||||
| 	var locals []string | ||||
| 	for s := range p.lsZip(p.r) { | ||||
| 		locals = append(locals, s) | ||||
| 	} | ||||
| 	sort.Strings(locals) | ||||
| 	return locals | ||||
| } | ||||
|  | ||||
| func (p *zipFS) LoadMessagesFile(domain, lang, ext string) ([]byte, error) { | ||||
| 	trName := p.makeMessagesFileName(domain, lang, ext) | ||||
| 	for _, f := range p.r.File { | ||||
| 		if f.Name != trName { | ||||
| 			continue | ||||
| 		} | ||||
| 		rc, err := f.Open() | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		rcData, err := ioutil.ReadAll(rc) | ||||
| 		rc.Close() | ||||
| 		return rcData, err | ||||
| 	} | ||||
| 	return nil, fmt.Errorf("not found") | ||||
| } | ||||
|  | ||||
| func (p *zipFS) LoadResourceFile(domain, lang, name string) ([]byte, error) { | ||||
| 	rcName := p.makeResourceFileName(domain, lang, name) | ||||
| 	for _, f := range p.r.File { | ||||
| 		if f.Name != rcName { | ||||
| 			continue | ||||
| 		} | ||||
| 		rc, err := f.Open() | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		rcData, err := ioutil.ReadAll(rc) | ||||
| 		rc.Close() | ||||
| 		return rcData, err | ||||
| 	} | ||||
| 	return nil, fmt.Errorf("not found") | ||||
| } | ||||
|  | ||||
| func (p *zipFS) String() string { | ||||
| 	return "gettext.zipfs(" + p.name + ")" | ||||
| } | ||||
|  | ||||
| func (p *zipFS) makeMessagesFileName(domain, lang, ext string) string { | ||||
| 	return fmt.Sprintf("%s/%s/LC_MESSAGES/%s%s", p.root, lang, domain, ext) | ||||
| } | ||||
|  | ||||
| func (p *zipFS) makeResourceFileName(domain, lang, name string) string { | ||||
| 	return fmt.Sprintf("%s/%s/LC_RESOURCE/%s/%s", p.root, lang, domain, name) | ||||
| } | ||||
|  | ||||
| func (p *zipFS) lsZip(r *zip.Reader) map[string]bool { | ||||
| 	ssMap := make(map[string]bool) | ||||
| 	for _, f := range r.File { | ||||
| 		if x := strings.Index(f.Name, "LC_MESSAGES"); x != -1 { | ||||
| 			s := strings.TrimRight(f.Name[:x], `\/`) | ||||
| 			if x = strings.LastIndexAny(s, `\/`); x != -1 { | ||||
| 				s = s[x+1:] | ||||
| 			} | ||||
| 			if s != "" { | ||||
| 				ssMap[s] = true | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 		if x := strings.Index(f.Name, "LC_RESOURCE"); x != -1 { | ||||
| 			s := strings.TrimRight(f.Name[:x], `\/`) | ||||
| 			if x = strings.LastIndexAny(s, `\/`); x != -1 { | ||||
| 				s = s[x+1:] | ||||
| 			} | ||||
| 			if s != "" { | ||||
| 				ssMap[s] = true | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| 	return ssMap | ||||
| } | ||||
| @@ -5,57 +5,91 @@ | ||||
| package gettext | ||||
| 
 | ||||
| var ( | ||||
| 	defaultManager = newDomainManager() | ||||
| 	DefaultLanguage string = getDefaultLanguage() // use $(LC_MESSAGES) or $(LANG) or "default" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	DefaultLocale = getDefaultLocale() // use $(LC_MESSAGES) or $(LANG) or "default" | ||||
| ) | ||||
| type Gettexter interface { | ||||
| 	FileSystem() FileSystem | ||||
| 
 | ||||
| // SetLocale sets and queries the program's current locale. | ||||
| 	GetDomain() string | ||||
| 	SetDomain(domain string) Gettexter | ||||
| 
 | ||||
| 	GetLanguage() string | ||||
| 	SetLanguage(lang string) Gettexter | ||||
| 
 | ||||
| 	Gettext(msgid string) string | ||||
| 	PGettext(msgctxt, msgid string) string | ||||
| 
 | ||||
| 	NGettext(msgid, msgidPlural string, n int) string | ||||
| 	PNGettext(msgctxt, msgid, msgidPlural string, n int) string | ||||
| 
 | ||||
| 	DGettext(domain, msgid string) string | ||||
| 	DPGettext(domain, msgctxt, msgid string) string | ||||
| 	DNGettext(domain, msgid, msgidPlural string, n int) string | ||||
| 	DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string | ||||
| 
 | ||||
| 	Getdata(name string) []byte | ||||
| 	DGetdata(domain, name string) []byte | ||||
| } | ||||
| 
 | ||||
| // New create Interface use default language. | ||||
| func New(domain, path string, data ...interface{}) Gettexter { | ||||
| 	return newLocale(domain, path, data...) | ||||
| } | ||||
| 
 | ||||
| var defaultGettexter struct { | ||||
| 	lang   string | ||||
| 	domain string | ||||
| 	Gettexter | ||||
| } | ||||
| 
 | ||||
| func init() { | ||||
| 	defaultGettexter.lang = getDefaultLanguage() | ||||
| 	defaultGettexter.domain = "default" | ||||
| 	defaultGettexter.Gettexter = newLocale("", "") | ||||
| } | ||||
| 
 | ||||
| // BindLocale sets and queries program's domains. | ||||
| // | ||||
| // If the locale is not empty string, set the new local. | ||||
| // Examples: | ||||
| //	BindLocale(New("poedit", "locale")) // bind "poedit" domain | ||||
| // | ||||
| // If the locale is empty string, don't change anything. | ||||
| // Use zip file: | ||||
| //	BindLocale(New("poedit", "locale.zip"))          // bind "poedit" domain | ||||
| //	BindLocale(New("poedit", "locale.zip", zipData)) // bind "poedit" domain | ||||
| // | ||||
| // Use FileSystem: | ||||
| //	BindLocale(New("poedit", "name", OS("path/to/dir"))) // bind "poedit" domain | ||||
| //	BindLocale(New("poedit", "name", OS("path/to.zip"))) // bind "poedit" domain | ||||
| // | ||||
| func BindLocale(g Gettexter) { | ||||
| 	if g != nil { | ||||
| 		defaultGettexter.Gettexter = g | ||||
| 		defaultGettexter.SetLanguage(defaultGettexter.lang) | ||||
| 	} else { | ||||
| 		defaultGettexter.Gettexter = newLocale("", "") | ||||
| 		defaultGettexter.SetLanguage(defaultGettexter.lang) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SetLanguage sets and queries the program's current lang. | ||||
| // | ||||
| // If the lang is not empty string, set the new locale. | ||||
| // | ||||
| // If the lang is empty string, don't change anything. | ||||
| // | ||||
| // Returns is the current locale. | ||||
| // | ||||
| // Examples: | ||||
| //	SetLocale("")      // get locale: return DefaultLocale | ||||
| //	SetLocale("zh_CN") // set locale: return zh_CN | ||||
| //	SetLocale("")      // get locale: return zh_CN | ||||
| func SetLocale(locale string) string { | ||||
| 	return defaultManager.SetLocale(locale) | ||||
| //	SetLanguage("")      // get locale: return DefaultLocale | ||||
| //	SetLanguage("zh_CN") // set locale: return zh_CN | ||||
| //	SetLanguage("")      // get locale: return zh_CN | ||||
| func SetLanguage(lang string) string { | ||||
| 	defaultGettexter.SetLanguage(lang) | ||||
| 	return defaultGettexter.GetLanguage() | ||||
| } | ||||
| 
 | ||||
| // BindTextdomain sets and queries program's domains. | ||||
| // | ||||
| // If the domain and path are all not empty string, bind the new domain. | ||||
| // If the domain already exists, return error. | ||||
| // | ||||
| // If the domain is not empty string, but the path is the empty string, | ||||
| // delete the domain. | ||||
| // If the domain don't exists, return error. | ||||
| // | ||||
| // If the domain and the path are all empty string, don't change anything. | ||||
| // | ||||
| // Returns is the all bind domains. | ||||
| // | ||||
| // Examples: | ||||
| //	BindTextdomain("poedit", "local", nil) // bind "poedit" domain | ||||
| //	BindTextdomain("", "", nil)            // return all domains | ||||
| //	BindTextdomain("poedit", "", nil)      // delete "poedit" domain | ||||
| //	BindTextdomain("", "", nil)            // return all domains | ||||
| // | ||||
| // Use zip file: | ||||
| //	BindTextdomain("poedit", "local.zip", nil)     // bind "poedit" domain | ||||
| //	BindTextdomain("poedit", "local.zip", zipData) // bind "poedit" domain | ||||
| // | ||||
| func BindTextdomain(domain, path string, zipData []byte) (domains, paths []string) { | ||||
| 	return defaultManager.Bind(domain, path, zipData) | ||||
| } | ||||
| 
 | ||||
| // Textdomain sets and retrieves the current message domain. | ||||
| // SetDomain sets and retrieves the current message domain. | ||||
| // | ||||
| // If the domain is not empty string, set the new domains. | ||||
| // | ||||
| @@ -64,10 +98,11 @@ func BindTextdomain(domain, path string, zipData []byte) (domains, paths []strin | ||||
| // Returns is the all used domains. | ||||
| // | ||||
| // Examples: | ||||
| //	Textdomain("poedit") // set domain: poedit | ||||
| //	Textdomain("")       // get domain: return poedit | ||||
| func Textdomain(domain string) string { | ||||
| 	return defaultManager.SetDomain(domain) | ||||
| //	SetDomain("poedit") // set domain: poedit | ||||
| //	SetDomain("")       // get domain: return poedit | ||||
| func SetDomain(domain string) string { | ||||
| 	defaultGettexter.SetDomain(domain) | ||||
| 	return defaultGettexter.GetDomain() | ||||
| } | ||||
| 
 | ||||
| // Gettext attempt to translate a text string into the user's native language, | ||||
| @@ -77,10 +112,10 @@ func Textdomain(domain string) string { | ||||
| // | ||||
| // Examples: | ||||
| //	func Foo() { | ||||
| //		msg := gettext.Gettext("Hello") // msgctxt is "some/package/name.Foo" | ||||
| //		msg := gettext.Gettext("Hello") // msgctxt is "" | ||||
| //	} | ||||
| func Gettext(msgid string) string { | ||||
| 	return PGettext(callerName(2), msgid) | ||||
| 	return defaultGettexter.Gettext(msgid) | ||||
| } | ||||
| 
 | ||||
| // Getdata attempt to translate a resource file into the user's native language, | ||||
| @@ -89,11 +124,11 @@ func Gettext(msgid string) string { | ||||
| // Examples: | ||||
| //	func Foo() { | ||||
| //		Textdomain("hello") | ||||
| //		BindTextdomain("hello", "local.zip", nilOrZipData) | ||||
| //		BindLocale("hello", "locale.zip", nilOrZipData) | ||||
| //		poems := gettext.Getdata("poems.txt") | ||||
| //	} | ||||
| func Getdata(name string) []byte { | ||||
| 	return defaultManager.Getdata(name) | ||||
| 	return defaultGettexter.Getdata(name) | ||||
| } | ||||
| 
 | ||||
| // NGettext attempt to translate a text string into the user's native language, | ||||
| @@ -107,7 +142,7 @@ func Getdata(name string) []byte { | ||||
| //		msg := gettext.NGettext("%d people", "%d peoples", 2) | ||||
| //	} | ||||
| func NGettext(msgid, msgidPlural string, n int) string { | ||||
| 	return PNGettext(callerName(2), msgid, msgidPlural, n) | ||||
| 	return defaultGettexter.NGettext(msgid, msgidPlural, n) | ||||
| } | ||||
| 
 | ||||
| // PGettext attempt to translate a text string into the user's native language, | ||||
| @@ -118,7 +153,7 @@ func NGettext(msgid, msgidPlural string, n int) string { | ||||
| //		msg := gettext.PGettext("gettext-go.example", "Hello") // msgctxt is "gettext-go.example" | ||||
| //	} | ||||
| func PGettext(msgctxt, msgid string) string { | ||||
| 	return PNGettext(msgctxt, msgid, "", 0) | ||||
| 	return defaultGettexter.PGettext(msgctxt, msgid) | ||||
| } | ||||
| 
 | ||||
| // PNGettext attempt to translate a text string into the user's native language, | ||||
| @@ -130,7 +165,7 @@ func PGettext(msgctxt, msgid string) string { | ||||
| //		msg := gettext.PNGettext("gettext-go.example", "%d people", "%d peoples", 2) | ||||
| //	} | ||||
| func PNGettext(msgctxt, msgid, msgidPlural string, n int) string { | ||||
| 	return defaultManager.PNGettext(msgctxt, msgid, msgidPlural, n) | ||||
| 	return defaultGettexter.PNGettext(msgctxt, msgid, msgidPlural, n) | ||||
| } | ||||
| 
 | ||||
| // DGettext like Gettext(), but looking up the message in the specified domain. | ||||
| @@ -140,7 +175,7 @@ func PNGettext(msgctxt, msgid, msgidPlural string, n int) string { | ||||
| //		msg := gettext.DGettext("poedit", "Hello") | ||||
| //	} | ||||
| func DGettext(domain, msgid string) string { | ||||
| 	return DPGettext(domain, callerName(2), msgid) | ||||
| 	return defaultGettexter.DGettext(domain, msgid) | ||||
| } | ||||
| 
 | ||||
| // DNGettext like NGettext(), but looking up the message in the specified domain. | ||||
| @@ -150,7 +185,7 @@ func DGettext(domain, msgid string) string { | ||||
| //		msg := gettext.PNGettext("poedit", "gettext-go.example", "%d people", "%d peoples", 2) | ||||
| //	} | ||||
| func DNGettext(domain, msgid, msgidPlural string, n int) string { | ||||
| 	return DPNGettext(domain, callerName(2), msgid, msgidPlural, n) | ||||
| 	return defaultGettexter.DNGettext(domain, msgid, msgidPlural, n) | ||||
| } | ||||
| 
 | ||||
| // DPGettext like PGettext(), but looking up the message in the specified domain. | ||||
| @@ -160,7 +195,7 @@ func DNGettext(domain, msgid, msgidPlural string, n int) string { | ||||
| //		msg := gettext.DPGettext("poedit", "gettext-go.example", "Hello") | ||||
| //	} | ||||
| func DPGettext(domain, msgctxt, msgid string) string { | ||||
| 	return DPNGettext(domain, msgctxt, msgid, "", 0) | ||||
| 	return defaultGettexter.DPGettext(domain, msgctxt, msgid) | ||||
| } | ||||
| 
 | ||||
| // DPNGettext like PNGettext(), but looking up the message in the specified domain. | ||||
| @@ -170,7 +205,7 @@ func DPGettext(domain, msgctxt, msgid string) string { | ||||
| //		msg := gettext.DPNGettext("poedit", "gettext-go.example", "%d people", "%d peoples", 2) | ||||
| //	} | ||||
| func DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string { | ||||
| 	return defaultManager.DPNGettext(domain, msgctxt, msgid, msgidPlural, n) | ||||
| 	return defaultGettexter.DPNGettext(domain, msgctxt, msgid, msgidPlural, n) | ||||
| } | ||||
| 
 | ||||
| // DGetdata like Getdata(), but looking up the resource in the specified domain. | ||||
| @@ -180,5 +215,5 @@ func DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string { | ||||
| //		msg := gettext.DGetdata("hello", "poems.txt") | ||||
| //	} | ||||
| func DGetdata(domain, name string) []byte { | ||||
| 	return defaultManager.DGetdata(domain, name) | ||||
| 	return defaultGettexter.DGetdata(domain, name) | ||||
| } | ||||
							
								
								
									
										39
									
								
								vendor/github.com/chai2010/gettext-go/gettext/caller.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/chai2010/gettext-go/gettext/caller.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,39 +0,0 @@ | ||||
| // Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package gettext | ||||
|  | ||||
| import ( | ||||
| 	"regexp" | ||||
| 	"runtime" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	reInit    = regexp.MustCompile(`init·\d+$`) // main.init·1 | ||||
| 	reClosure = regexp.MustCompile(`func·\d+$`) // main.func·001 | ||||
| ) | ||||
|  | ||||
| // caller types: | ||||
| // runtime.goexit | ||||
| // runtime.main | ||||
| // main.init | ||||
| // main.main | ||||
| // main.init·1 -> main.init | ||||
| // main.func·001 -> main.func | ||||
| // code.google.com/p/gettext-go/gettext.TestCallerName | ||||
| // ... | ||||
| func callerName(skip int) string { | ||||
| 	pc, _, _, ok := runtime.Caller(skip) | ||||
| 	if !ok { | ||||
| 		return "" | ||||
| 	} | ||||
| 	name := runtime.FuncForPC(pc).Name() | ||||
| 	if reInit.MatchString(name) { | ||||
| 		return reInit.ReplaceAllString(name, "init") | ||||
| 	} | ||||
| 	if reClosure.MatchString(name) { | ||||
| 		return reClosure.ReplaceAllString(name, "func") | ||||
| 	} | ||||
| 	return name | ||||
| } | ||||
							
								
								
									
										119
									
								
								vendor/github.com/chai2010/gettext-go/gettext/domain.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										119
									
								
								vendor/github.com/chai2010/gettext-go/gettext/domain.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,119 +0,0 @@ | ||||
| // Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package gettext | ||||
|  | ||||
| import ( | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| type domainManager struct { | ||||
| 	mutex     sync.Mutex | ||||
| 	locale    string | ||||
| 	domain    string | ||||
| 	domainMap map[string]*fileSystem | ||||
| 	trTextMap map[string]*translator | ||||
| } | ||||
|  | ||||
| func newDomainManager() *domainManager { | ||||
| 	return &domainManager{ | ||||
| 		locale:    DefaultLocale, | ||||
| 		domainMap: make(map[string]*fileSystem), | ||||
| 		trTextMap: make(map[string]*translator), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *domainManager) makeTrMapKey(domain, locale string) string { | ||||
| 	return domain + "_$$$_" + locale | ||||
| } | ||||
|  | ||||
| func (p *domainManager) Bind(domain, path string, data []byte) (domains, paths []string) { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
|  | ||||
| 	switch { | ||||
| 	case domain != "" && path != "": // bind new domain | ||||
| 		p.bindDomainTranslators(domain, path, data) | ||||
| 	case domain != "" && path == "": // delete domain | ||||
| 		p.deleteDomain(domain) | ||||
| 	} | ||||
|  | ||||
| 	// return all bind domain | ||||
| 	for k, fs := range p.domainMap { | ||||
| 		domains = append(domains, k) | ||||
| 		paths = append(paths, fs.FsName) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (p *domainManager) SetLocale(locale string) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	if locale != "" { | ||||
| 		p.locale = locale | ||||
| 	} | ||||
| 	return p.locale | ||||
| } | ||||
|  | ||||
| func (p *domainManager) SetDomain(domain string) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	if domain != "" { | ||||
| 		p.domain = domain | ||||
| 	} | ||||
| 	return p.domain | ||||
| } | ||||
|  | ||||
| func (p *domainManager) Getdata(name string) []byte { | ||||
| 	return p.getdata(p.domain, name) | ||||
| } | ||||
|  | ||||
| func (p *domainManager) DGetdata(domain, name string) []byte { | ||||
| 	return p.getdata(domain, name) | ||||
| } | ||||
|  | ||||
| func (p *domainManager) PNGettext(msgctxt, msgid, msgidPlural string, n int) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	return p.gettext(p.domain, msgctxt, msgid, msgidPlural, n) | ||||
| } | ||||
|  | ||||
| func (p *domainManager) DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	return p.gettext(domain, msgctxt, msgid, msgidPlural, n) | ||||
| } | ||||
|  | ||||
| func (p *domainManager) gettext(domain, msgctxt, msgid, msgidPlural string, n int) string { | ||||
| 	if p.locale == "" || p.domain == "" { | ||||
| 		return msgid | ||||
| 	} | ||||
| 	if _, ok := p.domainMap[domain]; !ok { | ||||
| 		return msgid | ||||
| 	} | ||||
| 	if f, ok := p.trTextMap[p.makeTrMapKey(domain, p.locale)]; ok { | ||||
| 		return f.PNGettext(msgctxt, msgid, msgidPlural, n) | ||||
| 	} | ||||
| 	return msgid | ||||
| } | ||||
|  | ||||
| func (p *domainManager) getdata(domain, name string) []byte { | ||||
| 	if p.locale == "" || p.domain == "" { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if _, ok := p.domainMap[domain]; !ok { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if fs, ok := p.domainMap[domain]; ok { | ||||
| 		if data, err := fs.LoadResourceFile(domain, p.locale, name); err == nil { | ||||
| 			return data | ||||
| 		} | ||||
| 		if p.locale != "default" { | ||||
| 			if data, err := fs.LoadResourceFile(domain, "default", name); err == nil { | ||||
| 				return data | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										50
									
								
								vendor/github.com/chai2010/gettext-go/gettext/domain_helper.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										50
									
								
								vendor/github.com/chai2010/gettext-go/gettext/domain_helper.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,50 +0,0 @@ | ||||
| // Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package gettext | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| func (p *domainManager) bindDomainTranslators(domain, path string, data []byte) { | ||||
| 	if _, ok := p.domainMap[domain]; ok { | ||||
| 		p.deleteDomain(domain) // delete old domain | ||||
| 	} | ||||
| 	fs := newFileSystem(path, data) | ||||
| 	for locale, _ := range fs.LocaleMap { | ||||
| 		trMapKey := p.makeTrMapKey(domain, locale) | ||||
| 		if data, err := fs.LoadMessagesFile(domain, locale, ".mo"); err == nil { | ||||
| 			p.trTextMap[trMapKey], _ = newMoTranslator( | ||||
| 				fmt.Sprintf("%s_%s.mo", domain, locale), | ||||
| 				data, | ||||
| 			) | ||||
| 			continue | ||||
| 		} | ||||
| 		if data, err := fs.LoadMessagesFile(domain, locale, ".po"); err == nil { | ||||
| 			p.trTextMap[trMapKey], _ = newPoTranslator( | ||||
| 				fmt.Sprintf("%s_%s.po", domain, locale), | ||||
| 				data, | ||||
| 			) | ||||
| 			continue | ||||
| 		} | ||||
| 		p.trTextMap[p.makeTrMapKey(domain, locale)] = nilTranslator | ||||
| 	} | ||||
| 	p.domainMap[domain] = fs | ||||
| } | ||||
|  | ||||
| func (p *domainManager) deleteDomain(domain string) { | ||||
| 	if _, ok := p.domainMap[domain]; !ok { | ||||
| 		return | ||||
| 	} | ||||
| 	// delete all mo files | ||||
| 	trMapKeyPrefix := p.makeTrMapKey(domain, "") | ||||
| 	for k, _ := range p.trTextMap { | ||||
| 		if strings.HasPrefix(k, trMapKeyPrefix) { | ||||
| 			delete(p.trTextMap, k) | ||||
| 		} | ||||
| 	} | ||||
| 	delete(p.domainMap, domain) | ||||
| } | ||||
							
								
								
									
										187
									
								
								vendor/github.com/chai2010/gettext-go/gettext/fs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										187
									
								
								vendor/github.com/chai2010/gettext-go/gettext/fs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,187 +0,0 @@ | ||||
| // Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package gettext | ||||
|  | ||||
| import ( | ||||
| 	"archive/zip" | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type fileSystem struct { | ||||
| 	FsName    string | ||||
| 	FsRoot    string | ||||
| 	FsZipData []byte | ||||
| 	LocaleMap map[string]bool | ||||
| } | ||||
|  | ||||
| func newFileSystem(path string, data []byte) *fileSystem { | ||||
| 	fs := &fileSystem{ | ||||
| 		FsName:    path, | ||||
| 		FsZipData: data, | ||||
| 	} | ||||
| 	if err := fs.init(); err != nil { | ||||
| 		log.Printf("gettext-go: invalid domain, err = %v", err) | ||||
| 	} | ||||
| 	return fs | ||||
| } | ||||
|  | ||||
| func (p *fileSystem) init() error { | ||||
| 	zipName := func(name string) string { | ||||
| 		if x := strings.LastIndexAny(name, `\/`); x != -1 { | ||||
| 			name = name[x+1:] | ||||
| 		} | ||||
| 		name = strings.TrimSuffix(name, ".zip") | ||||
| 		return name | ||||
| 	} | ||||
|  | ||||
| 	// zip data | ||||
| 	if len(p.FsZipData) != 0 { | ||||
| 		p.FsRoot = zipName(p.FsName) | ||||
| 		p.LocaleMap = p.lsZip(p.FsZipData) | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// local dir or zip file | ||||
| 	fi, err := os.Stat(p.FsName) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// local dir | ||||
| 	if fi.IsDir() { | ||||
| 		p.FsRoot = p.FsName | ||||
| 		p.LocaleMap = p.lsDir(p.FsName) | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// local zip file | ||||
| 	p.FsZipData, err = ioutil.ReadFile(p.FsName) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	p.FsRoot = zipName(p.FsName) | ||||
| 	p.LocaleMap = p.lsZip(p.FsZipData) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *fileSystem) LoadMessagesFile(domain, local, ext string) ([]byte, error) { | ||||
| 	if len(p.FsZipData) == 0 { | ||||
| 		trName := p.makeMessagesFileName(domain, local, ext) | ||||
| 		rcData, err := ioutil.ReadFile(trName) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return rcData, nil | ||||
| 	} else { | ||||
| 		r, err := zip.NewReader(bytes.NewReader(p.FsZipData), int64(len(p.FsZipData))) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		trName := p.makeMessagesFileName(domain, local, ext) | ||||
| 		for _, f := range r.File { | ||||
| 			if f.Name != trName { | ||||
| 				continue | ||||
| 			} | ||||
| 			rc, err := f.Open() | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			rcData, err := ioutil.ReadAll(rc) | ||||
| 			rc.Close() | ||||
| 			return rcData, err | ||||
| 		} | ||||
| 		return nil, fmt.Errorf("not found") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *fileSystem) LoadResourceFile(domain, local, name string) ([]byte, error) { | ||||
| 	if len(p.FsZipData) == 0 { | ||||
| 		rcName := p.makeResourceFileName(domain, local, name) | ||||
| 		rcData, err := ioutil.ReadFile(rcName) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return rcData, nil | ||||
| 	} else { | ||||
| 		r, err := zip.NewReader(bytes.NewReader(p.FsZipData), int64(len(p.FsZipData))) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		rcName := p.makeResourceFileName(domain, local, name) | ||||
| 		for _, f := range r.File { | ||||
| 			if f.Name != rcName { | ||||
| 				continue | ||||
| 			} | ||||
| 			rc, err := f.Open() | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			rcData, err := ioutil.ReadAll(rc) | ||||
| 			rc.Close() | ||||
| 			return rcData, err | ||||
| 		} | ||||
| 		return nil, fmt.Errorf("not found") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *fileSystem) makeMessagesFileName(domain, local, ext string) string { | ||||
| 	return fmt.Sprintf("%s/%s/LC_MESSAGES/%s%s", p.FsRoot, local, domain, ext) | ||||
| } | ||||
|  | ||||
| func (p *fileSystem) makeResourceFileName(domain, local, name string) string { | ||||
| 	return fmt.Sprintf("%s/%s/LC_RESOURCE/%s/%s", p.FsRoot, local, domain, name) | ||||
| } | ||||
|  | ||||
| func (p *fileSystem) lsZip(data []byte) map[string]bool { | ||||
| 	r, err := zip.NewReader(bytes.NewReader(data), int64(len(data))) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	ssMap := make(map[string]bool) | ||||
| 	for _, f := range r.File { | ||||
| 		if x := strings.Index(f.Name, "LC_MESSAGES"); x != -1 { | ||||
| 			s := strings.TrimRight(f.Name[:x], `\/`) | ||||
| 			if x = strings.LastIndexAny(s, `\/`); x != -1 { | ||||
| 				s = s[x+1:] | ||||
| 			} | ||||
| 			if s != "" { | ||||
| 				ssMap[s] = true | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 		if x := strings.Index(f.Name, "LC_RESOURCE"); x != -1 { | ||||
| 			s := strings.TrimRight(f.Name[:x], `\/`) | ||||
| 			if x = strings.LastIndexAny(s, `\/`); x != -1 { | ||||
| 				s = s[x+1:] | ||||
| 			} | ||||
| 			if s != "" { | ||||
| 				ssMap[s] = true | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| 	return ssMap | ||||
| } | ||||
|  | ||||
| func (p *fileSystem) lsDir(path string) map[string]bool { | ||||
| 	list, err := ioutil.ReadDir(path) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	ssMap := make(map[string]bool) | ||||
| 	for _, dir := range list { | ||||
| 		if dir.IsDir() { | ||||
| 			ssMap[dir.Name()] = true | ||||
| 		} | ||||
| 	} | ||||
| 	return ssMap | ||||
| } | ||||
							
								
								
									
										205
									
								
								vendor/github.com/chai2010/gettext-go/locale.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								vendor/github.com/chai2010/gettext-go/locale.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,205 @@ | ||||
| // Copyright 2020 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package gettext | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| type _Locale struct { | ||||
| 	mutex     sync.Mutex | ||||
| 	fs        FileSystem | ||||
| 	lang      string | ||||
| 	domain    string | ||||
| 	trMap     map[string]*translator | ||||
| 	trCurrent *translator | ||||
| } | ||||
|  | ||||
| var _ Gettexter = (*_Locale)(nil) | ||||
|  | ||||
| func newLocale(domain, path string, data ...interface{}) *_Locale { | ||||
| 	if domain == "" { | ||||
| 		domain = "default" | ||||
| 	} | ||||
| 	p := &_Locale{ | ||||
| 		lang:   DefaultLanguage, | ||||
| 		domain: domain, | ||||
| 	} | ||||
| 	if len(data) > 0 { | ||||
| 		p.fs = NewFS(path, data[0]) | ||||
| 	} else { | ||||
| 		p.fs = NewFS(path, nil) | ||||
| 	} | ||||
|  | ||||
| 	p.syncTrMap() | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| func (p *_Locale) makeTrMapKey(domain, _Locale string) string { | ||||
| 	return domain + "_$$$_" + _Locale | ||||
| } | ||||
|  | ||||
| func (p *_Locale) FileSystem() FileSystem { | ||||
| 	return p.fs | ||||
| } | ||||
|  | ||||
| func (p *_Locale) GetLanguage() string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
|  | ||||
| 	return p.lang | ||||
| } | ||||
| func (p *_Locale) SetLanguage(lang string) Gettexter { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
|  | ||||
| 	if lang == "" { | ||||
| 		lang = DefaultLanguage | ||||
| 	} | ||||
| 	if lang == p.lang { | ||||
| 		return p | ||||
| 	} | ||||
|  | ||||
| 	p.lang = lang | ||||
| 	p.syncTrMap() | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| func (p *_Locale) GetDomain() string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	return p.domain | ||||
| } | ||||
|  | ||||
| func (p *_Locale) SetDomain(domain string) Gettexter { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
|  | ||||
| 	if domain == "" || domain == p.domain { | ||||
| 		return p | ||||
| 	} | ||||
|  | ||||
| 	p.domain = domain | ||||
| 	p.syncTrMap() | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| func (p *_Locale) syncTrMap() { | ||||
| 	p.trMap = make(map[string]*translator) | ||||
| 	trMapKey := p.makeTrMapKey(p.domain, p.lang) | ||||
|  | ||||
| 	if tr, ok := p.trMap[trMapKey]; ok { | ||||
| 		p.trCurrent = tr | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// try load po file | ||||
| 	if data, err := p.fs.LoadMessagesFile(p.domain, p.lang, ".po"); err == nil { | ||||
| 		if tr, err := newPoTranslator(fmt.Sprintf("%s_%s.po", p.domain, p.lang), data); err == nil { | ||||
| 			p.trMap[trMapKey] = tr | ||||
| 			p.trCurrent = tr | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// try load mo file | ||||
| 	if data, err := p.fs.LoadMessagesFile(p.domain, p.lang, ".mo"); err == nil { | ||||
| 		if tr, err := newMoTranslator(fmt.Sprintf("%s_%s.mo", p.domain, p.lang), data); err == nil { | ||||
| 			p.trMap[trMapKey] = tr | ||||
| 			p.trCurrent = tr | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// try load json file | ||||
| 	if data, err := p.fs.LoadMessagesFile(p.domain, p.lang, ".json"); err == nil { | ||||
| 		if tr, err := newJsonTranslator(p.lang, fmt.Sprintf("%s_%s.json", p.domain, p.lang), data); err == nil { | ||||
| 			p.trMap[trMapKey] = tr | ||||
| 			p.trCurrent = tr | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// no po/mo file | ||||
| 	p.trMap[trMapKey] = nilTranslator | ||||
| 	p.trCurrent = nilTranslator | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (p *_Locale) Gettext(msgid string) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	return p.trCurrent.PGettext("", msgid) | ||||
| } | ||||
|  | ||||
| func (p *_Locale) PGettext(msgctxt, msgid string) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	return p.trCurrent.PGettext(msgctxt, msgid) | ||||
| } | ||||
|  | ||||
| func (p *_Locale) NGettext(msgid, msgidPlural string, n int) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	return p.trCurrent.PNGettext("", msgid, msgidPlural, n) | ||||
| } | ||||
|  | ||||
| func (p *_Locale) PNGettext(msgctxt, msgid, msgidPlural string, n int) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	return p.trCurrent.PNGettext(msgctxt, msgid, msgidPlural, n) | ||||
| } | ||||
|  | ||||
| func (p *_Locale) DGettext(domain, msgid string) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	return p.gettext(domain, "", msgid, "", 0) | ||||
| } | ||||
|  | ||||
| func (p *_Locale) DNGettext(domain, msgid, msgidPlural string, n int) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	return p.gettext(domain, "", msgid, msgidPlural, n) | ||||
| } | ||||
|  | ||||
| func (p *_Locale) DPGettext(domain, msgctxt, msgid string) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	return p.gettext(domain, msgctxt, msgid, "", 0) | ||||
| } | ||||
|  | ||||
| func (p *_Locale) DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string { | ||||
| 	p.mutex.Lock() | ||||
| 	defer p.mutex.Unlock() | ||||
| 	return p.gettext(domain, msgctxt, msgid, msgidPlural, n) | ||||
| } | ||||
|  | ||||
| func (p *_Locale) Getdata(name string) []byte { | ||||
| 	return p.getdata(p.domain, name) | ||||
| } | ||||
|  | ||||
| func (p *_Locale) DGetdata(domain, name string) []byte { | ||||
| 	return p.getdata(domain, name) | ||||
| } | ||||
|  | ||||
| func (p *_Locale) gettext(domain, msgctxt, msgid, msgidPlural string, n int) string { | ||||
| 	if f, ok := p.trMap[p.makeTrMapKey(domain, p.lang)]; ok { | ||||
| 		return f.PNGettext(msgctxt, msgid, msgidPlural, n) | ||||
| 	} | ||||
| 	return msgid | ||||
| } | ||||
|  | ||||
| func (p *_Locale) getdata(domain, name string) []byte { | ||||
| 	if data, err := p.fs.LoadResourceFile(domain, p.lang, name); err == nil { | ||||
| 		return data | ||||
| 	} | ||||
| 	if p.lang != "default" { | ||||
| 		if data, err := p.fs.LoadResourceFile(domain, "default", name); err == nil { | ||||
| 			return data | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -7,11 +7,11 @@ Package mo provides support for reading and writing GNU MO file. | ||||
| 
 | ||||
| Examples: | ||||
| 	import ( | ||||
| 		"github.com/chai2010/gettext-go/gettext/mo" | ||||
| 		"github.com/chai2010/gettext-go/mo" | ||||
| 	) | ||||
| 
 | ||||
| 	func main() { | ||||
| 		moFile, err := mo.Load("test.mo") | ||||
| 		moFile, err := mo.LoadFile("test.mo") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| @@ -48,7 +48,9 @@ func encodeData(hdr *moHeader, f *File) []byte { | ||||
| 		} | ||||
| 		msgList = append(msgList, v) | ||||
| 	} | ||||
| 	sort.Sort(byMessages(msgList)) | ||||
| 	sort.Slice(msgList, func(i, j int) bool { | ||||
| 		return msgList[i].less(&msgList[j]) | ||||
| 	}) | ||||
| 
 | ||||
| 	var buf bytes.Buffer | ||||
| 	var msgIdPosList = make([]moStrPos, len(msgList)) | ||||
| @@ -101,24 +103,3 @@ func encodeMsgStr(v Message) string { | ||||
| 	} | ||||
| 	return v.MsgStr | ||||
| } | ||||
| 
 | ||||
| type byMessages []Message | ||||
| 
 | ||||
| func (d byMessages) Len() int { | ||||
| 	return len(d) | ||||
| } | ||||
| func (d byMessages) Less(i, j int) bool { | ||||
| 	if a, b := d[i].MsgContext, d[j].MsgContext; a != b { | ||||
| 		return a < b | ||||
| 	} | ||||
| 	if a, b := d[i].MsgId, d[j].MsgId; a != b { | ||||
| 		return a < b | ||||
| 	} | ||||
| 	if a, b := d[i].MsgIdPlural, d[j].MsgIdPlural; a != b { | ||||
| 		return a < b | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| func (d byMessages) Swap(i, j int) { | ||||
| 	d[i], d[j] = d[j], d[i] | ||||
| } | ||||
| @@ -37,17 +37,21 @@ type File struct { | ||||
| 	Messages     []Message | ||||
| } | ||||
| 
 | ||||
| // Load loads mo file format data. | ||||
| func Load(data []byte) (*File, error) { | ||||
| 	return loadData(data) | ||||
| } | ||||
| 
 | ||||
| // Load loads a named mo file. | ||||
| func Load(name string) (*File, error) { | ||||
| 	data, err := ioutil.ReadFile(name) | ||||
| func LoadFile(path string) (*File, error) { | ||||
| 	data, err := ioutil.ReadFile(path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return LoadData(data) | ||||
| 	return loadData(data) | ||||
| } | ||||
| 
 | ||||
| // LoadData loads mo file format data. | ||||
| func LoadData(data []byte) (*File, error) { | ||||
| func loadData(data []byte) (*File, error) { | ||||
| 	r := bytes.NewReader(data) | ||||
| 
 | ||||
| 	var magicNumber uint32 | ||||
| @@ -37,3 +37,16 @@ func (p Message) String() string { | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
| 
 | ||||
| func (m_i *Message) less(m_j *Message) bool { | ||||
| 	if a, b := m_i.MsgContext, m_j.MsgContext; a != b { | ||||
| 		return a < b | ||||
| 	} | ||||
| 	if a, b := m_i.MsgId, m_j.MsgId; a != b { | ||||
| 		return a < b | ||||
| 	} | ||||
| 	if a, b := m_i.MsgIdPlural, m_j.MsgIdPlural; a != b { | ||||
| 		return a < b | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| @@ -7,7 +7,7 @@ Package plural provides standard plural formulas. | ||||
| 
 | ||||
| Examples: | ||||
| 	import ( | ||||
| 		"code.google.com/p/gettext-go/gettext/plural" | ||||
| 		"github.com/chai2010/gettext-go/plural" | ||||
| 	) | ||||
| 
 | ||||
| 	func main() { | ||||
| @@ -7,11 +7,11 @@ Package po provides support for reading and writing GNU PO file. | ||||
| 
 | ||||
| Examples: | ||||
| 	import ( | ||||
| 		"github.com/chai2010/gettext-go/gettext/po" | ||||
| 		"github.com/chai2010/gettext-go/po" | ||||
| 	) | ||||
| 
 | ||||
| 	func main() { | ||||
| 		poFile, err := po.Load("test.po") | ||||
| 		poFile, err := po.LoadFile("test.po") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| @@ -20,17 +20,21 @@ type File struct { | ||||
| 	Messages   []Message | ||||
| } | ||||
| 
 | ||||
| // Load loads a named po file. | ||||
| func Load(name string) (*File, error) { | ||||
| 	data, err := ioutil.ReadFile(name) | ||||
| // Load loads po file format data. | ||||
| func Load(data []byte) (*File, error) { | ||||
| 	return loadData(data) | ||||
| } | ||||
| 
 | ||||
| // LoadFile loads a named po file. | ||||
| func LoadFile(path string) (*File, error) { | ||||
| 	data, err := ioutil.ReadFile(path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return LoadData(data) | ||||
| 	return loadData(data) | ||||
| } | ||||
| 
 | ||||
| // LoadData loads po file format data. | ||||
| func LoadData(data []byte) (*File, error) { | ||||
| func loadData(data []byte) (*File, error) { | ||||
| 	r := newLineReader(string(data)) | ||||
| 	var file File | ||||
| 	for { | ||||
| @@ -59,7 +63,9 @@ func (f *File) Data() []byte { | ||||
| 	// sort the massge as ReferenceFile/ReferenceLine field | ||||
| 	var messages []Message | ||||
| 	messages = append(messages, f.Messages...) | ||||
| 	sort.Sort(byMessages(messages)) | ||||
| 	sort.Slice(messages, func(i, j int) bool { | ||||
| 		return messages[i].less(&messages[j]) | ||||
| 	}) | ||||
| 
 | ||||
| 	var buf bytes.Buffer | ||||
| 	fmt.Fprintf(&buf, "%s\n", f.MimeHeader.String()) | ||||
| @@ -26,29 +26,21 @@ type Message struct { | ||||
| 	MsgStrPlural []string // msgstr[0] translated-string-case-0 | ||||
| } | ||||
| 
 | ||||
| type byMessages []Message | ||||
| 
 | ||||
| func (d byMessages) Len() int { | ||||
| 	return len(d) | ||||
| } | ||||
| func (d byMessages) Less(i, j int) bool { | ||||
| 	if d[i].Comment.less(&d[j].Comment) { | ||||
| func (p *Message) less(q *Message) bool { | ||||
| 	if p.Comment.less(&q.Comment) { | ||||
| 		return true | ||||
| 	} | ||||
| 	if a, b := d[i].MsgContext, d[j].MsgContext; a != b { | ||||
| 	if a, b := p.MsgContext, q.MsgContext; a != b { | ||||
| 		return a < b | ||||
| 	} | ||||
| 	if a, b := d[i].MsgId, d[j].MsgId; a != b { | ||||
| 	if a, b := p.MsgId, q.MsgId; a != b { | ||||
| 		return a < b | ||||
| 	} | ||||
| 	if a, b := d[i].MsgIdPlural, d[j].MsgIdPlural; a != b { | ||||
| 	if a, b := p.MsgIdPlural, q.MsgIdPlural; a != b { | ||||
| 		return a < b | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| func (d byMessages) Swap(i, j int) { | ||||
| 	d[i], d[j] = d[j], d[i] | ||||
| } | ||||
| 
 | ||||
| func (p *Message) readPoEntry(r *lineReader) (err error) { | ||||
| 	*p = Message{} | ||||
| @@ -175,15 +167,27 @@ func (p *Message) readString(r *lineReader) (msg string, err error) { | ||||
| func (p Message) String() string { | ||||
| 	var buf bytes.Buffer | ||||
| 	fmt.Fprintf(&buf, "%s", p.Comment.String()) | ||||
| 	if p.MsgContext != "" { | ||||
| 		fmt.Fprintf(&buf, "msgctxt %s", encodePoString(p.MsgContext)) | ||||
| 	} | ||||
| 	fmt.Fprintf(&buf, "msgid %s", encodePoString(p.MsgId)) | ||||
| 	if p.MsgIdPlural != "" { | ||||
| 		fmt.Fprintf(&buf, "msgid_plural %s", encodePoString(p.MsgIdPlural)) | ||||
| 	} | ||||
| 	if p.MsgStr != "" { | ||||
| 		fmt.Fprintf(&buf, "msgstr %s", encodePoString(p.MsgStr)) | ||||
| 	} | ||||
| 	for i := 0; i < len(p.MsgStrPlural); i++ { | ||||
| 		fmt.Fprintf(&buf, "msgstr[%d] %s", i, encodePoString(p.MsgStrPlural[i])) | ||||
| 	if len(p.MsgStrPlural) == 0 { | ||||
| 		if p.MsgStr != "" { | ||||
| 			fmt.Fprintf(&buf, "msgstr %s", encodePoString(p.MsgStr)) | ||||
| 		} else { | ||||
| 			fmt.Fprintf(&buf, "msgstr %s", `""`+"\n") | ||||
| 		} | ||||
| 	} else { | ||||
| 		for i := 0; i < len(p.MsgStrPlural); i++ { | ||||
| 			if p.MsgStrPlural[i] != "" { | ||||
| 				fmt.Fprintf(&buf, "msgstr[%d] %s", i, encodePoString(p.MsgStrPlural[i])) | ||||
| 			} else { | ||||
| 				fmt.Fprintf(&buf, "msgstr[%d] %s", i, `""`+"\n") | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
| @@ -70,7 +70,11 @@ func encodePoString(text string) string { | ||||
| 				buf.WriteRune(r) | ||||
| 			} | ||||
| 		} | ||||
| 		buf.WriteString(`\n"` + "\n") | ||||
| 		if i < len(lines)-1 { | ||||
| 			buf.WriteString(`\n"` + "\n") | ||||
| 		} else { | ||||
| 			buf.WriteString(`"` + "\n") | ||||
| 		} | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
| @@ -5,9 +5,11 @@ | ||||
| package gettext | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/chai2010/gettext-go/gettext/mo" | ||||
| 	"github.com/chai2010/gettext-go/gettext/plural" | ||||
| 	"github.com/chai2010/gettext-go/gettext/po" | ||||
| 	"encoding/json" | ||||
| 
 | ||||
| 	"github.com/chai2010/gettext-go/mo" | ||||
| 	"github.com/chai2010/gettext-go/plural" | ||||
| 	"github.com/chai2010/gettext-go/po" | ||||
| ) | ||||
| 
 | ||||
| var nilTranslator = &translator{ | ||||
| @@ -26,9 +28,9 @@ func newMoTranslator(name string, data []byte) (*translator, error) { | ||||
| 		err error | ||||
| 	) | ||||
| 	if len(data) != 0 { | ||||
| 		f, err = mo.LoadData(data) | ||||
| 		f, err = mo.Load(data) | ||||
| 	} else { | ||||
| 		f, err = mo.Load(name) | ||||
| 		f, err = mo.LoadFile(name) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -53,9 +55,9 @@ func newPoTranslator(name string, data []byte) (*translator, error) { | ||||
| 		err error | ||||
| 	) | ||||
| 	if len(data) != 0 { | ||||
| 		f, err = po.LoadData(data) | ||||
| 		f, err = po.Load(data) | ||||
| 	} else { | ||||
| 		f, err = po.Load(name) | ||||
| 		f, err = po.LoadFile(name) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -80,8 +82,43 @@ func newPoTranslator(name string, data []byte) (*translator, error) { | ||||
| 	return tr, nil | ||||
| } | ||||
| 
 | ||||
| func newJsonTranslator(lang, name string, jsonData []byte) (*translator, error) { | ||||
| 	var msgList []struct { | ||||
| 		MsgContext  string   `json:"msgctxt"`      // msgctxt context | ||||
| 		MsgId       string   `json:"msgid"`        // msgid untranslated-string | ||||
| 		MsgIdPlural string   `json:"msgid_plural"` // msgid_plural untranslated-string-plural | ||||
| 		MsgStr      []string `json:"msgstr"`       // msgstr translated-string | ||||
| 	} | ||||
| 	if err := json.Unmarshal(jsonData, &msgList); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	var tr = &translator{ | ||||
| 		MessageMap:    make(map[string]mo.Message), | ||||
| 		PluralFormula: plural.Formula(lang), | ||||
| 	} | ||||
| 
 | ||||
| 	for _, v := range msgList { | ||||
| 		var v_MsgStr string | ||||
| 		var v_MsgStrPlural = v.MsgStr | ||||
| 
 | ||||
| 		if len(v.MsgStr) != 0 { | ||||
| 			v_MsgStr = v.MsgStr[0] | ||||
| 		} | ||||
| 
 | ||||
| 		tr.MessageMap[tr.makeMapKey(v.MsgContext, v.MsgId)] = mo.Message{ | ||||
| 			MsgContext:   v.MsgContext, | ||||
| 			MsgId:        v.MsgId, | ||||
| 			MsgIdPlural:  v.MsgIdPlural, | ||||
| 			MsgStr:       v_MsgStr, | ||||
| 			MsgStrPlural: v_MsgStrPlural, | ||||
| 		} | ||||
| 	} | ||||
| 	return tr, nil | ||||
| } | ||||
| 
 | ||||
| func (p *translator) PGettext(msgctxt, msgid string) string { | ||||
| 	return p.PNGettext(msgctxt, msgid, "", 0) | ||||
| 	return p.findMsgStr(msgctxt, msgid) | ||||
| } | ||||
| 
 | ||||
| func (p *translator) PNGettext(msgctxt, msgid, msgidPlural string, n int) string { | ||||
| @@ -100,6 +137,16 @@ func (p *translator) PNGettext(msgctxt, msgid, msgidPlural string, n int) string | ||||
| 	return msgid | ||||
| } | ||||
| 
 | ||||
| func (p *translator) findMsgStr(msgctxt, msgid string) string { | ||||
| 	key := p.makeMapKey(msgctxt, msgid) | ||||
| 	if v, ok := p.MessageMap[key]; ok { | ||||
| 		if v.MsgStr != "" { | ||||
| 			return v.MsgStr | ||||
| 		} | ||||
| 	} | ||||
| 	return msgid | ||||
| } | ||||
| 
 | ||||
| func (p *translator) findMsgStrPlural(msgctxt, msgid, msgidPlural string) []string { | ||||
| 	key := p.makeMapKey(msgctxt, msgid) | ||||
| 	if v, ok := p.MessageMap[key]; ok { | ||||
| @@ -9,17 +9,17 @@ import ( | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| func getDefaultLocale() string { | ||||
| func getDefaultLanguage() string { | ||||
| 	if v := os.Getenv("LC_MESSAGES"); v != "" { | ||||
| 		return simplifiedLocale(v) | ||||
| 		return simplifiedLanguage(v) | ||||
| 	} | ||||
| 	if v := os.Getenv("LANG"); v != "" { | ||||
| 		return simplifiedLocale(v) | ||||
| 		return simplifiedLanguage(v) | ||||
| 	} | ||||
| 	return "default" | ||||
| } | ||||
| 
 | ||||
| func simplifiedLocale(lang string) string { | ||||
| func simplifiedLanguage(lang string) string { | ||||
| 	// en_US/en_US.UTF-8/zh_CN/zh_TW/el_GR@euro/... | ||||
| 	if idx := strings.Index(lang, ":"); idx != -1 { | ||||
| 		lang = lang[:idx] | ||||
							
								
								
									
										14
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							| @@ -173,12 +173,12 @@ github.com/blang/semver/v4 | ||||
| # github.com/cespare/xxhash/v2 v2.1.2 => github.com/cespare/xxhash/v2 v2.1.2 | ||||
| ## explicit; go 1.11 | ||||
| github.com/cespare/xxhash/v2 | ||||
| # github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 => github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 | ||||
| ## explicit | ||||
| github.com/chai2010/gettext-go/gettext | ||||
| github.com/chai2010/gettext-go/gettext/mo | ||||
| github.com/chai2010/gettext-go/gettext/plural | ||||
| github.com/chai2010/gettext-go/gettext/po | ||||
| # github.com/chai2010/gettext-go v1.0.2 => github.com/chai2010/gettext-go v1.0.2 | ||||
| ## explicit; go 1.14 | ||||
| github.com/chai2010/gettext-go | ||||
| github.com/chai2010/gettext-go/mo | ||||
| github.com/chai2010/gettext-go/plural | ||||
| github.com/chai2010/gettext-go/po | ||||
| # github.com/checkpoint-restore/go-criu/v5 v5.3.0 => github.com/checkpoint-restore/go-criu/v5 v5.3.0 | ||||
| ## explicit; go 1.13 | ||||
| github.com/checkpoint-restore/go-criu/v5 | ||||
| @@ -2591,7 +2591,7 @@ sigs.k8s.io/yaml | ||||
| # github.com/census-instrumentation/opencensus-proto => github.com/census-instrumentation/opencensus-proto v0.2.1 | ||||
| # github.com/certifi/gocertifi => github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 | ||||
| # github.com/cespare/xxhash/v2 => github.com/cespare/xxhash/v2 v2.1.2 | ||||
| # github.com/chai2010/gettext-go => github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 | ||||
| # github.com/chai2010/gettext-go => github.com/chai2010/gettext-go v1.0.2 | ||||
| # github.com/checkpoint-restore/go-criu/v5 => github.com/checkpoint-restore/go-criu/v5 v5.3.0 | ||||
| # github.com/chzyer/logex => github.com/chzyer/logex v1.1.10 | ||||
| # github.com/chzyer/readline => github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Davanum Srinivas
					Davanum Srinivas