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

如何在React.js应用中自动查找硬编码文本并迁移至react-i18n的JSON文件?

自动化迁移React硬编码文本到react-i18n的实用方案

手动在React项目里揪出所有硬编码文本迁移到react-i18n确实是个头疼活儿——不仅费时间,还很容易漏掉零散的文本,尤其是在大型项目里。我之前帮不少团队解决过这个问题,下面分享几个靠谱的自动化方案,附带上你提到的NotFoundPage组件的实操示例:

1. 用babel-plugin-react-intl一键提取替换

这是最省心的方案之一,它基于AST(抽象语法树)扫描你的JSX代码,自动提取硬编码文本到语言文件,同时把组件里的文本替换成react-i18n的t()调用。

步骤:

  • 先安装依赖:
    npm install babel-plugin-react-intl --save-dev
    
  • 在你的babel配置文件(.babelrc或babel.config.js)里添加插件配置:
    {
      "plugins": [
        [
          "react-intl",
          {
            "messagesDir": "./src/locales/extracted-messages/", // 提取的临时消息文件存放目录
            "extractFromFormatMessageCall": true
          }
        ]
      ]
    }
    
  • 运行babel编译项目(比如npm run build或者直接用babel-cli处理文件),插件会自动把所有JSX里的文本提取到指定目录的.json文件中。
  • 之后你可以把这些提取的消息整理到react-i18n正式的语言包文件里(比如src/locales/zh-CN.json),大部分场景下插件还会自动帮你替换组件里的文本为t()调用。

对应你的NotFoundPage示例:

改造前的组件:

import React from 'react';

const NotFoundPage = () => {
  return (
    <div>
      <h1>404</h1>
      <p className="subTitle">页面不存在</p>
      <button>返回首页</button>
    </div>
  );
};

export default NotFoundPage;

提取后生成的临时消息文件:

{
  "NotFoundPage.subTitle": "页面不存在",
  "NotFoundPage.button": "返回首页"
}

改造后的组件(插件自动生成):

import React from 'react';
import { useTranslation } from 'react-i18next';

const NotFoundPage = () => {
  const { t } = useTranslation();
  return (
    <div>
      <h1>404</h1>
      <p className="subTitle">{t('NotFoundPage.subTitle')}</p>
      <button>{t('NotFoundPage.button')}</button>
    </div>
  );
};

export default NotFoundPage;

2. 自定义Codemod脚本做定制化处理

如果你的项目有特殊的文本格式(比如包含变量的文本、特定组件的文本),可以用jscodeshift写自定义的codemod脚本,完全按照你的需求来扫描、提取和替换。

核心思路:

  • 遍历所有JSX文件的文本节点,过滤掉空白文本
  • 为每个文本生成唯一的键名(比如基于组件名+文本内容的哈希,或者组件名+元素类型)
  • 把键值对写入统一的JSON语言文件
  • 自动替换组件里的文本为t()调用,同时确保组件导入了useTranslation并初始化

简单的codemod片段示例:

export default function transformer(file, api) {
  const j = api.jscodeshift;
  const root = j(file.source);
  const componentName = file.path.split('/').pop().replace('.jsx', '');
  
  // 收集所有非空白的JSX文本
  const textNodes = [];
  root.find(j.JSXText).forEach(path => {
    const cleanText = path.node.value.trim();
    if (cleanText) textNodes.push({ text: cleanText, path });
  });
  
  // 替换文本并生成i18n键
  textNodes.forEach(({ text, path }) => {
    const i18nKey = `${componentName}.${text.replace(/\s+/g, '_')}`;
    // 把文本替换成t()调用
    j(path).replaceWith(j.jsxExpressionContainer(
      j.callExpression(j.identifier('t'), [j.literal(i18nKey)])
    ));
    // 这里可以额外处理把键值对写入JSON文件的逻辑(需要fs模块)
  });
  
  // 自动添加useTranslation导入
  if (!root.find(j.ImportDeclaration, { source: { value: 'react-i18next' } }).size()) {
    root.find(j.ImportDeclaration).at(0).insertBefore(
      j.importDeclaration(
        [j.importSpecifier(j.identifier('useTranslation'))],
        j.literal('react-i18next')
      )
    );
  }
  
  // 自动添加useTranslation调用
  if (!root.find(j.VariableDeclaration, {
    declarations: [{ id: { type: 'ObjectPattern', properties: [{ key: { name: 't' } }] } }]
  }).size()) {
    root.find(j.FunctionDeclaration).forEach(funcPath => {
      j(funcPath.get('body', 'body')).at(0).insertBefore(
        j.variableDeclaration('const', [
          j.variableDeclarator(
            j.objectPattern([j.objectProperty(j.identifier('t'), j.identifier('t'))]),
            j.callExpression(j.identifier('useTranslation'), [])
          )
        ])
      );
    });
  }
  
  return root.toSource();
}

运行脚本的命令:

npx jscodeshift -t ./your-custom-transformer.js src/components/

3. IDE正则批量替换(轻量场景)

如果项目规模不大,也可以用IDE的正则匹配+批量替换功能辅助:

  • 用正则匹配JSX中的文本,比如(?<=<(?!script|style)[^>]+>)\s*([^<\s].*?)\s*(?=<\/)(可以根据你的代码场景调整)
  • 批量提取匹配到的文本到JSON文件,手动补充键名
  • 再用正则把文本替换成t('你的键名'),比如把匹配到的$1替换成{t('NotFoundPage.$1')}(需要结合组件名调整)

关键注意事项

  • 不管用哪种自动化工具,跑完之后一定要人工校验一遍——动态文本(比如包含{variable}的)、数字类文本(比如404)可能不需要国际化,特殊场景的文本也可能需要手动调整
  • 提前定好i18n键的命名规范,比如组件名.元素类型.功能描述,避免后续键名混乱

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:15:55