formatter.go

 1package i18n
 2
 3import (
 4	"golang.org/x/text/language"
 5	"golang.org/x/text/message"
 6)
 7
 8// NumberFormatter formats numbers according to locale rules.
 9type NumberFormatter struct {
10	locale  *Locale
11	printer *message.Printer
12}
13
14// NewNumberFormatter creates a formatter for a locale.
15func NewNumberFormatter(locale *Locale) *NumberFormatter {
16	tag := language.English
17	if locale != nil && locale.Tag != language.Und {
18		tag = locale.Tag
19	}
20
21	return &NumberFormatter{
22		locale:  locale,
23		printer: message.NewPrinter(tag),
24	}
25}
26
27// FormatInt formats an integer according to locale rules.
28func (f *NumberFormatter) FormatInt(n int) string {
29	return f.printer.Sprintf("%d", n)
30}
31
32// FormatInt64 formats an int64 according to locale rules.
33func (f *NumberFormatter) FormatInt64(n int64) string {
34	return f.printer.Sprintf("%d", n)
35}
36
37// FormatFloat formats a float64 with the specified precision.
38func (f *NumberFormatter) FormatFloat(n float64, precision int) string {
39	format := "%." + string(rune(precision+'0')) + "f"
40	return f.printer.Sprintf(format, n)
41}
42
43// FormatPercent formats a number as a percentage (0.5 -> "50%").
44func (f *NumberFormatter) FormatPercent(n float64) string {
45	return f.printer.Sprintf("%.0f%%", n*100)
46}
47
48// FormatFileSize formats a byte count as a human-readable size.
49func (f *NumberFormatter) FormatFileSize(bytes int64) string {
50	const unit = 1024
51	if bytes < unit {
52		return f.printer.Sprintf("%d B", bytes)
53	}
54
55	div, exp := int64(unit), 0
56	for n := bytes / unit; n >= unit; n /= unit {
57		div *= unit
58		exp++
59	}
60
61	units := []string{"KB", "MB", "GB", "TB", "PB"}
62	if exp >= len(units) {
63		exp = len(units) - 1
64	}
65
66	return f.printer.Sprintf("%.1f %s", float64(bytes)/float64(div), units[exp])
67}