ボタンを押した時に、文字列が日本語から英語に(またはその逆に)切り替わるようにします。
※今回の記事は、前回の記事からの抜粋です。
tomo-mana.hatenablog.com
構成
言語切り替えボタンと、切り替える対象となるテキスト、ボタンで構成されていることを想定します。
言語切り替えのボタンを押した時に、対象のコンポーネントにメッセージが飛んで、言語毎の表示に切り替わるようにします。
メッセージにはExecuteEvents
を使用します。
クラス関係
文字列IDと文字列(GlobalString
)、メッセージ(ILangSwitchHandler
)を受け取るコンポーネント(LangSwitchComponent
)で構成します。
メッセージを飛ばすボタンはグループにします(LangSwitch
)。
コンポーネントは、任意のテキストまたはボタンに取り付けることができます。表示する文字は文字列ID(enum NAME_ID
)で指定します。
テキストはTextMeshPro
を想定しています。
オブジェクトの構成
コード
言語テーブル (GlobalString)
public enum LANG { LANG_JPN = 0, LANG_ENG, LANG_MAX }; public enum NAME_ID { NAME_ID_CASH = 0, NAME_ID_FLA, : NAME_ID_MAX }; public class GlobalString { public class LangNames { public string jpn; public string eng; public LangNames(string jp, string en) { this.jpn = jp; this.eng = en; } }; static LangNames[] langNames = { new LangNames( "現金", "Cash" ), new LangNames( "流動資産", "Flex.Assets" ), : }; public static LANG selectedLang = LANG.LANG_JPN; public static string GetStrLang( NAME_ID id ) { if( selectedLang == LANG.LANG_ENG ){ return (langNames[(int)id]).eng; } else { return (langNames[(int)id]).jpn; } } }
スイッチ(LangSwitch)
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; // メッセージハンドラ public interface ILangSwitchHandler : IEventSystemHandler { void LangSelected(LANG selectedLang); } public class LangSwitch : MonoBehaviour { void ILangSwitchHandlerCallback(ILangSwitchHandler receiver, BaseEventData eventData) { receiver.LangSelected( GlobalString.GetSelectedLang() ); } void ChangeLanguage( GameObject gameobject ) { // 子から先に(再帰) foreach( Transform child in gameobject.transform ){ ChangeLanguage( child.gameObject ); } // 言語切り替わったメッセージ ExecuteEvents.Execute<ILangSwitchHandler>( target: gameobject, eventData: null, functor: ILangSwitchHandlerCallback ); } void ButtonClicked(int buttonNo) { GlobalString.SetSelectedLang( (LANG)buttonNo ); foreach( GameObject root in gameObject.scene.GetRootGameObjects() ) { if( root.GetComponent<Canvas>() ){ foreach( Transform child in root.transform ){ ChangeLanguage( child.gameObject ); } } } } // Start is called before the first frame update void Start() { int i = 0; Button button; foreach( Transform child in gameObject.transform ){ button = child.gameObject.GetComponent<Button>(); if( !ReferenceEquals(button, null) ){ int ii = i; button.onClick.AddListener(() => ButtonClicked(ii)); i++; } } ButtonClicked(0); } }
コンポーネント(TextMeshPro または Button - TextMeshPro)
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro; public class LangSwitchComponent : MonoBehaviour, ILangSwitchHandler { [SerializeField] NAME_ID label = default; TextMeshProUGUI textArea; public void SetLanguage() { if( !ReferenceEquals( textArea, null ) ){ textArea.text = GlobalString.GetStrLang( label ); } } public void LangSelected(LANG selectedLang) { SetLanguage(); } // Start is called before the first frame update void Start() { if( (textArea = gameObject.GetComponent<TextMeshProUGUI>()) == null ){ foreach( Transform trans in gameObject.transform ){ if( trans.gameObject.GetComponent<TextMeshProUGUI>() ){ textArea = trans.gameObject.GetComponent<TextMeshProUGUI>(); break; } } } if( textArea != null ){ SetLanguage(); } } // Update is called once per frame void Update() { } }
コンポーネントは取り付けた後、文字列IDだけ選択しておきます。
拡張 (ILangSwitchHandlerインターフェース)
LangSwitch.cs
は LangSwitchComponent
が自分の下位層にあるすべてのTextMeshProUGUI
を捜索してテキスト領域を書き変える処理をします。同じTMPro
パッケージでもTextMeshProUGUI
でない InputField
などには対応していません(継承関係はそのうち調べます)。これらのクラスにも言語切替を通知するには、通知を受け取りたいゲームオブジェクトに ILangSwitchHandler
を実装します。void LangSelected( LANG )
インターフェースで、言語が切り替わった(または据え置きかもしれませんが)ことを知ることができます。
課題
●あまり長い文字列向けにはなっていない(容量の最適化)
●printf()
などで使われるようなフォーマット指定子などは対応していない
(以上)