Plugin Localization SDK
Permission-gated host locale, localized text, and scoped Domain Lexicon APIs for plugins
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.i18nandcontext.utils.lexicon - Mirrored main/runtime context:
context.utils.plugin.i18nandcontext.utils.plugin.lexicon - Plugin renderer:
usePluginI18n()andusePluginLexicon()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:
{
"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"
}
}
| Permission | Required by |
|---|---|
i18n.read | getLocale(), resolveText() |
lexicon.read | resolve(), search() |
lexicon.register | register() |
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
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
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
| Method | Result | Notes |
|---|---|---|
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?) | string | Creates a $i18n: transport message without a host call. |
Domain Lexicon
| Method | Result | Notes |
|---|---|---|
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
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.readytoplugin:<pluginId>:status.readyand setssource=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_UNAVAILABLEPLUGIN_I18N_PERMISSION_DENIEDPLUGIN_LEXICON_PERMISSION_UNAVAILABLEPLUGIN_LEXICON_PERMISSION_DENIEDPLUGIN_LOCALIZATION_SDK_UNSUPPORTEDPLUGIN_LOCALIZATION_INVALID_REQUESTPLUGIN_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.