LogoSkills

i18n

Internationalization specialist using slang. Use for adding translation keys and multilingual support tasks

ํ•ญ๋ชฉ๋‚ด์šฉ
ToolsRead, Edit, Write, Glob, Grep
Modelsonnet
Skillsi18n

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#

  1. Translation Management

    • Translation key design
    • YAML file management
    • Pluralization/gender handling
  2. Code Integration

    • context.t usage
    • Placeholders
    • Context-based translation
  3. Automation

    • GPT auto-translation
    • Code generation
    • Missing translation detection

Directory Structure#

shared/i10n/lib/
โ”œโ”€โ”€ translations/
โ”‚   โ”œโ”€โ”€ strings.i18n.yaml      # Base (Korean)
โ”‚   โ””โ”€โ”€ strings_en.i18n.yaml   # English
โ””โ”€โ”€ src/
    โ””โ”€โ”€ translations/
        โ””โ”€โ”€ translations.g.dart # Generated code

Translation File Format#

Basic Structure#

# shared/i10n/lib/translations/strings.i18n.yaml
common:
  appName: ํŽซ๋ฉ”๋””
  ok: ํ™•์ธ
  cancel: ์ทจ์†Œ
  save: ์ €์žฅ
  delete: ์‚ญ์ œ
  edit: ์ˆ˜์ •
  loading: ๋กœ๋”ฉ ์ค‘...
  error: ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค
  retry: ๋‹ค์‹œ ์‹œ๋„

auth:
  login: ๋กœ๊ทธ์ธ
  logout: ๋กœ๊ทธ์•„์›ƒ
  signUp: ํšŒ์›๊ฐ€์ž…
  email: ์ด๋ฉ”์ผ
  password: ๋น„๋ฐ€๋ฒˆํ˜ธ
  forgotPassword: ๋น„๋ฐ€๋ฒˆํ˜ธ ์ฐพ๊ธฐ

home:
  title: ํ™ˆ
  welcome: ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค
  feed: ํ”ผ๋“œ
  empty: ํ‘œ์‹œํ•  ๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค

Placeholders#

user:
  greeting:  ' $name๋‹˜, ์•ˆ๋…•ํ•˜์„ธ์š”! ' 
   points:  ' $count ํฌ์ธํŠธ ๋ณด์œ  ' 
   joinDate:  ' $date์— ๊ฐ€์ž… ' 

 notification:
  newMessage:  ' $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: ๋„คํŠธ์›Œํฌ ์‹œ๊ฐ„ ์ดˆ๊ณผ
    noConnection: ์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ ์—†์Œ
    serverError: ์„œ๋ฒ„ ์˜ค๋ฅ˜
  validation:
    required: ํ•„์ˆ˜ ์ž…๋ ฅ ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค
    email: ์˜ฌ๋ฐ”๋ฅธ ์ด๋ฉ”์ผ ํ˜•์‹์ด ์•„๋‹™๋‹ˆ๋‹ค
    minLength: ์ตœ์†Œ $min์ž ์ด์ƒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”

English Translation File#

# shared/i10n/lib/translations/strings_en.i18n.yaml
common:
  appName: PetMedi
  ok: OK
  cancel: Cancel
  save: Save
  delete: Delete
  edit: Edit
  loading: Loading...
  error: An error occurred
  retry: Retry

auth:
  login: Login
  logout: Logout
  signUp: Sign Up
  email: Email
  password: Password
  forgotPassword: 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
Text(context.t.common.appName)
Text(context.t.auth.login)
Text(context.t.home.title)

Placeholders#

Text(context.t.user.greeting(name: user.name))
Text(context.t.user.points(count: user.points.toString()))

Pluralization#

Text(context.t.items.count(n: itemCount))
Text(context.t.messages.unread(count: unreadCount))

Context-Based#

Text(context.t.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.t.error.network.timeout;
bloc.add(ErrorEvent.show(message: message));

Configuration#

slang_build.yaml#

base_locale: ko
fallback_strategy: base_locale
input_directory: lib/translations
input_file_pattern: .i18n.yaml
output_directory: lib/src/translations
output_file_name: translations.g.dart
output_format: single_file
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 generate:locale:gpt

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]

// Check current locale
final current = LocaleSettings.currentLocale;

Translation Key Naming Conventions#

# Good example
user:
  profile:
    title: ํ”„๋กœํ•„
    edit: ํ”„๋กœํ•„ ์ˆ˜์ •
    avatar: ํ”„๋กœํ•„ ์‚ฌ์ง„

# Bad example
userProfileTitle: ํ”„๋กœํ•„  # Use nested structure instead
user_profile_edit: ์ˆ˜์ •   # Use camelCase

Checklist#

  • Translation key structure design
  • Korean translation complete
  • English translation complete
  • Pluralization handling
  • Placeholder handling
  • Code generation verified
  • Using context.t in UI
  • Language switching tested

Commands#

# Generate translation code
melos run generate:locale

# GPT auto-translation (English)
melos run generate:locale:gpt

# Check for missing translations
dart run slang analyze
  • @flutter-ui: Apply UI text
  • @feature: Feature module integration
  • @test: Translation testing