Xamarin.Android에서 앱 언어를 동적으로 전환

여러 언어의 리소스를 준비해 두고 시스템의 언어를 바꾸면 앱에서 사용하는 언어 리소스도 바뀌는데, 시스템 설정에 관계없이 앱 내에서 언어 선택을 하고 싶다.
즉,
  • java - Android N change language programmatically - Stack Overflow

  • 이것.
    Kotlin에서도 할 수 있었으므로, 어차피라면 하는 것으로 Xamarin.Android에서도 해 보았습니다.

    완성



    이런 느낌의 성과가 됩니다.



    방법



    1. 다국어용 리소스 파일 준비



    Android 사양에 따라 values/ 또는 values-ja-rJP/String.xml를 제공합니다.
    파일을 추가한 후 Build Action이 "AndroidResource"로 설정되어 있는지 확인하십시오.

    values/String.xml (영어 또는 기본값):
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">ResourceTest</string>
    
        <string name="welcome">WELCOME</string>
        <string name="to_japanese">To Japanese</string>
        <string name="to_english">To English</string>
    </resources>
    

    values-ko-rJP/String.xml(한국어):
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">ResourceTest</string>
    
        <string name="welcome">ようこそ</string>
        <string name="to_japanese">日本語にする</string>
        <string name="to_english">英語にする</string>
    </resources>
    

    2. MainActivity 구현



    우선 ざっと.

    MainActivity.cs:
    using Android.App;
    using Android.Widget;
    using Android.OS;
    using Android.Content;
    using Android.Content.Res;
    using Java.Util;
    using System.Linq;
    using System;
    
    namespace ResourceTest
    {
        [Activity(Label = "ResourceTest", MainLauncher = true, Icon = "@mipmap/icon")]
        public class MainActivity : Activity
        {
            protected override void AttachBaseContext(Context baseContext)
            {
                var pref = baseContext.GetSharedPreferences("mypref", FileCreationMode.Private);
    
                var locale = pref.GetString("locale", string.Empty);
                var newLocale = Locale.GetAvailableLocales().FirstOrDefault(
                    l => string.Equals(l.ToString(), locale, StringComparison.OrdinalIgnoreCase))
                                      ?? Locale.Default;
    
                var configuration = baseContext.Resources.Configuration;
                configuration.Locale = newLocale;
                var newContext = new ContextWrapper(
                    baseContext.CreateConfigurationContext(configuration));
    
    
                base.AttachBaseContext(newContext);
            }
    
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
                SetContentView(Resource.Layout.Main);
    
                FindViewById<TextView>(Resource.Id.textWelcome).Text = Resources.GetString(Resource.String.welcome);
    
                var pref = this.GetSharedPreferences("mypref", FileCreationMode.Private);
    
                FindViewById<Button>(Resource.Id.buttonToEnglish).Click += (sender, e) => 
                {
                    var editor = pref.Edit();
                    editor.PutString("locale", "en_US");
                    editor.Commit();
                    Restart();
                };
    
                FindViewById<Button>(Resource.Id.buttonToJapanese).Click += (sender, e) =>
                {
                    var editor = pref.Edit();
                    editor.PutString("locale", "ja_JP");
                    editor.Commit();
                    Restart();
                };
            }
    
            private void Restart()
            {
                var intent = new Intent(this, typeof(MainActivity));
                this.Finish();
                this.StartActivity(intent);
            }
        }
    }
    

    간단히 설명하면 "AttachBaseContext() 을 override 하고, 거기서 임의의 Locale 로 바꾼 Context 로 대체"하고 있습니다.

    임의의 Locale은 두 개의 버튼을 누를 때 각각 ja_JPen_US를 SharedPreference에 저장하고 Activity를 다시 시작합니다.

    재시작 직후에 AttachBaseContext() 가 불리기 때문에, 거기서 SharedPreference 에 기억된 Locale 를 읽어내고 있습니다.



    1st try에서는, SharedPref 를 사용하는 것을 귀찮게 해서, Application 클래스에 기억시키려고 작전이었지만, 실패했습니다. 그 원인은 AttachBaseContext()OnCreate() 보다 먼저 불려 갔고, AttachBaseContext() 시점에서는 Activity.Applicationnull 가 되어 있기 때문이었습니다.

    좋은 웹페이지 즐겨찾기