【问题标题】:Android image localisation in Xamarin FormXamarin Form 中的 Android 图像本地化
【发布时间】:2020-12-20 08:13:22
【问题描述】:

我有一个 Xamarin Form 应用程序,它有一个语言下拉菜单,因此用户可以选择应用程序语言。当用户选择我调用的语言时:

            CultureInfo culture = CultureInfo.CreateSpecificCulture(language);
            System.Globalization.CultureInfo.CurrentUICulture = culture;
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;
            AppResources.Culture = culture;

应用程序运行良好并从 AppResources.{language}.resx 中挑选字符串 我的问题是本地化图像时。根据微软的建议,我已将我的图像添加到 android 项目内的 Resources/drawable 文件夹中。就我而言,我将thanks.jpg 添加到Resources/drawable 和Resources/drawable-fr。但是即使我选择 fr-FR 作为语言,它也只会在 Resources/drawable 文件夹上显示图像,但是我发现如果不是更改应用程序语言(文化),而是更改设备语言,设备显示正确的图像( Resources/drawable-fr 中的图像)。我想知道是否有任何方法可以解决这个问题。

【问题讨论】:

    标签: xamarin xamarin.forms xamarin.android


    【解决方案1】:

    你可以创建一个依赖服务来修复它。

    首先,创建一个接口。

        public interface IChangeService
        {
            void ChangeIanguage(string lang);
        }
    

    我们在 xamarin 表单的这种格式代码中使用了它。

      <StackLayout>
            <TimePicker></TimePicker>
            <Image WidthRequest="100">
                <Image.Source>
                    <OnPlatform x:TypeArguments="ImageSource">
                        <On Platform="iOS, Android" Value="flag.png" />
                        <On Platform="UWP" Value="Assets/Images/flag.png" />
                    </OnPlatform>
                </Image.Source>
                </Image>
                <Button Text="Change" Clicked="Button_Clicked"></Button>
        </StackLayout>
    

    这是后台代码。

     public partial class LocalizedXamlPage : ContentPage
        {
            public LocalizedXamlPage()
            {
                InitializeComponent();
            }
    
            private void Button_Clicked(object sender, System.EventArgs e)
            {
                DependencyService.Get<IChangeService>().ChangeIanguage("en");
            }
        }
    

    然后在android平台上实现接口。如果我们更改本地化,我们需要它在运行时工作,我们应该重新启动我们的应用程序。

    [assembly: Dependency(typeof(ChangeLanguageService))]
    namespace UsingResxLocalization.Droid
    {
        public class ChangeLanguageService : IChangeService
        {
            public void ChangeIanguage(string lang = "in")
            {
               
                LanguageManager.ChangeLanguage(MainActivity.instance, lang);
                //restart your application.
                Intent intent = new Intent(MainActivity.instance, typeof(MainActivity));
                intent.SetFlags(ActivityFlags.ClearTask | ActivityFlags.NewTask);
                MainActivity.instance.StartActivity(intent);
            }
        }
    }
    

    然后我们需要创建一个BaseActivity(因为我们在android中更改了Locale,所以我们应该使用相同的Context。)和LanguageManager(在运行时更改本地化)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Android.App;
    using Android.Content;
    using Android.OS;
    using Android.Runtime;
    using Android.Support.V7.App;
    using Android.Views;
    using Android.Widget;
    using Java.Util;
    using Xamarin.Forms.Platform.Android;
    
    namespace UsingResxLocalization.Droid
    {
        public class BaseActivity : FormsAppCompatActivity
        {
            protected override void AttachBaseContext(Context @base)
            {
                base.AttachBaseContext(LanguageManager.LoadLanguage(@base));
            }
    
        }
    
        public class LanguageManager
        {
            private const string MYLANGUAGE = "myLanguage";
            private const string MYPREF = "myPreference";
    
            public static Context LoadLanguage(Context context)
            {
                var loadedLanguage = GetLanguage(context, Locale.Default.Language);
                return ChangeLanguage(context, loadedLanguage);
            }
    
            public static Context ChangeLanguage(Context context, string language)
            {
                SaveLanguage(context, language);
                if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
                {
                    return ChangeForAPI24(context, language);
                }
                return ChangeForLegacy(context, language);
            }
    
            private static string GetLanguage(Context context, string Language)
            {
                var privatePreference = context.GetSharedPreferences(MYPREF, FileCreationMode.Private);
                return privatePreference.GetString(MYLANGUAGE, Language);
            }
    
            private static void SaveLanguage(Context context, string language)
            {
                var privatePreference = context.GetSharedPreferences(MYPREF, FileCreationMode.Private);
                var editor = privatePreference.Edit();
                editor.PutString(MYLANGUAGE, language);
                editor.Apply();
            }
    
            private static Context ChangeForAPI24(Context context, string language)
            {
                // for api >= 24
                var locale = new Locale(language);
                Locale.Default = locale;
                var configuration = context.Resources.Configuration;
                configuration.SetLocale(locale);
                configuration.SetLayoutDirection(locale);
    
                return context.CreateConfigurationContext(configuration);
            }
    
            private static Context ChangeForLegacy(Context context, string language)
            {
                var locale = new Locale(language);
                Locale.Default = locale;
                var resources = context.Resources;
                var configuration = resources.Configuration;
                configuration.Locale = locale;
                resources.UpdateConfiguration(configuration, resources.DisplayMetrics);
                return context;
            }
        }
    }
    

    使 mainAcitvity 扩展 BaseActivity.cs。并暴露 public static MainActivity instance;,

     [Activity(Label = "UsingResxLocalization", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
        public class MainActivity : BaseActivity
        {
            public static MainActivity instance;
            protected override void OnCreate(Bundle savedInstanceState)
            {
                TabLayoutResource = Resource.Layout.Tabbar;
                ToolbarResource = Resource.Layout.Toolbar;
                instance = this;
                base.OnCreate(savedInstanceState);
    
                global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
                LoadApplication(new App());
            }
        }
    

    这是正在运行的 GIF。

    ========更新==========

    当设备语言为英语时,我通过将语言更改为 fr 来测试法国国旗。

    我把我的demo上传给你,你可以测试一下。

    https://github.com/851265601/LocalzationDemo/blob/master/LocalzationDemoWithFlag.zip

    如果你想改变Button或其他标签的文字,当你点击Button时,请在点击事件中添加CultureInfo.CurrentUICulture = new CultureInfo("fr", false);。你可以看到这个 GIF。

    【讨论】:

    • 如果以上回答对您有帮助,请不要忘记采纳为回答(点击此回答左上角的“✔”),对有类似问题的人会有所帮助
    • 它对我不起作用。让我们简单点。当设备语言为英语时,我想通过将语言更改为 fr 来查看法国国旗。我尝试了 ChangeForAPI24 和 ChangeForLegacy,但它们都不起作用
    • 我用我的演示用法国国旗做了一个测试,它成功了。你可以看到我的更新答案。
    • @LeonLu-MSFT 为了更好地说明,您可以更改显示按钮文本的语言吗?它只是显示标志的变化,但令人困惑的是它是否真的改变了应用程序的语言。
    • @Blu 谢谢你的建议,我改了答案。
    猜你喜欢
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    相关资源
    最近更新 更多