GDPR 준수 기업
ISO 27001 인증 기업
SOC II 준수 기업
Flutter 현지화: ARB 파일, intl, gen-l10n 완벽 해설
Flutter 현지화는 애플리케이션의 메시지와 인터페이스를 여러 로캘에 맞게 조정하는 작업입니다. 기본 제공 프로세스에서 flutter_localizations는 현지화된 프레임워크 위젯을 지원하고, ARB 리소스와 gen-l10n은 애플리케이션의 AppLocalizations API를 생성하며, intl은 언어에 따라 달라지는 메시지와 서식을 지원합니다.

세계 최대 기업 80곳 이상이 Smartcat을 선택했습니다
flutter_localizations와 gen-l10n 설정
이 가이드에서는 간단한 영어·스페인어 예제를 설정하고, 메시지 메타데이터를 설명하며, 일반적인 패키지 접근 방식을 비교합니다. 또한 번역 플랫폼을 Flutter 프로젝트에 연결하기 전에 검증해야 할 사항도 소개합니다.
현지화 생성기는 하나만 사용하고 입력 및 출력 위치를 명시하세요. 아래 예제는 자체 SDK 제약 조건과 일반적인 프로젝트 구성을 갖춘 기존 Flutter 애플리케이션을 전제로 합니다.
관련 항목을 pubspec.yaml에 병합하세요. dependencies 또는 flutter 섹션을 중복해서 만들지 마세요.
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: any
flutter:
generate: trueflutter pub get으로 종속성을 해결하세요. intl: any 항목은 공식 설정 패턴을 따르므로 종속성 해결 과정에서 Flutter SDK와 호환되는 버전이 선택됩니다. 애플리케이션의 lockfile과 일반적인 종속성 검토 프로세스는 그대로 유지하세요.
프로젝트 루트에 l10n.yaml을 생성하세요.
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dartSDK별 설정은 최신 Flutter 국제화 가이드를 참고하세요. 최신 프로세스에서는 생성된 현지화 파일이 애플리케이션 소스 트리에 위치합니다. 이 예제는 lib/l10n에서 가져옵니다. 예전의 합성 package:flutter_gen import를 새 설정에 복사하지 마세요. 생성 소스 마이그레이션 안내를 참고하세요.
맥락과 타입이 지정된 플레이스홀더로 ARB 파일 작성하기
ARB 파일은 메시지와 선택적 메타데이터를 담은 JSON 기반 리소스 번들입니다. 메시지 키를 안정적으로 유지하고, 완전한 메시지를 작성하며, 메타데이터로 텍스트의 사용 방식을 설명하세요.
lib/l10n/app_en.arb를 생성하세요.
{
"@@locale": "en",
"appTitle": "Reading room",
"@appTitle": {
"description": "Title of the sample reading application"
},
"welcomeName": "Welcome, {name}",
"@welcomeName": {
"description": "Greeting on the home screen",
"placeholders": {
"name": {"type": "String", "example": "Sam"}
}
},
"savedBooks": "{count, plural, =0{No saved books} one{1 saved book} other{{count} saved books}}",
"@savedBooks": {
"description": "Number of books saved to the user's library",
"placeholders": {
"count": {"type": "int"}
}
},
"readingState": "{state, select, active{Reading now} paused{Reading paused} other{Ready to read}}",
"@readingState": {
"description": "Reading status; state is active, paused or another value",
"placeholders": {
"state": {"type": "String"}
}
}
}lib/l10n/app_es.arb를 생성하세요.
{
"@@locale": "es",
"appTitle": "Sala de lectura",
"welcomeName": "Te damos la bienvenida, {name}",
"savedBooks": "{count, plural, =0{No hay libros guardados} one{1 libro guardado} other{{count} libros guardados}}",
"readingState": "{state, select, active{Leyendo ahora} paused{Lectura en pausa} other{Todo listo para leer}}"
}템플릿에는 생성기가 사용하는 플레이스홀더 메타데이터가 들어 있습니다. 현지화된 파일은 메시지 키, 플레이스홀더 이름, select 식별자를 유지하면서 사용자에게 표시되는 문구만 바꿉니다. 이 스페인어 예제는 작동 방식을 보여 주기 위한 것이며, 프로덕션 언어는 실제 제품 맥락에서 원어민 검토를 받아야 합니다.
리소스를 추가하거나 변경한 후에는 flutter gen-l10n을 실행하세요. 생성기 오류는 조치가 필요한 리소스 문제로 간주하고, 파일을 릴리스에 통합하기 전에 해결하세요.
생성된 메시지를 MaterialApp에 연결하기
생성된 delegate와 지원 로캘을 등록한 다음, 애플리케이션 위젯 아래의 context에서 현지화된 메시지를 읽으세요.
생성이 끝나면 다음 예제를 lib/main.dart에 넣으세요.
import 'package:flutter/material.dart';
import 'l10n/app_localizations.dart';
void main() => runApp(const ReadingApp());
class ReadingApp extends StatelessWidget {
const ReadingApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const ReadingHome(),
);
}
}
class ReadingHome extends StatelessWidget {
const ReadingHome({super.key});
@override
Widget build(BuildContext context) {
final messages = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(title: Text(messages.appTitle)),
body: Padding(
padding: const EdgeInsetsDirectional.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(messages.welcomeName('Sam')),
Text(messages.savedBooks(3)),
Text(messages.readingState('active')),
],
),
),
);
}
}ReadingHome 위젯은 MaterialApp에서 제공하는 현지화를 사용할 수 있습니다. 바깥 위젯의 context에서 AppLocalizations 를 요청하면 해당 위젯이 만든 provider보다 위쪽을 찾게 됩니다. Localizations API 문서 에서 하위 위젯에 현지화 리소스가 제공되는 방식을 설명합니다.생성된 API는 일반 메시지와 인수가 있는 메시지의 차이를 코드에서 명확히 보여 줍니다. appTitle은 값으로 접근하고, welcomeName, savedBooks, readingState는 메시지를 만드는 데 필요한 값을 전달받습니다.
복수형과 select 메시지를 신중하게 처리하기
복수형 메시지는 수량과 대상 로캘의 문법에 따라 문구를 선택합니다. select 메시지는 애플리케이션이 제공하는 식별자에 따라 분기를 선택합니다. 각 분기에 표시되는 텍스트를 번역하되 구문과 식별자는 그대로 유지하세요.
복수형
예제에서 =0은 빈 상태를 위한 명시적인 문장을 제공합니다. one과 other 분기는 예제 언어에서 사용하는 형태를 다룰 뿐, 모든 대상 로캘에 통하는 범용 템플릿은 아닙니다. 검토자가 해당 언어에 필요한 형태와 앱이 만들어 낼 수 있는 값을 알 수 있도록 충분한 맥락을 제공하세요.
select 메시지
active와 paused 같은 값은 프로그램 식별자입니다. 이러한 식별자를 번역하면 리소스와 해당 값을 제공하는 코드의 연결이 끊어집니다. other 분기는 이름이 지정된 분기와 일치하지 않는 값에 대한 대체 메시지를 제공합니다.
완전한 메시지
번역된 동사, 숫자, 번역된 명사 같은 조각을 이어 붙이지 마세요. 완전한 메시지를 제공해야 대상 언어에서 어순을 자유롭게 정할 수 있습니다. 검토자가 사용자에게 보이는 그대로 문장을 평가할 수 있도록 브리프에 값, 예상 범위, 화면 맥락을 설명하세요.
Flutter 현지화 패키지 비교
리소스 형식, 애플리케이션 아키텍처, 유지 관리 요구 사항에 따라 패키지를 선택하세요. 아래 패키지들은 서로 다른 규칙을 따르며, 같은 메시지에 생성기를 둘 이상 사용하면 불필요한 혼란이 생깁니다.
| 방식 | 일반적인 리소스 | 코드 생성 | 복수형 처리 방식 | 적합한 경우 |
|---|---|---|---|---|
| 기본 제공 gen-l10n | ARB | 타입이 지정된 Dart 접근자 생성 | ICU 스타일 메시지 구문 | 공식 Flutter 리소스 프로세스를 원하는 경우 |
| easy_localization | 기본은 JSON이며 추가 로더 사용 가능 | 선택적 생성 도구 | 패키지 복수형 API와 로캘 인식 규칙 | 해당 패키지의 에셋 로딩 및 로캘 관리 방식을 선호하는 경우 |
| GetX 번역 | 문서화된 기본 프로세스에서는 로캘을 키로 하는 맵 | 기본 맵 API에는 필요 없음 | trPlural은 단수/복수 키를 사용하므로 더 복잡한 문법은 별도로 평가 필요 | 애플리케이션에서 이미 GetX를 사용하고 있고 그 번역 모델이 요구 사항에 맞는 경우 |
선택하기 전에 최신 easy_localization 문서와 GetX 문서를 검토하세요. 실제 메시지로 대체 동작, 매개변수, 복수형 범주, 추출 프로세스를 테스트하세요. 영어 문자열에 편리한 API라고 해서 출시하려는 모든 언어를 지원한다는 보장은 없습니다.
intl은 경쟁 관계에 있는 번역 관리 플랫폼이 아닙니다. 현지화 프로세스에서 사용하는 국제화 유틸리티를 제공합니다. gen-l10n은 ARB 리소스에서 애플리케이션 접근자를 생성합니다. 별도의 intl_utils 패키지도 현지화 코드를 생성하지만, 2026년 10월 30일 확인 당시 패키지 페이지에 지원 중단으로 표시되어 있었습니다. 새 프로젝트에 도입하기 전에 유지 관리 상태를 확인하세요.
로캘 전환, RTL, 텍스트 길이 증가 테스트하기
리소스의 정확성과 번역된 텍스트가 인터페이스에서 보이는 방식을 모두 테스트하세요. JSON 파싱이나 코드 생성이 성공했다고 해서 화면이 이해하기 쉽고 사용하기 편하다는 뜻은 아닙니다.
로캘 전환
개발 단계에서 간단히 확인하려면 MaterialApp.locale을 const Locale('es')처럼 지원되는 값으로 설정하세요. 프로덕션용 언어 선택기에서는 선택한 로캘을 애플리케이션 상태에 보관하고, 제품 요구 사항에 따라 설정을 저장하며, 시스템 언어를 따르는 옵션을 제공하세요. 저장된 설정은 현재 앱 버전이 실제로 지원하는 로캘과 대조해 검증하세요.
오른쪽에서 왼쪽으로 쓰는 레이아웃
읽기 방향을 따라야 하는 요소에는 방향성 레이아웃 API를 사용하세요. 실제 RTL 로캘에서 여백, 정렬, 탐색 요소, 방향이 섞인 콘텐츠를 확인하세요. 모든 아이콘을 반전해야 한다고 가정하지 마세요. 방향을 나타내는 탐색 화살표와 브랜드 기호는 의미가 다릅니다.
텍스트 길이 증가
긴 번역문과 큰 텍스트 크기를 테스트하세요. 버튼, 탭, 대화 상자, 빈 상태, 오류, 좁은 레이아웃을 점검하세요. 긴 이름이나 숫자 같은 동적 값을 포함해, 사용자가 실제로 받게 될 메시지로 레이아웃을 확인하세요.
실용적인 테스트 매트릭스를 활용하세요.
| 확인 항목 | 예시 |
|---|---|
| 리소스 범위 | 필수 템플릿 키마다 의도된 현지화 값 또는 대체 값이 있음 |
| 메시지 인수 | 플레이스홀더 이름과 타입이 생성된 메서드와 계속 호환됨 |
| 수량 동작 | 0, 1, 그리고 대상 언어의 추가 형태를 확인할 수 있는 값 |
| select 동작 | 알려진 상태와 other로 이어지는 예상치 못한 값 |
| 로캘 동작 | 시스템 언어, 명시적 선택, 재시작, 지원되지 않는 설정 |
| 레이아웃 | 늘어난 텍스트, 큰 글꼴 설정, RTL 콘텐츠 |
| 의미 | 중요한 사용자 여정에 대한 원어민 검토 |
프로세스의 언어 측면에는 현지화 테스트 프로세스를 활용하세요. 언어 승인과 기능 테스트 결과는 별개의 릴리스 근거로 확인할 수 있게 유지하세요.
Flutter 웹 현지화와 검색 노출은 따로 계획하세요
Flutter 웹은 현지화된 애플리케이션 리소스를 사용할 수 있지만, 인터페이스를 현지화한다고 해서 SEO에 적합한 다국어 웹사이트가 자동으로 만들어지지는 않습니다. 언어 선택, 라우팅, 메타데이터, 콘텐츠의 검색 노출은 여전히 아키텍처 차원에서 결정해야 합니다.
Flutter 웹 FAQ는 Flutter가 애플리케이션 경험에 중점을 둔다고 설명하며, 텍스트가 많은 정적 웹 콘텐츠에는 문서 중심 접근 방식을 권장합니다. 마케팅, 도움말, 편집 페이지가 자연 검색에서 성과를 내야 한다면 별도의 HTML 기반 페이지를 고려하세요.
앱과 이러한 공개 페이지의 용어를 일치시키세요. 두 화면이 서로 다른 렌더링 시스템을 사용하더라도, 검색으로 유입된 방문자가 현지화된 랜딩 페이지에서 애플리케이션으로 이동한 후에도 기능 이름을 알아볼 수 있어야 합니다.
규모를 키우기 전에 ARB 번역 프로세스를 검증하세요
ARB를 단순한 텍스트 값 파일이 아닌 구조화된 애플리케이션 리소스로 다루세요. 번역을 넘길 때는 키, 메타데이터, 플레이스홀더, 메시지 구문이 유지되어야 하며, 반환된 파일은 생성 단계와 앱 테스트를 통과해야 합니다.
Smartcat에서 문서화한 소프트웨어 프로젝트 형식에는 JSON, YAML, Android XML, iOS .strings, LocJSON 가져오기가 포함됩니다. 이 가이드에서 검토한 문서로는 ARB 기본 지원이나 테스트를 거친 ARB-JSON 변환 프로세스를 확인할 수 없습니다. 파일 확장자를 바꾼다고 호환성이 입증된다고 가정하지 마세요. 소프트웨어 프로젝트 문서를 참고하세요.
다음 내용은 이미 테스트된 커넥터 방법이 아니라 구현 팀과 함께 진행할 검증 절차 제안으로 활용하세요.
대표 샘플 선택
일반 문자열, 메타데이터, 타입이 지정된 플레이스홀더, 복수형, select가 포함된 작은 ARB 샘플을 선택합니다.
가져오기 및 내보내기 확인
@메타데이터와 ICU 메시지 처리 방식을 포함해 지원되는 가져오기/내보내기 방법을 제품 팀과 확인합니다.언어 자산과 맥락 제공
용어집, 필요한 경우 번역 메모리, 각 메시지에 대한 명확한 맥락을 제공합니다.
번역 및 구조 보호
프로그램 식별자와 구조를 보호하면서 사용자에게 표시되는 텍스트를 번역하고 검토합니다.
비교 및 복원
반환된 리소스를 원본 계약과 비교하고 예상 프로젝트 경로에 다시 배치합니다.
생성 및 테스트
프로젝트에 고정된 SDK 환경에서
flutter gen-l10n, 정적 분석, 관련 테스트를 실행합니다.검토 및 기록
현지화된 인터페이스를 검토하고 승인된 소스 버전을 기록합니다.
이 왕복 과정이 성공한 후에만 리포지토리 동기화를 자동화하세요. 소스 변경을 누가 처리할지, 검토 상태를 어떻게 무효화할지, 생성된 결과물을 어떻게 관리할지 정의하세요. ARB 리소스는 애플리케이션 프로세스의 기준 데이터로서 버전 관리하세요.
Flutter 번역 프로세스 검토받기
흔한 문제와 먼저 확인할 사항
| 증상 | 먼저 확인할 사항 |
|---|---|
| 생성된 import를 찾을 수 없음 | 생성이 성공적으로 실행되었고 import가 구성된 소스 출력 경로와 일치하는지 |
AppLocalizations.of(context)를 사용할 수 없음 | context가 애플리케이션의 현지화 provider 아래에 있는지 |
| 메시지 메서드에 예상치 못한 인수가 있음 | 템플릿 플레이스홀더 메타데이터와 생성된 API |
| select가 항상 대체 값을 표시함 | 애플리케이션 식별자가 리소스 분기와 정확히 일치하는지 |
| 로캘이 누락됨 | 리소스 파일, 지원 로캘, 로캘 결정 구성 |
| 내보낸 후 번역이 깨짐 | 왕복 과정 후에도 키, JSON 유효성, 메타데이터, ICU 구문이 유지되었는지 |
생성된 Dart 코드를 직접 수정하지 말고 가장 먼저 깨진 계약을 고치세요. 생성된 코드는 다시 생성될 수 있으므로, 그곳에서 수동으로 고친 내용은 다음에 리소스가 바뀔 때 사라질 가능성이 높습니다.
자주 묻는 질문
Flutter에서 ARB 파일이란 무엇인가요?
Application Resource Bundle은 현지화된 메시지와 선택적 메타데이터를 담은 JSON 기반 파일입니다. Flutter의 gen-l10n 프로세스는 ARB 리소스를 사용해 Dart 현지화 API를 생성합니다. 메타데이터로 메시지와 플레이스홀더를 설명할 수 있어 개발자와 번역가에게 각 키에 대한 더 명확한 계약을 제공합니다.
gen-l10n과 intl_utils의 차이점은 무엇인가요?
두 도구 모두 ARB 리소스에서 현지화 코드를 생성하지만, 구성 방식과 출력 규칙이 다른 별개의 도구입니다. gen-l10n은 Flutter의 기본 제공 프로세스에 포함되어 있습니다. 이 가이드를 작성하며 확인했을 때 intl_utils 패키지 페이지는 지원 중단으로 표시되어 있었으므로, 새로 구현할 때 선택하기 전에 유지 관리 상태를 확인하세요.
ARB 파일은 어떻게 번역해야 하나요?
안정적인 키, 플레이스홀더 식별자, 메타데이터, 필수 메시지 구조를 유지하면서 사용자에게 표시되는 메시지를 번역하세요. 이러한 요구 사항을 지원하는 프로세스를 사용한 다음, 반환된 파일로 생성 단계와 애플리케이션 테스트를 실행하세요. 원어민 검토에서는 구조적 유효성뿐 아니라 의미와 맥락도 평가해야 합니다.
Smartcat은 ARB 플레이스홀더와 복수형을 지원하나요?
여기서 검토한 소프트웨어 프로젝트 문서로는 ARB 기본 지원이나 모든 ARB 기능을 유지하는 검증된 변환 경로를 확인할 수 없습니다. 도입 전에 제품 팀과 가져오기/내보내기 방법을 확인하고 대표적인 왕복 과정을 검증하세요. 일반적인 JSON 지원만으로 ARB 호환성이 입증되지는 않습니다.
Flutter 현지화는 웹에서도 작동하나요?
Flutter 웹 애플리케이션도 현지화된 리소스와 로캘 선택을 사용할 수 있습니다. 검색 노출은 별개의 문제이며, 공개 마케팅 및 도움말 콘텐츠에는 HTML 기반 아키텍처가 더 유리할 수 있습니다. 모바일 현지화 설정으로 웹 SEO까지 해결된다고 가정하지 말고, 해당 웹 경험의 라우팅, 언어 선택, 메타데이터를 테스트하세요.
원하는 답변을 찾지 못하셨나요? 현지화 전문가와 상담하세요
번역 인계도 리소스 계약만큼 신뢰할 수 있게 만드세요
작은 ARB 샘플과 빌드에 필요한 검사 항목을 준비하세요. 모든 언어와 릴리스로 확장하기 전에 프로세스를 검토하세요.