- 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.
295 lines
5.8 KiB
Markdown
295 lines
5.8 KiB
Markdown
# 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:
|
|
|
|
```html
|
|
<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:
|
|
|
|
```html
|
|
<span>{{ '::Welcome' }}</span>
|
|
<span>{{ '::Hello, ' + name }}</span>
|
|
<p>{{ '::You have ' + count + ' messages' }}</p>
|
|
```
|
|
|
|
### In Scripts
|
|
|
|
Use `__m()` function:
|
|
|
|
```html
|
|
<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`**:
|
|
|
|
```yaml
|
|
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
|
|
|
|
```html
|
|
<!-- 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
|
|
|
|
```typescript
|
|
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
|
|
|
|
```javascript
|
|
// 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
|
|
<html lang="{{ $locale }}">
|
|
<body dir="{{ $direction }}">
|
|
...
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
## Custom Formatter
|
|
|
|
Define a custom formatter process:
|
|
|
|
```yaml
|
|
# In locale file
|
|
formatter: scripts.locale.format
|
|
```
|
|
|
|
**`scripts/locale.js`**:
|
|
|
|
```javascript
|
|
function format(text, args) {
|
|
// Custom formatting logic
|
|
return text.replace(/%d/g, () => args.shift());
|
|
}
|
|
```
|
|
|
|
## RTL Support
|
|
|
|
For right-to-left languages:
|
|
|
|
```yaml
|
|
# __locales/ar/home.yml
|
|
name: ar
|
|
direction: rtl
|
|
timezone: +03:00
|
|
|
|
messages:
|
|
Hello: مرحبا
|
|
```
|
|
|
|
```html
|
|
<body dir="{{ $direction }}">
|
|
<!-- Content automatically flows RTL -->
|
|
</body>
|
|
```
|
|
|
|
## Building Translations
|
|
|
|
### Generate Translation Files
|
|
|
|
```bash
|
|
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`**:
|
|
|
|
```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`**:
|
|
|
|
```yaml
|
|
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`**:
|
|
|
|
```yaml
|
|
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!": "私たちのサイトへようこそ!"
|
|
```
|