Skip to main content

Cjelovit vodič za internacionalizaciju u jeziku Go

Od datoteka poruka do razrješavanja jezika sigurnog za rad u gorutinama: postavite i18n u Go aplikaciji pomoću go-i18n, a zatim automatizirajte prijevode pomoću AI-ja.

1

Instalirajte go-i18n

go-i18n je najpopularnija knjižnica za internacionalizaciju u jeziku Go. Koristi CLDR pravila množine, Go predloške za interpolaciju varijabli i podržava JSON, TOML i YAML datoteke poruka. Potreban Vam je i paket golang.org/x/text za podudaranje jezičnih oznaka.

go-i18n v2 zahtijeva Go 1.16+. Paket golang.org/x/text omogućuje raščlanjivanje i podudaranje jezičnih oznaka prema standardu BCP 47, što go-i18n interno koristi za odabir pravila množine.
Terminal
go get -u github.com/nicksnyder/go-i18n/v2/i18n
go get -u golang.org/x/text/language
2

Izradite datoteke poruka

Izradite po jednu JSON datoteku za svaki jezik u mapi locales. Svaka poruka ima ID i jedan ili više oblika množine. go-i18n koristi sintaksu Go predloška (dvostruke vitičaste zagrade s prefiksom točke) za interpolaciju varijabli.

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."
  }
}
Upotrebljavajte opisne identifikatore poruka kao što su 'ItemCount' ili 'WelcomeBack' umjesto putanja razdvojenih točkama. go-i18n upotrebljava jednostavne identifikatore, a ne ugniježđene ključeve. Pišite identifikatore u obliku PascalCase kako biste slijedili konvencije jezika Go.
3

Učitajte Bundle

Bundle je središnji registar knjižnice go-i18n. Izradite ga pri pokretanju, registrirajte format datoteke i učitajte sve datoteke poruka. Bundle je siguran za rad u gorutinama — izradite ga samo jednom i dijelite ga u cijeloj aplikaciji.

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) // "こんにちは、世界!"
}
Ako vidite 'message not found', provjerite tri stvari: 1) datoteka poruka učitana je pomoću LoadMessageFile ili MustLoadMessageFile; 2) nastavak datoteke odgovara registriranoj funkciji za raščlanjivanje; 3) MessageID u LocalizeConfig potpuno odgovara ključu u JSON datoteci (uz razlikovanje velikih i malih slova).
4

Upotrijebite Localizer

Izradite Localizer za svaki zahtjev prema željenom korisnikovu jeziku. Localizer razrješava poruke iz objekta Bundle, obrađuje prikaz predloška pomoću mehanizma text/template jezika Go i bira ispravan oblik množine na temelju vrijednosti 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))
}
NewLocalizer prihvaća više jezičnih oznaka — isprobava ih redom. Izravno proslijedite zaglavlje Accept-Language: i18n.NewLocalizer(bundle, r.Header.Get("Accept-Language")). go-i18n raščlanjuje zaglavlje i automatski ga podudara s dostupnim prijevodima.
5

Obradite pravila množine

