mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 03:11:40 +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:
parent
f3f50b4d7c
commit
1ff96ede74
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
|
||||
|
Loading…
Reference in New Issue
Block a user