Today's

길을 나서지 않으면 그 길에서 만날 수 있는 사람을 만날 수 없다

모바일 앱(안드로이드)

Google Cloud Translate V2 을 활용해서 strings.xml 을 번역해 보겠습니다.

Billcorea 2025. 2. 7. 15:35
반응형

Google Cloud Translate V2 을 활용해서 strings.xml 을 번역해 보겠습니다.

 

배경 설명

 

다국적(?) 앱을 만들어 볼 요량으로 여러버 시도했던 이야기를 다시 해 보겠습니다.  이제 우리앱은 다양한 언어를 구현하는 앱으로 발전하게 될 것 입니다. 

 

다국어 버전의 앱

 

우리가 작성하는 앱이 이렇게 구현이 된다면 어떤 느낌이 들까요 ???   기본적으로 앱을 구현할 떄 영어 버전과  우리말 버전은 잘 만들어 집니다. 하지만, 다른 언어를 활용하는 앱을 구현 하는 것 다른 이야기 이지 않을 까 합니다. 

 

이제 만들어진 한국어 버전의 strings.xml 을 보겠습니다. 

 

<resources>
    <string name="app_name">취업 검색, 다국어 지원</string>
    <string name="todayTitle">일자리 리스트</string>
    <string name="msgToday">구직자분들은 원하시는 공고를 클릭해서 자세한 정보를 확인해주시기 바랍니다.</string>
    <string name="workInfo">작업\n정보</string>
    <string name="workPlace">직장\n장소</string>
    <string name="title_activity_google_login">구글 로그인</string>
    <string name="doRegister">등록 ?</string>
    <string name="doLogout">로그아웃</string>
    <string name="mesgRegistorOnlyGoogle">이 앱의 사용자는 Google 계정만 등록합니다.</string>
    <string name="addChatRoom">채팅방 만들기 ?</string>
    <string name="titleChatRoom">채팅방</string>
    <string name="titleMakeChatRoom">채팅방 만들기</string>
    <string name="mesgMakeChatRoom">채팅방을 만드시겠습니까?</string>
    <string name="OK">확인</string>
    <string name="CANCEL">취소</string>
    <string name="TITLE">제목</string>
    <string name="ROOMNAME">방이름</string>
    <string name="ROOMNO">방 번호</string>
    <string name="entryRoomNm">방 이름 입력</string>
    <string name="entryTitle">제목을 입력하세요</string>
    <string name="saveCompleted">저장 완료</string>
    <string name="title_activity_setting">환경</string>
    <string name="title_translate_ty">언어 번역</string>
    <string name="msgAutoTranslate">자동 번역</string>
    <string name="msgTranslateNo">번역된 언어가 보이지 않습니다</string>
    <string name="title_master_language">당신의 언어?</string>
    <string name="localTime">현지 시간</string>
    <string name="msgNonOwner">당신은 이 방을 만든 사용자가 아닙니다.</string>
    <string name="msgGuestExists">이 방에는 채팅을 하는 사용자가 있습니다.</string>
    <string name="msgLogOutClickAgain">로그아웃하시겠습니까?</string>
    <string name="msgDontGetPicutre">사진을 얻지 마세요</string>
    <string name="profileImage">사용자정보</string>
    
    
    --- 중략 ---
    
    <string name="longClickToMoveMarker">지정할 위치를 길게 클릭하세요</string>
    <string name="msgNotFoundAddress">주소를 찾을 수 없습니다.</string>
    <string name="msgReadyUpdate">이 앱의 새로운 기능 사용을 위한 새로운 버전이 확인 되었습니다. 새 버전을 사용할까요?</string>
    <string name="msgUpdateCompleted">새로운 버전을 사용할 준비가 완료 되었습니다.  앱을 다시 시작 하세요.새로운 버전을 사용할 준비가 완료 되었습니다.  앱을 다시 시작 하세요.</string>
    <string name="msgRequestPasswordEtc">채팅방 비밀번호 요청을 진행할까요???</string>
    <string name="readyDate">업무개시가능일자 : %s</string>
    <string name="sendChatReq">대화참여요청</string>
    <string name="RequestJoinChat">채팅방 참여 요청</string>
    <string name="msgRequestJoinChat">이 사용자 에게 채팅방 참여를 요청 할까요?</string>
    <string name="msgBeforeSaveProfile">먼저 사용자 정보를 저장해야 합니다.</string>
    <string name="menuReqList">비밀번호요청목록</string>
    <string name="arrowBack">뒤로가기</string>
    <string name="Save">저장</string>
    <string name="baseAddress">기본주소: %s</string>
