enhanced-message-context
Enhanced Message Context
When implementing Lingui i18n, add translator comments to messages so translators have context to provide the best translation. Even when the message text is self-explanatory, it is important to know where and how it appears in the UI to choose the correct tone, length, and wording.
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?)
- Could benefit from UI context even if clear: Where the text appears (button, dialog, banner, form field) affects tone and length - add a brief location or purpose comment when it helps.
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"
API Reference
Lingui provides three ways to add translator comments:
1. JS Macro (t)
For JavaScript code outside JSX:
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`,
});
2. React Macro (Trans)
For JSX elements:
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>
3. Deferred/Lazy Messages (defineMessage / msg)
For messages defined separately from their usage:
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
Before (no context):
<button onClick={goBack}>
<Trans>Back</Trans>
</button>
After (with context):
<button onClick={goBack}>
<Trans comment="Button in the toolbar that navigates to the previous page">
Back
</Trans>
</button>
Example 2: UI Label Without Context
Before (no context):
const columns = [
{ key: "name", label: t`Name` },
{ key: "status", label: t`Status` },
];
After (with context):
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
Before (ambiguous):
<button onClick={handlePost}>
<Trans>Post</Trans>
</button>
After (clarified as verb):
<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
Before (unclear what count represents):
const message = t`${count} items selected`;
After (clarified):
const message = t({
comment: "Shows the number of email messages currently selected in the inbox",
message: `${count} items selected`,
});
Example 5: Self-Explanatory Message (Comment Still Optional but Helpful)
// Message is clear on its own; adding a comment with location still helps translators
<Trans comment="Validation hint shown below the password field on the sign-up form">
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
commentfield with location, purpose, and any disambiguation - If no: Skip the comment and keep the code clean
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
More from lingui/skills
lingui-best-practices
Implement internationalization with Lingui in React and JavaScript applications. Use when adding i18n, translating UI, working with Trans/useLingui/Plural, extracting messages, compiling catalogs, or when the user mentions Lingui, internationalization, i18n, translations, locales, message extraction, ICU MessageFormat, or working with .po files.
145swc-plugin-compatibility
Diagnose and fix Lingui SWC plugin compatibility errors with Next.js, Rspack, or other SWC runtimes. Use when seeing errors like "failed to invoke plugin", "failed to run Wasm plugin transform", "out of bounds memory access", or "LayoutError" during builds with @lingui/swc-plugin.
46migrate-i18next-to-lingui
Migrate i18next/react-i18next projects to Lingui. Use when the user wants to replace i18next, react-i18next, useTranslation, i18n.t(), Trans i18nKey, or i18next JSON catalogs with Lingui equivalents. Covers package installation, config setup, code transformation patterns, plural migration, namespace handling, and catalog conversion.
6