Skip to content

Internationalization

Oleg Ivanchenko edited this page Oct 18, 2026 · 2 revisions

Internationalization (i18n)

oCMS includes a comprehensive internationalization system for the admin interface, modules, and themes.

Overview

The i18n system supports:

  • Admin interface translations
  • Module-embedded translations
  • Theme-level translation overrides
  • Multiple languages (English, Russian by default)
  • JSON Schema validation for translation files

Translation File Format

{
    "$schema": "../../../../.schema/i18n-schema.json",
    "language": "en",
    "messages": [
        {
            "id": "module.key",
            "message": "Original text (English)",
            "translation": "Translated text"
        }
    ]
}

Fields

Field Required Description
$schema No Path to JSON schema for validation
language Yes ISO 639-1 language code
messages Yes Array of translation entries
messages[].id Yes Unique identifier using dot notation
messages[].message No Original text (for reference)
messages[].translation Yes Translated text

Naming Conventions

Translation IDs use dot notation: {namespace}.{category}.{key}

Examples:

  • hcaptcha.title — Module title
  • analytics_ext.ga4_measurement_id — Form field label
  • nav.dashboard — Navigation item
  • frontend.read_more — Frontend string

Core Translations

Located in internal/i18n/locales/:

internal/i18n/locales/
├── en/messages.json
└── ru/messages.json

Module Translations

Modules embed their own translations. See Module System for details.

modules/mymodule/
├── module.go
└── locales/
    ├── en/messages.json
    └── ru/messages.json

Embed and expose via TranslationsFS():

//go:embed locales
var localesFS embed.FS

func (m *Module) TranslationsFS() embed.FS {
    return localesFS
}

Theme Translations

Themes can override global translations for frontend strings. See Theme System for details.

custom/themes/mytheme/
└── locales/
    ├── en/messages.json
    └── ru/messages.json

TTheme vs T

Function Use Case Fallback
TTheme Theme templates (frontend) Theme → Global
T Admin templates, modules Global only
<!-- Theme template -->
<a href="{{.URL}}">{{TTheme .LangCode "frontend.read_more"}}</a>

<!-- Admin template -->
<h1>{{T .AdminLang "mymodule.title"}}</h1>

Using Translations in Go Code

import "github.com/olegiv/ocms-go/internal/i18n"

message := i18n.T(lang, "mymodule.success_save")

Adding a New Language

  1. Create language directories in core and each module:

    mkdir -p internal/i18n/locales/de
    mkdir -p modules/hcaptcha/locales/de
  2. Copy English files as templates and translate

  3. Update the language field in each file

  4. Add the language code to SupportedLanguages in internal/i18n/i18n.go and rebuild; translations for a code not listed there are never loaded

  5. Register the language in the database (Admin > Languages) so that it is active and appears in the admin language selector

JSON Schema Validation

The project includes a JSON schema at .schema/i18n-schema.json.

VS Code Setup

Add to .vscode/settings.json:

{
    "json.schemas": [
        {
            "fileMatch": ["**/locales/*/messages.json"],
            "url": "./.schema/i18n-schema.json"
        }
    ]
}

Best Practices

  • Use lowercase with dots as separators for IDs
  • Start with module/namespace name
  • Group related translations (module.error_*, module.success_*, etc.)
  • Keep translations concise
  • Consider text expansion for longer languages
  • Use placeholders for dynamic content: "Welcome, %s"
  • Keep message order consistent across languages

Supported Languages

Code Language
en English
ru Russian

See Multi-Language for content translation (as opposed to UI translation).

Clone this wiki locally