# 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 (
{errors.email && {m(formMessages.validation.email)}}
); } ``` ### 动态生成内容 ```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)