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}