Xamarin.Forms应用如何加载系统不支持的自定义语言字符串资源文件
问题根源
你遇到的报错是因为运行Xamarin.Forms的Mono runtime默认未内置克林贡语、世界语这类小众/人造语言的CultureInfo配置,直接构造对应文化实例时会触发校验失败异常。
以下是两种可行的实现方案:
方案1:自定义文化注册(低侵入,兼容原有多语言逻辑)
Mono runtime支持手动注册自定义文化,注册完成后原有构造CultureInfo的代码、AppResources.xx.resx的命名规则、系统自动加载资源的逻辑都不需要修改,适配成本最低。
- 先在应用初始化阶段(如
App.xaml.cs构造函数最开头)注册所有需要的自定义文化:
using System.Globalization; public void RegisterCustomCultures() { // 按需求添加所有需要支持的小众语言 var customLangList = new List<(string langCode, string englishName, string nativeName)> { ("eo", "Esperanto", "Esperanto"), ("tok", "Toki Pona", "Toki Pona"), ("tlh", "Klingon", "tlhIngan Hol"), ("ido", "Ido", "Ido") }; foreach (var lang in customLangList) { try { // 跳过已经被系统支持的文化 CultureInfo.GetCultureInfo(lang.langCode); continue; } catch (CultureNotFoundException) { // 构造自定义文化配置 var cultureBuilder = new CultureAndRegionInfoBuilder(lang.langCode, CultureAndRegionModifiers.None); // 基础配置继承自带的英语文化,避免缺参数报错 cultureBuilder.LoadDataFromCultureInfo(CultureInfo.GetCultureInfo("en")); cultureBuilder.CultureEnglishName = lang.englishName; cultureBuilder.CultureNativeName = lang.nativeName; cultureBuilder.TwoLetterISOLanguageName = lang.langCode; // 注册到当前 runtime cultureBuilder.Register(); } } }
- 注册完成后,你原有的切换语言代码无需修改即可正常运行:
CultureInfo language = new CultureInfo("eo");
该方案适配Mac、Android平台的Xamarin运行环境,iOS端如果遇到权限限制可切换为方案2
方案2:自主接管资源加载(零依赖系统文化配置,全平台兼容)
如果你不需要系统的其他本地化能力,只需要加载对应resx的字符串,可以完全绕开CultureInfo相关逻辑,自己实现资源读取:
- 把所有
AppResources.xx.resx文件的「生成操作」属性设置为嵌入的资源 - 实现自定义本地化管理器,缓存所有语言的字符串资源:
using System.Reflection; using System.Resources; public static class LocalizationManager { private static readonly Dictionary<string, Dictionary<string, string>> _langCache = new(); private static string _currentLang = "en"; private const string ResxBaseName = "你的应用命名空间.AppResources"; static LocalizationManager() { // 预加载所有自定义语言的资源 LoadLangRes("eo"); LoadLangRes("tok"); LoadLangRes("tlh"); LoadLangRes("ido"); // 官方语言按需加载 } private static void LoadLangRes(string langCode) { var resManager = new ResourceManager($"{ResxBaseName}.{langCode}", Assembly.GetExecutingAssembly()); var resourceSet = resManager.GetResourceSet(CultureInfo.InvariantCulture, true, true); var langDict = resourceSet.Cast<DictionaryEntry>() .ToDictionary(k => k.Key.ToString(), v => v.Value.ToString()); _langCache[langCode] = langDict; } public static void SetCurrentLang(string langCode) { if (_langCache.ContainsKey(langCode)) _currentLang = langCode; // 可添加fallback逻辑 } public static string GetString(string key) { if (_langCache[_currentLang].TryGetValue(key, out var value)) return value; // 找不到时返回默认语言的对应值 return _langCache["en"][key]; } }
- 所有原来调用
AppResources.xxx的地方替换为LocalizationManager.GetString("xxx")即可。
内容的提问来源于stack exchange,提问作者Tanja
相关产品推荐
相关产品推荐

