npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

babel-plugin-auto-i18n-ast

v1.0.0

Published

Babel plugin for auto i18n with full AST transformation - More precise Chinese to t(key) conversion

Readme

babel-plugin-auto-i18n-ast

基于完整 AST 遍历的 Babel i18n 转换插件,用于 Webpack 等构建工具。相比简单的字符串匹配,AST 方案更加精确,能够准确识别代码结构,避免误转换。

✨ 特性

  • 🎯 完整 AST 遍历 - 使用 Babel 的 visitor 模式精确遍历所有节点
  • 🔍 语义理解 - 自动跳过 import、console、类型注解等不应转换的内容
  • 📦 完整支持 - 支持 JSX、TypeScript、普通 JavaScript
  • 🛡️ 智能检测 - 自动识别已在 i18n 函数中的字符串,避免重复转换
  • 🔧 可配置 - 丰富的配置选项

🔬 AST vs 正则方案对比

| 特性 | AST 方案 (本包) | 正则方案 | |------|----------------|----------| | 精确度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | | 跳过注释 | ✅ 自动 | ❌ 需特殊处理 | | 跳过 import | ✅ 自动 | ❌ 需特殊处理 | | 跳过 console | ✅ 自动 | ❌ 需特殊处理 | | 避免重复转换 | ✅ 完美 | ⚠️ 可能出问题 | | JSX 结构 | ✅ 完美支持 | ⚠️ 可能误匹配 |

📦 安装

# npm
npm install babel-plugin-auto-i18n-ast -D

# pnpm
pnpm add babel-plugin-auto-i18n-ast -D

# yarn
yarn add babel-plugin-auto-i18n-ast -D

🚀 快速开始

Webpack + Babel 配置

// babel.config.js
module.exports = {
  presets: [
    '@babel/preset-env',
    '@babel/preset-react', // 如果使用 React
    '@babel/preset-typescript', // 如果使用 TypeScript
  ],
  plugins: [
    ['babel-plugin-auto-i18n-ast', {
      localesDir: 'locales',  // 语言包目录名(向上查找)或绝对路径
      sourceLocale: 'zh-CN',
      translateFn: 't',
      debug: process.env.NODE_ENV === 'development',
    }],
  ],
}

Webpack 配置

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|jsx|ts|tsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            // babel.config.js 配置会自动加载
          },
        },
      },
    ],
  },
}

语言包结构

// src/locales/zh-CN.json
{
  "hello": "你好世界",
  "welcome": "欢迎使用",
  "button": {
    "submit": "提交",
    "cancel": "取消"
  }
}

转换示例

转换前:

import React from 'react'

function App() {
  const message = '欢迎使用'
  console.log('调试信息') // 不会转换
  
  return (
    <div>
      <h1>你好世界</h1>
      <button title="提交按钮">提交</button>
    </div>
  )
}

转换后:

import React from 'react'

function App() {
  const message = t('welcome')
  console.log('调试信息')
  
  return (
    <div>
      <h1>{t('hello')}</h1>
      <button title={t('button.submit')}>{t('button.submit')}</button>
    </div>
  )
}

⚙️ 配置选项

interface LocalesRule {
  /** 文件路径匹配模式(glob 或正则) */
  match: string | RegExp
  /** 该匹配使用的语言包目录 */
  localesDir: string
  /** 可选的命名空间前缀 */
  namespace?: string
}

interface BabelI18nAstPluginOptions {
  /** 语言包目录名(向上查找)或绝对路径(直接使用)
   * 
   * - 字符串:单一目录名,如 'locales'
   * - 数组:多个目录名,按优先级排序,如 ['locales', 'i18n', 'langs']
   * - 绝对路径:直接使用,不进行向上查找
   * 
   * @default 'locales'
   */
  localesDir?: string | string[]
  
  /** 路径匹配规则(优先级高于 localesDir)
   * 用于特殊项目的精确控制
   */
  localesRules?: LocalesRule[]
  
  /** 源语言代码
   * @default 'zh-CN'
   */
  sourceLocale?: string
  
  /** 翻译函数名
   * @default 't'
   */
  translateFn?: string
  
  /** 调试模式 - 输出详细转换日志
   * @default false
   */
  debug?: boolean
  
  /** 排除的文件模式
   * @default [/node_modules/, /\.d\.ts$/, /\/locales\//, /\/langs\//]
   */
  exclude?: (string | RegExp)[]
  
  /** 缺少翻译时的处理方式
   * - 'warn': 控制台警告(默认)
   * - 'error': 抛出错误,中断构建
   * - 'ignore': 静默忽略
   * @default 'warn'
   */
  onMissing?: 'warn' | 'error' | 'ignore'
}

🔍 AST 转换原理

Babel 插件工作流程

源代码 (.js/.jsx/.ts/.tsx)
           │
           ▼
   @babel/parser (解析)
           │
           ▼
         AST
           │
           ▼
   babel-plugin-auto-i18n-ast (转换)
   ├── visitor.JSXText
   ├── visitor.JSXAttribute  
   ├── visitor.JSXExpressionContainer
   ├── visitor.StringLiteral
   └── visitor.TemplateLiteral
           │
           ▼
      转换后的 AST
           │
           ▼
   @babel/generator (生成)
           │
           ▼
      输出代码

Visitor 模式

插件使用 Babel 的 visitor 模式遍历 AST:

visitor: {
  // JSX 文本: <div>中文</div>
  JSXText(path) {
    // 转换为 <div>{t('key')}</div>
  },
  
  // JSX 属性: <div title="中文">
  JSXAttribute(path) {
    // 转换为 <div title={t('key')}>
  },
  
  // JSX 表达式: {'中文'}
  JSXExpressionContainer(path) {
    // 转换为 {t('key')}
  },
  
  // 普通字符串: const x = '中文'
  StringLiteral(path) {
    // 转换为 const x = t('key')
  },
  
  // 模板字符串: `中文`
  TemplateLiteral(path) {
    // 转换为 t('key')
  },
}

自动跳过的上下文

基于 AST 分析,自动跳过:

  1. Import 声明

    import xxx from '路径' // ✅ 跳过
  2. Console 调用

    console.log('中文日志') // ✅ 跳过
  3. 已在 i18n 函数中

    t('已经转换的') // ✅ 跳过,不会变成 t(t('xxx'))
    tt('直接翻译') // ✅ 跳过
  4. 对象非计算 Key

    const obj = { '中文key': value } // ✅ 跳过 key
  5. 类型注解

    type Status = '成功' | '失败' // ✅ 跳过
  6. Tagged Template

    css`color: red;` // ✅ 跳过

🎯 最佳实践

1. 配合 Vue Webpack

// babel.config.js
module.exports = {
  presets: ['@babel/preset-env'],
  plugins: [
    ['babel-plugin-auto-i18n-ast', {
      localesDir: 'src/locales',
      translateFn: 't', // Vue 脚本中使用 t()
    }],
  ],
}

注意:Vue 模板需要配合 vue-loader 和专门的 Vue i18n 插件处理。

2. 配合 React Webpack

// babel.config.js
module.exports = {
  presets: [
    '@babel/preset-env',
    ['@babel/preset-react', { runtime: 'automatic' }],
  ],
  plugins: [
    ['babel-plugin-auto-i18n-ast', {
      localesDir: 'src/locales',
      translateFn: 't',
    }],
  ],
}

3. 生产环境关闭调试

['babel-plugin-auto-i18n-ast', {
  debug: process.env.NODE_ENV === 'development',
}]

4. 严格模式

['babel-plugin-auto-i18n-ast', {
  onMissing: 'error', // 缺少翻译时报错
}]

📊 调试输出

开启 debug: true 后,控制台会输出:

[babel-i18n-ast] Processing: /src/App.tsx
[babel-i18n-ast] JSX Text: "你好世界" → {t('hello')}
[babel-i18n-ast] JSX Attr: "提交" → {t('button.submit')}
[babel-i18n-ast] Script: "欢迎使用" → t('welcome')
[babel-i18n-ast] Completed: 3 transforms (JSX: 2, Script: 1)

⚠️ 注意事项

  1. 性能考虑:AST 转换在每次编译时执行,建议在生产构建时关闭 debug。

  2. 运行时依赖:需要在运行时提供 t 函数,配合 @mico_fe/i18n-core 或其他运行时库使用。

  3. 动态字符串:以下情况无法自动转换:

    // ❌ 变量
    const key = someCondition ? '成功' : '失败'
       
    // ❌ 带表达式的模板字符串
    const msg = `欢迎 ${name}!`
       
    // ✅ 需要手动处理
    const key = someCondition ? t('success') : t('failure')
    const msg = t('welcome.user', { name })
  4. Vue 模板:此插件只处理 <script> 部分,Vue 模板需要额外的 loader 处理。

🔗 相关包

📄 License

MIT