Skip to content

Commit a3498dc

Browse files
authored
extract messages from slices and maps (#169)
1 parent 4878883 commit a3498dc

File tree

2 files changed

+106
-14
lines changed

2 files changed

+106
-14
lines changed

v2/goi18n/extract_command.go

+61-13
Original file line numberDiff line numberDiff line change
@@ -140,29 +140,78 @@ func (e *extractor) err(err error) {
140140
}
141141

142142
func (e *extractor) Visit(node ast.Node) ast.Visitor {
143-
e.extractMessage(node)
143+
e.extractMessages(node)
144144
return e
145145
}
146146

147-
func (e *extractor) extractMessage(node ast.Node) {
147+
func (e *extractor) extractMessages(node ast.Node) {
148148
cl, ok := node.(*ast.CompositeLit)
149149
if !ok {
150150
return
151151
}
152-
se, ok := cl.Type.(*ast.SelectorExpr)
153-
if !ok {
154-
return
152+
switch t := cl.Type.(type) {
153+
case *ast.SelectorExpr:
154+
if !e.isMessageType(t) {
155+
return
156+
}
157+
e.extractMessage(cl)
158+
case *ast.ArrayType:
159+
if !e.isMessageType(t.Elt) {
160+
return
161+
}
162+
for _, el := range cl.Elts {
163+
ecl, ok := el.(*ast.CompositeLit)
164+
if !ok {
165+
continue
166+
}
167+
e.extractMessage(ecl)
168+
}
169+
case *ast.MapType:
170+
if !e.isMessageType(t.Value) {
171+
return
172+
}
173+
for _, el := range cl.Elts {
174+
kve, ok := el.(*ast.KeyValueExpr)
175+
if !ok {
176+
continue
177+
}
178+
vcl, ok := kve.Value.(*ast.CompositeLit)
179+
if !ok {
180+
continue
181+
}
182+
e.extractMessage(vcl)
183+
}
184+
}
185+
}
186+
187+
func (e *extractor) isMessageType(expr ast.Expr) bool {
188+
se := unwrapSelectorExpr(expr)
189+
if se == nil {
190+
return false
155191
}
156192
if se.Sel.Name != "Message" && se.Sel.Name != "LocalizeConfig" {
157-
return
193+
return false
158194
}
159195
x, ok := se.X.(*ast.Ident)
160196
if !ok {
161-
return
197+
return false
162198
}
163-
if x.Name != e.i18nPackageName {
164-
return
199+
return x.Name == e.i18nPackageName
200+
}
201+
202+
func unwrapSelectorExpr(e ast.Expr) *ast.SelectorExpr {
203+
switch et := e.(type) {
204+
case *ast.SelectorExpr:
205+
return et
206+
case *ast.StarExpr:
207+
se, _ := et.X.(*ast.SelectorExpr)
208+
return se
209+
default:
210+
return nil
165211
}
212+
}
213+
214+
func (e *extractor) extractMessage(cl *ast.CompositeLit) {
166215
data := make(map[string]string)
167216
for _, elt := range cl.Elts {
168217
kve, ok := elt.(*ast.KeyValueExpr)
@@ -182,11 +231,10 @@ func (e *extractor) extractMessage(node ast.Node) {
182231
if len(data) == 0 {
183232
return
184233
}
185-
if se.Sel.Name == "Message" {
186-
e.messages = append(e.messages, internal.MustNewMessage(data))
187-
} else if messageID := data["MessageID"]; messageID != "" {
188-
e.messages = append(e.messages, &i18n.Message{ID: messageID})
234+
if messageID := data["MessageID"]; messageID != "" {
235+
data["ID"] = messageID
189236
}
237+
e.messages = append(e.messages, internal.MustNewMessage(data))
190238
}
191239

192240
func extractStringLiteral(expr ast.Expr) (string, bool) {

v2/goi18n/extract_command_test.go

+45-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,50 @@ func TestExtract(t *testing.T) {
5151
`,
5252
activeFile: []byte(`a = "a \" b"
5353
b = "a \" b"
54+
`),
55+
},
56+
{
57+
name: "array",
58+
fileName: "file.go",
59+
file: `package main
60+
61+
import "github.com/nicksnyder/go-i18n/v2/i18n"
62+
63+
var a = []*i18n.Message{
64+
{
65+
ID: "a",
66+
Other: "a",
67+
},
68+
{
69+
ID: "b",
70+
Other: "b",
71+
},
72+
}
73+
`,
74+
activeFile: []byte(`a = "a"
75+
b = "b"
76+
`),
77+
},
78+
{
79+
name: "map",
80+
fileName: "file.go",
81+
file: `package main
82+
83+
import "github.com/nicksnyder/go-i18n/v2/i18n"
84+
85+
var a = map[string]*i18n.Message{
86+
"a": {
87+
ID: "a",
88+
Other: "a",
89+
},
90+
"b": {
91+
ID: "b",
92+
Other: "b",
93+
},
94+
}
95+
`,
96+
activeFile: []byte(`a = "a"
97+
b = "b"
5498
`),
5599
},
56100
{
@@ -144,7 +188,7 @@ zero = "Zero translation"
144188
}
145189

146190
for _, test := range tests {
147-
t.Run(test.name+" active file", func(t *testing.T) {
191+
t.Run(test.name, func(t *testing.T) {
148192
indir := mustTempDir("TestExtractCommandIn")
149193
defer os.RemoveAll(indir)
150194
outdir := mustTempDir("TestExtractCommandOut")

0 commit comments

Comments
 (0)