First implementation of CLI tool
This commit is contained in:
40
cli/xgotext/README.md
Normal file
40
cli/xgotext/README.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# xgotext
|
||||||
|
|
||||||
|
CLI tool to extract translation strings from Go packages into .PO files.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```
|
||||||
|
go install github.com/leonelquinteros/gotext/cli/xgotext
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
xgotext /path/to/go/package [/path/to/output/dir]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
This is the first (naive) implementation for this tool.
|
||||||
|
|
||||||
|
It will scan the Go package provided for method calls that matches the method names from the gotext package and write the corresponding translation files to the output directory.
|
||||||
|
|
||||||
|
Isn't able to parse calls to translation functions using parameters inside variables, if the translation string is inside a variable and that variable is used to invoke the translation function, this tool won't be able to parse that string. See this example code:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// This line will be added to the .po file
|
||||||
|
gotext.Get("Translate this")
|
||||||
|
|
||||||
|
tr := "Translate this string"
|
||||||
|
// The following line will NOT be added to the .po file
|
||||||
|
gotext.Get(tr)
|
||||||
|
```
|
||||||
|
|
||||||
|
The CLI tool doesn't traverse sub-directories and other packages.
|
||||||
|
|
||||||
|
|
||||||
|
## Contribute
|
||||||
|
|
||||||
|
Please
|
||||||
|
|
||||||
28
cli/xgotext/fixtures/i18n/default.po
Normal file
28
cli/xgotext/fixtures/i18n/default.po
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Language: \n"
|
||||||
|
"X-Generator: xgotext\n"
|
||||||
|
|
||||||
|
|
||||||
|
#: fixtures/main.go:23
|
||||||
|
#. gotext.Get
|
||||||
|
msgid "My text on 'domain-name' domain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: fixtures/main.go:38
|
||||||
|
#. l.GetN
|
||||||
|
msgid "Singular"
|
||||||
|
msgid_plural "Plural"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
|
|
||||||
|
#: fixtures/main.go:40
|
||||||
|
#. l.GetN
|
||||||
|
msgid "SingularVar"
|
||||||
|
msgid_plural "PluralVar"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
15
cli/xgotext/fixtures/i18n/domain.po
Normal file
15
cli/xgotext/fixtures/i18n/domain.po
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Language: \n"
|
||||||
|
"X-Generator: xgotext\n"
|
||||||
|
|
||||||
|
|
||||||
|
#: fixtures/main.go:42
|
||||||
|
#. l.GetDC
|
||||||
|
msgctxt "ctx"
|
||||||
|
msgid "string"
|
||||||
|
msgstr ""
|
||||||
14
cli/xgotext/fixtures/i18n/domain2.po
Normal file
14
cli/xgotext/fixtures/i18n/domain2.po
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Language: \n"
|
||||||
|
"X-Generator: xgotext\n"
|
||||||
|
|
||||||
|
|
||||||
|
#: fixtures/main.go:26
|
||||||
|
#. gotext.GetD
|
||||||
|
msgid "Another text on a different domain"
|
||||||
|
msgstr ""
|
||||||
22
cli/xgotext/fixtures/i18n/translations.po
Normal file
22
cli/xgotext/fixtures/i18n/translations.po
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Language: \n"
|
||||||
|
"X-Generator: xgotext\n"
|
||||||
|
|
||||||
|
|
||||||
|
#: fixtures/main.go:35
|
||||||
|
#. l.GetD
|
||||||
|
msgid "Translate this"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: fixtures/main.go:43
|
||||||
|
#. l.GetNDC
|
||||||
|
msgctxt "NDC-CTX"
|
||||||
|
msgid "ndc"
|
||||||
|
msgid_plural "ndcs"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
47
cli/xgotext/fixtures/main.go
Normal file
47
cli/xgotext/fixtures/main.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fake object with methods similar to gotext
|
||||||
|
type Fake struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get by id
|
||||||
|
func (f Fake) Get(id int) int {
|
||||||
|
return 42
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Configure package
|
||||||
|
gotext.Configure("/path/to/locales/root/dir", "en_UK", "domain-name")
|
||||||
|
|
||||||
|
// Translate text from default domain
|
||||||
|
fmt.Println(gotext.Get("My text on 'domain-name' domain"))
|
||||||
|
|
||||||
|
// Translate text from a different domain without reconfigure
|
||||||
|
fmt.Println(gotext.GetD("domain2", "Another text on a different domain"))
|
||||||
|
|
||||||
|
// Create Locale with library path and language code
|
||||||
|
l := gotext.NewLocale("/path/to/locales/root/dir", "es_UY")
|
||||||
|
|
||||||
|
// Load domain '/path/to/locales/root/dir/es_UY/default.po'
|
||||||
|
l.AddDomain("default")
|
||||||
|
|
||||||
|
// Translate text from domain
|
||||||
|
fmt.Println(l.GetD("translations", "Translate this"))
|
||||||
|
|
||||||
|
// Get plural translations
|
||||||
|
l.GetN("Singular", "Plural", 4)
|
||||||
|
num := 17
|
||||||
|
l.GetN("SingularVar", "PluralVar", num)
|
||||||
|
|
||||||
|
l.GetDC("domain", "string", "ctx")
|
||||||
|
l.GetNDC("translations", "ndc", "ndcs", 7, "NDC-CTX")
|
||||||
|
|
||||||
|
f := Fake{}
|
||||||
|
f.Get(3)
|
||||||
|
}
|
||||||
364
cli/xgotext/main.go
Normal file
364
cli/xgotext/main.go
Normal file
@@ -0,0 +1,364 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
dirName string
|
||||||
|
outputDir string
|
||||||
|
fset *token.FileSet
|
||||||
|
domainFiles map[string]*os.File
|
||||||
|
currentDomain = "default"
|
||||||
|
currentFile string
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Init logger
|
||||||
|
log.SetFlags(0)
|
||||||
|
|
||||||
|
// Init domain files
|
||||||
|
domainFiles = make(map[string]*os.File)
|
||||||
|
|
||||||
|
// Validate args
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
log.Println("Usage: ")
|
||||||
|
log.Fatal("$ xgotext /path/to/package [ /path/to/output/dir ]")
|
||||||
|
}
|
||||||
|
if len(os.Args) > 2 {
|
||||||
|
outputDir = os.Args[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if dir name parameter is valid
|
||||||
|
dirName = os.Args[1]
|
||||||
|
f, err := os.Stat(dirName)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process file or dir
|
||||||
|
if f.IsDir() {
|
||||||
|
parseDir(dirName)
|
||||||
|
} else {
|
||||||
|
parseFile(dirName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDomainFile(domain string) *os.File {
|
||||||
|
// Return existent when available
|
||||||
|
if f, ok := domainFiles[domain]; ok {
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the file doesn't exist, create it.
|
||||||
|
filePath := path.Join(outputDir, domain+".po")
|
||||||
|
f, err := os.OpenFile(filePath, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
domainFiles[domain] = f
|
||||||
|
writePoHeader(f)
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func writePoHeader(f *os.File) {
|
||||||
|
h := `msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Language: \n"
|
||||||
|
"X-Generator: xgotext\n"
|
||||||
|
|
||||||
|
`
|
||||||
|
f.Write([]byte(h))
|
||||||
|
}
|
||||||
|
|
||||||
|
func write(dom, msgid string) {
|
||||||
|
f := getDomainFile(dom)
|
||||||
|
f.Write([]byte("\nmsgid " + msgid))
|
||||||
|
f.Write([]byte("\nmsgstr \"\""))
|
||||||
|
f.Write([]byte("\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func writePlural(dom, msgid, msgidPlural string) {
|
||||||
|
f := getDomainFile(dom)
|
||||||
|
f.Write([]byte("\nmsgid " + msgid))
|
||||||
|
f.Write([]byte("\nmsgid_plural " + msgidPlural))
|
||||||
|
f.Write([]byte("\nmsgstr[0] \"\""))
|
||||||
|
f.Write([]byte("\nmsgstr[1] \"\""))
|
||||||
|
f.Write([]byte("\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeContext(dom, ctx string) {
|
||||||
|
f := getDomainFile(dom)
|
||||||
|
f.Write([]byte("\nmsgctxt " + ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeComments(dom, file, call string) {
|
||||||
|
f := getDomainFile(dom)
|
||||||
|
f.Write([]byte("\n#: " + file))
|
||||||
|
f.Write([]byte("\n#. " + call))
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDir(dirName string) error {
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
pkgs, err := parser.ParseDir(fset, dirName, nil, parser.AllErrors)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range pkgs {
|
||||||
|
for fn := range pkg.Files {
|
||||||
|
parseFile(fn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFile(fileName string) error {
|
||||||
|
// Remember current file to write comments on .po file
|
||||||
|
currentFile = fileName
|
||||||
|
|
||||||
|
// Parse AST
|
||||||
|
fset = token.NewFileSet()
|
||||||
|
node, err := parser.ParseFile(fset, fileName, nil, parser.AllErrors)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
//ast.Print(fset, node)
|
||||||
|
|
||||||
|
ast.Inspect(node, inspectFile)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func inspectFile(n ast.Node) bool {
|
||||||
|
switch x := n.(type) {
|
||||||
|
case *ast.CallExpr:
|
||||||
|
inspectCallExpr(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func inspectCallExpr(n *ast.CallExpr) {
|
||||||
|
if se, ok := n.Fun.(*ast.SelectorExpr); ok {
|
||||||
|
switch se.Sel.String() {
|
||||||
|
case "Get":
|
||||||
|
parseGet(n)
|
||||||
|
|
||||||
|
case "GetN":
|
||||||
|
parseGetN(n)
|
||||||
|
|
||||||
|
case "GetD":
|
||||||
|
parseGetD(n)
|
||||||
|
|
||||||
|
case "GetND":
|
||||||
|
parseGetND(n)
|
||||||
|
|
||||||
|
case "GetC":
|
||||||
|
parseGetC(n)
|
||||||
|
|
||||||
|
case "GetNC":
|
||||||
|
parseGetNC(n)
|
||||||
|
|
||||||
|
case "GetDC":
|
||||||
|
parseGetDC(n)
|
||||||
|
|
||||||
|
case "GetNDC":
|
||||||
|
parseGetNDC(n)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGet(call *ast.CallExpr) {
|
||||||
|
// Expect first param to be string
|
||||||
|
if call.Args != nil && len(call.Args) > 0 {
|
||||||
|
if lit, ok := call.Args[0].(*ast.BasicLit); ok {
|
||||||
|
if lit.Kind == token.STRING {
|
||||||
|
writeComments(currentDomain,
|
||||||
|
fmt.Sprintf("%s:%d", fset.Position(call.Lparen).Filename, fset.Position(call.Lparen).Line),
|
||||||
|
fmt.Sprintf("%s.%s", call.Fun.(*ast.SelectorExpr).X.(*ast.Ident).Name, call.Fun.(*ast.SelectorExpr).Sel.String()),
|
||||||
|
)
|
||||||
|
write(currentDomain, lit.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGetN(call *ast.CallExpr) {
|
||||||
|
// Expect at least 3 params, first 2 strings, third int
|
||||||
|
if call.Args == nil || len(call.Args) < 3 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if lit, ok := call.Args[0].(*ast.BasicLit); ok {
|
||||||
|
if lit1, ok1 := call.Args[1].(*ast.BasicLit); ok1 {
|
||||||
|
if lit.Kind == token.STRING && lit1.Kind == token.STRING {
|
||||||
|
switch x := call.Args[2].(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if x.Kind != token.INT {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.Ident:
|
||||||
|
if x.Obj.Kind != ast.Var && x.Obj.Kind != ast.Con {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeComments(currentDomain,
|
||||||
|
fmt.Sprintf("%s:%d", fset.Position(call.Lparen).Filename, fset.Position(call.Lparen).Line),
|
||||||
|
fmt.Sprintf("%s.%s", call.Fun.(*ast.SelectorExpr).X.(*ast.Ident).Name, call.Fun.(*ast.SelectorExpr).Sel.String()),
|
||||||
|
)
|
||||||
|
writePlural(currentDomain, lit.Value, lit1.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGetD(call *ast.CallExpr) {
|
||||||
|
// Expect first 2 params to be string
|
||||||
|
if call.Args != nil && len(call.Args) > 1 {
|
||||||
|
if lit, ok := call.Args[0].(*ast.BasicLit); ok {
|
||||||
|
if lit1, ok := call.Args[1].(*ast.BasicLit); ok {
|
||||||
|
if lit.Kind == token.STRING && lit1.Kind == token.STRING {
|
||||||
|
dom, err := strconv.Unquote(lit.Value)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
writeComments(dom,
|
||||||
|
fmt.Sprintf("%s:%d", fset.Position(call.Lparen).Filename, fset.Position(call.Lparen).Line),
|
||||||
|
fmt.Sprintf("%s.%s", call.Fun.(*ast.SelectorExpr).X.(*ast.Ident).Name, call.Fun.(*ast.SelectorExpr).Sel.String()),
|
||||||
|
)
|
||||||
|
write(dom, lit1.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGetND(call *ast.CallExpr) {
|
||||||
|
// Expect first 3 params to be string
|
||||||
|
if call.Args != nil && len(call.Args) > 2 {
|
||||||
|
if lit, ok := call.Args[0].(*ast.BasicLit); ok {
|
||||||
|
if lit1, ok := call.Args[1].(*ast.BasicLit); ok {
|
||||||
|
if lit2, ok := call.Args[2].(*ast.BasicLit); ok {
|
||||||
|
if lit.Kind == token.STRING && lit1.Kind == token.STRING && lit2.Kind == token.STRING {
|
||||||
|
dom, err := strconv.Unquote(lit.Value)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
writeComments(dom,
|
||||||
|
fmt.Sprintf("%s:%d", fset.Position(call.Lparen).Filename, fset.Position(call.Lparen).Line),
|
||||||
|
fmt.Sprintf("%s.%s", call.Fun.(*ast.SelectorExpr).X.(*ast.Ident).Name, call.Fun.(*ast.SelectorExpr).Sel.String()),
|
||||||
|
)
|
||||||
|
writePlural(dom, lit1.Value, lit2.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGetC(call *ast.CallExpr) {
|
||||||
|
// Expect first 2 params to be string
|
||||||
|
if call.Args != nil && len(call.Args) > 1 {
|
||||||
|
if lit, ok := call.Args[0].(*ast.BasicLit); ok {
|
||||||
|
if lit1, ok := call.Args[1].(*ast.BasicLit); ok {
|
||||||
|
if lit.Kind == token.STRING && lit1.Kind == token.STRING {
|
||||||
|
writeComments(currentDomain,
|
||||||
|
fmt.Sprintf("%s:%d", fset.Position(call.Lparen).Filename, fset.Position(call.Lparen).Line),
|
||||||
|
fmt.Sprintf("%s.%s", call.Fun.(*ast.SelectorExpr).X.(*ast.Ident).Name, call.Fun.(*ast.SelectorExpr).Sel.String()),
|
||||||
|
)
|
||||||
|
writeContext(currentDomain, lit1.Value)
|
||||||
|
write(currentDomain, lit.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGetNC(call *ast.CallExpr) {
|
||||||
|
// Expect at least 4 params. 1, 2, and 3 as string
|
||||||
|
if call.Args != nil && len(call.Args) > 3 {
|
||||||
|
if lit, ok := call.Args[0].(*ast.BasicLit); ok {
|
||||||
|
if lit1, ok := call.Args[1].(*ast.BasicLit); ok {
|
||||||
|
if lit3, ok := call.Args[3].(*ast.BasicLit); ok {
|
||||||
|
if lit.Kind == token.STRING && lit1.Kind == token.STRING && lit3.Kind == token.STRING {
|
||||||
|
writeComments(currentDomain,
|
||||||
|
fmt.Sprintf("%s:%d", fset.Position(call.Lparen).Filename, fset.Position(call.Lparen).Line),
|
||||||
|
fmt.Sprintf("%s.%s", call.Fun.(*ast.SelectorExpr).X.(*ast.Ident).Name, call.Fun.(*ast.SelectorExpr).Sel.String()),
|
||||||
|
)
|
||||||
|
writeContext(currentDomain, lit3.Value)
|
||||||
|
writePlural(currentDomain, lit.Value, lit1.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGetDC(call *ast.CallExpr) {
|
||||||
|
if call.Args != nil && len(call.Args) > 2 {
|
||||||
|
if lit, ok := call.Args[0].(*ast.BasicLit); ok {
|
||||||
|
if lit1, ok := call.Args[1].(*ast.BasicLit); ok {
|
||||||
|
if lit2, ok := call.Args[2].(*ast.BasicLit); ok {
|
||||||
|
if lit.Kind == token.STRING && lit1.Kind == token.STRING && lit2.Kind == token.STRING {
|
||||||
|
dom, err := strconv.Unquote(lit.Value)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
writeComments(dom,
|
||||||
|
fmt.Sprintf("%s:%d", fset.Position(call.Lparen).Filename, fset.Position(call.Lparen).Line),
|
||||||
|
fmt.Sprintf("%s.%s", call.Fun.(*ast.SelectorExpr).X.(*ast.Ident).Name, call.Fun.(*ast.SelectorExpr).Sel.String()),
|
||||||
|
)
|
||||||
|
writeContext(dom, lit2.Value)
|
||||||
|
write(dom, lit1.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGetNDC(call *ast.CallExpr) {
|
||||||
|
if call.Args != nil && len(call.Args) > 4 {
|
||||||
|
if lit, ok := call.Args[0].(*ast.BasicLit); ok {
|
||||||
|
if lit1, ok := call.Args[1].(*ast.BasicLit); ok {
|
||||||
|
if lit2, ok := call.Args[2].(*ast.BasicLit); ok {
|
||||||
|
if lit4, ok := call.Args[4].(*ast.BasicLit); ok {
|
||||||
|
if lit.Kind == token.STRING && lit1.Kind == token.STRING && lit2.Kind == token.STRING && lit4.Kind == token.STRING {
|
||||||
|
dom, err := strconv.Unquote(lit.Value)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
writeComments(dom,
|
||||||
|
fmt.Sprintf("%s:%d", fset.Position(call.Lparen).Filename, fset.Position(call.Lparen).Line),
|
||||||
|
fmt.Sprintf("%s.%s", call.Fun.(*ast.SelectorExpr).X.(*ast.Ident).Name, call.Fun.(*ast.SelectorExpr).Sel.String()),
|
||||||
|
)
|
||||||
|
writeContext(dom, lit4.Value)
|
||||||
|
writePlural(dom, lit1.Value, lit2.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -152,7 +152,7 @@ func (l *Locale) AddTranslator(dom string, tr Translator) {
|
|||||||
l.Unlock()
|
l.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDomain is the domain getter for the package configuration
|
// GetDomain is the domain getter for Locale configuration
|
||||||
func (l *Locale) GetDomain() string {
|
func (l *Locale) GetDomain() string {
|
||||||
l.RLock()
|
l.RLock()
|
||||||
dom := l.defaultDomain
|
dom := l.defaultDomain
|
||||||
|
|||||||
Reference in New Issue
Block a user