1package nnh 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 nnh 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 currencyPositivePrefix string 26 currencyNegativePrefix 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 'nnh' locale 45func New() locales.Translator { 46 return &nnh{ 47 locale: "nnh", 48 pluralsCardinal: []locales.PluralRule{2, 6}, 49 pluralsOrdinal: nil, 50 pluralsRange: nil, 51 decimal: ",", 52 group: ".", 53 percent: "%", 54 timeSeparator: ":", 55 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", "KES", "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", "FCFA", "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"}, 56 currencyPositivePrefix: " ", 57 currencyNegativePrefix: " ", 58 monthsAbbreviated: []string{"", "saŋ tsetsɛ̀ɛ lùm", "saŋ kàg ngwóŋ", "saŋ lepyè shúm", "saŋ cÿó", "saŋ tsɛ̀ɛ cÿó", "saŋ njÿoláʼ", "saŋ tyɛ̀b tyɛ̀b mbʉ̀ŋ", "saŋ mbʉ̀ŋ", "saŋ ngwɔ̀ʼ mbÿɛ", "saŋ tàŋa tsetsáʼ", "saŋ mejwoŋó", "saŋ lùm"}, 59 monthsWide: []string{"", "saŋ tsetsɛ̀ɛ lùm", "saŋ kàg ngwóŋ", "saŋ lepyè shúm", "saŋ cÿó", "saŋ tsɛ̀ɛ cÿó", "saŋ njÿoláʼ", "saŋ tyɛ̀b tyɛ̀b mbʉ̀ŋ", "saŋ mbʉ̀ŋ", "saŋ ngwɔ̀ʼ mbÿɛ", "saŋ tàŋa tsetsáʼ", "saŋ mejwoŋó", "saŋ lùm"}, 60 daysAbbreviated: []string{"lyɛʼɛ́ sẅíŋtè", "mvfò lyɛ̌ʼ", "mbɔ́ɔntè mvfò lyɛ̌ʼ", "tsètsɛ̀ɛ lyɛ̌ʼ", "mbɔ́ɔntè tsetsɛ̀ɛ lyɛ̌ʼ", "mvfò màga lyɛ̌ʼ", "màga lyɛ̌ʼ"}, 61 daysShort: []string{"lyɛʼɛ́ sẅíŋtè", "mvfò lyɛ̌ʼ", "mbɔ́ɔntè mvfò lyɛ̌ʼ", "tsètsɛ̀ɛ lyɛ̌ʼ", "mbɔ́ɔntè tsetsɛ̀ɛ lyɛ̌ʼ", "mvfò màga lyɛ̌ʼ", "màga lyɛ̌ʼ"}, 62 daysWide: []string{"lyɛʼɛ́ sẅíŋtè", "mvfò lyɛ̌ʼ", "mbɔ́ɔntè mvfò lyɛ̌ʼ", "tsètsɛ̀ɛ lyɛ̌ʼ", "mbɔ́ɔntè tsetsɛ̀ɛ lyɛ̌ʼ", "mvfò màga lyɛ̌ʼ", "màga lyɛ̌ʼ"}, 63 periodsAbbreviated: []string{"mbaʼámbaʼ", "ncwònzém"}, 64 periodsWide: []string{"mbaʼámbaʼ", "ncwònzém"}, 65 erasAbbreviated: []string{"m.z.Y.", "m.g.n.Y."}, 66 erasNarrow: []string{"", ""}, 67 erasWide: []string{"mé zyé Yěsô", "mé gÿo ńzyé Yěsô"}, 68 timezones: map[string]string{"CHADT": "CHADT", "AEDT": "AEDT", "WAT": "WAT", "TMT": "TMT", "∅∅∅": "∅∅∅", "WARST": "WARST", "HNNOMX": "HNNOMX", "CLT": "CLT", "HAST": "HAST", "CHAST": "CHAST", "MESZ": "MESZ", "LHST": "LHST", "ART": "ART", "PST": "PST", "MEZ": "MEZ", "TMST": "TMST", "HNCU": "HNCU", "CST": "CST", "AWST": "AWST", "AEST": "AEST", "ECT": "ECT", "HADT": "HADT", "ADT": "ADT", "WESZ": "WESZ", "NZST": "NZST", "HEEG": "HEEG", "ACWDT": "ACWDT", "HENOMX": "HENOMX", "ARST": "ARST", "JST": "JST", "EDT": "EDT", "HNEG": "HNEG", "HNOG": "HNOG", "HNT": "HNT", "VET": "VET", "HNPM": "HNPM", "WITA": "WITA", "SRT": "SRT", "AKDT": "AKDT", "MYT": "MYT", "UYST": "UYST", "WIT": "WIT", "CDT": "CDT", "BOT": "BOT", "MDT": "MDT", "OESZ": "OESZ", "ChST": "ChST", "HNPMX": "HNPMX", "JDT": "JDT", "BT": "BT", "CAT": "CAT", "LHDT": "LHDT", "WART": "WART", "CLST": "CLST", "COST": "COST", "GYT": "GYT", "HECU": "HECU", "SGT": "SGT", "IST": "IST", "EAT": "EAT", "AWDT": "AWDT", "AST": "AST", "WEZ": "WEZ", "ACDT": "ACDT", "OEZ": "OEZ", "GMT": "GMT", "AKST": "AKST", "COT": "COT", "NZDT": "NZDT", "HKT": "HKT", "ACWST": "ACWST", "HKST": "HKST", "HEPM": "HEPM", "PDT": "PDT", "HEPMX": "HEPMX", "ACST": "ACST", "HEOG": "HEOG", "HAT": "HAT", "UYT": "UYT", "SAST": "SAST", "GFT": "GFT", "EST": "EST", "WAST": "WAST", "WIB": "WIB", "MST": "MST"}, 69 } 70} 71 72// Locale returns the current translators string locale 73func (nnh *nnh) Locale() string { 74 return nnh.locale 75} 76 77// PluralsCardinal returns the list of cardinal plural rules associated with 'nnh' 78func (nnh *nnh) PluralsCardinal() []locales.PluralRule { 79 return nnh.pluralsCardinal 80} 81 82// PluralsOrdinal returns the list of ordinal plural rules associated with 'nnh' 83func (nnh *nnh) PluralsOrdinal() []locales.PluralRule { 84 return nnh.pluralsOrdinal 85} 86 87// PluralsRange returns the list of range plural rules associated with 'nnh' 88func (nnh *nnh) PluralsRange() []locales.PluralRule { 89 return nnh.pluralsRange 90} 91 92// CardinalPluralRule returns the cardinal PluralRule given 'num' and digits/precision of 'v' for 'nnh' 93func (nnh *nnh) CardinalPluralRule(num float64, v uint64) locales.PluralRule { 94 95 n := math.Abs(num) 96 97 if n == 1 { 98 return locales.PluralRuleOne 99 } 100 101 return locales.PluralRuleOther 102} 103 104// OrdinalPluralRule returns the ordinal PluralRule given 'num' and digits/precision of 'v' for 'nnh' 105func (nnh *nnh) OrdinalPluralRule(num float64, v uint64) locales.PluralRule { 106 return locales.PluralRuleUnknown 107} 108 109// RangePluralRule returns the ordinal PluralRule given 'num1', 'num2' and digits/precision of 'v1' and 'v2' for 'nnh' 110func (nnh *nnh) RangePluralRule(num1 float64, v1 uint64, num2 float64, v2 uint64) locales.PluralRule { 111 return locales.PluralRuleUnknown 112} 113 114// MonthAbbreviated returns the locales abbreviated month given the 'month' provided 115func (nnh *nnh) MonthAbbreviated(month time.Month) string { 116 return nnh.monthsAbbreviated[month] 117} 118 119// MonthsAbbreviated returns the locales abbreviated months 120func (nnh *nnh) MonthsAbbreviated() []string { 121 return nnh.monthsAbbreviated[1:] 122} 123 124// MonthNarrow returns the locales narrow month given the 'month' provided 125func (nnh *nnh) MonthNarrow(month time.Month) string { 126 return nnh.monthsNarrow[month] 127} 128 129// MonthsNarrow returns the locales narrow months 130func (nnh *nnh) MonthsNarrow() []string { 131 return nil 132} 133 134// MonthWide returns the locales wide month given the 'month' provided 135func (nnh *nnh) MonthWide(month time.Month) string { 136 return nnh.monthsWide[month] 137} 138 139// MonthsWide returns the locales wide months 140func (nnh *nnh) MonthsWide() []string { 141 return nnh.monthsWide[1:] 142} 143 144// WeekdayAbbreviated returns the locales abbreviated weekday given the 'weekday' provided 145func (nnh *nnh) WeekdayAbbreviated(weekday time.Weekday) string { 146 return nnh.daysAbbreviated[weekday] 147} 148 149// WeekdaysAbbreviated returns the locales abbreviated weekdays 150func (nnh *nnh) WeekdaysAbbreviated() []string { 151 return nnh.daysAbbreviated 152} 153 154// WeekdayNarrow returns the locales narrow weekday given the 'weekday' provided 155func (nnh *nnh) WeekdayNarrow(weekday time.Weekday) string { 156 return nnh.daysNarrow[weekday] 157} 158 159// WeekdaysNarrow returns the locales narrow weekdays 160func (nnh *nnh) WeekdaysNarrow() []string { 161 return nnh.daysNarrow 162} 163 164// WeekdayShort returns the locales short weekday given the 'weekday' provided 165func (nnh *nnh) WeekdayShort(weekday time.Weekday) string { 166 return nnh.daysShort[weekday] 167} 168 169// WeekdaysShort returns the locales short weekdays 170func (nnh *nnh) WeekdaysShort() []string { 171 return nnh.daysShort 172} 173 174// WeekdayWide returns the locales wide weekday given the 'weekday' provided 175func (nnh *nnh) WeekdayWide(weekday time.Weekday) string { 176 return nnh.daysWide[weekday] 177} 178 179// WeekdaysWide returns the locales wide weekdays 180func (nnh *nnh) WeekdaysWide() []string { 181 return nnh.daysWide 182} 183 184// Decimal returns the decimal point of number 185func (nnh *nnh) Decimal() string { 186 return nnh.decimal 187} 188 189// Group returns the group of number 190func (nnh *nnh) Group() string { 191 return nnh.group 192} 193 194// Group returns the minus sign of number 195func (nnh *nnh) Minus() string { 196 return nnh.minus 197} 198 199// FmtNumber returns 'num' with digits/precision of 'v' for 'nnh' and handles both Whole and Real numbers based on 'v' 200func (nnh *nnh) FmtNumber(num float64, v uint64) string { 201 202 s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64) 203 l := len(s) + 1 + 1*len(s[:len(s)-int(v)-1])/3 204 count := 0 205 inWhole := v == 0 206 b := make([]byte, 0, l) 207 208 for i := len(s) - 1; i >= 0; i-- { 209 210 if s[i] == '.' { 211 b = append(b, nnh.decimal[0]) 212 inWhole = true 213 continue 214 } 215 216 if inWhole { 217 if count == 3 { 218 b = append(b, nnh.group[0]) 219 count = 1 220 } else { 221 count++ 222 } 223 } 224 225 b = append(b, s[i]) 226 } 227 228 if num < 0 { 229 b = append(b, nnh.minus[0]) 230 } 231 232 // reverse 233 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 { 234 b[i], b[j] = b[j], b[i] 235 } 236 237 return string(b) 238} 239 240// FmtPercent returns 'num' with digits/precision of 'v' for 'nnh' and handles both Whole and Real numbers based on 'v' 241// NOTE: 'num' passed into FmtPercent is assumed to be in percent already 242func (nnh *nnh) FmtPercent(num float64, v uint64) string { 243 return strconv.FormatFloat(math.Abs(num), 'f', int(v), 64) 244} 245 246// FmtCurrency returns the currency representation of 'num' with digits/precision of 'v' for 'nnh' 247func (nnh *nnh) FmtCurrency(num float64, v uint64, currency currency.Type) string { 248 249 s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64) 250 symbol := nnh.currencies[currency] 251 l := len(s) + len(symbol) + 3 + 1*len(s[:len(s)-int(v)-1])/3 252 count := 0 253 inWhole := v == 0 254 b := make([]byte, 0, l) 255 256 for i := len(s) - 1; i >= 0; i-- { 257 258 if s[i] == '.' { 259 b = append(b, nnh.decimal[0]) 260 inWhole = true 261 continue 262 } 263 264 if inWhole { 265 if count == 3 { 266 b = append(b, nnh.group[0]) 267 count = 1 268 } else { 269 count++ 270 } 271 } 272 273 b = append(b, s[i]) 274 } 275 276 for j := len(symbol) - 1; j >= 0; j-- { 277 b = append(b, symbol[j]) 278 } 279 280 for j := len(nnh.currencyPositivePrefix) - 1; j >= 0; j-- { 281 b = append(b, nnh.currencyPositivePrefix[j]) 282 } 283 284 if num < 0 { 285 b = append(b, nnh.minus[0]) 286 } 287 288 // reverse 289 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 { 290 b[i], b[j] = b[j], b[i] 291 } 292 293 if int(v) < 2 { 294 295 if v == 0 { 296 b = append(b, nnh.decimal...) 297 } 298 299 for i := 0; i < 2-int(v); i++ { 300 b = append(b, '0') 301 } 302 } 303 304 return string(b) 305} 306 307// FmtAccounting returns the currency representation of 'num' with digits/precision of 'v' for 'nnh' 308// in accounting notation. 309func (nnh *nnh) FmtAccounting(num float64, v uint64, currency currency.Type) string { 310 311 s := strconv.FormatFloat(math.Abs(num), 'f', int(v), 64) 312 symbol := nnh.currencies[currency] 313 l := len(s) + len(symbol) + 3 + 1*len(s[:len(s)-int(v)-1])/3 314 count := 0 315 inWhole := v == 0 316 b := make([]byte, 0, l) 317 318 for i := len(s) - 1; i >= 0; i-- { 319 320 if s[i] == '.' { 321 b = append(b, nnh.decimal[0]) 322 inWhole = true 323 continue 324 } 325 326 if inWhole { 327 if count == 3 { 328 b = append(b, nnh.group[0]) 329 count = 1 330 } else { 331 count++ 332 } 333 } 334 335 b = append(b, s[i]) 336 } 337 338 if num < 0 { 339 340 for j := len(symbol) - 1; j >= 0; j-- { 341 b = append(b, symbol[j]) 342 } 343 344 for j := len(nnh.currencyNegativePrefix) - 1; j >= 0; j-- { 345 b = append(b, nnh.currencyNegativePrefix[j]) 346 } 347 348 b = append(b, nnh.minus[0]) 349 350 } else { 351 352 for j := len(symbol) - 1; j >= 0; j-- { 353 b = append(b, symbol[j]) 354 } 355 356 for j := len(nnh.currencyPositivePrefix) - 1; j >= 0; j-- { 357 b = append(b, nnh.currencyPositivePrefix[j]) 358 } 359 360 } 361 362 // reverse 363 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 { 364 b[i], b[j] = b[j], b[i] 365 } 366 367 if int(v) < 2 { 368 369 if v == 0 { 370 b = append(b, nnh.decimal...) 371 } 372 373 for i := 0; i < 2-int(v); i++ { 374 b = append(b, '0') 375 } 376 } 377 378 return string(b) 379} 380 381// FmtDateShort returns the short date representation of 't' for 'nnh' 382func (nnh *nnh) FmtDateShort(t time.Time) string { 383 384 b := make([]byte, 0, 32) 385 386 if t.Day() < 10 { 387 b = append(b, '0') 388 } 389 390 b = strconv.AppendInt(b, int64(t.Day()), 10) 391 b = append(b, []byte{0x2f}...) 392 393 if t.Month() < 10 { 394 b = append(b, '0') 395 } 396 397 b = strconv.AppendInt(b, int64(t.Month()), 10) 398 399 b = append(b, []byte{0x2f}...) 400 401 if t.Year() > 9 { 402 b = append(b, strconv.Itoa(t.Year())[2:]...) 403 } else { 404 b = append(b, strconv.Itoa(t.Year())[1:]...) 405 } 406 407 return string(b) 408} 409 410// FmtDateMedium returns the medium date representation of 't' for 'nnh' 411func (nnh *nnh) FmtDateMedium(t time.Time) string { 412 413 b := make([]byte, 0, 32) 414 415 b = strconv.AppendInt(b, int64(t.Day()), 10) 416 b = append(b, []byte{0x20}...) 417 b = append(b, nnh.monthsAbbreviated[t.Month()]...) 418 b = append(b, []byte{0x2c, 0x20}...) 419 420 if t.Year() > 0 { 421 b = strconv.AppendInt(b, int64(t.Year()), 10) 422 } else { 423 b = strconv.AppendInt(b, int64(-t.Year()), 10) 424 } 425 426 return string(b) 427} 428 429// FmtDateLong returns the long date representation of 't' for 'nnh' 430func (nnh *nnh) FmtDateLong(t time.Time) string { 431 432 b := make([]byte, 0, 32) 433 434 b = append(b, []byte{0x6c, 0x79, 0xc9, 0x9b}...) 435 b = append(b, []byte{0xcc, 0x8c, 0xca, 0xbc, 0x20}...) 436 b = strconv.AppendInt(b, int64(t.Day()), 10) 437 b = append(b, []byte{0x20, 0x6e, 0x61}...) 438 b = append(b, []byte{0x20}...) 439 b = append(b, nnh.monthsWide[t.Month()]...) 440 b = append(b, []byte{0x2c, 0x20}...) 441 442 if t.Year() > 0 { 443 b = strconv.AppendInt(b, int64(t.Year()), 10) 444 } else { 445 b = strconv.AppendInt(b, int64(-t.Year()), 10) 446 } 447 448 return string(b) 449} 450 451// FmtDateFull returns the full date representation of 't' for 'nnh' 452func (nnh *nnh) FmtDateFull(t time.Time) string { 453 454 b := make([]byte, 0, 32) 455 456 b = append(b, nnh.daysWide[t.Weekday()]...) 457 b = append(b, []byte{0x20, 0x2c, 0x20, 0x6c, 0x79, 0xc9, 0x9b}...) 458 b = append(b, []byte{0xcc, 0x8c, 0xca, 0xbc, 0x20}...) 459 b = strconv.AppendInt(b, int64(t.Day()), 10) 460 b = append(b, []byte{0x20, 0x6e, 0x61}...) 461 b = append(b, []byte{0x20}...) 462 b = append(b, nnh.monthsWide[t.Month()]...) 463 b = append(b, []byte{0x2c, 0x20}...) 464 465 if t.Year() > 0 { 466 b = strconv.AppendInt(b, int64(t.Year()), 10) 467 } else { 468 b = strconv.AppendInt(b, int64(-t.Year()), 10) 469 } 470 471 return string(b) 472} 473 474// FmtTimeShort returns the short time representation of 't' for 'nnh' 475func (nnh *nnh) FmtTimeShort(t time.Time) string { 476 477 b := make([]byte, 0, 32) 478 479 return string(b) 480} 481 482// FmtTimeMedium returns the medium time representation of 't' for 'nnh' 483func (nnh *nnh) FmtTimeMedium(t time.Time) string { 484 485 b := make([]byte, 0, 32) 486 487 return string(b) 488} 489 490// FmtTimeLong returns the long time representation of 't' for 'nnh' 491func (nnh *nnh) FmtTimeLong(t time.Time) string { 492 493 b := make([]byte, 0, 32) 494 495 return string(b) 496} 497 498// FmtTimeFull returns the full time representation of 't' for 'nnh' 499func (nnh *nnh) FmtTimeFull(t time.Time) string { 500 501 b := make([]byte, 0, 32) 502 503 return string(b) 504} 505