번역을 위한 소스 코드 작성
애플리케이션을 현지화할 수 있도록 Qml 및 Qt C++ 소스 코드를 작성하십시오:
- 번역 대상 문자열 표시
- 문자열을 연결하는 대신 매개변수 사용
- 복수형 처리
- 지역별 숫자 설정 사용
- 날짜, 시간 및 통화 국제화
- 번역 가능한 데이터 텍스트 문자열 표시
- 번역가를 위한 주석 추가
- 동일한 텍스트의 모호성 해소
- 키보드 단축키를 번역 가능하게 만들기
- 로케일을 사용하여 현지화 기능 확장
- 번역 활성화
- 동적 언어 변경 준비
C++ 애플리케이션을 개발할 때는 ‘C++ 코드에 대한 추가 고려 사항’도 참조하십시오.
번역 대상 문자열 표시
애플리케이션에서 번역해야 하는 텍스트의 대부분은 단일 단어나 짧은 구로 구성됩니다. 이러한 텍스트는 일반적으로 창 제목, 메뉴 항목, 툴팁, 그리고 버튼, 확인란, 라디오 버튼의 레이블로 나타납니다.
Qt는 각 창이 생성될 때 해당 문구를 번역함으로써 번역 사용에 따른 성능 부담을 최소화합니다. 대부분의 애플리케이션에서 메인 창은 단 한 번만 생성됩니다. 대화 상자는 대개 한 번 생성된 후 필요에 따라 표시되거나 숨겨집니다. 초기 번역이 완료되면 번역된 창에 대해서는 더 이상 런타임 오버헤드가 발생하지 않습니다. 생성되었다가 소멸된 후 다시 생성되는 창에 대해서만 번역 성능 비용이 발생합니다.
런타임에 언어를 전환하는 애플리케이션을 만들 수 있지만, 이는 상당한 노력이 필요하며 런타임 성능 비용이 발생합니다.
Qt Qml 및 C++ 코드에서 사용자에게 표시되는 UI 텍스트를 번역 대상으로 지정하려면 번역 함수를 사용하십시오. Qt는 번역 가능한 텍스트를 식별하는 두 가지 방법, 즉 텍스트 기반 방식과 ID 기반 방식을 지원합니다.
텍스트 기반 번역 방식에서 Qt는 각 번역 가능한 문자열을 번역 컨텍스트와 선택적으로 연관된 모호성 해소 주석으로 색인화합니다. 동일한 문구가 여러 컨텍스트에서 충돌 없이 나타날 수 있습니다. 특정 컨텍스트에서 문구가 두 번 이상 나타날 경우, 한 번만 번역되며 해당 번역은 컨텍스트 내의 모든 발생 위치에 적용됩니다.
ID 기반 번역 방식에서는 각 번역이 명시적인 ID로 고유하게 식별됩니다. ID는 프로젝트 전체에서 고유합니다. 프로젝트 내에서 동일한 ID가 두 번 이상 나타날 경우, 해당 ID는 한 번만 번역되며, 그 번역 결과는 프로젝트 내의 모든 해당 위치에 적용됩니다.
QML
QML에서는 .qml 파일에서 사용자에게 표시되는 문자열을 번역 대상으로 지정하기 위해 다음 함수를 사용할 수 있습니다:
- qsTr(): 텍스트 기반 번역
- qsTranslate(): 텍스트 기반 번역
- qsTrId(): ID 기반 번역
텍스트 기반 qsTr():
Text {
id: txt1
text: qsTr("Back")
}이 코드는 'Back'을 번역 소스(TS) 파일의 키 항목으로 만듭니다. 실행 시, 번역 시스템은 현재 컨텍스트(아래 참조)에서 키워드 'Back'을 조회한 다음, 현재 시스템 로케일에 해당하는 번역 값을 가져옵니다. 결과는 ` text ` 속성에 반환되며, UI에는 현재 로케일에 맞는 'Back'의 적절한 번역이 표시됩니다. 번역이 발견되지 않으면 ` qsTr() `는 원본 문자열을 반환합니다.
특정 파일에 대한 번역 컨텍스트는 다음과 같이 설정할 수 있습니다:
pragma Translator: ChosenContext또는
pragma Translator: "Chosen::Context"qsTranslate() 를 통해 설정된 컨텍스트는 pragma Translator 을 통해 설정된 컨텍스트보다 우선합니다. QML에서는 기본적으로 번역 컨텍스트가 파일 이름입니다.
ID 기반 qsTrId():
Text {
id: txt1
//% "Back"
text: qsTrId("BackID")
}이 코드는 "BackID"를 번역 소스(TS) 파일 내의 고유한 키 항목으로 만들고, 소스 텍스트로 "Back"을 기록합니다. 실행 시, 번역 시스템은 ID "BackID" 를 조회한 후 현재 시스템 로케일에 해당하는 번역 값(또는 번역되지 않은 경우 소스 텍스트)을 가져옵니다. 결과는 text 속성으로 반환되며, UI에는 현재 로캘에 맞는 "BackID" 의 적절한 번역이 표시됩니다. TS 파일에서 ID "BackID" 를 가진 항목을 찾지 못하면, qsTrId() 는 ID 자체를 반환합니다. 정상적인 상황에서는 이런 일이 발생하지 않아야 합니다.
C++
C++에서는 다음 함수를 사용하여 사용자에게 표시되는 문자열을 번역 대상으로 지정할 수 있습니다:
- tr(): 텍스트 기반 번역
- QCoreApplication::translate(): 텍스트 기반 번역
- QTranslator::translate(): 텍스트 기반 번역
- qtTrId(): ID 기반 번역
- 더 많은 옵션에 대해서는 linguist-id-based-i18n.html을 참조하십시오
텍스트 기반 tr()
tr() 함수를 사용하여 텍스트를 번역 가능으로 표시하고 번역된 텍스트를 표시할 수 있습니다. 번역 컨텍스트는 해당 문자열이 사용되는 ` QObject ` 하위 클래스의 이름입니다. 새로운 ` QObject` 기반 클래스에 대한 번역 컨텍스트를 정의하려면, 각 새로운 클래스 정의에서 ` Q_OBJECT ` 매크로를 사용하십시오.
tr() 가 호출되면, ‘번역 활성화’ 섹션에 설명된 대로 애플리케이션 객체에 설치해야 하는 QTranslator 객체를 사용하여 번역 가능한 문자열을 조회합니다.
예를 들어, LoginWidget 가 QWidget 의 서브클래스라고 가정하면:
이 방식은 작성하게 될 사용자 가시 문자열의 99%를 차지합니다. 문자열 리터럴을 번역 가능으로 표시하는 방법에 대한 자세한 내용은 '번역 가능한 데이터 텍스트 문자열 표시'를 참조하십시오.
인용된 텍스트가 ` QObject ` 하위 클래스의 멤버 함수 내에 없는 경우, 해당 클래스의 ` tr() ` 함수를 사용하거나 ` QCoreApplication::translate()` 함수를 직접 사용하십시오:
void some_global_function(LoginWidget *logwid)
{
QLabel *label = new QLabel(
LoginWidget::tr("Password:"), logwid);
}
void same_global_function(LoginWidget *logwid)
{
QLabel *label = new QLabel(
QCoreApplication::translate("LoginWidget", "Password:"), logwid);
}ID 기반 qtTrId()
qtTrId()는 ID로 식별되는 번역된 문자열을 반환합니다. 따라서 함수 내에서 번역 가능한 문자열 자체를 작성하는 대신, 번역본의 ID를 작성하면 됩니다. 원본 텍스트(기본 문자열)는 메타문자열 표기법 //% 을 사용하여 작성됩니다. 텍스트가 번역되지 않은 경우, //% 로 주석이 달린 원본 텍스트가 반환됩니다. 일치하는 ID가 발견되지 않으면 ID 자체가 반환됩니다. 정상적인 상황에서는 이러한 일이 발생해서는 안 됩니다.
이 코드는 "PasswordID"를 번역 소스(TS) 파일 내의 고유 키 항목으로 만들고, 소스 텍스트로 "Password:"를 기록합니다. 실행 시, 번역 시스템은 ID "PasswordID" 를 조회한 후 현재 시스템 로케일에 해당하는 번역 값(또는 번역되지 않은 경우 원본 텍스트)을 가져옵니다.
참고: QT_NO_CAST_FROM_ASCII 매크로를 정의하여 애플리케이션을 컴파일함으로써 const char * 에서 QString 로의 자동 변환을비활성화하면 , 누락된 문자열을 대부분 포착할 수 있습니다. 자세한 내용은 QString::fromUtf8() 및 QString::fromLatin1()을 참조하십시오.
문자열 연결 대신 매개변수 사용
언어마다 구, 절, 문장에서 단어를 배열하는 방식이 다르므로, 단어와 데이터를 연결하여 문자열을 생성하지 마십시오. 대신 % 을 사용하여 매개변수를 문자열에 삽입하십시오.
예를 들어, 문자열 After processing file %1, file %2 is next in line 에서 %1 및 %2 는 번호가 매겨진 매개변수입니다. 실행 시, %1 및 %2 는 각각 첫 번째 및 두 번째 파일 이름으로 대체됩니다. 번역본에도 동일한 번호의 매개변수가 나타나야 하지만, 반드시 같은 순서일 필요는 없습니다. 이 문자열을 독일어로 번역할 때 문구 순서가 바뀔 수 있습니다. 예를 들어, Datei %2 wird bearbeitet, wenn Datei %1 fertig ist 와 같이 번역될 수 있습니다. 두 번호가 매겨진 매개변수 모두 번역에 나타나지만, 순서는 반대로 되어 있습니다.
QML: .arg() 사용
다음 QML 코드 조각에는 두 개의 번호 매기된 매개변수 %1 와 %2 가 포함된 문자열이 있습니다. 이 매개변수들은 .arg() 함수를 사용하여 삽입됩니다.
Text {
text: qsTr("File %1 of %2").arg(counter).arg(total)
}%1 는 첫 번째 매개변수를, %2 는 두 번째 매개변수를 가리키므로, 이 코드는 다음과 같은 출력을 생성합니다: 3개 중 2번째 파일.
인수가 포함된 템플릿 문자열의 사용은 피하십시오. 결과 문자열이 컴파일 시점이 아닌 런타임에 정의되기 때문입니다. 그 결과, 번역 도구가 템플릿 문자열에 대한 올바른 번역을 찾을 수 없습니다.
C++: QString::arg() 사용
C++에서는 QString::arg() 함수를 사용하여 매개변수를 대체하십시오:
void FileCopier::showProgress(int done, int total,
const QString ¤tFile)
{
label.setText(tr("%1 of %2 files copied.\nCopying: %3")
.arg(done)
.arg(total)
.arg(currentFile));
}이 코드는 다음과 같은 출력을 생성합니다: 10개 파일 중 5개 복사됨. 복사 중: somefile.txt.
복수형 처리
번역 함수에 추가 정수 매개변수(n)를 전달하고, 번역 가능한 각 문자열에서 복수형(%n)을 나타내는 특수 표기법을 사용할 수 있습니다.
n의 값에 따라 번역 함수는 대상 언어의 올바른 문법적 수를 반영한 서로 다른 번역 결과를 반환합니다. 또한, %n 가 나타나는 모든 위치는 n의 값으로 대체됩니다.
예를 들어, “ %n message(s) saved ”라는 문자열의 영어와 프랑스어 번역에는 서로 다른 복수형이 필요합니다.
| n | 번역 없음 | 프랑스어 | 프랑스어영어 |
|---|---|---|---|
| 0번역 없음프랑스어영어 | "저장된 메시지 0개" | "저장된 메시지 0개" | "저장된메시지 0개" |
| 1 | "1개의 메시지가 저장되었습니다" | "1개의 메시지가 저장되었습니다" | "저장된 메시지 1개" |
| 2 | "2개의 메시지가 저장되었습니다" | "2개의메시지가저장됨" | "저장된메시지 2개" |
| 37 | "37개의 메시지가 저장되었습니다" | "37개의메시지가저장되었습니다" | "37개의메시지가 저장되었습니다" |
이 관용구는 이중수(dual form)와 같이 여러 복수형이 존재하는 대상 언어에서도 적용됩니다. 또한, 프랑스어와 같이 단수형을 요구하는 언어의 경우, n == 0 (수-복수형)을 올바르게 처리합니다.
Qt Linguist 및 lrelease 가 복수 형태가 포함된 문자열을 번역할 때 사용하는 규칙에 대한 요약은 ‘복수 형태에 대한 번역 규칙’을 참조하십시오.
원어의 복수형을 처리하려면 해당 언어의 TS 파일도 함께 불러오십시오. lupdate 도구의 -pluralonly 명령줄 옵션을 사용하여 복수형 항목만 포함된 TS 파일을 생성하십시오.
또는 lconvert 도구의 -pluralonly 명령줄 옵션을 사용하여 기존 TS 파일에서 복수형이 아닌 모든 형태를 제거할 수도 있습니다.
QML 예제
다음 QML 코드 스니펫은 원본 텍스트를 올바른 복수형으로 변환하고, ` %n `을 ` total`의 값으로 대체합니다:
Text {
text: qsTr("%n message(s) saved", "", total)
}C++ 예제
다음 C++ 코드 스니펫은 ` %n `을 ` count() ` 함수가 반환하는 값으로 대체합니다:
int n = messages.count();
showMessage(tr("%n message(s) saved", "", n));지역별 숫자 설정 사용
매개변수를 지정할 때 %L 수정자를 포함하면, 숫자는 현재 지역 설정에 따라 현지화됩니다. 변환 시 로케일이 설정되어 있으면 해당 로케일을 사용하고, 그렇지 않으면 시스템 전체 로케일을 사용합니다.
QML: %L 사용
예를 들어, 다음 QML 코드 조각에서 %L1 은 현재 선택된 로케일(지리적 지역)의 숫자 서식 규칙에 따라 첫 번째 매개변수를 서식화합니다:
Text {
text: qsTr("%L1").arg(total)
}total 가 4321.56인 경우, 영어 지역 설정(로케일)에서는 4,321.56이 출력되는 반면, 독일어 지역 설정에서는 4.321,56이 출력됩니다.
C++: %Ln 사용
C++에서는 ` %Ln `을 사용하여 ` n`의 지역화된 표현을 생성할 수 있습니다. 기본 로케일을 설정하려면 ` QLocale::setDefault()`을 사용하십시오.
날짜, 시간 및 통화 국제화
지역에서 선호하는 형식을 사용하여 날짜, 시간 및 통화를 표시하십시오.
QML: QtQml 함수 사용
QML에는 날짜와 시간을 포맷팅하기 위한 문자열 내부의 특수 수정자가 없습니다. 대신, 현재 로케일(지리적 지역)을 조회하고 Date의 메서드를 사용하여 문자열을 포맷팅해야 합니다.
Qt.locale() Locale 객체를 반환하며, 이 객체에는 로케일에 대한 정보가 포함되어 있습니다. 특히, 속성에는 현재 로케일의 언어와 국가가 포함되어 있습니다. 이 값을 그대로 사용하거나 구문 분석하여 현재 로케일에 적합한 내용을 결정할 수 있습니다. Locale.name
다음 코드 조각은 ` Date()`를 사용하여 현재 날짜와 시간을 가져온 다음, 이를 현재 로케일에 맞는 문자열로 변환합니다. 그런 다음 적절한 번역을 위해 해당 날짜 문자열을 ` %1 ` 매개변수에 삽입합니다.
Text {
text: qsTr("Date %1").arg(Date().toLocaleString(Qt.locale()))
}통화 숫자를 현지화하려면 Number 유형을 사용하십시오. 이 유형은 숫자를 현지화된 통화 문자열로 변환하는 데 있어 Date 유형과 유사한 기능을 제공합니다.
C++: QLocale 클래스 사용
C++에서는 QLocale::timeFormat() 또는 QLocale::toString(QTime) 또는 toString(QDate) 를 사용합니다:
QLabel *label = new QLabel(this);
label->setText(tr("Date %1").arg(QLocale().toString(QDate::currentDate()));번역 가능한 데이터 텍스트 문자열 표시
_NOOP 함수(QML에서)와 _NOOP 매크로(C++에서)를 사용하여 lupdate 도구가 추출할 수 있도록 번역 가능한 문자열 리터럴을 표시합니다.
QML: _NOOP 함수 사용
QML에서는 다음 함수를 사용하여 번역 가능한 문자열 리터럴을 지정합니다:
사용자가 재부팅 없이 시스템 언어를 변경하는 경우, 시스템에 따라 배열, 리스트 모델 및 기타 데이터 구조에 포함된 문자열이 자동으로 갱신되지 않을 수 있습니다. UI에 텍스트가 표시될 때 강제로 갱신되도록 하려면, ` QT_TR_NOOP() ` 함수를 사용하여 문자열을 선언해야 합니다. 그런 다음, 표시할 객체에 데이터를 채울 때 각 텍스트에 대한 번역을 명시적으로 가져와야 합니다.
예를 들어:
ListModel {
id: myListModel
ListElement {
//: Capital city of Finland
name: QT_TR_NOOP("Helsinki")
}
}
...
Text {
text: qsTr(myListModel.get(0).name)
// Get the translation of the name property in element 0
}C++: _NOOP 매크로 사용
함수 외부에 완전히 위치한 번역 가능한 텍스트의 경우, 컨텍스트를 제외하고 텍스트만 남도록 확장되는 QT_TR_NOOP(), QT_TRID_NOOP(), QT_TRANSLATE_NOOP() 매크로를 사용하십시오.
QT_TR_NOOP() 의 예:
QString FriendlyConversation::greeting(int type)
{
static const char *greeting_strings[] = {
QT_TR_NOOP("Hello"),
QT_TR_NOOP("Goodbye")
};
return tr(greeting_strings[type]);
}QT_TRANSLATE_NOOP() 의 예시:
static const char *greeting_strings[] = {
QT_TRANSLATE_NOOP("FriendlyConversation", "Hello"),
QT_TRANSLATE_NOOP("FriendlyConversation", "Goodbye")
};
QString FriendlyConversation::greeting(int type)
{
return tr(greeting_strings[type]);
}
QString global_greeting(int type)
{
return QCoreApplication::translate("FriendlyConversation",
greeting_strings[type]);
}번역가를 위한 주석 추가
번역 가능하다고 표시한 문자열 앞에 소스 코드에 주석을 추가하여 그 용도를 명확히 할 수 있습니다. 이 주석들은 번역가에게 전달하는 TS 파일에 포함됩니다.
참고: TS파일은 원문과 번역된 텍스트를 넣을 공간이 포함된 XML 파일입니다. 업데이트된 TS 파일은 바이너리 번역 파일로 변환되어 최종 애플리케이션의 일부로 포함됩니다.
QML: //: 및 //~ 사용
다음 코드 예제에서 //: 줄의 텍스트는 번역가를 위한 주요 주석입니다.
//~ 줄의 텍스트는 선택적인 추가 정보입니다. 이 텍스트의 첫 단어는 TS 파일 내 XML 요소에서 추가 식별자로 사용되므로, 첫 단어가 문장의 일부가 되지 않도록 주의하십시오. 예를 들어, " Context Not related to back-stepping "이라는 주석은 TS 파일에서 " <extra-Context>Not related to back-stepping "으로 변환됩니다.
Text {
id: txt1;
// This UI string is only used here
//: The back of the object, not the front
//~ Context Not related to back-stepping
text: qsTr("Back");
}C++: 주석 문자 사용
C++에서 주석을 추가하려면, 코드 내의 tr() 호출에 “ //: ” 형식의 주석을 추가하거나 주석의 시작과 끝을 명확히 표시하십시오.
다음 예제에서 주석은 각 호출의 맥락에서 tr() 에 전달된 문자열과 연관되어 있습니다:
//: This name refers to a host name.
hostNameLabel->setText(tr("Name:"));
/*: This text refers to a C++ code example. */
QString example = tr("Example");선택적 주석을 추가하려면 다음을 사용합니다:
//~ <field name> <field contents>필드 이름은 도메인 접두사(해당 필드의 모델이 된 파일 형식의 일반적인 파일 확장자일 수 있음), 하이픈, 그리고 밑줄로 구분된 표기법의 실제 필드 이름으로 구성되어야 합니다. TS 파일에 저장할 때, 필드 이름과 접두사 extra- 이 결합되어 XML 요소 이름을 형성합니다. 필드 내용은 XML 이스케이프 처리되지만, 그 외에는 요소의 내용으로 그대로 표시됩니다. 각 메시지에 고유한 필드를 원하는 수만큼 추가할 수 있습니다.
예시:
//: This is a comment for the translator.
//~ loc-layout_id foo_dialog
//~ loc-blank False
//~ magic-stuff This might mean something magic.
QString text = MyMagicClass::tr("Sim sala bim.");참고: 텍스트 기반 번역의 ID를 설정하기 위해 //= 메타스트링 주석을사용하는 방법은 Qt 6.10에서 더 이상 권장되지 않으며, 향후 버전에서 제거될 예정입니다.
번역자 주석에는 TRANSLATOR 키워드를 사용할 수 있습니다. TRANSLATOR 키워드 바로 앞에 나오는 메타데이터는 TS 파일 전체에 적용됩니다.
참고: TS 파일을 Qt Linguist 에서열면 , //: 로 주석이 달린 내용은 Qt Linguist 의 메시지 편집기에 표시됩니다. 반면, //~ 표기법을 사용하여 제공된 텍스트는 추가 정보이며 TS 파일 내에서만 생성됩니다. 이 텍스트는 주로 다른 형식으로의 변환을 목적으로 하며, Qt Linguist 에서는 숨겨져 있습니다.
ID 기반 번역 그룹화
각 ID 기반 번역에 레이블을 할당하여 대규모 프로젝트의 ID 기반 항목을 더 작은 그룹으로 정리할 수 있습니다.
ID 기반 항목에 레이블을 할당하려면, 레이블 이름을 명시한 ` //@ ` 주석을 추가하면 됩니다. 예를 들어 C++에서는 다음과 같습니다:
//% "Open file"
//@ FileOperations
qtTrId("msg.open");또는 QML의 경우:
//% "Open file"
//@ FileOperations
qsTrId("msg.open");TS 파일을 Qt Linguist, 동일한 레이블을 가진 ID 기반 항목들은 문맥별로 그룹화되는 텍스트 기반 항목과 유사하게 함께 묶입니다. 레이블이 없는 항목은 ` <unnamed label>` 아래에 표시됩니다.
참고: 레이블 이름은 조회나 고유성에 영향을 미치지 않습니다. ID는 전역적으로 고유하게 유지되며, 레이블을 참조하지 않고도 ` qtTrId("msgid") `를 통해 계속 불러올 수 있습니다. 레이블 태그는 번역가의 탐색 편의성을 높이기 위한 목적으로만 사용되며, 런타임 동작을 변경하지 않습니다.
동일한 텍스트의 모호성 해소
번역 시스템은 동일한 텍스트를 여러 번 번역해야 하는 상황을 방지하기 위해 UI 텍스트 문자열을 고유한 항목으로 통합합니다. 그러나 어떤 텍스트는 다른 텍스트와 외관상 동일해 보이지만 의미가 다를 수 있습니다. 예를 들어, 영어에서 'back'은 '뒤로 가는 것'과 '앞과 반대쪽'을 모두 의미합니다. 번역가가 두 가지 별개의 번역을 생성할 수 있도록, 번역 시스템에 이 두 가지 서로 다른 의미를 알려주어야 합니다.
QML: qsTr()에 의미 구분자 추가
QML에서 qsTr() 함수의 두 번째 매개변수로 의미 구분 문자열을 추가합니다.
다음 코드 예제에서, ID ‘ not front ’는 ‘Back’이라는 텍스트를 ‘뒤로 이동’을 의미하는 ‘Back’ 텍스트와 구별해 줍니다:
Text {
id: txt1
// This UI string is used only here
//: The back of the object, not the front
//~ Context Not related to back-stepping
text: qsTr("Back", "not front")
}C++: tr()에 구분자 추가
C++에서는 tr() 호출 시 구분을 위한 문자열을 전달합니다.
다음 코드 예제에서 ID recipient 은 수신자의 이름을 발신자의 이름과 구별합니다:
MyWindow::MyWindow()
{
QLabel *senderLabel = new QLabel(tr("Name:"));
QLabel *recipientLabel = new QLabel(tr("Name:", "recipient"));
...키보드 단축키를 번역 가능하게 만들기
가장 일반적인 형태의 키보드 단축키는 특정 동작을 수행하기 위해 누르는 키 조합을 의미합니다. ` standard shortcuts`의 경우, 표준 키를 사용하여 각 단축키와 연관된 플랫폼별 키 시퀀스를 요청하십시오.
사용자 정의 단축키의 경우 Ctrl+Q나 Alt+F와 같이 사람이 읽을 수 있는 문자열을 사용하십시오. 이를 통해 다양한 언어를 사용하는 사용자에게 적합한 단축키로 번역할 수 있습니다.
애플리케이션에 키보드 단축키를 하드코딩하면 번역가가 이를 재정의할 수 없습니다.
메뉴 항목 및 버튼 텍스트에서 키보드 단축키를 사용할 경우, 니모닉 문자(밑줄로 표시됨)는 밑줄이 그어진 문자와 함께 Alt 또는 Ctrl 키를 누르면 메뉴 항목을 클릭하거나 버튼을 누르는 것과 동일한 동작이 수행됨을 나타냅니다.
예를 들어, 애플리케이션에서는 종종 ‘ File ’ 메뉴에서 F를 니모닉 문자로 사용하므로, 메뉴 항목을 클릭하거나 Alt+F를 눌러 메뉴를 열 수 있습니다. 번역 가능한 문자열("File")에서 니모닉 문자를 정의하려면, 그 앞에 앰퍼샌드(&)를 붙이십시오: "&File". 문자열의 번역본에도 앰퍼샌드가 포함되어야 하며, 가급적이면 동일한 문자 앞에 위치해야 합니다.
QML 예제
QML에서:
Menu {
id: fileMenu
title: qsTr("&File")
MenuItem {
objectName: "quitMenuItem"
text: qsTr("E&xit")
onTriggered: Qt.quit()
}
}C++: QKeySequence 클래스 사용
C++에서는 QAction 및 QKeySequence 객체를 사용하여 동작을 실행하는 키보드 단축키를 지정합니다:
exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcuts(QKeySequence::Quit);키보드 단축키의 번역은 QShortcut 컨텍스트와 연결됩니다.
로케일을 사용하여 현지화 기능 확장
지역에 따라 더 적합한 그래픽이나 오디오가 있을 수 있습니다.
일반적으로 이미지의 현지화는 피하는 것이 좋습니다. 지역적인 말장난이나 지나치게 확장된 비유에 의존하기보다는 전 세계적으로 통용되는 아이콘을 제작하십시오. 다만, 아랍어 및 히브리어 로케일의 경우 왼쪽과 오른쪽을 가리키는 화살표 이미지의 방향을 반대로 바꿔야 할 수도 있습니다.
로케일은 기본 파일 선택기 중 하나이므로, 파일 선택을 통해 시스템 로케일에 따라 리소스로 제공되는 서로 다른 이미지를 표시할 수 있습니다.
다음 섹션의 QML 및 C++ 코드 예제는 애플리케이션 리소스에 다음 파일을 제공하고, 하위 폴더 이름으로 언어 및 국가 코드를 사용한다고 가정합니다.
images
├── language-icon.png
├── +en_GB
│ └── language-icon.png
└── +fi_FI
└── language-icon.pngQML: 이미지 소스 설정
다음 QML 코드 스니펫은 현재 로케일에 따라 아이콘 소스 이미지를 선택하는 방법을 보여줍니다:
icon.source: "qrc:/images/language-icon.png"C++: QFileSelector 사용
다음 C++ 코드 스니펫은 ` QFileSelector `를 사용하여 시스템 로케일에 따라 ` images ` 폴더에서 언어 아이콘을 선택합니다:
const QFileSelector selector;
const QIcon languageIcon(selector.select(":/images/language-icon.png"));번역 활성화
TS 파일 이름에는 ISO 언어 및 국가 코드가 포함되어야 합니다:
예를 들어, ` qml_de.ts `는 대상 언어를 독일어로 설정하고, ` qml_de_CH.ts `는 대상 언어를 독일어로, 대상 국가를 스위스로 설정합니다. ` lrelease ` 도구는 ` qml_de.qm ` 및 ` qml_de_CH.qm `라는 QM 파일을 생성하며, 애플리케이션은 시스템 로케일에 따라 이 파일을 로드합니다.
QML: QQmlApplicationEngine 사용
QML에서는 QQmlApplicationEngine 을 사용하여 메인 QML 파일이 포함된 디렉터리의 i18n 하위 디렉터리에서 번역 파일을 자동으로 로드합니다. 번역 파일 이름에는 qml_ 접두사가 반드시 포함되어야 합니다. 예를 들어, qml_en_US.qm 와 같습니다. 다국어 앱을 설정하는 방법은 다음 CMake 코드 스니펫을 참조하십시오:
...
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick LinguistTools)
qt_standard_project_setup(REQUIRES 6.5 I18N_TRANSLATED_LANGUAGES ja_JP)
qt_add_qml_module(appmultilingual_demo
URI multilingual_demo
QML_FILES
Main.qml
)
qt_add_translations(appmultilingual_demo
TS_FILE_BASE qml
TS_FILE_DIR i18n
RESOURCE_PREFIX /qt/qml/multilingual_demo/i18n
)
...QJSEngine::uiLanguage 또는 Qt.uiLanguage 속성 값이 변경되면 애플리케이션은 번역 내용을 다시 불러옵니다. 다음 코드 스니펫은 사용자가 버튼을 클릭할 때 언어를 동적으로 변경합니다:
Button {
anchors.centerIn: parent
text: qsTr("Translate")
onClicked: {
Qt.uiLanguage = Qt.uiLanguage === "en" ? "ja" : "en"
}
}C++: QTranslator 사용
C++에서는 TS 파일 이름에 애플리케이션 이름이 포함되어야 합니다. 예를 들어, app_de_DE.ts 입니다.
일반적으로 Qt C++ 애플리케이션의 main() 함수는 다음과 같은 형태를 띱니다:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QTranslator myappTranslator;
if (myappTranslator.load(QLocale::system(), u"myapp"_s, u"_"_s, u":/i18n"_s))
app.installTranslator(&myappTranslator);
return app.exec();
}번역 기능을 지원하는 애플리케이션의 경우, QTranslator 객체를 생성하고, 런타임에 사용자의 UI 표시 로케일에 따라 번역을 load 하며, 번역기 객체를 애플리케이션에 등록합니다.
동적 언어 변경 준비
Qt Widgets 와 Qt Quick 는 모두 Qt의 이벤트 시스템을 사용하여 클래스에 번역 변경 사항을 알립니다.
LanguageChange QCoreApplication::installTranslator() 함수를 사용하여 새 번역을 설치하면 이벤트가 게시됩니다. 다른 애플리케이션 구성 요소도 이벤트를 게시하여 유형에서 파생된 위젯이나 QML 유형이 스스로 업데이트되도록 강제할 수 있습니다. LanguageChange Item
기본적으로 LanguageChange 이벤트는 모든 최상위 창으로 전파되며, 거기서부터 Item에서 파생된 위젯 또는 QML 유형의 전체 트리를 통해 전파됩니다.
Qt Widgets: changeEvent 재정의
QWidget 의 하위 클래스에 대한 기본 이벤트 핸들러는 QEvent::LanguageChange 이벤트에 반응하며, 필요할 때 changeEvent() 함수를 호출합니다.
Qt Widgets가 설치된 ` QTranslator ` 객체의 변경 사항을 인식하도록 하려면, 위젯의 ` changeEvent()` 함수를 재구현하여 해당 이벤트가 ` LanguageChange ` 이벤트인지 확인하고, ` tr()` 함수를 사용하여 위젯에 표시되는 텍스트를 업데이트하십시오. 예를 들어:
void MyWidget::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange) {
titleLabel->setText(tr("Document Title"));
...
okPushButton->setText(tr("&OK"));
} else
QWidget::changeEvent(event);
}Qt Widgets Designer UI 파일(.ui)과 uic 를 사용할 때는 새로운 번역 파일을 읽어들이고 ui.retranslateUi(this) 를 직접 호출할 수 있습니다:
void MyWidget::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange) {
ui.retranslateUi(this);
} else
QWidget::changeEvent(event);
}다른 변경 이벤트를 전달하려면 해당 함수의 기본 구현을 호출하십시오.
LocaleChange 이벤트에 따라 설치된 번역기 목록이 변경될 수 있으며, 애플리케이션에서 사용자가 현재 애플리케이션 언어를 변경할 수 있는 UI를 제공할 수도 있습니다.
QML: Item에서 파생된 유형에 대한 이벤트 재정의
사용자 정의 C++ 등록 유형이 없는 일반 QML 애플리케이션의 경우, QQmlApplicationEngine을 사용하는 것만으로도 모든 번역 바인딩의 업데이트를 트리거하기에 충분합니다.
그러나 QQuickItem 에서 파생된 타입을 등록했고, 해당 타입의 속성 중 하나가 번역된 텍스트를 노출하거나(또는 다른 방식으로 언어에 의존하는 경우) 해당 타입의 ` event method `를 재정의하고 그 안에서 속성의 변경 신호를 발산해야 합니다(바인딩 가능한 속성의 경우 ` notify `를 호출). 예를 들어:
class MyItem : public QQuickItem
{
Q_OJBECT
QML_ELEMENT
Q_PROPERTY(QString greeting READ greeting NOTIFY greetingChanged)
public signals:
void greetingChanged();
public:
QString greeting() const
{
return tr("Hello World!");
}
bool event(QEvent *ev) override
{
if (ev->type() == QEvent::LanguageChange)
emit greetingChanged();
return QQuickItem::event(ev);
}
};이렇게 하면 해당 속성이 사용된 QML 내의 모든 바인딩이 재평가되어 언어 변경 사항을 반영하게 됩니다.
일반 QObject 파생 클래스: 이벤트 필터 사용
일부 클래스는 QWidget 나 QQuickItem 에서 파생되지 않았더라도 언어 변경 이벤트를 처리해야 할 수 있습니다. 이 경우, QCoreApplication 에 이벤트 필터를 설치하십시오.
class CustomObject : public QObject
{
Q_OBJECT
public:
QList<QQuickItem *> managedItems;
CustomObject(QOject *parent = nullptr) : QObject(parent)
{
QCoreApplication::instance()->installEventFilter(this);
}
bool eventFilter(QObject *obj, QEvent *ev) override
{
if (obj == QCoreApplication::instance() && ev->type() == QEvent::LanguageChange) {
for (auto item : std::as_const(managedItems))
QCoreApplication::sendEvent(item, ev);
// do any further work on reaction, e.g. emit changed signals
}
return false;
}
};이는 클래스에서 번역된 문자열을 제공하여 나중에 사용자 인터페이스(예: 사용자 정의 item model)에 표시되는 경우나, 클래스가 위젯(Widgets) 또는 퀵 아이템(Quick Items)의 컨테이너 역할을 하여 해당 객체들로 이벤트를 전달해야 하는 경우에 필요할 수 있습니다.
C++ 코드에 대한 추가 고려 사항
다음 섹션에서는 번역 가능한 애플리케이션에서 Qt C++ 클래스 및 함수를 사용하는 방법에 대한 자세한 정보를 다룹니다.
사용자에게 표시되는 모든 텍스트에 QString 사용
QString 는 내부적으로 유니코드 인코딩을 사용하므로, 익숙한 텍스트 처리 연산을 통해 전 세계 모든 언어를 투명하게 처리할 수 있습니다. 또한, 사용자에게 텍스트를 표시하는 모든 Qt 함수는 QString 객체를 매개변수로 받기 때문에, char * 에서 QString 로의 변환에 따른 오버헤드가 발생하지 않습니다.
번역 컨텍스트 정의하기
QObject 및 각 QObject 하위 클래스의 번역 컨텍스트는 클래스 이름 그 자체입니다. QObject 의 하위 클래스를 정의하는 경우, 클래스 정의에서 Q_OBJECT 매크로를 사용하여 번역 컨텍스트를 재정의하십시오. 이 매크로는 컨텍스트를 하위 클래스의 이름으로 설정합니다.
예를 들어, 다음 클래스 정의에는 Q_OBJECT 매크로가 포함되어 있으며, MainWindow 컨텍스트를 사용하는 새로운 tr() 함수를 구현합니다:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
...클래스 정의에서 ` Q_OBJECT `을 사용하지 않으면 컨텍스트는 기본 클래스에서 상속됩니다. 예를 들어, Qt의 모든 ` QObject` 기반 클래스는 컨텍스트를 제공하므로, ` Q_OBJECT ` 매크로 없이 정의된 새로운 ` QWidget ` 하위 클래스의 ` tr() ` 함수를 호출하면 ` QWidget ` 컨텍스트가 사용됩니다.
Qt가 아닌 클래스 변환
QObject 을 상속받지 않거나 Q_OBJECT 매크로를 사용하지 않는 클래스의 문자열에 대해서는 lupdate 에 대한 추가 정보를 제공해야 합니다. 비-Qt 클래스에 번역 지원을 추가하려면 Q_DECLARE_TR_FUNCTIONS() 매크로를 사용할 수 있습니다. 예를 들어:
class MyClass
{
Q_DECLARE_TR_FUNCTIONS(MyClass)
public:
MyClass();
...
};이렇게 하면 해당 클래스와 관련된 문자열을 번역하는 데 사용할 수 있는 ` tr()` 함수가 클래스에 제공되며, ` lupdate `가 소스 코드에서 번역 가능한 문자열을 찾을 수 있게 됩니다.
또는, lupdate 및 Qt Linguist 에서 인식하는 특정 컨텍스트를 사용하여 QCoreApplication::translate() 함수를 호출할 수도 있습니다.
QObject 하위 클래스 외부에 있는 텍스트 번역하기
인용된 텍스트가 QObject 서브클래스의 멤버 함수 내에 있지 않은 경우, 적절한 클래스의 tr() 함수를 사용하거나 QCoreApplication::translate() 함수를 직접 호출하십시오:
void some_global_function(LoginWidget *logwid)
{
QLabel *label = new QLabel(
LoginWidget::tr("Password:"), logwid);
}
void same_global_function(LoginWidget *logwid)
{
QLabel *label = new QLabel(
QCoreApplication::translate("LoginWidget", "Password:"),
logwid);
}© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.