Locara

39 — Internationalization (i18n)

v1 is English-only. This document captures the commitment, the architecture for future localization, and what app authors should do today to avoid painting themselves into a corner.

v1 stance

  • The framework, CLI, runtime, client, registry, and all reference apps are English-only.
  • Documentation is English-only.
  • Manifest fields with user-visible text expect English.
  • App authors writing apps for non-English audiences can do so, but the framework provides no localization support yet.

This is a deliberate scope choice. i18n done well is a year of work; done poorly it’s worse than no support.

When i18n becomes priority

After phase 4 (catalog + ecosystem maturity). Triggers:

  • ~10k+ users, with significant non-English user base demanding it.
  • A trusted contributor willing to lead the localization effort.
  • A budget for ongoing translation maintenance.

Until then, anyone who wants Locara in another language is welcome to fork.

What app authors should do today

Despite no framework support, savvy authors can structure their apps to make future localization easier:

1. Externalize strings

Don’t hardcode user-visible strings in JSX:

// Bad
<button>Save</button>

// Good
<button>{t('save')}</button>
// where t('save') currently always returns 'Save' from a single-locale dict

A simple t() function with a flat string table works fine for v1 even though it’s effectively a no-op.

2. Separate UI text from logic

Keep all user-facing strings in src/strings/en.ts (or similar). Easy to add src/strings/es.ts later.

3. Use locale-aware formatting

For dates, times, numbers:

// Bad
const display = `${date.toString()} - ${count.toString()}`

// Good
const display = `${date.toLocaleDateString()} - ${count.toLocaleString()}`

toLocaleString works in any browser/Tauri; uses the OS locale automatically.

4. Avoid baked-in language assumptions

  • Don’t assume English plural rules (some languages have 6 plural forms).
  • Don’t concatenate sentence fragments.
  • Don’t hardcode left-to-right layout if you might support RTL languages later.

5. Structure the manifest for future locales

The manifest’s displayName, description, etc. are currently strings. v2 may expand to:

"displayName": {
  "en": "Transcribe",
  "es": "Transcribir",
  "ja": "Transcribe"
}

Apps written today will continue to work (the string form will be treated as the English value).

Future framework architecture (sketch)

When i18n ships (v2+), the design will likely:

Locale negotiation

Each Locara app reads the user’s preferred locale from macOS:

import { i18n } from '@locara/sdk'

const locale = i18n.getLocale()  // 'en-US', 'fr-FR', etc.

Translation file format

Apps ship translation files alongside source:

src/
├── strings/
│   ├── en.json      // canonical
│   ├── es.json
│   ├── fr.json
│   └── ja.json

Translation function

import { t } from '@locara/sdk/i18n'

t('transcribe.welcome', { name: 'King' })
// Returns translated + interpolated string for current locale

Manifest localization

Apps declare which locales they support:

"locales": {
  "supported": ["en", "es", "fr"],
  "default": "en"
}

Display fields are looked up against the user’s locale; fall back to default if unsupported.

Registry + website

  • Catalog lists each app’s supported locales.
  • Users can filter apps by their locale.
  • The locara.app website itself is localized; optional Locara Manager utility (if shipped) is localized.

What makes i18n hard

The reasons to defer:

  • Translation quality. Machine translation is OK for prototyping; production-quality requires human translators and ongoing maintenance.
  • Plural rules. Different languages have different plural forms; libraries like ICU MessageFormat handle this but add complexity.
  • Bidirectional text (RTL). Arabic, Hebrew, etc. require layout flips; CSS logical properties help but aren’t free.
  • Date/time/number formats that differ enormously — “5,000.00” in US vs “5.000,00” in Germany vs “5 000,00” in France.
  • Cultural variants beyond text — colors, icons, references.
  • Maintenance. Every UI change ripples to every locale.

A small project that ships English first and adds locales later is a successful pattern. A project that ships half-localized to many languages from day one usually has worse UX than English-only.

Specific languages prioritized later (provisional)

When i18n does start, candidate locales (subject to actual user demand):

  1. Spanish — large user base in EU, Americas, philosophy-of-craft alignment.
  2. French — EU, Quebec.
  3. Japanese — high local-AI interest (Apple Silicon, privacy culture).
  4. German — large dev community.
  5. Brazilian Portuguese.
  6. Simplified Chinese — large potential audience but politically complex; defer.

This list is provisional. Real prioritization depends on where users actually come from.

Accessibility ↔ i18n overlap

20-accessibility.md flagged the EU Accessibility Act compliance angle. Localization is necessary for many EU markets but not strictly required for accessibility per se.

The two are related: VoiceOver in different locales speaks different languages; we need to support those even if our visible UI is English.

What we’re NOT going to do

  • Auto-translate user content. If an app processes a French audio file, that’s the app’s job, not the framework’s.
  • Real-time conversation translation. Apps can build it; framework doesn’t.
  • Localization of model output. Whatever the model says, it says. Apps can prompt-engineer for locale-aware output.
  • Currency conversion. Apps that show money do their own conversion logic.
  • Pseudolocalization for UI testing. Useful but defer to v2.

Open questions

  • (open) When v2 i18n ships, do existing apps need to migrate, or can the framework backfill English locale from string fields? Probably backfill for compatibility.
  • (open) Should community-contributed translations have a different trust level than core ones? Likely yes — translations are user-visible content; bad translations are an attack surface.
  • (open) Should the manifest support locale-specific screenshots / icons? Eventually yes.

Cross-references