도움 센터

Flutter 현지화: ARB 파일, Intl 및 자동화

Flutter 내장 현지화 시스템은 Application Resource Bundle(ARB) 파일과 intl 패키지를 사용해 어떤 언어에서도 완전한 네이티브 경험을 제공합니다. 이 가이드는 프로젝트 설정, ARB 형식 세부사항부터 언어 전환, 복수형 처리, 그리고 l10n.dev를 이용한 번역 자동화까지 모두 다룹니다.

Flutter 현지화란?

Flutter 현지화는 앱을 여러 언어와 지역에 맞게 조정하는 공식 방법입니다. 번역된 문자열을 저장하는 ARB 파일과 타입 안전 Dart 접근자를 생성하는 flutter_gen 코드 생성기를 사용합니다. 실행 시 Flutter는 기기 로케일에 맞는 ARB 파일을 선택하며, 프로그래밍 방식으로 로케일을 변경해도 재시작이 필요 없습니다.

프로젝트 설정

Flutter 현지화 파이프라인은 pubspec.yaml과 l10n.yaml 두 개의 구성 파일로 구동됩니다. pubspec.yaml에서 코드 생성을 활성화하고 Flutter에게 ARB 디렉터리를 지정하세요.

1. pubspec.yaml 업데이트

flutter_localizations와 intl을 의존성에 추가하고 generate 플래그를 활성화해 Flutter가 ARB 파일에서 자동으로 Dart 현지화 클래스를 생성하도록 하세요.

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any

flutter:
  generate: true

2. l10n.yaml 생성

프로젝트 루트에 l10n.yaml 파일을 두어 ARB 디렉터리, 템플릿 파일, 생성될 출력 파일 이름을 설정하세요.

arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart

ARB 파일 형식

ARB(Application Resource Bundle)는 Flutter 국제화를 위해 특별히 설계된 JSON 기반 형식입니다. 각 키는 번역 가능한 문자열에 매핑되며, 선택적 메타데이터 키(@로 시작)는 설명, 자리표시자 정의, 번역가를 위한 문맥을 포함합니다.

  • @@locale: 파일의 로케일을 선언합니다(예: "en", "fr", "zh_CN"). l10n.dev가 대상 언어 코드로 자동 업데이트합니다.
  • @@last_modified: 마지막 수정 시각입니다. l10n.dev가 번역 파일 생성 시 현재 UTC 타임스탬프로 자동 설정합니다.
  • @key 메타데이터: 설명, 예시, 자리표시자 같은 메타데이터 항목은 기본적으로 번역되지 않고 그대로 유지되어 번역가 문맥을 보존합니다. translateMetadata 설정을 활성화하면 이들도 번역됩니다.
  • 자리표시자 및 ICU 메시지: 문자열은 명명된 자리표시자({name})와 복수형 및 선택을 위한 ICU 메시지 구문을 포함할 수 있으며, 번역 시 올바르게 보존됩니다.

원본 ARB 파일 (영어)

{
  "@@locale": "en",
  "@@last_modified": "2026-01-15T10:30:00Z",

  "appTitle": "My App",
  "@appTitle": {
    "description": "The title of the application"
  },

  "welcome": "Welcome, {name}!",
  "@welcome": {
    "description": "Welcome message shown on the home screen",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "Alice"
      }
    }
  },

  "unreadMessages": "{count, plural, =0{No unread messages} =1{1 unread message} other{{count} unread messages}}",
  "@unreadMessages": {
    "description": "Number of unread messages",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}

번역된 ARB 파일 (프랑스어)

번역 후 UI 문자열은 현지화되고 메타데이터 구조는 그대로 유지됩니다. l10n.dev가 @@locale과 @@last_modified를 자동으로 업데이트합니다.

{
  "@@locale": "fr",
  "@@last_modified": "2026-01-15T10:30:01Z",

  "appTitle": "Mon Application",
  "@appTitle": {
    "description": "The title of the application"
  },

  "welcome": "Bienvenue, {name} !",
  "@welcome": {
    "description": "Welcome message shown on the home screen",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "Alice"
      }
    }
  },

  "unreadMessages": "{count, plural, =0{Aucun message non lu} =1{1 message non lu} other{{count} messages non lus}}",
  "@unreadMessages": {
    "description": "Number of unread messages",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}

파일 명명 규칙

ARB 파일은 기본 접두사(app_) 뒤에 로케일 코드와 .arb 확장자를 붙이는 단순한 명명 패턴을 따릅니다. Flutter와 l10n.dev는 언어와 지역 코드를 구분할 때 밑줄(_)을 사용합니다.

