안드로이드 개발 시 strings.xml 파일에서 동적으로 값을 주입해야 하는 경우가 많습니다. 특히 다국어 지원(Localization)을 고려할 때, 언어마다 단어의 순서가 달라질 수 있으므로 단순한 %s나 %d 대신 위치 지정 포맷터(Positional Formatter)를 사용하는 것이 필수적입니다.
정수형(Integer) 포맷팅
정수 값을 문자열에 삽입할 때는 %d를 사용하며, 위치를 명시하기 위해 %1$d와 같이 작성합니다.
<!-- res/values/strings.xml -->
<string name="user_age_info">현재 사용자의 나이는 %1$d세입니다.</string>
자바 코드에서는 String.format()을 사용하여 리소스 문자열에 실제 정수 값을 바인딩합니다.
String ageTemplate = getResources().getString(R.string.user_age_info);
int currentAge = 28;
String finalAgeMessage = String.format(ageTemplate, currentAge);
// 결과: "현재 사용자의 나이는 28세입니다."
만약 하나의 문자열에 여러 개의 정수가 필요하다면 %2$d, %3$d 순서로 인덱스를 증가시켜 사용하면 됩니다.
문자열(String) 포맷팅
문자열 값을 치환할 때는 %s를 사용하며, 마찬가지로 %1$s, %2$s 형태로 위치를 지정합니다.
<!-- res/values/strings.xml -->
<string name="user_location_info">%1$s님의 현재 위치는 %2$s입니다.</string>
코드에서 여러 개의 문자열 인자를 전달할 경우, 정의된 인덱스 순서대로 값이 매핑됩니다.
String locationTemplate = getResources().getString(R.string.user_location_info);
String userName = "김철수";
String region = "서울특별시";
String finalLocationMessage = String.format(locationTemplate, userName, region);
// 결과: "김철수님의 현재 위치는 서울특별시입니다."
포맷팅 옵션 및 제어
기본적인 치환 외에도, 출력 형식을 세밀하게 제어할 수 있는 다양한 옵션을 제공할 수 있습니다.
%1$md: 정수 출력 시 전체 길이를m으로 맞추고 남는 공간은 공백으로 채웁니다.%1$0md: 정수 출력 시 전체 길이를m으로 맞추고 남는 공간은0으로 채웁니다. (예:%1$04d-> 0007)%1$.mf: 부동 소수점 출력 시 소수점 아래 자릿수를m으로 제한합니다. (예:%1$.2f-> 3.14)
XLIFF 태그를 활용한 번역 보호
다국어 번역을 외부 에이전시나 툴에 맡길 때, 번역가가 포맷팅 기호(%1$s 등)를 실수로 수정하거나 삭제하는 것을 방지해야 합니다. 이때 <xliff:g> 태그를 사용하면 해당 영역을 번역 불가 영역으로 보호할 수 있습니다.
먼저 resources 태그에 XLIFF 네임스페이스를 선언해야 합니다.
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="school_grade_info">
<xliff:g id="student_name" example="영희">%1$s</xliff:g> 학생은 올해
<xliff:g id="grade_level" example="3">%2$d</xliff:g>학년으로 진급했습니다.
</string>
</resources>
id 속성은 번역 도구에서 해당 변수의 용도를 식별하는 데 사용되며, example 속성은 번역가에게 컨텍스트를 제공하는 데 도움이 됩니다.
이제 자바 코드에서 해당 리소스를 가져와 포맷팅을 수행합니다.
String gradeTemplate = getResources().getString(R.string.school_grade_info);
String student = "이영희";
int grade = 4;
String finalGradeMessage = String.format(gradeTemplate, student, grade);
// 결과: "이영희 학생은 올해 4학년으로 진급했습니다."