.NET Core中C#代码带重音法语文本i18n翻译失效问题
问题描述
我们有一个法语.NET Core应用,使用i18n实现英语翻译。目前遇到异常:C#代码中所有带重音符号(如“é”)的文本,i18n无法返回对应的msgstr翻译内容,仅显示默认语言的msgid。
示例.po文件内容:
#: Views\User\Index.cshtml:58 msgid "Compte bloqué" msgstr "Blocked account"
复现场景
翻译正常工作的场景
- 纯HTML中
- JavaScript/jQuery中
翻译失效的场景
- Razor代码(如ActionLink等)中
- Model/Controller中
注:i18n已识别到需要翻译(未显示
[[[ ]]]包裹文本),但未返回指定翻译内容,也无错误日志。已确认所有文件均为UTF-8编码(有无BOM无差异)。
当前配置
.pot文件头
msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2022-10-04 15:13+02:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: pot (1.0.16)\n"
Startup.cs中的i18n配置
services.AddI18NLocalization(_webHostEnvironment, options => { var supportedCultures = new[] { new CultureInfo("fr-FR"), new CultureInfo("en-US") }; var defaultCulture = supportedCultures.Single(x => x.Name == "fr-FR"); options.DefaultRequestCulture = new RequestCulture(defaultCulture); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; options.RequestCultureProviders = new List<IRequestCultureProvider> { new CookieRequestCultureProvider() }; });
临时方案(不可行)
在代码中使用变量,并在.pot文件的msgstr中写入带重音的文本,但.pot是模板文件,i18n更新时所有msgstr会被重置。另外尝试生成fr-FR(默认语言)的.po文件,文件生成正常但内容被忽略,msgid未被替换为指定msgstr。
解决思路
验证字符串匹配的规范化一致性:重音字符存在Unicode规范化差异(比如预组合形式
é和组合形式e+´),检查代码中的msgid和.po文件中的字符是否属于同一规范化形式。可在代码中使用string.Normalize(NormalizationForm.FormC)统一格式后再调用翻译。确认本地化调用方式正确性:检查Razor/Controller中是否使用了正确的本地化扩展方法,比如Razor中是否用
@Localizer["Compte bloqué"]而非直接硬编码字符串;Controller中是否通过IStringLocalizer实例调用翻译,而非直接输出字符串。检查线程文化设置:在翻译失效的场景中,打印
Thread.CurrentThread.CurrentUICulture.Name确认当前线程的UI文化是否确实切换到了en-US,避免因文化未正确切换导致使用默认语言文本。启用i18n调试日志:开启i18n库的调试日志,查看.po文件加载过程中带重音的msgid是否被正确解析并加入资源缓存,排查是否存在加载时的编码或解析异常。
尝试Unicode转义序列:在.po文件中用Unicode转义序列代替直接的重音字符,比如将
msgid "Compte bloqué"改为msgid "Compte bloqu\u00e9",验证是否能匹配成功。升级i18n库版本:检查当前使用的i18n库是否存在已知的重音字符匹配bug,尝试升级到最新稳定版本。
内容的提问来源于stack exchange,提问作者Shilok

