• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

romshark / tik / 15475864183

05 Jun 2025 07:44PM UTC coverage: 95.377% (+0.02%) from 95.361%
15475864183

push

github

romshark
fix: Improve specification for magic constant {3}

9 of 9 new or added lines in 1 file covered. (100.0%)

2 existing lines in 2 files now uncovered.

557 of 584 relevant lines covered (95.38%)

30.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.45
/tik-go/icu.go
1
package tik
2

3
import (
4
        "bytes"
5
        "strconv"
6
)
7

8
// ICUTranslator is a reusable TIK to ICU message translator.
9
type ICUTranslator struct {
10
        b    bytes.Buffer
11
        conf *Config
12
}
13

14
func NewICUTranslator(conf *Config) *ICUTranslator {
2✔
15
        if conf == nil {
2✔
16
                conf = defaultConfig
×
17
        }
×
18
        return &ICUTranslator{conf: conf}
2✔
19
}
20

21
type ICUModifier struct{ Gender, Plural bool }
22

23
func (i *ICUTranslator) writeModifiers(
24
        pos int, modifiers map[int]ICUModifier,
25
        gender, plural bool, writeContent func(),
26
) {
26✔
27
        if modifiers == nil {
46✔
28
                writeContent()
20✔
29
                return
20✔
30
        }
20✔
31
        m, ok := modifiers[pos]
6✔
32
        if !ok {
7✔
33
                writeContent()
1✔
34
                return
1✔
35
        }
1✔
36

37
        applyGender := gender && m.Gender
5✔
38
        applyPlural := plural && m.Plural
5✔
39

5✔
40
        if !applyGender && !applyPlural {
7✔
41
                writeContent()
2✔
42
                return
2✔
43
        }
2✔
44

45
        if applyGender {
5✔
46
                i.write("{")
2✔
47
                i.writePositionalPlaceholder(pos, "_gender")
2✔
48
                i.write(", select, ")
2✔
49
                i.write("other {")
2✔
50
                if applyPlural {
3✔
51
                        // Apply both gender and pluralization.
1✔
52
                        i.write("{")
1✔
53
                        i.writePositionalPlaceholder(pos, "_plural")
1✔
54
                        i.write(", plural, ")
1✔
55
                        i.write("other {")
1✔
56
                        writeContent()
1✔
57
                        i.write("}}")
1✔
58
                } else {
2✔
59
                        writeContent()
1✔
60
                        i.write("}}")
1✔
61
                }
1✔
62
        } else if applyPlural {
2✔
63
                // Apply only pluralization.
1✔
64
                i.write("{")
1✔
65
                i.writePositionalPlaceholder(pos, "_plural")
1✔
66
                i.write(", plural, ")
1✔
67
                i.write("other {")
1✔
68
                writeContent()
1✔
69
                i.write("}}")
1✔
70
        }
1✔
71
}
72

73
func (i *ICUTranslator) writePositionalPlaceholder(index int, suffix string) {
34✔
74
        i.b.WriteString("var")
34✔
75
        i.b.WriteString(strconv.Itoa(index))
34✔
76
        i.b.WriteString(suffix)
34✔
77
}
34✔
78

79
func (i *ICUTranslator) write(s string) { _, _ = i.b.WriteString(s) }
165✔
80

