miroir/docs/search_ui_i18n.md
jedarden c4c74eb572 feat(search-ui): add i18n locales field to SearchUiIndexConfig (plan §13.21)
- Add `locales` field to SearchUiIndexConfig (HashMap<lang, translations>)
- Enable operators to configure custom translations via config endpoint
- JavaScript already has i18n support (lang query param, fallback to en)
- Add documentation for operators on how to configure locales

Acceptance: GET /ui/search/{index}?lang=fr returns French UI strings when
fr locale configured; falls back to en.
2026-05-31 12:02:07 -04:00

3.2 KiB

Search UI i18n (Internationalization)

Overview

The Search UI supports internationalization (i18n) for operator-supplied translations. This is part of plan §13.21.

How It Works

  1. Query Parameter: Users can specify a language via the lang query parameter:

    • Example: GET /ui/search/myindex?lang=fr
  2. Browser Fallback: If no lang parameter is provided, the UI uses navigator.language

  3. Fallback to English: If the requested language is not configured, the UI falls back to English (the default built-in locale)

Configuring Custom Locales

Operators can add custom translations via the POST /_miroir/ui/search/{index}/config endpoint:

curl -X POST "http://miroir:8080/_miroir/ui/search/myindex/config" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <admin_key>" \
  -d '{
    "locales": {
      "fr": {
        "ui.title": "Recherche",
        "ui.logo": "Recherche",
        "ui.search.placeholder": "Rechercher...",
        "ui.search.label": "Recherche",
        "ui.search.ariaLabel": "Requête de recherche",
        "ui.search.hint": "Tapez pour rechercher. Appuyez sur / pour focus. Utilisez les flèches pour naviguer.",
        "ui.search.button": "Rechercher",
        "ui.filters": "Filtres",
        "ui.sort.label": "Trier:",
        "ui.sort.relevance": "Pertinence",
        "ui.perPage.label": "Par page:",
        "ui.results.empty": "Aucun résultat trouvé",
        "ui.results.emptyHint": "Essayez d'ajuster votre recherche ou vos filtres",
        "ui.results.count": "{count} résultats ({time}ms)"
      }
    }
  }'

Built-in Translations

The Search UI includes English translations by default in the bundled JavaScript. The t() function handles variable interpolation:

// With interpolation
t('ui.results.count', { count: 42, time: 15 })
// Returns: "42 results (15ms)"

// With French locale
// Returns: "42 résultats (15ms)"

Translation Keys

The following translation keys are supported (with default English values):

UI Labels

  • ui.title - Page title
  • ui.logo - Logo text
  • ui.search.placeholder - Search input placeholder
  • ui.search.label - Search label
  • ui.search.ariaLabel - Search ARIA label
  • ui.search.hint - Search keyboard hint
  • ui.search.button - Search button ARIA label
  • ui.darkMode.ariaLabel - Dark mode toggle ARIA label
  • ui.filters - Filters button text
  • ui.sort.label - Sort selector label
  • ui.sort.relevance - Default sort option text
  • ui.perPage.label - Per-page selector label

Results

  • ui.results.empty - Empty state title
  • ui.results.emptyHint - Empty state hint
  • ui.results.didYouMean - "Did you mean" suggestion (use {query} variable)
  • ui.results.count - Result count (use {count} and {time} variables)

Errors

  • ui.error.noIndex - No index specified error
  • ui.error.searchFailed - Search failed error (use {status} variable)
  • ui.error.initFailed - Init failed error (use {message} variable)
  • ui.error.sessionFailed - Session fetch failed

Accessibility

  • ui.filters.ariaLabel - Filters ARIA label
  • ui.pagination.ariaLabel - Pagination ARIA label
  • ui.keyboardShortcuts.ariaLabel - Keyboard shortcuts ARIA label
  • ui.keyboardShortcuts.text - Keyboard shortcuts help text