Formats
Each function in this page uses the current locale, including its region. They
follow lang.SetLocale without extra work.
now := time.Now()
lines := []string{
// month/day/year in en-US, day.month.year in de-DE
"Date: " + lang.FormatDate(now),
// "2:05 PM" in en-US, "14:05" in de-DE
"Time: " + lang.FormatTime(now.Hour(), now.Minute()),
// "MM/DD/YYYY" in en-US, "DD.MM.YYYY" in de-DE
"Date hint: " + lang.DatePatternHint(),
// "1,234,567.89" in en-US, "1.234.567,89" in de-DE
"Number: " + lang.FormatDecimal(1234567.891, 2),
// "$19.99" in en-US, "19,99 €" in de-DE
"Price: " + lang.FormatCurrency(19.99, lang.DefaultCurrency()),
// "red, green, and blue" in English, "red, green und blue" in German
"Colours: " + lang.FormatList([]string{"red", "green", "blue"}),
// "1.24 mi" in en-US, "2 km" in de-DE
"Distance: " + lang.FormatDistance(2000),
}Dates and times
| Function | Returns |
|---|---|
FormatDate(t) | the short numeric date, such as 03/09/2026 (en-US) or 09.03.2026 (de-DE) |
FormatTime(hour, minute) | 2:05 PM or 14:05 |
FormatDateTime(t) | both, separated by a space |
FormatMonthYear(t) | the translated month name and the year |
DatePatternHint() | a placeholder for input fields, such as MM/DD/YYYY |
WeekStartDay() | the first day of the week: Sunday in the US, Monday in Germany |
ParseDate and ParseDateTime read text in the same format back into a
time.Time. ParseDate accepts single-digit days and months, such as
1/5/2026. DatePattern, TimePattern and DateTimePattern return the Go
layout strings, if you want to call time.Format yourself.
lang.Prefers24HourClock
reports whether the region normally uses a 24-hour clock. Most regions do.
The exceptions include the United States, Canada, Australia, India and
Korea. Use it to decide whether a time input needs an AM/PM switch:
if lang.Prefers24HourClock() {
lines = append(lines, "This locale uses a 24-hour clock")
}Dates use the Gregorian calendar in every locale.
Numbers and money
FormatDecimal(v, digits)formats a number with the locale’s decimal and grouping separators. A negativedigitsshows as many decimals as needed and no trailing zeros.ParseLocaleFloat(s)reads a number typed in the locale’s format. See the example below.DecimalSeparator()andGroupSeparator()return the separators.FormatCurrency(amount, code)formats money with two decimals and the currency’s symbol, placed before or after the number as the region does:$19.99,19,99 €. The code is an ISO 4217 code such as"EUR".DefaultCurrency()returns the region’s currency code, andCurrencySymbol(code)the symbol.
typed := "1.234,5" // what a German user might type
if v, err := lang.ParseLocaleFloat(typed); err == nil {
lines = append(lines, "Parsed: "+lang.FormatDecimal(v, -1))
}The locale’s separators decide the result. Under de-DE this text reads as
1234.5. Under en-US the same text reads as 1.2345, because there the comma
is the grouping separator and is dropped.
Lists and units
FormatList
joins items with the locale’s separators and conjunction: “red, green, and
blue” in English, “red, green und blue” in German, “red、green、blue” in
Japanese. Use it instead of joining with ", " and "and" yourself.
FormatDistance(meters)
and FormatMass(grams)
take a value in metres or grams and choose the unit. The United States, the
United Kingdom, Liberia and Myanmar get feet and miles, or pounds. Elsewhere
the result is in metres or kilometres, grams or kilograms. Values are rounded
to two decimals.
FormatUnit(value, unit)
formats a value in a unit you choose, from metres, kilometres, miles, feet,
grams, kilograms and pounds. The unit’s label takes the right plural form,
such as Polish “1 mila”, “2 mile”, “5 mil”.
FormatUnit, FormatDistance and FormatMass log a “Unit
format failure” error when the value has a fractional part, such as 1.24
miles. The text they return is still correct.Sorting text
Sorting strings with < puts them in code-point order, which is wrong for
most languages: “Zoë” before “apple”, and accented letters at the end. Use
lang.Compare:
names := []string{"Zoë", "Ärger", "apple", "Österreich", "zebra"}
sort.Slice(names, func(i, j int) bool {
return lang.Compare(names[i], names[j]) < 0
})
lines = append(lines, "Sorted: "+strings.Join(names, ", "))In German, this sorts “Ärger” with the A words and “Österreich” with the O
words. In Swedish, Ä and Ö come after Z. Compare is safe to call from any
goroutine and follows SetLocale.
lang.CompareFoldignores case and accents. Use it to match search text.lang.NewCollatormakes a reusable comparer for sorting large slices. Options includelang.CollateNumeric, which sorts “file2” before “file10”. A collator keeps the locale it was made with and must not be shared between goroutines.
Sorting by locale adds about 1.75 MB of collation tables to your binary, only if you call one of these functions.
The full program:
// Locale-aware formatting of dates, times, numbers, money, lists and
// distances, and locale-aware sorting.
package main
import (
"sort"
"strings"
"time"
"github.com/belluikit/bellui"
"github.com/belluikit/bellui/app"
"github.com/belluikit/bellui/container"
"github.com/belluikit/bellui/lang"
"github.com/belluikit/bellui/widget"
)
func main() {
a := app.New()
w := a.NewWindow("Formats")
now := time.Now()
lines := []string{
// month/day/year in en-US, day.month.year in de-DE
"Date: " + lang.FormatDate(now),
// "2:05 PM" in en-US, "14:05" in de-DE
"Time: " + lang.FormatTime(now.Hour(), now.Minute()),
// "MM/DD/YYYY" in en-US, "DD.MM.YYYY" in de-DE
"Date hint: " + lang.DatePatternHint(),
// "1,234,567.89" in en-US, "1.234.567,89" in de-DE
"Number: " + lang.FormatDecimal(1234567.891, 2),
// "$19.99" in en-US, "19,99 €" in de-DE
"Price: " + lang.FormatCurrency(19.99, lang.DefaultCurrency()),
// "red, green, and blue" in English, "red, green und blue" in German
"Colours: " + lang.FormatList([]string{"red", "green", "blue"}),
// "1.24 mi" in en-US, "2 km" in de-DE
"Distance: " + lang.FormatDistance(2000),
}
if lang.Prefers24HourClock() {
lines = append(lines, "This locale uses a 24-hour clock")
}
typed := "1.234,5" // what a German user might type
if v, err := lang.ParseLocaleFloat(typed); err == nil {
lines = append(lines, "Parsed: "+lang.FormatDecimal(v, -1))
}
names := []string{"Zoë", "Ärger", "apple", "Österreich", "zebra"}
sort.Slice(names, func(i, j int) bool {
return lang.Compare(names[i], names[j]) < 0
})
lines = append(lines, "Sorted: "+strings.Join(names, ", "))
w.SetContent(container.NewVBox(widget.NewLabel(strings.Join(lines, "\n"))))
bellui.ShowAndRun(w)
}