81
// TIK2ICUBuf similar TIK2ICU but gives temporary access to the internal buffer
82
// to avoid string allocation if only a temporary byte slice is needed.
83
// This function can be used instead TIK2ICU to achieve efficiency when possible
84
// but must be used with caution!
85
//
86
// WARNING: Never use or alias buf outside fn!
87
func (i *ICUTranslator) TIK2ICUBuf(
88
        tik TIK, modifiers map[int]ICUModifier, fn func(buf *bytes.Buffer),
89
) {
24✔
90
        i.b.Reset()
24✔
91

24✔
92
        positionalIndex := 0
24✔
93

24✔
94
        for _, token := range tik.Tokens {
91✔
95
                switch token.Type {
67✔
96
                case TokenTypeStringLiteral:
32✔
97
                        i.write(token.String(tik.Raw))
32✔
98
                case TokenTypeStringPlaceholder:
12✔
99
                        pos := positionalIndex
12✔
100
                        positionalIndex++
12✔
101
                        i.writeModifiers(pos, modifiers, true, true, func() {
24✔
102
                                i.write("{")
12✔
103
                                i.writePositionalPlaceholder(pos, "")
12✔
104
                                i.write("}")
12✔
105
                        })
12✔
106
                case TokenTypeNumber:
1✔
107
                        pos := positionalIndex
1✔
108
                        positionalIndex++
1✔
109
                        i.writeModifiers(pos, modifiers, true, true, func() {
2✔
110
                                i.write("{")
1✔
111
                                i.writePositionalPlaceholder(pos, "")
1✔
112
                                i.write(", number, integer}")
1✔
113
                        })
1✔
114
                case TokenTypeCurrency:
1✔
115
                        pos := positionalIndex
1✔
116
                        positionalIndex++
1✔
117
                        i.writeModifiers(pos, modifiers, true, true, func() {
2✔
118
                                i.write("{")
1✔
119
                                i.writePositionalPlaceholder(pos, "")
1✔
120
                                i.write(", number, ::currency/auto}")
1✔
121
                        })
1✔
122

123
                case TokenTypeTimeFull,
124
                        TokenTypeTimeLong,
125
                        TokenTypeTimeMedium,
126
                        TokenTypeTimeShort,
127
                        TokenTypeDateFull,
128
                        TokenTypeDateLong,
129
                        TokenTypeDateMedium,
130
                        TokenTypeDateShort:
10✔
131
                        pos := positionalIndex
10✔
132
                        positionalIndex++
10✔
133
                        var varType, style string
10✔
134
                        switch token.Type {
10✔
135
                        case TokenTypeTimeFull:
1✔
136
                                varType, style = "time", "full"
1✔
137
                        case TokenTypeTimeLong:
1✔
138
                                varType, style = "time", "long"
1✔
139
                        case TokenTypeTimeMedium:
1✔
140
                                varType, style = "time", "medium"
1✔
141
                        case TokenTypeTimeShort:
2✔
142
                                varType, style = "time", "short"
2✔
143
                        case TokenTypeDateFull:
1✔
144
                                varType, style = "date", "full"
1✔
145
                        case TokenTypeDateLong:
2✔
146
                                varType, style = "date", "long"
2✔
147
                        case TokenTypeDateMedium:
1✔
148
                                varType, style = "date", "medium"
1✔
149
                        case TokenTypeDateShort:
1✔
150
                                varType, style = "date", "short"
1✔
151
                        default:
×
UNCOV
152
                                panic("unexpected token type")
×
153
                        }
154
                        i.writeModifiers(pos, modifiers, true, true, func() {
20✔
155
                                i.write("{") // Start placeholder.
10✔
156
                                i.writePositionalPlaceholder(pos, "")
10✔
157
                                i.write(", ")
10✔
158
                                i.write(varType)
10✔
159
                                i.write(", ")
10✔
160
                                i.write(style)
10✔
161
                                i.write("}")
10✔
162
                        })
10✔
163

164
                case TokenTypeOrdinalPlural:
1✔
165
                        pos := positionalIndex
1✔
166
                        positionalIndex++
1✔
167

1✔
168
                        i.write("{") // Start plural block.
1✔
169
                        i.writePositionalPlaceholder(pos, "")
1✔
170
                        i.write(", selectordinal, ")
1✔
171
                        i.write("other {#")
1✔
172
                        i.write(i.conf.MagicConstants.OrdinalPlural.DefaultICUSuffix)
1✔
173
                        i.write("}}")
1✔
174

175
                case TokenTypeCardinalPluralStart:
3✔
176
                        pos := positionalIndex
3✔
177
                        positionalIndex++
3✔
178

3✔
179
                        i.write("{") // Start plural block.
3✔
180
                        i.writePositionalPlaceholder(pos, "")
3✔
181
                        i.write(", plural, ")
3✔
182
                        i.write("other {")
3✔
183
                        i.write("# ") // Number placeholder.
3✔
184

185
                case TokenTypeCardinalPluralEnd:
3✔
186
                        i.write("}}") // Finish both other and plural blocks.
3✔
187

188
                case TokenTypeGenderPronoun:
2✔
189
                        pos := positionalIndex
2✔
190
                        positionalIndex++
2✔
191

2✔
192
                        i.writeModifiers(pos, modifiers, false, true, func() {
4✔
193
                                i.write("{")
2✔
194
                                i.writePositionalPlaceholder(pos, "")
2✔
195
                                i.write(", select, ")
2✔
196
                                i.write("other {")
2✔
197
                                pronoun := token.String(tik.Raw)
2✔
198
                                i.write(pronoun[1 : len(pronoun)-1])
2✔
199
                                i.write("}}")
2✔
200
                        })
2✔
201
                }
202
        }
203

204
        fn(&i.b)
24✔
205
}
206

207
// TIK2ICU translates a TIK into an incomplete ICU message
208
// that needs to be translated later.
209
// (See https://unicode-org.github.io/icu/userguide/format_parse/messages/)
210
// modifiers define positional modifiers such as gender and pluralization
211
// that weren't defined in the tik.
212
func (i *ICUTranslator) TIK2ICU(tik TIK, modifiers map[int]ICUModifier) (str string) {
24✔
213
        i.TIK2ICUBuf(tik, modifiers, func(buf *bytes.Buffer) { str = buf.String() })
48✔
214
        return str
24✔
215
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc