Skip to main content

Täydellinen opas Go:n kansainvälistämiseen

Sanomatiedostoista goroutine-turvalliseen kieliversion ratkaisuun: ota i18n käyttöön Go-sovelluksessasi go-i18n:llä ja automatisoi sitten käännökset tekoälyllä.

1

Asenna go-i18n

go-i18n on Go:n suosituin kansainvälistämiskirjasto. Se käyttää CLDR-monikkosääntöjä, Go-malleja muuttujien interpolointiin ja tukee JSON-, TOML- ja YAML-sanomatiedostoja. Tarvitset lisäksi golang.org/x/text-paketin kielitunnisteiden täsmäykseen.

go-i18n v2 vaatii Go-version 1.16+. golang.org/x/text-paketti jäsentää ja täsmää BCP 47 -kielitunnisteet, ja go-i18n käyttää sitä sisäisesti monikkosäännön valintaan.
Terminal
go get -u github.com/nicksnyder/go-i18n/v2/i18n
go get -u golang.org/x/text/language
2

Luo sanomatiedostot

Luo locales-hakemistoon yksi JSON-tiedosto kieltä kohden. Jokaisella sanomalla on tunniste ja yksi tai useampi monikkomuoto. Go-i18n käyttää muuttujien interpolointiin Go-mallisyntaksia, eli kaksinkertaisia aaltosulkeita ja piste-etuliitettä.

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."
  }
}
Käytä pisteillä erotettujen polkujen sijaan kuvaavia sanomatunnisteita, kuten 'ItemCount' tai 'WelcomeBack'. go-i18n käyttää litteitä tunnisteita, ei sisäkkäisiä avaimia. Pidä tunnisteet Go:n käytäntöjen mukaisesti PascalCase-muodossa.
3

Lataa Bundle

Bundle on go-i18n:n keskusrekisteri. Luo se kerran käynnistyksen yhteydessä, rekisteröi tiedostomuotosi ja lataa kaikki sanomatiedostot. Bundle on goroutine-turvallinen — luo se kerran ja jaa se koko sovellukselle.

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) // "こんにちは、世界!"
}
Jos näet 'message not found' -virheen, tarkista kolme asiaa: 1) Sanomatiedosto ladattiin LoadMessageFile- tai MustLoadMessageFile-funktiolla. 2) Tiedostopääte vastaa rekisteröityä jäsentämisfunktiota. 3) LocalizeConfigin MessageID vastaa JSON-tiedoston avainta täsmälleen kirjainkoko mukaan lukien.
4

Käytä Localizeria

Luo jokaiselle pyynnölle Localizer käyttäjän ensisijaisella kielellä. Localizer ratkaisee sanomat Bundlesta, käsittelee mallien hahmontamisen Go:n text/template-moottorilla ja valitsee oikean monikkomuodon PluralCount-arvon perusteella.

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))
}
NewLocalizer hyväksyy useita kielimerkkijonoja ja kokeilee niitä järjestyksessä. Välitä Accept-Language-otsake suoraan: i18n.NewLocalizer(bundle, r.Header.Get("Accept-Language")). go-i18n jäsentää otsakkeen ja täsmää saatavilla olevat käännökset automaattisesti.
5

Käsittele monikkosäännöt

go-i18n toteuttaa CLDR-monikkosäännöt kaikille kielille. Englannissa on kaksi muotoa (one, other), arabiassa kuusi (zero, one, two, few, many, other) ja japanissa yksi (other). Määritä sanomatiedostoissasi kaikki tarvittavat muodot, niin go-i18n valitsee PluralCount-arvon perusteella oikean.

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: "عنصر واحد"
PluralCount ja TemplateData ovat erillisiä. PluralCount valitsee monikkomuodon ja TemplateData antaa arvot mallin hahmontamiseen. Jos tarvitset määrän sanomatekstiin, välitä se molemmissa: PluralCount: n ja TemplateData: map[string]interface{'}'{"Count": n}.
6

Kieliversion tunnistus

Tunnista verkkosovelluksissa käyttäjän ensisijainen kieli useista lähteistä: kyselyparametreista, evästeistä, Accept-Language-otsakkeesta tai URL-polun segmenteistä. Käytä BCP 47 -yhteensopivaan kielineuvotteluun golang.org/x/text/language.Matcheria.

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
})
language.NewMatcher palauttaa tuetuista kielistä parhaan vastineen, ei käyttäjän käsittelemätöntä asetusta. Jos käyttäjä pyytää pt-BR:ää ja tuet vain pt:tä, matcher palauttaa oikein pt:n. Ilman matcheria tarvitsisit manuaalisen varakielilogiikan jokaiselle alueelliselle muodolle.
7

