enhanced-message-context

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Enhanced 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
comment
field when the message:
  • 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}
      (count of what?),
      {name}
      (user name, file name, project name?)
当消息满足以下情况时,添加
comment
字段:
  • 存在歧义:可作为不同词性的简短词汇/短语
    • "Back"(名词还是动词?)、"Delete"(按钮还是确认操作?)、"Close"(动词还是形容词?)
  • 缺乏UI语境:脱离周边环境的标签
    • 表格列标题、提示框内容、独立按钮标签、菜单项
  • 具有领域特定含义:在不同语境下含义不同的术语
    • "Post"(动词还是名词?)、"Tag"(名词还是动词?)、"Follow"(社交媒体关注还是指令?)
  • 依赖语法性别:翻译结果取决于消息所指代的对象
    • "Selected"(阴/阳/中性形式取决于被选中的对象)
  • 使用不明确变量:占位符名称无法体现其内容
    • {count}
      (统计的是什么?)、
      {name}
      (用户名、文件名还是项目名?)

When to Skip Comments

何时跳过注释

Skip the
comment
field when the message:
  • 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:
  1. 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"
  2. 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"
  3. 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"
优质的翻译注释应包含:
  1. 位置:消息在UI中的显示位置
    • "顶部导航栏中的按钮"
    • "保存图标对应的提示框"
    • "用户表格中的列标题"
  2. 操作/用途:对应的操作或含义
    • "返回上一页"
    • "永久删除选中项"
    • "显示未读通知的数量"
  3. 消歧义说明:明确词性或含义
    • "用作动词,而非名词"
    • "指代电子邮箱地址,而非邮政地址"
    • "单数形式,用户将根据数量看到'item'或'items'"

API Reference

API参考

Lingui provides three ways to add translator comments:
Lingui提供三种添加翻译注释的方式:

1. JS Macro (
t
)

1. JS宏(
t

For 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
)

2. React宏(
Trans

For 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
)

3. 延迟/懒加载消息(
defineMessage
/
msg

For 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:
  1. Read the message: Look at the string itself
  2. Check context: Consider where and how it's used in the code
  3. Ask: "Could a translator misinterpret this without seeing the UI?"
  4. If yes: Add a
    comment
    field with location, purpose, and any disambiguation
  5. If no: Skip the comment and keep the code clean
在实现或审核Lingui消息时:
  1. 阅读消息:查看字符串本身
  2. 检查上下文:考虑其在代码中的使用位置和方式
  3. 提问:“如果看不到UI,翻译人员是否会误解这条消息?”
  4. 如果是:添加包含位置、用途和消歧义说明的
    comment
    字段
  5. 如果否:跳过注释,保持代码简洁

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)中
  • 在项目的所有注释中使用一致的术语