# Internationalization (i18n) ## Locale Files Create `locales/` directory in the assistant: ``` assistants/my-assistant/ └── locales/ ├── en-us.yml ├── zh-cn.yml └── ja.yml ``` ## Locale File Format ```yaml # locales/en-us.yml name: My Assistant description: A helpful AI assistant chat: title: New Chat description: How can I help you today? prompts: - What can you do? - Help me with a task - Tell me about yourself messages: welcome: Welcome back! error: Something went wrong processing: Processing your request... ``` ```yaml # locales/zh-cn.yml name: 我的助手 description: 一个有帮助的AI助手 chat: title: 新对话 description: 今天我能帮您什么? prompts: - 你能做什么? - 帮我完成一个任务 - 介绍一下你自己 messages: welcome: 欢迎回来! error: 出了点问题 processing: 正在处理您的请求... ``` ## Using Translations ### In package.yao Use `{{ key }}` syntax: ```json { "name": "{{ name }}", "description": "{{ description }}", "placeholder": { "title": "{{ chat.title }}", "description": "{{ chat.description }}", "prompts": [ "{{ chat.prompts.0 }}", "{{ chat.prompts.1 }}", "{{ chat.prompts.2 }}" ] } } ``` ### In Prompts ```yaml - role: system content: | You are {{ name }}. {{ description }} Respond in the user's language. ``` ## Locale Detection The system detects locale from: 1. Request header `Accept-Language` 2. User preference (stored in memory) 3. Default: `en-us` ### Override in Hook ```typescript function Create(ctx: agent.Context, messages: agent.Message[]): agent.Create { // Get user preference const userLocale = ctx.memory.user.Get("preferred_locale"); return { messages, locale: userLocale || "en-us" }; } ``` ## Global Translations Define global translations in `agent/locales/`: ``` agent/ └── locales/ ├── en-us.yml └── zh-cn.yml ``` These are available to all assistants via the `__global__` namespace. ## Accessing Translations in Hooks ```typescript function Create(ctx: agent.Context, messages: agent.Message[]): agent.Create { const locale = ctx.locale; // e.g., "en-us" // Use locale for custom logic if (locale.startsWith("zh")) { return { messages, prompt_preset: "chinese" }; } return { messages }; } ``` ## Nested Keys Access nested values with dot notation: ```yaml # locales/en-us.yml errors: validation: required: This field is required invalid: Invalid value network: timeout: Connection timed out ``` ```json { "placeholder": { "title": "{{ errors.validation.required }}" } } ``` ## Fallback Behavior If a translation key is not found: 1. Try the requested locale 2. Fall back to `en-us` 3. Return the key itself if not found ## Dynamic Locale Content ```typescript function Create(ctx: agent.Context, messages: agent.Message[]): agent.Create { // Add locale-specific system message const localeGreeting = { "en-us": "Hello! How can I help you?", "zh-cn": "你好!有什么可以帮您的?", "ja": "こんにちは!何かお手伝いできますか?" }; const greeting = localeGreeting[ctx.locale] || localeGreeting["en-us"]; return { messages: [ { role: "system", content: `Greeting: ${greeting}` }, ...messages ] }; } ``` ## Best Practices 1. **Keep keys consistent** - Use the same keys across all locale files 2. **Use nested structure** - Organize related translations together 3. **Provide fallbacks** - Always have `en-us` as the base locale 4. **Test all locales** - Verify translations render correctly 5. **Use context variables** - Combine with `$CTX.locale` in prompts