</resources>

 

 

영어버전의 strings.xml 에는 영어로 등록 합니다. android studio 에서 다국어 버전을 만들기 위해서  한국어 부터 추가해 등록 합니다. 

 

android studio 번역 선택

 

추가(+)을 클릭하고 추가 하고자 하는 언어을 선택 하면 됩니다.   그러면 기본적인 폴더들이 생성이 될 것 같습니다.

 

번역기 구현해 보기

코드 구현은 python 으로 해 보겠습니다.  그래야 PC 에서 활용하기 수월 하기도 하고 이런 저런 추가 작업이 필요한 경우 원할하게 해 볼 수 있습니다. 

 

from google.cloud import translate_v2 as translate
import os
import html
import requests

locale=["ko","us","ja","zh","vi","in","ar","bn","de","es","fr","hi","it","ms","nl","pt","ru","th","tr"]
gcLocale=["ko","en","ja","zh","vi","id","ar","bn","de","es","fr","hi","it","ms","nl","pt","ru","th","tr"]
target=["ko-rKR","","ja-rJP","zh-rCN","vi-rVN","in-rID","ar-rAE","bn-rIN","de-rDE","es-rES","fr-rFR","hi-rIN","it-rIT","ms-rMY","nl-rNL","pt-rPT","ru-rRU","th-rTH","tr-rTR"]
# 서비스 계정 키 파일 경로 설정 (다운로드한 JSON 파일 경로)
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = './multichat-a2026-a5e95fece213.json'

def translate_text(target: str, text: str):
    """Translates text into the target language.

    Target must be an ISO 639-1 language code.
    See https://g.co/cloud/translate/v2/translate-reference#supported_languages
    """
    requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)

    translate_client = translate.Client()
    text = text.replace('\n','')
    if isinstance(text, bytes):
        text = text.decode("utf-8")

    # Text can also be a sequence of strings, in which case this method
    # will return a sequence of results for each text.
    result = translate_client.translate(text, target_language=target)

    # print("Text: {}".format(result["input"]))
    # print("Translation: {}".format(result["translatedText"]))
    # print("Detected source language: {}".format(result["detectedSourceLanguage"]))

    rValue = result["translatedText"]
    rValue = html.escape(rValue)
    print('trans:', rValue)
    return rValue


srcDir='C:/Users/nari4/AndroidStudioProjects/multichat416_v2/app/src/main/res'
tarDir='C:/Users/nari4/AndroidStudioProjects/multichat416_v2/images/res'