ARB 파일은 하이픈이 아닌 밑줄을 사용합니다 - app_en_US.arb, app_zh_CN.arb로 작성하세요. app_en-US.arb나 app_zh-CN.arb는 사용하지 마세요.
# Default pattern (recommended)
app_en.arb
app_fr.arb
app_en_US.arb          # Locale with region (underscore format)
app_zh_CN.arb          # Chinese Simplified

# Custom prefix patterns also supported
my_app_en.arb
my_app_fr.arb

# Note: ARB files use underscores, not hyphens
# ✓  app_en_US.arb
# ✗  app_en-US.arb

프로젝트 구조

모든 ARB 파일을 lib/ 내의 전용 l10n 폴더에 정리하세요. Flutter 코드 생성기는 l10n.yaml의 arb-dir 설정을 기반으로 자동으로 이들을 인식하고 바로 사용할 수 있는 Dart 클래스를 출력합니다.

lib/
├── l10n/
│   ├── app_en.arb        ← Source (English)
│   ├── app_fr.arb        ← French
│   ├── app_de.arb        ← German
│   ├── app_ja.arb        ← Japanese
│   ├── app_zh_CN.arb     ← Chinese Simplified
│   └── app_es.arb        ← Spanish
├── main.dart
└── ...

# Generated output (do not edit manually)
.dart_tool/
└── flutter_gen/
    └── gen_l10n/
        └── app_localizations.dart

초기화

생성된 Dart 현지화 클래스를 MaterialApp에 연결하려면 localizationsDelegates와 supportedLocales를 제공하세요. 그러면 Flutter가 기기 로케일에 맞는 ARB 데이터를 올바르게 해결합니다.

MaterialApp 설정

필수 4개 위임자(생성된 AppLocalizations.delegate와 Flutter SDK 3개 위임자)를 전달하고, 앱이 지원하는 모든 로케일을 나열하세요. 위젯 트리 어디서든 AppLocalizations.of(context)!를 사용해 번역된 문자열에 접근할 수 있습니다.

import 'package:flutter/material.dart';
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(
      title: 'My App',

      // Required delegates
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],

      // Supported locales
      supportedLocales: AppLocalizations.supportedLocales,

      home: const HomePage(),
    );
  }
}

// Use in a widget
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;

    return Scaffold(
      appBar: AppBar(title: Text(l10n.appTitle)),
      body: Center(child: Text(l10n.welcome('Alice'))),
    );
  }
}

실행 중 언어 전환

Flutter는 MaterialApp의 locale 속성을 업데이트해 실행 중에 앱 로케일을 전환할 수 있게 합니다. 일반적인 패턴은 StatefulWidget이나 상태 관리 솔루션에서 Locale을 보유하고 변경 콜백을 노출하는 것입니다. 위젯 트리는 새 로케일로 자동 재빌드됩니다.

// Manage locale state at the app level
class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Locale _locale = const Locale('en');

  void _changeLocale(Locale locale) {
    setState(() => _locale = locale);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      locale: _locale,
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: AppLocalizations.supportedLocales,
      home: SettingsPage(onLocaleChange: _changeLocale),
    );
  }
}

// Language selector widget
class LanguageSelector extends StatelessWidget {
  final void Function(Locale) onLocaleChange;

  const LanguageSelector({super.key, required this.onLocaleChange});

  @override
  Widget build(BuildContext context) {
    return DropdownButton<Locale>(
      value: Localizations.localeOf(context),
      items: AppLocalizations.supportedLocales
          .map((locale) => DropdownMenuItem(
                value: locale,
                child: Text(locale.toLanguageTag()),
              ))
          .toList(),
      onChanged: (locale) {
        if (locale != null) onLocaleChange(locale);
      },
    );
  }
}

복수형 처리

Flutter는 ARB 파일 내 복수형 처리를 위해 ICU 메시지 구문을 사용합니다. intl 패키지는 모든 CLDR 복수형 범주를 처리하며, 대상 언어 규칙에 따라 올바른 형태를 자동 적용합니다.

  • ARB 문자열 값 내에서 {count, plural, =0{...} =1{...} other{...}} 구문을 사용하세요.
  • @key 메타데이터에서 count 자리표시자를 int 타입으로 선언하세요.
  • l10n.dev는 아랍어, 러시아어, 폴란드어 등 복잡한 언어를 포함해 각 대상 언어별 필요한 모든 복수형을 자동 생성합니다.
{
  "cartItems": "{count, plural, =0{Your cart is empty} =1{1 item in your cart} other{{count} items in your cart}}",
  "@cartItems": {
    "description": "Cart item count",
    "placeholders": {
      "count": { "type": "int" }
    }
  },

  "daysLeft": "{days, plural, =1{1 day left} other{{days} days left}}",
  "@daysLeft": {
    "description": "Days remaining",
    "placeholders": {
      "days": { "type": "int" }
    }
  }
}

l10n.dev의 완전한 ARB 지원

