MVVMCross即时更改语言 - IOS / Android

时间:2018-01-05 08:51:34

标签: xamarin.ios xamarin.android localization mvvmcross

我在网上和论坛上搜索了这些 - 发现了这些:

https://forums.xamarin.com/discussion/103572/any-xamarin-ios-code-to-change-the-language-of-the-app-instantly-without-need-to-restart-the-app

http://enginecore.blogspot.in/2013/09/localization-in-xamarin-mvvmcross_18.html

http://opendix.blogspot.in/2013/05/using-resx-files-for-localization-in.html

以及Xamarin Forms的更多内容。

但这些都不是很有希望并且可以动态更改文本(在内部更改文本)。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:0)

对于Android,你可以这样做:

  • 像这样创建自己的contextWrapper:

     public class MyContextWrapper : ContextWrapper
    {
       public MyContextWrapper(Context context) : base(context)          
       {
    
       }
    public static Locale getSystemLocaleLegacy(Configuration config)
    {
        return config.Locale;
    }
    public static Locale getSystemLocale(Configuration config)
    {
        return config.Locales.Get(0);
    }
    public static void setSystemLocaleLegacy(Configuration config, Locale locale)
    {
        config.SetLocale(locale);
        config.SetLayoutDirection(locale);
    }
    public static void setSystemLocale(Configuration config, Locale locale)
    {
        config.SetLocale(locale);
        config.SetLayoutDirection(locale);
    }
    
    public static ContextWrapper wrap(Context context, string language)
    {
        Configuration config = context.Resources.Configuration;
        Locale sysLocale = null;
        if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
        {
            sysLocale = getSystemLocale(config);
        }
        else
        {
            sysLocale = getSystemLocaleLegacy(config);
        }
    
        Locale locale;
    
        if (language == "en")
        {
            locale = new Locale(language, "US");
        }
        else if (language == "zh")
        {
            locale = new Locale(language, "CN");
        }
        else
        {
            locale = new Locale("en", "US");
        }
    
        Locale.Default = (locale);
    
        if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
        {
            setSystemLocale(config, locale);
        }
        else
        {
            setSystemLocaleLegacy(config, locale);
        }
    
        if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBeanMr1)
        {
            context = context.CreateConfigurationContext(config);
        }
        else
        {
            context.Resources.UpdateConfiguration(config, context.Resources.DisplayMetrics);
        }
    
        return new MyContextWrapper(context);
    }
    

    }

  • 将以下代码添加到您的活动中:

     protected override void AttachBaseContext(Context @base)
    {
        try
        {              
        base.AttachBaseContext(MyContextWrapper.wrap(@base,"Your_language"));
        }
    
    }
    
  • 在您的资源中添加您的语言字符串文件及其相应的语言名称,例如对于中文您添加以下值文件夹: values-zh-rCN

有关详细信息,请查看here

<强>更新

  • ios代码:

      public class Localize
    {
       public void SetLocale(CultureInfo ci)
    {
        Thread.CurrentThread.CurrentCulture = ci;
        Thread.CurrentThread.CurrentUICulture = ci;
    
        CultureChanged?.Invoke(this, ci);
    }
    
    public event EventHandler<CultureInfo> CultureChanged = delegate { };
    
    public CultureInfo GetCurrentCultureInfo()
    {
        var netLanguage = "en";
        if (NSLocale.PreferredLanguages.Length > 0)
        {
            var pref = NSLocale.PreferredLanguages[0];
            netLanguage = iOSToDotnetLanguage(pref);
        }
        // this gets called a lot - try/catch can be expensive so consider caching or something
        System.Globalization.CultureInfo ci = null;
        try
        {
            ci = new System.Globalization.CultureInfo(netLanguage);
        }
        catch
        {
            // iOS locale not valid .NET culture (eg. "en-ES" : English in Spain)
            // fallback to first characters, in this case "en"
            try
            {
                var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
                ci = new System.Globalization.CultureInfo(fallback);
            }
            catch
            {
                // iOS language not valid .NET culture, falling back to English
                ci = new System.Globalization.CultureInfo("en");
            }
        }
        return ci;
    }
    
    string iOSToDotnetLanguage(string iOSLanguage)
    {
        var netLanguage = iOSLanguage;
        //certain languages need to be converted to CultureInfo equivalent
        switch (iOSLanguage)
        {
            case "ms-MY": // "Malaysian (Malaysia)" not supported .NET culture
            case "ms-SG": // "Malaysian (Singapore)" not supported .NET culture
                netLanguage = "ms"; // closest supported
                break;
            case "gsw-CH": // "Schwiizertüütsch (Swiss German)" not supported .NET culture
                netLanguage = "de-CH"; // closest supported
                break;
                // add more application-specific cases here (if required)
                // ONLY use cultures that have been tested and known to work
        }
        return netLanguage;
    }
    
    string ToDotnetFallbackLanguage(PlatformCulture platCulture)
    {
        var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars, usually);
        switch (platCulture.LanguageCode)
        {
            case "pt":
                netLanguage = "pt-PT"; // fallback to Portuguese (Portugal)
                break;
            case "gsw":
                netLanguage = "de-CH"; // equivalent to German (Switzerland) for this app
                break;
                // add more application-specific cases here (if required)
                // ONLY use cultures that have been tested and known to work
        }
        return netLanguage;
    }
     }
    
    • 有关步骤的参考,请转到here

答案 1 :(得分:0)

如果您使用MvvmCross和resx PCL,此代码可以正常使用

public class ResxTextProvider : IMvxTextProvider
    {
        private readonly ResourceManager _resourceManager;
        private readonly MvxSubscriptionToken _token;
        IMvxMessenger messenger;

        public ResxTextProvider(ResourceManager resourceManager , string CultureInfoString)
        {
            _resourceManager = resourceManager;
            CurrentLanguage = new CultureInfo(CultureInfoString);

            messenger = Mvx.Resolve<IMvxMessenger>();
            if (messenger != null)
            {
                _token = messenger.Subscribe<languageChangedMessage>(OnlanguageChange);
            }
        }

        private void OnlanguageChange(languageChangedMessage obj)
        {
            CurrentLanguage = new CultureInfo(obj.LangId);
        }