[Unity] Localization에서 Format String 쓰기

화이팅!·2025년 8월 14일

Unity

목록 보기
6/8
post-thumbnail

안녕하세요?
오늘은 Localication 활용 중 Format String 방법을 쓰는 방법에 대해 배워보겠습니다.

사진은 구글 시트에서 작성한 Localize Table인데요. 구글 시트에서 한국어 대사를 적용하면 Translation 함수로 한번에 영어로 번역하고 pull을 통해 유니티로 끌고 올 수 있다고 지난 게시글에서 배웠었죠.

[Unity] Localization, 구글시트 연동하기

그 Localization Table에서 중간에 변하는 데이터를 넣고 싶다면 어떻게 해야 할까요?
(저는 대사 중간에 PlayerPrefs로 저장된 플레이어의 이름과 등장인물의 한/영 버전 이름을 넣고 싶었습니다.)

Smart String으로 할수도 있나요? 저는 처음에 시도했지만 그 방법을 실패하고 다른 방법으로 해냈습니다.

format string 방법입니다.
언어를 공부해보신 분들은 익숙한 방법일 겁니다.
문자열 안에 {0}, {1} 같은 자리 표시자를 넣고, 실제 값을 순서대로 전달하는 방법이죠.


본격적으로 Format String 활용하기

먼저 Localization Table에 위 사진과 같이 format 방식으로({0}, {1}과 같이) 대사를 입력해줍니다.

    IEnumerator ShowDialogue(TextMeshProUGUI textUI, string key)
    {
        var localizedString = new LocalizedString(tableName, key);
        var docNameString = new LocalizedString("LocalTable", "오랑이");
        var beastNameString = new LocalizedString("LocalTable", "짐승덕기");
        var crewNameString = new LocalizedString("LocalTable", "활주미란");
        
        bool done = false;
        bool beastDone = false;
        bool crewDone = false;
        bool docDone = false;

        string docName = null;
        string beastName = null;
        string crewName = null;
        string playerName = PlayerPrefs.GetString("Name", "DefaultName");
        
        docNameString.StringChanged += (value) => { docName = value; docDone = true; };
        while (!docDone)
            yield return null;

        beastNameString.StringChanged += (value) => { beastName = value; beastDone = true; };
        while (!beastDone)
            yield return null;

        crewNameString.StringChanged += (value) => { crewName = value; crewDone = true; };
        while (!crewDone)
            yield return null;
        
        localizedString.Arguments = new List<object>() { docName, crewName, beastName, playerName };

        localizedString.StringChanged += (value) =>
        {
            textUI.text = $"{value}";
            done = true;
        };

        while (!done)
            yield return null;
    }

localizedString.Arguments = new List<object>() { docName, crewName, beastName, playerName };
위 코드에서 쓴 docName, crewName, beastName, playerName이 차례로 테이블에서 작성한 대사의 {0}, {1}, {2}, {3}에 해당할 거라는 걸 눈치채실 수 있겠죠?

var로 가져온 어쩌구NameString은 LocalizedString 객체라서 바로 {n}에 들어갈 수 없습니다. 반드시 .StringChanged와 같은 방법으로 문자열을 받아야 합니다.
localizedString.Arguments의 Arguments에는 실제 문자열이 들어가야 해요.

즉, var 객체의 값을 먼저 가져와야 합니다.

그 방법은 .StringChanged를 통해 값(string)을 가져오는 것입니다.

LocalizedString.StringChanged를 설명해보자면 로컬라이즈된 문자열이 준비되었을 때 알림을 받는 이벤트입니다.
Unity Localization에서 로컬라이즈된 문자열은 즉시 가져올 수 없고, 내부적으로 비동기로 로딩되기 때문에 바로 값이 안 나올 수 있습니다. 그래서 StringChanged 이벤트를 써서 값이 준비되면 처리해야 하는 거죠.
StringChanged는 비동기 이벤트라 코루틴에서 yield로 기다려야 실제 문자열을 안전하게 사용할 수 있어요.

따라서

bool docDone = false;

docNameString.StringChanged += (value) => { docName = value; docDone = true; };
        while (!docDone)
            yield return null;

이런 형태로 값이 준비될 때까지 기다려줍니다.
로컬라이즈된 문자열이 준비가 되면 우리는 Localize Table에 있는 데이터를 (객체->값으로 바꿨기 때문에) Arguments에 집어넣을 수 있고, format 방식으로 화면에 띄울 수가 있게 되는 겁니다!

StartCouroutine(ShowDialogue(TextMeshProUGUI textUI, string key));을 사용하면 바로 대사를 정상적으로 띄울 수 있게 됩니다 ~

{1}: "{0} 의사선생님이 쓰러졌어요! {2} 선생님을 불러주세요!"의 영어버전인
{1}: "Doctor {0} has collapsed! Please call Doctor {2}!"
이 정상적으로 나타난 모습입니다. ^^

localizedString.Arguments = new List<object>() { docName, crewName, beastName, playerName }; 순서대로 작성한 값이 대사에 들어갑니다.


자 오늘은 Localication 활용 중 Format String 방법을 쓰는 방법에 대해 알아보았는데요. 이 정도라면 Localization을 통해 웬만한 대사의 다중언어 적용은 가능할 것으로 보여집니다.

저는 Smart String을 꼭 자유자재로 쓰고 싶은데 (banana=1이라면 banana로 출력되고, 2이상이라면 bananas로 출력하는 게 멋있어보입니다.)
아직 많이 부족하고 어렵네요.

그래도 포기하지 않고 열심히 해볼겁니다~ 파이팅!

0개의 댓글