(开发者)为blender插件制作翻译(i18n/international) make translations for blender addon

不直观的教程/文档

https://developer.blender.org/docs/handbook/translating/translator_guide/?utm_source=blender-4.3.2#manage-ui-translations-add-on
https://developer.blender.org/docs/handbook/translating/developer_guide/#python-translation-api
https://docs.blender.org/api/current/bpy.app.translations.html
demo: https://github.com/blender/blender-addons/tree/main/render_copy_settings

BLT/user translate

这些插件使用自己的csv,需要依赖这些插件才能加载翻译。不考虑。

利用官方的可翻译词汇

https://translate.blender.org/search/blender-ui/?offset=&q=关键词&sort_by=num_words

然后开启禅模式即可。

方案1:部分用python自带的gettext

一部分blender translate插件检测不出来的,得手动用gettext
详见:https://github.com/AClon314/mocap_importer_blender/tree/a01887c098ad1308d81aaf5bf5dbaae2b93d5a4a/i18n/zh_HANS/LC_MESSAGES

pot.py,调用xgettext快速创建.pot/.po/.mo
#!/bin/env python
import os
import re
import time
import difflib
import subprocess
from lib import get_toml, ID
LANGS: list[str] = ['zh_HANS']
DIR_LOCALE = 'i18n'
POT = 'msg.pot'
DIR_SELF = os.path.dirname(__file__).removesuffix('.')
METAINFO = {
    'Project-Id-Version': get_toml()['version'],
    'PO-Revision-Date': time.strftime('%Y-%m-%d %H:%M%z'),
    'Last-Translator': 'nolca <nolca@qq.com>',
    # 'Language-Team': 'mocap_importer contributors <github.com/aclon314/mocap_importer>',
}


def path_lc(lang: str, suffix='.po') -> str:
    folder = os.path.join(DIR_SELF, DIR_LOCALE, lang, 'LC_MESSAGES')
    os.makedirs(folder, exist_ok=True)
    return os.path.join(folder, ID + suffix)


def merge_diff(old: str, new: str, rule=[r'-msgstr "', r'\+msgstr ""']):
    with open(old, 'r') as o, open(new, 'r') as n:
        old_lines = o.readlines()
        new_lines = n.readlines()

    diff = difflib.unified_diff(old_lines, new_lines, fromfile=old, tofile=new)

    prev = ''
    begin = end = offset = 0
    skip = 2
    for l in diff:
        if skip > 0:
            skip -= 1
            continue
        print(l, end='')
        match = re.search(r'@@ -(\d*),(\d*) \+(\d*),(\d*) @@', l)
        if match:
            skip = 3    # skip no change 3 lines
            begin_end = match.groups()
            a_begin, a_count, b_begin, b_count = map(int, begin_end)
            offset = min(a_begin, b_begin) + 1

        if l.startswith(' ') or l.startswith('+'):
            offset += 1
        if re.search(rule[0], prev) and re.search(rule[1], l):
            print(f'\t{new_lines[offset][:-1]} -> {prev[1:]}')
            new_lines[offset] = prev[1:]

        prev = l
    return ''.join(new_lines)


def pot():
    pys = [f for f in os.listdir('.') if f.endswith('.py')]
    subprocess.run([
        'xgettext', '--language=Python', '--keyword=_', f'--output={POT}', *pys
    ])


def pot_to_po(lang):
    PATH_NEW = PATH_OLD = path_lc(lang)
    need_diff = False
    if os.path.exists(PATH_OLD):
        PATH_NEW += '.bak'

    subprocess.run([
        'msginit', f'--input={POT}', '--no-translator', '--locale', lang, '--output', PATH_NEW
    ])
    subprocess.run([
        'msgconv', '--to-code=UTF-8', PATH_NEW, '-o', PATH_NEW
    ])
    text = ''
    with open(PATH_NEW, 'r') as f:
        text: str = f.read()
    with open(PATH_NEW, 'w') as f:
        for k, v in METAINFO.items():
            text = re.sub(f'"({k}: ).*?"', f'"\\1 {v}"', text)
        f.seek(0)
        f.write(text)

    if PATH_OLD != PATH_NEW:
        text = merge_diff(PATH_OLD, PATH_NEW)
        with open(PATH_OLD, 'w') as f:
            f.write(text)
        os.remove(PATH_NEW)


def po_to_mo(lang):
    subprocess.run([
        'msgfmt', path_lc(lang), '--output-file',
        path_lc(lang, '.mo')
    ])


def main():
    pot()
    for lang in LANGS:
        pot_to_po(lang)
    os.remove(POT)

    for lang in LANGS:
        po_to_mo(lang)


if __name__ == "__main__":
    main()

方案2:blender工作流

更新:终于弄懂了,官方文档写的不直白。

git clone

git clone --depth 1 https://github.com/blender/blender
# git clone --depth 1 https://projects.blender.org/blender/blender-ui-translations #如果你要带翻译来编译blender……

为何--depth 1

很有趣,项目源码本身不大,git commit history却很庞大,如translations仓库,8MB,但其git history有1.5GB!这就是年长的开源项目啊!

启用/配置Manage UI translations插件

把blender的git库的地址填到:源文件根目录。这是linux下成功示例(Windows需自行编译fribidi.dll):
成功示例
注意,不是blender/blender(可执行文件),而是blender文件夹

在渲染选项卡内的面板

In the I18n Update Translation panel (bottom of Render buttons)...
panel

渲染选项卡(有设置修改器/骨骼/物理约束的侧边栏)里。
这个太坑爹了,到处找都找不到。

  1. 在列表内选择要翻译的语言(对于插件开发者,只选英文与中文就够。不要强行上机翻,放到开源仓库,让其母语者做pr/issue)
  2. 然后点击 Refresh i18n data/刷新i18n数据,选择你的插件。
  3. 再点击 Export PO/导出PO文件,选择要导出的文件夹,如addon/i18n。之后会得到一堆.po文件与一个translate.py
posted @ 2025-03-15 09:59  Nolca  阅读(320)  评论(0)    收藏  举报