Korjaa avainkohtainen varakieli go-locale-chain:illa

go-i18n:ssä on tunnettu rajoitus: kun kieliversio vastaa eli siinä on joitakin käännöksiä ladattuna, puuttuvat avaimet eivät siirry ketjun seuraavaan kieliversioon. Osittain käännettyä pt-BR-tiedostoa käyttävä pt-BR-käyttäjä saa tyhjiä merkkijonoja pt-PT:hen tai pt:hen siirtymisen sijaan. go-locale-chain korjaa tämän ratkaisemalla avainkohtaiset varakielet 75 sisäänrakennetussa kieliversioketjussa.

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
}
go-locale-chain on avoimen lähdekoodin Go-paketti ilman ulkoisia riippuvuuksia. Se täydentää go-i18n:ää — käytä go-i18n:ää sanomien lataamiseen, monikkomuotoihin ja mallien hahmontamiseen ja go-locale-chain:ia varakieliketjujen oikeaan ratkaisuun.
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
Mukauta tiettyjä ketjuja ja säilytä oletukset ConfigureWithOverrides()-funktiolla. Voit esimerkiksi yksinkertaistaa pt-BR-ketjun siirtymään vain pt:hen tai lisätä oletuksista puuttuvalle kieliversiolle ketjun, kuten sv-FI → sv.
8

Automatisoi käännökset

Kun i18n on otettu käyttöön, käännä kieliversiotiedostosi tekoälyllä. Luo käännökset kaikille kohdekielille englanninkielisestä lähdetiedostosta suoraan IDE-ympäristössäsi tai CI/CD-putkessasi.

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
Käännä vaiheittain — kun lisäät lähdetiedostoon uusia sanomatunnisteita, käännä vain uudet avaimet äläkä luo kaikkia tiedostoja uudelleen. Näin ihmisten tarkistamat käännökset säilyvät.

Automatisoi käännöslaatu

Löydä puuttuvat avaimet ja rikkoutuneet paikkamerkit i18n-validate:lla ennen julkaisua. Testaa käyttöliittymää pseudokäännöksillä i18n-pseudo:n avulla ennen oikeiden käännösten valmistumista.

Tavalliset sudenkuopat

PluralCount ja TemplateData eivät vastaa toisiaan

PluralCount valitsee monikkomuodon mutta ei injektoi arvoa malliin. Määrä on välitettävä myös TemplateDatassa, jotta se näkyy hahmonnetussa sanomassa. Ilman TemplateDataa '{'{.Count}'}' hahmontuu muodossa '<no value>'.

RegisterUnmarshalFunc puuttuu

LoadMessageFile ei palauta huomaamatta sanomia, jos unohdat kutsua tiedostomuodon bundle.RegisterUnmarshalFunc()-funktiota. Rekisteröi aina json.Unmarshal tai toml/yaml ennen tiedostojen lataamista.

Avainkohtainen varakieli ei toimi

go-i18n:n NewLocalizer hyväksyy useita kieliä, mutta kun kieliversio vastaa yhteen avaimeen, puuttuvat avaimet palauttavat tyhjiä merkkijonoja siirtymisen sijaan. Korjaa tämä oikealla avainkohtaisella ketjutuksella go-locale-chain:in avulla.

Mallisyntaksi: {'{.Var}'}, ei {'{Var}'}

go-i18n käyttää Go:n text/template-syntaksia. Muuttujilla on oltava piste-etuliite: {'{.Name}'}, ei {'{Name}'}. Piste viittaa TemplateData-karttaan. Puuttuva piste aiheuttaa mallin suoritusvirheen.

Suositeltu tiedostorakenne

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

Kokeile i18n Agent:ia nyt

Pudota käännöstiedostosi tähän

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

tai valitse napsauttamalla

Kohdekielet

Rekisteröitymistä ei tarvitaVälitön arvio

Varakieliketju go-locale-chain:illa

Kun alueellisesta kieliversiosta, kuten pt-BR:stä, puuttuu käännösavain, go-i18n siirtyy suoraan oletuskieleen eikä tarkista ensin pääkieliversiota 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"},
    },
})

Katso varakielioppaastamme kaikki tuetut ohjelmistokehykset ja 75 sisäänrakennettua ketjua. Learn more →

Usein kysyttyä Go i18n:stä