Skip to main content

Panduan Lengkap Pengantarabangsaan Go

Daripada fail mesej hingga resolusi lokal yang selamat untuk goroutine: sediakan i18n dalam aplikasi Go anda dengan go-i18n, kemudian automatikkan terjemahan dengan AI.

1

Pasang go-i18n

go-i18n ialah pustaka pengantarabangsaan paling popular untuk Go. Pustaka ini menggunakan peraturan bentuk jamak CLDR, templat Go untuk interpolasi pemboleh ubah, serta menyokong fail mesej JSON, TOML, dan YAML. Anda juga memerlukan golang.org/x/text untuk pemadanan tag bahasa.

go-i18n v2 memerlukan Go 1.16+. Pakej golang.org/x/text menyediakan penghuraian dan pemadanan tag bahasa BCP 47, yang digunakan secara dalaman oleh go-i18n untuk memilih peraturan bentuk jamak.
Terminal
go get -u github.com/nicksnyder/go-i18n/v2/i18n
go get -u golang.org/x/text/language
2

Cipta Fail Mesej

Cipta satu fail JSON bagi setiap bahasa dalam direktori locales. Setiap mesej mempunyai ID dan satu atau beberapa bentuk jamak. Go-i18n menggunakan sintaks templat Go (kurungan berombak berganda dengan awalan titik) untuk interpolasi pemboleh ubah.

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."
  }
}
Gunakan ID mesej deskriptif seperti 'ItemCount' atau 'WelcomeBack', bukan laluan yang dipisahkan titik. go-i18n menggunakan ID rata, bukan kekunci bersarang. Gunakan PascalCase pada ID agar sepadan dengan konvensyen Go.
3

Muatkan Bundle

Bundle ialah daftar pusat go-i18n. Cipta satu semasa permulaan, daftarkan format fail anda, dan muatkan semua fail mesej. Bundle selamat untuk goroutine — cipta sekali dan kongsikannya merentas aplikasi anda.

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) // "こんにちは、世界!"
}
Jika anda melihat 'message not found', semak tiga perkara: 1) Fail mesej telah dimuatkan dengan LoadMessageFile atau MustLoadMessageFile. 2) Sambungan fail sepadan dengan fungsi nyahmarshal yang didaftarkan. 3) MessageID dalam LocalizeConfig sama tepat dengan kekunci dalam fail JSON anda (peka huruf besar-kecil).
4

Gunakan Localizer

Cipta Localizer bagi setiap permintaan dengan bahasa pilihan pengguna. Localizer memilih mesej daripada Bundle, mengendalikan pemaparan templat dengan enjin text/template Go, dan memilih bentuk jamak yang betul berdasarkan 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 menerima beberapa rentetan bahasa — fungsi ini mencubanya mengikut urutan. Hantar pengepala Accept-Language secara langsung: i18n.NewLocalizer(bundle, r.Header.Get("Accept-Language")). go-i18n menghuraikan pengepala dan memadankannya dengan terjemahan yang tersedia secara automatik.
5

Kendalikan Peraturan Bentuk Jamak

go-i18n melaksanakan peraturan bentuk jamak CLDR untuk semua bahasa. Bahasa Inggeris mempunyai 2 bentuk (satu, lain). Bahasa Arab mempunyai 6 (sifar, satu, dua, sedikit, banyak, lain). Bahasa Jepun mempunyai 1 (lain). Tentukan semua bentuk yang diperlukan dalam fail mesej anda — go-i18n memilih bentuk yang betul berdasarkan 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 dan TemplateData adalah berasingan. PluralCount memilih bentuk jamak, manakala TemplateData menyediakan nilai untuk pemaparan templat. Jika anda memerlukan bilangan dalam teks mesej, hantarkannya kepada kedua-duanya: PluralCount: n dan TemplateData: map[string]interface{'}'{"Count": n}.
6

Pengesanan Lokal

Dalam aplikasi web, kesan bahasa pilihan pengguna daripada beberapa sumber: parameter pertanyaan, kuki, pengepala Accept-Language, atau segmen laluan URL. Gunakan golang.org/x/text/language.Matcher untuk perundingan bahasa yang mematuhi 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 mengembalikan padanan terbaik daripada bahasa yang anda sokong, bukan pilihan mentah pengguna. Jika pengguna meminta 'pt-BR' dan anda hanya menyokong 'pt', pemadan akan mengembalikan 'pt' dengan betul. Tanpa pemadan, anda memerlukan logik sandaran manual bagi setiap varian serantau.
7

Baiki Sandaran Setiap Kekunci dengan go-locale-chain

go-i18n mempunyai batasan yang diketahui: setelah sesuatu lokal sepadan (mempunyai terjemahan yang dimuatkan), kekunci yang tiada tidak beralih kepada lokal seterusnya dalam rantaian. Pengguna pt-BR dengan fail pt-BR yang baru diterjemahkan sebahagian akan mendapat rentetan kosong dan bukannya bersandar kepada pt-PT atau pt. go-locale-chain membaikinya dengan resolusi sandaran setiap kekunci merentas 75 rantaian lokal terbina dalam.

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 ialah pakej Go sumber terbuka tanpa kebergantungan luaran. Pakej ini melengkapi go-i18n — gunakan go-i18n untuk memuatkan mesej, mengendalikan bentuk jamak, dan memaparkan templat, serta go-locale-chain untuk resolusi rantaian sandaran yang betul.
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
Gunakan ConfigureWithOverrides() untuk menyesuaikan rantaian tertentu sambil mengekalkan lalai. Contohnya, ringkaskan pt-BR supaya hanya bersandar kepada pt, atau tambahkan rantaian untuk lokal yang tiada dalam lalai seperti sv-FI -> sv.
8

Automatikkan Terjemahan

Selepas persediaan i18n selesai, terjemahkan fail lokal anda menggunakan AI. Jana terjemahan untuk semua bahasa sasaran daripada fail sumber bahasa Inggeris — secara langsung daripada IDE atau dalam saluran CI/CD anda.

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
Terjemahkan secara berperingkat — apabila anda menambahkan ID mesej baharu pada fail sumber, terjemahkan hanya kekunci baharu dan bukannya menjana semula semua fail. Cara ini mengekalkan terjemahan yang telah disemak manusia.

Automatikkan Kualiti Terjemahan

Kesan kekunci hilang dan ruang letak rosak sebelum dikeluarkan dengan i18n-validate. Uji UI dengan terjemahan pseudo menggunakan i18n-pseudo sebelum terjemahan sebenar tersedia.

Kesilapan Umum

PluralCount dan TemplateData Tidak Sepadan

PluralCount memilih bentuk jamak, tetapi tidak menyuntik nilainya ke dalam templat. Anda juga mesti menghantar bilangan dalam TemplateData agar ia muncul dalam mesej yang dipaparkan. Tanpa TemplateData, '{'{.Count}'}' dipaparkan sebagai '<no value>'.

RegisterUnmarshalFunc Tiada

LoadMessageFile secara senyap tidak mengembalikan mesej jika anda terlupa memanggil bundle.RegisterUnmarshalFunc() untuk format fail tersebut. Sentiasa daftarkan json.Unmarshal (atau toml/yaml) sebelum memuatkan fail.

Sandaran Setiap Kekunci Tidak Berfungsi

NewLocalizer milik go-i18n menerima beberapa bahasa, tetapi setelah sesuatu lokal sepadan dengan satu kekunci, kekunci yang tiada akan mengembalikan rentetan kosong dan bukannya bersandar. Gunakan go-locale-chain untuk membaikinya dengan lata setiap kekunci yang betul.

Sintaks Templat: {'{.Var}'}, Bukan {'{Var}'}

go-i18n menggunakan sintaks text/template Go. Pemboleh ubah mesti diawali titik: {'{.Name}'}, bukan {'{Name}'}. Titik tersebut merujuk kepada peta TemplateData. Tanpa titik, ralat pelaksanaan templat berlaku.

Struktur Fail yang Disyorkan

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

Cuba i18n Agent Sekarang

Lepaskan fail terjemahan anda di sini

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

atau klik untuk semak imbas

Bahasa sasaran

Tidak perlu mendaftarAnggaran serta-merta

Sandaran Lokal dengan go-locale-chain

Apabila kekunci terjemahan tiada dalam lokal serantau seperti pt-BR, go-i18n terus beralih kepada bahasa lalai dan bukannya menyemak lokal induk pt terlebih dahulu.

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"},
    },
})

Lihat Panduan Sandaran Bahasa kami untuk senarai lengkap rangka kerja yang disokong dan 75 rantaian terbina dalam. Learn more →

Soalan Lazim Go i18n