Skip to main content

Ang Kumpletong Gabay sa Go Internationalization

Mula sa mga message file hanggang goroutine-safe na locale resolution: i-set up ang i18n sa inyong Go app gamit ang go-i18n, pagkatapos ay i-automate ang pagsasalin gamit ang AI.

1

I-install ang go-i18n

Ang go-i18n ang pinakasikat na internationalization library para sa Go. Gumagamit ito ng mga CLDR plural rule, Go template para sa variable interpolation, at sumusuporta sa JSON, TOML, at YAML message file. Kailangan ninyo rin ang golang.org/x/text para sa language tag matching.

Nangangailangan ang go-i18n v2 ng Go 1.16+. Nagbibigay ang package na golang.org/x/text ng BCP 47 language tag parsing at matching, na ginagamit ng go-i18n sa loob para sa pagpili ng plural rule.
Terminal
go get -u github.com/nicksnyder/go-i18n/v2/i18n
go get -u golang.org/x/text/language
2

Gumawa ng Mga Message File

Gumawa ng isang JSON file bawat wika sa isang locales directory. May ID ang bawat message at isa o higit pang plural form. Gumagamit ang go-i18n ng Go template syntax (double curly braces na may dot prefix) para sa variable interpolation.

locales/en.json
{
  "HelloWorld": { "other": "Hello, World!" },
  "Greeting": { "other": "Hello, {{.Name}}!" },
  "ItemCount": {
    "one": "{{.Count}} item",
    "other": "{{.Count}} items"
  },
  "WelcomeBack": {
    "other": "Welcome back, {{.Name}}. You have {{.Count}} messages."
  }
}
Gumamit ng mapaglarawang message ID tulad ng 'ItemCount' o 'WelcomeBack' sa halip na mga path na pinaghiwa-hiwalay ng tuldok. Gumagamit ang go-i18n ng flat ID, hindi mga nested key. Panatilihing PascalCase ang mga ID upang tumugma sa mga convention ng Go.
3

I-load ang Bundle

Ang Bundle ang central registry ng go-i18n. Gumawa ng isa sa startup, irehistro ang file format, at i-load ang lahat ng message file. Goroutine-safe ang Bundle — gumawa nito nang isang beses at ibahagi sa buong application.

main.go
package main

import (
    "encoding/json"
    "fmt"
    "github.com/nicksnyder/go-i18n/v2/i18n"
    "golang.org/x/text/language"
)

func main() {
    // 1. Create a bundle with a default language
    bundle := i18n.NewBundle(language.English)
    // 2. Register the unmarshal function for your file format
    bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
    // 3. Load message files
    bundle.MustLoadMessageFile("locales/en.json")
    bundle.MustLoadMessageFile("locales/ja.json")
    bundle.MustLoadMessageFile("locales/de.json")
    // 4. Create a localizer and localize a message
    localizer := i18n.NewLocalizer(bundle, "ja")
    msg := localizer.MustLocalize(&i18n.LocalizeConfig{
        MessageID: "HelloWorld",
    })
    fmt.Println(msg) // "こんにちは、世界!"
}
Kung makakita kayo ng 'message not found', suriin ang tatlong bagay: 1) Na-load ang message file gamit ang LoadMessageFile o MustLoadMessageFile. 2) Tumutugma ang file extension sa nairehistrong unmarshal function. 3) Eksaktong tumutugma ang MessageID sa LocalizeConfig sa key sa inyong JSON file (case-sensitive).
4

Gamitin ang Localizer

Gumawa ng Localizer para sa bawat request gamit ang preferred language ng user. Nireresolba ng Localizer ang mga message mula sa Bundle, humahawak ng template rendering gamit ang text/template engine ng Go, at pumipili ng tamang plural form batay sa PluralCount.

Using the Localizer
// Simple message
msg := localizer.MustLocalize(&i18n.LocalizeConfig{
    MessageID: "HelloWorld",
})

// Message with template data
msg := localizer.MustLocalize(&i18n.LocalizeConfig{
    MessageID: "Greeting",
    TemplateData: map[string]interface{}{
        "Name": "Alice",
    },
})
// "Hello, Alice!" (en) or "こんにちは、Aliceさん!" (ja)

// Plural + template data
msg := localizer.MustLocalize(&i18n.LocalizeConfig{
    MessageID: "ItemCount",
    PluralCount: 5,
    TemplateData: map[string]interface{}{
        "Count": 5,
    },
})
// "5 items" (en) or "5個のアイテム" (ja)

// Combined: plurals + multiple variables
msg := localizer.MustLocalize(&i18n.LocalizeConfig{
    MessageID: "WelcomeBack",
    TemplateData: map[string]interface{}{
        "Name":  "Alice",
        "Count": 3,
    },
})
HTTP handler with locale detection
func handler(w http.ResponseWriter, r *http.Request) {
    // Accept-Language: ja,en;q=0.9,de;q=0.8
    accept := r.Header.Get("Accept-Language")

    // NewLocalizer accepts multiple languages — first match wins
    localizer := i18n.NewLocalizer(bundle, accept)

    msg := localizer.MustLocalize(&i18n.LocalizeConfig{
        MessageID: "HelloWorld",
    })

    w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    w.Write([]byte(msg))
}
Tumatanggap ang NewLocalizer ng maraming language string — sinusubukan nito ang mga iyon nang sunod-sunod. I-pass nang direkta ang Accept-Language header: i18n.NewLocalizer(bundle, r.Header.Get("Accept-Language")). Ipe-parse ng go-i18n ang header at awtomatikong itatapat sa mga available na pagsasalin.
5

Hawakan ang Mga Plural Rule

Ipinatutupad ng go-i18n ang CLDR plural rules para sa lahat ng wika. May 2 form ang English (one, other). May 6 ang Arabic (zero, one, two, few, many, other). May 1 ang Japanese (other). I-define ang lahat ng kinakailangang form sa inyong message file — pipiliin ng go-i18n ang tama batay sa PluralCount.

Plural forms by language
// English: 2 forms (one, other)
{
  "ItemCount": {
    "one": "{{.Count}} item",
    "other": "{{.Count}} items"
  }
}

// Arabic: 6 forms (zero, one, two, few, many, other)
{
  "ItemCount": {
    "zero": "لا عناصر",
    "one": "عنصر واحد",
    "two": "عنصران",
    "few": "{{.Count}} عناصر",
    "many": "{{.Count}} عنصرًا",
    "other": "{{.Count}} عنصر"
  }
}

// Japanese: 1 form (other)
{
  "ItemCount": {
    "other": "{{.Count}}個のアイテム"
  }
}
Using plural rules
// go-i18n selects the correct plural form based on PluralCount
localizer := i18n.NewLocalizer(bundle, "ar")

msg := localizer.MustLocalize(&i18n.LocalizeConfig{
    MessageID:   "ItemCount",
    PluralCount: 3,
    TemplateData: map[string]interface{}{
        "Count": 3,
    },
})
// Arabic "few" form: "3 عناصر"

msg = localizer.MustLocalize(&i18n.LocalizeConfig{
    MessageID:   "ItemCount",
    PluralCount: 1,
    TemplateData: map[string]interface{}{
        "Count": 1,
    },
})
// Arabic "one" form: "عنصر واحد"
Magkahiwalay ang PluralCount at TemplateData. Ang PluralCount ang pumipili ng plural form, at ang TemplateData ang nagbibigay ng mga value para sa template rendering. Kung kailangan ninyo ang count sa text ng message, i-pass ito sa pareho: PluralCount: n at TemplateData: map[string]interface{'}'{"Count": n}.
6

Pag-detect ng Locale

Sa mga web application, i-detect ang preferred language ng user mula sa maraming pinagmumulan: query parameter, cookie, Accept-Language header, o URL path segment. Gamitin ang golang.org/x/text/language.Matcher para sa BCP 47-compliant na language negotiation.

Locale detection middleware
// detectLocale resolves the user's preferred language.
// Priority: query param > cookie > Accept-Language header > default
func detectLocale(r *http.Request, matcher language.Matcher) string {
    // 1. Explicit query parameter: ?lang=ja
    if lang := r.URL.Query().Get("lang"); lang != "" {
        tag, _, _ := matcher.Match(language.Make(lang))
        return tag.String()
    }
    // 2. Cookie from previous selection
    if cookie, err := r.Cookie("lang"); err == nil {
        tag, _, _ := matcher.Match(language.Make(cookie.Value))
        return tag.String()
    }
    // 3. Accept-Language header
    accept := r.Header.Get("Accept-Language")
    if accept != "" {
        tags, _, _ := language.ParseAcceptLanguage(accept)
        if len(tags) > 0 {
            tag, _, _ := matcher.Match(tags...)
            return tag.String()
        }
    }
    return "en" // 4. Default
}

// Usage:
matcher := language.NewMatcher([]language.Tag{
    language.English, language.Japanese,
    language.German, language.Spanish,
})

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    locale := detectLocale(r, matcher)
    localizer := i18n.NewLocalizer(bundle, locale)
    // ... use localizer
})
Nagbabalik ang language.NewMatcher ng pinakamahusay na tugma mula sa inyong mga supported language, hindi ang raw na preference ng user. Kung humihiling ang user ng 'pt-BR' at 'pt' lang ang sinusuportahan ninyo, tama na ibabalik ng matcher ang 'pt'. Kung walang matcher, kakailanganin ninyo ng manual fallback logic para sa bawat regional variant.
7

