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

@gulibs/react-vintl

v0.0.20

Published

Type-safe i18n library for React with Vite plugin and automatic type inference

Readme

@gulibs/react-vintl

🌍 为 React 设计的类型安全 i18n 库,具有自动类型推断功能 - 无需单独的键文件!

✨ 特性

  • 🎯 完美的 IDE 自动补全 - 联合类型生成提供无与伦比的自动补全体验(例如,输入 t('common. 会显示所有 common.* 键)
  • 极致 API 设计 - useTranslation() 直接返回函数,无需解构!
  • 🚀 零配置 - 开箱即用,具有合理的默认设置
  • 🔥 热模块替换 - 翻译文件的更改会立即更新类型和 UI
  • 📦 Vite 插件 - 与您的 Vite 工作流无缝集成
  • 🎨 React Hooks 和组件 - 适用于所有用例的灵活 API
  • 🌐 多种文件格式 - 支持 JSON、TypeScript 和 JavaScript
  • 💪 完全类型安全 - 无效翻译键的编译时错误
  • 🔄 命名空间支持 - 使用点记法的有序分层键结构
  • 🔄 自动类型同步 - 添加新字段后编辑器立即识别,无需重启 TypeScript 服务器
  • 🌐 远程翻译加载 - 支持从网络接口动态加载翻译并自动合并

📦 安装

npm install @gulibs/react-vintl
# 或
pnpm add @gulibs/react-vintl
# 或
yarn add @gulibs/react-vintl

🚀 快速开始

1. 配置 Vite 插件

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { createReactVintlPlugin } from '@gulibs/react-vintl'

export default defineConfig({
  plugins: [
    react(),
    createReactVintlPlugin({
      basePath: 'src/locales',
      debug: true
    })
  ]
})

2. 创建翻译文件

src/locales/
├── en/
│   ├── common.json
│   └── auth.json
└── zh/
    ├── common.json
    └── auth.json

翻译文件示例:

// src/locales/en/common.json
{
  "welcome": "Welcome",
  "buttons": {
    "save": "Save",
    "cancel": "Cancel"
  }
}
// src/locales/zh/common.json
{
  "welcome": "欢迎",
  "buttons": {
    "save": "保存",
    "cancel": "取消"
  }
}

3. 在您的应用中使用

// src/App.tsx
import { I18nProvider, useTranslation, useI18n, Translation } from '@gulibs/react-vintl'
import { resources, supportedLocales } from '@gulibs/react-vintl-locales'

function ExampleComponent() {
  // ✅ 极致 API:useTranslation 直接返回翻译函数
  const t = useTranslation()

  // ✅ 用于全局状态的独立钩子
  const { locale, setLocale } = useI18n()

  return (
    <div>
      <h1>{t('common.welcome')}</h1>
      <button>{t('common.buttons.save')}</button>

      {/* 使用 Translation 组件 */}
      <Translation keyPath="common.welcome" />

      {/* 语言切换器 */}
      <select value={locale} onChange={e => setLocale(e.target.value)}>
        {supportedLocales.map(loc => (
          <option key={loc} value={loc}>{loc}</option>
        ))}
      </select>
    </div>
  )
}

export default function App() {
  return (
    <I18nProvider
      resources={resources}
      defaultLocale="en"
      supportedLocales={supportedLocales}
    >
      <ExampleComponent />
    </I18nProvider>
  )
}

📖 API 参考

插件选项

interface I18nPluginOptions {
  basePath?: string              // 默认: 'src/locales'
  extensions?: string[]          // 默认: ['.json', '.ts', '.js']
  localePattern?: 'directory' | 'filename'  // 默认: 'directory'
  hmr?: boolean                  // 默认: true
  debug?: boolean                // 默认: false
}

钩子

useTranslation(namespace?)

新特性: 直接返回翻译函数 - 无需解构!

// 无命名空间 - 完整键路径
const t = useTranslation()
t('common.welcome')           // ✅ 完整自动补全
t('auth.login.title')         // ✅ 所有键都可用

// 带命名空间 - 相对键路径
const tCommon = useTranslation('common')
tCommon('welcome')            // ✅ 仅 common.* 键
tCommon('buttons.save')       // ✅ 作用域自动补全

const tAuth = useTranslation('auth')
tAuth('login.title')          // ✅ 仅 auth.* 键

// 带参数
const text = t('messages.greeting', { name: 'World' })

类型签名:

function useTranslation(): TranslationFunction
function useTranslation<N extends I18nNamespaces>(namespace: N): NamespacedTranslationFunction<N>

useI18n()

新特性: 从翻译函数中独立获取全局 i18n 状态。

const { locale, supportedLocales, setLocale, resources } = useI18n()

// 现在您可以多次调用 useTranslation 而不会产生冗余状态
const t1 = useTranslation('common')
const t2 = useTranslation('auth')
const { locale } = useI18n()  // 只获取状态一次

useLocale()

用于语言切换的 useI18n() 简化版本。

const { locale, supportedLocales, setLocale, isSupportedLocale } = useLocale()

useTranslationKey(key, params?)

返回带有记忆化的特定翻译。

const { translation, t } = useTranslationKey('common.welcome')

useLoadRemoteTranslations(source, options?)

新特性: 从外部接口加载翻译资源并自动合并到现有资源。

支持三种加载方式:

  • URL 字符串: 从 HTTP 接口加载
  • 函数: 从自定义加载函数获取
  • Promise: 从 Promise 获取
// 从 URL 加载
const { loading, error, data, retry } = useLoadRemoteTranslations(
  'https://api.example.com/translations/en',
  {
    namespace: 'remote',  // 合并到指定的 namespace
    locale: 'en',
    merge: true,         // 自动合并(默认 true)
    cache: true,         // 启用缓存(默认 true)
    onSuccess: (resources) => console.log('Loaded:', resources),
    onError: (error) => console.error('Error:', error),
    retry: 3,            // 重试次数
    retryDelay: 1000    // 重试延迟(毫秒)
  }
)

// 从函数加载
const loader = useLoadRemoteTranslations(
  () => fetch('/api/translations').then(r => r.json()),
  { namespace: 'remote' }
)

// 从 Promise 加载
const promiseLoader = useLoadRemoteTranslations(
  fetch('/api/translations').then(r => r.json()),
  { namespace: 'remote' }
)

// 使用合并后的翻译(立即可用)
const t = useTranslation()
t('remote.title' as any)  // 动态字段需要使用类型断言

选项说明:

interface LoadRemoteTranslationsOptions {
  locale?: string        // 目标语言,默认使用当前语言
  namespace?: string     // 合并到指定的 namespace(可选)
  merge?: boolean        // 是否自动合并(默认 true)
  cache?: boolean        // 是否启用缓存(默认 true)
  onSuccess?: (resources: I18nResources) => void
  onError?: (error: Error) => void
  retry?: number         // 重试次数(默认 0)
  retryDelay?: number    // 重试延迟(毫秒,默认 1000)
}

返回值:

interface LoadRemoteTranslationsResult {
  loading: boolean       // 是否正在加载
  error: Error | null    // 错误信息
  data: I18nResources | null  // 加载的数据
  retry: () => void      // 手动重试函数
}

特性:

  • ✅ 自动合并到现有资源
  • ✅ 支持 namespace 级别的合并
  • ✅ 支持根级别合并(不指定 namespace)
  • ✅ 加载状态管理(loading、error、data)
  • ✅ 智能缓存机制避免重复请求
    • 不同的 namespace 配置使用不同的缓存键,避免冲突
    • 支持缓存过期时间(默认 5 分钟)
  • ✅ 请求去重(多个组件同时加载相同资源)
  • ✅ 错误处理和重试机制
  • ✅ 加载后翻译立即可用
  • ✅ 资源合并后自动更新翻译函数

完整示例:

查看 test/src/RemoteTranslationDemo.tsx 获取完整的使用示例。

组件

<Translation>

渲染带有可选参数和命名空间支持的翻译。

{/* 无命名空间 - 完整键路径 */}
<Translation keyPath="common.welcome" />
<Translation keyPath="auth.login.title" params={{ name: 'React' }} />

{/* 带命名空间 - 相对键路径 */}
<Translation namespace="common" keyPath="welcome" />
<Translation namespace="auth" keyPath="login.title" />

{/* 自定义渲染 */}
<Translation keyPath="common.welcome" fallback="Welcome">
  {text => <strong>{text}</strong>}
</Translation>

<T>

<Translation> 组件的别名。

<T keyPath="common.welcome" />
<T namespace="auth" keyPath="logout" />

<LocaleSwitcher>

内置语言切换器组件。

<LocaleSwitcher />

⚡ 极致 API 设计

react-vintl 遵循现代 React Hooks 约定,通过直接返回函数而不是对象。

对象返回的问题

// ❌ 传统方法 - 需要解构
const { t } = useTranslation()
const { t: tCommon } = useTranslation('common')
const { t: tAuth, locale } = useTranslation('auth')
// 问题:冗长,冗余的状态访问

我们的解决方案:直接函数返回

// ✅ 极致 API - 直接函数返回
const t = useTranslation()              // 无需解构!
const tCommon = useTranslation('common')
const tAuth = useTranslation('auth')

// ✅ 独立的状态访问
const { locale, setLocale } = useI18n() // 仅在需要时

优势

  1. 更简洁的代码

    const t = useTranslation()          // 对比 const { t } = useTranslation()
  2. 清晰的关注点分离

    • useTranslation() → 翻译函数
    • useI18n() → 全局状态管理
    • useLocale() → 语言切换
  3. 更好的性能

    • 使用多个命名空间时不会创建冗余对象
    • 减少内存占用
  4. 遵循 React 约定

    • useRef() - 直接返回 ref
    • useCallback() - 直接返回函数
    • useMemo() - 直接返回值

实际示例

function MyComponent() {
  // 多个翻译函数 - 无冗余
  const tCommon = useTranslation('common')
  const tAuth = useTranslation('auth')
  const tProducts = useTranslation('products')

  // 全局状态 - 只访问一次
  const { locale, setLocale } = useI18n()

  return (
    <div>
      <h1>{tCommon('welcome')}</h1>
      <p>{tAuth('login.title')}</p>
      <button>{tProducts('addToCart')}</button>
      <p>Current: {locale}</p>
    </div>
  )
}

🎯 类型推断魔法

react-vintl 的核心创新是自动类型推断,无需生成单独的类型文件!

工作原理

  1. 启动时生成 - 插件扫描翻译文件并在 react-vintl-locales.d.ts 中生成联合类型
  2. 联合类型推断 - 所有翻译键都被提取为字符串字面量联合类型
  3. 热模块替换 - 文件更改会自动更新类型并触发 HMR
  4. 完美的 IDE 集成 - TypeScript 为所有键提供即时自动补全

自动类型同步

当您添加新的国际化字段时,插件会:

  1. 自动检测变化 - 监听 locale 文件夹的文件变化
  2. 更新类型定义 - 自动更新 react-vintl-locales.d.ts 文件
  3. 触发 TypeScript 服务器重新加载 - 通过文件系统事件通知 TypeScript 语言服务器
  4. 立即生效 - 编辑器通常在几秒内识别新字段,无需手动重启

这意味着:

  • ✅ 添加新字段后,编辑器立即提供自动补全
  • ✅ 构建时类型检查自动通过,不会因为新字段而失败
  • ✅ 无需手动重启 TypeScript 服务器
  • ✅ 支持所有主流编辑器(VSCode、WebStorm、Sublime Text 等)
// 插件自动在 react-vintl-locales.d.ts 中生成:

export type I18nKeys =
  | 'common.welcome'
  | 'common.buttons.save'
  | 'common.buttons.cancel'
  | 'auth.login.title'
  | 'auth.login.username'
  | ... // 所有您的翻译键作为联合类型!

// 您的编辑器获得完美的自动补全!
const text = t('common.')      // ✅ 显示:welcome, buttons.save, buttons.cancel...
const text = t('auth.login.')  // ✅ 显示:title, username, password...

为什么使用联合类型?

  • ✅ 完美的 IDE 自动补全体验
  • ✅ 即使有数千个键也能快速 TypeScript 编译
  • ✅ 使用无效键时的清晰类型错误
  • ✅ 命名空间感知建议(输入 common. 只显示 common.* 键)

无需单独的键文件!

与需要生成单独类型定义文件的传统 i18n 库不同,react-vintl 直接从虚拟模块推断类型:

// ❌ 传统方法 - 需要单独生成
import { I18nKeys } from './i18n-keys' // 单独文件

// ✅ react-vintl - 自动推断
import { type I18nKeys } from '@gulibs/react-vintl-locales' // 来自虚拟模块!

🔧 高级用法

远程翻译加载

react-vintl 支持从外部接口动态加载翻译资源,实现文件翻译(基础)+ 接口翻译(动态)的混合模式。

基本用法

import { useLoadRemoteTranslations, useTranslation } from '@gulibs/react-vintl'

function MyComponent() {
  // 加载远程翻译
  const { loading, error } = useLoadRemoteTranslations(
    'https://api.example.com/translations/en',
    {
      namespace: 'remote',  // 合并到 'remote' namespace
      merge: true           // 自动合并
    }
  )

  const t = useTranslation()

  if (loading) return <div>Loading translations...</div>
  if (error) return <div>Error: {error.message}</div>

  // 远程翻译立即可用
  return <div>{t('remote.title' as any)}</div>
}

合并策略

Namespace 级别合并:

// 将远程翻译合并到指定的 namespace
useLoadRemoteTranslations(
  fetch('/api/translations').then(r => r.json()),
  { namespace: 'remote' }
)

// 结果结构:
// {
//   en: {
//     common: { ... },      // 文件翻译
//     remote: { ... }       // 远程翻译合并到这里
//   }
// }

根级别合并:

// 不指定 namespace,合并到根级别(与现有 namespace 平级)
useLoadRemoteTranslations(
  Promise.resolve({
    en: {
      rootLevel: {
        message: "This is merged at root level"
      }
    },
    zh: {
      rootLevel: {
        message: "这是在根级别合并的"
      }
    }
  }),
  { merge: true }  // 不指定 namespace
)

// 结果结构:
// {
//   en: {
//     common: { ... },      // 文件翻译
//     rootLevel: { ... }   // 远程翻译(新 namespace,与 common 平级)
//   }
// }

// 使用合并后的翻译
const t = useTranslation()
t('rootLevel.message')  // ✅ 立即可用

重要提示:

  • 根级别合并时,远程翻译中的每个顶级键都会作为新的 namespace 合并
  • 不同的 namespace 配置会使用不同的缓存键,即使 source 相同也不会冲突
  • 资源合并后,翻译函数会在下次渲染时自动更新,确保使用最新资源

手动更新资源

您也可以手动更新资源:

import { useI18nContext } from '@gulibs/react-vintl'

function MyComponent() {
  const { updateResources } = useI18nContext()

  const handleLoad = async () => {
    const remoteTranslations = await fetch('/api/translations').then(r => r.json())
    
    // 合并到指定的 namespace
    updateResources(remoteTranslations, {
      namespace: 'remote',
      merge: true
    })
  }

  return <button onClick={handleLoad}>Load Translations</button>
}

工具函数

import { mergeResources } from '@gulibs/react-vintl'

// 手动合并资源
const merged = mergeResources(
  baseResources,
  remoteResources,
  {
    namespace: 'remote',  // 可选:合并到指定 namespace
    locale: 'en'         // 可选:只合并指定 locale
  }
)

完整示例:

查看 test/src/RemoteTranslationDemo.tsx 获取完整的使用示例和所有功能演示。

TypeScript 翻译文件

您可以使用 TypeScript 进行动态翻译:

// src/locales/en/dynamic.ts
export default {
  currentYear: new Date().getFullYear(),
  greeting: (name: string) => `Hello, ${name}!`,
  environment: process.env.NODE_ENV === 'development' ? 'Dev' : 'Prod'
} as const

命名空间翻译

按功能组织翻译:

src/locales/
├── en/
│   ├── common.json
│   ├── auth/
│   │   ├── login.json
│   │   └── register.json
│   └── dashboard/
│       └── stats.json

使用点记法访问:

t('auth.login.title')
t('dashboard.stats.users')

高级参数插值

react-vintl 支持强大的参数插值系统,包括多种格式化选项:

简单插值

{
  "greeting": "Hello, {{name}}!",
  "user_info": "User {{user.name}} has {{user.count}} messages"
}
t('greeting', { name: 'John' })
// 结果: "Hello, John!"

t('user_info', { user: { name: 'Jane', count: 3 } })
// 结果: "User Jane has 3 messages"

复数形式

{
  "item_count": "{{count, plural, one=1 item, other=# items}}",
  "message_count": "{{count, plural, zero=No messages, one=1 message, other=# messages}}"
}
t('item_count', { count: 1 })   // "1 item"
t('item_count', { count: 5 })   // "5 items"
t('message_count', { count: 0 }) // "No messages"

选择形式

{
  "gender_greeting": "{{gender, select, male=He, female=She, other=They}} is here",
  "status_message": "{{status, select, active=Online, inactive=Offline, other=Unknown}}"
}
t('gender_greeting', { gender: 'male' })    // "He is here"
t('gender_greeting', { gender: 'female' })  // "She is here"
t('status_message', { status: 'active' })   // "Online"

数字格式化

{
  "price": "Price: {{amount, number}}",
  "decimal": "Value: {{value, number, minimumFractionDigits=2}}",
  "currency": "Cost: {{amount, currency, currency=USD}}"
}
t('price', { amount: 1234.56 })        // "Price: 1,234.56"
t('decimal', { value: 1234.5 })        // "Value: 1,234.50"
t('currency', { amount: 99.99 })       // "Cost: $99.99"

日期格式化

{
  "created_date": "Created on {{date, date}}",
  "full_date": "{{date, date, year=numeric, month=long, day=numeric}}",
  "time": "Time: {{date, date, hour=numeric, minute=2-digit}}"
}
t('created_date', { date: new Date() })
// 结果: "Created on 1/15/2024"

t('full_date', { date: new Date('2024-01-15') })
// 结果: "January 15, 2024"

文本格式化

{
  "text_format": "{{text, uppercase}} - {{text, lowercase}} - {{text, capitalize}}"
}
t('text_format', { text: 'hello world' })
// 结果: "HELLO WORLD - hello world - Hello world"

嵌套对象支持

{
  "user_profile": "{{user.profile.name}} ({{user.profile.age}} years old)"
}
t('user_profile', {
  user: {
    profile: {
      name: 'John',
      age: 25
    }
  }
})
// 结果: "John (25 years old)"

错误处理和验证

react-vintl 提供了强大的错误处理机制:

// 参数验证
t('greeting', { name: 'John' })           // ✅ 正常
t('greeting', { invalid: 'data' })        // ⚠️ 警告:参数不匹配
t('greeting', { name: null })             // ✅ 正常:null 值会被转换为字符串

// 循环引用检测
const circular = { name: 'John' }
circular.self = circular
t('greeting', circular)                   // ⚠️ 警告:检测到循环引用

// 格式错误处理
t('price', { amount: 'invalid' })         // ✅ 正常:返回原始值
t('date', { date: 'invalid-date' })       // ✅ 正常:返回原始值

🎨 与其他解决方案的对比

vs vgrove-i18n

  • ✅ 相同的类型推断方法
  • ✅ React 特定的钩子和组件
  • ✅ 无需 keysOutput 选项
  • 更强大的参数插值系统 - 支持复数、选择、格式化等高级功能

vs react-i18next

  • ✅ 更好的 TypeScript 支持
  • ✅ Vite 原生虚拟模块
  • ✅ 无运行时开销
  • ✅ 自动类型推断
  • 内置格式化功能 - 无需额外插件即可使用数字、日期、货币格式化

vs formatjs

  • ✅ 更简单的 API
  • ✅ 无需 ICU 消息格式
  • ✅ 更好的开发者体验与自动补全
  • 轻量级实现 - 无需复杂的 ICU 解析器
  • 更好的性能 - 原生 JavaScript 实现,无外部依赖

📝 最佳实践

  1. 使用目录模式进行本地化 - 更容易组织和维护
  2. 保持翻译文件小巧 - 按功能或模块分割
  3. 对动态内容使用 TypeScript - 更好的类型安全
  4. 利用自动补全 - 让您的编辑器指导您
  5. 合理使用参数插值 - 避免过度复杂的插值表达式
  6. 参数验证 - 始终验证传入的参数,避免运行时错误
  7. 格式化一致性 - 在项目中保持数字、日期格式的一致性
  8. 复数规则 - 根据目标语言正确设置复数规则
  9. 远程翻译策略 - 使用文件翻译作为基础,远程翻译作为补充
  10. 缓存管理 - 合理使用缓存机制,避免不必要的网络请求
    • 不同的 namespace 配置会自动使用不同的缓存键
    • 根级别合并和 namespace 合并不会共享缓存
  11. 错误处理 - 为远程翻译加载提供适当的错误处理和重试机制
  12. 资源同步 - 资源合并后,翻译函数会在下次渲染时自动更新
    • 如果需要在资源合并后立即使用翻译键,可以使用 useI18n() 检查资源是否已同步

🔧 日志配置

react-vintl 提供了统一的日志系统,允许您控制所有日志输出。所有模块(包括插件)都使用统一的 logger,确保日志行为一致。

日志级别

  • debug - 调试日志,用于开发时的详细调试信息(如 [useLoadRemoteTranslations][mergeResources]
  • info - 一般信息日志,用于重要的运行时信息
  • warn - 警告日志,用于潜在问题或非致命错误
  • error - 错误日志,用于错误信息(始终输出,包括生产环境)

默认行为

  • 开发环境 (NODE_ENV=development): 所有日志级别都启用
  • 生产环境 (NODE_ENV=production): 仅 error 日志启用,debuginfowarn 自动禁用

控制日志输出

import { logger } from '@gulibs/react-vintl'

// 禁用调试日志
logger.setConfig({ debug: false })

// 禁用信息日志
logger.setConfig({ info: false })

// 禁用警告日志
logger.setConfig({ warn: false })

// 禁用错误日志(不推荐,仅在特殊情况下使用)
logger.setConfig({ error: false })

// 同时配置多个选项
logger.setConfig({
  debug: false,
  info: true,
  warn: true,
  error: true
})

日志去重

Logger 默认启用去重机制,防止相同消息在短时间内(默认 5 秒)重复输出:

// 禁用去重
logger.setConfig({ deduplicate: false })

// 自定义去重时间窗口(毫秒)
logger.setConfig({ deduplicationWindow: 10000 }) // 10 秒

调试日志和生产日志的区别

  • 调试日志 (debug): 包含详细的执行流程信息,如资源加载、合并过程等,默认在生产环境禁用
  • 生产日志: 仅包含错误信息,确保生产环境不会输出过多日志影响性能

插件日志

插件中的日志也通过 logger 统一控制。插件会尊重其 debug 选项,但最终输出由 logger 配置决定:

// vite.config.ts
createReactVintlPlugin({
  basePath: 'src/locales',
  debug: true  // 插件会使用 logger.debug() 输出日志
})

即使插件设置了 debug: true,如果 logger 的 debug 配置为 false,日志仍不会输出。

🐛 故障排除

类型在编辑器中不显示?

  1. 等待自动同步 - 插件会自动更新类型文件并触发 TypeScript 服务器重新加载,通常几秒内生效
  2. 手动重启 TypeScript 服务器 - 如果类型仍未更新,在编辑器中重启 TypeScript 服务器:
    • VSCode: Cmd/Ctrl + Shift + P → 输入 "TypeScript: Restart TS Server"
    • WebStorm: FileInvalidate Caches... → 选择 "Invalidate and Restart"
  3. 检查插件是否在 vite.config.ts 中正确配置
  4. 确保翻译文件位于正确的位置
  5. 检查 react-vintl-locales.d.ts 文件是否存在且包含最新的类型定义

添加新字段后编辑器仍显示类型错误?

这是类型同步问题。插件会自动处理,但有时需要额外步骤:

  1. 等待几秒钟 - 插件会在文件变化后自动更新类型并触发 TypeScript 服务器重新加载
  2. 检查文件是否已更新 - 查看 react-vintl-locales.d.ts 文件,确认新字段已包含在类型定义中
  3. 重启 TypeScript 服务器 - 如果类型文件已更新但编辑器仍显示错误,手动重启 TypeScript 服务器
  4. 检查构建模式 - 在构建时,类型文件会自动更新,确保构建时类型检查通过
  5. 查看插件日志 - 如果启用了 debug: true,检查控制台是否有类型更新相关的错误信息

如果问题仍然存在:

  • 确保开发服务器正在运行(类型更新需要 HMR 支持)
  • 检查文件权限,确保插件可以写入类型文件
  • 尝试删除 react-vintl-locales.d.ts 文件,让插件重新生成

热重载不工作?

  1. 检查插件选项中的 hmr: true
  2. 验证文件路径是否正确
  3. 重启开发服务器

参数插值不工作?

  1. 检查参数格式 - 确保使用 {{key}} 格式
  2. 验证参数传递 - 确保参数对象正确传递
  3. 检查控制台警告 - 查看是否有参数验证错误
  4. 测试简单插值 - 先测试 {{name}} 等简单格式
  5. 检查嵌套对象 - 确保嵌套对象结构正确

格式化不生效?

  1. 检查格式选项 - 确保格式选项拼写正确
  2. 验证数据类型 - 确保传入的数据类型正确
  3. 测试浏览器支持 - 某些格式化功能需要现代浏览器支持
  4. 查看控制台错误 - 格式化失败时会回退到原始值

📄 许可证

MIT

🤝 贡献

欢迎贡献!请随时提交 Pull Request。


由 gulibs 用 ❤️ 制作