Skip to content

Latest commit

 

History

History
147 lines (105 loc) · 4.35 KB

File metadata and controls

147 lines (105 loc) · 4.35 KB

Multi-Language & i18n Support

Full content localization with AI-powered translation, space-level locale management, and intelligent fallback chains.

Overview

Numen's i18n system enables content creators to manage multiple language variants of the same content. Every space can have multiple configured locales, and content can be translated automatically using the AI pipeline — preserving the original tone and voice through the existing Persona system.

Key capabilities:

  • Space-level locale configuration (add/remove/reorder locales, set default)
  • AI-powered translation with tone awareness (respects Persona)
  • Translation matrix dashboard (per-content, per-locale coverage)
  • Intelligent 5-step fallback chain for graceful degradation
  • REST API for translation workflow
  • CLI migration tool for existing spaces

Architecture

Locale Management

Each space has a set of configured locales. Locales are identified by BCP 47 language tags (e.g., en, de, fr, en-US, pt-BR).

Core concepts:

  • Default locale — the locale used when no preference is specified
  • Supported locales — all locales available in a space
  • Locale order — display priority for frontend locale pickers

Translation Workflow

When a user requests a translation:

  1. A TranslateContentJob is queued on the ai-pipeline queue
  2. The job uses the AITranslationService to call the LLM
  3. The prompt includes the Persona configuration to preserve tone
  4. Translated blocks are stored as translation_jobs records
  5. On completion, a TranslationCompleted event fires (webhook-friendly)
  6. On failure, a TranslationFailed event fires with error details

Fallback Chain

When content is requested in a locale that has no translation, Numen applies a 5-step fallback:

1. Exact match (e.g., "en-US" → look for "en-US" translation)
   ↓ (if missing)
2. Language prefix (e.g., "en-US" → look for "en" translation)
   ↓ (if missing)
3. Fallback locale (configured in space locale settings)
   ↓ (if missing)
4. Space default locale
   ↓ (if missing)
5. "en" (hardcoded fallback)

This ensures content is always available, even with incomplete translations.

Usage

Setup

For existing spaces, run the setup command to initialize locales:

php artisan numen:setup-i18n {space_id}

This:

  • Creates a space_locales record for the default locale (en)
  • Marks it as the default
  • Tracks the baseline for future translation jobs

API

List Locales

curl -X GET "http://localhost:8000/api/v1/locales?space_id=YOUR_SPACE_ID" \
  -H "Authorization: Bearer YOUR_TOKEN"

Translate Content

curl -X POST "http://localhost:8000/api/v1/content/{content_id}/translate" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "target_locale": "fr",
    "force": false
  }'

Translation Matrix

View coverage across all content and locales:

curl -X GET "http://localhost:8000/api/v1/translations/matrix?space_id=YOUR_SPACE_ID&status_filter=all&limit=50" \
  -H "Authorization: Bearer YOUR_TOKEN"

Locale Awareness (Content Delivery)

The SetLocaleFromRequest middleware sets the current locale from (in order of priority):

  1. Accept-Language header
  2. ?locale= query parameter
  3. X-Locale header

When content is requested, the API automatically selects the best-match translation using the fallback chain.

Data Model

Tables

space_locales

Locale configuration per space.

Column Type Notes
id uuid Primary key
space_id uuid Foreign key to spaces
locale string BCP 47 code
is_default boolean Default locale
sort_order integer Display priority

translation_jobs

Translation job tracking.

Column Type Notes
id uuid Primary key
content_id uuid Foreign key
from_locale string Source locale
to_locale string Target locale
status enum pending/completed/failed
translated_title text Translated title
translated_excerpt text Translated excerpt
error_message text Error details

See Also