Languages — Reference
The Languages surface is the locale-registration plane for an SGEN site. It owns the catalog of language locales the site supports — locale codes, display names, fallback chain, default-locale designation, right-to-left flag, and the per-locale enabled-on-storefront flag. Anything that decides which language to render, which fallback to follow when a string is missing, or which direction to lay out the page traces back to a record managed here.
This page is a reference for platform engineers and integrators who need to understand the surface before extending it, scripting against it, or scoping a localization model. Customer-facing how-tos live in the customer docs set; this page describes the shape of the surface, not the steps to drive it.
This surface is distinct from Translations. Languages registers the locales the site supports — the menu of languages the storefront can switch into, the default for new visitors, and the fallback chain when a string in the active locale is missing. Translations holds the actual translated strings per locale. A locale must be registered here before a translation can be authored against it.
Overview
Languages lives under the Settings module in SG-Admin, in the localization group. The module renders three primary views — the locale list, the locale detail / edit form, and the fallback-chain editor — and exposes a small set of write operations for register, unregister, edit fallback chain, set default locale, and toggle storefront-enabled.
The module is paired by convention: one half renders the views and prepares the catalog data, the other half handles writes and returns AJAX responses. Engineers reading the SG-Admin source will see this split across two controller files; the reference below describes the combined surface as it appears to a calling integration.
A locale identifier is a tuple of a language code and an optional region code — en, en-PH, fr-CA, pt-BR. The Languages surface accepts both bare-language and language-region forms. Region codes resolve against the Countries catalog when present; bare-language locales bypass the country reference.
Where it lives in SG-Admin:
- Sidebar: SG-Admin → Settings → Localization → Languages
- URL prefix:
/sg-admin/languages/ - View templates:
application/views/Admin/Settings/Languages/
┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Settings → Localization → Languages [ + Register ] │├──────────────────────────────────────────────────────────────────────┤│ Locale Display name Direction Fallback chain Storefront││ ─────── ─────────────── ───────── ────────────────── ──────────││ en English (default) LTR — ✔ enabled││ en-PH English (PH) LTR en-PH → en ✔ enabled││ tl Tagalog LTR tl → en ✔ enabled││ fr Français LTR fr → en ✔ enabled││ ar العربية RTL ar → en — paused ││ zh-Hant 繁體中文 LTR zh-Hant → zh → en ✔ enabled││ ││ Registered: 6 · Default: en · RTL enabled: 1 ││ [ Edit ] [ Edit fallback ] [ Set as default ] │└──────────────────────────────────────────────────────────────────────┘Actions
The Languages surface exposes the following operations. Each is described by what it does to the data, not by its internal method name.
List and filter
Returns the registered-locale catalog paginated, with locale code, display name, text direction (LTR or RTL), default-locale flag, storefront-enabled flag, and a fallback-chain summary. Supports filter by enabled state, by direction, and by free-text on display name. The default locale is pinned to the top of the list regardless of sort.
View locale
Returns the full record for a single locale — locale code, display name, text direction, default flag, enabled flag, fallback chain (ordered list of locales to consult when a string is missing in this locale), country binding (if a region code is present), and the translation-completeness summary computed against the Translations surface.
Register locale
Opens an empty registration form. Required fields at minimum: locale code, display name, text direction. Optional fields cover initial fallback chain, country binding (auto-suggested when a region code is supplied), and the enabled flag. On submit, the surface validates the locale code against the BCP-47 grammar, validates uniqueness, persists the record, and returns the new identifier.
Edit locale
Loads the locale record into the registration form, pre-populated. Submit replaces the stored locale metadata with the posted values. The locale code itself is read-only after registration — to rename a locale, unregister and re-register (which forfeits the translation completeness state).
Edit fallback chain
Opens a dedicated reorderable editor for the fallback chain. Each step is a locale that already exists in the catalog. The chain terminates implicitly at the default locale — even an empty chain falls back to default. Cycles are rejected at write time (a chain cannot reference itself directly or transitively).
Set default locale
Designates a registered locale as the site default. The default locale is the terminal fallback for every other locale and the locale a visitor sees on first arrival when no preference is captured. Exactly one locale carries the default flag. Setting a new default clears the flag on the previous default.
Toggle storefront enabled
Dedicated toggle that flips the enabled flag. A disabled locale does not appear in the storefront language selector but remains queryable in admin views and remains attached to historical translations. The default locale cannot be disabled — the surface returns a structured rejection.
Unregister locale
Removes a locale from the catalog. The translation strings attached to the locale are not deleted — they remain in the Translations store, orphaned, until cleaned up separately. The default locale cannot be unregistered; rotate the default first.
Engineering note. Unregistering a locale that other locales fall back to is permitted — the fallback chains rewriting is automatic, with each chain rewritten to skip the unregistered step. The Activity Log captures the chain rewrites as part of the unregister event.
Data model
A locale record carries the following fields. Field names below are the conceptual shape — the on-disk column names match closely but are not contractually stable across releases.
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. Stable across edits. |
code | string | BCP-47 locale identifier. Unique. Read-only after registration. |
language_code | string | The language half of the locale code (en, tl, fr). |
region_code | string | The region half of the locale code, if present (PH, CA, BR). Optional. |
display_name | string | Operator-facing display name (also surfaced in storefront selector). |
direction | enum | ltr or rtl. |
is_default | boolean | Exactly one locale carries true. |
enabled | boolean | Whether the locale appears in the storefront language selector. |
country_id | integer | Foreign key into Countries when region code is present. Null otherwise. |
fallback_chain | json | Ordered list of locale codes. Empty means fall back directly to default. |
created_at | timestamp | Set on register, immutable. |
updated_at | timestamp | Touched on any edit. |
fallback_chain in order, returning the first hit. If the chain is exhausted, it consults the default locale. If the default locale also misses, the storefront renders the message key itself (so a missing translation is visible in operator review rather than rendering as empty).Right-to-left rule: the direction flag is read by the storefront layout engine at render time. Switching a locale to RTL automatically applies the RTL layout template to pages rendered in that locale — no per-page edit is required.
Country binding: when a locale carries a region code, the surface auto-suggests the matching country record. The binding is informational — it surfaces in admin views and in the storefront country/locale selector, but does not affect translation resolution.
RENDER REQUEST (locale = fr-CA)│▼┌───────────────────────────────────────────┐│ Translation lookup ││ ││ Step 1: fr-CA store miss ││ Step 2: fr-CA fallback[0] = fr hit ✔ │ → return "Bienvenue"│ Step 3: (skipped — hit found) ││ ││ if all steps miss: ││ consult default locale (en) ││ if default also misses: ││ render the message key │└───────────────────────────────────────────┘Permissions
Access to the Languages surface is gated at two layers.
Layer 1 — admin gate. Every action under SG-Admin passes through the platform's standard admin access check at request entry. An unauthenticated request never reaches the Languages surface.
Layer 2 — per-action capability. Within SG-Admin, each Languages action checks a capability associated with the calling operator's role. The default role configuration ships with three roles — Administrator, Editor, Viewer — and the capability map is:
| Capability | Administrator | Editor | Viewer |
|---|---|---|---|
| List locales | ✔ | ✔ | ✔ |
| View locale detail | ✔ | ✔ | ✔ |
| Register locale | ✔ | ✔ | — |
| Edit locale metadata | ✔ | ✔ | — |
| Edit fallback chain | ✔ | ✔ | — |
| Toggle storefront enabled | ✔ | ✔ | — |
| Set default locale | ✔ | — | — |
| Unregister locale | ✔ | — | — |
Self-protection rules. The default locale cannot be disabled. The default locale cannot be unregistered — rotate the default first. The fallback chain cannot reference itself directly or transitively (cycles are rejected at write time). At least one locale must remain registered at all times — the surface returns a structured rejection on the unregister that would leave zero.
Audit. Every write — register, edit, fallback edit, default rotation, enable, disable, unregister — emits an Activity Log entry. The log records the acting operator, the locale identifier, and the change shape. Default rotations and unregistrations write dedicated event types for audit clarity.
REQUEST│▼┌───────────────────────────┐│ Admin gate │ unauth → reject│ (every /sg-admin/* call) │└─────────────┬─────────────┘│ authed▼┌───────────────────────────┐│ Capability check │ role lacks cap → reject│ (per-action) │ (custom roles override defaults)└─────────────┬─────────────┘│ allowed▼┌───────────────────────────┐│ Self-protection rules │ default-disable / fallback cycle /│ │ zero-registered → reject└─────────────┬─────────────┘│ passes▼action executes│▼Activity Log entryRelated references
- Translations — Reference. Holds the actual translated strings per locale. A locale must be registered here before a translation can be authored. Unregister-with-orphaned-translations is documented there.
- Countries — Reference. Region codes in locale identifiers resolve against the Countries catalog. The binding surfaces in admin views and the storefront country/locale selector.
- Pages — Reference. Per-page locale overrides reference locales registered here. A page can be excluded from selected locales.
- Products — Reference. Per-product locale overrides reference locales registered here. A product can be hidden in selected locales.
- Currencies — Reference. A locale and a currency are independent — a visitor can browse in
fr-CAwhile paying in PHP. The two surfaces are paired by visitor choice, not by configuration. - Settings — Reference. Owns the default direction handling, the locale-selector visibility rule on the storefront, and the BCP-47 grammar configuration. Changes there reshape the registration validation.
/docs/languages.