夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

HoloLensアプリを多言語対応する

本日はHoloLensアプリ表現の調査枠です。

先日よりYubimoziHoloLensのリリースに向け機能を実装しています。

今回は海外での利用も想定し多言語化対応の仕組みを実装します。

〇デバイスの言語を取得する

UnityではApplication.systemLanguageを使用することでデバイスのシステムが使用している言語を取得することができます。

日本語ではJapaneseが返されます。

これを利用して日本語とその他の言語(英語)で設定を行えるようにしました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LangageManager : MonoBehaviour
{
    public bool _isJapaneese=false;
    public bool _isEnglish=false;
    // Start is called before the first frame update
    void Start()
    {
        string lang = Application.systemLanguage.ToString();
        //select App UI laungage from system laungage
        if (lang == "Japanese")
        {
            _isJapaneese = true;
        }
        else
        {
            _isEnglish = true;
        }
    }
}

LangageManagerコンポーネントをシーンに一つ配置しておくことで日本語を使用するか、英語を使用するかを自動的に分けることができます。

テキストや今回の場合Azure Speech to Textで使用する言語をLangageManager._isJapaneeseで取得することで英語、日本語で分けることができます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Translation;
using Microsoft.MixedReality.Toolkit.UI;
using TMPro;

public class Translatio : MonoBehaviour
{
 public TextMeshPro recognizedText;
    public TextMeshPro translatedText;
    public PressableButton micButton;

    public string SpeechServiceSubscriptionKey = "";
    public string SpeechServiceRegion = "";

    private bool waitingforReco;
    private string recognizedString;
    private string translatedString;

    private bool micPermissionGranted = false;

    private object threadLocker = new object();
    [SerializeField]
    private LangageManager _lm;
    public async void ButtonClick()
    {
        var translationConfig = SpeechTranslationConfig.FromSubscription(SpeechServiceSubscriptionKey, SpeechServiceRegion);
         
        if (_lm._isJapaneese)
        {
            translationConfig.SpeechRecognitionLanguage = "ja-JP";   
        }
        else
        {
            translationConfig.SpeechRecognitionLanguage = "en-US";
        }
        translationConfig.AddTargetLanguage("fr");

        using (var recognizer = new TranslationRecognizer(translationConfig))
        {
            lock (threadLocker)
            {
                waitingforReco = true;
            }

            var result = await recognizer.RecognizeOnceAsync().ConfigureAwait(false);

            if (result.Reason == ResultReason.TranslatedSpeech)
            {
                recognizedString = result.Text;
                foreach (var element in result.Translations)
                {
                    translatedString = element.Value;
                }
            }
            else if (result.Reason == ResultReason.NoMatch)
            {
                recognizedString = "NOMATCH: Speech could not be recognized.";
            }
            else if (result.Reason == ResultReason.Canceled)
            {
                var cancellation = CancellationDetails.FromResult(result);
                recognizedString = $"CANCELED: Reason={cancellation.Reason} ErrorDetails={cancellation.ErrorDetails}";
            }
            lock (threadLocker)
            {
                waitingforReco = false;
            }
        }
    }


    // Start is called before the first frame update
    void Start()
    {
        if (translatedText == null)
        {
            UnityEngine.Debug.LogError("translatedText property is null! Assign a UI TextMeshPro Text element to it.");
        }
        else if (micButton == null)
        {
            UnityEngine.Debug.LogError("micButton property is null! Assign a MRTK Pressable Button to it.");
        }
        else
        {
            micPermissionGranted = true;
            micButton.ButtonPressed.AddListener(ButtonClick);
        }
    }

    // Update is called once per frame
    void Update()
    {
        lock (threadLocker)
        {
            recognizedText.text = recognizedString;
            translatedText.text = translatedString;
        }
    }
}

UIなどのテキストはこちらのコンポーネントをアタッチします。

f:id:Holomoto-Sumire:20220306203111p:plain

PressableButton HoloLens 2などはButtonConfigHelper経由でテキストを変えているため専用の変換処理を行っています。

using System.Collections;
using System.Collections.Generic;
using Microsoft.MixedReality.Toolkit.UI;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
using Microsoft.MixedReality.Toolkit.UI;

public class TextTranslation : MonoBehaviour
{
     TextMeshPro text;
     private string stext;
     [SerializeField] private LangageManager _lm;

     [SerializeField]
     private string _japaneeseText;

     bool appLaungjapa;
     bool appLaungEng;
     [SerializeField] private string _englishText;

     [SerializeField] private bool _isFlatTmpText;
     [SerializeField] private bool _isHLButton;
     
    // Start is called before the first frame update
    void Start()
    {

        if (_isFlatTmpText)
        {
            FlatTmpText();
        }

        if (_isHLButton)
        {
            HoloLensButtonText();
        }
    }

    public  void FlatTmpText()
    {
        text = this.GetComponent<TextMeshPro>();
        appLaungjapa  = _lm._isJapaneese;
        appLaungEng = _lm._isEnglish;
        Debug.Log(appLaungjapa);
        if (appLaungjapa)
        {
            text.text = _japaneeseText;
            Debug.Log("Japaneese");
        }
        else
        {
            text.text = _englishText;
            Debug.Log("English");
        }
    }

    public void HoloLensButtonText()
    {
        stext = this.GetComponent<ButtonConfigHelper>().MainLabelText;
          
        appLaungjapa  = _lm._isJapaneese;
        appLaungEng = _lm._isEnglish;
        if (appLaungjapa)
        {
            stext = _japaneeseText;
            Debug.Log("Japaneese");
        }
        else
        {
            stext = _englishText;
            Debug.Log("English");
        }        
    }
}