React - react -intl 中FormattedMessage组件中如何传递参数

react-intlFormattedMessage 组件中,可以通过 values 属性来传递参数。这个属性接收一个对象,对象的键对应消息中的变量名。

基本用法

1. 简单变量替换

首先,在语言文件中定义带有变量的消息:

src/locales/en.json

{
  "greeting": "Hello, {name}!",
  "welcome": "Welcome, {username}. You have {count} messages.",
  "product.info": "Product: {productName}, Price: {price}"
}

src/locales/zh.json

{
  "greeting": "你好,{name}!",
  "welcome": "欢迎,{username}。您有 {count} 条消息。",
  "product.info": "产品:{productName},价格:{price}"
}

然后在组件中传递参数:

import React from "react";
import { FormattedMessage } from "react-intl";

function UserGreeting() {
  return (
    <div>
      {/* 传递字符串参数 */}
      <h1>
        <FormattedMessage id="greeting" values={{ name: "张三" }} />
      </h1>

      {/* 传递多个参数 */}
      <p>
        <FormattedMessage
          id="welcome"
          values={{
            username: "李四",
            count: 5,
          }}
        />
      </p>
    </div>
  );
}

2. 传递动态数据

可以从组件的 state、props 或变量中传递动态数据:

import React, { useState } from "react";
import { FormattedMessage } from "react-intl";

function UserDashboard({ user }) {
  const [messageCount, setMessageCount] = useState(10);

  return (
    <div>
      {/* 从 props 传递数据 */}
      <FormattedMessage id="greeting" values={{ name: user.name }} />

      {/* 从 state 传递数据 */}
      <FormattedMessage
        id="welcome"
        values={{
          username: user.username,
          count: messageCount,
        }}
      />

      {/* 传递计算结果 */}
      <FormattedMessage
        id="product.info"
        values={{
          productName: "笔记本电脑",
          price: `$${user.balance}`,
        }}
      />
    </div>
  );
}

高级用法

1. 传递 React 组件作为参数

FormattedMessagevalues 属性不仅可以传递字符串和数字,还可以传递React 组件,实现富文本格式化:

import React from "react";
import { FormattedMessage } from "react-intl";

function RichTextExample() {
  return (
    <div>
      <FormattedMessage
        id="terms.agreement"
        values={{
          // 传递链接组件
          termsLink: (chunks) => <a href="/terms">{chunks}</a>,
          privacyLink: (chunks) => <a href="/privacy">{chunks}</a>,
          // 传递带样式的文本
          bold: (chunks) => <strong>{chunks}</strong>,
        }}
      />
    </div>
  );
}

对应的语言文件:

{
  "terms.agreement": "I agree to the {termsLink}Terms of Service{/termsLink} and {privacyLink}Privacy Policy{/privacyLink}. This is {bold}important{/bold}."
}

2. 格式化数字和日期

可以在传递参数前进行格式化,或者结合其他 react-intl 组件:

import React from "react";
import { FormattedMessage, FormattedNumber, FormattedDate } from "react-intl";

function ProductDisplay({ product }) {
  return (
    <div>
      {/* 方法1:传递格式化后的值 */}
      <FormattedMessage
        id="product.info"
        values={{
          name: product.name,
          price: (
            <FormattedNumber
              value={product.price}
              style="currency"
              currency="USD"
            />
          ),
          date: (
            <FormattedDate
              value={product.releaseDate}
              year="numeric"
              month="long"
              day="numeric"
            />
          ),
        }}
      />

      {/* 方法2:在 values 中直接传递数字,让 react-intl 自动格式化 */}
      <FormattedMessage
        id="product.stats"
        values={{
          sales: product.sales,
          rating: product.rating,
        }}
      />
    </div>
  );
}

语言文件:

{
  "product.info": "Product: {name}, Price: {price}, Released: {date}",
  "product.stats": "Sales: {sales, number} units, Rating: {rating, number, ::.1f}"
}

3. 条件格式化(复数化)

react-intl 支持 ICU 消息语法,可以在消息内部处理复数逻辑:

{
  "messages.count": "You have {count, plural, =0 {no messages} one {# message} other {# messages}}.",
  "items.count": "{count, plural, =0 {No items} one {1 item} other {{count} items}} in cart"
}

使用时只需传递数字参数:

function MessageCounter({ count }) {
  return (
    <div>
      <FormattedMessage id="messages.count" values={{ count: count }} />
    </div>
  );
}

// 使用示例:
// count = 0  -> "You have no messages."
// count = 1  -> "You have 1 message."
// count = 5  -> "You have 5 messages."

4. 传递数组

function CategoryList({ categories }) {
  return (
    <div>
      <FormattedMessage
        id="categories.display"
        values={{
          // 传递数组并格式化
          list: categories.join(", "),
          // 或者传递整个数组
          items: categories,
        }}
      />
    </div>
  );
}

语言文件:

{
  "categories.display": "Categories: {list}. Total: {items.length} items"
}

完整的实际示例

import React, { useState } from "react";
import { FormattedMessage, useIntl } from "react-intl";

function ShoppingCart() {
  const [cart, setCart] = useState([
    { id: 1, name: "Laptop", price: 999.99, quantity: 1 },
    { id: 2, name: "Mouse", price: 29.99, quantity: 2 },
  ]);

  const intl = useIntl();

  const total = cart.reduce((sum, item) => sum + item.price * item.quantity, 0);

  return (
    <div>
      <h2>
        <FormattedMessage id="cart.title" />
      </h2>

      {cart.map((item) => (
        <div key={item.id}>
          <FormattedMessage
            id="cart.item"
            values={{
              name: item.name,
              price: intl.formatNumber(item.price, {
                style: "currency",
                currency: "USD",
              }),
              quantity: item.quantity,
              // 使用组件作为参数
              removeButton: (chunks) => (
                <button onClick={() => removeItem(item.id)}>{chunks}</button>
              ),
            }}
          />
        </div>
      ))}

      <div className="total">
        <FormattedMessage
          id="cart.total"
          values={{
            total: intl.formatNumber(total, {
              style: "currency",
              currency: "USD",
            }),
            itemCount: cart.length,
          }}
        />
      </div>

      <button>
        <FormattedMessage
          id="cart.checkout"
          values={{ itemCount: cart.length }}
        />
      </button>
    </div>
  );
}

export default ShoppingCart;

对应的语言文件:

{
  "cart.title": "Shopping Cart",
  "cart.item": "{name} - {price} x {quantity} {removeButton}Remove{/removeButton}",
  "cart.total": "Total: {total} ({itemCount, plural, =0 {no items} one {# item} other {# items}})",
  "cart.checkout": "Checkout ({itemCount, plural, =0 {empty} other {# items}})"
}

总结

参数类型 示例 说明
字符串 values={{ name: '张三' }} 最简单的文本替换
数字 values={{ count: 5 }} 用于计数或配合复数语法
组件 values={{ link: (chunks) => <a>{chunks}</a> }} 实现富文本
格式化值 values={{ price: <FormattedNumber value={99.9} /> }} 嵌套使用其他格式化组件
数组 values={{ items: ['a', 'b'] }} 传递列表数据

values 属性非常灵活,可以满足各种动态内容的国际化需求。

posted @ 2026-03-22 22:20  箫笛  阅读(1)  评论(0)    收藏  举报