Skip to content

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

FunctionReturns
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 negative digits shows 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() and GroupSeparator() 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, and CurrencySymbol(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”.

In bellui v1.0.0, 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.CompareFold ignores case and accents. Use it to match search text.
  • lang.NewCollator makes a reusable comparer for sorting large slices. Options include lang.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)
}