woocommerce/.ai/skills/woocommerce-dev-cycle/zh-cn/js-i18n-patterns.md
2026-04-15 10:18:01 +08:00

293 lines
No EOL
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# JavaScript/TypeScript i18n 样板
## 目录
- [概述](#概述)
- [翻译函数](#翻译函数)
- [占位符样板](#占位符样板)
- [翻译器评论](#翻译器评论)
- [复杂字符串样板](#复杂字符串样板)
- [常见陷阱](#常见陷阱)
- [快速命令参考](#快速命令参考)
## 概述
WooCommerce 使用来自 `@wordpress/i18n` 的 WordPress i18n 函数来处理可翻译字符串。像 "WooPayments" 这样的品牌名称应使用占位符以提高翻译灵活性。
```typescript
import { __, sprintf } from '@wordpress/i18n';
```
## 翻译函数
### 基础翻译
```typescript
// 简单字符串
__( '保存更改', 'woocommerce' )
// 带占位符的字符串
sprintf(
/* 译: %s: 支付提供者名称 (例如: WooPayments) */
__( '设置 %s', 'woocommerce' ),
'WooPayments'
)
```
### 使用 `_n` 的复数形式
```typescript
import { _n, sprintf } from '@wordpress/i18n';
sprintf(
/* 译: %d: 项目数量 */
_n(
'%d 个项目已选中',
'%d 个项目已选中',
count,
'woocommerce'
),
count
)
```
### 使用 `createInterpolateElement` 进行插值元素
```typescript
import { createInterpolateElement } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
createInterpolateElement(
sprintf(
/* translators: 1: 支付提供者名称 */
__( '为您的商店启用 <strong>%1$s</strong>。', 'woocommerce' ),
'WooPayments'
),
{
strong: <strong />,
}
)
```
## 占位符样板
### 单个占位符
使用 `%s` 表示单个占位符:
```typescript
sprintf(
/* translators: %s: 支付提供者名称例如WooPayments */
__( '通过 %s 收款', 'woocommerce' ),
'WooPayments'
)
```
### 多个相同占位符
当同一数值多次出现时,请使用带编号的占位符 `%1$s`
```typescript
sprintf(
/* translators: 1: 支付提供者名称例如WooPayments */
__(
'使用 %1$s 即表示您同意我们的条款。通过 %1$s 进行的支付是安全的。',
'woocommerce'
),
'WooPayments'
)
```
### 多个不同的占位符
使用带编号的占位符 `%1$s``%2$s` 来表示不同的值:
```typescript
sprintf(
/* translators: 1: 支付提供者名称, 2: 扩展名称 */
_n(
'正在安装 %1$s 将启用 %2$s 扩展。',
'正在安装 %1$s 将启用 %2$s 扩展。',
extensionCount,
'woocommerce'
),
'WooPayments',
extensionNames
)
```
## 译: 评论
### 评论位置
译者评论必须**紧接在 `__()``_n()` 函数之前**,而不是在 `sprintf()` 之前:
```typescript
// ❌ 错误 - 评论在 sprintf 之前
/* translators: %s: 支付提供者名称 */
sprintf(
__( 'Set up %s', 'woocommerce' ),
'WooPayments'
)
// ✅ 正确 - 评论在 sprintf 内部,在 __() 之前
sprintf(
/* translators: %s: 支付提供者名称 */
__( 'Set up %s', 'woocommerce' ),
'WooPayments'
)
```
### 数字占位符的评论格式
当使用像 `%1$s` 这样的数字占位符时,在评论中只使用数字:
```typescript
// ❌ 错误 - 在评论中使用 %1$s
/* translators: %1$s: Provider name, %2$s: Country */
// ✅ 正确 - 只使用数字
/* translators: 1: Provider name, 2: Country */
```
### 描述性评论
总是为译:提供上下文:
```typescript
// ❌ 错误 - 无上下文
/* translators: %s: 名称 */
// ✅ 正确 - 清晰的上下文
/* translators: %s: 支付提供者名称 (例如WooPayments) */
```
## 复杂字符串样板
### 结合使用 `sprintf`、`_n` 和 `createInterpolateElement`
```typescript
installText: ( extensionsString: string ) => {
const count = extensionsString.split( ', ' ).length;
return createInterpolateElement(
sprintf(
/* translators: 1: Provider name, 2: Extension names */
_n(
'正在安装 <strong>%1$s</strong> 会启用 <strong>%2$s</strong>。',
'正在安装 <strong>%1$s</strong> 会启用 <strong>%2$s</strong>。',
count,
'woocommerce'
),
'WooPayments',
extensionsString
),
{ strong: <strong /> }
);
}
```
### 带链接的字符串
```typescript
createInterpolateElement(
sprintf(
/* 译: 1: 支付提供者名称 */
__(
'了解更多关于<a>%1$s</a>的产品特点。',
'woocommerce'
),
'WooPayments'
),
{
a: (
<a
href="https://example.com"
target="_blank"
rel="noopener noreferrer"
/>
),
}
)
```
## 常见陷阱
### 花式撇号
TypeScript 文件可能使用花式撇号(`'` U+2019而非直撇号`'` U+0027。编辑时请保留原始字符
```typescript
// 原文使用花式撇号 - 请保留它
__( 'I don't want to install another plugin', 'woocommerce' )
// ^ 这是 U+2019不是 U+0027
```
### ESLint i18n 规则
`@wordpress/i18n-translator-comments` 规则要求注释直接位于翻译函数之前:
```typescript
// ❌ ESLint 错误 - 注释未紧邻 __()
const title = sprintf(
/* translators: %s: Provider name */
__( 'Set up %s', 'woocommerce' ),
'WooPayments'
);
// ✅ 正确 - 注释直接位于 __() 之前
const title = sprintf(
/* translators: %s: Provider name */
__( 'Set up %s', 'woocommerce' ),
'WooPayments'
);
```
### 品牌名称
始终为品牌名称使用占位符以提高翻译灵活性:
```typescript
// ✅ 正确 - 为品牌名称使用占位符
title: sprintf(
/* 译: %s: 支付提供者名称 */
__( '通过 %s 收款', 'woocommerce' ),
'WooPayments'
)
// ✅ 正确 - 在描述中使用占位符
description: sprintf(
/* 译: %s: 支付提供者名称 */
__( '启用 PayPal 与 %s 并存', 'woocommerce' ),
'WooPayments'
)
// ❌ 错误 - 硬编码品牌名称
title: __( '通过 WooPayments 收款', 'woocommerce' )
```
## 快速命令参考
```bash
# 检查特定文件
npx eslint client/path/to/file.tsx
# 修复特定文件
npx eslint --fix client/path/to/file.tsx
# 类型检查
pnpm run ts:check
# ❌ 从不检查整个代码库
pnpm run lint # 否 - 会检查所有内容
```
## 摘要
| 样板 | 例子 |
|-------------------------------|----------------------------------------------|
| **单个占位符** | `sprintf( __( '设置 %s' ), '名称' )` |
| **重复占位符** | `sprintf( __( '%1$s 通过 %1$s' ), '名称' )` |
| **多个占位符** | `sprintf( __( '%1$s 在 %2$s' ), 'A', 'B' )` |
| **评论格式 (简单)** | `/* 译: %s: 提供者名称 */` |
| **评论格式 (带数值)** | `/* 译: 1: 提供者, 2: 国家 */` |