123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- package locales
- import (
- "strconv"
- "time"
- "github.com/go-playground/locales/currency"
- )
- // // ErrBadNumberValue is returned when the number passed for
- // // plural rule determination cannot be parsed
- // type ErrBadNumberValue struct {
- // NumberValue string
- // InnerError error
- // }
- // // Error returns ErrBadNumberValue error string
- // func (e *ErrBadNumberValue) Error() string {
- // return fmt.Sprintf("Invalid Number Value '%s' %s", e.NumberValue, e.InnerError)
- // }
- // var _ error = new(ErrBadNumberValue)
- // PluralRule denotes the type of plural rules
- type PluralRule int
- // PluralRule's
- const (
- PluralRuleUnknown PluralRule = iota
- PluralRuleZero // zero
- PluralRuleOne // one - singular
- PluralRuleTwo // two - dual
- PluralRuleFew // few - paucal
- PluralRuleMany // many - also used for fractions if they have a separate class
- PluralRuleOther // other - required—general plural form—also used if the language only has a single form
- )
- const (
- pluralsString = "UnknownZeroOneTwoFewManyOther"
- )
- // Translator encapsulates an instance of a locale
- // NOTE: some values are returned as a []byte just in case the caller
- // wishes to add more and can help avoid allocations; otherwise just cast as string
- type Translator interface {
- // The following Functions are for overriding, debugging or developing
- // with a Translator Locale
- // Locale returns the string value of the translator
- Locale() string
- // returns an array of cardinal plural rules associated
- // with this translator
- PluralsCardinal() []PluralRule
- // returns an array of ordinal plural rules associated
- // with this translator
- PluralsOrdinal() []PluralRule
- // returns an array of range plural rules associated
- // with this translator
- PluralsRange() []PluralRule
- // returns the cardinal PluralRule given 'num' and digits/precision of 'v' for locale
- CardinalPluralRule(num float64, v uint64) PluralRule
- // returns the ordinal PluralRule given 'num' and digits/precision of 'v' for locale
- OrdinalPluralRule(num float64, v uint64) PluralRule
- // returns the ordinal PluralRule given 'num1', 'num2' and digits/precision of 'v1' and 'v2' for locale
- RangePluralRule(num1 float64, v1 uint64, num2 float64, v2 uint64) PluralRule
- // returns the locales abbreviated month given the 'month' provided
- MonthAbbreviated(month time.Month) string
- // returns the locales abbreviated months
- MonthsAbbreviated() []string
- // returns the locales narrow month given the 'month' provided
- MonthNarrow(month time.Month) string
- // returns the locales narrow months
- MonthsNarrow() []string
- // returns the locales wide month given the 'month' provided
- MonthWide(month time.Month) string
- // returns the locales wide months
- MonthsWide() []string
- // returns the locales abbreviated weekday given the 'weekday' provided
- WeekdayAbbreviated(weekday time.Weekday) string
- // returns the locales abbreviated weekdays
- WeekdaysAbbreviated() []string
- // returns the locales narrow weekday given the 'weekday' provided
- WeekdayNarrow(weekday time.Weekday) string
- // WeekdaysNarrowreturns the locales narrow weekdays
- WeekdaysNarrow() []string
- // returns the locales short weekday given the 'weekday' provided
- WeekdayShort(weekday time.Weekday) string
- // returns the locales short weekdays
- WeekdaysShort() []string
- // returns the locales wide weekday given the 'weekday' provided
- WeekdayWide(weekday time.Weekday) string
- // returns the locales wide weekdays
- WeekdaysWide() []string
- // The following Functions are common Formatting functionsfor the Translator's Locale
- // returns 'num' with digits/precision of 'v' for locale and handles both Whole and Real numbers based on 'v'
- FmtNumber(num float64, v uint64) string
- // returns 'num' with digits/precision of 'v' for locale and handles both Whole and Real numbers based on 'v'
- // NOTE: 'num' passed into FmtPercent is assumed to be in percent already
- FmtPercent(num float64, v uint64) string
- // returns the currency representation of 'num' with digits/precision of 'v' for locale
- FmtCurrency(num float64, v uint64, currency currency.Type) string
- // returns the currency representation of 'num' with digits/precision of 'v' for locale
- // in accounting notation.
- FmtAccounting(num float64, v uint64, currency currency.Type) string
- // returns the short date representation of 't' for locale
- FmtDateShort(t time.Time) string
- // returns the medium date representation of 't' for locale
- FmtDateMedium(t time.Time) string
- // returns the long date representation of 't' for locale
- FmtDateLong(t time.Time) string
- // returns the full date representation of 't' for locale
- FmtDateFull(t time.Time) string
- // returns the short time representation of 't' for locale
- FmtTimeShort(t time.Time) string
- // returns the medium time representation of 't' for locale
- FmtTimeMedium(t time.Time) string
- // returns the long time representation of 't' for locale
- FmtTimeLong(t time.Time) string
- // returns the full time representation of 't' for locale
- FmtTimeFull(t time.Time) string
- }
- // String returns the string value of PluralRule
- func (p PluralRule) String() string {
- switch p {
- case PluralRuleZero:
- return pluralsString[7:11]
- case PluralRuleOne:
- return pluralsString[11:14]
- case PluralRuleTwo:
- return pluralsString[14:17]
- case PluralRuleFew:
- return pluralsString[17:20]
- case PluralRuleMany:
- return pluralsString[20:24]
- case PluralRuleOther:
- return pluralsString[24:]
- default:
- return pluralsString[:7]
- }
- }
- //
- // Precision Notes:
- //
- // must specify a precision >= 0, and here is why https://play.golang.org/p/LyL90U0Vyh
- //
- // v := float64(3.141)
- // i := float64(int64(v))
- //
- // fmt.Println(v - i)
- //
- // or
- //
- // s := strconv.FormatFloat(v-i, 'f', -1, 64)
- // fmt.Println(s)
- //
- // these will not print what you'd expect: 0.14100000000000001
- // and so this library requires a precision to be specified, or
- // inaccurate plural rules could be applied.
- //
- //
- //
- // n - absolute value of the source number (integer and decimals).
- // i - integer digits of n.
- // v - number of visible fraction digits in n, with trailing zeros.
- // w - number of visible fraction digits in n, without trailing zeros.
- // f - visible fractional digits in n, with trailing zeros.
- // t - visible fractional digits in n, without trailing zeros.
- //
- //
- // Func(num float64, v uint64) // v = digits/precision and prevents -1 as a special case as this can lead to very unexpected behaviour, see precision note's above.
- //
- // n := math.Abs(num)
- // i := int64(n)
- // v := v
- //
- //
- // w := strconv.FormatFloat(num-float64(i), 'f', int(v), 64) // then parse backwards on string until no more zero's....
- // f := strconv.FormatFloat(n, 'f', int(v), 64) // then turn everything after decimal into an int64
- // t := strconv.FormatFloat(n, 'f', int(v), 64) // then parse backwards on string until no more zero's....
- //
- //
- //
- // General Inclusion Rules
- // - v will always be available inherently
- // - all require n
- // - w requires i
- //
- // W returns the number of visible fraction digits in N, without trailing zeros.
- func W(n float64, v uint64) (w int64) {
- s := strconv.FormatFloat(n-float64(int64(n)), 'f', int(v), 64)
- // with either be '0' or '0.xxxx', so if 1 then w will be zero
- // otherwise need to parse
- if len(s) != 1 {
- s = s[2:]
- end := len(s) + 1
- for i := end; i >= 0; i-- {
- if s[i] != '0' {
- end = i + 1
- break
- }
- }
- w = int64(len(s[:end]))
- }
- return
- }
- // F returns the visible fractional digits in N, with trailing zeros.
- func F(n float64, v uint64) (f int64) {
- s := strconv.FormatFloat(n-float64(int64(n)), 'f', int(v), 64)
- // with either be '0' or '0.xxxx', so if 1 then f will be zero
- // otherwise need to parse
- if len(s) != 1 {
- // ignoring error, because it can't fail as we generated
- // the string internally from a real number
- f, _ = strconv.ParseInt(s[2:], 10, 64)
- }
- return
- }
- // T returns the visible fractional digits in N, without trailing zeros.
- func T(n float64, v uint64) (t int64) {
- s := strconv.FormatFloat(n-float64(int64(n)), 'f', int(v), 64)
- // with either be '0' or '0.xxxx', so if 1 then t will be zero
- // otherwise need to parse
- if len(s) != 1 {
- s = s[2:]
- end := len(s) + 1
- for i := end; i >= 0; i-- {
- if s[i] != '0' {
- end = i + 1
- break
- }
- }
- // ignoring error, because it can't fail as we generated
- // the string internally from a real number
- t, _ = strconv.ParseInt(s[:end], 10, 64)
- }
- return
- }
|