Skip to content

Multi-Language and i18n

Greentic uses “multi-language” in two different but related ways:

  • Implementation languages - Digital-worker components run as WebAssembly components, so teams can build reusable operations in Rust, Go, JavaScript, Python, or any language that can target WASI Preview 2.
  • User-facing languages - Messages, Adaptive Cards, WebChat labels, templates, prompts, and other visible strings can be translated and selected by locale at runtime.

The important design point is that language support is packaged and deployed with the worker. An application pack can carry translation files, WebChat extensions can scaffold locale-aware assets into a bundle, and tenant/session context tells the runtime which locale to use for a given user interaction.

Greentic treats locale as runtime context, not as a hard-coded global. A request or session can carry a locale, and the runtime can fall back through broader scopes when a narrower locale is not set.

Typical resolution order:

  1. Session or user locale
  2. Team default locale
  3. Tenant default locale
  4. Bundle or global default locale
  5. Source language fallback

TenantCtx also carries localization context through host calls and component invocations. That means a component, flow node, messaging extension, or WebChat surface can resolve text consistently while still preserving tenant, team, session, trace, and correlation information.

Greentic keeps translations close to the worker artifacts that use them:

LocationUsed for
Application pack assetsCards, templates, prompts, app-specific messages, and flow-owned UI strings
Bundle assetsDeployment-specific overrides, WebChat skins, locale files, embed snippets, and tenant-specific customizations
Extension pack defaultsDefault WebChat labels, skins, and public extension assets
Runtime contextCurrent locale, tenant, team, session, trace, and fallback context

This avoids forking an application pack for every language or customer. You can ship one pack, then override or add locale files at the bundle level for a specific tenant or deployment.

For WebChat-based workers, enable the WebChat i18n capability when creating the bundle:

create-answers.json
{
"answers": {
"delegate_answer_document": {
"answers": {
"capabilities": [
"greentic.cap.bundle_assets.read.v1",
"greentic.cap.webchat.i18n.v1"
]
}
}
}
}

When greentic.cap.webchat.i18n.v1 is enabled, gtc wizard and gtc setup can scaffold locale-aware WebChat assets under the bundle ./assets/ directory. The bundle can then override extension defaults without modifying the original .gtpack.

Automatic translation and packing at export

Section titled “Automatic translation and packing at export”

When a digital worker is exported with additional languages selected in the designer export wizard, the greentic-pack build step automatically translates the Adaptive Card strings and packs the resulting locale files into the application .gtpack. No manual translation step or post-build copy is needed.

The process runs during greentic-pack build:

  1. greentic-i18n-translator reads the English source strings from the pack.
  2. It produces assets/i18n/<lang>.json for each selected language, plus assets/i18n/_manifest.json describing the available locales.
  3. Both the locale files and the manifest are written inside the application .gtpack.
  4. At runtime, greentic-start synthesises the webchat-gui locale-picker manifest from those packed files, so the picker shows exactly the languages the operator selected at export.

Translation is non-fatal. If the translator is unavailable or a specific language fails, greentic-pack logs a warning, skips that language, and completes the build with the remaining locales.

Example of the packed locale structure inside a .gtpack:

assets/
└── i18n/
├── _manifest.json # lists available locales
├── en.json
├── de.json
├── es.json
└── ja.json

Example bundle asset layout (bundle-level overlays):

my-bundle/
└── assets/
└── webchat-gui/
└── skins/
└── demo/
└── i18n/
├── en.json
├── de.json
├── es.json
└── ja.json

The WebChat UI exposes a locale picker, remembers the selected locale in the session, and resolves labels and messages from the active locale file. The picker entries are driven by the _manifest.json packed inside the .gtpack, so it shows only the languages that were actually translated and included at build time.

Adaptive Cards and templates should use stable translation keys instead of duplicating card files for every language. Current Greentic packs use readable JSON catalog keys such as card.main_menu.body_0.text and references such as {{i18n:card.main_menu.body_0.text}}.

The usual workflow is:

  1. Create or extract source strings from cards, templates, or other assets into an English source map.

    assets/i18n/en.json
    {
    "card.welcome.body_0.text": "Welcome",
    "card.welcome.actions_0.title": "Get Started"
    }
  2. Select target languages in the designer export wizard. The greentic-pack build step automatically runs greentic-i18n-translator to produce locale files for each selected language. No manual translation command is needed; the translator runs as part of the pack build.

  3. Locale files are packed automatically. The translated assets/i18n/<lang>.json files and a _manifest.json index are written inside the application .gtpack by greentic-pack. You do not need to copy or manage them separately.

  4. Resolve text at runtime from the current session, team, tenant, or default locale.

Multi-tenancy and i18n are connected. The same digital worker can serve many tenants while each tenant has different:

  • Default locale
  • Enabled languages
  • WebChat skin and labels
  • Brand-specific phrasing
  • Legal or compliance wording
  • Team-level terminology

Bundle assets make those differences deployment-specific. A pack can provide defaults, while ./assets/ overlays customize the visible experience for a tenant or bundle.

For a new worker:

  1. Decide the source language, for example en.
  2. Enable greentic.cap.webchat.i18n.v1 if the worker uses WebChat.
  3. Keep user-facing strings in cards, templates, or locale files rather than hard-coding them in component logic.
  4. Use stable i18n keys for strings that need translation.
  5. Test at least one non-default locale before publishing the pack.