From c8ee4cf0c9fa5470b4c312126342074b093ea4f8 Mon Sep 17 00:00:00 2001 From: Myssal <143514975+myssal@users.noreply.github.com> Date: Mon, 28 Apr 2025 01:03:18 +0700 Subject: [PATCH] feat: spine exporter localize --- SpineViewer/Controls/SpinePreviewPanel.cs | 2 +- SpineViewer/Dialogs/ProgressDialog.cs | 2 +- SpineViewer/Program.cs | 2 +- SpineViewer/Properties/Resources.Designer.cs | 801 ++++++++++++++++++ SpineViewer/Properties/Resources.en-US.resx | 268 ++++++ SpineViewer/Properties/Resources.resx | 267 ++++++ .../Spine/SpineExporter/AvifExporter.cs | 31 +- SpineViewer/Spine/SpineExporter/Exporter.cs | 89 +- .../SpineExporter/FFmpegVideoExporter.cs | 37 +- .../Spine/SpineExporter/FrameExporter.cs | 25 +- .../SpineExporter/FrameSequenceExporter.cs | 5 +- .../Spine/SpineExporter/GifExporter.cs | 31 +- .../Spine/SpineExporter/MkvExporter.cs | 23 +- .../Spine/SpineExporter/MovExporter.cs | 17 +- .../Spine/SpineExporter/Mp4Exporter.cs | 25 +- .../Spine/SpineExporter/VideoExporter.cs | 53 +- .../Spine/SpineExporter/WebmExporter.cs | 23 +- .../Spine/SpineExporter/WebpExporter.cs | 49 +- 18 files changed, 1592 insertions(+), 158 deletions(-) diff --git a/SpineViewer/Controls/SpinePreviewPanel.cs b/SpineViewer/Controls/SpinePreviewPanel.cs index 1ae26eb..79a36e3 100644 --- a/SpineViewer/Controls/SpinePreviewPanel.cs +++ b/SpineViewer/Controls/SpinePreviewPanel.cs @@ -494,7 +494,7 @@ namespace SpineViewer.Controls { logger.Fatal(ex.ToString()); logger.Fatal("Render task stopped"); - MessagePopup.Error(ex.ToString(), "预览画面已停止渲染", Properties.Resources.msgBoxError); + MessagePopup.Error(ex.ToString(), Properties.Resources.previewRenderStopped); } finally { diff --git a/SpineViewer/Dialogs/ProgressDialog.cs b/SpineViewer/Dialogs/ProgressDialog.cs index 9a088d7..cff9aca 100644 --- a/SpineViewer/Dialogs/ProgressDialog.cs +++ b/SpineViewer/Dialogs/ProgressDialog.cs @@ -52,7 +52,7 @@ namespace SpineViewer.Dialogs if (e.Error != null) { logger.Error(e.Error.ToString()); - MessagePopup.Error(e.Error.ToString(), "执行出错", Properties.Resources.msgBoxError); + MessagePopup.Error(e.Error.ToString(), Properties.Resources.runtimeError); DialogResult = DialogResult.Abort; } else if (e.Cancelled) diff --git a/SpineViewer/Program.cs b/SpineViewer/Program.cs index 3f11361..a82366f 100644 --- a/SpineViewer/Program.cs +++ b/SpineViewer/Program.cs @@ -59,7 +59,7 @@ namespace SpineViewer catch (Exception ex) { logger.Fatal(ex.ToString()); - MessagePopup.Error(ex.ToString(), "程序已崩溃", Properties.Resources.msgBoxError); + MessagePopup.Error(ex.ToString(), Properties.Resources.programCrashed); } } diff --git a/SpineViewer/Properties/Resources.Designer.cs b/SpineViewer/Properties/Resources.Designer.cs index 130780e..a799f89 100644 --- a/SpineViewer/Properties/Resources.Designer.cs +++ b/SpineViewer/Properties/Resources.Designer.cs @@ -69,6 +69,15 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 动画. + /// + internal static string animation { + get { + return ResourceManager.GetString("animation", resourceCulture); + } + } + /// /// Looks up a localized string similar to atlas文件不存在. /// @@ -78,6 +87,24 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to atlas文件路径. + /// + internal static string atlasPath { + get { + return ResourceManager.GetString("atlasPath", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 基本信息. + /// + internal static string basicInfo { + get { + return ResourceManager.GetString("basicInfo", resourceCulture); + } + } + /// /// Looks up a localized string similar to 自定义. /// @@ -96,6 +123,33 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to [2] FFmpeg 基本参数. + /// + internal static string categoryFFmpegParameter { + get { + return ResourceManager.GetString("categoryFFmpegParameter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [3] 格式参数. + /// + internal static string categoryFormatParameters { + get { + return ResourceManager.GetString("categoryFormatParameters", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [2] 帧序列参数. + /// + internal static string categoryFrameSequenceParameters { + get { + return ResourceManager.GetString("categoryFrameSequenceParameters", resourceCulture); + } + } + /// /// Looks up a localized string similar to [1] 预览. /// @@ -105,6 +159,24 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to [1] 单帧画面. + /// + internal static string categorySingleFrame { + get { + return ResourceManager.GetString("categorySingleFrame", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [1] 视频参数. + /// + internal static string categoryVideoParameters { + get { + return ResourceManager.GetString("categoryVideoParameters", resourceCulture); + } + } + /// /// Looks up a localized string similar to 项,共 . /// @@ -132,6 +204,33 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 调试. + /// + internal static string debug { + get { + return ResourceManager.GetString("debug", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 使用预览画面分辨率的情况下, 允许内容溢出到边缘和填充区域. + /// + internal static string descAllowContentOverflow { + get { + return ResourceManager.GetString("descAllowContentOverflow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 小于该值的像素点会被认为是透明像素. + /// + internal static string descAlphaThreshold { + get { + return ResourceManager.GetString("descAlphaThreshold", resourceCulture); + } + } + /// /// Looks up a localized string similar to 相关联的 SpineListView. /// @@ -141,6 +240,51 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 根据导出内容自动设置分辨率, 四周填充距离和内容溢出参数将会被忽略. + /// + internal static string descAutoResolution { + get { + return ResourceManager.GetString("descAutoResolution", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -c:v, 要使用的编码器\n建议使用硬件加速, libaom-av1 速度非常非常非常慢. + /// + internal static string descAvifEncoder { + get { + return ResourceManager.GetString("descAvifEncoder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 要使用的背景色, 格式为 #RRGGBBAA. + /// + internal static string descBackgroundColor { + get { + return ResourceManager.GetString("descBackgroundColor", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -crf, 取值范围 0-63, 建议范围 18-28, 默认取值 23, 数值越小则输出质量越高. + /// + internal static string descCRF { + get { + return ResourceManager.GetString("descCRF", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 使用 \"ffmpeg -h encoder=<编码器>\" 查看编码器支持的参数\n使用 \"ffmpeg -h muxer=<文件格式>\" 查看文件格式支持的参数. + /// + internal static string descCustomArgument { + get { + return ResourceManager.GetString("descCustomArgument", resourceCulture); + } + } + /// /// Looks up a localized string similar to 用于显示画面属性的属性页. /// @@ -150,6 +294,123 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 导出图像的每英寸像素数,用于调整图像的物理尺寸. + /// + internal static string descDPI { + get { + return ResourceManager.GetString("descDPI", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 可以从模型列表查看动画时长, 如果小于 0, 则在逐个导出时每个模型使用各自的所有轨道动画时长最大值. + /// + internal static string descDuration { + get { + return ResourceManager.GetString("descDuration", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 是否将模型在同一个画面上导出单个文件,否则逐个导出模型. + /// + internal static string descExportSingle { + get { + return ResourceManager.GetString("descExportSingle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -f, 文件格式. + /// + internal static string descFileFormat { + get { + return ResourceManager.GetString("descFileFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 与图像格式匹配的文件名后缀. + /// + internal static string descFileNameExtension { + get { + return ResourceManager.GetString("descFileNameExtension", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 文件名后缀. + /// + internal static string descFilenameSuffix { + get { + return ResourceManager.GetString("descFilenameSuffix", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 每秒画面数. + /// + internal static string descFPS { + get { + return ResourceManager.GetString("descFPS", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 帧文件的后缀,同时决定帧图像格式. + /// + internal static string descFrameFileExtension { + get { + return ResourceManager.GetString("descFrameFileExtension", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 当设置保留最后一帧时, 动图会更为连贯, 但是帧数可能比预期帧数多 1. + /// + internal static string descKeepLastFrame { + get { + return ResourceManager.GetString("descKeepLastFrame", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -loop, 循环次数, 0 无限循环, 取值范围 [0, 65535]. + /// + internal static string descLoopCount { + get { + return ResourceManager.GetString("descLoopCount", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -lossless, 0 表示有损, 1 表示无损. + /// + internal static string descLoseless { + get { + return ResourceManager.GetString("descLoseless", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 画布外部的边缘距离 (Margin), 最终导出的分辨率需要加上这个边距. + /// + internal static string descMargin { + get { + return ResourceManager.GetString("descMargin", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 设置调色板使用的最大颜色数量, 越多则色彩保留程度越高. + /// + internal static string descMaxColor { + get { + return ResourceManager.GetString("descMaxColor", resourceCulture); + } + } + /// /// Looks up a localized string similar to 用于显示模型属性的组合属性页. /// @@ -159,6 +420,105 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 逐个导出时可以留空,将逐个导出到模型自身所在目录. + /// + internal static string descOutputFolder { + get { + return ResourceManager.GetString("descOutputFolder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 画布内部的填充距离 (Padding), 导出的分辨率大小不会发生变化, 但是会留有四周空间. + /// + internal static string descPadding { + get { + return ResourceManager.GetString("descPadding", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -pix_fmt, 要使用的像素格式. + /// + internal static string descPixelFormat { + get { + return ResourceManager.GetString("descPixelFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -profile, 预设配置. + /// + internal static string descPreset { + get { + return ResourceManager.GetString("descPreset", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 预览画面的视区参数,请在预览画面参数面板进行调整. + /// + internal static string descPreviewViewport { + get { + return ResourceManager.GetString("descPreviewViewport", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to -quality, 取值范围 0-100, 默认值 75. + /// + internal static string descQuality { + get { + return ResourceManager.GetString("descQuality", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 是否仅导出选中的模型,请在预览画面参数面板进行调整. + /// + internal static string descRenderSelected { + get { + return ResourceManager.GetString("descRenderSelected", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 是否将模型在同一个画面上导出单个文件,否则逐个导出模型. + /// + internal static string descResolution { + get { + return ResourceManager.GetString("descResolution", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 允许内容溢出. + /// + internal static string displayAllowContentOverflow { + get { + return ResourceManager.GetString("displayAllowContentOverflow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 透明度阈值. + /// + internal static string displayAlphaThreshold { + get { + return ResourceManager.GetString("displayAlphaThreshold", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 自动分辨率. + /// + internal static string displayAutoResolution { + get { + return ResourceManager.GetString("displayAutoResolution", resourceCulture); + } + } + /// /// Looks up a localized string similar to 背景颜色. /// @@ -177,6 +537,51 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 自定义参数. + /// + internal static string displayCustomArgument { + get { + return ResourceManager.GetString("displayCustomArgument", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 编码器. + /// + internal static string displayEncoder { + get { + return ResourceManager.GetString("displayEncoder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 导出单个. + /// + internal static string displayExportSingle { + get { + return ResourceManager.GetString("displayExportSingle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 文件格式. + /// + internal static string displayFileFormat { + get { + return ResourceManager.GetString("displayFileFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 文件名后缀. + /// + internal static string displayFilenameSuffix { + get { + return ResourceManager.GetString("displayFilenameSuffix", resourceCulture); + } + } + /// /// Looks up a localized string similar to 水平翻转. /// @@ -195,6 +600,69 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 帧率. + /// + internal static string displayFPS { + get { + return ResourceManager.GetString("displayFPS", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 图像格式. + /// + internal static string displayImageFormat { + get { + return ResourceManager.GetString("displayImageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 保留最后一帧. + /// + internal static string displayKeepLastFrame { + get { + return ResourceManager.GetString("displayKeepLastFrame", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 循环次数. + /// + internal static string displayLoopCount { + get { + return ResourceManager.GetString("displayLoopCount", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 无损. + /// + internal static string displayLoseless { + get { + return ResourceManager.GetString("displayLoseless", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 四周边缘距离. + /// + internal static string displayMargin { + get { + return ResourceManager.GetString("displayMargin", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 调色板最大颜色数量. + /// + internal static string displayMaxColor { + get { + return ResourceManager.GetString("displayMaxColor", resourceCulture); + } + } + /// /// Looks up a localized string similar to 最大帧率. /// @@ -204,6 +672,60 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 输出文件夹. + /// + internal static string displayOutputFolder { + get { + return ResourceManager.GetString("displayOutputFolder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 四周填充距离. + /// + internal static string displayPadding { + get { + return ResourceManager.GetString("displayPadding", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 像素格式. + /// + internal static string displayPixelFormat { + get { + return ResourceManager.GetString("displayPixelFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 预设. + /// + internal static string displayPreset { + get { + return ResourceManager.GetString("displayPreset", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 预览画面视区. + /// + internal static string displayPreviewViewport { + get { + return ResourceManager.GetString("displayPreviewViewport", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 质量. + /// + internal static string displayQuality { + get { + return ResourceManager.GetString("displayQuality", resourceCulture); + } + } + /// /// Looks up a localized string similar to 仅渲染选中. /// @@ -249,6 +771,15 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 时长. + /// + internal static string duration { + get { + return ResourceManager.GetString("duration", resourceCulture); + } + } + /// /// Looks up a localized string similar to 骨骼加载失败. /// @@ -258,6 +789,105 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 文件版本. + /// + internal static string fileVersion { + get { + return ResourceManager.GetString("fileVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 水平翻转. + /// + internal static string flipX { + get { + return ResourceManager.GetString("flipX", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 垂直翻转. + /// + internal static string flipY { + get { + return ResourceManager.GetString("flipY", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 文件夹 . + /// + internal static string folderNotExistPrefix { + get { + return ResourceManager.GetString("folderNotExistPrefix", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 不存在. + /// + internal static string folderNotExistSuffix { + get { + return ResourceManager.GetString("folderNotExistSuffix", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 无法解析颜色,请使用 #RRGGBBAA、#RRGGBB、#RGBA 或 #RGB 格式. + /// + internal static string formatExceptionParseColor { + get { + return ResourceManager.GetString("formatExceptionParseColor", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 无法解析颜色,请检查格式. + /// + internal static string formatExceptionParseColorError { + get { + return ResourceManager.GetString("formatExceptionParseColorError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 无法解析颜色,请使用已知的颜色名称. + /// + internal static string formatExceptionUnknownColor { + get { + return ResourceManager.GetString("formatExceptionUnknownColor", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 帧. + /// + internal static string frame { + get { + return ResourceManager.GetString("frame", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 输出文件夹无效. + /// + internal static string invalidInputFolder { + get { + return ResourceManager.GetString("invalidInputFolder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 是否隐藏. + /// + internal static string isHidden { + get { + return ResourceManager.GetString("isHidden", resourceCulture); + } + } + /// /// Looks up a localized string similar to 已选择 . /// @@ -294,6 +924,15 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 全轨道最大时长. + /// + internal static string maximumTrackLength { + get { + return ResourceManager.GetString("maximumTrackLength", resourceCulture); + } + } + /// /// Looks up a localized string similar to 错误信息. /// @@ -330,6 +969,33 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 导出单个时必须提供输出文件夹. + /// + internal static string mustProvideOutputFolder { + get { + return ResourceManager.GetString("mustProvideOutputFolder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 名称. + /// + internal static string name { + get { + return ResourceManager.GetString("name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 导出单个时导出时长不能为负数. + /// + internal static string negativeDuration { + get { + return ResourceManager.GetString("negativeDuration", resourceCulture); + } + } + /// /// Looks up a localized string similar to 链接已复制到剪贴板,请前往浏览器进行访问. /// @@ -348,6 +1014,24 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 位置. + /// + internal static string position { + get { + return ResourceManager.GetString("position", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 预览画面已停止渲染. + /// + internal static string previewRenderStopped { + get { + return ResourceManager.GetString("previewRenderStopped", resourceCulture); + } + } + /// /// Looks up a localized string similar to 已处理 . /// @@ -357,6 +1041,15 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 程序已崩溃. + /// + internal static string programCrashed { + get { + return ResourceManager.GetString("programCrashed", resourceCulture); + } + } + /// /// Looks up a localized string similar to 确认移除所有 . /// @@ -384,6 +1077,24 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 渲染. + /// + internal static string render { + get { + return ResourceManager.GetString("render", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 资源目录. + /// + internal static string resourcesPath { + get { + return ResourceManager.GetString("resourcesPath", resourceCulture); + } + } + /// /// Looks up a localized string similar to 语言已设为英语。立即重启应用程序吗?. /// @@ -402,6 +1113,33 @@ namespace SpineViewer.Properties { } } + /// + /// Looks up a localized string similar to 执行出错. + /// + internal static string runtimeError { + get { + return ResourceManager.GetString("runtimeError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 运行时版本. + /// + internal static string runtimeVersion { + get { + return ResourceManager.GetString("runtimeVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 缩放比例. + /// + internal static string scale { + get { + return ResourceManager.GetString("scale", resourceCulture); + } + } + /// /// Looks up a localized string similar to skel文件不存在. /// @@ -410,5 +1148,68 @@ namespace SpineViewer.Properties { return ResourceManager.GetString("skelNotExist", resourceCulture); } } + + /// + /// Looks up a localized string similar to skel文件路径. + /// + internal static string skelPath { + get { + return ResourceManager.GetString("skelPath", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 皮肤. + /// + internal static string skin { + get { + return ResourceManager.GetString("skin", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 插槽. + /// + internal static string slot { + get { + return ResourceManager.GetString("slot", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 变换. + /// + internal static string transform { + get { + return ResourceManager.GetString("transform", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 预乘Alpha通道. + /// + internal static string usePremultipliedAlpha { + get { + return ResourceManager.GetString("usePremultipliedAlpha", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 需要提供有效的文件名后缀. + /// + internal static string validExtensionRequired { + get { + return ResourceManager.GetString("validExtensionRequired", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 需要提供有效的格式. + /// + internal static string validFormatRequired { + get { + return ResourceManager.GetString("validFormatRequired", resourceCulture); + } + } } } diff --git a/SpineViewer/Properties/Resources.en-US.resx b/SpineViewer/Properties/Resources.en-US.resx index ec2224d..f01fb36 100644 --- a/SpineViewer/Properties/Resources.en-US.resx +++ b/SpineViewer/Properties/Resources.en-US.resx @@ -120,15 +120,27 @@ About + + Animation + Atlas file doesn't exist. + + Atlas file path + + + Basic info + Custom [0] Export + + [3] Format parameters + [1] Preview @@ -141,12 +153,18 @@ in total. + + Debug + Associated SpineListView Property page for displaying image properties + + -c:v: Video encoder to use. Hardware acceleration is recommended. Note: libaom-av1 is extremely slow. + Model attributes display page. @@ -156,6 +174,9 @@ Center point of screen + + Encoder + Flip horizontal @@ -180,9 +201,33 @@ Zoom + + Duration + Failed to load skeleton + + File version + + + FlipX + + + FlipY + + + Unable to parse color, please use #RRGGBBAA, #RRGGBB, #RGBA or #RGB format. + + + Color format is invalid. Please check the format. + + + Color not recognized. Please use a valid color name. + + + Is hidden + . @@ -195,6 +240,9 @@ skeletons found. Do you want to load them all at once? + + Maximum Track Length + Error @@ -207,15 +255,27 @@ Warning + + Name + Link copied to clipboard. Please open it in browser Invalid Parameters + + Position + + + Preview Render Stopped + Processed + + Application has crashed + Remove all @@ -225,13 +285,221 @@ item(s)? + + Render + + + Resource Path + Language set to Simplified Chinese. Restart application now? Application restart required! + + Runtime error + + + Runtime version + + + Scale + Skel file doesn't exist. + + Skel file path + + + Skin + + + Slot + + + Transform + + + UsePremultipliedAlpha + + + -crf: Accepts values from 0 to 63. Recommended range is 18–28 (default is 23). Lower values result in higher output quality + + + Pixel format + + + -pix_fmt: Pixel format to use. + + + Loop count + + + -loop: Number of loops. 0 for infinite loops. Valid range: [0, 65535]. + + + Invalid output folder + + + Folder + + + doesn't exist. + + + An output folder must be provided when exporting a single file. + + + [2] FFmpeg Basic Parameters + + + File format + + + -f: Specify the output file format + + + File extension + + + File extension + + + Output folder + + + Leave empty to export to each model's folder. + + + Export single + + + Export all models in a single file, or export each model separately. + + + Set pixel size in preview panel. + + + Preview viewport + + + Preview viewport settings. Adjust in the preview panel. + + + Export selected models only. Adjust this in the preview settings panel. + + + Background color to use, in #RRGGBBAA format. + + + Margin + + + Outer canvas margin. This will be added to the final export resolution. + + + Padding + + + Internal canvas padding. The export resolution remains unchanged, but space will be left around the edges. + + + Allow content overflow + + + When using the preview resolution, allow content to overflow into the edges and padding areas. + + + Auto resolution + + + Automatically set resolution based on export content. Edge padding and content overflow settings will be ignored. + + + Valid format required. + + + Valie extension required. + + + Use "ffmpeg -h encoder=<encoder>" to view supported encoder parameters. +Use "ffmpeg -h muxer=<file format>" to view supported file format parameters. + + + Custom arguments + + + [1] Single Frame + + + Image format + + + Filename extension matching the image format. + + + Pixels per inch (PPI) for the exported image, used to adjust the physical size of the image. + + + [2] Frame Sequence Parameters + + + Frame file extension, which also defines the image format of each frame. + + + Max colors in palette + + + Max colors in palette. Higher value = better color retention. + + + Alpha threshold + + + Pixels below this value will be considered transparent. + + + Preset + + + -profile: Preset configuration + + + Export duration cannot be negative when exporting a single file. + + + frame(s) + + + [1] Video Parameters + + + Check animation duration in the model list. If less than 0, each model uses its longest track when exporting individually. + + + FPS + + + Frames Per Second (FPS) + + + Keep last frame + + + Keeping the last frame smooths the animation, but may add one extra frame. + + + Loseless + + + -lossless: 0 for lossy, 1 for lossless. + + + Quality + + + -quality: Range 0-100, default is 75. + \ No newline at end of file diff --git a/SpineViewer/Properties/Resources.resx b/SpineViewer/Properties/Resources.resx index c7fbbd2..a701e31 100644 --- a/SpineViewer/Properties/Resources.resx +++ b/SpineViewer/Properties/Resources.resx @@ -120,15 +120,27 @@ 关于 + + 动画 + atlas文件不存在 + + atlas文件路径 + + + 基本信息 + 自定义 [0] 导出 + + [3] 格式参数 + [1] 预览 @@ -141,12 +153,18 @@ + + 调试 + 相关联的 SpineListView 用于显示画面属性的属性页 + + -c:v, 要使用的编码器\n建议使用硬件加速, libaom-av1 速度非常非常非常慢 + 用于显示模型属性的组合属性页 @@ -156,6 +174,9 @@ 画面中心点 + + 编码器 + 水平翻转 @@ -180,9 +201,33 @@ 缩放 + + 时长 + 骨骼加载失败 + + 文件版本 + + + 水平翻转 + + + 垂直翻转 + + + 无法解析颜色,请使用 #RRGGBBAA、#RRGGBB、#RGBA 或 #RGB 格式 + + + 无法解析颜色,请检查格式 + + + 无法解析颜色,请使用已知的颜色名称 + + + 是否隐藏 + 已选择 @@ -195,6 +240,9 @@ 个可加载骨骼,数量较多,是否一次性全部加载? + + 全轨道最大时长 + 错误信息 @@ -207,15 +255,27 @@ 警告信息 + + 名称 + 链接已复制到剪贴板,请前往浏览器进行访问 参数错误 + + 位置 + + + 预览画面已停止渲染 + 已处理 + + 程序已崩溃 + 确认移除所有 @@ -225,13 +285,220 @@ 项吗? + + 渲染 + + + 资源目录 + 语言已设为英语。立即重启应用程序吗? 需要重新启动应用程序! + + 执行出错 + + + 运行时版本 + + + 缩放比例 + skel文件不存在 + + skel文件路径 + + + 皮肤 + + + 插槽 + + + 变换 + + + 预乘Alpha通道 + + + -crf, 取值范围 0-63, 建议范围 18-28, 默认取值 23, 数值越小则输出质量越高 + + + 像素格式 + + + -pix_fmt, 要使用的像素格式 + + + 循环次数 + + + -loop, 循环次数, 0 无限循环, 取值范围 [0, 65535] + + + 输出文件夹无效 + + + 文件夹 + + + 不存在 + + + 导出单个时必须提供输出文件夹 + + + [2] FFmpeg 基本参数 + + + 文件格式 + + + -f, 文件格式 + + + 文件名后缀 + + + 文件名后缀 + + + 输出文件夹 + + + 逐个导出时可以留空,将逐个导出到模型自身所在目录 + + + 导出单个 + + + 是否将模型在同一个画面上导出单个文件,否则逐个导出模型 + + + 是否将模型在同一个画面上导出单个文件,否则逐个导出模型 + + + 预览画面视区 + + + 预览画面的视区参数,请在预览画面参数面板进行调整 + + + 是否仅导出选中的模型,请在预览画面参数面板进行调整 + + + 要使用的背景色, 格式为 #RRGGBBAA + + + 四周边缘距离 + + + 画布外部的边缘距离 (Margin), 最终导出的分辨率需要加上这个边距 + + + 四周填充距离 + + + 画布内部的填充距离 (Padding), 导出的分辨率大小不会发生变化, 但是会留有四周空间 + + + 允许内容溢出 + + + 使用预览画面分辨率的情况下, 允许内容溢出到边缘和填充区域 + + + 自动分辨率 + + + 根据导出内容自动设置分辨率, 四周填充距离和内容溢出参数将会被忽略 + + + 需要提供有效的格式 + + + 需要提供有效的文件名后缀 + + + 使用 \"ffmpeg -h encoder=<编码器>\" 查看编码器支持的参数\n使用 \"ffmpeg -h muxer=<文件格式>\" 查看文件格式支持的参数 + + + 自定义参数 + + + [1] 单帧画面 + + + 图像格式 + + + 与图像格式匹配的文件名后缀 + + + 导出图像的每英寸像素数,用于调整图像的物理尺寸 + + + [2] 帧序列参数 + + + 帧文件的后缀,同时决定帧图像格式 + + + 调色板最大颜色数量 + + + 设置调色板使用的最大颜色数量, 越多则色彩保留程度越高 + + + 透明度阈值 + + + 小于该值的像素点会被认为是透明像素 + + + 预设 + + + -profile, 预设配置 + + + 导出单个时导出时长不能为负数 + + + + + + [1] 视频参数 + + + 可以从模型列表查看动画时长, 如果小于 0, 则在逐个导出时每个模型使用各自的所有轨道动画时长最大值 + + + 帧率 + + + 每秒画面数 + + + 保留最后一帧 + + + 当设置保留最后一帧时, 动图会更为连贯, 但是帧数可能比预期帧数多 1 + + + 无损 + + + -lossless, 0 表示有损, 1 表示无损 + + + 质量 + + + -quality, 取值范围 0-100, 默认值 75 + \ No newline at end of file diff --git a/SpineViewer/Spine/SpineExporter/AvifExporter.cs b/SpineViewer/Spine/SpineExporter/AvifExporter.cs index a06ed17..2f65141 100644 --- a/SpineViewer/Spine/SpineExporter/AvifExporter.cs +++ b/SpineViewer/Spine/SpineExporter/AvifExporter.cs @@ -1,5 +1,6 @@ using FFMpegCore; using SpineViewer.Utils; +using SpineViewer.Utils.Localize; using System; using System.Collections.Generic; using System.ComponentModel; @@ -64,13 +65,17 @@ namespace SpineViewer.Spine.SpineExporter /// [StringEnumConverter.StandardValues("av1_nvenc", "av1_amf", "libaom-av1", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("编码器"), Description("-c:v, 要使用的编码器\n建议使用硬件加速, libaom-av1 速度非常非常非常慢")] - public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayEncoder")] + [LocalizedDescription(typeof(Properties.Resources), "descAvifEncoder")] + public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } - /// - /// CRF - /// - [Category("[3] 格式参数"), DisplayName("CRF"), Description("-crf, 取值范围 0-63, 建议范围 18-28, 默认取值 23, 数值越小则输出质量越高")] + /// + /// CRF + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [DisplayName("CRF")] + [LocalizedDescription(typeof(Properties.Resources), "descCRF")] public int CRF { get => Exporter.CRF; set => Exporter.CRF = value; } /// @@ -78,13 +83,17 @@ namespace SpineViewer.Spine.SpineExporter /// [StringEnumConverter.StandardValues("yuv420p", "yuv422p", "yuv444p", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("像素格式"), Description("-pix_fmt, 要使用的像素格式")] + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayPixelFormat")] + [LocalizedDescription(typeof(Properties.Resources), "descPixelFormat")] public string PixelFormat { get => Exporter.PixelFormat; set => Exporter.PixelFormat = value; } - /// - /// 循环次数 - /// - [Category("[3] 格式参数"), DisplayName("循环次数"), Description("-loop, 循环次数, 0 无限循环, 取值范围 [0, 65535]")] + /// + /// 循环次数 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayLoopCount")] + [LocalizedDescription(typeof(Properties.Resources), "descLoopCount")] public int Loop { get => Exporter.Loop; set => Exporter.Loop = value; } } } diff --git a/SpineViewer/Spine/SpineExporter/Exporter.cs b/SpineViewer/Spine/SpineExporter/Exporter.cs index 438a3c4..d1d52ca 100644 --- a/SpineViewer/Spine/SpineExporter/Exporter.cs +++ b/SpineViewer/Spine/SpineExporter/Exporter.cs @@ -1,6 +1,7 @@ using NLog; using SpineViewer.Extensions; using SpineViewer.Utils; +using SpineViewer.Utils.Localize; using System; using System.Collections.Generic; using System.ComponentModel; @@ -345,66 +346,86 @@ namespace SpineViewer.Spine.SpineExporter /// 输出文件夹 /// [Editor(typeof(FolderNameEditor), typeof(UITypeEditor))] - [Category("[0] 导出"), DisplayName("输出文件夹"), Description("逐个导出时可以留空,将逐个导出到模型自身所在目录")] + [LocalizedCategory(typeof(Properties.Resources), "categoryExport")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayOutputFolder")] + [LocalizedDescription(typeof(Properties.Resources), "descOutputFolder")] public string? OutputDir { get => Exporter.OutputDir; set => Exporter.OutputDir = value; } - /// - /// 导出单个 - /// - [Category("[0] 导出"), DisplayName("导出单个"), Description("是否将模型在同一个画面上导出单个文件,否则逐个导出模型")] - public bool IsExportSingle { get => Exporter.IsExportSingle; set => Exporter.IsExportSingle = value; } + /// + /// 导出单个 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryExport")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayExportSingle")] + [LocalizedDescription(typeof(Properties.Resources), "descExportSingle")] + public bool IsExportSingle { get => Exporter.IsExportSingle; set => Exporter.IsExportSingle = value; } /// /// 画面分辨率 /// [TypeConverter(typeof(SizeConverter))] - [Category("[0] 导出"), DisplayName("分辨率"), Description("画面的宽高像素大小,请在预览画面参数面板进行调整")] - public Size Resolution { get => Exporter.Resolution; } + [LocalizedCategory(typeof(Properties.Resources), "categoryExport")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayResoulution")] + [LocalizedDescription(typeof(Properties.Resources), "descResolution")] + public Size Resolution { get => Exporter.Resolution; } - /// - /// 预览画面视区 - /// - [Category("[0] 导出"), DisplayName("预览画面视区"), Description("预览画面的视区参数,请在预览画面参数面板进行调整")] - public SFML.Graphics.View View { get => Exporter.PreviewerView; } + /// + /// 预览画面视区 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryExport")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayPreviewViewport")] + [LocalizedDescription(typeof(Properties.Resources), "descPreviewViewport")] + public SFML.Graphics.View View { get => Exporter.PreviewerView; } - /// - /// 是否仅渲染选中 - /// - [Category("[0] 导出"), DisplayName("仅渲染选中"), Description("是否仅导出选中的模型,请在预览画面参数面板进行调整")] - public bool RenderSelectedOnly { get => Exporter.RenderSelectedOnly; } + /// + /// 是否仅渲染选中 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryExport")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayRenderSelected")] + [LocalizedDescription(typeof(Properties.Resources), "descRenderSelected")] + public bool RenderSelectedOnly { get => Exporter.RenderSelectedOnly; } /// /// 背景颜色 /// [Editor(typeof(SFMLColorEditor), typeof(UITypeEditor))] [TypeConverter(typeof(SFMLColorConverter))] - [Category("[0] 导出"), DisplayName("背景颜色"), Description("要使用的背景色, 格式为 #RRGGBBAA")] - public SFML.Graphics.Color BackgroundColor { get => Exporter.BackgroundColor; set => Exporter.BackgroundColor = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryExport")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayBackgroundColor")] + [LocalizedDescription(typeof(Properties.Resources), "descBackgroundColor")] + public SFML.Graphics.Color BackgroundColor { get => Exporter.BackgroundColor; set => Exporter.BackgroundColor = value; } /// /// 四周边缘距离 /// [TypeConverter(typeof(PaddingConverter))] - [Category("[0] 导出"), DisplayName("四周边缘距离"), Description("画布外部的边缘距离 (Margin), 最终导出的分辨率需要加上这个边距")] - public Padding Margin { get => Exporter.Margin; set => Exporter.Margin = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryExport")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayMargin")] + [LocalizedDescription(typeof(Properties.Resources), "descMargin")] + public Padding Margin { get => Exporter.Margin; set => Exporter.Margin = value; } /// /// 四周填充距离 /// [TypeConverter(typeof(PaddingConverter))] - [Category("[0] 导出"), DisplayName("四周填充距离"), Description("画布内部的填充距离 (Padding), 导出的分辨率大小不会发生变化, 但是会留有四周空间")] - public Padding Padding { get => Exporter.Padding; set => Exporter.Padding = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryExport")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayPadding")] + [LocalizedDescription(typeof(Properties.Resources), "descPadding")] + public Padding Padding { get => Exporter.Padding; set => Exporter.Padding = value; } - /// - /// 允许内容溢出到边缘和填充区域 - /// - [Category("[0] 导出"), DisplayName("允许内容溢出"), Description("使用预览画面分辨率的情况下, 允许内容溢出到边缘和填充区域")] - public bool AllowContentOverflow { get => Exporter.AllowContentOverflow; set => Exporter.AllowContentOverflow = value; } + /// + /// 允许内容溢出到边缘和填充区域 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryExport")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayAllowContentOverflow")] + [LocalizedDescription(typeof(Properties.Resources), "descAllowContentOverflow")] + public bool AllowContentOverflow { get => Exporter.AllowContentOverflow; set => Exporter.AllowContentOverflow = value; } - /// - /// 自动分辨率 - /// - [Category("[0] 导出"), DisplayName("自动分辨率"), Description("根据导出内容自动设置分辨率, 四周填充距离和内容溢出参数将会被忽略")] - public bool AutoResolution { get => Exporter.AutoResolution; set => Exporter.AutoResolution = value; } + /// + /// 自动分辨率 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryExport")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayAutoResolution")] + [LocalizedDescription(typeof(Properties.Resources), "descAutoResolution")] + public bool AutoResolution { get => Exporter.AutoResolution; set => Exporter.AutoResolution = value; } } } diff --git a/SpineViewer/Spine/SpineExporter/FFmpegVideoExporter.cs b/SpineViewer/Spine/SpineExporter/FFmpegVideoExporter.cs index e7147ce..a908095 100644 --- a/SpineViewer/Spine/SpineExporter/FFmpegVideoExporter.cs +++ b/SpineViewer/Spine/SpineExporter/FFmpegVideoExporter.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; +using SpineViewer.Utils.Localize; namespace SpineViewer.Spine.SpineExporter { @@ -45,9 +46,9 @@ namespace SpineViewer.Spine.SpineExporter if (base.Validate() is string error) return error; if (string.IsNullOrWhiteSpace(Format)) - return "需要提供有效的格式"; + return Properties.Resources.validFormatRequired; if (string.IsNullOrWhiteSpace(Suffix)) - return "需要提供有效的文件名后缀"; + return Properties.Resources.validExtensionRequired; return null; } @@ -114,22 +115,28 @@ namespace SpineViewer.Spine.SpineExporter [Browsable(false)] public override FFmpegVideoExporter Exporter => (FFmpegVideoExporter)base.Exporter; - /// - /// 文件格式 - /// - [Category("[2] FFmpeg 基本参数"), DisplayName("文件格式"), Description("-f, 文件格式")] + /// + /// 文件格式 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFFmpegParameter")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayFileFormat")] + [LocalizedDescription(typeof(Properties.Resources), "descFileFormat")] public virtual string Format => Exporter.Format; - /// - /// 文件名后缀 - /// - [Category("[2] FFmpeg 基本参数"), DisplayName("文件名后缀"), Description("文件名后缀")] + /// + /// 文件名后缀 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFFmpegParameter")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayFilenameSuffix")] + [LocalizedDescription(typeof(Properties.Resources), "descFilenameSuffix")] public virtual string Suffix => Exporter.Suffix; - /// - /// 文件名后缀 - /// - [Category("[2] FFmpeg 基本参数"), DisplayName("自定义参数"), Description("使用 \"ffmpeg -h encoder=<编码器>\" 查看编码器支持的参数\n使用 \"ffmpeg -h muxer=<文件格式>\" 查看文件格式支持的参数")] - public string CustomArgument { get => Exporter.CustomArgument; set => Exporter.CustomArgument = value; } + /// + /// 文件名后缀 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFFmpegParameter")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayCustomArgument")] + [LocalizedDescription(typeof(Properties.Resources), "descCustomArgument")] + public string CustomArgument { get => Exporter.CustomArgument; set => Exporter.CustomArgument = value; } } } diff --git a/SpineViewer/Spine/SpineExporter/FrameExporter.cs b/SpineViewer/Spine/SpineExporter/FrameExporter.cs index 0d7152b..194be41 100644 --- a/SpineViewer/Spine/SpineExporter/FrameExporter.cs +++ b/SpineViewer/Spine/SpineExporter/FrameExporter.cs @@ -1,4 +1,5 @@ using SpineViewer.Spine; +using SpineViewer.Utils.Localize; using System; using System.Collections.Generic; using System.ComponentModel; @@ -49,7 +50,7 @@ namespace SpineViewer.Spine.SpineExporter var filename = $"frame_{timestamp}{ImageFormat.GetSuffix()}"; var savePath = Path.Combine(OutputDir, filename); - worker?.ReportProgress(0, $"已处理 0/1"); + worker?.ReportProgress(0, $"{Properties.Resources.process} 0/1"); try { using var frame = GetFrame(spinesToRender); @@ -62,7 +63,7 @@ namespace SpineViewer.Spine.SpineExporter logger.Error(ex.ToString()); logger.Error("Failed to save single frame"); } - worker?.ReportProgress(100, $"已处理 1/1"); + worker?.ReportProgress(100, $"{Properties.Resources.process} 1/1"); } protected override void ExportIndividual(SpineObject[] spinesToRender, BackgroundWorker? worker = null) @@ -71,7 +72,7 @@ namespace SpineViewer.Spine.SpineExporter int success = 0; int error = 0; - worker?.ReportProgress(0, $"已处理 0/{total}"); + worker?.ReportProgress(0, $"{Properties.Resources.process} 0/{total}"); for (int i = 0; i < total; i++) { var spine = spinesToRender[i]; @@ -95,7 +96,7 @@ namespace SpineViewer.Spine.SpineExporter error++; } - worker?.ReportProgress((int)((i + 1) * 100.0) / total, $"已处理 {i + 1}/{total}"); + worker?.ReportProgress((int)((i + 1) * 100.0) / total, $"{Properties.Resources.process} {i + 1}/{total}"); } if (error > 0) @@ -114,20 +115,24 @@ namespace SpineViewer.Spine.SpineExporter /// 单帧画面格式 /// [TypeConverter(typeof(ImageFormatConverter))] - [Category("[1] 单帧画面"), DisplayName("图像格式")] + [LocalizedCategory(typeof(Properties.Resources), "categorySingleFrame")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayImageFormat")] public ImageFormat ImageFormat { get => Exporter.ImageFormat; set => Exporter.ImageFormat = value; } - /// - /// 文件名后缀 - /// - [Category("[1] 单帧画面"), DisplayName("文件名后缀"), Description("与图像格式匹配的文件名后缀")] + /// + /// 文件名后缀 + /// + [LocalizedCategory(typeof(Properties.Resources), "categorySingleFrame")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayFilenameSuffix")] + [LocalizedDescription(typeof(Properties.Resources), "descFileNameExtension")] public string Suffix { get => Exporter.ImageFormat.GetSuffix(); } /// /// DPI /// [TypeConverter(typeof(SizeFConverter))] - [Category("[1] 单帧画面"), DisplayName("DPI"), Description("导出图像的每英寸像素数,用于调整图像的物理尺寸")] + [LocalizedCategory(typeof(Properties.Resources), "categorySingleFrame")] + [LocalizedDescription(typeof(Properties.Resources), "descDPI")] public SizeF DPI { get => Exporter.DPI; set => Exporter.DPI = value; } } } diff --git a/SpineViewer/Spine/SpineExporter/FrameSequenceExporter.cs b/SpineViewer/Spine/SpineExporter/FrameSequenceExporter.cs index ac39fcb..adfaeaa 100644 --- a/SpineViewer/Spine/SpineExporter/FrameSequenceExporter.cs +++ b/SpineViewer/Spine/SpineExporter/FrameSequenceExporter.cs @@ -1,5 +1,6 @@ using SpineViewer.Spine; using SpineViewer.Utils; +using SpineViewer.Utils.Localize; using System; using System.Collections.Generic; using System.ComponentModel; @@ -93,7 +94,9 @@ namespace SpineViewer.Spine.SpineExporter /// 文件名后缀 /// [TypeConverter(typeof(StringEnumConverter)), StringEnumConverter.StandardValues(".png", ".jpg", ".tga", ".bmp")] - [Category("[2] 帧序列参数"), DisplayName("文件名后缀"), Description("帧文件的后缀,同时决定帧图像格式")] + [LocalizedCategory(typeof(Properties.Resources), "categoryFrameSequenceParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayFilenameSuffix")] + [LocalizedDescription(typeof(Properties.Resources), "descFrameFileExtension")] public string Suffix { get => Exporter.Suffix; set => Exporter.Suffix = value; } } } diff --git a/SpineViewer/Spine/SpineExporter/GifExporter.cs b/SpineViewer/Spine/SpineExporter/GifExporter.cs index 8395f73..921d631 100644 --- a/SpineViewer/Spine/SpineExporter/GifExporter.cs +++ b/SpineViewer/Spine/SpineExporter/GifExporter.cs @@ -1,4 +1,5 @@ using FFMpegCore; +using SpineViewer.Utils.Localize; using System; using System.Collections.Generic; using System.ComponentModel; @@ -58,22 +59,28 @@ namespace SpineViewer.Spine.SpineExporter [Browsable(false)] public override GifExporter Exporter => (GifExporter)base.Exporter; - /// - /// 调色板最大颜色数量 - /// - [Category("[3] 格式参数"), DisplayName("调色板最大颜色数量"), Description("设置调色板使用的最大颜色数量, 越多则色彩保留程度越高")] + /// + /// 调色板最大颜色数量 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayMaxColor")] + [LocalizedDescription(typeof(Properties.Resources), "descMaxColor")] public uint MaxColors { get => Exporter.MaxColors; set => Exporter.MaxColors = value; } - /// - /// 透明度阈值 - /// - [Category("[3] 格式参数"), DisplayName("透明度阈值"), Description("小于该值的像素点会被认为是透明像素")] + /// + /// 透明度阈值 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayAlphaThreshold")] + [LocalizedDescription(typeof(Properties.Resources), "descAlphaThreshold")] public byte AlphaThreshold { get => Exporter.AlphaThreshold; set => Exporter.AlphaThreshold = value; } - /// - /// 透明度阈值 - /// - [Category("[3] 格式参数"), DisplayName("循环次数"), Description("-loop, 循环次数, -1 不循环, 0 无限循环, 取值范围 [-1, 65535]")] + /// + /// 透明度阈值 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayLoopCount")] + [LocalizedDescription(typeof(Properties.Resources), "descLoopCount")] public int Loop { get => Exporter.Loop; set => Exporter.Loop = value; } } } diff --git a/SpineViewer/Spine/SpineExporter/MkvExporter.cs b/SpineViewer/Spine/SpineExporter/MkvExporter.cs index c7be9c2..909d9e1 100644 --- a/SpineViewer/Spine/SpineExporter/MkvExporter.cs +++ b/SpineViewer/Spine/SpineExporter/MkvExporter.cs @@ -1,5 +1,6 @@ using FFMpegCore; using SpineViewer.Utils; +using SpineViewer.Utils.Localize; using System; using System.Collections.Generic; using System.ComponentModel; @@ -58,21 +59,27 @@ namespace SpineViewer.Spine.SpineExporter /// [StringEnumConverter.StandardValues("libx264", "libx265", "libvpx-vp9", "av1_nvenc", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("编码器"), Description("-c:v, 要使用的编码器")] - public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayEncoder")] + [LocalizedDescription(typeof(Properties.Resources), "descAvifEncoder")] + public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } - /// - /// CRF - /// - [Category("[3] 格式参数"), DisplayName("CRF"), Description("-crf, 取值范围 0-63, 建议范围 18-28, 默认取值 23, 数值越小则输出质量越高")] - public int CRF { get => Exporter.CRF; set => Exporter.CRF = value; } + /// + /// CRF + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [DisplayName("CRF")] + [LocalizedDescription(typeof(Properties.Resources), "descCRF")] + public int CRF { get => Exporter.CRF; set => Exporter.CRF = value; } /// /// 像素格式 /// [StringEnumConverter.StandardValues("yuv420p", "yuv422p", "yuv444p", "yuva420p", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("像素格式"), Description("-pix_fmt, 要使用的像素格式")] + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayPixelFormat")] + [LocalizedDescription(typeof(Properties.Resources), "descPixelFormat")] public string PixelFormat { get => Exporter.PixelFormat; set => Exporter.PixelFormat = value; } } } diff --git a/SpineViewer/Spine/SpineExporter/MovExporter.cs b/SpineViewer/Spine/SpineExporter/MovExporter.cs index dddcbb6..163c17b 100644 --- a/SpineViewer/Spine/SpineExporter/MovExporter.cs +++ b/SpineViewer/Spine/SpineExporter/MovExporter.cs @@ -1,5 +1,6 @@ using FFMpegCore; using SpineViewer.Utils; +using SpineViewer.Utils.Localize; using System; using System.Collections.Generic; using System.ComponentModel; @@ -57,15 +58,19 @@ namespace SpineViewer.Spine.SpineExporter /// [StringEnumConverter.StandardValues("prores_ks", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("编码器"), Description("-c:v, 要使用的编码器")] - public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayEncoder")] + [LocalizedDescription(typeof(Properties.Resources), "descAvifEncoder")] + public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } /// /// 预设 /// [StringEnumConverter.StandardValues("auto", "proxy", "lt", "standard", "hq", "4444", "4444xq")] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("预设"), Description("-profile, 预设配置")] + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayPreset")] + [LocalizedDescription(typeof(Properties.Resources), "descPreset")] public string Profile { get => Exporter.Profile; set => Exporter.Profile = value; } /// @@ -73,7 +78,9 @@ namespace SpineViewer.Spine.SpineExporter /// [StringEnumConverter.StandardValues("yuv422p10le", "yuv444p10le", "yuva444p10le", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("像素格式"), Description("-pix_fmt, 要使用的像素格式")] - public string PixelFormat { get => Exporter.PixelFormat; set => Exporter.PixelFormat = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayPixelFormat")] + [LocalizedDescription(typeof(Properties.Resources), "descPixelFormat")] + public string PixelFormat { get => Exporter.PixelFormat; set => Exporter.PixelFormat = value; } } } diff --git a/SpineViewer/Spine/SpineExporter/Mp4Exporter.cs b/SpineViewer/Spine/SpineExporter/Mp4Exporter.cs index e6aac2a..e1553d6 100644 --- a/SpineViewer/Spine/SpineExporter/Mp4Exporter.cs +++ b/SpineViewer/Spine/SpineExporter/Mp4Exporter.cs @@ -1,5 +1,6 @@ using FFMpegCore; using SpineViewer.Utils; +using SpineViewer.Utils.Localize; using System; using System.Collections.Generic; using System.ComponentModel; @@ -58,21 +59,27 @@ namespace SpineViewer.Spine.SpineExporter /// [StringEnumConverter.StandardValues("libx264", "libx265", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("编码器"), Description("-c:v, 要使用的编码器")] - public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayEncoder")] + [LocalizedDescription(typeof(Properties.Resources), "descAvifEncoder")] + public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } - /// - /// CRF - /// - [Category("[3] 格式参数"), DisplayName("CRF"), Description("-crf, 取值范围 0-63, 建议范围 18-28, 默认取值 23, 数值越小则输出质量越高")] - public int CRF { get => Exporter.CRF; set => Exporter.CRF = value; } + /// + /// CRF + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [DisplayName("CRF")] + [LocalizedDescription(typeof(Properties.Resources), "descCRF")] + public int CRF { get => Exporter.CRF; set => Exporter.CRF = value; } /// /// 像素格式 /// [StringEnumConverter.StandardValues("yuv420p", "yuv422p", "yuv444p", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("像素格式"), Description("-pix_fmt, 要使用的像素格式")] - public string PixelFormat { get => Exporter.PixelFormat; set => Exporter.PixelFormat = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayPixelFormat")] + [LocalizedDescription(typeof(Properties.Resources), "descPixelFormat")] + public string PixelFormat { get => Exporter.PixelFormat; set => Exporter.PixelFormat = value; } } } diff --git a/SpineViewer/Spine/SpineExporter/VideoExporter.cs b/SpineViewer/Spine/SpineExporter/VideoExporter.cs index 04bc6fe..7b55087 100644 --- a/SpineViewer/Spine/SpineExporter/VideoExporter.cs +++ b/SpineViewer/Spine/SpineExporter/VideoExporter.cs @@ -1,4 +1,5 @@ using SpineViewer.Spine; +using SpineViewer.Utils.Localize; using System; using System.Collections.Generic; using System.ComponentModel; @@ -34,7 +35,7 @@ namespace SpineViewer.Spine.SpineExporter if (base.Validate() is string error) return error; if (IsExportSingle && Duration < 0) - return "导出单个时导出时长不能为负数"; + return Properties.Resources.negativeDuration; return null; } @@ -55,11 +56,11 @@ namespace SpineViewer.Spine.SpineExporter int frameCount = 1 + total + final; // 所有帧的数量 = 起始帧 + 完整帧 + 最后一帧 - worker?.ReportProgress(0, $"{spine.Name} 已处理 0/{frameCount} 帧"); + worker?.ReportProgress(0, $"{spine.Name} {Properties.Resources.process} 0/{frameCount} {Properties.Resources.frame}"); // 导出首帧 var firstFrame = GetFrame(spine); - worker?.ReportProgress(1 * 100 / frameCount, $"{spine.Name} 已处理 1/{frameCount} 帧"); + worker?.ReportProgress(1 * 100 / frameCount, $"{spine.Name} {Properties.Resources.process} 1/{frameCount} {Properties.Resources.frame}"); yield return firstFrame; // 导出完整帧 @@ -73,7 +74,7 @@ namespace SpineViewer.Spine.SpineExporter spine.Update(delta); var frame = GetFrame(spine); - worker?.ReportProgress((1 + i + 1) * 100 / frameCount, $"{spine.Name} 已处理 {1 + i + 1}/{frameCount} 帧"); + worker?.ReportProgress((1 + i + 1) * 100 / frameCount, $"{spine.Name} {Properties.Resources.process} {1 + i + 1}/{frameCount} {Properties.Resources.frame}"); yield return frame; } @@ -82,7 +83,7 @@ namespace SpineViewer.Spine.SpineExporter { spine.Update(deltaFinal); var finalFrame = GetFrame(spine); - worker?.ReportProgress(100, $"{spine.Name} 已处理 {frameCount}/{frameCount} 帧"); + worker?.ReportProgress(100, $"{spine.Name} {Properties.Resources.process} {frameCount}/{frameCount} {Properties.Resources.frame}"); yield return finalFrame; } } @@ -103,11 +104,11 @@ namespace SpineViewer.Spine.SpineExporter int frameCount = 1 + total + final; // 所有帧的数量 = 起始帧 + 完整帧 + 最后一帧 - worker?.ReportProgress(0, $"已处理 0/{frameCount} 帧"); + worker?.ReportProgress(0, $"{Properties.Resources.process} 0/{frameCount} {Properties.Resources.frame}"); // 导出首帧 var firstFrame = GetFrame(spinesToRender); - worker?.ReportProgress(1 * 100 / frameCount, $"已处理 1/{frameCount} 帧"); + worker?.ReportProgress(1 * 100 / frameCount, $"{Properties.Resources.process} 1/{frameCount} {Properties.Resources.frame}"); yield return firstFrame; // 导出完整帧 @@ -121,7 +122,7 @@ namespace SpineViewer.Spine.SpineExporter foreach (var spine in spinesToRender) spine.Update(delta); var frame = GetFrame(spinesToRender); - worker?.ReportProgress((1 + i + 1) * 100 / frameCount, $"已处理 {1 + i + 1}/{frameCount} 帧"); + worker?.ReportProgress((1 + i + 1) * 100 / frameCount, $"{Properties.Resources.process} {1 + i + 1}/{frameCount} {Properties.Resources.frame}"); yield return frame; } @@ -130,7 +131,7 @@ namespace SpineViewer.Spine.SpineExporter { foreach (var spine in spinesToRender) spine.Update(delta); var finalFrame = GetFrame(spinesToRender); - worker?.ReportProgress(100, $"已处理 {frameCount}/{frameCount} 帧"); + worker?.ReportProgress(100, $"{Properties.Resources.process} {frameCount}/{frameCount} {Properties.Resources.frame}"); yield return finalFrame; } } @@ -148,22 +149,28 @@ namespace SpineViewer.Spine.SpineExporter [Browsable(false)] public override VideoExporter Exporter => (VideoExporter)base.Exporter; - /// - /// 导出时长 - /// - [Category("[1] 视频参数"), DisplayName("时长"), Description("可以从模型列表查看动画时长, 如果小于 0, 则在逐个导出时每个模型使用各自的所有轨道动画时长最大值")] + /// + /// 导出时长 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryVideoParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "duration")] + [LocalizedDescription(typeof(Properties.Resources), "descDuration")] public float Duration { get => Exporter.Duration; set => Exporter.Duration = value; } - /// - /// 帧率 - /// - [Category("[1] 视频参数"), DisplayName("帧率"), Description("每秒画面数")] - public float FPS { get => Exporter.FPS; set => Exporter.FPS = value; } + /// + /// 帧率 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryVideoParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayFPS")] + [LocalizedDescription(typeof(Properties.Resources), "descFPS")] + public float FPS { get => Exporter.FPS; set => Exporter.FPS = value; } - /// - /// 保留最后一帧 - /// - [Category("[1] 视频参数"), DisplayName("保留最后一帧"), Description("当设置保留最后一帧时, 动图会更为连贯, 但是帧数可能比预期帧数多 1")] - public bool KeepLast { get => Exporter.KeepLast; set => Exporter.KeepLast = value; } + /// + /// 保留最后一帧 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryVideoParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayKeepLastFrame")] + [LocalizedDescription(typeof(Properties.Resources), "descKeepLastFrame")] + public bool KeepLast { get => Exporter.KeepLast; set => Exporter.KeepLast = value; } } } diff --git a/SpineViewer/Spine/SpineExporter/WebmExporter.cs b/SpineViewer/Spine/SpineExporter/WebmExporter.cs index 560d8a0..36c42d1 100644 --- a/SpineViewer/Spine/SpineExporter/WebmExporter.cs +++ b/SpineViewer/Spine/SpineExporter/WebmExporter.cs @@ -1,5 +1,6 @@ using FFMpegCore; using SpineViewer.Utils; +using SpineViewer.Utils.Localize; using System; using System.Collections.Generic; using System.ComponentModel; @@ -59,21 +60,27 @@ namespace SpineViewer.Spine.SpineExporter /// [StringEnumConverter.StandardValues("libvpx-vp9", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("编码器"), Description("-c:v, 要使用的编码器")] - public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayEncoder")] + [LocalizedDescription(typeof(Properties.Resources), "descAvifEncoder")] + public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } - /// - /// CRF - /// - [Category("[3] 格式参数"), DisplayName("CRF"), Description("-crf, 取值范围 0-63, 建议范围 18-28, 默认取值 23, 数值越小则输出质量越高")] - public int CRF { get => Exporter.CRF; set => Exporter.CRF = value; } + /// + /// CRF + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [DisplayName("CRF")] + [LocalizedDescription(typeof(Properties.Resources), "descCRF")] + public int CRF { get => Exporter.CRF; set => Exporter.CRF = value; } /// /// 像素格式 /// [StringEnumConverter.StandardValues("yuv420p", "yuv422p", "yuv444p", "yuva420p", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("像素格式"), Description("-pix_fmt, 要使用的像素格式")] + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayPixelFormat")] + [LocalizedDescription(typeof(Properties.Resources), "descPixelFormat")] public string PixelFormat { get => Exporter.PixelFormat; set => Exporter.PixelFormat = value; } } } diff --git a/SpineViewer/Spine/SpineExporter/WebpExporter.cs b/SpineViewer/Spine/SpineExporter/WebpExporter.cs index fc62228..3ac6d61 100644 --- a/SpineViewer/Spine/SpineExporter/WebpExporter.cs +++ b/SpineViewer/Spine/SpineExporter/WebpExporter.cs @@ -1,5 +1,6 @@ using FFMpegCore; using SpineViewer.Utils; +using SpineViewer.Utils.Localize; using System; using System.Collections.Generic; using System.ComponentModel; @@ -69,33 +70,43 @@ namespace SpineViewer.Spine.SpineExporter /// [StringEnumConverter.StandardValues("libwebp_anim", "libwebp", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("编码器"), Description("-c:v, 要使用的编码器")] - public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayEncoder")] + [LocalizedDescription(typeof(Properties.Resources), "descAvifEncoder")] + public string Codec { get => Exporter.Codec; set => Exporter.Codec = value; } - /// - /// 是否无损 - /// - [Category("[3] 格式参数"), DisplayName("无损"), Description("-lossless, 0 表示有损, 1 表示无损")] - public bool Lossless { get => Exporter.Lossless; set => Exporter.Lossless = value; } + /// + /// 是否无损 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayLoseless")] + [LocalizedDescription(typeof(Properties.Resources), "descLoseless")] + public bool Lossless { get => Exporter.Lossless; set => Exporter.Lossless = value; } - /// - /// CRF - /// - [Category("[3] 格式参数"), DisplayName("质量"), Description("-quality, 取值范围 0-100, 默认值 75")] - public int Quality { get => Exporter.Quality; set => Exporter.Quality = value; } + /// + /// CRF + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayQuality")] + [LocalizedDescription(typeof(Properties.Resources), "descQuality")] + public int Quality { get => Exporter.Quality; set => Exporter.Quality = value; } /// /// 像素格式 /// [StringEnumConverter.StandardValues("yuv420p", "yuva420p", Customizable = true)] [TypeConverter(typeof(StringEnumConverter))] - [Category("[3] 格式参数"), DisplayName("像素格式"), Description("-pix_fmt, 要使用的像素格式")] - public string PixelFormat { get => Exporter.PixelFormat; set => Exporter.PixelFormat = value; } + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayPixelFormat")] + [LocalizedDescription(typeof(Properties.Resources), "descPixelFormat")] + public string PixelFormat { get => Exporter.PixelFormat; set => Exporter.PixelFormat = value; } - /// - /// 透明度阈值 - /// - [Category("[3] 格式参数"), DisplayName("循环次数"), Description("-loop, 循环次数, 0 无限循环, 取值范围 [0, 65535]")] - public int Loop { get => Exporter.Loop; set => Exporter.Loop = value; } + /// + /// 透明度阈值 + /// + [LocalizedCategory(typeof(Properties.Resources), "categoryFormatParameters")] + [LocalizedDisplayName(typeof(Properties.Resources), "displayLoopCount")] + [LocalizedDescription(typeof(Properties.Resources), "descLoopCount")] + public int Loop { get => Exporter.Loop; set => Exporter.Loop = value; } } }