Интернационализация (i18n) в Go (Golang): Полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Интернационализация (i18n) в Go (Golang): Полное руководство для разработчиков

Интернационализация (i18n) — это процесс проектирования программного обеспечения таким образом, чтобы его можно было легко адаптировать для различных языков и регионов без внесения изменений в исходный код. В Go (Golang) для этих целей существует несколько зрелых решений, но самым популярным и стандартизированным является пакет golang.org/x/text, который предоставляет мощные инструменты для работы с локализацией. В этой статье мы подробно разберем, как настроить i18n в Go-приложении, используя официальные библиотеки и лучшие практики.

Основные библиотеки для i18n в Go

Экосистема Go предлагает несколько подходов к интернационализации. Рассмотрим ключевые из них:

  • golang.org/x/text — основной пакет от команды Go, поддерживающий Unicode, CLDR (Common Locale Data Repository) и сложные правила плюрализации.
  • github.com/nicksnyder/go-i18n — популярная сторонняя библиотека с поддержкой JSON, TOML и YAML файлов переводов, простым API и автоматическим определением языка.
  • github.com/leonelquinteros/gotext — легковесная альтернатива, работающая с форматом GNU gettext (.po/.mo файлы), идеальна для небольших проектов.

В этом руководстве мы сосредоточимся на go-i18n как на самом сбалансированном решении для веб-приложений, но концепции применимы к любой библиотеке.

Установка и настройка go-i18n

Для начала установите библиотеку и CLI-инструмент для работы с переводами:

go get github.com/nicksnyder/go-i18n/v2/i18n
go install github.com/nicksnyder/go-i18n/v2/goi18n@latest

Создайте структуру проекта:

myapp/
├── active.en.json
├── active.ru.json
├── main.go
└── go.mod

Создание файлов переводов

Библиотека использует JSON-файлы с переводами. Пример для английского и русского языков:

active.en.json

{
  "greeting": {
    "other": "Hello, {{.Name}}!"
  },
  "cakes_count": {
    "one": "You have {{.Count}} cake.",
    "few": "You have {{.Count}} cakes.",
    "many": "You have {{.Count}} cakes.",
    "other": "You have {{.Count}} cakes."
  }
}

active.ru.json

{
  "greeting": {
    "other": "Привет, {{.Name}}!"
  },
  "cakes_count": {
    "one": "У вас {{.Count}} пирожное.",
    "few": "У вас {{.Count}} пирожных.",
    "many": "У вас {{.Count}} пирожных.",
    "other": "У вас {{.Count}} пирожных."
  }
}

Обратите внимание на использование правил плюрализации: one, few, many и other. В русском языке существуют 4 формы, в то время как в английском — только 2 (one/other). Библиотека автоматически выбирает правильную форму на основе числа.

Пример использования в коде

Теперь напишем код, который загружает переводы и отображает локализованные сообщения:

package main

import (
    "fmt"
    "log"

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

func main() {
    // Создаем бандл с языковыми файлами
    bundle := i18n.NewBundle(language.English)
    bundle.RegisterUnmarshalFunc("json", json.Unmarshal)

    // Загружаем файлы переводов
    _, err := bundle.LoadMessageFile("active.en.json")
    if err != nil {
        log.Fatal(err)
    }
    _, err = bundle.LoadMessageFile("active.ru.json")
    if err != nil {
        log.Fatal(err)
    }

    // Создаем локализатор для русского языка
    localizer := i18n.NewLocalizer(bundle, "ru")

    // Пример 1: Простое приветствие
    greeting, err := localizer.Localize(&i18n.LocalizeConfig{
        MessageID: "greeting",
        TemplateData: map[string]string{
            "Name": "Алексей",
        },
    })
    if err == nil {
        fmt.Println(greeting) // Вывод: Привет, Алексей!
    }

    // Пример 2: Счет с плюрализацией
    for _, count := range []int{1, 2, 5, 21} {
        message, err := localizer.Localize(&i18n.LocalizeConfig{
            MessageID: "cakes_count",
            PluralCount: count,
            TemplateData: map[string]interface{}{
                "Count": count                    

Рекомендаций