1package saq
2
3import (
4	"math"
5	"strconv"
6	"time"
7
8	"github.com/go-playground/locales"
9	"github.com/go-playground/locales/currency"
10)
11
12type saq struct {
13	locale                 string
14	pluralsCardinal        []locales.PluralRule
15	pluralsOrdinal         []locales.PluralRule
16	pluralsRange           []locales.PluralRule
17	decimal                string
18	group                  string
19	minus                  string
20	percent                string
21	perMille               string
22	timeSeparator          string
23	inifinity              string
24	currencies             []string // idx = enum of currency code
25	currencyNegativePrefix string
26	currencyNegativeSuffix string
27	monthsAbbreviated      []string
28	monthsNarrow           []string
29	monthsWide             []string
30	daysAbbreviated        []string
31	daysNarrow             []string
32	daysShort              []string
33	daysWide               []string
34	periodsAbbreviated     []string
35	periodsNarrow          []string
36	periodsShort           []string
37	periodsWide            []string
38	erasAbbreviated        []string
39	erasNarrow             []string
40	erasWide               []string
41	timezones              map[string]string
42}
43
44// New returns a new instance of translator for the 'saq' locale
45func New() locales.Translator {
46	return &saq{
47		locale:                 "saq",
48		pluralsCardinal:        []locales.PluralRule{2, 6},
49		pluralsOrdinal:         nil,
50		pluralsRange:           nil,
51		timeSeparator:          ":",
52		currencies:             []string{"ADP", "AED", "AFA", "AFN", "ALK", "ALL", "AMD", "ANG", "AOA", "AOK", "AON", "AOR", "ARA", "ARL", "ARM", "ARP", "ARS", "ATS", "AUD", "AWG", "AZM", "AZN", "BAD", "BAM", "BAN", "BBD", "BDT", "BEC", "BEF", "BEL", "BGL", "BGM", "BGN", "BGO", "BHD", "BIF", "BMD", "BND", "BOB", "BOL", "BOP", "BOV", "BRB", "BRC", "BRE", "BRL", "BRN", "BRR", "BRZ", "BSD", "BTN", "BUK", "BWP", "BYB", "BYN", "BYR", "BZD", "CAD", "CDF", "CHE", "CHF", "CHW", "CLE", "CLF", "CLP", "CNH", "CNX", "CNY", "COP", "COU", "CRC", "CSD", "CSK", "CUC", "CUP", "CVE", "CYP", "CZK", "DDM", "DEM", "DJF", "DKK", "DOP", "DZD", "ECS", "ECV", "EEK", "EGP", "ERN", "ESA", "ESB", "ESP", "ETB", "EUR", "FIM", "FJD", "FKP", "FRF", "GBP", "GEK", "GEL", "GHC", "GHS", "GIP", "GMD", "GNF", "GNS", "GQE", "GRD", "GTQ", "GWE", "GWP", "GYD", "HKD", "HNL", "HRD", "HRK", "HTG", "HUF", "IDR", "IEP", "ILP", "ILR", "ILS", "INR", "IQD", "IRR", "ISJ", "ISK", "ITL", "JMD", "JOD", "JPY", "Ksh", "KGS", "KHR", "KMF", "KPW", "KRH", "KRO", "KRW", "KWD", "KYD", "KZT", "LAK", "LBP", "LKR", "LRD", "LSL", "LTL", "LTT", "LUC", "LUF", "LUL", "LVL", "LVR", "LYD", "MAD", "MAF", "MCF", "MDC", "MDL", "MGA", "MGF", "MKD", "MKN", "MLF", "MMK", "MNT", "MOP", "MRO", "MTL", "MTP", "MUR", "MVP", "MVR", "MWK", "MXN", "MXP", "MXV", "MYR", "MZE", "MZM", "MZN", "NAD", "NGN", "NIC", "NIO", "NLG", "NOK", "NPR", "NZD", "OMR", "PAB", "PEI", "PEN", "PES", "PGK", "PHP", "PKR", "PLN", "PLZ", "PTE", "PYG", "QAR", "RHD", "ROL", "RON", "RSD", "RUB", "RUR", "RWF", "SAR", "SBD", "SCR", "SDD", "SDG", "SDP", "SEK", "SGD", "SHP", "SIT", "SKK", "SLL", "SOS", "SRD", "SRG", "SSP", "STD", "STN", "SUR", "SVC", "SYP", "SZL", "THB", "TJR", "TJS", "TMM", "TMT", "TND", "TOP", "TPE", "TRL", "TRY", "TTD", "TWD", "TZS", "UAH", "UAK", "UGS", "UGX", "USD", "USN", "USS", "UYI", "UYP", "UYU", "UZS", "VEB", "VEF", "VND", "VNN", "VUV", "WST", "XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XEU", "XFO", "XFU", "XOF", "XPD", "XPF", "XPT", "XRE", "XSU", "XTS", "XUA", "XXX", "YDD", "YER", "YUD", "YUM", "YUN", "YUR", "ZAL", "ZAR", "ZMK", "ZMW", "ZRN", "ZRZ", "ZWD", "ZWL", "ZWR"},
53		currencyNegativePrefix: "(",
54		currencyNegativeSuffix: ")",
55		monthsAbbreviated:      []string{"", "Obo", "Waa", "Oku", "Ong", "Ime", "Ile", "Sap", "Isi", "Saa", "Tom", "Tob", "Tow"},
56		monthsNarrow:           []string{"", "O", "W", "O", "O", "I", "I", "S", "I", "S", "T", "T", "T"},
57		monthsWide:             []string{"", "Lapa le obo", "Lapa le waare", "Lapa le okuni", "Lapa le ong’wan", "Lapa le imet", "Lapa le ile", "Lapa le sapa", "Lapa le isiet", "Lapa le saal", "Lapa le tomon", "Lapa le tomon obo", "Lapa le tomon waare"},
58		daysAbbreviated:        []string{"Are", "Kun", "Ong", "Ine", "Ile", "Sap", "Kwe"},
59		daysNarrow:             []string{"A", "K", "O", "I", "I", "S", "K"},
60		daysWide:               []string{"Mderot ee are", "Mderot ee kuni", "Mderot ee ong’wan", "Mderot ee inet", "Mderot ee ile", "Mderot ee sapa", "Mderot ee kwe"},
61		periodsAbbreviated:     []string{"Tesiran", "Teipa"},
62		periodsWide:            []string{"Tesiran", "Teipa"},
63		erasAbbreviated:        []string{"KK", "BK"},
64		erasNarrow:             []string{"", ""},
65		erasWide:               []string{"Kabla ya Christo", "Baada ya Christo"},
66		timezones:              map[string]string{"ECT": "ECT", "ACWDT": "ACWDT", "HNEG": "HNEG", "LHDT": "LHDT", "TMT": "TMT", "HADT": "HADT", "∅∅∅": "∅∅∅", "WEZ": "WEZ", "JDT": "JDT", "AKDT": "AKDT", "OEZ": "OEZ", "HNCU": "HNCU", "HEPMX": "HEPMX", "MST": "MST", "TMST": "TMST", "UYT": "UYT", "ChST": "ChST", "CDT": "CDT", "AKST": "AKST", "ACWST": "ACWST", "WITA": "WITA", "CHADT": "CHADT", "HECU": "HECU", "AWST": "AWST", "SAST": "SAST", "WIB": "WIB", "BOT": "BOT", "HNOG": "HNOG", "HNPM": "HNPM", "OESZ": "OESZ", "CHAST": "CHAST", "WESZ": "WESZ", "MYT": "MYT", "EAT": "EAT", "AST": "AST", "HEEG": "HEEG", "HNNOMX": "HNNOMX", "CAT": "CAT", "GYT": "GYT", "MEZ": "MEZ", "MESZ": "MESZ", "HKST": "HKST", "IST": "IST", "COST": "COST", "AEST": "AEST", "EST": "EST", "HENOMX": "HENOMX", "CLST": "CLST", "WAST": "WAST", "PST": "PST", "AWDT": "AWDT", "AEDT": "AEDT", "WARST": "WARST", "CLT": "CLT", "CST": "CST", "HNPMX": "HNPMX", "ADT": "ADT", "MDT": "MDT", "NZDT": "NZDT", "ART": "ART", "GMT": "GMT", "UYST": "UYST", "PDT": "PDT", "EDT": "EDT", "ACST": "ACST", "LHST": "LHST", "HNT": "HNT", "SRT": "SRT", "JST": "JST", "SGT": "SGT", "ACDT": "ACDT", "WART": "WART", "HAT": "HAT", "WIT": "WIT", "ARST": "ARST", "WAT": "WAT", "BT": "BT", "HEPM": "HEPM", "HAST": "HAST", "NZST": "NZST", "GFT": "GFT", "HEOG": "HEOG", "HKT": "HKT", "VET": "VET", "COT": "COT"},
67	}
68}
69
70// Locale returns the current translators string locale
71func (saq *saq) Locale() string {
72	return saq.locale
73}
74
75// PluralsCardinal returns the list of cardinal plural rules associated with 'saq'
76func (saq *saq) PluralsCardinal() []locales.PluralRule {
77	return saq.pluralsCardinal
78}
79
80// PluralsOrdinal returns the list of ordinal plural rules associated with 'saq'
81func (saq *saq) PluralsOrdinal() []locales.PluralRule {
82	return saq.pluralsOrdinal
83}
84
85// PluralsRange returns the list of range plural rules associated with 'saq'
86func (saq *saq) PluralsRange() []locales.PluralRule {
87	return saq.pluralsRange
88}
89
90// CardinalPluralRule returns the cardinal PluralRule given 'num' and digits/precision of 'v' for 'saq'
91func (saq *saq) CardinalPluralRule(num float64, v uint64) locales.PluralRule {
92
93	n := math.Abs(num)
94
95	if n == 1 {
96		return locales.PluralRuleOne
97	}
98
99	return locales.PluralRuleOther
100}
101
102// OrdinalPluralRule returns the ordinal PluralRule given 'num' and digits/precision of 'v' for 'saq'
103func (saq *saq) OrdinalPluralRule(num float64, v uint64) locales.PluralRule {
104	return locales.PluralRuleUnknown
105}
106
107// RangePluralRule returns the ordinal PluralRule given 'num1', 'num2' and digits/precision of 'v1' and 'v2' for 'saq'
108func (saq *saq) RangePluralRule(num1 float64, v1 uint64, num2 float64, v2 uint64) locales.PluralRule {
109	return locales.PluralRuleUnknown
110}
111
112// MonthAbbreviated returns the locales abbreviated month given the 'month' provided
113func (saq *saq) MonthAbbreviated(month time.Month) string {
114	return saq.monthsAbbreviated[month]
115}
116
117// MonthsAbbreviated returns the locales abbreviated months
118func (saq *saq) MonthsAbbreviated() []string {
119	return saq.monthsAbbreviated[1:]
120}
121
122// MonthNarrow returns the locales narrow month given the 'month' provided
123func (saq *saq) MonthNarrow(month time.Month) string {
124	return saq.monthsNarrow[month]
125}
126
127// MonthsNarrow returns the locales narrow months
128func (saq *saq) MonthsNarrow() []string {
129	return saq.monthsNarrow[1:]
130}
131
132// MonthWide returns the locales wide month given the 'month' provided
133func (saq *saq) MonthWide(month time.Month) string {
134	return saq.monthsWide[month]
135}
136
137// MonthsWide returns the locales wide months
138func (saq *saq) MonthsWide() []string {
139	return saq.monthsWide[1:]
140}
141
142// WeekdayAbbreviated returns the locales abbreviated weekday given the 'weekday' provided
143func (saq *saq) WeekdayAbbreviated(weekday time.Weekday) string {
144	return saq.daysAbbreviated[weekday]
145}
146
147// WeekdaysAbbreviated returns the locales abbreviated weekdays
148func (saq *saq) WeekdaysAbbreviated() []string {
149	return saq.daysAbbreviated
150}
151
152// WeekdayNarrow returns the locales narrow weekday given the 'weekday' provided
153func (saq *saq) WeekdayNarrow(weekday time.Weekday) string {
154	return saq.daysNarrow[weekday]
155}
156
157// WeekdaysNarrow returns the locales narrow weekdays
158func (saq *saq) WeekdaysNarrow() []string {
159	return saq.daysNarrow
160}
161
162// WeekdayShort returns the locales short weekday given the 'weekday' provided
163func (saq *saq) WeekdayShort(weekday time.Weekday) string {
164	return saq.daysShort[weekday]
165}
166
167// WeekdaysShort returns the locales short weekdays
168func (saq *saq) WeekdaysShort() []string {
169	return saq.daysShort
170}
171
172// WeekdayWide returns the locales wide weekday given the 'weekday' provided
173func (saq *saq) WeekdayWide(weekday time.Weekday) string {
174	return saq.daysWide[weekday]
175}
176
177// WeekdaysWide returns the locales wide weekdays
178func (saq *saq) WeekdaysWide() []string {
179	return saq.daysWide
180}
181
182// Decimal returns the decimal point of number
183func (saq *saq) Decimal() string {
184	return saq.decimal
185}
186
187// Group returns the group of number
188func (saq *saq) Group() string {
189	return saq.group
190}
191
192// Group returns the minus sign of number
193func (saq *saq) Minus() string {
194	return saq.minus
195}
196
197// FmtNumber returns 'num' with digits/precision of 'v' for 'saq' and handles both Whole and Real numbers based on 'v'
198func (saq *saq) FmtNumber(num float64, v uint64) string {
199
200	return strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
201}
202
203// FmtPercent returns 'num' with digits/precision of 'v' for 'saq' and handles both Whole and Real numbers based on 'v'
204// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
205func (saq *saq) FmtPercent(num float64, v uint64) string {
206	return strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
207}
208
209// FmtCurrency returns the currency representation of 'num' with digits/precision of 'v' for 'saq'
210func (saq *saq) FmtCurrency(num float64, v uint64, currency currency.Type) string {
211
212	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
213	symbol := saq.currencies[currency]
214	l := len(s) + len(symbol) + 0
215	count := 0
216	inWhole := v == 0
217	b := make([]byte, 0, l)
218
219	for i := len(s) - 1; i >= 0; i-- {
220
221		if s[i] == '.' {
222			b = append(b, saq.decimal[0])
223			inWhole = true
224			continue
225		}
226
227		if inWhole {
228			if count == 3 {
229				b = append(b, saq.group[0])
230				count = 1
231			} else {
232				count++
233			}
234		}
235
236		b = append(b, s[i])
237	}
238
239	for j := len(symbol) - 1; j >= 0; j-- {
240		b = append(b, symbol[j])
241	}
242
243	if num < 0 {
244		b = append(b, saq.minus[0])
245	}
246
247	// reverse
248	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
249		b[i], b[j] = b[j], b[i]
250	}
251
252	if int(v) < 2 {
253
254		if v == 0 {
255			b = append(b, saq.decimal...)
256		}
257
258		for i := 0; i < 2-int(v); i++ {
259			b = append(b, '0')
260		}
261	}
262
263	return string(b)
264}
265
266// FmtAccounting returns the currency representation of 'num' with digits/precision of 'v' for 'saq'
267// in accounting notation.
268func (saq *saq) FmtAccounting(num float64, v uint64, currency currency.Type) string {
269
270	s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64)
271	symbol := saq.currencies[currency]
272	l := len(s) + len(symbol) + 2
273	count := 0
274	inWhole := v == 0
275	b := make([]byte, 0, l)
276
277	for i := len(s) - 1; i >= 0; i-- {
278
279		if s[i] == '.' {
280			b = append(b, saq.decimal[0])
281			inWhole = true
282			continue
283		}
284
285		if inWhole {
286			if count == 3 {
287				b = append(b, saq.group[0])
288				count = 1
289			} else {
290				count++
291			}
292		}
293
294		b = append(b, s[i])
295	}
296
297	if num < 0 {
298
299		for j := len(symbol) - 1; j >= 0; j-- {
300			b = append(b, symbol[j])
301		}
302
303		b = append(b, saq.currencyNegativePrefix[0])
304
305	} else {
306
307		for j := len(symbol) - 1; j >= 0; j-- {
308			b = append(b, symbol[j])
309		}
310
311	}
312
313	// reverse
314	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
315		b[i], b[j] = b[j], b[i]
316	}
317
318	if int(v) < 2 {
319
320		if v == 0 {
321			b = append(b, saq.decimal...)
322		}
323
324		for i := 0; i < 2-int(v); i++ {
325			b = append(b, '0')
326		}
327	}
328
329	if num < 0 {
330		b = append(b, saq.currencyNegativeSuffix...)
331	}
332
333	return string(b)
334}
335
336// FmtDateShort returns the short date representation of 't' for 'saq'
337func (saq *saq) FmtDateShort(t time.Time) string {
338
339	b := make([]byte, 0, 32)
340
341	if t.Day() < 10 {
342		b = append(b, '0')
343	}
344
345	b = strconv.AppendInt(b, int64(t.Day()), 10)
346	b = append(b, []byte{0x2f}...)
347
348	if t.Month() < 10 {
349		b = append(b, '0')
350	}
351
352	b = strconv.AppendInt(b, int64(t.Month()), 10)
353
354	b = append(b, []byte{0x2f}...)
355
356	if t.Year() > 0 {
357		b = strconv.AppendInt(b, int64(t.Year()), 10)
358	} else {
359		b = strconv.AppendInt(b, int64(-t.Year()), 10)
360	}
361
362	return string(b)
363}
364
365// FmtDateMedium returns the medium date representation of 't' for 'saq'
366func (saq *saq) FmtDateMedium(t time.Time) string {
367
368	b := make([]byte, 0, 32)
369
370	b = strconv.AppendInt(b, int64(t.Day()), 10)
371	b = append(b, []byte{0x20}...)
372	b = append(b, saq.monthsAbbreviated[t.Month()]...)
373	b = append(b, []byte{0x20}...)
374
375	if t.Year() > 0 {
376		b = strconv.AppendInt(b, int64(t.Year()), 10)
377	} else {
378		b = strconv.AppendInt(b, int64(-t.Year()), 10)
379	}
380
381	return string(b)
382}
383
384// FmtDateLong returns the long date representation of 't' for 'saq'
385func (saq *saq) FmtDateLong(t time.Time) string {
386
387	b := make([]byte, 0, 32)
388
389	b = strconv.AppendInt(b, int64(t.Day()), 10)
390	b = append(b, []byte{0x20}...)
391	b = append(b, saq.monthsWide[t.Month()]...)
392	b = append(b, []byte{0x20}...)
393
394	if t.Year() > 0 {
395		b = strconv.AppendInt(b, int64(t.Year()), 10)
396	} else {
397		b = strconv.AppendInt(b, int64(-t.Year()), 10)
398	}
399
400	return string(b)
401}
402
403// FmtDateFull returns the full date representation of 't' for 'saq'
404func (saq *saq) FmtDateFull(t time.Time) string {
405
406	b := make([]byte, 0, 32)
407
408	b = append(b, saq.daysWide[t.Weekday()]...)
409	b = append(b, []byte{0x2c, 0x20}...)
410	b = strconv.AppendInt(b, int64(t.Day()), 10)
411	b = append(b, []byte{0x20}...)
412	b = append(b, saq.monthsWide[t.Month()]...)
413	b = append(b, []byte{0x20}...)
414
415	if t.Year() > 0 {
416		b = strconv.AppendInt(b, int64(t.Year()), 10)
417	} else {
418		b = strconv.AppendInt(b, int64(-t.Year()), 10)
419	}
420
421	return string(b)
422}
423
424// FmtTimeShort returns the short time representation of 't' for 'saq'
425func (saq *saq) FmtTimeShort(t time.Time) string {
426
427	b := make([]byte, 0, 32)
428
429	if t.Hour() < 10 {
430		b = append(b, '0')
431	}
432
433	b = strconv.AppendInt(b, int64(t.Hour()), 10)
434	b = append(b, saq.timeSeparator...)
435
436	if t.Minute() < 10 {
437		b = append(b, '0')
438	}
439
440	b = strconv.AppendInt(b, int64(t.Minute()), 10)
441
442	return string(b)
443}
444
445// FmtTimeMedium returns the medium time representation of 't' for 'saq'
446func (saq *saq) FmtTimeMedium(t time.Time) string {
447
448	b := make([]byte, 0, 32)
449
450	if t.Hour() < 10 {
451		b = append(b, '0')
452	}
453
454	b = strconv.AppendInt(b, int64(t.Hour()), 10)
455	b = append(b, saq.timeSeparator...)
456
457	if t.Minute() < 10 {
458		b = append(b, '0')
459	}
460
461	b = strconv.AppendInt(b, int64(t.Minute()), 10)
462	b = append(b, saq.timeSeparator...)
463
464	if t.Second() < 10 {
465		b = append(b, '0')
466	}
467
468	b = strconv.AppendInt(b, int64(t.Second()), 10)
469
470	return string(b)
471}
472
473// FmtTimeLong returns the long time representation of 't' for 'saq'
474func (saq *saq) FmtTimeLong(t time.Time) string {
475
476	b := make([]byte, 0, 32)
477
478	if t.Hour() < 10 {
479		b = append(b, '0')
480	}
481
482	b = strconv.AppendInt(b, int64(t.Hour()), 10)
483	b = append(b, saq.timeSeparator...)
484
485	if t.Minute() < 10 {
486		b = append(b, '0')
487	}
488
489	b = strconv.AppendInt(b, int64(t.Minute()), 10)
490	b = append(b, saq.timeSeparator...)
491
492	if t.Second() < 10 {
493		b = append(b, '0')
494	}
495
496	b = strconv.AppendInt(b, int64(t.Second()), 10)
497	b = append(b, []byte{0x20}...)
498
499	tz, _ := t.Zone()
500	b = append(b, tz...)
501
502	return string(b)
503}
504
505// FmtTimeFull returns the full time representation of 't' for 'saq'
506func (saq *saq) FmtTimeFull(t time.Time) string {
507
508	b := make([]byte, 0, 32)
509
510	if t.Hour() < 10 {
511		b = append(b, '0')
512	}
513
514	b = strconv.AppendInt(b, int64(t.Hour()), 10)
515	b = append(b, saq.timeSeparator...)
516
517	if t.Minute() < 10 {
518		b = append(b, '0')
519	}
520
521	b = strconv.AppendInt(b, int64(t.Minute()), 10)
522	b = append(b, saq.timeSeparator...)
523
524	if t.Second() < 10 {
525		b = append(b, '0')
526	}
527
528	b = strconv.AppendInt(b, int64(t.Second()), 10)
529	b = append(b, []byte{0x20}...)
530
531	tz, _ := t.Zone()
532
533	if btz, ok := saq.timezones[tz]; ok {
534		b = append(b, btz...)
535	} else {
536		b = append(b, tz...)
537	}
538
539	return string(b)
540}
541