Docs/Plugin Localization SDK

Plugin Localization SDK

Permission-gated host locale, localized text, and scoped Domain Lexicon APIs for plugins

Universal Developer

Plugin Localization SDK

Overview

The Localization SDK is the supported plugin contract for reading the host locale, resolving localized values, creating transport-safe i18n messages, and using the host Domain Lexicon.

It is available to plugins with sdkapi >= 260713 through:

  • Main/runtime context: context.utils.i18n and context.utils.lexicon
  • Mirrored main/runtime context: context.utils.plugin.i18n and context.utils.plugin.lexicon
  • Plugin renderer: usePluginI18n() and usePluginLexicon() from @talex-touch/utils/plugin/sdk

The current host locales are en-US and zh-CN.

Manifest requirements

Declare only the permissions used by the plugin:

EXAMPLE.JSON
{
"sdkapi": 260713,
"permissions": {
"required": ["i18n.read", "lexicon.read"],
"optional": ["lexicon.register"]
},
"permissionReasons": {
"i18n.read": "Resolve plugin labels using the host locale",
"lexicon.read": "Search the host Domain Lexicon",
"lexicon.register": "Register plugin-scoped aliases while the plugin is enabled"
}
}
PermissionRequired by
i18n.readgetLocale(), resolveText()
lexicon.readresolve(), search()
lexicon.registerregister()

The host checks the SDK marker, manifest declaration, current grant, loaded plugin, and verified plugin identity. Missing state fails closed before locale or lexicon services run.

createMessage() is a pure string constructor and does not read host state. It rejects an empty message key.

Runtime usage

EXAMPLE.TYPESCRIPT
export default {
async onInit(context) {
const { i18n, lexicon } = context.utils

      const locale = await i18n.getLocale()
      const title = await i18n.resolveText(
        {
          default: 'Unit Converter',
          locales: { 'zh-CN': '单位换算' }
        },
        locale
      )
      const message = i18n.createMessage('plugin.ready', { title })

      const meter = await lexicon.resolve('unit.length.meter', {
        locale,
        domain: 'unit'
      })
      const matches = await lexicon.search('meter', {
        locale,
        domain: 'unit',
        limit: 5
      })

      context.utils.logger.info(
        `${message}:${meter?.label ?? 'missing'}:${matches.length}`
      )
    }

## }

Renderer usage

EXAMPLE.TYPESCRIPT
import {
usePluginI18n,
usePluginLexicon
} from '@talex-touch/utils/plugin/sdk'

const i18n = usePluginI18n()
const lexicon = usePluginLexicon()

const locale = await i18n.getLocale()
const label = await i18n.resolveText({
default: 'Ready',
locales: { 'zh-CN': '就绪' }
})
const capabilities = await lexicon.search('ready', {
locale,
domain: 'capability'
})

Renderer hooks require an active plugin renderer channel. Do not call them from a normal application renderer or before the plugin channel is ready.

API reference

I18n

MethodResultNotes
getLocale()Promise<'en-US' | 'zh-CN'>Reads the current host locale.
resolveText(value, locale?)Promise<string>Resolves a string or { default, locales } value. The host locale is used when locale is omitted.
createMessage(key, params?)stringCreates a $i18n: transport message without a host call.

Domain Lexicon

MethodResultNotes
resolve(id, options?)Promise<ResolvedDomainLexiconEntry | null>Resolves an official entry or an entry owned by the calling plugin.
search(query, options?)Promise<DomainLexiconMatch[]>Searches official and caller-owned entries. Supports locale, domain, and limit.
register(entries, options?)Promise<PluginLexiconRegisterResult>Atomically registers plugin-local entries. replace: true replaces the caller's current overlay.

Supported domains are unit, currency, timezone, capability, fileType, and systemAction.

Register plugin-scoped entries

EXAMPLE.TYPESCRIPT
const result = await context.utils.lexicon.register(
[
{
id: 'status.ready',
domain: 'capability',
version: '1',
labels: {
default: 'Ready',
locales: { 'zh-CN': '就绪' }
},
aliases: {
default: ['ready'],
locales: { 'zh-CN': ['就绪'] }
}
}
],
{ replace: false }
)

// The host assigns plugin:<pluginId>:status.ready.
console.log(result.ids[0])

Registration boundaries:

  • IDs supplied by a plugin are local IDs. A plugin cannot choose another plugin namespace.
  • The host projects status.ready to plugin:<pluginId>:status.ready and sets source=plugin:<pluginId>.
  • Official IDs cannot be overridden, and one plugin cannot resolve or search another plugin's overlay.
  • Each plugin can hold at most 100 entries. One request can register at most 50 entries and 256 KiB.
  • A batch is fully validated before it is committed.
  • Plugin overlays are in memory only. They are removed when the plugin is disabled or unloaded and are not written to SQLite, Catalog, or sync payloads.

Errors and recovery

Permission, SDK, identity, and payload failures are explicit transport errors. Handle them as unavailable capability states rather than returning a fake localized value or empty successful result.

Common codes include:

  • PLUGIN_I18N_PERMISSION_UNAVAILABLE
  • PLUGIN_I18N_PERMISSION_DENIED
  • PLUGIN_LEXICON_PERMISSION_UNAVAILABLE
  • PLUGIN_LEXICON_PERMISSION_DENIED
  • PLUGIN_LOCALIZATION_SDK_UNSUPPORTED
  • PLUGIN_LOCALIZATION_INVALID_REQUEST
  • PLUGIN_LOCALIZATION_PLUGIN_UNAVAILABLE

Do not use host internals as a plugin API

i18nResolver.addMessages() and direct imports from the host locale registry are application-internal mechanisms. They do not provide plugin identity, permission checks, namespace isolation, or lifecycle cleanup. Plugins must use the Localization SDK described above.