diff --git a/core/export_resonite.py b/core/export_resonite.py index 4cb73fe..92be1e0 100644 --- a/core/export_resonite.py +++ b/core/export_resonite.py @@ -11,8 +11,8 @@ from ..functions.translations import t @register_wrap class ExportResonite(Operator): bl_idname = 'avatar_toolkit.export_resonite' - bl_label = t("Export.resonite.label") - bl_description = t("Export.resonite.desc") + bl_label = t("Importer.export_resonite.label") + bl_description = t("Importer.export_resonite.desc") bl_options = {'REGISTER', 'UNDO'} filepath: bpy.props.StringProperty() diff --git a/core/properties.py b/core/properties.py index 9fd77cb..2a00b5d 100644 --- a/core/properties.py +++ b/core/properties.py @@ -8,10 +8,6 @@ from ..core.register import register_wrap from ..core.addon_preferences import get_preference from ..core.common import SceneMatClass, material_list_bool, get_armatures, get_mesh_items - - - - def register() -> None: default_language = get_preference("language", 0) bpy.types.Scene.avatar_toolkit_language = bpy.props.EnumProperty( @@ -31,20 +27,20 @@ def register() -> None: bpy.types.Scene.avatar_toolkit_language_changed = bpy.props.BoolProperty(default=False) bpy.types.Scene.mouth_a = bpy.props.StringProperty( - name=t("Scene.mouth_a.label"), - description=t("Scene.mouth_a.desc") + name=t("VisemePanel.mouth_a.label"), + description=t("VisemePanel.mouth_a.desc") ) bpy.types.Scene.mouth_o = bpy.props.StringProperty( - name=t("Scene.mouth_o.label"), - description=t("Scene.mouth_o.desc") + name=t("VisemePanel.mouth_o.label"), + description=t("VisemePanel.mouth_o.desc") ) bpy.types.Scene.mouth_ch = bpy.props.StringProperty( - name=t("Scene.mouth_ch.label"), - description=t("Scene.mouth_ch.desc") + name=t("VisemePanel.mouth_ch.label"), + description=t("VisemePanel.mouth_ch.desc") ) bpy.types.Scene.shape_intensity = bpy.props.FloatProperty( - name=t("Scene.shape_intensity.label"), - description=t("Scene.shape_intensity.desc"), + name=t("VisemePanel.shape_intensity"), + description=t("VisemePanel.shape_intensity_desc"), default=1.0, min=0.0, max=2.0 diff --git a/functions/atlas_materials.py b/functions/atlas_materials.py index c0e537a..4c5bf83 100644 --- a/functions/atlas_materials.py +++ b/functions/atlas_materials.py @@ -10,10 +10,7 @@ from bpy.types import Material, Operator, Context, Object, Image, Mesh, MeshUVLo from ..core.register import register_wrap from ..core.common import SceneMatClass, material_list_bool from ..core.packer.rectangle_packer import MaterialImageList, BinPacker - - - - +from ..functions.translations import t def scale_images_to_largest(images:list[Image]) -> set: print([image.name for image in images]) @@ -119,8 +116,8 @@ def prep_images_in_scene(context: Context) -> list[MaterialImageList]: class Atlas_Materials(Operator): bl_idname = "avatar_toolkit.atlas_materials" - bl_label = "Atlas Materials" - bl_description = "Atlas materials to optimize the model" + bl_label = t("TextureAtlas.atlas_materials") + bl_description = t("TextureAtlas.atlas_materials_desc") bl_options = {'REGISTER', 'UNDO'} @classmethod @@ -270,9 +267,11 @@ class Atlas_Materials(Operator): mesh.materials.append(atlased_mat.material) + self.report({'INFO'}, t("TextureAtlas.atlas_completed")) return {"FINISHED"} except Exception as e: + self.report({'ERROR'}, t("TextureAtlas.atlas_error")) raise e - return {"FINISHED"} + return {"FINISHED"} \ No newline at end of file diff --git a/functions/combine_materials.py b/functions/combine_materials.py index 473e881..43d4472 100644 --- a/functions/combine_materials.py +++ b/functions/combine_materials.py @@ -71,7 +71,7 @@ class CombineMaterials(Operator): def execute(self, context: Context) -> Set[str]: armature = get_selected_armature(context) if not armature: - self.report({'WARNING'}, "No armature selected") + self.report({'WARNING'}, t("Optimization.no_armature_selected")) return {'CANCELLED'} context.view_layer.objects.active = armature @@ -79,7 +79,7 @@ class CombineMaterials(Operator): meshes = get_all_meshes(context) if not meshes: - self.report({'WARNING'}, "No meshes found for the selected armature") + self.report({'WARNING'}, t("Optimization.no_meshes_found")) return {'CANCELLED'} self.consolidate_materials(meshes) @@ -111,7 +111,7 @@ class CombineMaterials(Operator): else: mat_mapping[base_name] = mat - report_consolidated(self, num_combined) + self.report({'INFO'}, t("Optimization.materials_combined").format(num_combined=num_combined)) def remove_unused_materials(self) -> None: for mat in bpy.data.materials: diff --git a/functions/digitigrade_legs.py b/functions/digitigrade_legs.py index 27ea3e5..0544e6a 100644 --- a/functions/digitigrade_legs.py +++ b/functions/digitigrade_legs.py @@ -32,7 +32,7 @@ class CreateDigitigradeLegs(bpy.types.Operator): digi2 = digi1.children[0] digi3 = digi2.children[0] except: - print("bone format incorrect! Please select a chain of 4 continious bones!") #TODO: Show this to user. this is an error. + self.report({'ERROR'}, t('Tools.digitigrade_legs.error.bone_format')) return {'CANCELLED'} digi4 = None try: @@ -114,4 +114,6 @@ class CreateDigitigradeLegs(bpy.types.Operator): digi1.name = re.compile(re.escape(""), re.IGNORECASE).sub("",digi1.name)+"" digi2.name = re.compile(re.escape(""), re.IGNORECASE).sub("",digi2.name)+"" #finally fully done! + + self.report({'INFO'}, t('Tools.digitigrade_legs.success')) return {'FINISHED'} \ No newline at end of file diff --git a/functions/import_anything.py b/functions/import_anything.py index f4a5921..58ed75e 100644 --- a/functions/import_anything.py +++ b/functions/import_anything.py @@ -77,6 +77,7 @@ class ImportAnyModel(Operator, ImportHelper): print("importer error was:") print(e) + self.report({'INFO'}, t('Quick_Access.import_success')) return {'FINISHED'} diff --git a/functions/join_meshes.py b/functions/join_meshes.py index 9fbe3a1..3310ae9 100644 --- a/functions/join_meshes.py +++ b/functions/join_meshes.py @@ -23,7 +23,7 @@ class JoinAllMeshes(Operator): def join_all_meshes(self, context: Context) -> None: if not select_current_armature(context): - self.report({'WARNING'}, "No armature selected") + self.report({'WARNING'}, t("Optimization.no_armature_selected")) return armature = get_selected_armature(context) @@ -41,9 +41,9 @@ class JoinAllMeshes(Operator): fix_uv_coordinates(context) bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.select_all(action='DESELECT') - self.report({'INFO'}, "Meshes joined successfully") + self.report({'INFO'}, t("Optimization.meshes_joined")) else: - self.report({'WARNING'}, "No mesh objects selected") + self.report({'WARNING'}, t("Optimization.no_mesh_selected")) context.view_layer.objects.active = armature @@ -66,7 +66,7 @@ class JoinSelectedMeshes(Operator): selected_objects: List[Object] = [obj for obj in bpy.context.selected_objects if obj.type == 'MESH'] if len(selected_objects) < 2: - self.report({'WARNING'}, "Please select at least two mesh objects") + self.report({'WARNING'}, t("Optimization.select_at_least_two_meshes")) return bpy.ops.object.mode_set(mode='OBJECT') @@ -82,7 +82,6 @@ class JoinSelectedMeshes(Operator): fix_uv_coordinates(context) bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.select_all(action='DESELECT') - self.report({'INFO'}, "Selected meshes joined successfully") + self.report({'INFO'}, t("Optimization.selected_meshes_joined")) else: - self.report({'WARNING'}, "No mesh objects selected") - + self.report({'WARNING'}, t("Optimization.no_mesh_selected")) diff --git a/functions/remove_doubles_safely.py b/functions/remove_doubles_safely.py index 1631b68..9c2078c 100644 --- a/functions/remove_doubles_safely.py +++ b/functions/remove_doubles_safely.py @@ -6,7 +6,7 @@ from typing import List, Tuple, Optional, TypedDict from bpy.types import Material, Operator, Context, Object from ..core.register import register_wrap from ..core.common import get_selected_armature, is_valid_armature, select_current_armature, get_all_meshes - +from ..functions.translations import t class meshEntry(TypedDict): mesh: bpy.types.Object @@ -15,8 +15,8 @@ class meshEntry(TypedDict): @register_wrap class RemoveDoublesSafely(Operator): bl_idname = "avatar_toolkit.remove_doubles_safely" - bl_label = "Remove Doubles Safely" - bl_description = "Remove Doubles on all meshes, making sure to not fuse things like mouths together." + bl_label = t("Optimization.remove_doubles_safely.label") + bl_description = t("Optimization.remove_doubles_safely.desc") bl_options = {'REGISTER', 'UNDO'} objects_to_do: list[meshEntry] = [] merge_distance: bpy.props.FloatProperty(default=0.0001) @@ -28,7 +28,7 @@ class RemoveDoublesSafely(Operator): def execute(self, context: Context) -> set: if not select_current_armature(context): - self.report({'WARNING'}, "No armature selected") + self.report({'WARNING'}, t("Optimization.no_armature_selected")) return {'CANCELLED'} armature = get_selected_armature(context) @@ -117,6 +117,7 @@ class RemoveDoublesSafely(Operator): mesh["mesh"].select_set(False) else: + self.report({'INFO'}, t("Optimization.remove_doubles_completed")) return {'FINISHED'} return {'RUNNING_MODAL'} diff --git a/functions/resonite_functions.py b/functions/resonite_functions.py index 2b6a005..9d81d70 100644 --- a/functions/resonite_functions.py +++ b/functions/resonite_functions.py @@ -22,7 +22,7 @@ class ConvertToResonite(Operator): def execute(self, context: Context) -> set: armature = get_selected_armature(context) if not armature: - self.report({'WARNING'}, "No armature selected") + self.report({'WARNING'}, t("Tools.no_armature_selected")) return {'CANCELLED'} translate_bone_fails = 0 @@ -107,8 +107,8 @@ class ConvertToResonite(Operator): bpy.ops.object.mode_set(mode='OBJECT') if translate_bone_fails > 0: - self.report({'INFO'}, "Failed to translate {translate_bone_fails} bones to humanoid names. Adding \"\" to their names.".format(translate_bone_fails=translate_bone_fails)) + self.report({'INFO'}, t("Tools.bones_translated_with_fails").format(translate_bone_fails=translate_bone_fails)) else: - self.report({'INFO'}, "Successfully translated all bones to humanoid names") + self.report({'INFO'}, t("Tools.bones_translated_success")) return {'FINISHED'} diff --git a/functions/viseme.py b/functions/viseme.py index 9ba8849..871ce73 100644 --- a/functions/viseme.py +++ b/functions/viseme.py @@ -63,7 +63,6 @@ class AutoVisemeButton(bpy.types.Operator): print("Sorting shape keys...") common.sort_shape_keys(mesh) - print("Viseme creation completed.") self.report({'INFO'}, t('AutoVisemeButton.success')) return {'FINISHED'} diff --git a/resources/translations/en_US.json b/resources/translations/en_US.json index 8cdcb40..8d6f720 100644 --- a/resources/translations/en_US.json +++ b/resources/translations/en_US.json @@ -1,63 +1,120 @@ { - "authors": ["Avatar Toolkit Team"], + "authors": ["Avatar Toolkit Team"], "messages": { - "Language.auto": "Automatic", - "Language.en_US": "English", - "Language.ja_JP": "日本語", - "Quick_Access.label": "Quick Access", - "Quick_Access.import_export.label": "Import/Export", - "Quick_Access.options": "Quick Access Options", - "Quick_Access.import_menu.label": "Import Menu", - "Quick_Access.import": "Import", - "Quick_Access.export": "Export", - "Quick_Access.import_menu.desc": "Import a Model", - "Quick_Access.import_pmx": "Import PMX", - "Quick_Access.import_pmx.desc": "Import MMD PMX Model", - "Quick_Access.import_pmd": "Import PMD", - "Quick_Access.import_pmd.desc": "Import MMD PMD Model", - "Quick_Access.export_menu.label": "Export Menu", - "Quick_Access.select_export.label": "Select Export Method", - "Quick_Access.select_export_resonite.label": "Resonite", - "Export.resonite.label": "Export to Resonite", - "Export.resonite.desc": "Export a GLB with all animations and materials. For animation data see:", - "Optimization.label": "Optimization", - "Optimization.options.label": "Optimization Options", - "Optimization.combine_materials.label": "Combine Materials", - "Optimization.combine_materials.desc": "Combine similar materials to optimize the model", - "Optimization.join_all_meshes.label": "Join All Meshes", - "Optimization.join_all_meshes.desc": "Join all meshes into one", - "Optimization.join_selected_meshes.label": "Join Selected Mehses", - "Optimization.join_selected_meshes.desc": "Join all currntly Selected Mehses into one", - "Tools.tools_title.label": "Tools", - "Tools.convert_to_resonite.label": "Convert to Resonite", - "Tools.convert_to_resonite.desc": "Converts bone names on a model to names compatable with Resonite", - "VisemePanel.label": "Visemes", - "VisemePanel.error.noMesh": "No mesh selected", - "VisemePanel.error.noShapekeys": "Selected mesh has no shape keys", - "VisemePanel.info.selectMesh": "Select a mesh to create visemes", - "VisemePanel.mouth_a.label": "Mouth A", - "VisemePanel.mouth_o.label": "Mouth O", - "VisemePanel.mouth_ch.label": "Mouth CH", - "AutoVisemeButton.label": "Create Visemes", - "AutoVisemeButton.desc": "Create visemes automatically, based on shape keys", - "AutoVisemeButton.error.noShapekeys": "No shape keys found", - "AutoVisemeButton.error.selectShapekeys": "Please Select shape keys", - "AutoVisemeButton.success": "Visemes created successfully", - "Settings.translation_restart_popup.label": "Translation Update", - "Settings.label": "Settings", - "Settings.language.label": "Language", - "Settings.language.desc": "Select the language for the addon's UI", - "Settings.translation_restart_popup.description": "Information about translation updates", - "Settings.translation_restart_popup.message1": "Some translations may not apply", - "Settings.translation_restart_popup.message2": "until you restart Blender.", - "Importing.need_importer":"You do not have the required importer for the {extension} type! Opening web browser for importer search term...", - "Importer.mmd_anim_importer.label":"MMD Animation", - "Importer.mmd_anim_importer.desc":"Import a MMD Animation (.vmd)", - "Importing.importer_search_term":"https://search.brave.com/search?q=blender+{extension}+importer+addon&source=web", - "Importer.export_resonite.label":"Export to Resonite", - "Importer.export_resonite.desc":"Export to Resonite as a GLTF. Make sure your model is to scale in blender, and import as meters in Resonite.", - "Importer.export_vrchat.label":"Export to VRChat", - "Importer.export_vrchat.desc":"Export to VRChat, may also work for ChilloutVR. Is similar to Cats export." - } + "Language.auto": "Automatic", + "Language.en_US": "English", + "Language.ja_JP": "日本語", + "AvatarToolkit.label": "Avatar Toolkit", + "AvatarToolkit.welcome": "Welcome to Avatar Toolkit, a tool for", + "AvatarToolkit.description": "creating and editing avatars in blender,", + "AvatarToolkit.alpha_warning": "This is an early alpha version, so expect bugs and issues.", + "Quick_Access.label": "Quick Access", + "Quick_Access.import_export.label": "Import/Export", + "Quick_Access.options": "Quick Access Options", + "Quick_Access.import_menu.label": "Import Menu", + "Quick_Access.import": "Import", + "Quick_Access.export": "Export", + "Quick_Access.import_menu.desc": "Import a Model", + "Quick_Access.import_pmx": "Import PMX", + "Quick_Access.import_pmx.desc": "Import MMD PMX Model", + "Quick_Access.import_pmd": "Import PMD", + "Quick_Access.import_pmd.desc": "Import MMD PMD Model", + "Quick_Access.export_menu.label": "Export Menu", + "Quick_Access.export_menu.desc": "Export to a supported format", + "Quick_Access.select_export.label": "Select Export Method", + "Quick_Access.select_export_resonite.label": "Resonite", + "Quick_Access.export_fbx.label": "Export FBX", + "Quick_Access.export_fbx.desc": "Export the model as FBX", + "Quick_Access.import_success": "Model imported successfully", + "Export.resonite.label": "Export to Resonite", + "Export.resonite.desc": "Export a GLB with all animations and materials. For animation data see:", + "Optimization.label": "Optimization", + "Optimization.options.label": "Optimization Options", + "Optimization.combine_materials.label": "Combine Materials", + "Optimization.combine_materials.desc": "Combine similar materials to optimize the model", + "Optimization.join_all_meshes.label": "Join All Meshes", + "Optimization.join_all_meshes.desc": "Join all meshes into one", + "Optimization.join_selected_meshes.label": "Join Selected Meshes", + "Optimization.join_selected_meshes.desc": "Join all currently Selected Meshes into one", + "Optimization.remove_doubles_safely.label": "Remove Doubles Safely", + "Optimization.remove_doubles_safely.desc": "Remove doubles on all meshes, making sure not to fuse things like mouths together", + "Optimization.no_armature_selected": "No armature selected", + "Optimization.no_meshes_found": "No meshes found for the selected armature", + "Optimization.materials_combined": "Combined {num_combined} materials", + "Optimization.meshes_joined": "Meshes joined successfully", + "Optimization.no_mesh_selected": "No mesh objects selected", + "Optimization.select_at_least_two_meshes": "Please select at least two mesh objects", + "Optimization.selected_meshes_joined": "Selected meshes joined successfully", + "Optimization.vertex_excluded": "Shapekey has a moved vertex at index \"{index}\", excluding from double merging!", + "Optimization.processing_shapekey": "Processing shapekey \"{shapekeyname}\" on mesh \"{mesh_name}\"", + "Optimization.processing_mesh_no_shapekeys": "Processing mesh with no shapekeys named \"{mesh_name}\"", + "Optimization.remove_doubles_completed": "Remove doubles operation completed", + "Optimization.select_armature": "Please select an armature", + "Tools.select_armature": "Please select an armature", + "Tools.label": "Tools", + "Tools.tools_title.label": "Tools", + "Tools.convert_to_resonite.label": "Convert to Resonite", + "Tools.convert_to_resonite.desc": "Converts bone names on a model to names compatible with Resonite", + "Tools.create_digitigrade_legs.label": "Create Digitigrade Legs", + "Tools.create_digitigrade_legs.desc": "Create digitigrade legs from a selected bone chain", + "Tools.digitigrade_legs.error.bone_format": "Bone format incorrect! Please select a chain of 4 continuous bones!", + "Tools.digitigrade_legs.success": "Digitigrade legs created successfully", + "Tools.no_armature_selected": "No armature selected", + "Tools.bones_translated_with_fails": "Failed to translate {translate_bone_fails} bones to humanoid names. Adding \"\" to their names.", + "Tools.bones_translated_success": "Successfully translated all bones to humanoid names", + "Tools.import_any_model.desc": "Import any supported model, FBX, SMD, DMX, GLTF, PMD, PMX and more.", + "TextureAtlas.label": "Texture Atlasing", + "TextureAtlas.material_list_label": "Texture Atlas Material List Material", + "TextureAtlas.reload_list": "Reload Texture Atlas Material List", + "TextureAtlas.loaded_list": "Loaded Texture Atlas Material List", + "TextureAtlas.atlas_materials": "Atlas Materials", + "TextureAtlas.atlas_materials_desc": "Atlas materials to optimize the model", + "TextureAtlas.atlas_completed": "Texture atlas creation completed", + "TextureAtlas.atlas_error": "An error occurred during texture atlas creation", + "VisemePanel.label": "Visemes", + "VisemePanel.select_mesh": "Select Mesh", + "VisemePanel.mouth_a.label": "Mouth A", + "VisemePanel.mouth_a.desc": "The shapekey for the 'A' mouth shape", + "VisemePanel.mouth_o.label": "Mouth O", + "VisemePanel.mouth_o.desc": "The shapekey for the 'O' mouth shape", + "VisemePanel.mouth_ch.label": "Mouth CH", + "VisemePanel.mouth_ch.desc": "The shapekey for the 'CH' mouth shape", + "VisemePanel.shape_intensity": "Shape Intensity", + "VisemePanel.shape_intensity_desc": "The intensity of the viseme shapekeys", + "VisemePanel.create_visemes": "Create Visemes", + "VisemePanel.error.noMesh": "No mesh selected", + "VisemePanel.error.noShapekeys": "Selected mesh has no shape keys", + "VisemePanel.error.selectMesh": "Select a mesh to create visemes", + "VisemePanel.error.noArmature": "No armature selected", + "VisemePanel.info.selectMesh": "Select a mesh to create visemes", + "VisemePanel.start_viseme_creation": "Starting viseme creation...", + "VisemePanel.selected_shapes": "Selected shapes: A={shape_a}, O={shape_o}, CH={shape_ch}", + "VisemePanel.creating_viseme": "Creating viseme: {viseme_name}", + "VisemePanel.sorting_shapekeys": "Sorting shape keys...", + "VisemePanel.viseme_creation_completed": "Viseme creation completed.", + "VisemePanel.creating_viseme_detail": "Creating viseme: {viseme_name}", + "VisemePanel.removing_existing_viseme": "Removing existing viseme: {viseme_name}", + "VisemePanel.mixing_shape": "Mixing shape: {shape_name} with value: {value}", + "VisemePanel.viseme_created_successfully": "Viseme {viseme_name} created successfully", + "AutoVisemeButton.label": "Create Visemes", + "AutoVisemeButton.desc": "Create visemes automatically, based on shape keys", + "AutoVisemeButton.error.noShapekeys": "No shape keys found", + "AutoVisemeButton.error.selectShapekeys": "Please Select shape keys", + "AutoVisemeButton.success": "Visemes created successfully", + "Settings.label": "Settings", + "Settings.language.label": "Language", + "Settings.language.desc": "Select the language for the addon's UI", + "Settings.translation_restart_popup.label": "Translation Update", + "Settings.translation_restart_popup.description": "Information about translation updates", + "Settings.translation_restart_popup.message1": "Some translations may not apply", + "Settings.translation_restart_popup.message2": "until you restart Blender.", + "Importing.need_importer": "You do not have the required importer for the {extension} type! Opening web browser for importer search term...", + "Importer.mmd_anim_importer.label": "MMD Animation", + "Importer.mmd_anim_importer.desc": "Import a MMD Animation (.vmd)", + "Importing.importer_search_term": "https://search.brave.com/search?q=blender+{extension}+importer+addon&source=web", + "Importer.export_resonite.label": "Export to Resonite", + "Importer.export_resonite.desc": "Export to Resonite as a GLTF. Make sure your model is to scale in blender, and import as meters in Resonite.", + "Importer.export_vrchat.label": "Export to VRChat", + "Importer.export_vrchat.desc": "Export to VRChat, may also work for ChilloutVR. Is similar to Cats export." } - \ No newline at end of file +} diff --git a/resources/translations/ja_JP.json b/resources/translations/ja_JP.json index 0e9763e..fcbf679 100644 --- a/resources/translations/ja_JP.json +++ b/resources/translations/ja_JP.json @@ -1,9 +1,13 @@ { - "authors": ["Avatar Toolkit Team"], + "authors": ["Avatar Toolkit チーム"], "messages": { "Language.auto": "自動", - "Language.en_US": "英語", + "Language.en_US": "English", "Language.ja_JP": "日本語", + "AvatarToolkit.label": "アバターツールキット", + "AvatarToolkit.welcome": "アバターツールキットへようこそ、これは", + "AvatarToolkit.description": "Blenderでアバターを作成・編集するためのツールです。", + "AvatarToolkit.alpha_warning": "これは早期アルファ版なので、バグや問題が予想されます。", "Quick_Access.label": "クイックアクセス", "Quick_Access.import_export.label": "インポート/エクスポート", "Quick_Access.options": "クイックアクセスオプション", @@ -16,10 +20,14 @@ "Quick_Access.import_pmd": "PMDをインポート", "Quick_Access.import_pmd.desc": "MMD PMDモデルをインポート", "Quick_Access.export_menu.label": "エクスポートメニュー", + "Quick_Access.export_menu.desc": "サポートされているフォーマットにエクスポート", "Quick_Access.select_export.label": "エクスポート方法を選択", "Quick_Access.select_export_resonite.label": "Resonite", + "Quick_Access.export_fbx.label": "FBXをエクスポート", + "Quick_Access.export_fbx.desc": "モデルをFBXとしてエクスポート", + "Quick_Access.import_success": "モデルが正常にインポートされました", "Export.resonite.label": "Resoniteにエクスポート", - "Export.resonite.desc": "すべてのアニメーションとマテリアルを含むGLBをエクスポート。アニメーションデータについては以下を参照:", + "Export.resonite.desc": "すべてのアニメーションとマテリアルを含むGLBをエクスポートします。アニメーションデータについては以下を参照:", "Optimization.label": "最適化", "Optimization.options.label": "最適化オプション", "Optimization.combine_materials.label": "マテリアルを結合", @@ -28,16 +36,66 @@ "Optimization.join_all_meshes.desc": "すべてのメッシュを1つに結合", "Optimization.join_selected_meshes.label": "選択したメッシュを結合", "Optimization.join_selected_meshes.desc": "現在選択されているすべてのメッシュを1つに結合", + "Optimization.remove_doubles_safely.label": "安全に重複頂点を削除", + "Optimization.remove_doubles_safely.desc": "口などの部分が融合しないように注意しながら、すべてのメッシュの重複頂点を削除", + "Optimization.no_armature_selected": "アーマチュアが選択されていません", + "Optimization.no_meshes_found": "選択されたアーマチュアにメッシュが見つかりません", + "Optimization.materials_combined": "{num_combined}個のマテリアルを結合しました", + "Optimization.meshes_joined": "メッシュが正常に結合されました", + "Optimization.no_mesh_selected": "メッシュオブジェクトが選択されていません", + "Optimization.select_at_least_two_meshes": "少なくとも2つのメッシュオブジェクトを選択してください", + "Optimization.selected_meshes_joined": "選択されたメッシュが正常に結合されました", + "Optimization.vertex_excluded": "シェイプキーのインデックス\"{index}\"の頂点が移動しているため、重複マージから除外しました!", + "Optimization.processing_shapekey": "メッシュ\"{mesh_name}\"のシェイプキー\"{shapekeyname}\"を処理中", + "Optimization.processing_mesh_no_shapekeys": "シェイプキーのないメッシュ\"{mesh_name}\"を処理中", + "Optimization.remove_doubles_completed": "重複頂点の削除が完了しました", + "Optimization.select_armature": "アーマチュアを選択してください", + "Tools.select_armature": "アーマチュアを選択してください", + "Tools.label": "ツール", "Tools.tools_title.label": "ツール", "Tools.convert_to_resonite.label": "Resoniteに変換", - "Tools.convert_to_resonite.desc": "モデルのボーン名をResoniteと互換性のある名前に変換", + "Tools.convert_to_resonite.desc": "モデルのボーン名をResoniteと互換性のある名前に変換します", + "Tools.create_digitigrade_legs.label": "デジタイグレード脚を作成", + "Tools.create_digitigrade_legs.desc": "選択したボーンチェーンからデジタイグレード脚を作成", + "Tools.digitigrade_legs.error.bone_format": "ボーンフォーマットが正しくありません!4つの連続したボーンのチェーンを選択してください!", + "Tools.digitigrade_legs.success": "デジタイグレード脚が正常に作成されました", + "Tools.no_armature_selected": "アーマチュアが選択されていません", + "Tools.bones_translated_with_fails": "{translate_bone_fails}個のボーンをヒューマノイド名に変換できませんでした。それらの名前に\"\"を追加しています。", + "Tools.bones_translated_success": "すべてのボーンをヒューマノイド名に正常に変換しました", + "Tools.import_any_model.desc": "FBX、SMD、DMX、GLTF、PMD、PMXなど、サポートされているすべてのモデルをインポートします。", + "TextureAtlas.label": "テクスチャアトラス", + "TextureAtlas.material_list_label": "テクスチャアトラスマテリアルリストマテリアル", + "TextureAtlas.reload_list": "テクスチャアトラスマテリアルリストを再読み込み", + "TextureAtlas.loaded_list": "テクスチャアトラスマテリアルリストを読み込みました", + "TextureAtlas.atlas_materials": "アトラスマテリアル", + "TextureAtlas.atlas_materials_desc": "モデルを最適化するためにマテリアルをアトラス化", + "TextureAtlas.atlas_completed": "テクスチャアトラスの作成が完了しました", + "TextureAtlas.atlas_error": "テクスチャアトラスの作成中にエラーが発生しました", "VisemePanel.label": "ビセーム", + "VisemePanel.select_mesh": "メッシュを選択", + "VisemePanel.mouth_a.label": "口 A", + "VisemePanel.mouth_a.desc": "'A'の口の形のシェイプキー", + "VisemePanel.mouth_o.label": "口 O", + "VisemePanel.mouth_o.desc": "'O'の口の形のシェイプキー", + "VisemePanel.mouth_ch.label": "口 CH", + "VisemePanel.mouth_ch.desc": "'CH'の口の形のシェイプキー", + "VisemePanel.shape_intensity": "シェイプの強度", + "VisemePanel.shape_intensity_desc": "ビセームシェイプキーの強度", + "VisemePanel.create_visemes": "ビセームを作成", "VisemePanel.error.noMesh": "メッシュが選択されていません", "VisemePanel.error.noShapekeys": "選択されたメッシュにシェイプキーがありません", + "VisemePanel.error.selectMesh": "ビセームを作成するメッシュを選択してください", + "VisemePanel.error.noArmature": "アーマチュアが選択されていません", "VisemePanel.info.selectMesh": "ビセームを作成するメッシュを選択してください", - "VisemePanel.mouth_a.label": "口 A", - "VisemePanel.mouth_o.label": "口 O", - "VisemePanel.mouth_ch.label": "口 CH", + "VisemePanel.start_viseme_creation": "ビセーム作成を開始しています...", + "VisemePanel.selected_shapes": "選択されたシェイプ: A={shape_a}, O={shape_o}, CH={shape_ch}", + "VisemePanel.creating_viseme": "ビセームを作成中: {viseme_name}", + "VisemePanel.sorting_shapekeys": "シェイプキーをソート中...", + "VisemePanel.viseme_creation_completed": "ビセーム作成が完了しました。", + "VisemePanel.creating_viseme_detail": "ビセームを作成中: {viseme_name}", + "VisemePanel.removing_existing_viseme": "既存のビセームを削除中: {viseme_name}", + "VisemePanel.mixing_shape": "シェイプをミックス中: {shape_name} 値: {value}", + "VisemePanel.viseme_created_successfully": "ビセーム {viseme_name} が正常に作成されました", "AutoVisemeButton.label": "ビセームを作成", "AutoVisemeButton.desc": "シェイプキーに基づいて自動的にビセームを作成", "AutoVisemeButton.error.noShapekeys": "シェイプキーが見つかりません", @@ -45,10 +103,19 @@ "AutoVisemeButton.success": "ビセームが正常に作成されました", "Settings.label": "設定", "Settings.language.label": "言語", - "Settings.language.desc": "アドオンのUI言語を選択してください", + "Settings.language.desc": "アドオンのUIの言語を選択", "Settings.translation_restart_popup.label": "翻訳の更新", "Settings.translation_restart_popup.description": "翻訳の更新に関する情報", "Settings.translation_restart_popup.message1": "一部の翻訳は適用されない場合があります", - "Settings.translation_restart_popup.message2": "Blenderを再起動するまで。" + "Settings.translation_restart_popup.message2": "Blenderを再起動するまで。", + "Importing.need_importer": "{extension}タイプに必要なインポーターがありません!インポーター検索用のウェブブラウザを開いています...", + "Importer.mmd_anim_importer.label": "MMDアニメーション", + "Importer.mmd_anim_importer.desc": "MMDアニメーション(.vmd)をインポート", + "Importing.importer_search_term": "https://search.brave.com/search?q=blender+{extension}+importer+addon&source=web", + "Importer.export_resonite.label": "Resoniteにエクスポート", + "Importer.export_resonite.desc": "GLTFとしてResoniteにエクスポートします。Blenderでモデルが正しいスケールであることを確認し、Resoniteでメートル単位でインポートしてください。", + "Importer.export_vrchat.label": "VRChatにエクスポート", + "Importer.export_vrchat.desc": "VRChatにエクスポートします。ChilloutVRでも動作する可能性があります。Catsのエクスポートに似ています。" } } + diff --git a/ui/atlas_materials.py b/ui/atlas_materials.py index 4487718..63805a2 100644 --- a/ui/atlas_materials.py +++ b/ui/atlas_materials.py @@ -4,7 +4,7 @@ from ..core.register import register_wrap from .panel import AvatarToolkitPanel from ..core.common import SceneMatClass, material_list_bool from ..functions.atlas_materials import Atlas_Materials - +from ..functions.translations import t @register_wrap class ExpandSection_Materials(Operator): @@ -16,9 +16,7 @@ class ExpandSection_Materials(Operator): def poll(cls, context: Context) -> bool: return True - def execute(self, context: Context) -> set: - if not context.scene.texture_atlas_Has_Mat_List_Shown: context.scene.materials.clear() newlist: list[Material] = [] @@ -37,14 +35,12 @@ class ExpandSection_Materials(Operator): @register_wrap class MaterialTextureAtlasProperties(UIList): - bl_label = "Texture Atlas Material List Material" + bl_label = t("TextureAtlas.material_list_label") bl_idname = "Material_UL_avatar_toolkit_texture_atlas_mat_list_mat" bl_space_type = 'VIEW_3D' bl_region_type = 'UI' - def draw_item(self , context: Context, layout: UILayout, data: bpy.types.Object, item:SceneMatClass, icon, active_data, active_propname, index): - if context.scene.texture_atlas_Has_Mat_List_Shown: box = layout.box() row = box.row() @@ -61,18 +57,16 @@ class MaterialTextureAtlasProperties(UIList): col.prop(item.mat, "texture_atlas_height") col = box.row() col.prop(item.mat, "texture_atlas_roughness") - - - @register_wrap class TextureAtlasPanel(Panel): - bl_label = "Texture Atlasing" + bl_label = t("TextureAtlas.label") bl_idname = "OBJECT_PT_avatar_toolkit_texture_atlas" bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_category = "Avatar Toolkit" bl_parent_id = "OBJECT_PT_avatar_toolkit" + bl_order = 4 def draw(self, context: Context): layout = self.layout @@ -80,13 +74,10 @@ class TextureAtlasPanel(Panel): boxoutter = row.box() direction_icon = 'RIGHTARROW' if not context.scene.texture_atlas_Has_Mat_List_Shown else 'DOWNARROW_HLT' row = boxoutter.row() - row.operator(ExpandSection_Materials.bl_idname, text=("Reload Texture Atlas Material List" if not context.scene.texture_atlas_Has_Mat_List_Shown else "Loaded Texture Atlas Material List"), icon=direction_icon) + row.operator(ExpandSection_Materials.bl_idname, text=(t("TextureAtlas.reload_list") if not context.scene.texture_atlas_Has_Mat_List_Shown else t("TextureAtlas.loaded_list")), icon=direction_icon) if context.scene.texture_atlas_Has_Mat_List_Shown: - - #get_texture_node_list(bpy.context) - row = boxoutter.row() row.template_list(MaterialTextureAtlasProperties.bl_idname, 'material_list', context.scene, 'materials', context.scene, 'texture_atlas_material_index', rows=12, type='DEFAULT') row = layout.row() - row.operator(Atlas_Materials.bl_idname, text="Atlas Materials!") \ No newline at end of file + row.operator(Atlas_Materials.bl_idname, text=t("TextureAtlas.atlas_materials")) diff --git a/ui/optimization.py b/ui/optimization.py index 1726e22..3701ea5 100644 --- a/ui/optimization.py +++ b/ui/optimization.py @@ -12,6 +12,7 @@ class AvatarToolkitOptimizationPanel(bpy.types.Panel): bl_region_type = 'UI' bl_category = "Avatar Toolkit" bl_parent_id = "OBJECT_PT_avatar_toolkit" + bl_order = 2 def draw(self, context): layout = self.layout @@ -30,6 +31,7 @@ class AvatarToolkitOptimizationPanel(bpy.types.Panel): row.scale_y = 1.2 row.operator("avatar_toolkit.join_all_meshes", text=t("Optimization.join_all_meshes.label")) row.operator("avatar_toolkit.join_selected_meshes", text=t("Optimization.join_selected_meshes.label")) - row.operator("avatar_toolkit.remove_doubles_safely", text="Remove Doubles Safely") + row.operator("avatar_toolkit.remove_doubles_safely", text=t("Optimization.remove_doubles_safely.label")) else: - layout.label(text="Please select an armature in Quick Access") + layout.label(text=t("Optimization.select_armature")) + diff --git a/ui/panel.py b/ui/panel.py index 29829de..b8afd9e 100644 --- a/ui/panel.py +++ b/ui/panel.py @@ -4,7 +4,7 @@ from ..functions.translations import t @register_wrap class AvatarToolkitPanel(bpy.types.Panel): - bl_label = "Avatar Toolkit" + bl_label = t("AvatarToolkit.label") bl_idname = "OBJECT_PT_avatar_toolkit" bl_space_type = 'VIEW_3D' bl_region_type = 'UI' @@ -12,9 +12,8 @@ class AvatarToolkitPanel(bpy.types.Panel): def draw(self, context): layout = self.layout - layout.label(text="Welcome to Avatar Toolkit, a tool for") - layout.label(text="creating and editing avatars in blender,") - layout.label(text="This is an early alpha version, so expect") - layout.label(text="bugs and issues.") + layout.label(text=t("AvatarToolkit.welcome")) + layout.label(text=t("AvatarToolkit.description")) + layout.label(text=t("AvatarToolkit.alpha_warning")) #print("Avatar Toolkit Panel is being drawn") diff --git a/ui/quick_access.py b/ui/quick_access.py index 97e54d2..cf767a0 100644 --- a/ui/quick_access.py +++ b/ui/quick_access.py @@ -17,6 +17,7 @@ class AvatarToolkitQuickAccessPanel(bpy.types.Panel): bl_region_type = 'UI' bl_category = "Avatar Toolkit" bl_parent_id = "OBJECT_PT_avatar_toolkit" + bl_order = 1 def draw(self, context: Context): layout = self.layout @@ -38,7 +39,7 @@ class AvatarToolkitQuickAccessPanel(bpy.types.Panel): class AVATAR_TOOLKIT_OT_export_menu(bpy.types.Operator): bl_idname = "avatar_toolkit.export_menu" bl_label = t("Quick_Access.export_menu.label") - bl_description = t("Quick_Access.import_pmx.desc") + bl_description = t("Quick_Access.export_menu.desc") @classmethod def poll(cls, context): @@ -55,15 +56,16 @@ class AVATAR_TOOLKIT_OT_export_menu(bpy.types.Operator): layout = self.layout layout.label(text=t("Quick_Access.select_export.label")) layout.operator("avatar_toolkit.export_resonite", text=t("Quick_Access.select_export_resonite.label")) - layout.operator("avatar_toolkit.export_fbx", text="Export FBX") + layout.operator("avatar_toolkit.export_fbx", text=t("Quick_Access.export_fbx.label")) @register_wrap class AVATAR_TOOLKIT_OT_export_fbx(bpy.types.Operator): bl_idname = 'avatar_toolkit.export_fbx' - bl_label = "Export FBX" - bl_description = "Export the model as FBX" + bl_label = t("Quick_Access.export_fbx.label") + bl_description = t("Quick_Access.export_fbx.desc") bl_options = {'REGISTER', 'UNDO', 'INTERNAL'} def execute(self, context): bpy.ops.export_scene.fbx('INVOKE_DEFAULT') return {'FINISHED'} + diff --git a/ui/settings.py b/ui/settings.py index 9714da6..6425922 100644 --- a/ui/settings.py +++ b/ui/settings.py @@ -11,6 +11,7 @@ class AvatarToolkitSettingsPanel(bpy.types.Panel): bl_region_type = 'UI' bl_category = "Avatar Toolkit" bl_parent_id = "OBJECT_PT_avatar_toolkit" + bl_order = 6 def draw(self, context): layout = self.layout diff --git a/ui/tools.py b/ui/tools.py index ac4b71d..d139d7d 100644 --- a/ui/tools.py +++ b/ui/tools.py @@ -8,12 +8,13 @@ from ..core.common import get_selected_armature @register_wrap class AvatarToolkitToolsPanel(bpy.types.Panel): - bl_label = "Tools" + bl_label = t("Tools.label") bl_idname = "OBJECT_PT_avatar_toolkit_tools" bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_category = "Avatar Toolkit" bl_parent_id = "OBJECT_PT_avatar_toolkit" + bl_order = 3 def draw(self, context: Context): layout = self.layout @@ -27,8 +28,6 @@ class AvatarToolkitToolsPanel(bpy.types.Panel): row.scale_y = 1.5 row.operator("avatar_toolkit.convert_to_resonite", text=t("Tools.convert_to_resonite.label")) row = layout.row(align=True) - row.operator("avatar_toolkit.remove_doubles_safely", text="Remove Doubles Safely") - row = layout.row(align=True) - row.operator(CreateDigitigradeLegs.bl_idname, text="Create Digitigrade Legs") + row.operator(CreateDigitigradeLegs.bl_idname, text=t("Tools.create_digitigrade_legs.label")) else: - layout.label(text="Please select an armature in Quick Access") + layout.label(text=t("Tools.select_armature")) diff --git a/ui/viseme.py b/ui/viseme.py index d0ea8e3..239154b 100644 --- a/ui/viseme.py +++ b/ui/viseme.py @@ -11,13 +11,14 @@ class AvatarToolkitVisemePanel(bpy.types.Panel): bl_region_type = 'UI' bl_category = "Avatar Toolkit" bl_parent_id = "OBJECT_PT_avatar_toolkit" + bl_order = 5 def draw(self, context: bpy.types.Context) -> None: layout = self.layout armature = get_selected_armature(context) if armature: - layout.prop(context.scene, "selected_mesh", text="Select Mesh") + layout.prop(context.scene, "selected_mesh", text=t("VisemePanel.select_mesh")) mesh = bpy.data.objects.get(context.scene.selected_mesh) if mesh and mesh.type == 'MESH': @@ -26,9 +27,9 @@ class AvatarToolkitVisemePanel(bpy.types.Panel): layout.prop_search(context.scene, "mouth_o", mesh.data.shape_keys, "key_blocks", text=t('VisemePanel.mouth_o.label')) layout.prop_search(context.scene, "mouth_ch", mesh.data.shape_keys, "key_blocks", text=t('VisemePanel.mouth_ch.label')) - layout.prop(context.scene, 'shape_intensity') + layout.prop(context.scene, 'shape_intensity', text=t('VisemePanel.shape_intensity')) - layout.operator("avatar_toolkit.create_visemes", icon='TRIA_RIGHT') + layout.operator("avatar_toolkit.create_visemes", text=t('VisemePanel.create_visemes'), icon='TRIA_RIGHT') else: layout.label(text=t('VisemePanel.error.noShapekeys'), icon='ERROR') else: @@ -38,5 +39,3 @@ class AvatarToolkitVisemePanel(bpy.types.Panel): layout.separator() layout.label(text=t('VisemePanel.info.selectMesh')) - -