vtex-io-messages-and-i18n
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMessages & Internationalization
消息与国际化
When this skill applies
本技能适用场景
Use this skill when a VTEX IO app needs translated copy instead of hardcoded strings.
- Adding localized UI text to storefront or Admin apps
- Creating or updating translation files
/messages/*.json - Defining message keys in
context.json - Reviewing React, Admin, or backend code that currently hardcodes user-facing copy
- Integrating app-specific translations with
vtex.messages
Do not use this skill for:
- general UI layout or component composition
- authorization, policies, or auth tokens
- service runtime sizing
- choosing between HTTP, GraphQL, and event-driven APIs
当VTEX IO应用需要使用翻译文案而非硬编码字符串时使用本技能。
- 为店面或管理后台应用添加本地化UI文本
- 创建或更新翻译文件
/messages/*.json - 在中定义消息键
context.json - 评审当前硬编码了用户可见文案的React、管理后台或后端代码
- 将应用专属翻译与集成
vtex.messages
本技能不适用于:
- 通用UI布局或组件组合
- 授权、权限策略或身份令牌
- 服务运行时规格调整
- HTTP、GraphQL和事件驱动API的选型
Decision rules
决策规则
- Use the builder and translation files for user-facing copy instead of hardcoding labels, button text, or UI messages in source code.
messages - Keep translation keys stable, explicit, and scoped to the app domain instead of generic keys such as or
title. The exact format may vary, but keys should remain specific, descriptive, and clearly owned by the app.button - Prefix message IDs according to their UI surface or domain, for example for storefront messages and
store/...for Admin or Site Editor messages, so keys stay organized and do not collide across contexts.admin/... - Define message keys in so VTEX IO can discover and manage the app’s translation surface. Keep it as a flat map of
/messages/context.jsonand include the keys the app actually uses.messageId -> description - Keep translated message payloads small and app-focused. Do not turn the messages system into a general content store.
- In React or Admin UIs, prefer message IDs and localization helpers over literal copy in JSX.
- In backend or GraphQL flows, translate only when the app boundary truly needs localized text; otherwise return stable machine-oriented data and let the caller localize the presentation.
- Use app-level overrides of only when the app truly needs to customize translation behavior or message resolution beyond normal app-local message files.
vtex.messages
- 用户可见文案使用构建器和翻译文件管理,不要在源代码中硬编码标签、按钮文本或UI消息。
messages - 翻译键要保持稳定、明确,且归属到应用域名下,不要使用或
title这类通用键。具体格式可以灵活调整,但键必须是具体、描述性强,且明确归属于当前应用的。button - 消息ID要根据其所属UI界面或域名添加前缀,例如店面消息用前缀,管理后台或站点编辑器消息用
store/...前缀,保证键有序且不会在不同上下文下冲突。admin/... - 在中定义消息键,以便VTEX IO发现和管理应用的翻译范围。该文件要保存为
/messages/context.json的扁平映射,且仅包含应用实际使用的键。消息ID -> 描述 - 翻译消息负载要保持精简、聚焦于应用本身。不要将消息系统用作通用内容存储。
- 在React或管理后台UI中,优先使用消息ID和本地化辅助工具,不要在JSX中直接写字面量文案。
- 在后端或GraphQL流程中,仅当应用边界确实需要本地化文本时才做翻译;否则返回稳定的面向机器的数据,由调用方自行处理展示层的本地化。
- 仅当应用确实需要定制超出常规应用本地消息文件的翻译行为或消息解析逻辑时,才在应用层重写。
vtex.messages
Hard constraints
硬性约束
Constraint: User-facing strings must come from the messages infrastructure
约束:用户可见字符串必须来自消息基础设施
User-facing strings MUST come from the messages infrastructure instead of being hardcoded in components, handlers, or resolvers.
Why this matters
Hardcoded copy breaks localization, makes message review harder, and creates inconsistent behavior across storefront, Admin, and backend flows.
Detection
If you see labels, buttons, headings, alerts, or other user-facing text embedded directly in JSX or backend response formatting for a localized app, STOP and move that copy to message files.
Correct
tsx
<FormattedMessage id="admin/my-app.save" />Wrong
tsx
<button>Save</button>用户可见字符串必须来自消息基础设施,不能硬编码在组件、处理器或解析器中。
重要性
硬编码的文案会破坏本地化能力,增加消息评审难度,还会导致店面、管理后台和后端流程的行为不一致。
检测方式
如果在面向本地化的应用中,发现JSX或后端响应格式化代码中直接嵌入了标签、按钮、标题、提示或其他用户可见文本,请立即停止开发,将该文案迁移到消息文件中。
正确示例
tsx
<FormattedMessage id="admin/my-app.save" />错误示例
tsx
<button>Save</button>Constraint: Message keys must be declared and organized explicitly
约束:消息键必须显式声明并有序组织
Message keys MUST be app-scoped and represented in the app’s message configuration instead of being invented ad hoc in code.
Why this matters
Unstructured keys become hard to maintain, collide across app areas, and make message ownership unclear.
Detection
If code introduces new message IDs with no corresponding translation files or entry, STOP and add the message contract explicitly.
context.jsonCorrect
json
{
"admin/my-app.save": "Save"
}Wrong
json
{
"save": "Save"
}消息键必须归属到应用下,且在应用的消息配置中声明,不能在代码中临时随意创建。
重要性
非结构化的键难以维护,会在应用不同模块间发生冲突,也会导致消息归属不清晰。
检测方式
如果代码中引入了新的消息ID,但没有对应的翻译文件或条目,请立即停止开发,显式添加消息约定。
context.json正确示例
json
{
"admin/my-app.save": "Save"
}错误示例
json
{
"save": "Save"
}Constraint: The messages system must not be used as a general content or configuration store
约束:消息系统不得用作通用内容或配置存储
Translation files MUST contain localized copy, not operational configuration, secrets, or large content payloads.
Why this matters
The messages infrastructure is designed for translated strings. Using it for other data creates maintenance confusion and mixes localization concerns with configuration or content storage.
Detection
If message files contain API URLs, credentials, business rules, or long structured content blobs, STOP and move that data to app settings, configuration apps, or a content-specific mechanism.
Correct
json
{
"store/my-app.emptyState.title": "No records found"
}Wrong
json
{
"apiBaseUrl": "https://partner.example.com",
"featureFlags": {
"betaMode": true
}
}翻译文件必须只存放本地化文案,不能存放运营配置、密钥或大容量内容负载。
重要性
消息基础设施是为翻译字符串设计的。将其用于其他数据会导致维护混乱,还会将本地化逻辑与配置或内容存储逻辑耦合。
检测方式
如果消息文件中包含API URL、凭据、业务规则或长结构化内容块,请立即停止开发,将该数据迁移到应用设置、配置应用或专属内容存储机制中。
正确示例
json
{
"store/my-app.emptyState.title": "No records found"
}错误示例
json
{
"apiBaseUrl": "https://partner.example.com",
"featureFlags": {
"betaMode": true
}
}Preferred pattern
推荐模式
Recommended file layout:
text
.
├── messages/
│ ├── context.json
│ ├── en.json
│ └── pt.json
└── react/
└── components/
└── SaveButton.tsxMinimal messages setup:
json
// messages/context.json
{
"admin/my-app.save": "Label for the save action in the admin settings page"
}json
// messages/en.json
{
"admin/my-app.save": "Save",
"store/my-app.emptyState.title": "No records found"
}json
// messages/pt.json
{
"admin/my-app.save": "Salvar"
}tsx
import { FormattedMessage } from 'react-intl'
export function SaveButton() {
return <FormattedMessage id="admin/my-app.save" />
}Backend or GraphQL translation pattern:
graphql
scalar IOMessage
type ProductLabel {
id: ID
label: IOMessage
}
type Query {
productLabel(id: ID!): ProductLabel
}typescript
export const resolvers = {
Query: {
productLabel: async (_: unknown, { id }: { id: string }) => {
return {
id,
label: {
content: 'store/my-app.product-label',
description: 'Label for product badge',
from: 'en-US',
},
}
},
},
}Keep a complete as the default fallback, even when the app’s main audience uses another locale, so the messages system has a stable base for resolution and auto-translation behavior.
en.jsonUse translated IDs in code, keep translation files explicit, and centralize user-facing copy in the messages system instead of scattering literals through the app.
推荐的文件结构:
text
.
├── messages/
│ ├── context.json
│ ├── en.json
│ └── pt.json
└── react/
└── components/
└── SaveButton.tsx最小化消息配置:
json
// messages/context.json
{
"admin/my-app.save": "Label for the save action in the admin settings page"
}json
// messages/en.json
{
"admin/my-app.save": "Save",
"store/my-app.emptyState.title": "No records found"
}json
// messages/pt.json
{
"admin/my-app.save": "Salvar"
}tsx
import { FormattedMessage } from 'react-intl'
export function SaveButton() {
return <FormattedMessage id="admin/my-app.save" />
}后端或GraphQL翻译模式:
graphql
scalar IOMessage
type ProductLabel {
id: ID
label: IOMessage
}
type Query {
productLabel(id: ID!): ProductLabel
}typescript
export const resolvers = {
Query: {
productLabel: async (_: unknown, { id }: { id: string }) => {
return {
id,
label: {
content: 'store/my-app.product-label',
description: 'Label for product badge',
from: 'en-US',
},
}
},
},
}即使应用的主要受众使用其他语言,也要保留完整的作为默认回退版本,这样消息系统才有稳定的解析和自动翻译基础。
en.json代码中使用翻译ID,显式维护翻译文件,将用户可见文案集中存放在消息系统中,不要在应用中散落字面量文案。
Common failure modes
常见错误场景
- Hardcoding user-facing strings in JSX, resolvers, or handler responses.
- Adding new message IDs in code without updating or the message files.
context.json - Using generic or collision-prone keys such as ,
title, orsave.button - Storing configuration values or non-localized business payloads in message files.
- Treating overrides as the default path instead of app-local message management.
vtex.messages
- 在JSX、解析器或处理器响应中硬编码用户可见字符串。
- 在代码中添加新的消息ID,但未更新或消息文件。
context.json - 使用、
title、save这类通用或容易冲突的键。button - 在消息文件中存储配置值或非本地化的业务负载。
- 默认重写,而非优先使用应用本地消息管理能力。
vtex.messages
Review checklist
评审检查清单
- Are user-facing strings sourced from the messages infrastructure instead of hardcoded in code?
- Are message keys explicit, app-scoped, and declared consistently?
- Does reflect the translation surface used by the app?
context.json - Are message files limited to localized copy rather than configuration or operational data?
- Is any customization of truly necessary for this app?
vtex.messages
- 用户可见字符串是否来自消息基础设施,而非代码中硬编码?
- 消息键是否是显式的、归属到应用下、且声明方式统一?
- 是否覆盖了应用实际使用的所有翻译范围?
context.json - 消息文件是否仅存放本地化文案,没有存放配置或运营数据?
- 所有对的定制是否都是应用确实需要的?
vtex.messages
Related skills
相关技能
- - Use when the main question is storefront component structure and shopper-facing UI behavior
vtex-io-storefront-react - - Use when the main question is Admin UI structure and operational interaction patterns
vtex-io-admin-react - - Use when the main question is GraphQL schema and resolver design rather than translation infrastructure
vtex-io-graphql-api
- - 当核心问题是店面组件结构和面向消费者的UI行为时使用
vtex-io-storefront-react - - 当核心问题是管理后台UI结构和运营交互模式时使用
vtex-io-admin-react - - 当核心问题是GraphQL schema和解析器设计而非翻译基础设施时使用
vtex-io-graphql-api
Reference
参考资料
- Messages - VTEX messages app and runtime translation behavior
- Overwriting the Messages app - How app-specific overrides of work
vtex.messages
- Messages - VTEX消息应用与运行时翻译机制
- 重写Messages应用 - 应用专属重写的工作原理
vtex.messages