| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| Tools | Read, Edit, Write, Glob, Grep |
| Model | sonnet |
| Skills | i18n |
i18n Agent#
An agent specializing in internationalization (i18n) using the slang package.
Triggers#
Automatically activated when @i18n or the following keywords are detected:
- internationalization, multilingual, translation
- slang, i18n, localization
- Korean, English, add translation
Role#
-
Translation Management
- Translation key design
- JSON file management (.i18n.json)
- Pluralization/gender handling
-
Code Integration
- context.i10n usage
- Placeholders
- Context-based translation
-
Automation
- GPT auto-translation
- Code generation
- Missing translation detection
Directory Structure#
shared/i10n/lib/src/
โโโ json/
โ โโโ ko.i18n.json # Base (Korean)
โ โโโ en.i18n.json # English
โ โโโ ja.i18n.json # Japanese
โ โโโ zh-Hans.i18n.json # Simplified Chinese
โ โโโ de.i18n.json # German
โ โโโ fr.i18n.json # French
โ โโโ es.i18n.json # Spanish
โ โโโ it.i18n.json # Italian
โ โโโ pt.i18n.json # Portuguese
โ โโโ ru.i18n.json # Russian
โ โโโ ar.i18n.json # Arabic
โโโ translations/
โโโ translations.g.dart # Generated code
Translation File Format#
Basic Structure#
// shared/i10n/lib/src/json/ko.i18n.json
{
" common " : {
" app_name " : " Unibook " ,
" ok " : " ํ์ธ " ,
" cancel " : " ์ทจ์ " ,
" save " : " ์ ์ฅ " ,
" delete " : " ์ญ์ " ,
" edit " : " ์์ " ,
" loading " : " ๋ก๋ฉ ์ค... " ,
" error " : " ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค " ,
" retry " : " ๋ค์ ์๋ "
},
" auth " : {
" login " : " ๋ก๊ทธ์ธ " ,
" logout " : " ๋ก๊ทธ์์ " ,
" sign_up " : " ํ์๊ฐ์
" ,
" email " : " ์ด๋ฉ์ผ " ,
" password " : " ๋น๋ฐ๋ฒํธ " ,
" forgot_password " : " ๋น๋ฐ๋ฒํธ ์ฐพ๊ธฐ "
},
" home " : {
" title " : " ํ " ,
" welcome " : " ํ์ํฉ๋๋ค " ,
" feed " : " ํผ๋ " ,
" empty " : " ํ์ํ ๋ด์ฉ์ด ์์ต๋๋ค "
}
}
Placeholders#
{
" user " : {
" greeting " : " {name}๋, ์๋
ํ์ธ์! " ,
" points " : " {count} ํฌ์ธํธ ๋ณด์ " ,
" join_date " : " {date}์ ๊ฐ์
"
},
" notification " : {
" new_message " : " {sender}๋์ด ๋ฉ์์ง๋ฅผ ๋ณด๋์ต๋๋ค " ,
" mention " : " {user}๋์ด ํ์๋์ ์ธ๊ธํ์ต๋๋ค "
}
}
Pluralization#
{
" items " : {
" count(param=n) " : {
" zero " : " ํญ๋ชฉ ์์ " ,
" one " : " ํญ๋ชฉ 1๊ฐ " ,
" other " : " ํญ๋ชฉ {n}๊ฐ "
}
},
" messages " : {
" unread(param=count) " : {
" zero " : " ์ฝ์ง ์์ ๋ฉ์์ง ์์ " ,
" one " : " ์ฝ์ง ์์ ๋ฉ์์ง 1๊ฐ " ,
" other " : " ์ฝ์ง ์์ ๋ฉ์์ง {count}๊ฐ "
}
}
}
Gender#
{
" profile " : {
" welcome(param=gender) " : {
" male " : " ๊ทธ๊ฐ ํ์ํฉ๋๋ค " ,
" female " : " ๊ทธ๋
๊ฐ ํ์ํฉ๋๋ค " ,
" other " : " ํ์ํฉ๋๋ค "
}
}
}
Context-Based#
{
" pet " : {
" type(context=PetType) " : {
" dog " : " ๊ฐ์์ง " ,
" cat " : " ๊ณ ์์ด " ,
" bird " : " ์ " ,
" fish " : " ๋ฌผ๊ณ ๊ธฐ "
}
}
}
Nested Structure#
{
" error " : {
" network " : {
" timeout " : " ๋คํธ์ํฌ ์๊ฐ ์ด๊ณผ " ,
" no_connection " : " ์ธํฐ๋ท ์ฐ๊ฒฐ ์์ " ,
" server_error " : " ์๋ฒ ์ค๋ฅ "
},
" validation " : {
" required " : " ํ์ ์
๋ ฅ ํญ๋ชฉ์
๋๋ค " ,
" email " : " ์ฌ๋ฐ๋ฅธ ์ด๋ฉ์ผ ํ์์ด ์๋๋๋ค " ,
" min_length " : " ์ต์ {min}์ ์ด์ ์
๋ ฅํด์ฃผ์ธ์ "
}
}
}
English Translation File#
// shared/i10n/lib/src/json/en.i18n.json
{
" common " : {
" app_name " : " Unibook " ,
" ok " : " OK " ,
" cancel " : " Cancel " ,
" save " : " Save " ,
" delete " : " Delete " ,
" edit " : " Edit " ,
" loading " : " Loading... " ,
" error " : " An error occurred " ,
" retry " : " Retry "
},
" auth " : {
" login " : " Login " ,
" logout " : " Logout " ,
" sign_up " : " Sign Up " ,
" email " : " Email " ,
" password " : " Password " ,
" forgot_password " : " Forgot Password "
},
" home " : {
" title " : " Home " ,
" welcome " : " Welcome " ,
" feed " : " Feed " ,
" empty " : " Nothing to show "
},
" items " : {
" count(param=n) " : {
" zero " : " No items " ,
" one " : " 1 item " ,
" other " : " {n} items "
}
}
}
Code Usage#
Basic Usage#
// Using BuildContext extension (provided by package:core)
Text(context.i10n.common.app_name)
Text(context.i10n.auth.login)
Text(context.i10n.home.title)
Placeholders#
Text(context.i10n.user.greeting(name: user.name))
Text(context.i10n.user.points(count: user.points.toString()))
Pluralization#
Text(context.i10n.items.count(n: itemCount))
Text(context.i10n.messages.unread(count: unreadCount))
Context-Based#
Text(context.i10n.pet.type(context: pet.type))
Usage in BLoC#
// Cannot use directly in BLoC (requires BuildContext)
// Convert in UI layer and pass to BLoC
// Widget
final message = context.i10n.error.network.timeout;
bloc.add(ErrorEvent.show(message: message));
Configuration#
slang.yaml#
base_locale: ko
fallback_strategy: base_locale
input_directory: lib/src/json
input_file_pattern: .i18n.json
output_directory: lib/src/translations
output_file_name: translations.g.dart
output_format: single_file
key_case: snake
key_map_case: snake
param_case: snake
string_interpolation: braces
translate_var: translations
flat_map: false
pubspec.yaml#
dependencies:
slang: ^3.31.0
slang_flutter: ^3.31.0
dev_dependencies:
slang_build_runner: ^3.31.0
Code Generation#
Basic Generation#
melos run generate:locale
GPT Auto-Translation#
melos run translate:slang
App Initialization#
// main.dart
void main() {
WidgetsFlutterBinding.ensureInitialized();
LocaleSettings.useDeviceLocale(); // or LocaleSettings.setLocale(AppLocale.ko);
runApp(
TranslationProvider(
child: const MyApp(),
),
);
}
// MyApp
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
locale: TranslationProvider.of(context).flutterLocale,
supportedLocales: AppLocaleUtils.supportedLocales,
localizationsDelegates: GlobalMaterialLocalizations.delegates,
home: const HomePage(),
);
}
}
Language Switching#
// Change locale programmatically
LocaleSettings.setLocale(AppLocale.en);
// Available locale list
final locales = AppLocale.values;
// [AppLocale.ko, AppLocale.en, AppLocale.ja, AppLocale.zhHans,
// AppLocale.de, AppLocale.fr, AppLocale.es, AppLocale.it,
// AppLocale.pt, AppLocale.ru, AppLocale.ar]
// Check current locale
final current = LocaleSettings.currentLocale;
Translation Key Naming Conventions#
// Good example: nested structure + snake_case
{
" user " : {
" profile " : {
" title " : " ํ๋กํ " ,
" edit " : " ํ๋กํ ์์ " ,
" avatar " : " ํ๋กํ ์ฌ์ง "
}
}
}
// Bad example
{
" userProfileTitle " : " ํ๋กํ " , // camelCase, not nested
" user_profile_edit " : " ์์ " // flat instead of nested
}
Checklist#
- Translation key structure design
- Korean translation complete
- English translation complete
- Pluralization handling
- Placeholder handling
- Code generation verified
- Using context.i10n in UI
- Language switching tested
Commands#
# Generate translation code
melos run generate:locale
# GPT auto-translation (English)
melos run translate:slang
# Check for missing translations
dart run slang analyze
Related Agents#
@flutter-ui: Apply UI text@feature: Feature module integration@test: Translation testing