/shared:i18n — 여러 나라 말로 번역해 주는 도우미#
| 항목 | 내용 |
|---|---|
| 실행 명령 | /shared:i18n |
| 별칭 | /i18n:add, /locale:create |
| 모델 | sonnet |
| 사용 도구 | Read, Edit, Write, Glob, Grep |
| 연계 스킬 | i18n |
한마디로#
앱 화면에 나오는 모든 글자(버튼, 안내 문구 등)를 11개 나라 언어로 번역해 관리해 주는 도우미입니다. 식당 메뉴판을 여러 나라 말로 만들어 손님이 누구든 알아볼 수 있게 하는 것과 같아요.
누가·언제 쓰나요#
- 앱에 새 화면이나 버튼을 추가했는데 여러 나라 사용자가 자기 언어로 봐야 할 때
- 한국어로 쓴 문구를 영어·일본어·중국어 등 다른 언어로도 보이게 하고 싶을 때
/shared:i18n 명령을 부르면 이 도우미가 활성화됩니다. (같은 뜻으로 /i18n:add, /locale:create
로도 부를 수 있어요.)
무엇을 해주나요#
- 번역할 문구마다 고유 이름표(번역 Key)를 붙여 정리해 줍니다.
- 지원 언어는 총 11개입니다 — 아랍어(ar), 독일어(de), 영어(en), 스페인어(es), 프랑스어(fr), 이탈리아어(it), 일본어(ja), 한국어(ko), 포르투갈어(pt), 러시아어(ru), 중국어 간체(zh_Hans).
- 단순한 문구뿐 아니라 "항목 1개 / 항목 5개"처럼 개수에 따라 달라지는 표현, 이름이 들어가는 문구("환영합니다, 홍길동님!"), 성별에 따라 달라지는 호칭까지 처리합니다.
-
번역 내용은 언어별 JSON 파일(예:
translations_ko.i18n.json)에 저장되고, 앱에서 실제로 쓰이는 코드(translations.g.dart)는 자동으로 만들어집니다.
어떻게 쓰나요#
번역 도우미는 아래와 같은 항목을 받아 일합니다.
key: 번역 이름표 (영문 snake_case, 필수) 예) home_title
value_ko: 한국어 번역 문구 (필수) 예) 홈
namespace: 어느 화면·영역의 문구인지 (선택) 예) home, auth
has_params: 이름·숫자 같은 값이 끼어드는지 여부 (선택)
번역 코드를 새로 만들거나 점검할 때는 아래 명령들을 씁니다.
# 번역 코드 자동 생성
melos run generate:locale
# 번역 파일이 올바른지 점검
melos run translate:slang:fix
# 모든 언어 자동 번역 (AI 사용)
melos run translate:slang:all
안에서 무슨 일이 벌어지나요#
대략 이런 순서로 일이 진행됩니다.
- 먼저 영어(기본) 번역 파일과 한국어 번역 파일에 새 문구를 적습니다.
- 이름이 끼어드는 문구(
{param}), 개수에 따라 달라지는 문구(복수형) 등의 표기 규칙이 맞는지 확인합니다. - 번역 설정 파일(
slang.yaml)이 올바른지 점검합니다. melos run generate:locale명령으로 앱이 실제로 사용할 번역 코드를 자동 생성합니다.- 화면에서
context.i10n방식으로 번역이 잘 불려 나오는지, 앱 최상단에 번역 공급기(TranslationProvider)가 자리잡았는지 확인합니다.
⚙️ 상세 옵션·실행 명세 (개발자 / AI 에이전트용)
Role#
Manages multi-language support system using Slang.
- Translation key management
- 11 language support (ar, de, en, es, fr, it, ja, ko, pt, ru, zh_Hans)
- context.i10n extension method
- Pluralization, gender, parameter handling
Activation Conditions#
/shared:i18nActivated when command is invoked- Invoked during translation and multi-language support work
Parameters#
| Parameter | Required | Description |
|---|---|---|
key | ✅ | Translation Key (snake_case) |
value_ko | ✅ | Korean Translation Value |
namespace | ❌ | Namespace (예: home, auth) |
has_params | ❌ | Whether parameters are included |
Package Structure#
shared/i10n/
├── lib/
│ ├── i10n.dart # Export 파일
│ └── src/
│ ├── translations/
│ │ ├── translations.i18n.json # default 번역 (영어)
│ │ ├── translations_ar.i18n.json # 아랍어
│ │ ├── translations_de.i18n.json # 독일어
│ │ ├── translations_es.i18n.json # 스페인어
│ │ ├── translations_fr.i18n.json # 프랑스어
│ │ ├── translations_it.i18n.json # 이탈리아어
│ │ ├── translations_ja.i18n.json # 일본어
│ │ ├── translations_ko.i18n.json # 한국어
│ │ ├── translations_pt.i18n.json # 포르투갈어
│ │ ├── translations_ru.i18n.json # 러시아어
│ │ ├── translations_zh_Hans.i18n.json # in progress국어 간체
│ │ └── translations.g.dart # 자동 생성
│ └── utils/
│ └── translation_extension.dart # context.i10n 확장
└── slang.yaml # Slang 설정Import Order (Required)#
// 1. Flutter standard
import 'package:flutter/widgets.dart';
// 2. Slang package
import 'package:slang_flutter/slang_flutter.dart';
// 3. Generated translations
import '../translations/translations.g.dart';
Core Patterns#
1. Main Export File#
/// i10n 패키지 export
library i10n;
export 'package:flutter_localizations/flutter_localizations.dart';
export 'package:slang_flutter/slang_flutter.dart';
export 'src/translations/translations.g.dart';
export 'src/utils/translation_extension.dart';
2. context.i10n Extension Method#
import 'package:flutter/widgets.dart';
import '../translations/translations.g.dart';
/// BuildContext 번역 확장
extension TranslationExtension on BuildContext {
/// 현재 로케일의 번역 객체 접근
///
/// Usage example:
/// ```dart
/// Text(context.i10n.home.title)
/// Text(context.i10n.common.confirm)
/// <pre><code> Translations get i10n => Translations.of(this);
}</code></pre>
### 3. Translation JSON Structure
<pre><code>// translations_ko.i18n.json (한국어)
{
"@@locale": "ko",
"common": {
"confirm": "확인",
"cancel": "취소",
"save": "저장",
"delete": "삭제",
"edit": "수정",
"close": "닫기",
"loading": "로딩 in progress...",
"error": "오류가 발생했습니다",
"retry": "다시 시도",
"search": "검색",
"noData": "데이터가 없습니다"
},
"auth": {
"login": "로그인",
"logout": "로그아웃",
"signUp": "회원가입",
"email": "이메일",
"password": "비밀번호",
"forgotPassword": "비밀번호 찾기"
},
"home": {
"title": "홈",
"welcome": "환영합니다, {name}님!",
"itemCount(context=count)": {
"zero": "항목이 없습니다",
"one": "1개의 항목",
"other": "{count}개의 항목"
}
},
"error": {
"network": "네트워크 연결을 확인해주세요",
"server": "서버 오류가 발생했습니다",
"unknown": "알 수 없는 오류가 발생했습니다",
"validation": {
"required": "{field}은(는) 필수입니다",
"email": "올바른 이메일 형식이 아닙니다",
"minLength": "{field}은(는) 최소 {min}자 이상이어야 합니다"
}
}
}</code></pre>
### 4. English Translation (Default)
<pre><code>// translations.i18n.json (영어 - default)
{
"@@locale": "en",
"common": {
"confirm": "Confirm",
"cancel": "Cancel",
"save": "Save",
"delete": "Delete",
"edit": "Edit",
"close": "Close",
"loading": "Loading...",
"error": "An error occurred",
"retry": "Retry",
"search": "Search",
"noData": "No data available"
},
"auth": {
"login": "Login",
"logout": "Logout",
"signUp": "Sign Up",
"email": "Email",
"password": "Password",
"forgotPassword": "Forgot Password"
},
"home": {
"title": "Home",
"welcome": "Welcome, {name}!",
"itemCount(context=count)": {
"zero": "No items",
"one": "1 item",
"other": "{count} items"
}
},
"error": {
"network": "Please check your network connection",
"server": "A server error occurred",
"unknown": "An unknown error occurred",
"validation": {
"required": "{field} is required",
"email": "Invalid email format",
"minLength": "{field} must be at least {min} characters"
}
}
}</code></pre>
### 5. Slang Configuration File
<pre><code># slang.yaml
base_locale: en
fallback_strategy: base_locale
input_directory: lib/src/translations
input_file_pattern: .i18n.json
output_directory: lib/src/translations
output_file_name: translations.g.dart
output_format: single_file
key_case: camel
key_map_case: camel
param_case: camel
string_interpolation: braces
flat_map: false
timestamp: false
statistics: true
translation_class_visibility: public
key_class_visibility: public</code></pre>
### 6. Usage in Widget
```dart
import 'package:flutter/material.dart';
import 'package:i10n/i10n.dart';
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(context.i10n.home.title),
),
body: Column(
children: [
// 단순 문자열
Text(context.i10n.common.confirm),
// 파라미터 포함
Text(context.i10n.home.welcome(name: '홍길동')),
// 복수형
Text(context.i10n.home.itemCount(count: 5)),
// in progress첩 키
Text(context.i10n.error.validation.required(field: '이름')),
],
),
);
}
}
7. App Setup#
import 'package:flutter/material.dart';
import 'package:i10n/i10n.dart';
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return TranslationProvider(
child: MaterialApp(
locale: TranslationProvider.of(context).flutterLocale,
supportedLocales: AppLocaleUtils.supportedLocales,
localizationsDelegates: GlobalMaterialLocalizations.delegates,
home: const HomePage(),
),
);
}
}
Translation Grammar#
Basic String#
{
" greeting " : " 안녕하세요 "
}Usage: context.i10n.greeting
Parameters#
{
" welcome " : " 환영합니다, {name}님! "
}Usage: context.i10n.welcome(name: '홍길동')
Plurals#
{
" itemCount(context=count) " : {
" zero " : " 항목 없음 " ,
" one " : " 1개 항목 " ,
" two " : " 2개 항목 " ,
" few " : " {count}개 항목 " ,
" many " : " {count}개 항목 " ,
" other " : " {count}개 항목 "
}
}Usage: context.i10n.itemCount(count: 5)
Gender#
{
" greetPerson(context=gender) " : {
" male " : " {name}씨 " ,
" female " : " {name}님 " ,
" other " : " {name}님 "
}
}Usage: context.i10n.greetPerson(gender: Gender.female, name: '김영희')
Nested Keys#
{
" error " : {
" validation " : {
" required " : " {field}은(는) 필수입니다 "
}
}
}Usage: context.i10n.error.validation.required(field: '이메일')
Build Commands#
# Generate translation code
melos run generate:locale
# Verify translation files
melos run translate:slang:fix
# Translate all languages (using AI)
melos run translate:slang:all
# Build specific package only
cd shared/i10n & & dart run build_runner build --delete-conflicting-outputsReference Files#
shared/i10n/lib/i10n.dart
shared/i10n/lib/src/utils/translation_extension.dart
shared/i10n/lib/src/translations/translations_ko.i18n.json
shared/i10n/slang.yamlChecklist#
- Write translations.i18n.json (English) default translation
- Write translations_ko.i18n.json (Korean) translation
- Verify parameter syntax {param} is correct
- Verify plural context=count syntax
- Verify slang.yaml configuration
- Execute melos run generate:locale
- Verify context.i10n extension method usage
- Place TranslationProvider at app root