1
2
3
4
5 package po
6
7 import (
8 "bytes"
9 "fmt"
10 "io"
11 "strconv"
12 "strings"
13 )
14
15
16
17
18
19
20 type Message struct {
21 Comment
22 MsgContext string
23 MsgId string
24 MsgIdPlural string
25 MsgStr string
26 MsgStrPlural []string
27 }
28
29 func (p *Message) less(q *Message) bool {
30 if p.Comment.less(&q.Comment) {
31 return true
32 }
33 if a, b := p.MsgContext, q.MsgContext; a != b {
34 return a < b
35 }
36 if a, b := p.MsgId, q.MsgId; a != b {
37 return a < b
38 }
39 if a, b := p.MsgIdPlural, q.MsgIdPlural; a != b {
40 return a < b
41 }
42 return false
43 }
44
45 func (p *Message) readPoEntry(r *lineReader) (err error) {
46 *p = Message{}
47 if err = r.skipBlankLine(); err != nil {
48 return
49 }
50 defer func(oldPos int) {
51 newPos := r.currentPos()
52 if newPos != oldPos && err == io.EOF {
53 err = nil
54 }
55 }(r.currentPos())
56
57 if err = p.Comment.readPoComment(r); err != nil {
58 return
59 }
60 for {
61 var s string
62 if s, _, err = r.currentLine(); err != nil {
63 return
64 }
65
66 if p.isInvalidLine(s) {
67 err = fmt.Errorf("gettext: line %d, %v", r.currentPos(), "invalid line")
68 return
69 }
70 if reComment.MatchString(s) || reBlankLine.MatchString(s) {
71 return
72 }
73
74 if err = p.readMsgContext(r); err != nil {
75 return
76 }
77 if err = p.readMsgId(r); err != nil {
78 return
79 }
80 if err = p.readMsgIdPlural(r); err != nil {
81 return
82 }
83 if err = p.readMsgStrOrPlural(r); err != nil {
84 return
85 }
86 }
87 }
88
89 func (p *Message) readMsgContext(r *lineReader) (err error) {
90 var s string
91 if s, _, err = r.currentLine(); err != nil {
92 return
93 }
94 if !reMsgContext.MatchString(s) {
95 return
96 }
97 p.MsgContext, err = p.readString(r)
98 return
99 }
100
101 func (p *Message) readMsgId(r *lineReader) (err error) {
102 var s string
103 if s, _, err = r.currentLine(); err != nil {
104 return
105 }
106 if !reMsgId.MatchString(s) {
107 return
108 }
109 p.MsgId, err = p.readString(r)
110 return
111 }
112
113 func (p *Message) readMsgIdPlural(r *lineReader) (err error) {
114 var s string
115 if s, _, err = r.currentLine(); err != nil {
116 return
117 }
118 if !reMsgIdPlural.MatchString(s) {
119 return
120 }
121 p.MsgIdPlural, err = p.readString(r)
122 return nil
123 }
124
125 func (p *Message) readMsgStrOrPlural(r *lineReader) (err error) {
126 var s string
127 if s, _, err = r.currentLine(); err != nil {
128 return
129 }
130 if !reMsgStr.MatchString(s) && !reMsgStrPlural.MatchString(s) {
131 return
132 }
133 if reMsgStrPlural.MatchString(s) {
134 left, right := strings.Index(s, `[`), strings.LastIndex(s, `]`)
135 idx, _ := strconv.Atoi(s[left+1 : right])
136 s, err = p.readString(r)
137 if n := len(p.MsgStrPlural); (idx + 1) > n {
138 p.MsgStrPlural = append(p.MsgStrPlural, make([]string, (idx+1)-n)...)
139 }
140 p.MsgStrPlural[idx] = s
141 } else {
142 p.MsgStr, err = p.readString(r)
143 }
144 return nil
145 }
146
147 func (p *Message) readString(r *lineReader) (msg string, err error) {
148 var s string
149 if s, _, err = r.readLine(); err != nil {
150 return
151 }
152 msg += decodePoString(s)
153 for {
154 if s, _, err = r.readLine(); err != nil {
155 return
156 }
157 if !reStringLine.MatchString(s) {
158 r.unreadLine()
159 break
160 }
161 msg += decodePoString(s)
162 }
163 return
164 }
165
166
167 func (p Message) String() string {
168 var buf bytes.Buffer
169 fmt.Fprintf(&buf, "%s", p.Comment.String())
170 if p.MsgContext != "" {
171 fmt.Fprintf(&buf, "msgctxt %s", encodePoString(p.MsgContext))
172 }
173 fmt.Fprintf(&buf, "msgid %s", encodePoString(p.MsgId))
174 if p.MsgIdPlural != "" {
175 fmt.Fprintf(&buf, "msgid_plural %s", encodePoString(p.MsgIdPlural))
176 }
177 if len(p.MsgStrPlural) == 0 {
178 if p.MsgStr != "" {
179 fmt.Fprintf(&buf, "msgstr %s", encodePoString(p.MsgStr))
180 } else {
181 fmt.Fprintf(&buf, "msgstr %s", `""`+"\n")
182 }
183 } else {
184 for i := 0; i < len(p.MsgStrPlural); i++ {
185 if p.MsgStrPlural[i] != "" {
186 fmt.Fprintf(&buf, "msgstr[%d] %s", i, encodePoString(p.MsgStrPlural[i]))
187 } else {
188 fmt.Fprintf(&buf, "msgstr[%d] %s", i, `""`+"\n")
189 }
190 }
191 }
192 return buf.String()
193 }
194
View as plain text