☰
ShareX UploadersLib 多语言本地化体系:RESX 资源目录、命名规范与自动化校验
2026/9/30 8:09:25 网站建设 项目流程
  • 桌面应用
  • 图像处理
  • 音视频
  • OCR

【免费下载链接】ShareX

ShareX is a free and open-source application that enables users to capture or record any area of their screen with a single keystroke. It also supports uploading images, text, and various file types to a wide range of destinations.

项目地址:https://gitcode.com/GitHub_Trending/sh/ShareX
点击查看免费下载

导读

ShareX 的上传服务库(UploadersLib)承载了全部图片、文件、文本上传目标(如 Amazon S3、FTP、Backblaze B2、各类图床与短链服务)以及邮件、OAuth 监听等对话框,是用户界面文本量最大的模块之一。本文以仓库中的 UploadersLib 本地化状态文档 为主线,结合源码与校验脚本,系统讲解该库的 RESX 资源目录结构、键命名规范、C#/AXAML 引用方式、动态前缀本地化机制,以及仓库级的自动化翻译校验流水线。读完本文,你将掌握为 ShareX 上传服务模块新增或修改翻译文本的完整流程与验证命令。

本地化架构总览:字符串目录与资源边界

UploadersLib 的所有可翻译用户界面文本与运行时文本,统一存放在该库的Localization目录下,以共享的Strings.resx为默认(英文)目录,配套 28 个语言目录文件Strings.<culture>.resx(如 Strings.zh-CN.resx)。每个资源键(key)按"所属窗口、上传器、枚举或组件"进行作用域隔离,键名前缀即标识其归属,避免不同模块之间出现键名冲突。

与字符串目录相分离的是 Properties/Resources.resx 及其生成的Resources.Designer.cs,它继续负责非文本资源:上传器图标、图片以及 OAuth 回调页面资产(HTML)。这一分工保证了"可翻译文本"与"二进制/固定资产"两条线互不干扰,翻译人员只需要关注Localization/Strings*.resx。

资源键分区与命名规范

依据文档中的分区表,UploadersLib 的 488 个键被划分为四个区域,每个区域使用独立的前缀体系:

区域资源前缀键数状态
目标(Destination)设置DestinationSettings_、DestinationSettingsWindow_209完整
对话框窗口EmailWindow_、OAuthListenerWindow_、ParserSelectWindow_、ResponseWindow_、TextUploadWindow_、YouTubeVideoOptionsWindow_54完整
目标、协议、隐私与格式名称FileDestination_、ImageDestination_、TextDestination_、UrlShortenerType_及相关枚举前缀147完整
上传器错误与运行时消息上传器与辅助组件前缀73完整

四个区域的键数合计 209 + 54 + 147 + 73 = 488,与文档声明的总键数完全一致。打开 Strings.resx 可以看到实际键名的组织方式:

  • 枚举值名称类:AccountType_Anonymous、AccountType_User、AmazonS3StorageClass_STANDARD、BoxShareAccessLevel_Open;
  • 运行时错误消息类:BackblazeB2_Could_not_authenticate、BackblazeB2_Upload_failed_with_error、AzureStorage_Access_key_must_not_be_empty;
  • 数据校验类:Base58Converter_Invalid_character(含{0}、{1}两个复合格式占位符)。

命名规则可以归纳为组件前缀 + 语义化名称,组件名使用类名或枚举名(如BackblazeB2_、DestinationSettings_),语义部分使用下划线分隔的自然语言单词(如Could_not_get_upload_URL)。这种命名法让翻译人员在不阅读代码的情况下,也能通过键名判断文本出现在哪个窗口、属于哪个上传器。

所有 488 个键在默认英文目录与 28 个文化目录中完全对齐,且复合格式占位符(composite-format placeholders)在每种翻译中保持一致——例如{0}、{1}的位置与数量必须与英文原文相同,否则运行时string.Format会抛出异常或产生错误文案。

支持的语言与文化映射

28 个语言目录并非全部使用完整文化名(如cs-CZ),部分采用中性文化(neutral culture)目录(如cs),这是 .NET 资源回退机制允许的:当运行环境是cs-CZ时,会回退到cs目录。语言与目录的对应关系由 ShareX/LanguageHelper.cs 中的GetCultureName方法(第 68-165 行)集中维护,例如Arabic → ar-YE、SimplifiedChinese → zh-CN、TraditionalChinese → zh-TW、Portuguese → pt-PT、PortugueseBrazil → pt-BR、MexicanSpanish → es-MX、Spanish → es-ES。运行时若选择SupportedLanguage.Automatic,则采用CultureInfo.InstalledUICulture自动适配操作系统语言。

校验脚本 ValidateTranslations.ps1 中维护了一份与LanguageHelper严格一致的languageCatalogMap,并会反向解析LanguageHelper.cs源码,比对两边的文化列表是否完全相同——任何一边新增语言而忘记同步另一边,校验都会失败。仓库中共存在 28 个Strings.*.resx文件(不含默认的Strings.resx),与文档声明的 28 个支持文化吻合。

