yao/sui/docs/i18n.md
Max f115e6d782 Update Documentation for SUI Structure and Locale Handling
- Revised the README and agent-sui documentation to clarify the directory structure, including the addition of __data.json and __locales directories for global and page-level data.
- Enhanced explanations of the pages directory, emphasizing the organization of global and assistant-specific pages.
- Updated the i18n documentation to detail locale detection and the importance of server-side rendering for translations, including a code snippet for changing locales via JavaScript.
2026-01-03 15:06:32 +08:00

5.8 KiB

Internationalization (i18n)

SUI provides built-in support for internationalization with translation markers and locale files.

Translation Markers

Static Text

Use s:trans attribute for static text:

<span s:trans>Hello World</span>
<button s:trans>Submit</button>
<p s:trans>Welcome to our application</p>

In Expressions

Use '::' prefix in expressions:

<span>{{ '::Welcome' }}</span>
<span>{{ '::Hello, ' + name }}</span>
<p>{{ '::You have ' + count + ' messages' }}</p>

In Scripts

Use __m() function:

<script>
  const message = __m("Welcome back");
  const greeting = __m("Hello, ") + userName;
  alert(__m("Are you sure?"));
</script>

Locale Files

Directory Structure

/templates/<template>/
└── __locales/
    ├── en-us/
    │   ├── home.yml
    │   └── users/list.yml
    └── zh-cn/
        ├── home.yml
        └── users/list.yml

File Format

__locales/zh-cn/home.yml:

name: zh-cn
direction: ltr
timezone: +08:00
formatter: scripts.locale

messages:
  Hello World: 你好世界
  Welcome: 欢迎
  "Hello, ": "你好,"
  Submit: 提交
  "You have %d messages": "你有 %d 条消息"

keys:
  page_title: 首页
  nav_home: 首页
  nav_about: 关于

script_messages:
  Welcome back: 欢迎回来
  "Are you sure?": "你确定吗?"

Sections

Section Description
name Locale identifier
direction Text direction (ltr or rtl)
timezone Timezone offset
formatter Custom formatter process
messages Translations for s:trans and ::
keys Named translation keys
script_messages Translations for __m()

Using Translations

HTML Templates

<!-- Static translation -->
<h1 s:trans>Welcome to our site</h1>

<!-- Dynamic translation -->
<p>{{ '::Hello, ' + user.name }}</p>

<!-- With variables -->
<span>{{ '::You have ' + count + ' items' }}</span>

Named Keys

Named keys are used internally for translation lookup. The keys section in locale files provides named references for translations that can be used programmatically.

Scripts

import { Component } from "@yao/sui";

const self = this as Component;

self.ShowMessage = () => {
  const message = __m("Operation completed");
  alert(message);
};

self.Confirm = () => {
  return confirm(__m("Are you sure you want to delete?"));
};

Locale Detection

SUI detects locale from the locale HTTP cookie on the server side.

Important: s:trans translations are server-side rendered. This means:

  1. The translation happens when the page is generated on the server
  2. Changing locale via JavaScript only affects localStorage/client state
  3. To apply locale changes to s:trans content, you must reload the page
// To change locale and have s:trans reflect the change:
document.cookie = "locale=zh-CN;path=/;max-age=31536000";
location.reload(); // Required for server-side translations

Cookie Priority:

  1. locale cookie (primary)
  2. umi_locale cookie (fallback for CUI compatibility)
  3. Browser language
  4. Default (en-us)

Access Current Locale

<html lang="{{ $locale }}">
  <body dir="{{ $direction }}">
    ...
  </body>
</html>

Custom Formatter

Define a custom formatter process:

# In locale file
formatter: scripts.locale.format

scripts/locale.js:

function format(text, args) {
  // Custom formatting logic
  return text.replace(/%d/g, () => args.shift());
}

RTL Support

For right-to-left languages:

# __locales/ar/home.yml
name: ar
direction: rtl
timezone: +03:00

messages:
  Hello: مرحبا
<body dir="{{ $direction }}">
  <!-- Content automatically flows RTL -->
</body>

Building Translations

Generate Translation Files

yao sui trans <sui> <template>

This command:

  1. Scans all pages for translation markers
  2. Generates/updates locale files
  3. Builds the template

Translation Workflow

  1. Add s:trans or :: markers to your HTML
  2. Run yao sui trans to extract strings
  3. Edit locale files to add translations
  4. Build with yao sui build

Complete Example

/home/home.html:

<div class="home">
  <h1 s:trans>Welcome to our application</h1>

  <p>{{ '::Hello, ' + user.name }}</p>

  <div class="stats">
    <span>{{ '::You have ' + messageCount + ' messages' }}</span>
  </div>

  <nav>
    <a href="/" s:trans>Home</a>
    <a href="/about" s:trans>About</a>
    <a href="/contact" s:trans>Contact</a>
  </nav>

  <button s:on-click="ShowWelcome" s:trans>Show Welcome</button>
</div>

<script>
  import { Component } from "@yao/sui";

  const self = this as Component;

  self.ShowWelcome = () => {
    alert(__m("Welcome to our site!"));
  };
</script>

__locales/zh-cn/home.yml:

name: zh-cn
direction: ltr
timezone: +08:00

messages:
  Welcome to our application: 欢迎使用我们的应用
  "Hello, ": "你好,"
  "You have ": "你有 "
  " messages": " 条消息"
  Home: 首页
  About: 关于
  Contact: 联系我们
  Show Welcome: 显示欢迎

script_messages:
  "Welcome to our site!": "欢迎来到我们的网站!"

__locales/ja/home.yml:

name: ja
direction: ltr
timezone: +09:00

messages:
  Welcome to our application: アプリケーションへようこそ
  "Hello, ": "こんにちは、"
  "You have ": ""
  " messages": " 件のメッセージがあります"
  Home: ホーム
  About: について
  Contact: お問い合わせ
  Show Welcome: ようこそを表示

script_messages:
  "Welcome to our site!": "私たちのサイトへようこそ!"