You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
2.4 KiB

package gotext
import (
"context"
"gitoa.ru/go-4devs/translation"
"gitoa.ru/go-4devs/translation/arg"
"golang.org/x/text/currency"
"golang.org/x/text/language"
"golang.org/x/text/message"
"golang.org/x/text/message/catalog"
"golang.org/x/text/number"
)
var _ translation.Provider = (*Provider)(nil)
// Option confires message provider.
type Option func(*Provider)
// WithCatalog set coatalog bu domain name.
func WithCatalog(domain string, cat catalog.Catalog) Option {
return func(mp *Provider) {
mp.catalog[domain] = cat
}
}
// NewProvider creates new messgae provider.
func NewProvider(opts ...Option) *Provider {
mp := &Provider{
catalog: map[string]catalog.Catalog{
translation.DefaultDomain: message.DefaultCatalog,
},
}
for _, o := range opts {
o(mp)
}
return mp
}
// Provider provider messages.
type Provider struct {
catalog map[string]catalog.Catalog
}
// Translate by key and args.
func (mp *Provider) Translate(ctx context.Context, key string, opt translation.Translate) string {
return message.NewPrinter(opt.Locale, message.Catalog(mp.catalog[opt.Domain])).
Sprintf(key, messageArgs(opt.Locale, opt.Args)...)
}
func currencyMessage(lang language.Tag) func(v arg.Currency) interface{} {
return func(v arg.Currency) interface{} {
var u currency.Unit
if v.ISO != "" {
u, _ = currency.ParseISO(v.ISO)
} else {
u, _ = currency.FromTag(lang)
}
switch v.Format {
case arg.CurrencyFormatISO:
return currency.ISO(u.Amount(v.Val()))
case arg.CurrencyFormatSymbol:
return currency.Symbol(u.Amount(v.Val()))
case arg.CurrencyFormatNarrowSymbol:
return currency.NarrowSymbol(u.Amount(v.Val()))
}
return u.Amount(v.Val())
}
}
func numberMessage(v arg.Number) interface{} {
switch v.Format {
case arg.NumberFormatPercent:
return number.Percent(v.Val())
case arg.NumberFormatEngineering:
return number.Engineering(v.Val())
case arg.NumberFormatPerMille:
return number.PerMille(v.Val())
case arg.NumberFormatDecimal:
return number.Decimal(v.Val())
case arg.NumberFormatScientific:
return number.Scientific(v.Val())
}
return v.Val()
}
func messageArgs(lang language.Tag, in []translation.Arg) []interface{} {
out := make([]interface{}, 0, len(in))
for _, a := range in {
switch v := a.(type) {
case arg.Currency:
out = append(out, currencyMessage(lang)(v))
case arg.Number:
out = append(out, numberMessage(v))
default:
out = append(out, v.Val())
}
}
return out
}