Ayusin ang Per-Key Fallback gamit ang go-locale-chain

May kilalang limitasyon ang go-i18n: kapag tumugma na ang isang locale (may anumang pagsasalin na na-load), hindi na bumabagsak ang mga nawawalang key sa susunod na locale sa chain. Ang pt-BR user na may bahagyang naisaling pt-BR file ay nakakakuha ng empty string sa halip na mag-fallback sa pt-PT o pt. Inaayos ito ng go-locale-chain sa pamamagitan ng per-key fallback resolution sa 75 built-in na locale chain.

Terminal
go get github.com/i18n-agent/go-locale-chain
go-locale-chain with go-i18n
package main

import (
    "encoding/json"
    "fmt"

    "github.com/nicksnyder/go-i18n/v2/i18n"
    localechain "github.com/i18n-agent/go-locale-chain"
    "golang.org/x/text/language"
)

func main() {
    // 1. Configure fallback chains (call once at startup)
    localechain.Configure()

    // 2. Set up go-i18n bundle as usual
    bundle := i18n.NewBundle(language.English)
    bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
    bundle.MustLoadMessageFile("locales/en.json")
    bundle.MustLoadMessageFile("locales/pt.json")
    bundle.MustLoadMessageFile("locales/pt-PT.json")
    bundle.MustLoadMessageFile("locales/pt-BR.json")

    // 3. Resolve with per-key fallback
    result, _ := localechain.ResolveWithLoader("pt-BR", func(locale string) (map[string]string, error) {
        localizer := i18n.NewLocalizer(bundle, locale)
        messages := make(map[string]string)
        for _, id := range []string{"hello", "goodbye", "thanks"} {
            msg, err := localizer.Localize(&i18n.LocalizeConfig{MessageID: id})
            if err == nil {
                messages[id] = msg
            }
        }
        return messages, nil
    })

    fmt.Println(result["hello"])   // "Olá (BR)"   — from pt-BR
    fmt.Println(result["goodbye"]) // "Adeus (PT)" — fallback to pt-PT
    fmt.Println(result["thanks"])  // "Obrigado"   — fallback to pt
}
Ang go-locale-chain ay isang open-source na Go package na walang external dependency. Kinukumplemento nito ang go-i18n — gamitin ang go-i18n para sa message loading, pluralization, at template rendering, at ang go-locale-chain para sa tamang fallback chain resolution.
Standalone usage (no go-i18n)
// Standalone: zero external dependencies, works with any format
localechain.Configure()

result, _ := localechain.ResolveWithLoader("es-MX", func(locale string) (map[string]string, error) {
    data, err := os.ReadFile(fmt.Sprintf("locales/%s.json", locale))
    if err != nil {
        return nil, err // Locale file doesn't exist — skip
    }
    var msgs map[string]string
    json.Unmarshal(data, &msgs)
    return msgs, nil
})
// es-MX -> es-419 -> es: each key resolved from most specific locale
Gumamit ng ConfigureWithOverrides() upang i-customize ang mga partikular na chain habang pinananatili ang mga default. Halimbawa, pasimplehin ang pt-BR upang mag-fallback lang sa pt, o magdagdag ng chain para sa locale na wala sa mga default tulad ng sv-FI -> sv.
8

I-automate ang Mga Pagsasalin

