From a3d029f9d94d6992c1ac3c44e2580c0033b8c7e2 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Tue, 16 Jan 2024 17:06:18 +0500 Subject: [PATCH] add without-blender-way to generate translations module from po files though it does require `bpy` module which is available only for python 3.10. Actually, `bpy` module by itself is not necessary - we just need `bl_i18n_utils` that becomes available after `import `bpy`. So alternatively we can just download that module from Blender https://projects.blender.org/blender/blender/src/branch/main/scripts/modules/bl_i18n_utils --- .../scripts/bbim_setup_translations.py | 61 ++++++++++++++++--- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/src/blenderbim/scripts/bbim_setup_translations.py b/src/blenderbim/scripts/bbim_setup_translations.py index d49d087fe1..9a6575ff6a 100644 --- a/src/blenderbim/scripts/bbim_setup_translations.py +++ b/src/blenderbim/scripts/bbim_setup_translations.py @@ -4,6 +4,7 @@ import shutil import tempfile import importlib import os +import sys import bl_i18n_utils from pathlib import Path @@ -33,6 +34,20 @@ def get_branches_directory(): return Path(context.preferences.filepaths.i18n_branches_directory) +def rearrange_files_for_po_import(po_dir_path: Path, temp_directory: tempfile.TemporaryDirectory): + """I18n directory also has a bit different format then `ui_translate.export/import`, + every .po file has a parent folder with the same name. + So we rearrange the data that way""" + # NOTE: TemporaryDirectory is cleared automatically as variable goes out of scope + # so we expect it as an argument so it won't get cleared right away + + temp_po_dir_path = Path(temp_directory.name) + for file in po_dir_path.glob("**/*"): + if file.suffix != ".po": + continue + shutil.copy(file, temp_po_dir_path / file.name) + + def dump_py_messages_monkey_patch(msgs, reports, addons, settings, addons_only=False): ignore_addon_dirs = ["libs"] @@ -304,21 +319,14 @@ class UpdateTranslationsFromPo(bpy.types.Operator): def execute(self, context): temp_po_dir = tempfile.TemporaryDirectory() - temp_po_dir_path = Path(temp_po_dir.name) branches_dir = get_branches_directory() - - for file in branches_dir.glob("**/*"): - if file.suffix != ".po": - continue - shutil.copy(file, temp_po_dir_path / file.name) + rearrange_files_for_po_import(branches_dir, temp_po_dir) bpy.ops.ui.i18n_addon_translation_import( module_name=ADDON_NAME, directory=temp_po_dir.name, ) - temp_po_dir.cleanup() - # update translations in current Blender session if is_addon_loaded(ADDON_NAME): bpy.app.translations.unregister(ADDON_NAME) @@ -401,3 +409,40 @@ def register(): def unregister(): for cls in classes: bpy.utils.unregister_class(cls) + + +def update_translations_from_po(po_directory: Path, translations_module: Path): + from bl_i18n_utils.settings import I18nSettings + import bl_i18n_utils.utils as utils_i18n + + temp_po_dir = tempfile.TemporaryDirectory() + rearrange_files_for_po_import(po_directory, temp_po_dir) + + settings = I18nSettings() + + trans = utils_i18n.I18n(kind="PY", src=translations_module.as_posix(), settings=settings) + po_files = dict(utils_i18n.get_po_files_from_dir(temp_po_dir.name)) + + for po_uid, po_filepath in po_files.items(): + po_uid = po_uid[0] + msgs = utils_i18n.I18nMessages(uid=po_uid, kind="PO", key=po_uid, src=po_filepath, settings=settings) + if po_uid in trans.trans: + trans.trans[po_uid].merge(msgs, replace=True) + else: + trans.trans[po_uid] = msgs + + trans.write(kind="PY") + + +if __name__ == "__main__": + # Example: + # py src/blenderbim/scripts/bbim_setup_translations.py -i "C:/blenderbim-translations" -o "C:/Blender/4.0/scripts/addons/blenderbim/translations.py" + import argparse + + parser = argparse.ArgumentParser(description="Converts .po files to translations.py") + parser.add_argument("-i", "--input", type=str, required=True, help="Directory with .po files") + parser.add_argument( + "-o", "--output", type=str, required=True, help="translations.py module location (file may not exist yet)" + ) + args = parser.parse_args() + update_translations_from_po(po_directory=Path(args.input), translations_module=Path(args.output))