message/pipeline: hoist export code from cmd/text Change-Id: I51ff721870bd91ade99d7afede56556535bc93bc Reviewed-on: https://go-review.googlesource.com/83818 Run-TryBot: Marcel van Lohuizen <mpvl@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/cmd/gotext/extract.go b/cmd/gotext/extract.go index 221e776..8c80670 100644 --- a/cmd/gotext/extract.go +++ b/cmd/gotext/extract.go
@@ -5,12 +5,6 @@ package main import ( - "encoding/json" - "io/ioutil" - "os" - "path/filepath" - - "golang.org/x/text/internal" "golang.org/x/text/message/pipeline" ) @@ -40,24 +34,5 @@ if err != nil { return wrap(err, "extract failed") } - out := state.Extracted - - langs := append(getLangs(), config.SourceLanguage) - langs = internal.UniqueTags(langs) - for _, tag := range langs { - // TODO: inject translations from existing files to avoid retranslation. - out.Language = tag - data, err := json.MarshalIndent(out, "", " ") - if err != nil { - return wrap(err, "JSON marshal failed") - } - file := filepath.Join(*dir, tag.String(), outFile) - if err := os.MkdirAll(filepath.Dir(file), 0750); err != nil { - return wrap(err, "dir create failed") - } - if err := ioutil.WriteFile(file, data, 0740); err != nil { - return wrap(err, "write failed") - } - } - return nil + return wrap(state.Export(), "export failed") }
diff --git a/message/pipeline/pipeline.go b/message/pipeline/pipeline.go index 8087bf6..ff4505f 100644 --- a/message/pipeline/pipeline.go +++ b/message/pipeline/pipeline.go
@@ -15,12 +15,14 @@ "go/parser" "io/ioutil" "log" + "os" "path/filepath" "regexp" "strings" "text/template" "unicode" + "golang.org/x/text/internal" "golang.org/x/text/language" "golang.org/x/text/runes" "golang.org/x/tools/go/loader" @@ -248,7 +250,31 @@ // Export writes out the messages to translation out files. func (s *State) Export() error { - panic("unimplemented") + langs := []language.Tag{s.Config.SourceLanguage} + for _, t := range s.Translations { + langs = append(langs, t.Language) + } + langs = internal.UniqueTags(langs) + out := s.Extracted + path, err := outPattern(s) + if err != nil { + return wrap(err, "export failed") + } + for _, tag := range langs { + // TODO: inject translations from existing files to avoid retranslation. + out.Language = tag + data, err := json.MarshalIndent(out, "", " ") + if err != nil { + return wrap(err, "JSON marshal failed") + } + file := fmt.Sprintf(path, tag) + if err := os.MkdirAll(filepath.Dir(file), 0755); err != nil { + return wrap(err, "dir create failed") + } + if err := ioutil.WriteFile(file, data, 0644); err != nil { + return wrap(err, "write failed") + } + } return nil }
diff --git a/message/pipeline/pipeline_test.go b/message/pipeline/pipeline_test.go index 198d47f..78815f1 100644 --- a/message/pipeline/pipeline_test.go +++ b/message/pipeline/pipeline_test.go
@@ -57,7 +57,7 @@ // for range s.Config.Actions { // // TODO: do the actions. // } - // chk(t, s.Export()) // TODO + chk(t, s.Export()) chk(t, s.Generate()) writeJSON(t, filepath.Join(dir, "extracted.gotext.json"), s.Extracted) @@ -93,14 +93,10 @@ scanWant := bufio.NewScanner(bytes.NewReader(want)) line := 0 clean := func(s string) string { - s = path.Clean(filepath.ToSlash(s)) - if i := strings.LastIndex(s, "Size:"); i != -1 { + if i := strings.LastIndex(s, "//"); i != -1 { s = s[:i] } - if i := strings.LastIndex(s, "Total table size"); i != -1 { - s = s[:i] - } - return s + return path.Clean(filepath.ToSlash(s)) } for scanGot.Scan() && scanWant.Scan() { got := clean(scanGot.Text())
diff --git a/message/pipeline/testdata/test1/catalog_test.go b/message/pipeline/testdata/test1/catalog_test.go new file mode 100644 index 0000000..eeb7c25 --- /dev/null +++ b/message/pipeline/testdata/test1/catalog_test.go
@@ -0,0 +1,49 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "path" + "testing" + + "golang.org/x/text/message" +) + +func TestCatalog(t *testing.T) { + args := func(a ...interface{}) []interface{} { return a } + testCases := []struct { + lang string + key string + args []interface{} + want string + }{{ + lang: "en", + key: "Hello world!\n", + want: "Hello world!\n", + }, { + lang: "de", + key: "Hello world!\n", + want: "Hallo Welt!\n", + }, { + lang: "en", + key: "%d more files remaining!", + args: args(1), + want: "One file remaining!", + }, { + lang: "en-u-nu-fullwide", + key: "%d more files remaining!", + args: args(5), + want: "There are 5 more files remaining!", + }} + for _, tc := range testCases { + t.Run(path.Join(tc.lang, tc.key), func(t *testing.T) { + p := message.NewPrinter(message.MatchLanguage(tc.lang)) + got := p.Sprintf(tc.key, tc.args...) + if got != tc.want { + t.Errorf("got %q; want %q", got, tc.want) + } + }) + } +}
diff --git a/message/pipeline/testdata/test1/locales/de/out.gotext.json b/message/pipeline/testdata/test1/locales/de/out.gotext.json new file mode 100755 index 0000000..9c7e594 --- /dev/null +++ b/message/pipeline/testdata/test1/locales/de/out.gotext.json
@@ -0,0 +1,188 @@ +{ + "language": "de", + "messages": [ + { + "id": "Hello world!", + "key": "Hello world!\n", + "message": "Hello world!", + "translation": "", + "position": "testdata/test1/test1.go:19:10" + }, + { + "id": "Hello {City}!", + "key": "Hello %s!\n", + "message": "Hello {City}!", + "translation": "", + "placeholders": [ + { + "id": "City", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "city" + } + ], + "position": "testdata/test1/test1.go:24:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%s is visiting %s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "person", + "comment": "The person of matter." + }, + { + "id": "Place", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "place", + "comment": "Place the person is visiting." + } + ], + "position": "testdata/test1/test1.go:30:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%[1]s is visiting %[3]s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "comment": "Field names are placeholders.", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "pp.Person" + }, + { + "id": "Place", + "string": "%[3]s", + "type": "string", + "underlyingType": "string", + "argNum": 3, + "expr": "pp.Place", + "comment": "Place the person is visiting." + }, + { + "id": "Extra", + "string": "%[2]v", + "type": "int", + "underlyingType": "int", + "argNum": 2, + "expr": "pp.extra" + } + ], + "position": "testdata/test1/test1.go:44:10" + }, + { + "id": "{2} files remaining!", + "key": "%d files remaining!", + "message": "{2} files remaining!", + "translation": "", + "placeholders": [ + { + "id": "2", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "2" + } + ], + "position": "testdata/test1/test1.go:51:10" + }, + { + "id": "{N} more files remaining!", + "key": "%d more files remaining!", + "message": "{N} more files remaining!", + "translation": "", + "placeholders": [ + { + "id": "N", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "n" + } + ], + "position": "testdata/test1/test1.go:56:10" + }, + { + "id": "Use the following code for your discount: {ReferralCode}", + "key": "Use the following code for your discount: %d\n", + "message": "Use the following code for your discount: {ReferralCode}", + "translation": "", + "placeholders": [ + { + "id": "ReferralCode", + "string": "%[1]d", + "type": "./testdata/test1.referralCode", + "underlyingType": "int", + "argNum": 1, + "expr": "c" + } + ], + "position": "testdata/test1/test1.go:64:10" + }, + { + "id": [ + "msgOutOfOrder", + "{Device} is out of order!" + ], + "key": "%s is out of order!", + "message": "{Device} is out of order!", + "translation": "", + "comment": "This comment wins.\n", + "placeholders": [ + { + "id": "Device", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "device" + } + ], + "position": "testdata/test1/test1.go:70:10" + }, + { + "id": "{Miles} miles traveled ({Miles_1})", + "key": "%.2[1]f miles traveled (%[1]f)", + "message": "{Miles} miles traveled ({Miles_1})", + "translation": "", + "placeholders": [ + { + "id": "Miles", + "string": "%.2[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + }, + { + "id": "Miles_1", + "string": "%[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + } + ], + "position": "testdata/test1/test1.go:74:10" + } + ] +} \ No newline at end of file
diff --git a/message/pipeline/testdata/test1/locales/de/out.gotext.json.want b/message/pipeline/testdata/test1/locales/de/out.gotext.json.want new file mode 100755 index 0000000..9c7e594 --- /dev/null +++ b/message/pipeline/testdata/test1/locales/de/out.gotext.json.want
@@ -0,0 +1,188 @@ +{ + "language": "de", + "messages": [ + { + "id": "Hello world!", + "key": "Hello world!\n", + "message": "Hello world!", + "translation": "", + "position": "testdata/test1/test1.go:19:10" + }, + { + "id": "Hello {City}!", + "key": "Hello %s!\n", + "message": "Hello {City}!", + "translation": "", + "placeholders": [ + { + "id": "City", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "city" + } + ], + "position": "testdata/test1/test1.go:24:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%s is visiting %s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "person", + "comment": "The person of matter." + }, + { + "id": "Place", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "place", + "comment": "Place the person is visiting." + } + ], + "position": "testdata/test1/test1.go:30:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%[1]s is visiting %[3]s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "comment": "Field names are placeholders.", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "pp.Person" + }, + { + "id": "Place", + "string": "%[3]s", + "type": "string", + "underlyingType": "string", + "argNum": 3, + "expr": "pp.Place", + "comment": "Place the person is visiting." + }, + { + "id": "Extra", + "string": "%[2]v", + "type": "int", + "underlyingType": "int", + "argNum": 2, + "expr": "pp.extra" + } + ], + "position": "testdata/test1/test1.go:44:10" + }, + { + "id": "{2} files remaining!", + "key": "%d files remaining!", + "message": "{2} files remaining!", + "translation": "", + "placeholders": [ + { + "id": "2", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "2" + } + ], + "position": "testdata/test1/test1.go:51:10" + }, + { + "id": "{N} more files remaining!", + "key": "%d more files remaining!", + "message": "{N} more files remaining!", + "translation": "", + "placeholders": [ + { + "id": "N", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "n" + } + ], + "position": "testdata/test1/test1.go:56:10" + }, + { + "id": "Use the following code for your discount: {ReferralCode}", + "key": "Use the following code for your discount: %d\n", + "message": "Use the following code for your discount: {ReferralCode}", + "translation": "", + "placeholders": [ + { + "id": "ReferralCode", + "string": "%[1]d", + "type": "./testdata/test1.referralCode", + "underlyingType": "int", + "argNum": 1, + "expr": "c" + } + ], + "position": "testdata/test1/test1.go:64:10" + }, + { + "id": [ + "msgOutOfOrder", + "{Device} is out of order!" + ], + "key": "%s is out of order!", + "message": "{Device} is out of order!", + "translation": "", + "comment": "This comment wins.\n", + "placeholders": [ + { + "id": "Device", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "device" + } + ], + "position": "testdata/test1/test1.go:70:10" + }, + { + "id": "{Miles} miles traveled ({Miles_1})", + "key": "%.2[1]f miles traveled (%[1]f)", + "message": "{Miles} miles traveled ({Miles_1})", + "translation": "", + "placeholders": [ + { + "id": "Miles", + "string": "%.2[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + }, + { + "id": "Miles_1", + "string": "%[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + } + ], + "position": "testdata/test1/test1.go:74:10" + } + ] +} \ No newline at end of file
diff --git a/message/pipeline/testdata/test1/locales/en-US/out.gotext.json b/message/pipeline/testdata/test1/locales/en-US/out.gotext.json new file mode 100755 index 0000000..4d317af --- /dev/null +++ b/message/pipeline/testdata/test1/locales/en-US/out.gotext.json
@@ -0,0 +1,188 @@ +{ + "language": "en-US", + "messages": [ + { + "id": "Hello world!", + "key": "Hello world!\n", + "message": "Hello world!", + "translation": "", + "position": "testdata/test1/test1.go:19:10" + }, + { + "id": "Hello {City}!", + "key": "Hello %s!\n", + "message": "Hello {City}!", + "translation": "", + "placeholders": [ + { + "id": "City", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "city" + } + ], + "position": "testdata/test1/test1.go:24:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%s is visiting %s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "person", + "comment": "The person of matter." + }, + { + "id": "Place", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "place", + "comment": "Place the person is visiting." + } + ], + "position": "testdata/test1/test1.go:30:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%[1]s is visiting %[3]s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "comment": "Field names are placeholders.", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "pp.Person" + }, + { + "id": "Place", + "string": "%[3]s", + "type": "string", + "underlyingType": "string", + "argNum": 3, + "expr": "pp.Place", + "comment": "Place the person is visiting." + }, + { + "id": "Extra", + "string": "%[2]v", + "type": "int", + "underlyingType": "int", + "argNum": 2, + "expr": "pp.extra" + } + ], + "position": "testdata/test1/test1.go:44:10" + }, + { + "id": "{2} files remaining!", + "key": "%d files remaining!", + "message": "{2} files remaining!", + "translation": "", + "placeholders": [ + { + "id": "2", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "2" + } + ], + "position": "testdata/test1/test1.go:51:10" + }, + { + "id": "{N} more files remaining!", + "key": "%d more files remaining!", + "message": "{N} more files remaining!", + "translation": "", + "placeholders": [ + { + "id": "N", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "n" + } + ], + "position": "testdata/test1/test1.go:56:10" + }, + { + "id": "Use the following code for your discount: {ReferralCode}", + "key": "Use the following code for your discount: %d\n", + "message": "Use the following code for your discount: {ReferralCode}", + "translation": "", + "placeholders": [ + { + "id": "ReferralCode", + "string": "%[1]d", + "type": "./testdata/test1.referralCode", + "underlyingType": "int", + "argNum": 1, + "expr": "c" + } + ], + "position": "testdata/test1/test1.go:64:10" + }, + { + "id": [ + "msgOutOfOrder", + "{Device} is out of order!" + ], + "key": "%s is out of order!", + "message": "{Device} is out of order!", + "translation": "", + "comment": "This comment wins.\n", + "placeholders": [ + { + "id": "Device", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "device" + } + ], + "position": "testdata/test1/test1.go:70:10" + }, + { + "id": "{Miles} miles traveled ({Miles_1})", + "key": "%.2[1]f miles traveled (%[1]f)", + "message": "{Miles} miles traveled ({Miles_1})", + "translation": "", + "placeholders": [ + { + "id": "Miles", + "string": "%.2[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + }, + { + "id": "Miles_1", + "string": "%[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + } + ], + "position": "testdata/test1/test1.go:74:10" + } + ] +} \ No newline at end of file
diff --git a/message/pipeline/testdata/test1/locales/en-US/out.gotext.json.want b/message/pipeline/testdata/test1/locales/en-US/out.gotext.json.want new file mode 100755 index 0000000..4d317af --- /dev/null +++ b/message/pipeline/testdata/test1/locales/en-US/out.gotext.json.want
@@ -0,0 +1,188 @@ +{ + "language": "en-US", + "messages": [ + { + "id": "Hello world!", + "key": "Hello world!\n", + "message": "Hello world!", + "translation": "", + "position": "testdata/test1/test1.go:19:10" + }, + { + "id": "Hello {City}!", + "key": "Hello %s!\n", + "message": "Hello {City}!", + "translation": "", + "placeholders": [ + { + "id": "City", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "city" + } + ], + "position": "testdata/test1/test1.go:24:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%s is visiting %s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "person", + "comment": "The person of matter." + }, + { + "id": "Place", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "place", + "comment": "Place the person is visiting." + } + ], + "position": "testdata/test1/test1.go:30:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%[1]s is visiting %[3]s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "comment": "Field names are placeholders.", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "pp.Person" + }, + { + "id": "Place", + "string": "%[3]s", + "type": "string", + "underlyingType": "string", + "argNum": 3, + "expr": "pp.Place", + "comment": "Place the person is visiting." + }, + { + "id": "Extra", + "string": "%[2]v", + "type": "int", + "underlyingType": "int", + "argNum": 2, + "expr": "pp.extra" + } + ], + "position": "testdata/test1/test1.go:44:10" + }, + { + "id": "{2} files remaining!", + "key": "%d files remaining!", + "message": "{2} files remaining!", + "translation": "", + "placeholders": [ + { + "id": "2", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "2" + } + ], + "position": "testdata/test1/test1.go:51:10" + }, + { + "id": "{N} more files remaining!", + "key": "%d more files remaining!", + "message": "{N} more files remaining!", + "translation": "", + "placeholders": [ + { + "id": "N", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "n" + } + ], + "position": "testdata/test1/test1.go:56:10" + }, + { + "id": "Use the following code for your discount: {ReferralCode}", + "key": "Use the following code for your discount: %d\n", + "message": "Use the following code for your discount: {ReferralCode}", + "translation": "", + "placeholders": [ + { + "id": "ReferralCode", + "string": "%[1]d", + "type": "./testdata/test1.referralCode", + "underlyingType": "int", + "argNum": 1, + "expr": "c" + } + ], + "position": "testdata/test1/test1.go:64:10" + }, + { + "id": [ + "msgOutOfOrder", + "{Device} is out of order!" + ], + "key": "%s is out of order!", + "message": "{Device} is out of order!", + "translation": "", + "comment": "This comment wins.\n", + "placeholders": [ + { + "id": "Device", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "device" + } + ], + "position": "testdata/test1/test1.go:70:10" + }, + { + "id": "{Miles} miles traveled ({Miles_1})", + "key": "%.2[1]f miles traveled (%[1]f)", + "message": "{Miles} miles traveled ({Miles_1})", + "translation": "", + "placeholders": [ + { + "id": "Miles", + "string": "%.2[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + }, + { + "id": "Miles_1", + "string": "%[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + } + ], + "position": "testdata/test1/test1.go:74:10" + } + ] +} \ No newline at end of file
diff --git a/message/pipeline/testdata/test1/locales/zh/out.gotext.json b/message/pipeline/testdata/test1/locales/zh/out.gotext.json new file mode 100755 index 0000000..6f8aa67 --- /dev/null +++ b/message/pipeline/testdata/test1/locales/zh/out.gotext.json
@@ -0,0 +1,188 @@ +{ + "language": "zh", + "messages": [ + { + "id": "Hello world!", + "key": "Hello world!\n", + "message": "Hello world!", + "translation": "", + "position": "testdata/test1/test1.go:19:10" + }, + { + "id": "Hello {City}!", + "key": "Hello %s!\n", + "message": "Hello {City}!", + "translation": "", + "placeholders": [ + { + "id": "City", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "city" + } + ], + "position": "testdata/test1/test1.go:24:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%s is visiting %s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "person", + "comment": "The person of matter." + }, + { + "id": "Place", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "place", + "comment": "Place the person is visiting." + } + ], + "position": "testdata/test1/test1.go:30:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%[1]s is visiting %[3]s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "comment": "Field names are placeholders.", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "pp.Person" + }, + { + "id": "Place", + "string": "%[3]s", + "type": "string", + "underlyingType": "string", + "argNum": 3, + "expr": "pp.Place", + "comment": "Place the person is visiting." + }, + { + "id": "Extra", + "string": "%[2]v", + "type": "int", + "underlyingType": "int", + "argNum": 2, + "expr": "pp.extra" + } + ], + "position": "testdata/test1/test1.go:44:10" + }, + { + "id": "{2} files remaining!", + "key": "%d files remaining!", + "message": "{2} files remaining!", + "translation": "", + "placeholders": [ + { + "id": "2", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "2" + } + ], + "position": "testdata/test1/test1.go:51:10" + }, + { + "id": "{N} more files remaining!", + "key": "%d more files remaining!", + "message": "{N} more files remaining!", + "translation": "", + "placeholders": [ + { + "id": "N", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "n" + } + ], + "position": "testdata/test1/test1.go:56:10" + }, + { + "id": "Use the following code for your discount: {ReferralCode}", + "key": "Use the following code for your discount: %d\n", + "message": "Use the following code for your discount: {ReferralCode}", + "translation": "", + "placeholders": [ + { + "id": "ReferralCode", + "string": "%[1]d", + "type": "./testdata/test1.referralCode", + "underlyingType": "int", + "argNum": 1, + "expr": "c" + } + ], + "position": "testdata/test1/test1.go:64:10" + }, + { + "id": [ + "msgOutOfOrder", + "{Device} is out of order!" + ], + "key": "%s is out of order!", + "message": "{Device} is out of order!", + "translation": "", + "comment": "This comment wins.\n", + "placeholders": [ + { + "id": "Device", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "device" + } + ], + "position": "testdata/test1/test1.go:70:10" + }, + { + "id": "{Miles} miles traveled ({Miles_1})", + "key": "%.2[1]f miles traveled (%[1]f)", + "message": "{Miles} miles traveled ({Miles_1})", + "translation": "", + "placeholders": [ + { + "id": "Miles", + "string": "%.2[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + }, + { + "id": "Miles_1", + "string": "%[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + } + ], + "position": "testdata/test1/test1.go:74:10" + } + ] +} \ No newline at end of file
diff --git a/message/pipeline/testdata/test1/locales/zh/out.gotext.json.want b/message/pipeline/testdata/test1/locales/zh/out.gotext.json.want new file mode 100755 index 0000000..6f8aa67 --- /dev/null +++ b/message/pipeline/testdata/test1/locales/zh/out.gotext.json.want
@@ -0,0 +1,188 @@ +{ + "language": "zh", + "messages": [ + { + "id": "Hello world!", + "key": "Hello world!\n", + "message": "Hello world!", + "translation": "", + "position": "testdata/test1/test1.go:19:10" + }, + { + "id": "Hello {City}!", + "key": "Hello %s!\n", + "message": "Hello {City}!", + "translation": "", + "placeholders": [ + { + "id": "City", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "city" + } + ], + "position": "testdata/test1/test1.go:24:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%s is visiting %s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "person", + "comment": "The person of matter." + }, + { + "id": "Place", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "place", + "comment": "Place the person is visiting." + } + ], + "position": "testdata/test1/test1.go:30:10" + }, + { + "id": "{Person} is visiting {Place}!", + "key": "%[1]s is visiting %[3]s!\n", + "message": "{Person} is visiting {Place}!", + "translation": "", + "comment": "Field names are placeholders.", + "placeholders": [ + { + "id": "Person", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "pp.Person" + }, + { + "id": "Place", + "string": "%[3]s", + "type": "string", + "underlyingType": "string", + "argNum": 3, + "expr": "pp.Place", + "comment": "Place the person is visiting." + }, + { + "id": "Extra", + "string": "%[2]v", + "type": "int", + "underlyingType": "int", + "argNum": 2, + "expr": "pp.extra" + } + ], + "position": "testdata/test1/test1.go:44:10" + }, + { + "id": "{2} files remaining!", + "key": "%d files remaining!", + "message": "{2} files remaining!", + "translation": "", + "placeholders": [ + { + "id": "2", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "2" + } + ], + "position": "testdata/test1/test1.go:51:10" + }, + { + "id": "{N} more files remaining!", + "key": "%d more files remaining!", + "message": "{N} more files remaining!", + "translation": "", + "placeholders": [ + { + "id": "N", + "string": "%[1]d", + "type": "int", + "underlyingType": "int", + "argNum": 1, + "expr": "n" + } + ], + "position": "testdata/test1/test1.go:56:10" + }, + { + "id": "Use the following code for your discount: {ReferralCode}", + "key": "Use the following code for your discount: %d\n", + "message": "Use the following code for your discount: {ReferralCode}", + "translation": "", + "placeholders": [ + { + "id": "ReferralCode", + "string": "%[1]d", + "type": "./testdata/test1.referralCode", + "underlyingType": "int", + "argNum": 1, + "expr": "c" + } + ], + "position": "testdata/test1/test1.go:64:10" + }, + { + "id": [ + "msgOutOfOrder", + "{Device} is out of order!" + ], + "key": "%s is out of order!", + "message": "{Device} is out of order!", + "translation": "", + "comment": "This comment wins.\n", + "placeholders": [ + { + "id": "Device", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "device" + } + ], + "position": "testdata/test1/test1.go:70:10" + }, + { + "id": "{Miles} miles traveled ({Miles_1})", + "key": "%.2[1]f miles traveled (%[1]f)", + "message": "{Miles} miles traveled ({Miles_1})", + "translation": "", + "placeholders": [ + { + "id": "Miles", + "string": "%.2[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + }, + { + "id": "Miles_1", + "string": "%[1]f", + "type": "float64", + "underlyingType": "float64", + "argNum": 1, + "expr": "miles" + } + ], + "position": "testdata/test1/test1.go:74:10" + } + ] +} \ No newline at end of file