for loc in locale:
    if loc == 'ko': continue
    if loc == 'us': continue
    print(locale.index(loc), gcLocale[locale.index(loc)], target[locale.index(loc)])

    f=open(os.path.join(srcDir, 'values-ko-rKR/strings.xml'), 'r', encoding='UTF-8')
    if os.path.isdir(os.path.join(tarDir, 'values-' + target[locale.index(loc)])):
        pass
    else:
        os.mkdir(os.path.join(tarDir, 'values-' + target[locale.index(loc)]))
    wf=open(os.path.join(tarDir, 'values-'+target[locale.index(loc)],'strings.xml'), 'w', encoding='UTF-8')
    multiLineTy = False
    passTy=False
    sTitle=''
    while True:
        line = f.readline()
        if not line: break
        if '<string' in line and '</string' in line and '<![CDATA' not in line:
            print(line.split('"')[1], line.split('<')[1].split('<')[0].split('>')[1])
            wf.write('<string name="{0}">{1}</string>\n'.format(line.split('"')[1], translate_text(gcLocale[locale.index(loc)], line.split('<')[1].split('<')[0].split('>')[1])))
        elif '<string' in line and '</string' in line and '<![CDATA' in line:
            print(line.split('"')[1], line.split('<![CDATA[')[1].split(']]')[0])
            wf.write('<string name="{0}">{1}</string>\n'.format(line.split('"')[1], translate_text(gcLocale[locale.index(loc)], line.split('<![CDATA[')[1].split(']]')[0])))
        elif 'translatable="false' in line and '<string' in line and '</string' not in line:
            passTy=True
        elif '<string' in line and '</string' not in line:
            multiLineTy = True
            sTitle=line.split('"')[1]
            print(line.split('"')[1], line.split('>')[1])
            wf.write('<string name="{0}">{1}\n'.format(line.split('"')[1], translate_text(gcLocale[locale.index(loc)], line.split('>')[1])))
        elif multiLineTy and '<string' not in line and '</string' not in line:
            print(line)
            wf.write('{0}\n'.format(translate_text(gcLocale[locale.index(loc)], line)))
        elif multiLineTy and '<string' not in line and '</string' in line:
            multiLineTy = False
            wf.write('</string>\n')
        elif passTy and '</string' in line:
            passTy=False
        elif passTy:
            pass
        elif 'translatable="false' in line:
            pass
        else:
            if line != '':
                print(line)
                wf.write(line+'\n')
    f.close()
    wf.close()
    print(loc, '------------------------- End Next...')

print('End All Job...')

 

위 코드는 한국어 버전의 strings.xml 을 기반으로 다른 언어 버전으로 번역을 자동화 하기 위한 python 코드 입니다. 

strings.xml 의 구조는 resouces 태그 사이에 string 태크들이 들어 있는 구조을 가지고 있습니다. 

 

물론 string 태크 사이에는 한줄에 끝나는 것도 있지만, 여러줄에 나누어져 있는 것도 있습니다.  그것들을 활요하기 위해서 코드 구현을 해 보았습니다. 

 

source 을 보면

os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = './multichat-a2026-a5e95fece213.json'

 

google service key 가 들어 있는 파일을 가지고 있어야 합니다.  이 것을 얻기 위해서는 firebase 에서 프로젝트을 생성하고 프로젝트 정보에서 서비스 키을 받아올 수 있어야 합니다. 

 

서비스키 파일 생성

 

여기서 생성되는 파일 이름이 길게 생성 되어  수정을 조금 했습니다.   키 생성이 되면 json 파일을 받을 수 있으니 그걸 받아 python 프로젝트 폴더에 같이 넣으시고 이름을 수정해 python source 코드에 추가해 주시면 됩니다. 

 

그럼 실행 보겠습니다.   선언된 locale 순으로 자동 스럽게 번환이 될 것 입니다. 

 

한국어를 일본어로 번역

 

한국어를 튀르키예어로 변환

 

이렇게 변환된 파일을 이제 android project 에 적용해 보겠습니다. 

 

android studio 의 번역기 확인

 

android studio 에서 번역이 완료 되었는 지를 먼저 확인해 보았습니다.  외국어를 다 알지 못하는 입장(?)에서는 정상적으로 번역이 된 것 처럼 보입니다.  이제 빌드를 해 보겠습니다. 

 

그냥 빌드 하면 발생 하는 오류

 

 오류 메시지를 보면 번역시 오류가 발생한 strings.xml  을 찾아가 보면 아래 그림 처럼 string 값이 포함될 수 없는 값이 들어 있는 것을 확인해 볼 수 있습니다.   그걸 이제 하나 하나 수정을 해 주어야 합니다. 

strings.xml 오류 수정

 

이렇게 수정이 완료된 이후 앱을 실행 하면서 하나씩 구동해 보았습니다. 

여러나라 언어 적용

 

앱은 분명 한개 구성을 하였습니다 . 여러 나라 언어로 선택 활용할 수 있습니다.  이제 다국적 앱이 시작 됩니다.  

 

언제든 궁금한 부분이 있으시면 질문해 주시면 답변 달아 드리겠습니다. 

 

 

반응형