タイトルでだいたい説明した感じですが、ポイントとしては、
- TagProcessorクラスを介することでタグ解釈ができる(後述)
- UnityEngine.UI.Textのtextに$$で始まるキーを入れておくと、対応する訳を入れてくれる
- Resources.FindObjectsOfTypeAll
()でヒエラルキーをなめて、Textに翻訳データをぶち込む
といった感じです。
さっそくですがサンプルプロジェクトを以下に置きました。(Unity version 5.3.5f1 )
github.com
以下、説明していきます。
TranslateManagerのソースはこのようになっています。(今は日本語と英語だけに対応しています。)
using UnityEngine; using UnityEngine.UI; using System.Collections.Generic; using System.Xml; public class TranslateText { public string jp; public string eng; public TranslateText( string jp_, string eng_ ) { jp = jp_; eng = eng_; } } public class TranslateManager : Singleton< TranslateManager > { private Dictionary<string, TranslateText> texts = new Dictionary<string, TranslateText>(); ITagProcessor tagProcessor = null; //------------------------------------------------------------------------------ //Resourceフォルダ以下にあるExcelデータを読み込む public void Read( string path ) { TextAsset text_asset = Resources.Load<TextAsset>(path); Debug.Assert( text_asset != null ); XmlDocument xmldoc = new XmlDocument (); xmldoc.LoadXml ( text_asset.text ); var nsmgr = new XmlNamespaceManager(xmldoc.NameTable); nsmgr.AddNamespace("ss", "urn:schemas-microsoft-com:office:spreadsheet"); XmlNodeList rows = xmldoc.GetElementsByTagName("Row"); foreach (XmlNode row in rows){ XmlNodeList datas = row.SelectNodes("ss:Cell/ss:Data", nsmgr); string key = datas[0].InnerText; string jp = datas[1].InnerText; string eng = datas[2].InnerText; //改行コードを変換する //手元のExcelを使ってxml形式で保存すると改行が\r(CR)になっているので、 //それを変換する jp = jp.Replace( "\r", "\n" ); eng = eng.Replace( "\r", "\n" ); texts[ key ] = new TranslateText( jp, eng ); } } //------------------------------------------------------------------------------ //ヒエラルキーにあるテキスト仕込んだキーから変換 public void ApplyAllUIText() { Text[] text_components = Resources.FindObjectsOfTypeAll<Text>(); for (var i = 0; i < text_components.Length; ++i) { InterpretText( ref text_components[i] ); } } //------------------------------------------------------------------------------ //タグプロセッサーを設定 public void SetTagProcessor( ITagProcessor processor ) { tagProcessor = processor; } //------------------------------------------------------------------------------ //キーからテキスト取得 public string GetText( string key ) { string str = getTextRaw(key); if( tagProcessor != null ) { str = tagProcessor.Process( str ); } return str; } //------------------------------------------------------------------------------ //Textクラスを与えて、キーが入ってたら翻訳データを挿入 public void InterpretText( ref Text t ) { if( t.text.StartsWith( "$$" ) ) { string key = t.text.Substring(2).TrimEnd();//たまに間違って改行が入っている場合があって気づきにくいのでTrimEndしておく t.text = GetText( key ); } } //------------------------------------------------------------------------------ //タグ解釈していない、そのままのテキスト取得 private string getTextRaw( string key ) { // Debugしやすいように Application.systemLanguage を直接見ずにConfigというクラス経由で参照 if( Config.Language == SystemLanguage.Japanese ) { return texts[key].jp; } else { return texts[key].eng; } } }
Excelの翻訳データはこんな感じになっています。1列目がキー、2列目が日本語訳、3列目が英語訳です。
使い方としては、Editor上で、こんな感じで$$から始まるキーを打ち込んでおきます。
そんで、ゲームが起動した直後に、
tagProcessor = new TagProcessor();//タグプロセッサー作成 TranslateManager.Instance.SetTagProcessor( tagProcessor );//タグプロセッサー設定 TranslateManager.Instance.Read( "Text/texts" );//Resourcesから読み込む TranslateManager.Instance.ApplyAllUIText();//ヒエラルキーにある全Textに適用する
としておくと、
このように、対応した翻訳データに置き換わります。
また、Scriptで直接キーを指定して翻訳データをとってきたい場合には、
string text = TranslateManager.Instance.GetText( "1001" );
っとすることで取得できます。
TagProcessorとは?
先ほどのExcelデータの中で、#{MovieAward}っとなっている部分がタグです。
ゲームを作っていると文字列の中に変数を埋め込みたい時があります。
例えば、動画を見た時にコインをゲットできるけど、そのコイン枚数はレベルによって変わる。っという場合を考えてみます。
単純に考えると、レベルの数だけ文章を用意すれば良いということになります。すると、
- 10枚コインゲット!, You got 10 coins!
- 20枚コインゲット!, You got 20 coins!
- 40枚コインゲット!, You got 40 coins!
- ...
っと大量の翻訳データが必要になってしまいます。
それを、解決してくれるのがTagProcessorです。Excelに
Key | #{MovieAward}枚コインゲット! | You got #{MovieAward} coins!
と書いておき、TagProcessorの中で以下のように記述しておきます。
public class TagProcessor : ITagProcessor { protected int movieAward; public void SetMoviewAward( int award ) { movieAward = award; } //タグを処理する public string Process( string text ) { const string cTagWatchingMovieAward = "#{MovieAward}"; if( text.Contains( cTagWatchingMovieAward ) ) { //タグを置き換える text = text.Replace( cTagWatchingMovieAward, movieAward.ToString() ); } return text; } }
そして、TagProcessorに与える予定の枚数をSetMoviewAwardで与えておいて、
TranslateManager.Instance.GetText( Key )
っとすると、状況に応じた枚数の入った文章をゲットすることができます。
ちなみに、ITagProcessorの中身はこれだけです。
using UnityEngine; using System.Collections; public interface ITagProcessor { string Process( string text ); }
上記を利用して作ったアプリです!良かったらダウンロードお願いします!