# react-native: 共享字符串
URL: https://generaltranslation.com/zh/docs/react-native/guides/shared-strings.mdx
---
title: 共享字符串
description: 如何为多个组件和文件共用的字符串实现国际化
---
{/* 自动生成:请勿直接修改。请改为编辑 content/docs-templates/ 中的 template。 */}
共享字符串是指在整个应用的多个位置重复使用的文本值,例如导航标签、表单消息或设置数据。与其在各处重复编写翻译逻辑,不如使用 [`msg`](/docs/react-native/api/strings/msg) 将字符串标记为可翻译,再用 [`useMessages`](/docs/react-native/api/strings/use-messages) 对其进行解码。
## 共享内容存在的问题
来看一下这个在整个应用中复用的导航配置:
```tsx
// navData.ts
export const navData = [
{
label: 'Home',
description: 'The home page',
href: '/'
},
{
label: 'About',
description: 'Information about the company',
href: '/about'
}
];
```
要把这段内容国际化,你通常需要:
1. 把它改成一个接受翻译函数的函数
2. 更新每一处用法,改为传入 `t` 来调用该函数
3. 在整个代码库中处理由此带来的复杂性
这不仅会增加维护成本,也会让代码更难读。[`msg`](/docs/react-native/api/strings/msg) 函数解决了这个问题:你可以直接在原处标记需要翻译的字符串,并在需要时再将其解码。
## 快速开始
使用 [`msg`](/docs/react-native/api/strings/msg) 标记字符串,再用 [`useMessages`](/docs/react-native/api/strings/use-messages) 将其解码:
```tsx
// navData.ts - 标记字符串以供翻译
import { msg } from 'gt-react-native';
export const navData = [
{
label: msg('Home'),
description: msg('The home page'),
href: '/'
},
{
label: msg('About'),
description: msg('Information about the company'),
href: '/about'
}
];
```
```tsx
// 组件用法 - 解码已标记的字符串
import { useMessages } from 'gt-react-native';
import { navData } from './navData';
function Navigation() {
const m = useMessages();
return (
);
}
```
## 共享字符串的工作原理
共享字符串机制分为两个阶段:
1. **标记阶段**:[`msg`](/docs/react-native/api/strings/msg) 使用翻译元数据对字符串进行编码
2. **解码阶段**:[`useMessages`](/docs/react-native/api/strings/use-messages) 对字符串进行解码并完成翻译
```tsx
// msg() 将字符串与元数据一起编码
const encoded = msg('Hello, world!');
console.log(encoded); // "Hello, world!:eyIkX2hhc2giOiJkMjA3MDliZGExNjNlZmM2In0="
// useMessages() 解码并翻译
const m = useMessages();
const translated = m(encoded); // 以用户语言显示的 "Hello, world!"
```
来自 [`msg`](/docs/react-native/api/strings/msg) 的已编码字符串不能直接使用,必须先通过 [`useMessages`](/docs/react-native/api/strings/use-messages) 解码。
## 组件
使用 [`useMessages`](/docs/react-native/api/strings/use-messages) Hook:
```tsx
import { useMessages } from 'gt-react-native';
const encodedString = msg('Hello, world!');
function MyComponent() {
const m = useMessages();
return
{m(encodedString)}
;
}
```
## 使用 decodeMsg 获取原始字符串
有时你需要在不经过翻译的情况下访问原始字符串,例如用于记录日志、调试或比较。这时可使用 [`decodeMsg`](/docs/react-native/api/strings/msg) 提取原始文本:
```tsx
import { decodeMsg } from 'gt-react-native';
const encoded = msg('Hello, world!');
const original = decodeMsg(encoded); // "Hello, world!"(原始字符串)
const translated = m(encoded); // "Hello, world!"(用户语言版本)
// 适用于日志记录或调试
console.log('原始字符串:', decodeMsg(encoded));
console.log('已翻译字符串:', m(encoded));
```
### decodeMsg 的适用场景
* **开发与调试**:记录原始字符串,便于排查问题
* **回退处理**:翻译失败时使用原始文本
* **字符串比较**:与已知的原始值进行比较
* **分析统计**:跟踪原始字符串的使用情况
```tsx
// 示例:回退处理
function getDisplayText(encodedStr) {
const m = useMessages();
try {
return m(encodedStr);
} catch (error) {
console.warn('翻译失败,使用原始字符串:', decodeMsg(encodedStr));
return decodeMsg(encodedStr);
}
}
```
## 使用变量
对于包含动态内容的字符串,请使用占位符并传入变量:
```tsx
// 标记含变量的字符串
const items = 100;
export const pricing = [
{
name: 'Basic',
price: 100,
description: msg('The basic plan includes {items} items', { items })
}
];
```
```tsx
// 在组件中使用
function PricingCard() {
const m = useMessages();
return (
{pricing[0].name}
{m(pricing[0].description)}
);
}
```
### ICU 消息格式
如需更高级的格式控制,请使用 ICU 语法:
```tsx
const count = 10;
const message = msg('There are {count, plural, =0 {no items} =1 {one item} other {{count} items}} in the cart', { count });
```
可在 [Unicode 文档](https://unicode-org.github.io/icu/userguide/format_parse/messages/)中进一步了解 ICU 消息格式。
## 示例
### 导航配置
```tsx
// config/navigation.ts
import { msg } from 'gt-react-native';
export const mainNav = [
{
label: msg('Home'),
href: '/',
icon: 'home'
},
{
label: msg('Products'),
href: '/products',
icon: 'package'
},
{
label: msg('About Us'),
href: '/about',
icon: 'info'
}
];
export const footerLinks = [
{
title: msg('Company'),
links: [
{ label: msg('About'), href: '/about' },
{ label: msg('Careers'), href: '/careers' },
{ label: msg('Contact'), href: '/contact' }
]
},
{
title: msg('Support'),
links: [
{ label: msg('Help Center'), href: '/help' },
{ label: msg('Documentation'), href: '/docs' },
{ label: msg('API Reference'), href: '/api' }
]
}
];
```
```tsx
// components/Navigation.tsx
import { useMessages } from 'gt-react-native';
import { mainNav } from '../config/navigation';
function Navigation() {
const m = useMessages();
return (
);
}
```
### 表单设置
```tsx
// config/forms.ts
import { msg } from 'gt-react-native';
export const formMessages = {
placeholders: {
email: msg('Enter your email address'),
password: msg('Enter your password'),
message: msg('Type your message here...')
},
actions: {
send: msg('Send Message'),
save: msg('Save Changes'),
cancel: msg('Cancel')
},
validation: {
required: msg('This field is required'),
email: msg('Please enter a valid email address'),
minLength: msg('Must be at least {min} characters', { min: 8 }),
maxLength: msg('Cannot exceed {max} characters', { max: 100 })
},
success: {
saved: msg('Changes saved successfully'),
sent: msg('Message sent successfully'),
updated: msg('Profile updated')
},
errors: {
network: msg('Network error - please try again'),
server: msg('Server error - please contact support'),
timeout: msg('Request timed out - please try again')
}
};
```
```tsx
// components/ContactForm.tsx
import { useMessages } from 'gt-react-native';
import { formMessages } from '../config/forms';
function ContactForm() {
const m = useMessages();
const [errors, setErrors] = useState({});
return (
);
}
```
### 动态生成内容
```tsx
// utils/productData.ts
import { msg } from 'gt-react-native';
function mockProducts() {
return [
{ name: 'iPhone 15', company: 'Apple', category: 'Electronics' },
{ name: 'Galaxy S24', company: 'Samsung', category: 'Electronics' }
];
}
export function getProductData() {
const products = mockProducts();
return products.map(product => ({
...product,
description: msg('{name} is a {category} product by {company}', {
name: product.name,
category: product.category,
company: product.company
})
}));
}
```
```tsx
// components/ProductList.tsx
import { useMessages } from 'gt-react-native';
import { getProductData } from '../utils/productData';
function ProductList() {
const m = useMessages();
const products = getProductData();
return (
{products.map(product => (
{product.name}
{m(product.description)}
))}
);
}
```
## 常见问题
### 直接使用已编码的字符串
绝不要直接使用 [`msg`](/docs/react-native/api/strings/msg) 的输出:
```tsx
// ❌ 错误 - 直接使用编码后的字符串
const encoded = msg('Hello, world!');
return {encoded}
; // 显示的是编码字符串,而非翻译结果
// ✅ 正确 - 先解码字符串
const encoded = msg('Hello, world!');
const m = useMessages();
return {m(encoded)}
; // 显示正确的翻译结果
```
### msg() 中的动态内容
字符串必须在构建阶段就确定:
```tsx
// ❌ 错误 - 动态模板字面量
const name = 'John';
const message = msg(`Hello, ${name}`); // 构建时错误
// ✅ 正确 - 使用变量
const name = 'John';
const message = msg('Hello, {name}', { name });
```
### 忘记解码
每个 [`msg`](/docs/react-native/api/strings/msg) 字符串都需要先解码:
```tsx
// ❌ 缺少解码
const config = {
title: msg('Dashboard'),
subtitle: msg('Welcome back')
};
// 在组件中使用时 - 忘记解码
return {config.title}
; // 显示的是编码后的字符串
// ✅ 正确做法 - 使用时进行解码
const m = useMessages();
return {m(config.title)}
; // 显示已翻译的标题
```
## 后续步骤
* [字典指南](/docs/react-native/guides/dictionaries) - 使用结构化数据组织翻译
* [语言指南](/docs/react-native/guides/languages) - 配置支持的语言
* API 参考:
* [`msg` 函数](/docs/react-native/api/strings/msg)