在 C# 与 AXAML 中引用资源键

C# 强类型引用

UploadersLib 使用强类型访问器类 Strings.Designer.cs,它在编译期生成public static string属性,代码中直接写Localization.Strings.<键名>即可,例如Localization.Strings.DestinationSettings_Accounts。强类型引用的好处是:键名拼写错误会在编译期暴露,且 Visual Studio 的重构功能可以安全重命名。

AXAML 静态绑定

Avalonia 界面中通过x:Static扩展引用资源键。在 DestinationSettingsWindow.axaml 第 14 行的窗口标题即:

Title="{x:Static localization:Strings.DestinationSettingsWindow_ShareX_Destination_settings}"

EmailWindow.axaml 中大量使用了同样的模式,包括EmailWindow_To_email、EmailWindow_Subject、EmailWindow_Message等键,以及PlaceholderText="{x:Static localization:Strings.EmailWindow_name_example_com}"这样的输入框占位文本。校验脚本会扫描所有.axaml与.cs源文件,提取Strings.<key>形式的引用并与目录比对,确保"源码引用了不存在的键"或"目录中存在无引用的孤立键"都会被报告。

动态前缀与数据驱动本地化

UploadersLib 中约 147 个枚举名称键(FileDestination_、ImageDestination_、TextDestination_、UrlShortenerType_等)不是靠手写引用使用的,而是通过数据驱动查找在运行时解析:

  1. 枚举描述本地化:上传器服务基类 UploaderService.cs 第 39 行通过EnumValue.GetLocalizedDescription(Localization.Strings.ResourceManager)读取枚举值的本地化描述,因此"目标服务名称"(如 Imgur、FTP、Amazon S3)在界面上会随语言切换而本地化;
  2. 目标设置字段标签本地化:设置页构建器 DestinationSettingsPageBuilder.cs 的FormatLabel方法(第 984-992 行)会把属性名(如AccessKeyId)转换为可读标签,然后拼出"DestinationSettings_Field_" + 规范化名称作为资源键,调用Localization.Strings.ResourceManager.GetString(resourceName)查询;若目录中不存在该键,则回退到本地格式化生成的英文标签。

这套机制的关键在于:DestinationSettings_Field_、FileDestination_等属于数据驱动前缀(DynamicPrefixes),校验脚本不会把"未被源码直接引用"当作错误——因为键名是运行时拼接出来的。脚本对每个项目配置了前缀白名单(UploadersLib 共 20 个动态前缀,见 ValidateTranslations.ps1 中$projects数组),同时要求源码中必须存在对应的数据驱动查找调用(如"DestinationSettings_Field_" +与ResourceManager.GetString(resourceName)),防止前缀被误删。

新增或修改翻译文本的五步流程

文档给出了明确的改动流程,结合源码可以补充每一步的细节:

  1. 向Strings.resx添加带作用域的键:键名遵循组件前缀_语义名规范,例如新增某个上传器错误消息时使用MyUploader_Error_message;
  2. 在每一个Strings.<culture>.resx目录中添加翻译值:所有 28 个文化目录必须同步添加,键名完全一致;
  3. 使用直接引用:C# 中写Strings.<key>,AXAML 中写{x:Static localization:Strings.<key>},禁止在界面硬编码可见文本,也禁止使用旧的L()帮助方法或using别名(这两类用法会被校验脚本直接判错);
  4. 保留复合格式占位符:英文原文中的{0}、{1}等占位符在每种翻译中都必须原样保留(位置可随语言习惯调整,但数量与编号不能变);同时,翻译中的命令行占位符(形如$name$)也必须与英文一致;
  5. 构建ShareX.UploadersLib验证资源与 AXAML:运行项目构建确保Strings.Designer.cs重新生成、AXAML 绑定编译通过。

仓库级自动化校验:ValidateTranslations.ps1