Kapag kumpleto na ang inyong i18n setup, isalin ang inyong mga locale file gamit ang AI. Bumuo ng mga pagsasalin para sa lahat ng target language mula sa inyong English source file — direkta mula sa inyong IDE o sa CI/CD pipeline.

Terminal
# In your IDE, ask your AI assistant:
> Translate locales/en.json to German, Japanese, and Spanish

✓ locales/de.json created (1.2s)
✓ locales/ja.json created (1.5s)
✓ locales/es.json created (1.1s)

# Or use the CLI in CI/CD:
npx i18n-agent translate locales/en.json --lang de,ja,es
Isalin nang paunti-unti — kapag nagdagdag kayo ng mga bagong message ID sa inyong source file, isalin lang ang mga bagong key sa halip na i-regenerate ang lahat ng file. Napapanatili nito ang anumang na-review na ng tao na mga pagsasalin.

I-automate ang Kalidad ng Pagsasalin

Mahuli ang mga nawawalang key at sirang placeholder bago ito ma-ship gamit ang i18n-validate. Subukan ang inyong UI gamit ang pseudo-translation sa i18n-pseudo bago dumating ang mga totoong pagsasalin.

Mga Karaniwang Pagkakamali

Hindi Pagtutugma ng PluralCount at TemplateData

Pinipili ng PluralCount ang plural form ngunit hindi nito ini-inject ang value sa template. Kailangan din ninyong ipasa ang count sa TemplateData para lumabas ito sa rendered na message. Kung walang TemplateData, '{'{.Count}'}' ay ire-render bilang '<no value>'.

Nawawalang RegisterUnmarshalFunc

Tahimik na nagbabalik ang LoadMessageFile na walang message kung nakalimutan ninyong tawagin ang bundle.RegisterUnmarshalFunc() para sa file format. Laging irehistro ang json.Unmarshal (o toml/yaml) bago mag-load ng mga file.

Hindi Gumagana ang Per-Key Fallback

Tumatanggap ang NewLocalizer ng go-i18n ng maraming wika, pero kapag tumugma na ang isang locale sa kahit isang key, ang mga nawawalang key ay nagbabalik ng empty string sa halip na mag-fallback. Gumamit ng go-locale-chain para ayusin ito gamit ang tamang per-key cascade.

Syntax ng Template: {'{.Var}'} at hindi {'{Var}'}

Gumagamit ang go-i18n ng text/template syntax ng Go. Dapat may dot prefix ang mga variable: {'{.Name}'}, hindi {'{Name}'}. Tinutukoy ng tuldok ang TemplateData map. Nagdudulot ng template execution error kapag nawawala ang tuldok.

Inirerekomendang Istruktura ng File

Project Structure
my-go-app/
├── locales/
│   ├── en.json           # Source language (English)
│   ├── de.json           # German translations
│   ├── ja.json           # Japanese translations
│   ├── es.json           # Spanish translations
│   ├── pt.json           # Portuguese (base)
│   ├── pt-PT.json        # Portuguese (Portugal)
│   └── pt-BR.json        # Portuguese (Brazil)
├── i18n/
│   ├── bundle.go         # Bundle initialization
│   ├── detect.go         # Locale detection logic
│   └── middleware.go      # HTTP middleware for locale
├── main.go
├── go.mod
└── go.sum

Subukan ang i18n Agent Ngayon

I-drop dito ang inyong translation file

JSON, YAML, PO, XML, CSV, Markdown, Properties

o i-click para mag-browse

Mga target language

Hindi kailangan ang signupInstant na estimate

Locale Fallback gamit ang go-locale-chain

Kapag nawawala ang translation key sa isang regional locale tulad ng pt-BR, dumidiretso ang go-i18n sa default language sa halip na suriin muna ang parent locale na pt.

Terminal
go get github.com/i18n-agent/go-locale-chain
Configuration
import localechain "github.com/i18n-agent/go-locale-chain"

chain := localechain.New(localechain.Config{
    Fallbacks: map[string][]string{
        "pt-BR":      {"pt", "en"},
        "zh-Hant-HK": {"zh-Hant", "zh", "en"},
    },
})

Tingnan ang aming Locale Fallback Guide para sa buong listahan ng mga supported framework at 75 built-in na chain. Learn more →

FAQ sa Go i18n