국제화(i18n) — intl 패키지와 ARB 파일로 다국어 지원
국제화(i18n) — intl 패키지와 ARB 파일로 다국어 지원
글로벌 앱을 만들거나, 한국어/영어 전환이 필요한 앱이라면 국제화(i18n)는 필수입니다. Flutter의 공식 방법인 flutter_localizations + intl + ARB 파일 조합을 정리해보겠습니다.
설정
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.19.0
flutter:
generate: true # 코드 생성 활성화
# l10n.yaml (프로젝트 루트에 생성)
arb-dir: lib/l10n
template-arb-file: app_ko.arb
output-localization-file: app_localizations.dart
ARB 파일 작성
ARB(Application Resource Bundle)는 JSON 기반의 번역 파일입니다.
// lib/l10n/app_ko.arb (템플릿 - 한국어)
{
"@@locale": "ko",
"appTitle": "내 앱",
"@appTitle": {
"description": "앱 제목"
},
"hello": "안녕하세요, {name}님!",
"@hello": {
"description": "인사말",
"placeholders": {
"name": {
"type": "String",
"example": "홍길동"
}
}
},
"itemCount": "{count, plural, =0{항목 없음} =1{1개 항목} other{{count}개 항목}}",
"@itemCount": {
"description": "항목 수 (복수형)",
"placeholders": {
"count": {
"type": "int"
}
}
},
"settings": "설정",
"logout": "로그아웃",
"confirmDelete": "정말 삭제하시겠습니까?"
}
// lib/l10n/app_en.arb (영어)
{
"@@locale": "en",
"appTitle": "My App",
"hello": "Hello, {name}!",
"itemCount": "{count, plural, =0{No items} =1{1 item} other{{count} items}}",
"settings": "Settings",
"logout": "Logout",
"confirmDelete": "Are you sure you want to delete?"
}
코드 생성 및 설정
# 코드 생성 (자동으로 실행되기도 함)
flutter gen-l10n
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
// 지원하는 로케일 목록
supportedLocales: AppLocalizations.supportedLocales,
// 로케일 델리게이트
localizationsDelegates: AppLocalizations.localizationsDelegates,
// 기본 로케일 (선택)
locale: const Locale('ko'),
home: const HomeScreen(),
);
}
}
번역 사용
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
// AppLocalizations 인스턴스 가져오기
final l10n = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(title: Text(l10n.appTitle)),
body: Column(
children: [
Text(l10n.hello('심정훈')), // 안녕하세요, 심정훈님!
Text(l10n.itemCount(0)), // 항목 없음
Text(l10n.itemCount(1)), // 1개 항목
Text(l10n.itemCount(42)), // 42개 항목
Text(l10n.settings), // 설정
],
),
);
}
}
언어 전환
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Locale _locale = const Locale('ko');
void _changeLocale(Locale locale) {
setState(() => _locale = locale);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
locale: _locale,
supportedLocales: AppLocalizations.supportedLocales,
localizationsDelegates: AppLocalizations.localizationsDelegates,
home: HomeScreen(onLocaleChanged: _changeLocale),
);
}
}
// 언어 전환 버튼
DropdownButton<Locale>(
value: currentLocale,
items: const [
DropdownMenuItem(value: Locale('ko'), child: Text('한국어')),
DropdownMenuItem(value: Locale('en'), child: Text('English')),
],
onChanged: (locale) {
if (locale != null) widget.onLocaleChanged(locale);
},
)
날짜, 숫자 포맷팅
import 'package:intl/intl.dart';
// 날짜 포맷팅
final now = DateTime.now();
DateFormat.yMMMMd('ko').format(now); // 2026년 9월 7일
DateFormat.Hm('ko').format(now); // 14:30
DateFormat('yyyy-MM-dd').format(now); // 2026-09-07
// 숫자 포맷팅
NumberFormat.currency(locale: 'ko', symbol: '₩').format(29900);
// ₩29,900
NumberFormat.compact(locale: 'ko').format(1234567);
// 123만
NumberFormat.decimalPattern('ko').format(1234567);
// 1,234,567
NumberFormat.percentPattern('ko').format(0.756);
// 76%
ARB 파일 고급 문법
{
"gender": "{gender, select, male{그는} female{그녀는} other{그 분은}} 개발자입니다",
"@gender": {
"placeholders": {
"gender": {"type": "String"}
}
},
"lastLogin": "마지막 로그인: {date}",
"@lastLogin": {
"placeholders": {
"date": {
"type": "DateTime",
"format": "yMd"
}
}
}
}
팁: Extension으로 간결하게 접근
extension L10nContext on BuildContext {
AppLocalizations get l10n => AppLocalizations.of(this)!;
}
// 사용
Text(context.l10n.appTitle) // 더 간결
정리
flutter_localizations+intl+ ARB 파일이 Flutter 공식 i18n 방법입니다- ARB 파일에서
{name}플레이스홀더,plural,select등을 지원합니다 flutter gen-l10n명령으로 타입 안전한 코드가 자동 생성됩니다intl패키지로 날짜, 숫자, 통화 포맷팅도 로케일에 맞게 처리합니다- Extension을 활용하면
context.l10n으로 간결하게 접근할 수 있습니다
댓글 로딩 중...