1package saq 2 3import ( 4 "math" 5 "strconv" 6 "time" 7 8 "github.com/gohugoio/locales" 9 "github.com/gohugoio/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", "MRU", "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", "UYW", "UZS", "VEB", "VEF", "VES", "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{"ACDT": "ACDT", "ACST": "ACST", "ACWDT": "ACWDT", "ACWST": "ACWST", "ADT": "ADT", "AEDT": "AEDT", "AEST": "AEST", "AKDT": "AKDT", "AKST": "AKST", "ARST": "ARST", "ART": "ART", "AST": "AST", "AWDT": "AWDT", "AWST": "AWST", "BOT": "BOT", "BT": "BT", "CAT": "CAT", "CDT": "CDT", "CHADT": "CHADT", "CHAST": "CHAST", "CLST": "CLST", "CLT": "CLT", "COST": "COST", "COT": "COT", "CST": "CST", "ChST": "ChST", "EAT": "EAT", "ECT": "ECT", "EDT": "EDT", "EST": "EST", "GFT": "GFT", "GMT": "GMT", "GST": "GST", "GYT": "GYT", "HADT": "HADT", "HAST": "HAST", "HAT": "HAT", "HECU": "HECU", "HEEG": "HEEG", "HENOMX": "HENOMX", "HEOG": "HEOG", "HEPM": "HEPM", "HEPMX": "HEPMX", "HKST": "HKST", "HKT": "HKT", "HNCU": "HNCU", "HNEG": "HNEG", "HNNOMX": "HNNOMX", "HNOG": "HNOG", "HNPM": "HNPM", "HNPMX": "HNPMX", "HNT": "HNT", "IST": "IST", "JDT": "JDT", "JST": "JST", "LHDT": "LHDT", "LHST": "LHST", "MDT": "MDT", "MESZ": "MESZ", "MEZ": "MEZ", "MST": "MST", "MYT": "MYT", "NZDT": "NZDT", "NZST": "NZST", "OESZ": "OESZ", "OEZ": "OEZ", "PDT": "PDT", "PST": "PST", "SAST": "SAST", "SGT": "SGT", "SRT": "SRT", "TMST": "TMST", "TMT": "TMT", "UYST": "UYST", "UYT": "UYT", "VET": "VET", "WARST": "WARST", "WART": "WART", "WAST": "WAST", "WAT": "WAT", "WESZ": "WESZ", "WEZ": "WEZ", "WIB": "WIB", "WIT": "WIT", "WITA": "WITA", "∅∅∅": "∅∅∅"}, 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