文档明确指出,仓库根目录的 ValidateTranslations.ps1 承担着全部本地化项目的质量门禁。脚本执行完毕后还会自动调用 FormatTranslations.ps1 对资源文件做规范化。综合脚本源码,其校验范围包括:

  • 支持语言与目录清单:实际存在的语言目录必须与languageCatalogMap、LanguageHelper.cs三方一致,缺一个、多一个都报错;
  • 条目数量与键奇偶校验:每个语言目录的键数必须与英文目录完全相同,缺键、多余键都会被列出;
  • 空值检查:键值为空(含纯空白)即报错;
  • 格式占位符校验:逐键比对英文与翻译的{n}复合格式占位符集合,以及$name$命令占位符集合;
  • 编码与换行格式:文件必须是严格的 UTF-8 无 BOM(带 BOM 即报错),必须使用 CRLF 且以换行结尾,禁止裸 LF;还会检测可逆的 mojibake(乱码)与非法控制字符、错误的分号转义实体;
  • Designer 一致性:Strings.Designer.cs必须存在,ResourceManager基名必须为ShareX.UploadersLib.Localization.Strings,且每个键都有对应属性;
  • 源码引用检查:扫描全部.cs与.axaml源文件,源码引用的键必须在目录中存在,目录中无引用的键(非动态前缀)必须被删除;同时禁止本地化资源别名与L()帮助方法残留;
  • AXAML 字面文本检查:扫描Text、Content、Header、Title、Watermark、PlaceholderText、ToolTip.Tip等属性,发现用户可见的硬编码英文文本即报错(少量白名单值除外,如Auto、None、Transparent等布局关键字);
  • 英语等价物白名单:TranslationEnglishAllowlist.txt 以项目|文化|键|SHA256哈希四列格式记录了"允许保留英文原文"的特例(例如专有名词、域名类文本),每条记录附带哈希校验;翻译与英文相同且未在白名单中批准的键会被报告,同时白名单中的陈旧记录(已不再使用)也会被清理报告;
  • 未解决标记检查:源码中出现TODO: Translate注释即报错;
  • 数据驱动前缀检查:动态前缀必须被源码使用,数据驱动查找调用必须存在。

脚本最终输出按项目统计的表格(项目 / 英文键数 / 翻译数 / 文化数 / 总计 / 状态),全部通过后打印汇总并触发FormatTranslations.ps1;任何一项失败都会以非零退出码结束。

FormatTranslations.ps1:资源文件规范化

FormatTranslations.ps1 会遍历仓库中所有含Localization/Strings.resx的项目(共 9 个,包括ShareX、ShareX.Avalonia、ShareX.HelpersLib、ShareX.HistoryLib、ShareX.ImageEditor、ShareX.ImageEffectsLib、ShareX.ScreenCaptureLib、ShareX.Tools、ShareX.UploadersLib),对每个Strings*.resx执行:

  • 使用禁用 DTD 且XmlResolver = null的安全 XML 读取器解析,防止 XXE 类风险;
  • 将<data>元素按键名**序数排序(ordinal)**重新排列,保证文件内容确定性、便于 diff;
  • 检测重复键名并报错;
  • 以 UTF-8 无 BOM、两个空格缩进、CRLF 换行重新写出。

脚本只在实际字节发生变化时才覆盖文件,并输出格式化的文件总数与实际更新数,避免无意义的文件变动。

运行校验与构建

从仓库根目录执行校验与构建(文档给出的两条命令):

powershell -NoProfile -ExecutionPolicy Bypass -File Scripts\ValidateTranslations.ps1 dotnet build ShareX.UploadersLib/ShareX.UploadersLib.csproj --no-restore

第一条命令对全部本地化项目执行上述完整校验(结束后自动触发格式化);第二条命令编译 UploadersLib 项目本身,验证资源嵌入、强类型 Designer 与 AXAML 绑定。--no-restore跳过 NuGet 还原以加速本地迭代;在 CI 中则可去掉该参数确保依赖完整。校验脚本还通过"扫描Localization/Strings.resx存在的目录"自动发现本地化项目清单,并与内置的项目配置比对,因此新增本地化项目也必须同步更新脚本中的$projects数组。

延伸:统一的本地化体系

UploadersLib 采用的多目录 RESX + 强类型 Designer + 数据驱动前缀 + 集中校验脚本这套体系并非孤例,而是 ShareX 各模块统一遵循的工程约定。例如 HelpersLib 本地化状态文档 记录了颜色选择器窗口(ColorPickerWindow_34 键)、错误窗口、图像查看器、输入/输出框、打印窗口等 129 个键,同样覆盖全部 28 个文化,且同样由ValidateTranslations.ps1把关。理解 UploadersLib 的本地化机制后,其他模块的翻译工作流程完全一致,可以举一反三。

通过这套"资源目录分区 + 强类型引用 + 数据驱动查找 + 脚本级质量门禁"的组合,ShareX 得以在数百个上传目标、数千条界面文本的规模下,维持翻译完整性、占位符正确性与编码规范性,为社区翻译贡献提供了清晰且可自动验证的协作边界。

  • 桌面应用
  • 图像处理
  • 音视频
  • OCR

【免费下载链接】ShareX

ShareX is a free and open-source application that enables users to capture or record any area of their screen with a single keystroke. It also supports uploading images, text, and various file types to a wide range of destinations.

项目地址:https://gitcode.com/GitHub_Trending/sh/ShareX
点击查看免费下载

相关推荐

上一篇:Foundry RPC Fixture 生成指南:以 eth_getLogs.json 与 balance_params.json 为例
下一篇:Kubernetes 扩展性与性能目标全解析:SIG Scalability 定义的集群规模基准与实践指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询