You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IntlProvider未自动为FormattedMessage注入ID的问题求助

问题描述

按照FormatJS的自动ID生成指南配置IntlProvider下的FormattedMessage组件后,运行时未自动注入ID,控制台报错:

An id must be provided to format a message. You can either:

  1. Configure your build toolchain with babel-plugin-formatjs
    or @formatjs/ts-transformer

基于create-react-app创建React项目,已集成react-intl并遵循官方安装说明,相关配置如下:

项目配置文件

babel.config.json

{
  "plugins": [
    [
      "formatjs",
      {
        "idInterpolationPattern": "[sha512:contenthash:base64:6]",
        "ast": true
      }
    ]
  ]
}

package.json

{
  "name": "react-intl-test",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@types/node": "^16.18.23",
    "@types/react": "^18.0.35",
    "@types/react-dom": "^18.0.11",
    "babel-plugin-formatjs": "^10.4.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-intl": "^6.3.2",
    "react-scripts": "5.0.1",
    "typescript": "^4.9.5"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "extract": "formatjs extract src/**/*.ts* --ignore=**/*.d.ts --out-file lang/en-US.json --id-interpolation-pattern [sha512:contenthash:base64:6]",
    "compile": "formatjs compile lang/en-US.json --ast --out-file src/compiled-lang/en-US.json"
  },
  "eslintConfig": {
    "extends": "react-app",
    "plugins": [
      "formatjs"
    ],
    "rules": {
      "formatjs/no-offset": "error"
    }
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@babel/core": "^7.21.4",
    "@formatjs/cli": "^6.0.4",
    "babel-plugin-formatjs": "^10.4.0",
    "eslint": "^8.38.0",
    "eslint-plugin-formatjs": "^4.9.1"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
  "include": [
    "src"
  ]
}

App.tsx

import React from 'react';
import './App.css';
import { FormattedMessage } from 'react-intl';

function App() {
  return (
    <div className="App">
      hello <FormattedMessage description="other part of hello world" defaultMessage='world'></FormattedMessage>
    </div>
  );
}

export default App;

en-US.json

{
  "Oup1TP": [
    {
      "type": 0,
      "value": "world"
    }
  ]
}

已启用enforceId lint规则,可匹配到en-US.json中的ID;手动添加ID时应用正常,但自动ID注入未生效。

解决方法

核心原因

create-react-app默认不会加载项目根目录的babel.config.json,导致配置的babel-plugin-formatjs未在编译阶段生效,无法自动为FormattedMessage注入ID。

方案1:用react-app-rewired自定义Babel配置

  1. 安装依赖:
npm install react-app-rewired customize-cra --save-dev
  1. 在项目根目录创建config-overrides.js:
const { override, addBabelPlugin } = require('customize-cra');

module.exports = override(
  addBabelPlugin([
    'formatjs',
    {
      idInterpolationPattern: '[sha512:contenthash:base64:6]',
      ast: true
    }
  ])
);
  1. 修改package.json中的启动脚本:
"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  "eject": "react-scripts eject"
}

方案2:使用TypeScript Transformer(适合TS项目)

  1. 安装依赖:
npm install @formatjs/ts-transformer --save-dev
  1. 通过craco配置webpack,在ts-loader中添加transformer,创建craco.config.js:
const { default: formatjsTransformer } = require('@formatjs/ts-transformer');

module.exports = {
  typescript: {
    configure: (webpackConfig) => {
      webpackConfig.module.rules.forEach(rule => {
        if (rule.oneOf) {
          rule.oneOf.forEach(oneOfRule => {
            if (oneOfRule.test?.toString().includes('tsx|ts')) {
              oneOfRule.options.getCustomTransformers = () => ({
                before: [formatjsTransformer({
                  idInterpolationPattern: '[sha512:contenthash:base64:6]'
                })]
              });
            }
          });
        }
      });
      return webpackConfig;
    }
  }
};
  1. 修改package.json脚本使用craco启动:
"scripts": {
  "start": "craco start",
  "build": "craco build",
  "test": "craco test"
}

方案3:Eject项目(不推荐)

执行npm run eject暴露项目配置后,修改config/webpack.config.js中的babel-loader配置,手动添加formatjs插件。

额外检查

确保IntlProvider正确包裹应用,并加载编译后的语言文件:

import { IntlProvider } from 'react-intl';
import enUS from './compiled-lang/en-US.json';
import App from './App';

ReactDOM.render(
  <IntlProvider locale="en-US" messages={enUS}>
    <App />
  </IntlProvider>,
  document.getElementById('root')
);

内容的提问来源于stack exchange,提问作者xzist

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 19:42:02