1 package main
2
3 import (
4 "fmt"
5 "log"
6 "os"
7 "os/exec"
8 "regexp"
9 "sort"
10 "strconv"
11 "strings"
12
13 "github.com/go-playground/locales"
14
15 "golang.org/x/text/unicode/cldr"
16
17 "text/template"
18 )
19
20 const (
21 locDir = "../%s"
22 locFilename = locDir + "/%s.go"
23 )
24
25 var (
26 tfuncs = template.FuncMap{
27 "is_multibyte": func(s string) bool {
28 return len([]byte(s)) > 1
29 },
30 "reverse_bytes": func(s string) string {
31 b := make([]byte, 0, 8)
32
33 for j := len(s) - 1; j >= 0; j-- {
34 b = append(b, s[j])
35 }
36
37 return fmt.Sprintf("%#v", b)
38 },
39 "byte_count": func(s ...string) string {
40 var count int
41
42 for i := 0; i < len(s); i++ {
43 count += len([]byte(s[i]))
44 }
45
46 return strconv.Itoa(count)
47 },
48 }
49 prVarFuncs = map[string]string{
50 "n": "n := math.Abs(num)\n",
51 "i": "i := int64(n)\n",
52
53 "w": "w := locales.W(n, v)\n",
54 "f": "f := locales.F(n, v)\n",
55 "t": "t := locales.T(n, v)\n",
56 }
57
58 translators = make(map[string]*translator)
59 baseTranslators = make(map[string]*translator)
60 globalCurrenciesMap = make(map[string]struct{})
61 globCurrencyIdxMap = make(map[string]int)
62 globalCurrencies = make([]string, 0, 100)
63 tmpl *template.Template
64 nModRegex = regexp.MustCompile("(n%[0-9]+)")
65 iModRegex = regexp.MustCompile("(i%[0-9]+)")
66 wModRegex = regexp.MustCompile("(w%[0-9]+)")
67 fModRegex = regexp.MustCompile("(f%[0-9]+)")
68 tModRegex = regexp.MustCompile("(t%[0-9]+)")
69 groupLenRegex = regexp.MustCompile(",([0-9#]+)\\.")
70 groupLenPercentRegex = regexp.MustCompile(",([0-9#]+)$")
71 secondaryGroupLenRegex = regexp.MustCompile(",([0-9#]+),")
72 requiredNumRegex = regexp.MustCompile("([0-9]+)\\.")
73 requiredDecimalRegex = regexp.MustCompile("\\.([0-9]+)")
74
75 enInheritance = map[string]string{
76 "en_150": "en_001", "en_AG": "en_001", "en_AI": "en_001", "en_AU": "en_001", "en_BB": "en_001", "en_BE": "en_001", "en_BM": "en_001", "en_BS": "en_001", "en_BW": "en_001", "en_BZ": "en_001", "en_CA": "en_001", "en_CC": "en_001", "en_CK": "en_001", "en_CM": "en_001", "en_CX": "en_001", "en_CY": "en_001", "en_DG": "en_001", "en_DM": "en_001", "en_ER": "en_001", "en_FJ": "en_001", "en_FK": "en_001", "en_FM": "en_001", "en_GB": "en_001", "en_GD": "en_001", "en_GG": "en_001", "en_GH": "en_001", "en_GI": "en_001", "en_GM": "en_001", "en_GY": "en_001", "en_HK": "en_001", "en_IE": "en_001", "en_IL": "en_001", "en_IM": "en_001", "en_IN": "en_001", "en_IO": "en_001", "en_JE": "en_001", "en_JM": "en_001", "en_KE": "en_001", "en_KI": "en_001", "en_KN": "en_001", "en_KY": "en_001", "en_LC": "en_001", "en_LR": "en_001", "en_LS": "en_001", "en_MG": "en_001", "en_MO": "en_001", "en_MS": "en_001", "en_MT": "en_001", "en_MU": "en_001", "en_MW": "en_001", "en_MY": "en_001", "en_NA": "en_001", "en_NF": "en_001", "en_NG": "en_001", "en_NR": "en_001", "en_NU": "en_001", "en_NZ": "en_001", "en_PG": "en_001", "en_PH": "en_001", "en_PK": "en_001", "en_PN": "en_001", "en_PW": "en_001", "en_RW": "en_001", "en_SB": "en_001", "en_SC": "en_001", "en_SD": "en_001", "en_SG": "en_001", "en_SH": "en_001", "en_SL": "en_001", "en_SS": "en_001", "en_SX": "en_001", "en_SZ": "en_001", "en_TC": "en_001", "en_TK": "en_001", "en_TO": "en_001", "en_TT": "en_001", "en_TV": "en_001", "en_TZ": "en_001", "en_UG": "en_001", "en_VC": "en_001", "en_VG": "en_001", "en_VU": "en_001", "en_WS": "en_001", "en_ZA": "en_001", "en_ZM": "en_001", "en_ZW": "en_001", }
77 en150Inheritance = map[string]string{"en_AT": "en_150", "en_CH": "en_150", "en_DE": "en_150", "en_DK": "en_150", "en_FI": "en_150", "en_NL": "en_150", "en_SE": "en_150", "en_SI": "en_150"}
78 es419Inheritance = map[string]string{
79 "es_AR": "es_419", "es_BO": "es_419", "es_BR": "es_419", "es_BZ": "es_419", "es_CL": "es_419", "es_CO": "es_419", "es_CR": "es_419", "es_CU": "es_419", "es_DO": "es_419", "es_EC": "es_419", "es_GT": "es_419", "es_HN": "es_419", "es_MX": "es_419", "es_NI": "es_419", "es_PA": "es_419", "es_PE": "es_419", "es_PR": "es_419", "es_PY": "es_419", "es_SV": "es_419", "es_US": "es_419", "es_UY": "es_419", "es_VE": "es_419",
80 }
81 rootInheritance = map[string]string{
82 "az_Arab": "root", "az_Cyrl": "root", "bm_Nkoo": "root", "bs_Cyrl": "root", "en_Dsrt": "root", "en_Shaw": "root", "ha_Arab": "root", "iu_Latn": "root", "mn_Mong": "root", "ms_Arab": "root", "pa_Arab": "root", "shi_Latn": "root", "sr_Latn": "root", "uz_Arab": "root", "uz_Cyrl": "root", "vai_Latn": "root", "zh_Hant": "root", "yue_Hans": "root",
83 }
84 ptPtInheritance = map[string]string{
85 "pt_AO": "pt_PT", "pt_CH": "pt_PT", "pt_CV": "pt_PT", "pt_GQ": "pt_PT", "pt_GW": "pt_PT", "pt_LU": "pt_PT", "pt_MO": "pt_PT", "pt_MZ": "pt_PT", "pt_ST": "pt_PT", "pt_TL": "pt_PT",
86 }
87 zhHantHKInheritance = map[string]string{
88 "zh_Hant_MO": "zh_Hant_HK",
89 }
90
91 inheritMaps = []map[string]string{ enInheritance, en150Inheritance, es419Inheritance, rootInheritance, ptPtInheritance, zhHantHKInheritance}
92 )
93
94 type translator struct {
95 Locale string
96 BaseLocale string
97
98 Plurals string
99 CardinalFunc string
100 PluralsOrdinal string
101 OrdinalFunc string
102 PluralsRange string
103 RangeFunc string
104 Decimal string
105 Group string
106 Minus string
107 Percent string
108 PerMille string
109 TimeSeparator string
110 Infinity string
111 Currencies string
112
113
114 FmtNumberExists bool
115 FmtNumberGroupLen int
116 FmtNumberSecondaryGroupLen int
117 FmtNumberMinDecimalLen int
118
119
120 FmtPercentExists bool
121 FmtPercentGroupLen int
122 FmtPercentSecondaryGroupLen int
123 FmtPercentMinDecimalLen int
124 FmtPercentPrefix string
125 FmtPercentSuffix string
126 FmtPercentInPrefix bool
127 FmtPercentLeft bool
128
129
130 FmtCurrencyExists bool
131 FmtCurrencyGroupLen int
132 FmtCurrencySecondaryGroupLen int
133 FmtCurrencyMinDecimalLen int
134 FmtCurrencyPrefix string
135 FmtCurrencySuffix string
136 FmtCurrencyInPrefix bool
137 FmtCurrencyLeft bool
138 FmtCurrencyNegativeExists bool
139 FmtCurrencyNegativePrefix string
140 FmtCurrencyNegativeSuffix string
141 FmtCurrencyNegativeInPrefix bool
142 FmtCurrencyNegativeLeft bool
143
144
145 FmtCalendarExists bool
146
147 FmtMonthsAbbreviated string
148 FmtMonthsNarrow string
149 FmtMonthsWide string
150
151 FmtDaysAbbreviated string
152 FmtDaysNarrow string
153 FmtDaysShort string
154 FmtDaysWide string
155
156 FmtPeriodsAbbreviated string
157 FmtPeriodsNarrow string
158 FmtPeriodsShort string
159 FmtPeriodsWide string
160
161 FmtErasAbbreviated string
162 FmtErasNarrow string
163 FmtErasWide string
164
165 FmtTimezones string
166
167
168 DecimalNumberFormat string
169 PercentNumberFormat string
170 CurrencyNumberFormat string
171 NegativeCurrencyNumberFormat string
172
173
174 FmtDateFull string
175 FmtDateLong string
176 FmtDateMedium string
177 FmtDateShort string
178
179
180 FmtTimeFull string
181 FmtTimeLong string
182 FmtTimeMedium string
183 FmtTimeShort string
184
185
186 timezones map[string]*zoneAbbrev
187 }
188
189 type zoneAbbrev struct {
190 standard string
191 daylight string
192 }
193
194 var timezones = map[string]*zoneAbbrev{}
195
196 func main() {
197
198 var err error
199
200
201 tmpl, err = template.New("all").Funcs(tfuncs).ParseGlob("*.tmpl")
202 if err != nil {
203 log.Fatal(err)
204 }
205
206
207 var decoder cldr.Decoder
208
209 cldr, err := decoder.DecodePath("data/core")
210 if err != nil {
211 panic("failed decode CLDR data; " + err.Error())
212 }
213
214 preProcess(cldr)
215 postProcess(cldr)
216
217 var currencies string
218
219 for i, curr := range globalCurrencies {
220
221 if i == 0 {
222 currencies = curr + " Type = iota\n"
223 continue
224 }
225
226 currencies += curr + "\n"
227 }
228
229 if err = os.MkdirAll(fmt.Sprintf(locDir, "currency"), 0777); err != nil {
230 log.Fatal(err)
231 }
232
233 filename := fmt.Sprintf(locFilename, "currency", "currency")
234
235 output, err := os.Create(filename)
236 if err != nil {
237 log.Fatal(err)
238 }
239 defer output.Close()
240
241 if err := tmpl.ExecuteTemplate(output, "currencies", currencies); err != nil {
242 log.Fatal(err)
243 }
244
245 output.Close()
246
247
248 cmd := exec.Command("goimports", "-w", filename)
249 if err = cmd.Run(); err != nil {
250 log.Panic("failed execute \"goimports\" for file ", filename, ": ", err)
251 }
252
253 cmd = exec.Command("gofmt", "-s", "-w", filename)
254 if err = cmd.Run(); err != nil {
255 log.Panic("failed execute \"gofmt\" for file ", filename, ": ", err)
256 }
257
258 for _, trans := range translators {
259 fmt.Println("Writing Data:", trans.Locale)
260
261 if err = os.MkdirAll(fmt.Sprintf(locDir, trans.Locale), 0777); err != nil {
262 log.Fatal(err)
263 }
264
265 filename = fmt.Sprintf(locFilename, trans.Locale, trans.Locale)
266
267 output, err := os.Create(filename)
268 if err != nil {
269 log.Fatal(err)
270 }
271 defer output.Close()
272
273 if err := tmpl.ExecuteTemplate(output, "translator", trans); err != nil {
274 log.Fatal(err)
275 }
276
277 output.Close()
278
279
280 cmd := exec.Command("goimports", "-w", filename)
281 if err = cmd.Run(); err != nil {
282 log.Panic("failed execute \"goimports\" for file ", filename, ": ", err)
283 }
284
285
286 cmd = exec.Command("gofmt", "-s", "-w", filename)
287 if err = cmd.Run(); err != nil {
288 log.Panic("failed execute \"gofmt\" for file ", filename, ": ", err)
289 }
290
291 filename = fmt.Sprintf(locFilename, trans.Locale, trans.Locale+"_test")
292
293 if _, err := os.Stat(filename); err == nil {
294 fmt.Println("*************** test file exists, skipping:", filename)
295 continue
296 }
297
298 output, err = os.Create(filename)
299 if err != nil {
300 log.Fatal(err)
301 }
302 defer output.Close()
303
304 if err := tmpl.ExecuteTemplate(output, "tests", trans); err != nil {
305 log.Fatal(err)
306 }
307
308 output.Close()
309
310
311 cmd = exec.Command("goimports", "-w", filename)
312 if err = cmd.Run(); err != nil {
313 log.Panic("failed execute \"goimports\" for file ", filename, ": ", err)
314 }
315
316
317 cmd = exec.Command("gofmt", "-s", "-w", filename)
318 if err = cmd.Run(); err != nil {
319 log.Panic("failed execute \"gofmt\" for file ", filename, ": ", err)
320 }
321 }
322 }
323
324 func applyOverrides(trans *translator) {
325
326 if trans.BaseLocale == "ru" {
327 trans.PercentNumberFormat = "#,##0%"
328 }
329 }
330
331 func postProcess(cldr *cldr.CLDR) {
332
333 for _, v := range timezones {
334
335
336 if len(v.daylight) == 0 {
337 v.daylight = v.standard
338 }
339 }
340
341 var inherited *translator
342 var base *translator
343 var inheritedFound, baseFound bool
344
345 for _, trans := range translators {
346
347 fmt.Println("Post Processing:", trans.Locale)
348
349
350 trans.CardinalFunc, trans.Plurals = parseCardinalPluralRuleFunc(cldr, trans.Locale, trans.BaseLocale)
351
352
353 trans.OrdinalFunc, trans.PluralsOrdinal = parseOrdinalPluralRuleFunc(cldr, trans.BaseLocale)
354
355
356 trans.RangeFunc, trans.PluralsRange = parseRangePluralRuleFunc(cldr, trans.BaseLocale)
357
358
359 if trans.BaseLocale == trans.Locale {
360 inheritedFound = false
361 baseFound = false
362 } else {
363
364 inheritedFound = false
365
366 for _, inheritMap := range(inheritMaps) {
367 if inherit, found := inheritMap[trans.Locale]; found {
368 inherited, inheritedFound = translators[inherit]
369 break;
370 }
371 }
372
373 base, baseFound = baseTranslators[trans.BaseLocale]
374 }
375
376
377
378 if len(trans.Decimal) == 0 {
379
380 if inheritedFound {
381 trans.Decimal = inherited.Decimal
382 }
383
384 if len(trans.Decimal) == 0 && baseFound {
385 trans.Decimal = base.Decimal
386 }
387
388 if len(trans.Decimal) == 0 {
389 trans.Decimal = ""
390 }
391 }
392
393 if len(trans.Group) == 0 {
394
395 if inheritedFound {
396 trans.Group = inherited.Group
397 }
398
399 if len(trans.Group) == 0 && baseFound {
400 trans.Group = base.Group
401 }
402
403 if len(trans.Group) == 0 {
404 trans.Group = ""
405 }
406 }
407
408 if len(trans.Minus) == 0 {
409
410 if inheritedFound {
411 trans.Minus = inherited.Minus
412 }
413
414 if len(trans.Minus) == 0 && baseFound {
415 trans.Minus = base.Minus
416 }
417
418 if len(trans.Minus) == 0 {
419 trans.Minus = ""
420 }
421 }
422
423 if len(trans.Percent) == 0 {
424
425 if inheritedFound {
426 trans.Percent = inherited.Percent
427 }
428
429 if len(trans.Percent) == 0 && baseFound {
430 trans.Percent = base.Percent
431 }
432
433 if len(trans.Percent) == 0 {
434 trans.Percent = ""
435 }
436 }
437
438 if len(trans.PerMille) == 0 {
439
440 if inheritedFound {
441 trans.PerMille = inherited.PerMille
442 }
443
444 if len(trans.PerMille) == 0 && baseFound {
445 trans.PerMille = base.PerMille
446 }
447
448 if len(trans.PerMille) == 0 {
449 trans.PerMille = ""
450 }
451 }
452
453 if len(trans.TimeSeparator) == 0 && inheritedFound {
454 trans.TimeSeparator = inherited.TimeSeparator
455 }
456
457 if len(trans.TimeSeparator) == 0 && baseFound {
458 trans.TimeSeparator = base.TimeSeparator
459 }
460
461 if len(trans.Infinity) == 0 && inheritedFound {
462 trans.Infinity = inherited.Infinity
463 }
464
465 if len(trans.Infinity) == 0 && baseFound {
466 trans.Infinity = base.Infinity
467 }
468
469
470
471
472
473 if len(trans.DecimalNumberFormat) == 0 && inheritedFound {
474 trans.DecimalNumberFormat = inherited.DecimalNumberFormat
475 }
476
477 if len(trans.DecimalNumberFormat) == 0 && baseFound {
478 trans.DecimalNumberFormat = base.DecimalNumberFormat
479 }
480
481 if len(trans.PercentNumberFormat) == 0 && inheritedFound {
482 trans.PercentNumberFormat = inherited.PercentNumberFormat
483 }
484
485 if len(trans.PercentNumberFormat) == 0 && baseFound {
486 trans.PercentNumberFormat = base.PercentNumberFormat
487 }
488
489 if len(trans.CurrencyNumberFormat) == 0 && inheritedFound {
490 trans.CurrencyNumberFormat = inherited.CurrencyNumberFormat
491 }
492
493 if len(trans.CurrencyNumberFormat) == 0 && baseFound {
494 trans.CurrencyNumberFormat = base.CurrencyNumberFormat
495 }
496
497 if len(trans.NegativeCurrencyNumberFormat) == 0 && inheritedFound {
498 trans.NegativeCurrencyNumberFormat = inherited.NegativeCurrencyNumberFormat
499 }
500
501 if len(trans.NegativeCurrencyNumberFormat) == 0 && baseFound {
502 trans.NegativeCurrencyNumberFormat = base.NegativeCurrencyNumberFormat
503 }
504
505
506
507 if len(trans.FmtDateFull) == 0 && inheritedFound {
508 trans.FmtDateFull = inherited.FmtDateFull
509 }
510
511 if len(trans.FmtDateFull) == 0 && baseFound {
512 trans.FmtDateFull = base.FmtDateFull
513 }
514
515 if len(trans.FmtDateLong) == 0 && inheritedFound {
516 trans.FmtDateLong = inherited.FmtDateLong
517 }
518
519 if len(trans.FmtDateLong) == 0 && baseFound {
520 trans.FmtDateLong = base.FmtDateLong
521 }
522
523 if len(trans.FmtDateMedium) == 0 && inheritedFound {
524 trans.FmtDateMedium = inherited.FmtDateMedium
525 }
526
527 if len(trans.FmtDateMedium) == 0 && baseFound {
528 trans.FmtDateMedium = base.FmtDateMedium
529 }
530
531 if len(trans.FmtDateShort) == 0 && inheritedFound {
532 trans.FmtDateShort = inherited.FmtDateShort
533 }
534
535 if len(trans.FmtDateShort) == 0 && baseFound {
536 trans.FmtDateShort = base.FmtDateShort
537 }
538
539
540
541 if len(trans.FmtTimeFull) == 0 && inheritedFound {
542 trans.FmtTimeFull = inherited.FmtTimeFull
543 }
544
545 if len(trans.FmtTimeFull) == 0 && baseFound {
546 trans.FmtTimeFull = base.FmtTimeFull
547 }
548
549 if len(trans.FmtTimeLong) == 0 && inheritedFound {
550 trans.FmtTimeLong = inherited.FmtTimeLong
551 }
552
553 if len(trans.FmtTimeLong) == 0 && baseFound {
554 trans.FmtTimeLong = base.FmtTimeLong
555 }
556
557 if len(trans.FmtTimeMedium) == 0 && inheritedFound {
558 trans.FmtTimeMedium = inherited.FmtTimeMedium
559 }
560
561 if len(trans.FmtTimeMedium) == 0 && baseFound {
562 trans.FmtTimeMedium = base.FmtTimeMedium
563 }
564
565 if len(trans.FmtTimeShort) == 0 && inheritedFound {
566 trans.FmtTimeShort = inherited.FmtTimeShort
567 }
568
569 if len(trans.FmtTimeShort) == 0 && baseFound {
570 trans.FmtTimeShort = base.FmtTimeShort
571 }
572
573
574
575 if len(trans.FmtMonthsAbbreviated) == 0 && inheritedFound {
576 trans.FmtMonthsAbbreviated = inherited.FmtMonthsAbbreviated
577 }
578
579 if len(trans.FmtMonthsAbbreviated) == 0 && baseFound {
580 trans.FmtMonthsAbbreviated = base.FmtMonthsAbbreviated
581 }
582
583 if len(trans.FmtMonthsNarrow) == 0 && inheritedFound {
584 trans.FmtMonthsNarrow = inherited.FmtMonthsNarrow
585 }
586
587 if len(trans.FmtMonthsNarrow) == 0 && baseFound {
588 trans.FmtMonthsNarrow = base.FmtMonthsNarrow
589 }
590
591 if len(trans.FmtMonthsWide) == 0 && inheritedFound {
592 trans.FmtMonthsWide = inherited.FmtMonthsWide
593 }
594
595 if len(trans.FmtMonthsWide) == 0 && baseFound {
596 trans.FmtMonthsWide = base.FmtMonthsWide
597 }
598
599
600
601 if len(trans.FmtDaysAbbreviated) == 0 && inheritedFound {
602 trans.FmtDaysAbbreviated = inherited.FmtDaysAbbreviated
603 }
604
605 if len(trans.FmtDaysAbbreviated) == 0 && baseFound {
606 trans.FmtDaysAbbreviated = base.FmtDaysAbbreviated
607 }
608
609 if len(trans.FmtDaysNarrow) == 0 && inheritedFound {
610 trans.FmtDaysNarrow = inherited.FmtDaysNarrow
611 }
612
613 if len(trans.FmtDaysNarrow) == 0 && baseFound {
614 trans.FmtDaysNarrow = base.FmtDaysNarrow
615 }
616
617 if len(trans.FmtDaysShort) == 0 && inheritedFound {
618 trans.FmtDaysShort = inherited.FmtDaysShort
619 }
620
621 if len(trans.FmtDaysShort) == 0 && baseFound {
622 trans.FmtDaysShort = base.FmtDaysShort
623 }
624
625 if len(trans.FmtDaysWide) == 0 && inheritedFound {
626 trans.FmtDaysWide = inherited.FmtDaysWide
627 }
628
629 if len(trans.FmtDaysWide) == 0 && baseFound {
630 trans.FmtDaysWide = base.FmtDaysWide
631 }
632
633
634
635 if len(trans.FmtPeriodsAbbreviated) == 0 && inheritedFound {
636 trans.FmtPeriodsAbbreviated = inherited.FmtPeriodsAbbreviated
637 }
638
639 if len(trans.FmtPeriodsAbbreviated) == 0 && baseFound {
640 trans.FmtPeriodsAbbreviated = base.FmtPeriodsAbbreviated
641 }
642
643 if len(trans.FmtPeriodsNarrow) == 0 && inheritedFound {
644 trans.FmtPeriodsNarrow = inherited.FmtPeriodsNarrow
645 }
646
647 if len(trans.FmtPeriodsNarrow) == 0 && baseFound {
648 trans.FmtPeriodsNarrow = base.FmtPeriodsNarrow
649 }
650
651 if len(trans.FmtPeriodsShort) == 0 && inheritedFound {
652 trans.FmtPeriodsShort = inherited.FmtPeriodsShort
653 }
654
655 if len(trans.FmtPeriodsShort) == 0 && baseFound {
656 trans.FmtPeriodsShort = base.FmtPeriodsShort
657 }
658
659 if len(trans.FmtPeriodsWide) == 0 && inheritedFound {
660 trans.FmtPeriodsWide = inherited.FmtPeriodsWide
661 }
662
663 if len(trans.FmtPeriodsWide) == 0 && baseFound {
664 trans.FmtPeriodsWide = base.FmtPeriodsWide
665 }
666
667
668
669 if len(trans.FmtErasAbbreviated) == 0 && inheritedFound {
670 trans.FmtErasAbbreviated = inherited.FmtErasAbbreviated
671 }
672
673 if len(trans.FmtErasAbbreviated) == 0 && baseFound {
674 trans.FmtErasAbbreviated = base.FmtErasAbbreviated
675 }
676
677 if len(trans.FmtErasNarrow) == 0 && inheritedFound {
678 trans.FmtErasNarrow = inherited.FmtErasNarrow
679 }
680
681 if len(trans.FmtErasNarrow) == 0 && baseFound {
682 trans.FmtErasNarrow = base.FmtErasNarrow
683 }
684
685 if len(trans.FmtErasWide) == 0 && inheritedFound {
686 trans.FmtErasWide = inherited.FmtErasWide
687 }
688
689 if len(trans.FmtErasWide) == 0 && baseFound {
690 trans.FmtErasWide = base.FmtErasWide
691 }
692
693 ldml := cldr.RawLDML(trans.Locale)
694
695 currencies := make([]string, len(globalCurrencies), len(globalCurrencies))
696
697 var kval string
698
699 for k, v := range globCurrencyIdxMap {
700
701 kval = k
702
703
704
705
706 currencies[v] = kval
707 }
708
709
710 if ldml.Numbers != nil {
711
712 if ldml.Numbers.Currencies != nil {
713 for _, currency := range ldml.Numbers.Currencies.Currency {
714
715 if len(currency.Symbol) == 0 {
716 continue
717 }
718
719 if len(currency.Symbol[0].Data()) == 0 {
720 continue
721 }
722
723 if len(currency.Type) == 0 {
724 continue
725 }
726
727 currencies[globCurrencyIdxMap[currency.Type]] = currency.Symbol[0].Data()
728 }
729 }
730 }
731
732 trans.Currencies = fmt.Sprintf("%#v", currencies)
733
734
735
736 if (trans.timezones == nil || len(trans.timezones) == 0) && inheritedFound {
737 trans.timezones = inherited.timezones
738 }
739
740 if (trans.timezones == nil || len(trans.timezones) == 0) && baseFound {
741 trans.timezones = base.timezones
742 }
743
744
745 if inheritedFound {
746
747 var ok bool
748
749 for k, v := range inherited.timezones {
750
751 if _, ok = trans.timezones[k]; ok {
752 continue
753 }
754
755 trans.timezones[k] = v
756 }
757 }
758
759
760 if baseFound {
761
762 var ok bool
763
764 for k, v := range base.timezones {
765
766 if _, ok = trans.timezones[k]; ok {
767 continue
768 }
769
770 trans.timezones[k] = v
771 }
772 }
773
774 applyOverrides(trans)
775
776 parseDecimalNumberFormat(trans)
777 parsePercentNumberFormat(trans)
778 parseCurrencyNumberFormat(trans)
779 }
780
781 for _, trans := range translators {
782
783 fmt.Println("Final Processing:", trans.Locale)
784
785
786 if trans.timezones == nil {
787 trans.timezones = make(map[string]*zoneAbbrev)
788 }
789
790 tz := make(map[string]string)
791
792 for k, v := range timezones {
793
794 ttz, ok := trans.timezones[k]
795 if !ok {
796 ttz = v
797 trans.timezones[k] = v
798 }
799
800 tz[v.standard] = ttz.standard
801 tz[v.daylight] = ttz.daylight
802 }
803
804 trans.FmtTimezones = fmt.Sprintf("%#v", tz)
805
806 if len(trans.TimeSeparator) == 0 {
807 trans.TimeSeparator = ":"
808 }
809
810 trans.FmtDateShort, trans.FmtDateMedium, trans.FmtDateLong, trans.FmtDateFull = parseDateFormats(trans, trans.FmtDateShort, trans.FmtDateMedium, trans.FmtDateLong, trans.FmtDateFull)
811 trans.FmtTimeShort, trans.FmtTimeMedium, trans.FmtTimeLong, trans.FmtTimeFull = parseDateFormats(trans, trans.FmtTimeShort, trans.FmtTimeMedium, trans.FmtTimeLong, trans.FmtTimeFull)
812 }
813 }
814
815
816 func preProcess(cldrVar *cldr.CLDR) {
817
818 for _, l := range cldrVar.Locales() {
819
820 fmt.Println("Pre Processing:", l)
821
822 split := strings.SplitN(l, "_", 2)
823 baseLocale := split[0]
824
825
826
827
828
829
830
831
832 trans := &translator{
833 Locale: l,
834 BaseLocale: baseLocale,
835
836 }
837
838
839 if len(split) == 1 {
840 baseTranslators[baseLocale] = trans
841 }
842
843
844
845 translators[l] = trans
846
847
848
849
850 ldml := cldrVar.RawLDML(l)
851
852
853 if ldml.Numbers != nil {
854
855 if len(ldml.Numbers.Symbols) > 0 {
856
857 symbol := ldml.Numbers.Symbols[0]
858
859
860 systems := ldml.Numbers.DefaultNumberingSystem
861
862 if len(systems) > 0 {
863 if dns := systems[0].Data(); dns != "" {
864 for k := range ldml.Numbers.Symbols {
865 if ldml.Numbers.Symbols[k].NumberSystem == dns {
866 symbol = ldml.Numbers.Symbols[k]
867 break
868 }
869 }
870 }
871 }
872
873 if len(symbol.Decimal) > 0 {
874 trans.Decimal = symbol.Decimal[0].Data()
875 }
876 if len(symbol.Group) > 0 {
877 trans.Group = symbol.Group[0].Data()
878 }
879 if len(symbol.MinusSign) > 0 {
880 trans.Minus = symbol.MinusSign[0].Data()
881 }
882 if len(symbol.PercentSign) > 0 {
883 trans.Percent = symbol.PercentSign[0].Data()
884 }
885 if len(symbol.PerMille) > 0 {
886 trans.PerMille = symbol.PerMille[0].Data()
887 }
888
889 if len(symbol.TimeSeparator) > 0 {
890 trans.TimeSeparator = symbol.TimeSeparator[0].Data()
891 }
892
893 if len(symbol.Infinity) > 0 {
894 trans.Infinity = symbol.Infinity[0].Data()
895 }
896 }
897
898 if ldml.Numbers.Currencies != nil {
899
900 for _, currency := range ldml.Numbers.Currencies.Currency {
901
902 if len(strings.TrimSpace(currency.Type)) == 0 {
903 continue
904 }
905
906 globalCurrenciesMap[currency.Type] = struct{}{}
907 }
908 }
909
910 if len(ldml.Numbers.DecimalFormats) > 0 && len(ldml.Numbers.DecimalFormats[0].DecimalFormatLength) > 0 {
911
912 for _, dfl := range ldml.Numbers.DecimalFormats[0].DecimalFormatLength {
913 if len(dfl.Type) == 0 {
914 trans.DecimalNumberFormat = dfl.DecimalFormat[0].Pattern[0].Data()
915 break
916 }
917 }
918 }
919
920 if len(ldml.Numbers.PercentFormats) > 0 && len(ldml.Numbers.PercentFormats[0].PercentFormatLength) > 0 {
921
922 for _, dfl := range ldml.Numbers.PercentFormats[0].PercentFormatLength {
923 if len(dfl.Type) == 0 {
924 trans.PercentNumberFormat = dfl.PercentFormat[0].Pattern[0].Data()
925 break
926 }
927 }
928 }
929
930 if len(ldml.Numbers.CurrencyFormats) > 0 && len(ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength) > 0 {
931
932 if len(ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength[0].CurrencyFormat) > 1 {
933
934 split := strings.SplitN(ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength[0].CurrencyFormat[1].Pattern[0].Data(), ";", 2)
935
936 trans.CurrencyNumberFormat = split[0]
937
938 if len(split) > 1 && len(split[1]) > 0 {
939 trans.NegativeCurrencyNumberFormat = split[1]
940 } else {
941 trans.NegativeCurrencyNumberFormat = trans.CurrencyNumberFormat
942 }
943 } else {
944 trans.CurrencyNumberFormat = ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength[0].CurrencyFormat[0].Pattern[0].Data()
945 trans.NegativeCurrencyNumberFormat = trans.CurrencyNumberFormat
946 }
947 }
948 }
949
950 if ldml.Dates != nil {
951
952 if ldml.Dates.TimeZoneNames != nil {
953
954 for _, zone := range ldml.Dates.TimeZoneNames.Metazone {
955
956 for _, short := range zone.Short {
957
958 if len(short.Standard) > 0 {
959 za, ok := timezones[zone.Type]
960 if !ok {
961 za = new(zoneAbbrev)
962 timezones[zone.Type] = za
963 }
964 za.standard = short.Standard[0].Data()
965 }
966
967 if len(short.Daylight) > 0 {
968 za, ok := timezones[zone.Type]
969 if !ok {
970 za = new(zoneAbbrev)
971 timezones[zone.Type] = za
972 }
973 za.daylight = short.Daylight[0].Data()
974 }
975 }
976
977 for _, long := range zone.Long {
978
979 if trans.timezones == nil {
980 trans.timezones = make(map[string]*zoneAbbrev)
981 }
982
983 if len(long.Standard) > 0 {
984 za, ok := trans.timezones[zone.Type]
985 if !ok {
986 za = new(zoneAbbrev)
987 trans.timezones[zone.Type] = za
988 }
989 za.standard = long.Standard[0].Data()
990 }
991
992 za, ok := trans.timezones[zone.Type]
993 if !ok {
994 za = new(zoneAbbrev)
995 trans.timezones[zone.Type] = za
996 }
997
998 if len(long.Daylight) > 0 {
999 za.daylight = long.Daylight[0].Data()
1000 } else {
1001 za.daylight = za.standard
1002 }
1003 }
1004 }
1005 }
1006
1007 if ldml.Dates.Calendars != nil {
1008
1009 var calendar *cldr.Calendar
1010
1011 for _, cal := range ldml.Dates.Calendars.Calendar {
1012 if cal.Type == "gregorian" {
1013 calendar = cal
1014 }
1015 }
1016
1017 if calendar != nil {
1018
1019 if calendar.DateFormats != nil {
1020
1021 for _, datefmt := range calendar.DateFormats.DateFormatLength {
1022
1023 switch datefmt.Type {
1024 case "full":
1025 trans.FmtDateFull = datefmt.DateFormat[0].Pattern[0].Data()
1026
1027 case "long":
1028 trans.FmtDateLong = datefmt.DateFormat[0].Pattern[0].Data()
1029
1030 case "medium":
1031 trans.FmtDateMedium = datefmt.DateFormat[0].Pattern[0].Data()
1032
1033 case "short":
1034 trans.FmtDateShort = datefmt.DateFormat[0].Pattern[0].Data()
1035 }
1036 }
1037 }
1038
1039 if calendar.TimeFormats != nil {
1040
1041 for _, datefmt := range calendar.TimeFormats.TimeFormatLength {
1042
1043 switch datefmt.Type {
1044 case "full":
1045 trans.FmtTimeFull = datefmt.TimeFormat[0].Pattern[0].Data()
1046 case "long":
1047 trans.FmtTimeLong = datefmt.TimeFormat[0].Pattern[0].Data()
1048 case "medium":
1049 trans.FmtTimeMedium = datefmt.TimeFormat[0].Pattern[0].Data()
1050 case "short":
1051 trans.FmtTimeShort = datefmt.TimeFormat[0].Pattern[0].Data()
1052 }
1053 }
1054 }
1055
1056 if calendar.Months != nil {
1057
1058
1059
1060
1061 var abbrSet, narrSet, wideSet bool
1062
1063 for _, monthctx := range calendar.Months.MonthContext {
1064
1065 for _, months := range monthctx.MonthWidth {
1066
1067 var monthData []string
1068
1069 for _, m := range months.Month {
1070
1071 if len(m.Data()) == 0 {
1072 continue
1073 }
1074
1075 switch m.Type {
1076 case "1":
1077 monthData = append(monthData, m.Data())
1078 case "2":
1079 monthData = append(monthData, m.Data())
1080 case "3":
1081 monthData = append(monthData, m.Data())
1082 case "4":
1083 monthData = append(monthData, m.Data())
1084 case "5":
1085 monthData = append(monthData, m.Data())
1086 case "6":
1087 monthData = append(monthData, m.Data())
1088 case "7":
1089 monthData = append(monthData, m.Data())
1090 case "8":
1091 monthData = append(monthData, m.Data())
1092 case "9":
1093 monthData = append(monthData, m.Data())
1094 case "10":
1095 monthData = append(monthData, m.Data())
1096 case "11":
1097 monthData = append(monthData, m.Data())
1098 case "12":
1099 monthData = append(monthData, m.Data())
1100 }
1101 }
1102
1103 if len(monthData) > 0 {
1104
1105
1106
1107
1108 monthData = append(make([]string, 1, len(monthData)+1), monthData...)
1109
1110 switch months.Type {
1111 case "abbreviated":
1112 if !abbrSet {
1113 abbrSet = true
1114 trans.FmtMonthsAbbreviated = fmt.Sprintf("%#v", monthData)
1115 }
1116 case "narrow":
1117 if !narrSet {
1118 narrSet = true
1119 trans.FmtMonthsNarrow = fmt.Sprintf("%#v", monthData)
1120 }
1121 case "wide":
1122 if !wideSet {
1123 wideSet = true
1124 trans.FmtMonthsWide = fmt.Sprintf("%#v", monthData)
1125 }
1126 }
1127 }
1128 }
1129 }
1130 }
1131
1132 if calendar.Days != nil {
1133
1134
1135
1136
1137 var abbrSet, narrSet, shortSet, wideSet bool
1138
1139 for _, dayctx := range calendar.Days.DayContext {
1140
1141 for _, days := range dayctx.DayWidth {
1142
1143 var dayData []string
1144
1145 for _, d := range days.Day {
1146
1147 switch d.Type {
1148 case "sun":
1149 dayData = append(dayData, d.Data())
1150 case "mon":
1151 dayData = append(dayData, d.Data())
1152 case "tue":
1153 dayData = append(dayData, d.Data())
1154 case "wed":
1155 dayData = append(dayData, d.Data())
1156 case "thu":
1157 dayData = append(dayData, d.Data())
1158 case "fri":
1159 dayData = append(dayData, d.Data())
1160 case "sat":
1161 dayData = append(dayData, d.Data())
1162 }
1163 }
1164
1165 if len(dayData) > 0 {
1166 switch days.Type {
1167 case "abbreviated":
1168 if !abbrSet {
1169 abbrSet = true
1170 trans.FmtDaysAbbreviated = fmt.Sprintf("%#v", dayData)
1171 }
1172 case "narrow":
1173 if !narrSet {
1174 narrSet = true
1175 trans.FmtDaysNarrow = fmt.Sprintf("%#v", dayData)
1176 }
1177 case "short":
1178 if !shortSet {
1179 shortSet = true
1180 trans.FmtDaysShort = fmt.Sprintf("%#v", dayData)
1181 }
1182 case "wide":
1183 if !wideSet {
1184 wideSet = true
1185 trans.FmtDaysWide = fmt.Sprintf("%#v", dayData)
1186 }
1187 }
1188 }
1189 }
1190 }
1191 }
1192
1193 if calendar.DayPeriods != nil {
1194
1195
1196
1197
1198 var abbrSet, narrSet, shortSet, wideSet bool
1199
1200 for _, ctx := range calendar.DayPeriods.DayPeriodContext {
1201
1202 for _, width := range ctx.DayPeriodWidth {
1203
1204
1205
1206 ampm := make([]string, 2, 2)
1207
1208 for _, d := range width.DayPeriod {
1209
1210 if d.Type == "am" {
1211 ampm[0] = d.Data()
1212 continue
1213 }
1214
1215 if d.Type == "pm" {
1216 ampm[1] = d.Data()
1217 }
1218 }
1219
1220 switch width.Type {
1221 case "abbreviated":
1222 if !abbrSet {
1223 abbrSet = true
1224 trans.FmtPeriodsAbbreviated = fmt.Sprintf("%#v", ampm)
1225 }
1226 case "narrow":
1227 if !narrSet {
1228 narrSet = true
1229 trans.FmtPeriodsNarrow = fmt.Sprintf("%#v", ampm)
1230 }
1231 case "short":
1232 if !shortSet {
1233 shortSet = true
1234 trans.FmtPeriodsShort = fmt.Sprintf("%#v", ampm)
1235 }
1236 case "wide":
1237 if !wideSet {
1238 wideSet = true
1239 trans.FmtPeriodsWide = fmt.Sprintf("%#v", ampm)
1240 }
1241 }
1242 }
1243 }
1244 }
1245
1246 if calendar.Eras != nil {
1247
1248
1249
1250 abbrev := make([]string, 2, 2)
1251 narr := make([]string, 2, 2)
1252 wide := make([]string, 2, 2)
1253
1254 if calendar.Eras.EraAbbr != nil {
1255
1256 if len(calendar.Eras.EraAbbr.Era) == 4 {
1257 abbrev[0] = calendar.Eras.EraAbbr.Era[0].Data()
1258 abbrev[1] = calendar.Eras.EraAbbr.Era[2].Data()
1259 } else if len(calendar.Eras.EraAbbr.Era) == 2 {
1260 abbrev[0] = calendar.Eras.EraAbbr.Era[0].Data()
1261 abbrev[1] = calendar.Eras.EraAbbr.Era[1].Data()
1262 }
1263 }
1264
1265 if calendar.Eras.EraNarrow != nil {
1266
1267 if len(calendar.Eras.EraNarrow.Era) == 4 {
1268 narr[0] = calendar.Eras.EraNarrow.Era[0].Data()
1269 narr[1] = calendar.Eras.EraNarrow.Era[2].Data()
1270 } else if len(calendar.Eras.EraNarrow.Era) == 2 {
1271 narr[0] = calendar.Eras.EraNarrow.Era[0].Data()
1272 narr[1] = calendar.Eras.EraNarrow.Era[1].Data()
1273 }
1274 }
1275
1276 if calendar.Eras.EraNames != nil {
1277
1278 if len(calendar.Eras.EraNames.Era) == 4 {
1279 wide[0] = calendar.Eras.EraNames.Era[0].Data()
1280 wide[1] = calendar.Eras.EraNames.Era[2].Data()
1281 } else if len(calendar.Eras.EraNames.Era) == 2 {
1282 wide[0] = calendar.Eras.EraNames.Era[0].Data()
1283 wide[1] = calendar.Eras.EraNames.Era[1].Data()
1284 }
1285 }
1286
1287 trans.FmtErasAbbreviated = fmt.Sprintf("%#v", abbrev)
1288 trans.FmtErasNarrow = fmt.Sprintf("%#v", narr)
1289 trans.FmtErasWide = fmt.Sprintf("%#v", wide)
1290 }
1291 }
1292 }
1293 }
1294 }
1295
1296 for k := range globalCurrenciesMap {
1297 globalCurrencies = append(globalCurrencies, k)
1298 }
1299
1300 sort.Strings(globalCurrencies)
1301
1302 for i, loc := range globalCurrencies {
1303 globCurrencyIdxMap[loc] = i
1304 }
1305 }
1306
1307 func parseDateFormats(trans *translator, shortFormat, mediumFormat, longFormat, fullFormat string) (short, medium, long, full string) {
1308
1309
1310
1311 short = parseDateTimeFormat(trans.BaseLocale, shortFormat, 2)
1312 medium = parseDateTimeFormat(trans.BaseLocale, mediumFormat, 2)
1313 long = parseDateTimeFormat(trans.BaseLocale, longFormat, 1)
1314 full = parseDateTimeFormat(trans.BaseLocale, fullFormat, 0)
1315
1316
1317
1318 return
1319 }
1320
1321 func parseDateTimeFormat(baseLocale, format string, eraScore uint8) (results string) {
1322
1323
1324
1325
1326
1327
1328
1329 var inConstantText bool
1330 var start int
1331
1332 for i := 0; i < len(format); i++ {
1333
1334 switch format[i] {
1335
1336
1337 case ':':
1338
1339 if inConstantText {
1340 inConstantText = false
1341 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1342 }
1343
1344 results += "b = append(b, " + baseLocale + ".timeSeparator...)\n"
1345 case '\'':
1346
1347 i++
1348 startI := i
1349
1350
1351 if len(format) != i && format[i] == '\'' {
1352
1353 if inConstantText {
1354 inConstantText = false
1355 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i-1])) + "...)\n"
1356 } else {
1357 inConstantText = true
1358 start = i
1359 }
1360
1361 continue
1362 }
1363
1364
1365
1366 if len(format) != i {
1367
1368
1369 for ; i < len(format); i++ {
1370 if format[i] == '\'' {
1371
1372 if inConstantText {
1373 inConstantText = false
1374 b := []byte(format[start : startI-1])
1375 b = append(b, []byte(format[startI:i])...)
1376
1377 results += "b = append(b, " + fmt.Sprintf("%#v", b) + "...)\n"
1378
1379 } else {
1380 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[startI:i])) + "...)\n"
1381 }
1382
1383 break
1384 }
1385 }
1386 }
1387
1388
1389 case 'H':
1390
1391 if inConstantText {
1392 inConstantText = false
1393 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1394 }
1395
1396
1397
1398 if len(format) != i+1 && format[i+1] == 'H' {
1399 i++
1400 results += `
1401 if t.Hour() < 10 {
1402 b = append(b, '0')
1403 }
1404
1405 `
1406 }
1407
1408 results += "b = strconv.AppendInt(b, int64(t.Hour()), 10)\n"
1409
1410
1411 case 'h':
1412
1413 if inConstantText {
1414 inConstantText = false
1415 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1416 }
1417
1418 results += `
1419 h := t.Hour()
1420
1421 if h > 12 {
1422 h -= 12
1423 }
1424
1425 `
1426
1427
1428
1429 if len(format) != i+1 && format[i+1] == 'h' {
1430 i++
1431 results += `
1432 if h < 10 {
1433 b = append(b, '0')
1434 }
1435
1436 `
1437 }
1438
1439 results += "b = strconv.AppendInt(b, int64(h), 10)\n"
1440
1441
1442 case 'm':
1443
1444 if inConstantText {
1445 inConstantText = false
1446 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1447 }
1448
1449
1450
1451 if len(format) != i+1 && format[i+1] == 'm' {
1452 i++
1453 results += `
1454
1455 if t.Minute() < 10 {
1456 b = append(b, '0')
1457 }
1458
1459 `
1460 }
1461
1462 results += "b = strconv.AppendInt(b, int64(t.Minute()), 10)\n"
1463
1464
1465 case 's':
1466
1467 if inConstantText {
1468 inConstantText = false
1469 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1470 }
1471
1472
1473
1474 if len(format) != i+1 && format[i+1] == 's' {
1475 i++
1476 results += `
1477
1478 if t.Second() < 10 {
1479 b = append(b, '0')
1480 }
1481
1482 `
1483 }
1484
1485 results += "b = strconv.AppendInt(b, int64(t.Second()), 10)\n"
1486
1487
1488 case 'a':
1489
1490 if inConstantText {
1491 inConstantText = false
1492 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1493 }
1494
1495
1496
1497
1498
1499
1500 results += `
1501
1502 if t.Hour() < 12 {
1503 b = append(b, ` + baseLocale + `.periodsAbbreviated[0]...)
1504 } else {
1505 b = append(b, ` + baseLocale + `.periodsAbbreviated[1]...)
1506 }
1507
1508 `
1509
1510
1511 case 'z', 'v':
1512
1513 if inConstantText {
1514 inConstantText = false
1515 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1516 }
1517
1518
1519
1520 var count int
1521
1522 if format[i] == 'z' {
1523 for j := i; j < len(format); j++ {
1524 if format[j] == 'z' {
1525 count++
1526 } else {
1527 break
1528 }
1529 }
1530 }
1531
1532 if format[i] == 'v' {
1533 for j := i; j < len(format); j++ {
1534 if format[j] == 'v' {
1535 count++
1536 } else {
1537 break
1538 }
1539 }
1540 }
1541
1542 i += count - 1
1543
1544
1545
1546 if count < 4 {
1547
1548 results += `
1549
1550 tz, _ := t.Zone()
1551 b = append(b, tz...)
1552
1553 `
1554 } else {
1555
1556 results += `
1557 tz, _ := t.Zone()
1558
1559 if btz, ok := ` + baseLocale + `.timezones[tz]; ok {
1560 b = append(b, btz...)
1561 } else {
1562 b = append(b, tz...)
1563 }
1564
1565 `
1566 }
1567
1568
1569 case 'd':
1570
1571 if inConstantText {
1572 inConstantText = false
1573 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1574 }
1575
1576
1577
1578 if len(format) != i+1 && format[i+1] == 'd' {
1579 i++
1580 results += `
1581
1582 if t.Day() < 10 {
1583 b = append(b, '0')
1584 }
1585
1586 `
1587 }
1588
1589 results += "b = strconv.AppendInt(b, int64(t.Day()), 10)\n"
1590
1591
1592 case 'M':
1593
1594 if inConstantText {
1595 inConstantText = false
1596 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1597 }
1598
1599 var count int
1600
1601
1602 for j := i; j < len(format); j++ {
1603 if format[j] == 'M' {
1604 count++
1605 } else {
1606 break
1607 }
1608 }
1609
1610 switch count {
1611
1612
1613 case 1:
1614
1615 results += "b = strconv.AppendInt(b, int64(t.Month()), 10)\n"
1616
1617
1618 case 2:
1619
1620 results += `
1621
1622 if t.Month() < 10 {
1623 b = append(b, '0')
1624 }
1625
1626 b = strconv.AppendInt(b, int64(t.Month()), 10)
1627
1628 `
1629
1630
1631 case 3:
1632
1633 results += "b = append(b, " + baseLocale + ".monthsAbbreviated[t.Month()]...)\n"
1634
1635
1636 case 4:
1637
1638 results += "b = append(b, " + baseLocale + ".monthsWide[t.Month()]...)\n"
1639
1640
1641
1642 case 5:
1643
1644 results += "b = append(b, " + baseLocale + ".monthsNarrow[t.Month()]...)\n"
1645 }
1646
1647
1648 i += count - 1
1649
1650
1651 case 'y':
1652
1653 if inConstantText {
1654 inConstantText = false
1655 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1656 }
1657
1658
1659
1660 if len(format) != i+1 && format[i+1] == 'y' {
1661 i++
1662 results += `
1663
1664 if t.Year() > 9 {
1665 b = append(b, strconv.Itoa(t.Year())[2:]...)
1666 } else {
1667 b = append(b, strconv.Itoa(t.Year())[1:]...)
1668 }
1669
1670 `
1671 } else {
1672
1673 results += `
1674
1675 if t.Year() > 0 {
1676 b = strconv.AppendInt(b, int64(t.Year()), 10)
1677 } else {
1678 b = strconv.AppendInt(b, int64(-t.Year()), 10)
1679 }
1680
1681 `
1682 }
1683
1684
1685
1686 case 'E':
1687
1688 if inConstantText {
1689 inConstantText = false
1690 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1691 }
1692
1693 var count int
1694
1695
1696 for j := i; j < len(format); j++ {
1697 if format[j] == 'E' {
1698 count++
1699 } else {
1700 break
1701 }
1702 }
1703
1704 switch count {
1705
1706
1707 case 1:
1708
1709 results += "b = append(b, " + baseLocale + ".daysNarrow[t.Weekday()]...)\n"
1710
1711
1712 case 2:
1713
1714 results += "b = append(b, " + baseLocale + ".daysShort[t.Weekday()]...)\n"
1715
1716
1717 case 3:
1718
1719 results += "b = append(b, " + baseLocale + ".daysAbbreviated[t.Weekday()]...)\n"
1720
1721
1722 case 4:
1723
1724 results += "b = append(b, " + baseLocale + ".daysWide[t.Weekday()]...)\n"
1725 }
1726
1727
1728 i += count - 1
1729
1730
1731 case 'G':
1732
1733 if inConstantText {
1734 inConstantText = false
1735 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:i])) + "...)\n"
1736 }
1737
1738 switch eraScore {
1739 case 0:
1740 results += `
1741
1742 if t.Year() < 0 {
1743 b = append(b, ` + baseLocale + `.erasWide[0]...)
1744 } else {
1745 b = append(b, ` + baseLocale + `.erasWide[1]...)
1746 }
1747
1748 `
1749 case 1, 2:
1750 results += `
1751
1752 if t.Year() < 0 {
1753 b = append(b, ` + baseLocale + `.erasAbbreviated[0]...)
1754 } else {
1755 b = append(b, ` + baseLocale + `.erasAbbreviated[1]...)
1756 }
1757
1758 `
1759 }
1760
1761 default:
1762
1763 if !inConstantText {
1764 inConstantText = true
1765 start = i
1766 }
1767 }
1768 }
1769
1770
1771 if inConstantText {
1772
1773 results += "b = append(b, " + fmt.Sprintf("%#v", []byte(format[start:])) + "...)\n"
1774 }
1775
1776 return
1777 }
1778
1779 func parseCurrencyNumberFormat(trans *translator) {
1780
1781 if len(trans.CurrencyNumberFormat) == 0 {
1782 return
1783 }
1784
1785 trans.FmtCurrencyExists = true
1786 negativeEqual := trans.CurrencyNumberFormat == trans.NegativeCurrencyNumberFormat
1787
1788 match := groupLenRegex.FindString(trans.CurrencyNumberFormat)
1789 if len(match) > 0 {
1790 trans.FmtCurrencyGroupLen = len(match) - 2
1791 }
1792
1793 match = requiredDecimalRegex.FindString(trans.CurrencyNumberFormat)
1794 if len(match) > 0 {
1795 trans.FmtCurrencyMinDecimalLen = len(match) - 1
1796 }
1797
1798 match = secondaryGroupLenRegex.FindString(trans.CurrencyNumberFormat)
1799 if len(match) > 0 {
1800 trans.FmtCurrencySecondaryGroupLen = len(match) - 2
1801 }
1802
1803 idx := 0
1804
1805 for idx = 0; idx < len(trans.CurrencyNumberFormat); idx++ {
1806 if trans.CurrencyNumberFormat[idx] == '#' || trans.CurrencyNumberFormat[idx] == '0' {
1807 trans.FmtCurrencyPrefix = trans.CurrencyNumberFormat[:idx]
1808 break
1809 }
1810 }
1811
1812 for idx = len(trans.CurrencyNumberFormat) - 1; idx >= 0; idx-- {
1813 if trans.CurrencyNumberFormat[idx] == '#' || trans.CurrencyNumberFormat[idx] == '0' {
1814 idx++
1815 trans.FmtCurrencySuffix = trans.CurrencyNumberFormat[idx:]
1816 break
1817 }
1818 }
1819
1820 for idx = 0; idx < len(trans.FmtCurrencyPrefix); idx++ {
1821 if trans.FmtCurrencyPrefix[idx] == '¤' {
1822
1823 trans.FmtCurrencyInPrefix = true
1824 trans.FmtCurrencyPrefix = strings.Replace(trans.FmtCurrencyPrefix, string(trans.FmtCurrencyPrefix[idx]), "", 1)
1825
1826 if idx == 0 {
1827 trans.FmtCurrencyLeft = true
1828 } else {
1829 trans.FmtCurrencyLeft = false
1830 }
1831
1832 break
1833 }
1834 }
1835
1836 for idx = 0; idx < len(trans.FmtCurrencySuffix); idx++ {
1837 if trans.FmtCurrencySuffix[idx] == '¤' {
1838
1839 trans.FmtCurrencyInPrefix = false
1840 trans.FmtCurrencySuffix = strings.Replace(trans.FmtCurrencySuffix, string(trans.FmtCurrencySuffix[idx]), "", 1)
1841
1842 if idx == 0 {
1843 trans.FmtCurrencyLeft = true
1844 } else {
1845 trans.FmtCurrencyLeft = false
1846 }
1847
1848 break
1849 }
1850 }
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861 if negativeEqual {
1862
1863 trans.FmtCurrencyNegativePrefix = trans.FmtCurrencyPrefix
1864 trans.FmtCurrencyNegativeSuffix = trans.FmtCurrencySuffix
1865 trans.FmtCurrencyNegativeInPrefix = trans.FmtCurrencyInPrefix
1866 trans.FmtCurrencyNegativeLeft = trans.FmtCurrencyLeft
1867
1868 return
1869 }
1870
1871 trans.FmtCurrencyNegativeExists = true
1872
1873 for idx = 0; idx < len(trans.NegativeCurrencyNumberFormat); idx++ {
1874 if trans.NegativeCurrencyNumberFormat[idx] == '#' || trans.NegativeCurrencyNumberFormat[idx] == '0' {
1875
1876 trans.FmtCurrencyNegativePrefix = trans.NegativeCurrencyNumberFormat[:idx]
1877 break
1878 }
1879 }
1880
1881 for idx = len(trans.NegativeCurrencyNumberFormat) - 1; idx >= 0; idx-- {
1882 if trans.NegativeCurrencyNumberFormat[idx] == '#' || trans.NegativeCurrencyNumberFormat[idx] == '0' {
1883 idx++
1884 trans.FmtCurrencyNegativeSuffix = trans.NegativeCurrencyNumberFormat[idx:]
1885 break
1886 }
1887 }
1888
1889 for idx = 0; idx < len(trans.FmtCurrencyNegativePrefix); idx++ {
1890 if trans.FmtCurrencyNegativePrefix[idx] == '¤' {
1891
1892 trans.FmtCurrencyNegativeInPrefix = true
1893 trans.FmtCurrencyNegativePrefix = strings.Replace(trans.FmtCurrencyNegativePrefix, string(trans.FmtCurrencyNegativePrefix[idx]), "", 1)
1894
1895 if idx == 0 {
1896 trans.FmtCurrencyNegativeLeft = true
1897 } else {
1898 trans.FmtCurrencyNegativeLeft = false
1899 }
1900
1901 break
1902 }
1903 }
1904
1905 for idx = 0; idx < len(trans.FmtCurrencyNegativeSuffix); idx++ {
1906 if trans.FmtCurrencyNegativeSuffix[idx] == '¤' {
1907
1908 trans.FmtCurrencyNegativeInPrefix = false
1909 trans.FmtCurrencyNegativeSuffix = strings.Replace(trans.FmtCurrencyNegativeSuffix, string(trans.FmtCurrencyNegativeSuffix[idx]), "", 1)
1910
1911 if idx == 0 {
1912 trans.FmtCurrencyNegativeLeft = true
1913 } else {
1914 trans.FmtCurrencyNegativeLeft = false
1915 }
1916
1917 break
1918 }
1919 }
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929 return
1930 }
1931
1932 func parsePercentNumberFormat(trans *translator) {
1933
1934 if len(trans.PercentNumberFormat) == 0 {
1935 return
1936 }
1937
1938 trans.FmtPercentExists = true
1939
1940 match := groupLenPercentRegex.FindString(trans.PercentNumberFormat)
1941 if len(match) > 0 {
1942 trans.FmtPercentGroupLen = len(match) - 1
1943 }
1944
1945 match = requiredDecimalRegex.FindString(trans.PercentNumberFormat)
1946 if len(match) > 0 {
1947 trans.FmtPercentMinDecimalLen = len(match) - 1
1948 }
1949
1950 match = secondaryGroupLenRegex.FindString(trans.PercentNumberFormat)
1951 if len(match) > 0 {
1952 trans.FmtPercentSecondaryGroupLen = len(match) - 2
1953 }
1954
1955 idx := 0
1956
1957 for idx = 0; idx < len(trans.PercentNumberFormat); idx++ {
1958 if trans.PercentNumberFormat[idx] == '#' || trans.PercentNumberFormat[idx] == '0' {
1959 trans.FmtPercentPrefix = trans.PercentNumberFormat[:idx]
1960 break
1961 }
1962 }
1963
1964 for idx = len(trans.PercentNumberFormat) - 1; idx >= 0; idx-- {
1965 if trans.PercentNumberFormat[idx] == '#' || trans.PercentNumberFormat[idx] == '0' {
1966 idx++
1967 trans.FmtPercentSuffix = trans.PercentNumberFormat[idx:]
1968 break
1969 }
1970 }
1971
1972 for idx = 0; idx < len(trans.FmtPercentPrefix); idx++ {
1973 if trans.FmtPercentPrefix[idx] == '%' {
1974
1975 trans.FmtPercentInPrefix = true
1976 trans.FmtPercentPrefix = strings.Replace(trans.FmtPercentPrefix, string(trans.FmtPercentPrefix[idx]), "", 1)
1977
1978 if idx == 0 {
1979 trans.FmtPercentLeft = true
1980 } else {
1981 trans.FmtPercentLeft = false
1982 }
1983
1984 break
1985 }
1986 }
1987
1988 for idx = 0; idx < len(trans.FmtPercentSuffix); idx++ {
1989 if trans.FmtPercentSuffix[idx] == '%' {
1990
1991 trans.FmtPercentInPrefix = false
1992 trans.FmtPercentSuffix = strings.Replace(trans.FmtPercentSuffix, string(trans.FmtPercentSuffix[idx]), "", 1)
1993
1994 if idx == 0 {
1995 trans.FmtPercentLeft = true
1996 } else {
1997 trans.FmtPercentLeft = false
1998 }
1999
2000 break
2001 }
2002 }
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012 return
2013 }
2014
2015 func parseDecimalNumberFormat(trans *translator) {
2016
2017 if len(trans.DecimalNumberFormat) == 0 {
2018 return
2019 }
2020
2021 trans.FmtNumberExists = true
2022
2023 formats := strings.SplitN(trans.DecimalNumberFormat, ";", 2)
2024
2025 match := groupLenRegex.FindString(formats[0])
2026 if len(match) > 0 {
2027 trans.FmtNumberGroupLen = len(match) - 2
2028 }
2029
2030 match = requiredDecimalRegex.FindString(formats[0])
2031 if len(match) > 0 {
2032 trans.FmtNumberMinDecimalLen = len(match) - 1
2033 }
2034
2035 match = secondaryGroupLenRegex.FindString(formats[0])
2036 if len(match) > 0 {
2037 trans.FmtNumberSecondaryGroupLen = len(match) - 2
2038 }
2039
2040 return
2041 }
2042
2043 type sortRank struct {
2044 Rank uint8
2045 Value string
2046 }
2047
2048 type ByRank []sortRank
2049
2050 func (a ByRank) Len() int { return len(a) }
2051 func (a ByRank) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
2052 func (a ByRank) Less(i, j int) bool { return a[i].Rank < a[j].Rank }
2053
2054 type ByPluralRule []locales.PluralRule
2055
2056 func (a ByPluralRule) Len() int { return len(a) }
2057 func (a ByPluralRule) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
2058 func (a ByPluralRule) Less(i, j int) bool { return a[i] < a[j] }
2059
2060
2061
2062 func parseRangePluralRuleFunc(current *cldr.CLDR, baseLocale string) (results string, plurals string) {
2063
2064 var pluralRange *struct {
2065 cldr.Common
2066 Locales string `xml:"locales,attr"`
2067 PluralRange []*struct {
2068 cldr.Common
2069 Start string `xml:"start,attr"`
2070 End string `xml:"end,attr"`
2071 Result string `xml:"result,attr"`
2072 } `xml:"pluralRange"`
2073 }
2074
2075 var pluralArr []locales.PluralRule
2076
2077 for _, pr := range current.Supplemental().Plurals[1].PluralRanges {
2078
2079 locs := strings.Split(pr.Locales, " ")
2080
2081 for _, loc := range locs {
2082
2083 if loc == baseLocale {
2084 pluralRange = pr
2085 }
2086 }
2087 }
2088
2089
2090 if pluralRange == nil {
2091 plurals = "nil"
2092 results = "return locales.PluralRuleUnknown"
2093 return
2094 }
2095
2096 mp := make(map[string]struct{})
2097
2098
2099 for _, rule := range pluralRange.PluralRange {
2100 mp[rule.Result] = struct{}{}
2101 }
2102
2103 for k := range mp {
2104 psI := pluralStringToInt(k)
2105 pluralArr = append(pluralArr, psI)
2106 }
2107
2108 if len(mp) == 1 {
2109 results += "return locales." + pluralStringToString(pluralRange.PluralRange[0].Result)
2110 plurals = fmt.Sprintf("%#v", pluralArr)
2111 return
2112 }
2113
2114 multiple := len(pluralRange.PluralRange) > 1
2115
2116 if multiple {
2117 results += "start := " + baseLocale + ".CardinalPluralRule(num1, v1)\n"
2118 results += "end := " + baseLocale + ".CardinalPluralRule(num2, v2)\n\n"
2119 }
2120
2121 first := true
2122
2123
2124 for i, rule := range pluralRange.PluralRange {
2125
2126 if i == len(pluralRange.PluralRange)-1 {
2127
2128 if multiple {
2129 results += "\n\n"
2130 }
2131 results += "return locales." + pluralStringToString(rule.Result)
2132 continue
2133 }
2134
2135 if first {
2136 results += "if"
2137 first = false
2138 } else {
2139 results += "else if"
2140 }
2141
2142 results += " start == locales." + pluralStringToString(rule.Start) + " && end == locales." + pluralStringToString(rule.End) + " {\n return locales." + pluralStringToString(rule.Result) + "\n} "
2143
2144 }
2145
2146 if multiple {
2147 results = "\n" + results + "\n"
2148 }
2149
2150 if len(pluralArr) == 0 {
2151 plurals = "nil"
2152 } else {
2153
2154 ints := make([]int, len(pluralArr))
2155 for i := 0; i < len(pluralArr); i++ {
2156 ints[i] = int(pluralArr[i])
2157 }
2158
2159 sort.Ints(ints)
2160
2161 for i := 0; i < len(ints); i++ {
2162 pluralArr[i] = locales.PluralRule(ints[i])
2163 }
2164
2165 plurals = fmt.Sprintf("%#v", pluralArr)
2166 }
2167
2168 return
2169
2170 }
2171
2172
2173
2174 func parseOrdinalPluralRuleFunc(current *cldr.CLDR, baseLocale string) (results string, plurals string) {
2175
2176 var prOrdinal *struct {
2177 cldr.Common
2178 Locales string "xml:\"locales,attr\""
2179 PluralRule []*struct {
2180 cldr.Common
2181 Count string "xml:\"count,attr\""
2182 } "xml:\"pluralRule\""
2183 }
2184
2185 var pluralArr []locales.PluralRule
2186
2187
2188 for _, pr := range current.Supplemental().Plurals[0].PluralRules {
2189
2190 locs := strings.Split(pr.Locales, " ")
2191
2192 for _, loc := range locs {
2193
2194 if loc == baseLocale {
2195
2196 prOrdinal = pr
2197
2198
2199
2200 }
2201 }
2202 }
2203
2204
2205 if prOrdinal == nil {
2206 plurals = "nil"
2207 results = "return locales.PluralRuleUnknown"
2208 return
2209 }
2210
2211 vals := make(map[string]struct{})
2212 first := true
2213
2214
2215 for _, rule := range prOrdinal.PluralRule {
2216
2217 ps1 := pluralStringToString(rule.Count)
2218 psI := pluralStringToInt(rule.Count)
2219 pluralArr = append(pluralArr, psI)
2220
2221 data := strings.Replace(strings.Replace(strings.Replace(strings.TrimSpace(strings.SplitN(rule.Common.Data(), "@", 2)[0]), " = ", " == ", -1), " or ", " || ", -1), " and ", " && ", -1)
2222
2223 if len(data) == 0 {
2224 if len(prOrdinal.PluralRule) == 1 {
2225
2226 results = "return locales." + ps1
2227
2228 } else {
2229
2230 results += "\n\nreturn locales." + ps1
2231
2232 }
2233
2234 continue
2235 }
2236
2237
2238
2239
2240
2241
2242 if strings.Contains(data, "i") {
2243 vals[prVarFuncs["i"]] = struct{}{}
2244 }
2245
2246
2247
2248
2249
2250
2251 if strings.Contains(data, "w") {
2252 vals[prVarFuncs["w"]] = struct{}{}
2253 }
2254
2255 if strings.Contains(data, "f") {
2256 vals[prVarFuncs["f"]] = struct{}{}
2257 }
2258
2259 if strings.Contains(data, "t") {
2260 vals[prVarFuncs["t"]] = struct{}{}
2261 }
2262
2263 if first {
2264 results += "if "
2265 first = false
2266 } else {
2267 results += "else if "
2268 }
2269
2270 stmt := ""
2271
2272
2273
2274
2275
2276
2277 ors := strings.Split(data, "||")
2278
2279 for _, or := range ors {
2280
2281 stmt += "("
2282
2283 ands := strings.Split(strings.TrimSpace(or), "&&")
2284
2285 for _, and := range ands {
2286
2287 inArg := false
2288 pre := ""
2289 lft := ""
2290 preOperator := ""
2291 args := strings.Split(strings.TrimSpace(and), " ")
2292
2293 for _, a := range args {
2294
2295 if inArg {
2296
2297
2298 multiRange := strings.Count(a, "..") > 1
2299 cargs := strings.Split(strings.TrimSpace(a), ",")
2300 hasBracket := len(cargs) > 1
2301 bracketAdded := false
2302 lastWasRange := false
2303
2304 for _, carg := range cargs {
2305
2306 if rng := strings.Split(carg, ".."); len(rng) > 1 {
2307
2308 if multiRange {
2309 pre += " ("
2310 } else {
2311 pre += " "
2312 }
2313
2314 switch preOperator {
2315 case "==":
2316 pre += lft + " >= " + rng[0] + " && " + lft + "<=" + rng[1]
2317 case "!=":
2318 pre += "(" + lft + " < " + rng[0] + " || " + lft + " > " + rng[1] + ")"
2319 }
2320
2321 if multiRange {
2322 pre += ") || "
2323 } else {
2324 pre += " || "
2325 }
2326
2327 lastWasRange = true
2328 continue
2329 }
2330
2331 if lastWasRange {
2332 pre = strings.TrimRight(pre, " || ") + " && "
2333 }
2334
2335 lastWasRange = false
2336
2337 if hasBracket && !bracketAdded {
2338 pre += "("
2339 bracketAdded = true
2340 }
2341
2342
2343 switch preOperator {
2344 case "==":
2345 pre += " " + lft + preOperator + carg + " || "
2346 case "!=":
2347 pre += " " + lft + preOperator + carg + " && "
2348 }
2349
2350 }
2351
2352 pre = strings.TrimRight(pre, " || ")
2353 pre = strings.TrimRight(pre, " && ")
2354 pre = strings.TrimRight(pre, " || ")
2355
2356 if hasBracket && bracketAdded {
2357 pre += ")"
2358 }
2359
2360 continue
2361 }
2362
2363 if strings.Contains(a, "=") || a == ">" || a == "<" {
2364 inArg = true
2365 preOperator = a
2366 continue
2367 }
2368
2369 lft += a
2370 }
2371
2372 stmt += pre + " && "
2373 }
2374
2375 stmt = strings.TrimRight(stmt, " && ") + ") || "
2376 }
2377
2378 stmt = strings.TrimRight(stmt, " || ")
2379
2380 results += stmt
2381
2382 results += " {\n"
2383
2384
2385 results += "return locales." + ps1 + "\n"
2386
2387 results += "}"
2388 }
2389
2390 pre := "\n"
2391
2392
2393 vals[prVarFuncs["n"]] = struct{}{}
2394
2395 sorted := make([]sortRank, 0, len(vals))
2396
2397 for k := range vals {
2398 switch k[:1] {
2399 case "n":
2400 sorted = append(sorted, sortRank{
2401 Value: prVarFuncs["n"],
2402 Rank: 1,
2403 })
2404 case "i":
2405 sorted = append(sorted, sortRank{
2406 Value: prVarFuncs["i"],
2407 Rank: 2,
2408 })
2409 case "w":
2410 sorted = append(sorted, sortRank{
2411 Value: prVarFuncs["w"],
2412 Rank: 3,
2413 })
2414 case "f":
2415 sorted = append(sorted, sortRank{
2416 Value: prVarFuncs["f"],
2417 Rank: 4,
2418 })
2419 case "t":
2420 sorted = append(sorted, sortRank{
2421 Value: prVarFuncs["t"],
2422 Rank: 5,
2423 })
2424 }
2425 }
2426
2427 sort.Sort(ByRank(sorted))
2428
2429 for _, k := range sorted {
2430 pre += k.Value
2431 }
2432
2433 if len(results) == 0 {
2434 results = "return locales.PluralRuleUnknown"
2435 } else {
2436
2437 if !strings.HasPrefix(results, "return") {
2438
2439 results = manyToSingleVars(results)
2440
2441 results = pre + results
2442 }
2443 }
2444
2445 if len(pluralArr) == 0 {
2446 plurals = "nil"
2447 } else {
2448 plurals = fmt.Sprintf("%#v", pluralArr)
2449 }
2450
2451 return
2452 }
2453
2454
2455
2456
2457
2458 func parseCardinalPluralRuleFunc(current *cldr.CLDR, locale, baseLocale string) (results string, plurals string) {
2459
2460 var prCardinal *struct {
2461 cldr.Common
2462 Locales string "xml:\"locales,attr\""
2463 PluralRule []*struct {
2464 cldr.Common
2465 Count string "xml:\"count,attr\""
2466 } "xml:\"pluralRule\""
2467 }
2468
2469 var pluralArr []locales.PluralRule
2470 var inBaseLocale bool
2471 l := locale
2472
2473 FIND:
2474
2475 for _, pr := range current.Supplemental().Plurals[2].PluralRules {
2476
2477 locs := strings.Split(pr.Locales, " ")
2478
2479 for _, loc := range locs {
2480
2481 if loc == l {
2482 prCardinal = pr
2483 }
2484 }
2485 }
2486
2487
2488 if prCardinal == nil {
2489
2490 if !inBaseLocale {
2491 inBaseLocale = true
2492 l = baseLocale
2493 goto FIND
2494 }
2495
2496 plurals = "nil"
2497 results = "return locales.PluralRuleUnknown"
2498 return
2499 }
2500
2501 vals := make(map[string]struct{})
2502 first := true
2503
2504
2505 for _, rule := range prCardinal.PluralRule {
2506
2507 ps1 := pluralStringToString(rule.Count)
2508 psI := pluralStringToInt(rule.Count)
2509 pluralArr = append(pluralArr, psI)
2510
2511 data := strings.Replace(strings.Replace(strings.Replace(strings.TrimSpace(strings.SplitN(rule.Common.Data(), "@", 2)[0]), " = ", " == ", -1), " or ", " || ", -1), " and ", " && ", -1)
2512
2513 if len(data) == 0 {
2514 if len(prCardinal.PluralRule) == 1 {
2515
2516 results = "return locales." + ps1
2517
2518 } else {
2519
2520 results += "\n\nreturn locales." + ps1
2521
2522 }
2523
2524 continue
2525 }
2526
2527
2528
2529
2530
2531
2532 if strings.Contains(data, "i") {
2533 vals[prVarFuncs["i"]] = struct{}{}
2534 }
2535
2536
2537
2538
2539
2540
2541 if strings.Contains(data, "w") {
2542 vals[prVarFuncs["w"]] = struct{}{}
2543 }
2544
2545 if strings.Contains(data, "f") {
2546 vals[prVarFuncs["f"]] = struct{}{}
2547 }
2548
2549 if strings.Contains(data, "t") {
2550 vals[prVarFuncs["t"]] = struct{}{}
2551 }
2552
2553 if first {
2554 results += "if "
2555 first = false
2556 } else {
2557 results += "else if "
2558 }
2559
2560 stmt := ""
2561
2562
2563
2564
2565
2566
2567 ors := strings.Split(data, "||")
2568
2569 for _, or := range ors {
2570
2571 stmt += "("
2572
2573 ands := strings.Split(strings.TrimSpace(or), "&&")
2574
2575 for _, and := range ands {
2576
2577 inArg := false
2578 pre := ""
2579 lft := ""
2580 preOperator := ""
2581 args := strings.Split(strings.TrimSpace(and), " ")
2582
2583 for _, a := range args {
2584
2585 if inArg {
2586
2587
2588 multiRange := strings.Count(a, "..") > 1
2589 cargs := strings.Split(strings.TrimSpace(a), ",")
2590 hasBracket := len(cargs) > 1
2591 bracketAdded := false
2592 lastWasRange := false
2593
2594 for _, carg := range cargs {
2595
2596 if rng := strings.Split(carg, ".."); len(rng) > 1 {
2597
2598 if multiRange {
2599 pre += " ("
2600 } else {
2601 pre += " "
2602 }
2603
2604 switch preOperator {
2605 case "==":
2606 pre += lft + " >= " + rng[0] + " && " + lft + "<=" + rng[1]
2607 case "!=":
2608 pre += "(" + lft + " < " + rng[0] + " || " + lft + " > " + rng[1] + ")"
2609 }
2610
2611 if multiRange {
2612 pre += ") || "
2613 } else {
2614 pre += " || "
2615 }
2616
2617 lastWasRange = true
2618 continue
2619 }
2620
2621 if lastWasRange {
2622 pre = strings.TrimRight(pre, " || ") + " && "
2623 }
2624
2625 lastWasRange = false
2626
2627 if hasBracket && !bracketAdded {
2628 pre += "("
2629 bracketAdded = true
2630 }
2631
2632
2633 switch preOperator {
2634 case "==":
2635 pre += " " + lft + preOperator + carg + " || "
2636 case "!=":
2637 pre += " " + lft + preOperator + carg + " && "
2638 }
2639
2640 }
2641
2642 pre = strings.TrimRight(pre, " || ")
2643 pre = strings.TrimRight(pre, " && ")
2644 pre = strings.TrimRight(pre, " || ")
2645
2646 if hasBracket && bracketAdded {
2647 pre += ")"
2648 }
2649
2650 continue
2651 }
2652
2653 if strings.Contains(a, "=") || a == ">" || a == "<" {
2654 inArg = true
2655 preOperator = a
2656 continue
2657 }
2658
2659 lft += a
2660 }
2661
2662 stmt += pre + " && "
2663 }
2664
2665 stmt = strings.TrimRight(stmt, " && ") + ") || "
2666 }
2667
2668 stmt = strings.TrimRight(stmt, " || ")
2669
2670 results += stmt
2671
2672 results += " {\n"
2673
2674
2675 results += "return locales." + ps1 + "\n"
2676
2677 results += "}"
2678 }
2679
2680 pre := "\n"
2681
2682
2683 vals[prVarFuncs["n"]] = struct{}{}
2684
2685 sorted := make([]sortRank, 0, len(vals))
2686
2687 for k := range vals {
2688 switch k[:1] {
2689 case "n":
2690 sorted = append(sorted, sortRank{
2691 Value: prVarFuncs["n"],
2692 Rank: 1,
2693 })
2694 case "i":
2695 sorted = append(sorted, sortRank{
2696 Value: prVarFuncs["i"],
2697 Rank: 2,
2698 })
2699 case "w":
2700 sorted = append(sorted, sortRank{
2701 Value: prVarFuncs["w"],
2702 Rank: 3,
2703 })
2704 case "f":
2705 sorted = append(sorted, sortRank{
2706 Value: prVarFuncs["f"],
2707 Rank: 4,
2708 })
2709 case "t":
2710 sorted = append(sorted, sortRank{
2711 Value: prVarFuncs["t"],
2712 Rank: 5,
2713 })
2714 }
2715 }
2716
2717 sort.Sort(ByRank(sorted))
2718
2719 for _, k := range sorted {
2720 pre += k.Value
2721 }
2722
2723 if len(results) == 0 {
2724 results = "return locales.PluralRuleUnknown"
2725 } else {
2726
2727 if !strings.HasPrefix(results, "return") {
2728
2729 results = manyToSingleVars(results)
2730
2731 results = pre + results
2732 }
2733 }
2734
2735 if len(pluralArr) == 0 {
2736 plurals = "nil"
2737 } else {
2738 plurals = fmt.Sprintf("%#v", pluralArr)
2739 }
2740
2741 return
2742 }
2743
2744 func manyToSingleVars(input string) (results string) {
2745
2746 matches := nModRegex.FindAllString(input, -1)
2747 mp := make(map[string][]string)
2748 var found bool
2749 var split []string
2750 var variable string
2751
2752 for _, formula := range matches {
2753
2754 if _, found = mp[formula]; found {
2755 continue
2756 }
2757
2758 split = strings.SplitN(formula, "%", 2)
2759
2760 mp[formula] = []string{split[1], "math.Mod(" + split[0] + ", " + split[1] + ")"}
2761 }
2762
2763 for k, v := range mp {
2764 variable = "nMod" + v[0]
2765 results += variable + " := " + v[1] + "\n"
2766 input = strings.Replace(input, k, variable, -1)
2767 }
2768
2769 matches = iModRegex.FindAllString(input, -1)
2770 mp = make(map[string][]string)
2771
2772 for _, formula := range matches {
2773
2774 if _, found = mp[formula]; found {
2775 continue
2776 }
2777
2778 split = strings.SplitN(formula, "%", 2)
2779
2780 mp[formula] = []string{split[1], formula}
2781 }
2782
2783 for k, v := range mp {
2784 variable = "iMod" + v[0]
2785 results += variable + " := " + v[1] + "\n"
2786 input = strings.Replace(input, k, variable, -1)
2787 }
2788
2789 matches = wModRegex.FindAllString(input, -1)
2790 mp = make(map[string][]string)
2791
2792 for _, formula := range matches {
2793
2794 if _, found = mp[formula]; found {
2795 continue
2796 }
2797
2798 split = strings.SplitN(formula, "%", 2)
2799
2800 mp[formula] = []string{split[1], formula}
2801 }
2802
2803 for k, v := range mp {
2804 variable = "wMod" + v[0]
2805 results += variable + " := " + v[1] + "\n"
2806 input = strings.Replace(input, k, variable, -1)
2807 }
2808
2809 matches = fModRegex.FindAllString(input, -1)
2810 mp = make(map[string][]string)
2811
2812 for _, formula := range matches {
2813
2814 if _, found = mp[formula]; found {
2815 continue
2816 }
2817
2818 split = strings.SplitN(formula, "%", 2)
2819
2820 mp[formula] = []string{split[1], formula}
2821 }
2822
2823 for k, v := range mp {
2824 variable = "fMod" + v[0]
2825 results += variable + " := " + v[1] + "\n"
2826 input = strings.Replace(input, k, variable, -1)
2827 }
2828
2829 matches = tModRegex.FindAllString(input, -1)
2830 mp = make(map[string][]string)
2831
2832 for _, formula := range matches {
2833
2834 if _, found = mp[formula]; found {
2835 continue
2836 }
2837
2838 split = strings.SplitN(formula, "%", 2)
2839
2840 mp[formula] = []string{split[1], formula}
2841 }
2842
2843 for k, v := range mp {
2844 variable = "tMod" + v[0]
2845 results += variable + " := " + v[1] + "\n"
2846 input = strings.Replace(input, k, variable, -1)
2847 }
2848
2849 results = results + "\n" + input
2850
2851 return
2852 }
2853
2854
2855 func pluralStringToInt(plural string) locales.PluralRule {
2856
2857 switch plural {
2858 case "zero":
2859 return locales.PluralRuleZero
2860 case "one":
2861 return locales.PluralRuleOne
2862 case "two":
2863 return locales.PluralRuleTwo
2864 case "few":
2865 return locales.PluralRuleFew
2866 case "many":
2867 return locales.PluralRuleMany
2868 case "other":
2869 return locales.PluralRuleOther
2870 default:
2871 return locales.PluralRuleUnknown
2872 }
2873 }
2874
2875 func pluralStringToString(pr string) string {
2876
2877 pr = strings.TrimSpace(pr)
2878
2879 switch pr {
2880 case "zero":
2881 return "PluralRuleZero"
2882 case "one":
2883 return "PluralRuleOne"
2884 case "two":
2885 return "PluralRuleTwo"
2886 case "few":
2887 return "PluralRuleFew"
2888 case "many":
2889 return "PluralRuleMany"
2890 case "other":
2891 return "PluralRuleOther"
2892 default:
2893 return "PluralRuleUnknown"
2894 }
2895 }
2896
View as plain text