enhanced-message-context
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEnhanced Message Context
增强型消息语境
When implementing Lingui i18n, add translator comments to messages that need additional context. Not every message needs a comment - only those where the string alone could be misinterpreted.
在实现Lingui i18n时,为需要额外语境的消息添加翻译注释。并非每条消息都需要注释——只有那些仅通过字符串本身可能产生歧义的消息才需要。
When to Add Comments
何时添加注释
Add a field when the message:
comment- Is ambiguous: Short words/phrases that can be different parts of speech
- "Back" (noun or verb?), "Delete" (button or confirmation?), "Close" (verb or adjective?)
- Lacks UI context: Labels isolated from their surroundings
- Table column headers, tooltip content, standalone button labels, menu items
- Has domain-specific meaning: Terms with different meanings across contexts
- "Post" (verb or noun?), "Tag" (noun or verb?), "Follow" (social media or instruction?)
- Depends on grammatical gender: The translation depends on what the message refers to
- "Selected" (masculine/feminine/neutral depends on what is selected)
- Uses unclear variables: Placeholder names don't reveal what they contain
- (count of what?),
{count}(user name, file name, project name?){name}
当消息满足以下情况时,添加字段:
comment- 存在歧义:可作为不同词性的简短词汇/短语
- "Back"(名词还是动词?)、"Delete"(按钮还是确认操作?)、"Close"(动词还是形容词?)
- 缺乏UI语境:脱离周边环境的标签
- 表格列标题、提示框内容、独立按钮标签、菜单项
- 具有领域特定含义:在不同语境下含义不同的术语
- "Post"(动词还是名词?)、"Tag"(名词还是动词?)、"Follow"(社交媒体关注还是指令?)
- 依赖语法性别:翻译结果取决于消息所指代的对象
- "Selected"(阴/阳/中性形式取决于被选中的对象)
- 使用不明确变量:占位符名称无法体现其内容
- (统计的是什么?)、
{count}(用户名、文件名还是项目名?){name}
When to Skip Comments
何时跳过注释
Skip the field when the message:
comment- Is self-explanatory: Full sentences with clear subject and verb
- "Click the button to continue" (no ambiguity)
- Is already descriptive: Long enough to be unambiguous
- "Your password must be at least 8 characters long"
- Has a duplicate comment nearby: Don't repeat identical comments for the same concept
当消息满足以下情况时,跳过字段:
comment- 表意明确:包含清晰主语和谓语的完整句子
- "Click the button to continue"(无歧义)
- 描述充分:长度足够且无歧义
- "Your password must be at least 8 characters long"
- 附近已有重复注释:同一概念的注释无需重复添加
Writing Effective Comments
撰写有效注释的技巧
A good translator comment includes:
-
Location: Where in the UI the message appears
- "Button in the top navigation bar"
- "Tooltip for the save icon"
- "Column header in the users table"
-
Action/Purpose: What happens or what it means
- "Navigates back to the previous page"
- "Deletes the selected item permanently"
- "Shows the number of unread notifications"
-
Disambiguation: Clarify part of speech or meaning
- "Used as a verb, not a noun"
- "Refers to email addresses, not postal addresses"
- "Singular form, user will see 'item' or 'items' based on count"
优质的翻译注释应包含:
-
位置:消息在UI中的显示位置
- "顶部导航栏中的按钮"
- "保存图标对应的提示框"
- "用户表格中的列标题"
-
操作/用途:对应的操作或含义
- "返回上一页"
- "永久删除选中项"
- "显示未读通知的数量"
-
消歧义说明:明确词性或含义
- "用作动词,而非名词"
- "指代电子邮箱地址,而非邮政地址"
- "单数形式,用户将根据数量看到'item'或'items'"
API Reference
API参考
Lingui provides three ways to add translator comments:
Lingui提供三种添加翻译注释的方式:
1. JS Macro (t
)
t1. JS宏(t
)
tFor JavaScript code outside JSX:
js
import { t } from "@lingui/core/macro";
// With comment
const backLabel = t({
comment: "Button in the navigation bar that returns to the previous page",
message: "Back",
});
// With comment and variable
const uploadSuccess = t({
comment: "Success message showing the name of the file that was uploaded",
message: `File ${fileName} uploaded successfully`,
});适用于JSX之外的JavaScript代码:
js
import { t } from "@lingui/core/macro";
// 带注释
const backLabel = t({
comment: "Button in the navigation bar that returns to the previous page",
message: "Back",
});
// 带注释和变量
const uploadSuccess = t({
comment: "Success message showing the name of the file that was uploaded",
message: `File ${fileName} uploaded successfully`,
});2. React Macro (Trans
)
Trans2. React宏(Trans
)
TransFor JSX elements:
jsx
import { Trans } from "@lingui/react/macro";
// With comment
<Trans comment="Button that deletes the selected email message">Delete</Trans>
// With comment in a component
<button>
<Trans comment="Label for button that saves changes to user profile">
Save
</Trans>
</button>适用于JSX元素:
jsx
import { Trans } from "@lingui/react/macro";
// 带注释
<Trans comment="Button that deletes the selected email message">Delete</Trans>
// 组件中的带注释用法
<button>
<Trans comment="Label for button that saves changes to user profile">
Save
</Trans>
</button>3. Deferred/Lazy Messages (defineMessage
/ msg
)
defineMessagemsg3. 延迟/懒加载消息(defineMessage
/ msg
)
defineMessagemsgFor messages defined separately from their usage:
js
import { defineMessage } from "@lingui/core/macro";
const messages = {
deleteButton: defineMessage({
comment: "Button that permanently removes the item from the database",
message: "Delete",
}),
statusLabel: defineMessage({
comment: "Shows whether the service is currently operational. Values: 'Active', 'Inactive', 'Pending'",
message: "Status: {status}",
}),
};适用于与使用位置分开定义的消息:
js
import { defineMessage } from "@lingui/core/macro";
const messages = {
deleteButton: defineMessage({
comment: "Button that permanently removes the item from the database",
message: "Delete",
}),
statusLabel: defineMessage({
comment: "Shows whether the service is currently operational. Values: 'Active', 'Inactive', 'Pending'",
message: "Status: {status}",
}),
};Examples
示例
Example 1: Ambiguous Short Word
示例1:存在歧义的简短词汇
Before (no context):
jsx
<button onClick={goBack}>
<Trans>Back</Trans>
</button>After (with context):
jsx
<button onClick={goBack}>
<Trans comment="Button in the toolbar that navigates to the previous page">
Back
</Trans>
</button>之前(无语境):
jsx
<button onClick={goBack}>
<Trans>Back</Trans>
</button>之后(带语境):
jsx
<button onClick={goBack}>
<Trans comment="Button in the toolbar that navigates to the previous page">
Back
</Trans>
</button>Example 2: UI Label Without Context
示例2:缺乏语境的UI标签
Before (no context):
jsx
const columns = [
{ key: "name", label: t`Name` },
{ key: "status", label: t`Status` },
];After (with context):
jsx
const columns = [
{
key: "name",
label: t({
comment: "Column header in the projects table showing project name",
message: "Name"
})
},
{
key: "status",
label: t({
comment: "Column header showing project status: Active, Inactive, or Archived",
message: "Status"
})
},
{
key: "created",
label: t({
comment: "Column header showing the date when the project was created",
message: "Created"
})
},
];之前(无语境):
jsx
const columns = [
{ key: "name", label: t`Name` },
{ key: "status", label: t`Status` },
];之后(带语境):
jsx
const columns = [
{
key: "name",
label: t({
comment: "Column header in the projects table showing project name",
message: "Name"
})
},
{
key: "status",
label: t({
comment: "Column header showing project status: Active, Inactive, or Archived",
message: "Status"
})
},
{
key: "created",
label: t({
comment: "Column header showing the date when the project was created",
message: "Created"
})
},
];Example 3: Domain-Specific Term
示例3:领域特定术语
Before (ambiguous):
jsx
<button onClick={handlePost}>
<Trans>Post</Trans>
</button>After (clarified as verb):
jsx
<button onClick={handlePost}>
<Trans comment="Button that publishes the content. Used as a verb (to post), not a noun (a post)">
Post
</Trans>
</button>之前(歧义):
jsx
<button onClick={handlePost}>
<Trans>Post</Trans>
</button>之后(明确为动词):
jsx
<button onClick={handlePost}>
<Trans comment="Button that publishes the content. Used as a verb (to post), not a noun (a post)">
Post
</Trans>
</button>Example 4: Variable Without Clear Meaning
示例4:含义不明确的变量
Before (unclear what count represents):
js
const message = t`${count} items selected`;After (clarified):
js
const message = t({
comment: "Shows the number of email messages currently selected in the inbox",
message: `${count} items selected`,
});之前(不清楚count代表什么):
js
const message = t`${count} items selected`;之后(已明确):
js
const message = t({
comment: "Shows the number of email messages currently selected in the inbox",
message: `${count} items selected`,
});Example 5: Self-Explanatory Message (No Comment Needed)
示例5:表意明确的消息(无需注释)
jsx
// Good - no comment needed, message is clear
<Trans>
Your password must contain at least 8 characters, including one uppercase letter and one number.
</Trans>jsx
// 良好示例 - 无需注释,消息含义清晰
<Trans>
Your password must contain at least 8 characters, including one uppercase letter and one number.
</Trans>Workflow
工作流程
When implementing or reviewing Lingui messages:
- Read the message: Look at the string itself
- Check context: Consider where and how it's used in the code
- Ask: "Could a translator misinterpret this without seeing the UI?"
- If yes: Add a field with location, purpose, and any disambiguation
comment - If no: Skip the comment and keep the code clean
在实现或审核Lingui消息时:
- 阅读消息:查看字符串本身
- 检查上下文:考虑其在代码中的使用位置和方式
- 提问:“如果看不到UI,翻译人员是否会误解这条消息?”
- 如果是:添加包含位置、用途和消歧义说明的字段
comment - 如果否:跳过注释,保持代码简洁
Notes
注意事项
- Comments are extracted into message catalogs for translators
- Comments are stripped from production builds (zero runtime cost)
- Comments appear in translation management systems (TMS)
- Use consistent terminology across all comments in your project
- 注释会被提取到供翻译人员使用的消息目录中
- 注释会在生产构建中被移除(无运行时成本)
- 注释会显示在翻译管理系统(TMS)中
- 在项目的所有注释中使用一致的术语