go-i18n implementira CLDR pravila množine za sve jezike. Engleski ima 2 oblika (one, other). Arapski ima 6 (zero, one, two, few, many, other). Japanski ima 1 (other). Definirajte sve potrebne oblike u datotekama poruka — go-i18n bira ispravan oblik na temelju vrijednosti 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: "عنصر واحد"
PluralCount i TemplateData su odvojeni. PluralCount bira oblik množine, a TemplateData pruža vrijednosti za prikazivanje predloška. Ako Vam je broj potreban u tekstu poruke, proslijedite ga u oba: PluralCount: n i TemplateData: map[string]interface{'}'{"Count": n}.
6

Prepoznavanje jezika

U web-aplikacijama prepoznajte željeni korisnikov jezik iz više izvora: parametara upita, kolačića, zaglavlja Accept-Language ili segmenata URL putanje. Upotrijebite golang.org/x/text/language.Matcher za odabir jezika usklađen sa standardom BCP 47.

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 vraća najbolje podudaranje među podržanim jezicima, a ne izvornu korisnikovu postavku. Ako korisnik zatraži 'pt-BR', a podržavate samo 'pt', funkcija ispravno vraća 'pt'. Bez funkcije za podudaranje bila bi Vam potrebna ručna logika pričuvnog odabira za svaku regionalnu inačicu.
7

Ispravite pričuvni odabir za svaki ključ pomoću go-locale-chain

go-i18n ima poznato ograničenje: nakon što pronađe podudarnu jezičnu inačicu (s barem jednim učitanim prijevodom), za ključeve koji nedostaju ne nastavlja pretraživati sljedeću inačicu u lancu. Korisniku s oznakom pt-BR i djelomično prevedenom datotekom pt-BR prikazuju se prazni tekstni nizovi umjesto vrijednosti iz pt-PT ili pt. go-locale-chain to ispravlja pričuvnim razrješavanjem svakog ključa u 75 ugrađenih jezičnih lanaca.

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 je paket za Go otvorenog izvornog koda bez vanjskih ovisnosti. Dopunjuje go-i18n — upotrebljavajte go-i18n za učitavanje poruka, oblike množine i prikaz predloška, a go-locale-chain za pravilno razrješavanje pričuvnih lanaca.
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
Upotrijebite ConfigureWithOverrides() kako biste prilagodili određene lance i zadržali zadane vrijednosti. Primjerice, pojednostavnite pt-BR tako da prelazi samo na pt ili dodajte lanac za jezičnu inačicu koja nije obuhvaćena zadanim vrijednostima, kao što je sv-FI -> sv.
8

Automatizirajte prijevode

Kada postavite i18n sustav, prevedite lokalizacijske datoteke pomoću AI-ja. Generirajte prijevode za sve ciljne jezike iz engleske izvorne datoteke — izravno u IDE-u ili u CI/CD procesu.

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
Prevodite postupno — kada dodate nove identifikatore poruka u izvornu datoteku, prevedite samo nove ključeve umjesto ponovnog generiranja svih datoteka. Time se čuvaju prijevodi koje su ljudi pregledali.

Automatizirajte provjeru kvalitete prijevoda

Alatom i18n-validate otkrijte ključeve koji nedostaju i neispravna rezervirana mjesta prije isporuke. Korisničko sučelje testirajte pseudoprijevodima iz alata i18n-pseudo prije nego što stignu stvarni prijevodi.

Uobičajene zamke

Neslaganje vrijednosti PluralCount i TemplateData

PluralCount bira oblik množine, ali ne umeće vrijednost u predložak. Broj morate proslijediti i u TemplateData kako bi se pojavio u prikazanoj poruci. Bez TemplateData, '{'{.Count}'}' prikazuje se kao '<no value>'.

Nedostaje RegisterUnmarshalFunc

LoadMessageFile neprimjetno ne vraća nijednu poruku ako zaboravite pozvati bundle.RegisterUnmarshalFunc() za format datoteke. Uvijek registrirajte json.Unmarshal (ili toml/yaml) prije učitavanja datoteka.

Pričuvni odabir za svaki ključ ne radi

NewLocalizer iz sustava go-i18n prihvaća više jezika, ali nakon što se jezična inačica podudari s jednim ključem, za ključeve koji nedostaju vraća prazne tekstne nizove umjesto pričuvnih vrijednosti. Upotrijebite go-locale-chain kako biste to ispravili pravilnim nadovezivanjem za svaki ključ.

Sintaksa predloška: {'{.Var}'}, a ne {'{Var}'}

go-i18n upotrebljava sintaksu text/template jezika Go. Varijable moraju imati točku kao prefiks: {'{.Name}'}, a ne {'{Name}'}. Točka upućuje na mapu TemplateData. Bez točke dolazi do pogreške pri izvršavanju predloška.

Preporučena struktura datoteka

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

Isprobajte i18n Agent odmah

Povucite datoteku za prijevod ovdje

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

ili kliknite za odabir

Ciljni jezici

Registracija nije potrebnaProcjena odmah

Pričuvni odabir jezika uz go-locale-chain

Kada ključ prijevoda nedostaje u regionalnoj jezičnoj inačici kao što je pt-BR, go-i18n odmah prelazi na zadani jezik umjesto da prvo provjeri nadređenu jezičnu oznaku 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"},
    },
})

U našem vodiču za pričuvni odabir jezika pogledajte cjelovit popis podržanih radnih okvira i 75 ugrađenih lanaca. Learn more →

Česta pitanja o Go i18n sustavu