Internationalization (i18n)

Statigo provides built-in internationalization support with JSON-based translations and multi-language routing.

Translation Files

Translations are stored as JSON in the translations/ directory:

translations/en.json:

{
  "nav": {
    "home": "Home",
    "about": "About",
    "contact": "Contact"
  },
  "pages": {
    "home": {
      "title": "Welcome",
      "subtitle": "A fast web framework"
    },
    "about": {
      "title": "About Us",
      "description": "Learn more about our company"
    }
  }
}

translations/tr.json:

{
  "nav": {
    "home": "Anasayfa",
    "about": "Hakkında",
    "contact": "İletişim"
  },
  "pages": {
    "home": {
      "title": "Hoş Geldiniz",
      "subtitle": "Hızlı bir web framework"
    },
    "about": {
      "title": "Hakkımızda",
      "description": "Şirketimiz hakkında daha fazla bilgi edinin"
    }
  }
}

Initialization

import "statigo/framework/i18n"

i18nInstance, err := i18n.New(translationsFS, "en")
if err != nil {
    log.Fatal(err)
}

Parameters:

  • fs.FS - Filesystem containing translation files
  • defaultLang - Default language code (e.g., "en")

Using Translations in Go

Get String Value

title := i18nInstance.Get("tr", "pages.home.title")
// Returns: "Hoş Geldiniz"

Get Raw Value (Any Type)

data := i18nInstance.GetRaw("en", "pages.home")
// Returns: map[string]interface{}{"title": "Welcome", "subtitle": "..."}

Get with Fallback

value := i18nInstance.GetWithFallback("fr", "pages.home.title", "en")
// Falls back to "en" if "fr" translation doesn't exist

Using Translations in Templates

Basic Translation

<h1>{{t "pages.home.title"}}</h1>

Nested Keys

<nav>
  <a href="/">{{t "nav.home"}}</a>
  <a href="/about">{{t "nav.about"}}</a>
</nav>

With Language Context

The t function automatically uses the current language from context:

<p>{{t "pages.home.description"}}</p>

Language Detection

Statigo detects language in this priority order:

  1. URL Path - /en/ or /tr/ prefix
  2. Cookie - lang cookie value
  3. Accept-Language Header - Browser preferences
  4. Default - Configured default language

Language Middleware

import "statigo/framework/middleware"

langConfig := middleware.LanguageConfig{
    SupportedLanguages: []string{"en", "tr"},
    DefaultLanguage:    "en",
    SkipPaths:          []string{"/robots.txt", "/sitemap.xml"},
    SkipPrefixes:       []string{"/static/", "/health/"},
}
r.Use(middleware.Language(i18nInstance, langConfig))

Accessing Current Language

In Handlers

import "statigo/framework/middleware"

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    lang := middleware.GetLanguage(r.Context())
    // lang is "en", "tr", etc.
}

In Templates

<p>Current language: {{.Lang}}</p>

<a href="{{localePath "/about" .Lang}}">About</a>

Adding a New Language

  1. Create translation file:

translations/de.json:

{
  "nav": {
    "home": "Startseite",
    "about": "Über uns"
  }
}
  1. Add to supported languages:
languages := []string{"en", "tr", "de"}
routeRegistry := router.NewRegistry(languages)
  1. Add routes in routes.json:
{
  "canonical": "/about",
  "paths": {
    "en": "/en/about",
    "tr": "/tr/hakkinda",
    "de": "/de/ueber-uns"
  }
}

Translation Best Practices

  1. Use dot notation for nested keys

    {
      "pages": {
        "home": {
          "title": "Home"
        }
      }
    }
    
  2. Group related translations together

    {
      "nav": {...},
      "pages": {...},
      "errors": {...}
    }
    
  3. Use descriptive keys rather than complete sentences

    {
      "form": {
        "email_label": "Email Address",
        "email_error": "Please enter a valid email"
      }
    }
    
  4. Keep translations synchronized across all languages

  5. Provide fallbacks for missing translations

Pluralization

For pluralization, use object syntax:

{
  "items": {
    "zero": "No items",
    "one": "1 item",
    "other": "{{.Count}} items"
  }
}

Then in Go:

count := len(items)
key := "items.zero"
if count == 1 {
    key = "items.one"
} else if count > 1 {
    key = "items.other"
}
text := i18nInstance.Get(lang, key)

Date/Time Localization

Use the formatDate and formatDateTime template functions:

<p>{{formatDate .Date "2006-01-02"}}</p>
<p>{{formatDateTime .Date "2006-01-02T15:04:05Z"}}</p>

For language-specific formats, create translation keys:

{
  "dates": {
    "short": "Jan 2, 2006",
    "long": "January 2, 2006"
  }
}