l10n.dev는 Flutter ARB 워크플로우와 원활히 작동하도록 설계되었습니다. 원본 ARB 파일을 업로드하면 정확하고 올바른 구조의 번역을 받을 수 있습니다:

  • 자동 메타데이터 업데이트: @@locale은 대상 언어 코드로, @@last_modified는 현재 UTC 타임스탬프로 자동 업데이트됩니다.
  • 메타데이터 번역 제어: 기본적으로 @key 메타데이터 항목(설명, 예시, 문맥)은 번역되지 않고 그대로 유지되어 번역가 노트를 보존합니다. translateMetadata 설정을 활성화하면 UI 문자열과 함께 번역됩니다.
  • 사용자 지정 파일 접두사: app_en.arb, my_app_en_US.arb, strings_fr.arb 등 모든 명명 패턴을 지원합니다.
  • 밑줄 로케일 형식: ARB 로케일 코드는 하이픈이 아닌 밑줄(en_US, zh_CN)을 사용하며, l10n.dev가 이를 정확히 처리해 생성된 파일을 Flutter 프로젝트에 바로 적용할 수 있습니다.
  • 복수형 인식: ICU 복수형은 CLDR 규칙에 따라 모든 대상 언어별로 생성되어 번역 후 수동 복수형 편집이 필요 없습니다.

npm으로 번역 자동화

ai-l10n npm 패키지를 사용해 명령줄이나 CI/CD 파이프라인에서 원본 ARB 파일을 번역하세요. 한 번 설치 후 한 명령으로 여러 언어로 번역할 수 있습니다.

# Install the CLI
npm install ai-l10n

# Translate your source ARB to multiple languages
npx ai-l10n translate lib/l10n/app_en.arb \
  --languages fr,de,ja,zh_CN,es,ko

Flutter 빌드에 통합

ai-l10n을 Flutter 빌드 프로세스에 직접 연결하여 앱이 컴파일되기 전에 항상 번역이 최신 상태로 유지되도록 할 수 있습니다. 두 가지 일반적인 방법으로 package.json 스크립트나 Makefile을 사용하는 방법이 있습니다.

package.json 스크립트를 통한 방법

translate 스크립트를 추가하고 npm의 prebuild 라이프사이클 훅을 사용하여 모든 빌드 전에 자동으로 실행되도록 하세요. npm run build:android(또는 build:ios / build:web)를 실행하면 ai-l10n이 먼저 번역을 수행한 다음 Flutter로 작업을 넘깁니다.

{
  "scripts": {
    "translate": "ai-l10n translate lib/l10n/app_en.arb --languages fr,de,ja,zh_CN,es,ko --update",
    "prebuild": "npm run translate",
    "build:android": "flutter build apk",
    "build:ios": "flutter build ios",
    "build:web": "flutter build web"
  }
}

Makefile을 통한 방법

팀에서 Make를 사용하는 경우, translate 타겟을 선언하고 각 빌드 타겟이 이에 의존하도록 설정하세요. make build-android(또는 build-ios / build-all)를 실행하면 flutter build를 호출하기 전에 모든 대상 언어가 번역됩니다.

LANGUAGES = fr,de,ja,zh_CN,es,ko

translate:
	npx ai-l10n translate lib/l10n/app_en.arb --languages $(LANGUAGES) --update

build-android: translate
	flutter build apk

build-ios: translate
	flutter build ios

build-web: translate
	flutter build web

build-all: translate
	flutter build apk
	flutter build ios
	flutter build web

CI/CD 통합, 점진적 업데이트, 여러 파일 일괄 번역, GitHub Actions 워크플로 예제는 현지화 자동화 가이드에서 확인하세요.

VS Code 확장

l10n.dev VS Code 확장은 Flutter ARB 번역을 편집기 내에서 바로 제공합니다. ARB 파일을 우클릭해 VS Code를 떠나지 않고 대상 언어로 번역하세요.

VS Code에서 작동 방식:

  1. 원본 ARB 파일(예: app_en.arb)을 편집기에서 엽니다.
  2. 편집기에서 우클릭 후 "Translate JSON"을 선택하세요.
  3. 하나 이상의 대상 언어(예: 프랑스어, 일본어, 독일어)를 선택하세요.
  4. 확장이 원본 옆에 현지화된 ARB 파일을 생성하며 @@locale과 @@last_modified를 자동으로 업데이트합니다.

실제 예제 보기

다음은 VS Code 내에서 Flutter ARB 파일을 우즈베크어로 번역하는 실시간 예제입니다:

Flutter ARB localization in VS Code

Flutter 앱 현지화 시작하기

전 세계 사용자에게 다가갈 준비가 되셨나요? l10n.dev 작업 공간에서 ARB 파일을 직접 번역하거나, npm CLI로 자동화하거나, VS Code 내에서 바로 번역할 수 있습니다: