Загрузка данных
package i18n
import (
"embed"
"encoding/json"
"fmt"
"sync"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/text/language"
)
//go:embed translations/*.json
var translationFS embed.FS
// Locale represents supported locales
type Locale string
const (
// LocaleEN represents English locale
LocaleEN Locale = "en"
// LocaleRU represents Russian locale
LocaleRU Locale = "ru"
)
// DefaultLocale is the default locale used when none is specified
const DefaultLocale = LocaleEN
// MessageKey represents a translatable message identifier
type MessageKey string
// Message keys for all user-facing messages
const (
// Error messages
MsgCompanyAlreadyExists MessageKey = "company_already_exists"
MsgUserPowersNotConfirmed MessageKey = "user_powers_not_confirmed"
MsgNoMCHDFilesProvided MessageKey = "no_mchd_files_provided"
MsgNoSignedFileProvided MessageKey = "no_signed_file_provided"
MsgFailedToCreateCompany MessageKey = "failed_to_create_company"
MsgMCHDValidationFailed MessageKey = "mchd_validation_failed"
MsgRegulationsValidationFailed MessageKey = "regulations_validation_failed"
MsgRegulationsSignerMismatch MessageKey = "regulations_signer_mismatch"
MsgModeratorTaskFailed MessageKey = "moderator_task_failed"
MsgInvalidTaxID MessageKey = "invalid_tax_id"
MsgUnknownStep MessageKey = "unknown_step"
MsgUnknownAction MessageKey = "unknown_action"
MsgActionFailed MessageKey = "action_failed"
MsgFailedToDetermineNextStep MessageKey = "failed_to_determine_next_step"
// Notification messages
MsgVerificationStartedSubject MessageKey = "verification_started_subject"
MsgVerificationStartedBody MessageKey = "verification_started_body"
)
var (
bundle *i18n.Bundle
localizers map[Locale]*i18n.Localizer
initOnce sync.Once
)
// supportedLocales maps our Locale type to golang.org/x/text/language tags
var supportedLocales = map[Locale]language.Tag{
LocaleEN: language.English,
LocaleRU: language.Russian,
}
// initialize loads all translation files and creates localizers
func initialize() {
initOnce.Do(func() {
bundle = i18n.NewBundle(language.English)
bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
// Load translation files derived from supportedLocales
for locale := range supportedLocales {
file := fmt.Sprintf("translations/active.%s.json", locale)
// Embedded files should always load successfully; panic if not
if _, err := bundle.LoadMessageFileFS(translationFS, file); err != nil {
panic(fmt.Sprintf("failed to load %s: %v", file, err))
}
}
// Create localizers for each supported locale
localizers = make(map[Locale]*i18n.Localizer)
for locale, tag := range supportedLocales {
localizers[locale] = i18n.NewLocalizer(bundle, tag.String())
}
})
}
// getLocalizer returns the localizer for the given locale with fallback to default
func getLocalizer(locale Locale) *i18n.Localizer {
initialize()
if locale == "" {
locale = DefaultLocale
}
if loc, ok := localizers[locale]; ok {
return loc
}
return localizers[DefaultLocale]
}
// GetMessage returns a translated message for the given key and locale.
// If the locale or key is not found, it falls back to the default locale.
func GetMessage(locale Locale, key MessageKey) string {
return GetMessageWithData(locale, key, nil)
}
// GetMessageWithData returns a translated message with template data.
// Template data is a map that will be used to substitute placeholders in the message.
// For example: {"CompanyName": "Acme Corp"} will replace {{.CompanyName}} in the message.
func GetMessageWithData(locale Locale, key MessageKey, data map[string]interface{}) string {
localizer := getLocalizer(locale)
if localizer == nil {
return string(key)
}
msg, err := localizer.Localize(&i18n.LocalizeConfig{
MessageID: string(key),
TemplateData: data,
})
if err != nil {
return string(key)
}
return msg
}
// IsValidLocale checks if the given locale is supported
func IsValidLocale(locale Locale) bool {
_, ok := supportedLocales[locale]
return ok
}