1
2
3
4
5 package gettext
6
7 import (
8 "encoding/json"
9
10 "github.com/chai2010/gettext-go/mo"
11 "github.com/chai2010/gettext-go/plural"
12 "github.com/chai2010/gettext-go/po"
13 )
14
15 var nilTranslator = &translator{
16 MessageMap: make(map[string]mo.Message),
17 PluralFormula: plural.Formula("??"),
18 }
19
20 type translator struct {
21 MessageMap map[string]mo.Message
22 PluralFormula func(n int) int
23 }
24
25 func newMoTranslator(name string, data []byte) (*translator, error) {
26 var (
27 f *mo.File
28 err error
29 )
30 if len(data) != 0 {
31 f, err = mo.Load(data)
32 } else {
33 f, err = mo.LoadFile(name)
34 }
35 if err != nil {
36 return nil, err
37 }
38 var tr = &translator{
39 MessageMap: make(map[string]mo.Message),
40 }
41 for _, v := range f.Messages {
42 tr.MessageMap[tr.makeMapKey(v.MsgContext, v.MsgId)] = v
43 }
44 if lang := f.MimeHeader.Language; lang != "" {
45 tr.PluralFormula = plural.Formula(lang)
46 } else {
47 tr.PluralFormula = plural.Formula("??")
48 }
49 return tr, nil
50 }
51
52 func newPoTranslator(name string, data []byte) (*translator, error) {
53 var (
54 f *po.File
55 err error
56 )
57 if len(data) != 0 {
58 f, err = po.Load(data)
59 } else {
60 f, err = po.LoadFile(name)
61 }
62 if err != nil {
63 return nil, err
64 }
65 var tr = &translator{
66 MessageMap: make(map[string]mo.Message),
67 }
68 for _, v := range f.Messages {
69 tr.MessageMap[tr.makeMapKey(v.MsgContext, v.MsgId)] = mo.Message{
70 MsgContext: v.MsgContext,
71 MsgId: v.MsgId,
72 MsgIdPlural: v.MsgIdPlural,
73 MsgStr: v.MsgStr,
74 MsgStrPlural: v.MsgStrPlural,
75 }
76 }
77 if lang := f.MimeHeader.Language; lang != "" {
78 tr.PluralFormula = plural.Formula(lang)
79 } else {
80 tr.PluralFormula = plural.Formula("??")
81 }
82 return tr, nil
83 }
84
85 func newJsonTranslator(lang, name string, jsonData []byte) (*translator, error) {
86 var msgList []struct {
87 MsgContext string `json:"msgctxt"`
88 MsgId string `json:"msgid"`
89 MsgIdPlural string `json:"msgid_plural"`
90 MsgStr []string `json:"msgstr"`
91 }
92 if err := json.Unmarshal(jsonData, &msgList); err != nil {
93 return nil, err
94 }
95
96 var tr = &translator{
97 MessageMap: make(map[string]mo.Message),
98 PluralFormula: plural.Formula(lang),
99 }
100
101 for _, v := range msgList {
102 var v_MsgStr string
103 var v_MsgStrPlural = v.MsgStr
104
105 if len(v.MsgStr) != 0 {
106 v_MsgStr = v.MsgStr[0]
107 }
108
109 tr.MessageMap[tr.makeMapKey(v.MsgContext, v.MsgId)] = mo.Message{
110 MsgContext: v.MsgContext,
111 MsgId: v.MsgId,
112 MsgIdPlural: v.MsgIdPlural,
113 MsgStr: v_MsgStr,
114 MsgStrPlural: v_MsgStrPlural,
115 }
116 }
117 return tr, nil
118 }
119
120 func (p *translator) PGettext(msgctxt, msgid string) string {
121 return p.findMsgStr(msgctxt, msgid)
122 }
123
124 func (p *translator) PNGettext(msgctxt, msgid, msgidPlural string, n int) string {
125 n = p.PluralFormula(n)
126 if ss := p.findMsgStrPlural(msgctxt, msgid, msgidPlural); len(ss) != 0 {
127 if n >= len(ss) {
128 n = len(ss) - 1
129 }
130 if ss[n] != "" {
131 return ss[n]
132 }
133 }
134 if msgidPlural != "" && n > 0 {
135 return msgidPlural
136 }
137 return msgid
138 }
139
140 func (p *translator) findMsgStr(msgctxt, msgid string) string {
141 key := p.makeMapKey(msgctxt, msgid)
142 if v, ok := p.MessageMap[key]; ok {
143 if v.MsgStr != "" {
144 return v.MsgStr
145 }
146 }
147 return msgid
148 }
149
150 func (p *translator) findMsgStrPlural(msgctxt, msgid, msgidPlural string) []string {
151 key := p.makeMapKey(msgctxt, msgid)
152 if v, ok := p.MessageMap[key]; ok {
153 if len(v.MsgIdPlural) != 0 {
154 if len(v.MsgStrPlural) != 0 {
155 return v.MsgStrPlural
156 } else {
157 return nil
158 }
159 } else {
160 if len(v.MsgStr) != 0 {
161 return []string{v.MsgStr}
162 } else {
163 return nil
164 }
165 }
166 }
167 return nil
168 }
169
170 func (p *translator) makeMapKey(msgctxt, msgid string) string {
171 if msgctxt != "" {
172 return msgctxt + mo.EotSeparator + msgid
173 }
174 return msgid
175 }
176
View as plain text