i18n Templates#
Internationalization translation pattern templates.
Template A: Basic Translation Structure#
ko.i18n.json (Korean, base)#
{
" common " : {
" app_name " : " Unibook " ,
" ok " : " ํ์ธ " ,
" cancel " : " ์ทจ์ " ,
" save " : " ์ ์ฅ " ,
" delete " : " ์ญ์ " ,
" edit " : " ์์ " ,
" close " : " ๋ซ๊ธฐ " ,
" loading " : " ๋ก๋ฉ ์ค... " ,
" error " : " ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค " ,
" retry " : " ๋ค์ ์๋ " ,
" no_data " : " ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค "
},
" auth " : {
" login " : " ๋ก๊ทธ์ธ " ,
" logout " : " ๋ก๊ทธ์์ " ,
" sign_up " : " ํ์๊ฐ์
" ,
" email " : " ์ด๋ฉ์ผ " ,
" password " : " ๋น๋ฐ๋ฒํธ " ,
" forgot_password " : " ๋น๋ฐ๋ฒํธ๋ฅผ ์์ผ์
จ๋์? "
},
" navigation " : {
" home " : " ํ " ,
" search " : " ๊ฒ์ " ,
" mypage " : " ๋ง์ดํ์ด์ง " ,
" settings " : " ์ค์ "
}
}
en.i18n.json (English)#
{
" common " : {
" app_name " : " Unibook " ,
" ok " : " OK " ,
" cancel " : " Cancel " ,
" save " : " Save " ,
" delete " : " Delete " ,
" edit " : " Edit " ,
" close " : " Close " ,
" loading " : " Loading... " ,
" error " : " An error occurred " ,
" retry " : " Retry " ,
" no_data " : " No data available "
},
" auth " : {
" login " : " Login " ,
" logout " : " Logout " ,
" sign_up " : " Sign Up " ,
" email " : " Email " ,
" password " : " Password " ,
" forgot_password " : " Forgot password? "
},
" navigation " : {
" home " : " Home " ,
" search " : " Search " ,
" mypage " : " My Page " ,
" settings " : " Settings "
}
}
Template B: Parameter Patterns#
User Greetings#
{
" user " : {
" greeting " : " {name}๋, ์๋
ํ์ธ์! " ,
" welcome_back " : " {name}๋, ๋ค์ ์ค์
จ๊ตฐ์! " ,
" member_since " : " {date}์ ๊ฐ์
" ,
" points " : " {count} ํฌ์ธํธ ๋ณด์ " ,
" level_info " : " {level} ๋ฑ๊ธ ํ์์
๋๋ค "
}
}
Dart Usage Example#
// User greeting
Text(context.i10n.user.greeting(name: user.displayName))
// Points display
Text(context.i10n.user.points(count: user.points.toString()))
// Join date display
Text(context.i10n.user.member_since(date: DateFormat('yyyy-MM-dd').format(user.createdAt)))
Template C: Pluralization Patterns#
Item Counts#
{
" items " : {
" count(param=n) " : {
" zero " : " ํญ๋ชฉ ์์ " ,
" one " : " ํญ๋ชฉ 1๊ฐ " ,
" other " : " ํญ๋ชฉ {n}๊ฐ "
}
},
" cart " : {
" item_count(param=count) " : {
" zero " : " ์ฅ๋ฐ๊ตฌ๋๊ฐ ๋น์ด์์ต๋๋ค " ,
" one " : " ์ฅ๋ฐ๊ตฌ๋์ ์ํ 1๊ฐ " ,
" other " : " ์ฅ๋ฐ๊ตฌ๋์ ์ํ {count}๊ฐ "
}
},
" notifications " : {
" unread(param=count) " : {
" zero " : " ์ฝ์ง ์์ ์๋ฆผ ์์ " ,
" one " : " ์ฝ์ง ์์ ์๋ฆผ 1๊ฐ " ,
" other " : " ์ฝ์ง ์์ ์๋ฆผ {count}๊ฐ "
}
},
" messages " : {
" count(param=n) " : {
" zero " : " ๋ฉ์์ง ์์ " ,
" one " : " ๋ฉ์์ง 1๊ฐ " ,
" other " : " ๋ฉ์์ง {n}๊ฐ "
}
},
" followers " : {
" count(param=n) " : {
" zero " : " ํ๋ก์ ์์ " ,
" one " : " ํ๋ก์ 1๋ช
" ,
" other " : " ํ๋ก์ {n}๋ช
"
}
}
}
Dart Usage Example#
// Cart item count
Text(context.i10n.cart.item_count(count: cartItems.length))
// Notification badge
Badge(
label: Text(context.i10n.notifications.unread(count: unreadCount)),
)
// Follower count
Text(context.i10n.followers.count(n: followerCount))
Template D: Context-Based Patterns#
Enum-Based Translation#
{
" pet " : {
" type(context=PetType) " : {
" dog " : " ๊ฐ์์ง " ,
" cat " : " ๊ณ ์์ด " ,
" bird " : " ์ " ,
" fish " : " ๋ฌผ๊ณ ๊ธฐ " ,
" hamster " : " ํ์คํฐ " ,
" other " : " ๊ธฐํ "
}
},
" order " : {
" status(context=OrderStatus) " : {
" pending " : " ๋๊ธฐ ์ค " ,
" confirmed " : " ํ์ธ๋จ " ,
" shipping " : " ๋ฐฐ์ก ์ค " ,
" delivered " : " ๋ฐฐ์ก ์๋ฃ " ,
" cancelled " : " ์ทจ์๋จ "
}
},
" payment " : {
" method(context=PaymentMethod) " : {
" card " : " ์นด๋ ๊ฒฐ์ " ,
" bank " : " ๊ณ์ข์ด์ฒด " ,
" kakao " : " ์นด์นด์คํ์ด " ,
" naver " : " ๋ค์ด๋ฒํ์ด "
}
}
}
Dart Enum Definition#
// lib/domain/entity/pet_type.dart
enum PetType {
dog,
cat,
bird,
fish,
hamster,
other,
}
// Usage
Text(context.i10n.pet.type(context: pet.type))
Text(context.i10n.order.status(context: order.status))
Template E: Error Message Patterns#
Form Validation Errors#
{
" validation " : {
" required " : " ํ์ ์
๋ ฅ ํญ๋ชฉ์
๋๋ค " ,
" email " : {
" invalid " : " ์ฌ๋ฐ๋ฅธ ์ด๋ฉ์ผ ํ์์ด ์๋๋๋ค " ,
" exists " : " ์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ์ด๋ฉ์ผ์
๋๋ค "
},
" password " : {
" too_short " : " ๋น๋ฐ๋ฒํธ๋ ์ต์ 8์ ์ด์์ด์ด์ผ ํฉ๋๋ค " ,
" too_weak " : " ๋น๋ฐ๋ฒํธ๊ฐ ๋๋ฌด ์ฝํฉ๋๋ค " ,
" mismatch " : " ๋น๋ฐ๋ฒํธ๊ฐ ์ผ์นํ์ง ์์ต๋๋ค "
},
" phone " : {
" invalid " : " ์ฌ๋ฐ๋ฅธ ์ ํ๋ฒํธ ํ์์ด ์๋๋๋ค "
}
},
" error " : {
" network " : " ๋คํธ์ํฌ ์ฐ๊ฒฐ์ ํ์ธํด์ฃผ์ธ์ " ,
" server " : " ์๋ฒ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค " ,
" timeout " : " ์์ฒญ ์๊ฐ์ด ์ด๊ณผ๋์์ต๋๋ค " ,
" unauthorized " : " ๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค " ,
" forbidden " : " ์ ๊ทผ ๊ถํ์ด ์์ต๋๋ค " ,
" not_found " : " ์์ฒญํ ์ ๋ณด๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค " ,
" unknown " : " ์ ์ ์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค "
}
}
Dart Usage Example#
// Form validation
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return context.i10n.validation.required;
}
if (!EmailValidator.validate(value)) {
return context.i10n.validation.email.invalid;
}
return null;
},
)
// Error handling
result.fold(
(failure) => ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(context.i10n.error.network)),
),
(success) => navigateToHome(),
);
Template F: Date/Time Patterns#
Relative Time#
{
" time " : {
" just_now " : " ๋ฐฉ๊ธ ์ " ,
" minutes_ago " : " {minutes}๋ถ ์ " ,
" hours_ago " : " {hours}์๊ฐ ์ " ,
" days_ago " : " {days}์ผ ์ " ,
" weeks_ago " : " {weeks}์ฃผ ์ " ,
" months_ago " : " {months}๊ฐ์ ์ " ,
" years_ago " : " {years}๋
์ " ,
" in_minutes " : " {minutes}๋ถ ํ " ,
" in_hours " : " {hours}์๊ฐ ํ " ,
" in_days " : " {days}์ผ ํ "
}
}
Dart Usage Example#
String getRelativeTime(BuildContext context, DateTime dateTime) {
final now = DateTime.now();
final difference = now.difference(dateTime);
if (difference.inMinutes < 1) {
return context.i10n.time.just_now;
} else if (difference.inMinutes < 60) {
return context.i10n.time.minutes_ago(minutes: difference.inMinutes.toString());
} else if (difference.inHours < 24) {
return context.i10n.time.hours_ago(hours: difference.inHours.toString());
} else if (difference.inDays < 7) {
return context.i10n.time.days_ago(days: difference.inDays.toString());
} else if (difference.inDays < 30) {
return context.i10n.time.weeks_ago(weeks: (difference.inDays ~/ 7).toString());
} else if (difference.inDays < 365) {
return context.i10n.time.months_ago(months: (difference.inDays ~/ 30).toString());
} else {
return context.i10n.time.years_ago(years: (difference.inDays ~/ 365).toString());
}
}
Template G: Rich Text Patterns#
Text with Links#
{
" legal " : {
" terms_agreement " : " ์ด์ฉ์ฝ๊ด์ ๋์ํฉ๋๋ค. < link > ์์ธํ ๋ณด๊ธฐ < /link > " ,
" privacy_agreement " : " ๊ฐ์ธ์ ๋ณด ์ฒ๋ฆฌ๋ฐฉ์นจ์ ๋์ํฉ๋๋ค. < link > ์์ธํ ๋ณด๊ธฐ < /link > "
},
" marketing " : {
" promotion " : " < highlight > ํน๋ณ ํ ์ธ < /highlight > ์ด๋ฒคํธ๊ฐ ์งํ ์ค์
๋๋ค! " ,
" new_feature " : " ์๋ก์ด ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋์์ต๋๋ค. < link > ํ์ธํ๊ธฐ < /link > "
}
}
Dart Usage Example#
// Rich text builder
Text.rich(
context.i10n.legal.terms_agreement(
link: (text) => TextSpan(
text: text,
style: TextStyle(
color: AppColors.primary,
decoration: TextDecoration.underline,
),
recognizer: TapGestureRecognizer()
..onTap = () => Navigator.pushNamed(context, '/terms'),
),
),
)
// Highlighted text
Text.rich(
context.i10n.marketing.promotion(
highlight: (text) => TextSpan(
text: text,
style: TextStyle(
color: AppColors.accent,
fontWeight: FontWeight.bold,
),
),
),
)
Slang Configuration Template#
slang.yaml#
# Slang configuration file
base_locale: ko
fallback_strategy: base_locale
# Input settings
input_directory: lib/src/json
input_file_pattern: .i18n.json
# Output settings
output_directory: lib/src/translations
output_file_name: translations.g.dart
output_format: single_file
# Case settings
key_case: snake
key_map_case: snake
param_case: snake
# Other settings
string_interpolation: braces
flat_map: false
timestamp: true
statistics: true
translate_var: translations
# Interface generation (if needed)
interfaces:
PageData:
paths:
- home
- settings
- profile
GPT Translation Hint Template#
JSON does not support inline comments, so translation hints for slang_gpt
are provided via the reserved @ metadata keys (for example @app_name)
rather than comments.
{
" common " : {
" app_name " : " Unibook " ,
" @app_name " : {
" description " : " App name - do not translate, keep as Unibook "
}
},
" buttons " : {
" submit " : " ์ ์ถ " ,
" @submit " : { " description " : " Button text - keep short and clear (Submit) " },
" confirm " : " ํ์ธ " ,
" @confirm " : { " description " : " Button text - Confirm / OK " }
},
" pet " : {
" type(context=PetType) " : {
" dog " : " ๊ฐ์์ง " ,
" cat " : " ๊ณ ์์ด "
},
" @type " : {
" description " : " Pet species - maintain friendly tone; dog=dog, cat=cat "
}
}
}