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

React多语言自定义Hook如何在客户端读取Next.js public目录下的JSON文件

问题原因分析
  • 你的当前代码仅在Node.js服务端环境(typeof window === 'undefined')执行了读取逻辑,浏览器客户端环境下该分支不会执行,LanguagesFile变量默认为undefined
  • fs是Node.js专属的文件系统API,浏览器端不存在该能力,无法用fs读取本地项目文件
  • Next.js的public目录下的静态资源会直接暴露在服务的根路由下,客户端可以通过HTTP请求直接获取
修复方案

第一步:将语言文件加载逻辑迁移到LanguageProvider

统一在上下文层处理服务端、客户端的加载逻辑,避免重复加载,修改后代码示例:

'use client' // Next.js App Router 环境需要添加该指令
import { createContext, useContext, useState, useEffect } from 'react'

const LanguageContext = createContext({
  locale: 'zh-CN',
  languageData: {},
  setLocale: (locale: string) => {}
})

export function LanguageProvider({ children, defaultLocale = 'zh-CN' }) {
  const [locale, setLocale] = useState(defaultLocale)
  const [languageData, setLanguageData] = useState({})

  // 服务端直接读取文件
  if (typeof window === 'undefined') {
    const fs = require('fs')
    const fileContent = fs.readFileSync('./public/Languages.json', 'utf8')
    setLanguageData(JSON.parse(fileContent))
  }

  // 客户端通过请求获取静态资源
  useEffect(() => {
    const fetchLanguages = async () => {
      try {
        const res = await fetch('/Languages.json')
        const data = await res.json()
        setLanguageData(data)
      } catch (e) {
        console.error('加载语言文件失败,请检查public目录下是否存在Languages.json', e)
      }
    }
    // 避免hydration时服务端和客户端数据不一致,客户端仅在没有数据时请求
    if (Object.keys(languageData).length === 0) {
      fetchLanguages()
    }
  }, [languageData])

  return (
    <LanguageContext.Provider value={{ locale, setLocale, languageData }}>
      {children}
    </LanguageContext.Provider>
  )
}

第二步:简化useTranslation逻辑

直接从上下文取已经加载完成的语言数据,不需要处理加载逻辑,同时修正原代码的判断逻辑错误:

import { useContext } from 'react'
import { LanguageContext } from './LanguageProvider'

export function useTranslation() {
  const { locale, languageData } = useContext(LanguageContext)

  function t(key: string) {
    if (!languageData?.[locale]?.[key]) {
      console.warn(`No string '${key}' for locale '${locale}'`)
      return key // 找不到的时候返回key作为兜底,比返回false更友好
    }
    return languageData[locale][key].toString() || ''
  }

  return { t, locale }
}
额外优化建议
  • 可以给npm包增加配置项,支持用户自定义语言文件的路径,不要硬编码/Languages.json
  • 可以增加语言切换时的热加载能力,切换locale不需要刷新页面
  • 可以添加类型支持,根据用户的Languages.json生成key的类型提示,提升开发体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 20:45:06