V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
HeyCaptainJack
V2EX  ›  程序员

有 i18n 大佬帮忙看下吗, json 文件的翻译问题,工作量太大🤪

  •  
  •   HeyCaptainJack · 17 天前 · 5210 次点击

    请教个国际化的问题,目前我是 10 个语种的 i18n JSON 文件,每当后续有改动时,都要频繁去改 10 个文件,虽然有 Cursor AI 加持,翻译不成问题,但是工作量还是太大。

    请问大家有没有自动化检测,然后使用 AI 批量翻译的方案呢,感觉上应该有合适的 CI 方案。

    56 条回复    2024-12-09 00:19:17 +08:00
    hhacker
        1
    hhacker  
       17 天前
    用 babeledit 机翻
    erquren
        2
    erquren  
       17 天前
    维护一份 key value 自动翻译啊
    tonytonychopper
        3
    tonytonychopper  
       17 天前 via iPhone
    搞个 pipeline ,push 代码的时候对增量代码里的文案做翻译
    ma836323493
        4
    ma836323493  
       17 天前
    写个脚本。检查 1 个语种新增的,调用 api 翻译修改其他 9 个文件
    lisxour
        5
    lisxour  
       17 天前
    用 po/pot 好点吧
    ShareManT
        6
    ShareManT  
       17 天前
    之前做了个工具用来解决这个问题,可以试试,现在只接了 deepseek

    https://github.com/ShermanTsang/i18n-translator
    kongkx
        7
    kongkx  
       17 天前 via iPhone
    OP 是卡在翻译词条的提取? 还是?
    weithl
        8
    weithl  
       17 天前 via Android
    翻译来源是哪,如果是外部,直接整个 excel 给出去,定义好映射,只用负责解析就好。
    HeyCaptainJack
        9
    HeyCaptainJack  
    OP
       17 天前
    @hhacker 翻译本身直接用的 AI ,倒是没问题
    HeyCaptainJack
        10
    HeyCaptainJack  
    OP
       17 天前
    @erquren 上千行的 key value ,CRUD i18n 都得处理
    HeyCaptainJack
        11
    HeyCaptainJack  
    OP
       17 天前
    @kongkx 比如一个 en.json 文件内部,出现任何的 CRUD ,都要在其他剩余的 json 文件进行同步的 CRUD
    HeyCaptainJack
        12
    HeyCaptainJack  
    OP
       17 天前
    @weithl 初始内容翻译简单,难在后续的 CRUD 的同步
    HeyCaptainJack
        13
    HeyCaptainJack  
    OP
       17 天前
    @tonytonychopper 是的,想了好久,还是得依赖 git diff 之后做 pipe line ,今天来写一写代码试试
    HeyCaptainJack
        14
    HeyCaptainJack  
    OP
       17 天前
    @lisxour po/pot 原来也是一种文件格式啊,学习了
    HeyCaptainJack
        15
    HeyCaptainJack  
    OP
       17 天前
    @ShareManT 看了下,感觉不太符合我的场景😄
    guguji5
        16
    guguji5  
       17 天前
    我也有一样的问题,我是三种语言,也是几千条的 key value ,每次修改,我都新增,因为我懒得找对应的那一条去改掉。导致冗余越来越多
    Greendays
        17
    Greendays  
       17 天前
    我现在维护三种语言,都是让 GPT 来翻译的。直接把完整文件复制过去,让它把右边引号的内容翻译成指定语言。也就第一次翻译有工作量,后续小修小补都手动来了
    temporary
        18
    temporary  
       17 天前   ❤️ 1
    https://github.com/lokalise/i18n-ally
    这个插件,自动翻译还能看各语言有没有缺失
    TimePPT
        19
    TimePPT  
       17 天前
    sqlite 这种数据库维护 key 和各语言 value 的对应关系,配合导出脚本,update 后自动生成各语言 json ,然后发版呢?
    fov6363
        20
    fov6363  
       17 天前
    写个脚本处理一下,可以处理全量、增量的逻辑。维护 18 个语种,5 万个词条,常用的脚本 5 ~ 10 个,可以解决新增语言,增量翻译,全量翻译等功能

    就自己写脚本就行,不用专门的 ci 工具
    mocococ
        21
    mocococ  
       17 天前   ❤️ 2
    google 表格有一个函数是 “GOOGLETRANSLATE” 可以试试

    =GOOGLETRANSLATE(B6, "en", "zh")

    你只需要设置一个单词,其他语言可以自动翻译 ,如果某个翻译不准确可以手动改当前格子。

    翻译好了,下载 文件用程序转化成 json 就可以使用了




    https://zh.wikipedia.org/wiki/ISO_639-1
    XTTX
        22
    XTTX  
       17 天前
    import * as fs from 'fs'
    import * as path from 'path'

    function validateJSONKeys(basePath) {
    const baseJSON = JSON.parse(fs.readFileSync(path.join(basePath, 'en', 'common.json'), 'utf8'))
    const baseKeys = Object.keys(baseJSON)

    const folders = fs
    .readdirSync(basePath, { withFileTypes: true })
    .filter((dirent) => dirent.isDirectory())
    .map((dirent) => dirent.name)

    console.log('Validation Results:\n')

    folders.forEach((folder) => {
    if (folder === 'en') return

    const filePath = path.join(basePath, folder, 'common.json')
    if (!fs.existsSync(filePath)) {
    console.log(`[${folder}] common.json not found.`)
    return
    }

    const json = JSON.parse(fs.readFileSync(filePath, 'utf8'))
    const keys = Object.keys(json)

    const missingKeys = baseKeys.filter((key) => !keys.includes(key))
    const extraKeys = keys.filter((key) => !baseKeys.includes(key))

    if (missingKeys.length === 0 && extraKeys.length === 0) {
    console.log(`[${folder}] ✓ All keys are present.`)
    } else {
    if (missingKeys.length > 0) {
    console.log(`[${folder}] ✗ Missing keys.`)
    }
    if (extraKeys.length > 0) {
    console.log(`[${folder}] ⚠ Warning: Extra keys found.`)
    }
    }
    })
    }

    // Usage example
    const basePath = './public/locales'
    validateJSONKeys(basePath)
    前端项目要搞 几个 script , 放到 internal 里,类似 site map 生成,npm postbuild 自动跑。
    HeyCaptainJack
        23
    HeyCaptainJack  
    OP
       17 天前
    @TimePPT 用数据库来统一前后端的这个思路还真不错👍,我看看我的站点怎么改
    HeyCaptainJack
        24
    HeyCaptainJack  
    OP
       17 天前
    @fov6363 是的,我现在也在写脚本了😂
    HeyCaptainJack
        25
    HeyCaptainJack  
    OP
       17 天前
    @XTTX 赞,贴心把代码贴出来了,感谢
    HeyCaptainJack
        26
    HeyCaptainJack  
    OP
       17 天前
    @mocococ google 还有这种 GOOGLETRANSLATE 函数呢,真不错,学习了👍🏻
    ltaoo1o
        27
    ltaoo1o  
       17 天前   ❤️ 2
    @TimePPT 这个思路太好了,是不是可以更进一步做成 gui ,可视化查看已有什么语言,各语言下的字段,交互式增加、修改翻译。
    asdjgfr
        28
    asdjgfr  
       17 天前
    感觉你的需求用 weblate 就能实现
    https://docs.weblate.org/en/latest/admin/machine.html
    aloxaf
        29
    aloxaf  
       17 天前
    @HeyCaptainJack #13

    怎么会要依赖 git diff ,老哥你难道没用任何 i18n 框架么。

    比如前面有人提到的 .po ,这就是 gnu gettext 的翻译格式,你只要导入库后在代码里写 _("hello"),gettext 就会提取出这些字符串,和你和旧翻译对比、合并,你每次只管翻译就行了。
    ThomasChan
        30
    ThomasChan  
       17 天前
    你的思路没问题,脚本就让 AI 写就好了,我的 deno 脚本已经运行好久了,思路就是以 zh-CN 为主文件,增删改都是只改这一个语言文件,读 git diff ,按行处理和同步到其他语言文件,我也用的 deepseek 翻译。

    这个脚本还同时把超大的 json 文件的 key 按字母顺序排序了,也做了多文件的 key 一致性检查,等于是单测。
    ThomasChan
        31
    ThomasChan  
       17 天前
    大型复杂项目里的代码随着时间积累乱的程度还是挺高的, @aloxaf 就只是 _('hello') 这样的根本无法覆盖全部,有太多的情况是字符串拼接的 key 了
    icodesign
        32
    icodesign  
       17 天前
    我有个初步的开源项目可以满足你的这个需求,还比较初级,不过我自己在用了,你可以看看: https://github.com/icodesign/dolphin

    本质上是按照一个配置文件把项目里面的本地化文件收集起来然后本地会存一个状态,再通过 AI 去翻译,后面就会通过类似于 diff 的方式去更新
    yqs112358
        33
    yqs112358  
       17 天前
    话说 CRUD 为什么会出现在 i18n 的文件里面,这些不是应该都在代码逻辑里面么,i18n 文件里面用占位符替代
    yqs112358
        34
    yqs112358  
       17 天前
    另外这种专门辅助编辑 i18n 的平台也挺多的,比如 crowdin
    tuolanzhiren
        35
    tuolanzhiren  
       17 天前 via iPhone
    react 项目使用 i18next 的话 可以结合 i18next-parser 在 commit 的时候自动扫描并进行翻译
    aloxaf
        36
    aloxaf  
       17 天前
    @ThomasChan #31

    如果一开始没考虑好 i18n 的需求,后期再上确实挺麻烦。

    拼接的字符串,只要最终来源是常量,还是可以翻译的。完全动态的字符串,那没有任何手段能预先翻译……

    除了翻译的自动化提取合并,i18n 框架都提供了根据单复数或上下文来提供不同翻译的方法,对翻译要求高的话还是很必要的。就算不用现成框架,最后还是会走上造轮子的老路(
    cnhongwei
        37
    cnhongwei  
       17 天前
    我前端是使用 lingui js , 后端是 java ,使用 gettext ,写完程序,通过 lingui 的命令或 gettext maven 生成需要翻译的文件。集中翻译可以使用 crowdin,我用过,对这两个工具都兼容。 动态的需要自己先规划好,比如字符串的参数化,如果以前全是动态拼接的,确实很麻烦,不过可以慢慢都修改为这种模式。
    mooo
        38
    mooo  
       17 天前
    vscode 用 i18n-ally 插件,先把要翻译的提取到默认语言,然后翻译成其他语言
    echoless
        39
    echoless  
       17 天前
    hepin1989
        40
    hepin1989  
       17 天前
    给钱吗?
    RockShake
        41
    RockShake  
       17 天前
    unco020511
        42
    unco020511  
       17 天前 via Android
    你是已经有 i18n 机制了,只是增量词条如何处理是吧?这还不简单吗,团队规定好一个基准文件,比如 en_US.json ,每个需求有新增词条开发加到这里面,然后在编译流程或者 git 里插入一个 task ,检测增量就用类似 gpt 的 api 去翻译并同步到其他所有语言文件。你用 gpt 去写这些脚本两个小时就搞定了
    shiny
        43
    shiny  
       17 天前
    写过一个工具,先对比 diff 部分,再拿去翻译,再合并回来。
    https://github.com/shiny/chat-i18n
    HeyCaptainJack
        44
    HeyCaptainJack  
    OP
       17 天前
    @shiny 谢谢,请问 deekseek 翻译应该是最便宜的了吧,效果如何呢
    HeyCaptainJack
        45
    HeyCaptainJack  
    OP
       17 天前
    @unco020511 嗯,目前是准备按你的思路这样做了,棒棒
    HeyCaptainJack
        46
    HeyCaptainJack  
    OP
       17 天前
    @echoless 嗯,看了下,确实不错👍🏻
    HeyCaptainJack
        47
    HeyCaptainJack  
    OP
       17 天前
    @mooo 这个插件还得手动来处理吧
    shiny
        48
    shiny  
       17 天前
    @HeyCaptainJack 确实是最便宜的,效果还不错。但是前段时间用 Claude 对比后发现还是 Claude 自然。后面打算接入试试,只是 Claude 封号有点严重。
    HeyCaptainJack
        49
    HeyCaptainJack  
    OP
       17 天前   ❤️ 1
    @shiny 我现在用的 openrouter ,有 Claude 代理,还比较不错,你可以试试看
    amlee
        50
    amlee  
       17 天前
    claude 太贵了,用来翻译真奢侈
    zhmouV2
        51
    zhmouV2  
       17 天前
    在某个小公司当前端,i18n 这玩意儿确实蛋疼 目前草台如我司是用在线文档同步专职文案提供的翻译内容,翻译时还要提供一下相关场景的截图,让文案能理解整个上下文。
    话说拿 AI 翻译,AI 如何解决 Context 的问题?把背景和一些专用术语作为 system prompt 输入进去吗?另外这样谁来负责审核翻译,测试覆盖多语言吗,还是完全依赖外国用户当 QA ?实在不懂大厂是做 i18n 的标准 workflow / 团队协作翻译软件是啥样的,有没有懂哥聊聊?
    mooo
        52
    mooo  
       17 天前 via Android
    @HeyCaptainJack 插件可以调翻译 api ,我记得点几下就行。插件主要是有 GUI 友好一点,还可以把代码里的 key 显示成设置的语言
    mooo
        53
    mooo  
       17 天前 via Android
    @zhmouV2 有翻译协作平台的, 你们有预算的话可以用
    https://zh.crowdin.com
    TabGre
        54
    TabGre  
       16 天前 via iPhone
    woocommer 有什么好用的多语言方案吗? 翻译插件实在太贵了
    theprimone
        55
    theprimone  
       16 天前
    @zhmouV2 还要截图也太硬核了吧
    hamsterbase
        56
    hamsterbase  
       16 天前
    非常简单,可以试试看我的 vs code 插件,i18nease

    https://i18nease.hamsterbase.com/

    我是什么做的?

    1. 代码里只需要写 key + 英文即可

    localize('key','Default Message'

    2. 在文件改动的时候,分析代码的 ast ,然后自动提取出所有的 key 和 message, 生成 en-US.json


    3. 执行翻译的时候,自动和其他语言的 json 文件进行批评, 找出还未翻译的文本,提交给 AI ,获取结果后写入到各自的 json 文件里。



    这一套组合拳下来,每次开发的时候无需关心多语言,只需要写源码就够了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1298 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 17:34 · PVG 01:34 · LAX 09:34 · JFK 12:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.