You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Forms应用如何加载系统不支持的自定义语言字符串资源文件

问题根源

你遇到的报错是因为运行Xamarin.Forms的Mono runtime默认未内置克林贡语、世界语这类小众/人造语言的CultureInfo配置,直接构造对应文化实例时会触发校验失败异常。
以下是两种可行的实现方案:

方案1:自定义文化注册(低侵入,兼容原有多语言逻辑)

Mono runtime支持手动注册自定义文化,注册完成后原有构造CultureInfo的代码、AppResources.xx.resx的命名规则、系统自动加载资源的逻辑都不需要修改,适配成本最低。

  1. 先在应用初始化阶段(如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();
        }
    }
}
  1. 注册完成后,你原有的切换语言代码无需修改即可正常运行:
CultureInfo language = new CultureInfo("eo"); 

该方案适配Mac、Android平台的Xamarin运行环境,iOS端如果遇到权限限制可切换为方案2

方案2:自主接管资源加载(零依赖系统文化配置,全平台兼容)

如果你不需要系统的其他本地化能力,只需要加载对应resx的字符串,可以完全绕开CultureInfo相关逻辑,自己实现资源读取:

  1. 把所有AppResources.xx.resx文件的「生成操作」属性设置为嵌入的资源
  2. 实现自定义本地化管理器,缓存所有语言的字符串资源:
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];
    }
}
  1. 所有原来调用AppResources.xxx的地方替换为LocalizationManager.GetString("xxx")即可。

内容的提问来源于stack exchange,提问作者Tanja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 00:36:01