This document covers language tag parsing, validation, matching, and display name functionality based on BCP 47 and Unicode CLDR data.
Import path: golang.org/x/text/language
Implements BCP 47 language tags and related functionality for language identification and matching.
// Tag represents a BCP 47 language tag
type Tag struct{}
// Parsing functions
func Parse(s string) (Tag, error)
func Make(s string) Tag
func MustParse(s string) Tag
// Composition functions
func Compose(part ...interface{}) (Tag, error)
// Accept-Language parsing
func ParseAcceptLanguage(s string) (tag []Tag, q []float32, err error)func (t Tag) String() string
func (t Tag) Base() (Base, Confidence)
func (t Tag) Script() (Script, Confidence)
func (t Tag) Region() (Region, Confidence)
func (t Tag) Raw() (b Base, s Script, r Region)
func (t Tag) Variants() []Variant
func (t Tag) Parent() Tag
func (t Tag) IsRoot() bool
func (t Tag) Extension(x byte) (ext Extension, ok bool)
func (t Tag) Extensions() []Extension
func (t Tag) TypeForKey(key string) string
func (t Tag) SetTypeForKey(key, value string) (Tag, error)
func (t Tag) MarshalText() (text []byte, err error)
func (t Tag) UnmarshalText(text []byte) errorvar Und Tag // Undefined
// English variants
var English Tag
var AmericanEnglish Tag
var BritishEnglish Tag
// Spanish variants
var Spanish Tag
var EuropeanSpanish Tag
var LatinAmericanSpanish Tag
// French variants
var French Tag
var CanadianFrench Tag
// Other major languages
var German Tag
var Italian Tag
var Portuguese Tag
var BrazilianPortuguese Tag
var EuropeanPortuguese Tag
var Dutch Tag
var Russian Tag
var Japanese Tag
var Korean Tag
var Arabic Tag
var Hindi Tag
var Turkish Tag
var Polish Tag
var Ukrainian Tag
var Swedish Tag
var Danish Tag
var Norwegian Tag
var Finnish Tag
var Greek Tag
var Hebrew Tag
var Thai Tag
var Vietnamese Tag
var Indonesian Tag
var Malay Tag
// Chinese variants
var Chinese Tag
var SimplifiedChinese Tag
var TraditionalChinese Tag
var MandarinChinese Tag// Base is an ISO 639 language code
type Base struct{}
func ParseBase(s string) (Base, error)
func MustParseBase(s string) Base
func (b Base) String() string
func (b Base) ISO3() string
func (b Base) IsPrivateUse() bool// Script is a 4-letter ISO 15924 code
type Script struct{}
func ParseScript(s string) (Script, error)
func MustParseScript(s string) Script
func (s Script) String() string
func (s Script) IsPrivateUse() bool// Region is an ISO 3166-1 or UN M.49 code
type Region struct{}
func ParseRegion(s string) (Region, error)
func MustParseRegion(s string) Region
func EncodeM49(r int) (Region, error)
func (r Region) String() string
func (r Region) ISO3() string
func (r Region) M49() int
func (r Region) IsCountry() bool
func (r Region) IsGroup() bool
func (r Region) IsPrivateUse() bool
func (r Region) Canonicalize() Region
func (r Region) Contains(c Region) bool
func (r Region) TLD() (Region, error)// Variant represents a registered variant
type Variant struct{}
func ParseVariant(s string) (Variant, error)
func (v Variant) String() string// Extension is a single BCP 47 extension
type Extension struct{}
func ParseExtension(s string) (Extension, error)
func (e Extension) String() string
func (e Extension) Type() byte
func (e Extension) Tokens() []string// Matcher matches preferred tags against supported tags
type Matcher interface {
Match(t ...Tag) (tag Tag, index int, c Confidence)
}
func NewMatcher(t []Tag, options ...MatchOption) Matcher
func MatchStrings(m Matcher, lang ...string) (tag Tag, index int)
// MatchOption configures a Matcher
type MatchOption func(*matcher)
func PreferSameScript(preferSame bool) MatchOption// Confidence indicates the level of certainty
type Confidence int
const (
No Confidence = iota // No match
Low // Most likely value from alternatives
High // Generally assumed correct
Exact // Exact match or explicitly specified
)
func (c Confidence) String() string
// Comprehends reports confidence for speaker understanding alternative
func Comprehends(speaker, alternative Tag) Confidence// CanonType specifies canonicalization types
type CanonType int
const (
DeprecatedBase CanonType = 1 << iota
DeprecatedScript
DeprecatedRegion
SuppressScript
Legacy
Macro
CLDR
Raw CanonType = 0
Deprecated CanonType = DeprecatedBase | DeprecatedScript | DeprecatedRegion
BCP47 CanonType = Deprecated | SuppressScript
All CanonType = BCP47 | Legacy | Macro
Default CanonType = Deprecated | Legacy
)
func (c CanonType) Canonicalize(t Tag) (Tag, error)
func (c CanonType) Compose(part ...interface{}) (Tag, error)
func (c CanonType) Make(s string) Tag
func (c CanonType) MustParse(s string) Tag
func (c CanonType) Parse(s string) (Tag, error)// Coverage defines the level of coverage of an i18n service
type Coverage interface {
Tags() []Tag
BaseLanguages() []Base
Scripts() []Script
Regions() []Region
}
func NewCoverage(list ...interface{}) Coverage
var Supported Coverage // All supported subtags
// Compact tag indexing
const NumCompactTags int // Number of compact tags
func CompactIndex(t Tag) (index int, exact bool)var ErrMissingLikelyTagsData error
// ValueError is returned when input is well-formed but subtag not recognized
type ValueError interface {
error
Subtag() string
}const CLDRVersion string = "32"import "golang.org/x/text/language"
// Parse language tags
tag, err := language.Parse("en-US")
tag = language.Make("en-GB") // Panics on error
tag = language.English
// Get tag components
base, conf := tag.Base() // Base language
script, conf := tag.Script() // Script
region, conf := tag.Region() // Region
// Compose tags from parts
tag, err = language.Compose(
language.English,
language.MustParseScript("Latn"),
language.MustParseRegion("US"),
)
// Language matching for content negotiation
supported := []language.Tag{
language.English,
language.Spanish,
language.German,
}
matcher := language.NewMatcher(supported)
// Match user preferences
userPrefs := []language.Tag{
language.Make("es-MX"),
language.Make("en"),
}
tag, index, conf := matcher.Match(userPrefs...)
// Parse Accept-Language header
tags, q, err := language.ParseAcceptLanguage("en-US,en;q=0.9,es;q=0.8")
// Check if speaker can comprehend alternative
conf := language.Comprehends(language.Spanish, language.Catalan)
// Work with regions
region := language.MustParseRegion("US")
iso3 := region.ISO3() // "USA"
m49 := region.M49() // 840
isCountry := region.IsCountry() // true
// Canonicalization
deprecated := language.Make("iw") // Hebrew (deprecated code)
canonical, _ := language.BCP47.Canonicalize(deprecated)
// canonical is now "he" (modern Hebrew code)Import path: golang.org/x/text/language/display
Provides display names for languages, scripts, and regions in various languages.
// Namer returns names for given values
type Namer interface {
Name(x interface{}) string
}
// Get Namers for a specific language
func Languages(t language.Tag) Namer
func Scripts(t language.Tag) Namer
func Regions(t language.Tag) Namer
func Tags(t language.Tag) Namer// Dictionary holds Namers for a single language
type Dictionary struct{}
func (d *Dictionary) Languages() Namer
func (d *Dictionary) Scripts() Namer
func (d *Dictionary) Regions() Namer
func (d *Dictionary) Tags() Namer// Major languages
var Afrikaans *Dictionary
var Amharic *Dictionary
var Arabic *Dictionary
var ModernStandardArabic *Dictionary
var Azerbaijani *Dictionary
var Bulgarian *Dictionary
var Bengali *Dictionary
var Catalan *Dictionary
var Czech *Dictionary
var Danish *Dictionary
var German *Dictionary
var Greek *Dictionary
var English *Dictionary
var AmericanEnglish *Dictionary
var BritishEnglish *Dictionary
var Spanish *Dictionary
var EuropeanSpanish *Dictionary
var LatinAmericanSpanish *Dictionary
var Estonian *Dictionary
var Persian *Dictionary
var Finnish *Dictionary
var Filipino *Dictionary
var French *Dictionary
var CanadianFrench *Dictionary
var Gujarati *Dictionary
var Hebrew *Dictionary
var Hindi *Dictionary
var Croatian *Dictionary
var Hungarian *Dictionary
var Armenian *Dictionary
var Indonesian *Dictionary
var Icelandic *Dictionary
var Italian *Dictionary
var Japanese *Dictionary
var Georgian *Dictionary
var Kazakh *Dictionary
var Khmer *Dictionary
var Kannada *Dictionary
var Korean *Dictionary
var Kirghiz *Dictionary
var Lao *Dictionary
var Lithuanian *Dictionary
var Latvian *Dictionary
var Macedonian *Dictionary
var Malayalam *Dictionary
var Mongolian *Dictionary
var Marathi *Dictionary
var Malay *Dictionary
var Burmese *Dictionary
var Nepali *Dictionary
var Dutch *Dictionary
var Norwegian *Dictionary
var Punjabi *Dictionary
var Polish *Dictionary
var Portuguese *Dictionary
var BrazilianPortuguese *Dictionary
var EuropeanPortuguese *Dictionary
var Romanian *Dictionary
var Russian *Dictionary
var Sinhala *Dictionary
var Slovak *Dictionary
var Slovenian *Dictionary
var Albanian *Dictionary
var Serbian *Dictionary
var SerbianLatin *Dictionary
var Swedish *Dictionary
var Swahili *Dictionary
var Tamil *Dictionary
var Telugu *Dictionary
var Thai *Dictionary
var Turkish *Dictionary
var Ukrainian *Dictionary
var Urdu *Dictionary
var Uzbek *Dictionary
var Vietnamese *Dictionary
var Chinese *Dictionary
var SimplifiedChinese *Dictionary
var TraditionalChinese *Dictionary
var Zulu *Dictionary// SelfNamer returns language names in their own language
type SelfNamer struct {
Supported language.Coverage
}
func (s *SelfNamer) Name(x interface{}) string
var Self *SelfNamer // Shared instance// Formatter formats tags for display
type Formatter struct{}
func Language(lang interface{}) Formatter
func Script(script interface{}) Formatter
func Region(region interface{}) Formatter
func Tag(tag interface{}) Formatter
func (f Formatter) Format(state format.State, verb rune)var Supported language.Coverage // Languages for which names are defined
var Values language.Coverage // All possible values with namesconst CLDRVersion string = "32"
const Version string = "32" // Deprecated: Use CLDRVersionimport (
"fmt"
"golang.org/x/text/language"
"golang.org/x/text/language/display"
)
// Get language names in different languages
enNamer := display.English.Languages()
fmt.Println(enNamer.Name(language.Spanish)) // "Spanish"
fmt.Println(enNamer.Name(language.Japanese)) // "Japanese"
esNamer := display.Spanish.Languages()
fmt.Println(esNamer.Name(language.English)) // "inglés"
fmt.Println(esNamer.Name(language.French)) // "francés"
// Get region names
regionNamer := display.English.Regions()
fmt.Println(regionNamer.Name(language.MustParseRegion("US"))) // "United States"
fmt.Println(regionNamer.Name(language.MustParseRegion("JP"))) // "Japan"
// Get script names
scriptNamer := display.English.Scripts()
fmt.Println(scriptNamer.Name(language.MustParseScript("Latn"))) // "Latin"
fmt.Println(scriptNamer.Name(language.MustParseScript("Cyrl"))) // "Cyrillic"
// Get full tag descriptions
tagNamer := display.English.Tags()
tag := language.Make("zh-Hans-CN")
fmt.Println(tagNamer.Name(tag)) // "Simplified Chinese (China)"
// Get language names in their own language (self-naming)
fmt.Println(display.Self.Name(language.Spanish)) // "español"
fmt.Println(display.Self.Name(language.Japanese)) // "日本語"
fmt.Println(display.Self.Name(language.Arabic)) // "العربية"
// Use standalone functions
langNamer := display.Languages(language.German)
fmt.Println(langNamer.Name(language.Italian)) // "Italienisch"
regionNamer = display.Regions(language.French)
fmt.Println(regionNamer.Name(language.MustParseRegion("CA"))) // "Canada"
// Use with fmt.Printf via Formatter
fmt.Printf("Language: %v\n", display.Language(language.Spanish))
fmt.Printf("Region: %v\n", display.Region(language.MustParseRegion("MX")))import (
"net/http"
"golang.org/x/text/language"
)
func handleRequest(w http.ResponseWriter, r *http.Request) {
// Define supported languages
supported := []language.Tag{
language.English,
language.Spanish,
language.French,
language.German,
}
matcher := language.NewMatcher(supported)
// Parse Accept-Language header
acceptLang := r.Header.Get("Accept-Language")
tags, _, _ := language.ParseAcceptLanguage(acceptLang)
// Match best language
tag, index, conf := matcher.Match(tags...)
// Use matched language for response
// ...
}import (
"golang.org/x/text/language"
"golang.org/x/text/language/display"
)
type LanguageOption struct {
Code string
Name string
}
func getLanguageOptions(displayLang language.Tag) []LanguageOption {
namer := display.Languages(displayLang)
supported := []language.Tag{
language.English,
language.Spanish,
language.French,
language.German,
language.Japanese,
language.Chinese,
}
options := make([]LanguageOption, len(supported))
for i, tag := range supported {
options[i] = LanguageOption{
Code: tag.String(),
Name: namer.Name(tag),
}
}
return options
}import (
"strings"
"golang.org/x/text/language"
)
func extractLanguageFromPath(path string) (language.Tag, string) {
parts := strings.Split(strings.Trim(path, "/"), "/")
if len(parts) == 0 {
return language.English, path
}
// Try to parse first path component as language
tag, err := language.Parse(parts[0])
if err == nil {
// Valid language tag found
remainingPath := "/" + strings.Join(parts[1:], "/")
return tag, remainingPath
}
// No language in path
return language.English, path
}import "golang.org/x/text/language"
func validateAndCanonicalizeRegion(code string) (language.Region, error) {
region, err := language.ParseRegion(code)
if err != nil {
return language.Region{}, err
}
// Canonicalize deprecated regions
region = region.Canonicalize()
// Check if it's a real country (not a group)
if !region.IsCountry() {
return language.Region{}, fmt.Errorf("not a country: %s", code)
}
return region, nil
}
func getRegionHierarchy(region language.Region) []language.Region {
// Get containing regions (e.g., US -> Americas -> World)
hierarchy := []language.Region{region}
// Check M.49 groups
m49 := region.M49()
// ... lookup parent regions from M.49 codes
return hierarchy
}import "golang.org/x/text/language"
func findFallbackLanguage(requested language.Tag, available []language.Tag) language.Tag {
// Try exact match
for _, tag := range available {
if tag == requested {
return tag
}
}
// Try base language match (ignore script/region)
requestedBase, _ := requested.Base()
for _, tag := range available {
base, _ := tag.Base()
if base == requestedBase {
return tag
}
}
// Try parent
parent := requested.Parent()
if !parent.IsRoot() {
return findFallbackLanguage(parent, available)
}
// Default to first available
if len(available) > 0 {
return available[0]
}
return language.English
}import (
"golang.org/x/text/language"
"golang.org/x/text/language/display"
)
type LocalizedName struct {
Native string // Name in its own language
English string // Name in English
Local string // Name in user's language
}
func getLocalizedNames(tag language.Tag, userLang language.Tag) LocalizedName {
return LocalizedName{
Native: display.Self.Name(tag),
English: display.English.Languages().Name(tag),
Local: display.Languages(userLang).Name(tag),
}
}Based on: