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
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
|
|
}
|
|
|