I18n: Extract and translate asset catalog and asset names and descriptions #105747

Closed
Damien Picard wants to merge 2 commits from pioverfour:dp_translate_asset_nodes_menu into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
4 changed files with 61 additions and 4 deletions

View File

@ -928,6 +928,55 @@ def dump_template_messages(msgs, reports, settings):
reports, None, settings)
def dump_asset_messages(msgs, reports, settings):
# Where to search for assets, relative to the local user resources.
assets_dir = os.path.join(bpy.utils.resource_path('LOCAL'), "datafiles", "assets")
# Parse the catalog sidecar file
catalog_file = os.path.join(assets_dir, settings.ASSET_CATALOG_FILE)
with open(catalog_file, encoding="utf8") as f:
data = f.readlines()
catalogs = set()
for line in data:
pioverfour marked this conversation as resolved Outdated

debug prints should not be committed ;)

debug prints should not be committed ;)

Oops, sorry about that!

Oops, sorry about that!
if (line == "\n" or line.startswith("VERSION") or line.startswith("#")):
continue
_UUID, catalog_path, _simple_catalog_name = line.split(":")
catalogs.update(catalog_path.split("/"))
msgsrc = "Asset catalog from " + settings.ASSET_CATALOG_FILE
for catalog in sorted(catalogs):
process_msg(msgs, settings.DEFAULT_CONTEXT, catalog, msgsrc,
reports, None, settings)
# Parse the asset blend files
asset_files = {}
bfiles = glob.glob(assets_dir + "/**/*.blend", recursive=True)
for bfile in bfiles:
basename = os.path.basename(bfile)
bpy.ops.wm.open_mainfile(filepath=bfile)
# For now, only parse node groups.
# Perhaps some other assets will need to be extracted later?
for asset_type in ("node_groups",):
for asset in getattr(bpy.data, asset_type):
if asset.asset_data is None: # Not an asset
continue
assets = asset_files.setdefault(basename, [])
assets.append((asset.name, asset.asset_data.description))
for asset_file in sorted(asset_files):
for asset in sorted(asset_files[asset_file]):
name, description = asset
msgsrc = "Asset name from file " + asset_file
process_msg(msgs, settings.DEFAULT_CONTEXT, name, msgsrc,
reports, None, settings)
msgsrc = "Asset description from file " + asset_file
process_msg(msgs, settings.DEFAULT_CONTEXT, description, msgsrc,
reports, None, settings)
def dump_addon_bl_info(msgs, reports, module, settings):
for prop in ('name', 'location', 'description', 'warning'):
process_msg(
@ -980,6 +1029,7 @@ def dump_messages(do_messages, do_checks, settings):
dump_preset_messages(msgs, reports, settings)
# Get strings from startup templates.
# This loads each startup blend file in turn.
pioverfour marked this conversation as resolved Outdated

Would rather call this as a last step, since it load blend files... (also document that with a comment to the call)?

Would rather call this as a last step, since it load blend files... (also document that with a comment to the call)?

Would rather call this as a last step, since it load blend files... (also document that with a comment to the call)?

I moved it down, but another function loaded blends, dump_template_messages() for startup templates. Should I move it down too, or leave it be so messages remain stable?

> Would rather call this as a last step, since it load blend files... (also document that with a comment to the call)? I moved it down, but another function loaded blends, `dump_template_messages()` for startup templates. Should I move it down too, or leave it be so messages remain stable?

Not ideal, but would leave here for now 9for that reason of keeping existing messages order as stable as possible).

Not ideal, but would leave here for now 9for that reason of keeping existing messages order as stable as possible).
dump_template_messages(msgs, reports, settings)
# Get strings from addons' bl_info.
@ -1019,6 +1069,10 @@ def dump_messages(do_messages, do_checks, settings):
process_msg(msgs, settings.DEFAULT_CONTEXT, cat[1],
"Language categories labels from bl_i18n_utils/settings.py", reports, None, settings)
# Get strings from asset catalogs and blend files.
# This loads each asset blend file in turn.
dump_asset_messages(msgs, reports, settings)
# pot.check()
pot.unescape() # Strings gathered in py/C source code may contain escaped chars...
print_info(reports, pot)

View File

@ -527,6 +527,9 @@ REL_PRESETS_DIR = os.path.join("scripts", "presets")
# Where to search for templates (relative to SOURCE_DIR).
REL_TEMPLATES_DIR = os.path.join("scripts", "startup", "bl_app_templates_system")
# Name of the built-in asset catalog file.
ASSET_CATALOG_FILE = "blender_assets.cats.txt"
pioverfour marked this conversation as resolved Outdated

This is not relative to SOURCE_DIR, but to the installed data (like 3.6/datafiles/assets on linux builds e.g.)?
In source context, assets are from an SVN lib, so they live outside of the root git checkout (typically ../lib/assets/ relative to SOURCE_DIR).

So this path should rather be considered as relative to bpy.utils.resource_path('LOCAL')...

This is not relative to `SOURCE_DIR`, but to the installed data (like `3.6/datafiles/assets` on linux builds e.g.)? In source context, assets are from an SVN lib, so they live outside of the root git checkout (typically `../lib/assets/` relative to `SOURCE_DIR`). So this path should rather be considered as relative to `bpy.utils.resource_path('LOCAL')`...

My bad, I use symbolic links and thought this dir was from the sources.

My bad, I use symbolic links and thought this dir was from the sources.
# The template messages file (relative to I18N_DIR).
REL_FILE_NAME_POT = os.path.join(REL_BRANCHES_DIR, DOMAIN + ".pot")

View File

@ -190,7 +190,7 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
uiLayoutSetContextPointer(col, "asset_library_ref", &library_ptr);
uiItemO(
col, AS_asset_representation_name_get(&item.asset), ICON_NONE, "NODE_OT_add_group_asset");
col, IFACE_(AS_asset_representation_name_get(&item.asset)), ICON_NONE, "NODE_OT_add_group_asset");
}
catalog_item->foreach_child([&](asset_system::AssetCatalogTreeItem &child_item) {
@ -200,7 +200,7 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
&screen.id, &RNA_AssetCatalogPath, const_cast<asset_system::AssetCatalogPath *>(&path)};
uiLayout *col = uiLayoutColumn(layout, false);
uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr);
uiItemM(col, "NODE_MT_node_add_catalog_assets", path.name().c_str(), ICON_NONE);
uiItemM(col, "NODE_MT_node_add_catalog_assets", IFACE_(path.name().c_str()), ICON_NONE);
});
}
@ -270,7 +270,7 @@ static void add_root_catalogs_draw(const bContext *C, Menu *menu)
&screen.id, &RNA_AssetCatalogPath, const_cast<asset_system::AssetCatalogPath *>(&path)};
uiLayout *col = uiLayoutColumn(layout, false);
uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr);
uiItemM(col, "NODE_MT_node_add_catalog_assets", path.name().c_str(), ICON_NONE);
uiItemM(col, "NODE_MT_node_add_catalog_assets", IFACE_(path.name().c_str()), ICON_NONE);
});
}

View File

@ -468,7 +468,7 @@ static char *node_add_group_asset_get_description(struct bContext *C,
if (!asset_data.description) {
return nullptr;
}
return BLI_strdup(asset_data.description);
return BLI_strdup(DATA_(asset_data.description));
}
void NODE_OT_add_group_asset(wmOperatorType *ot)