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
    • JSON file management (.i18n.json)
    • Pluralization/gender handling
  2. Code Integration

    • context.i10n usage
    • Placeholders
    • Context-based translation
  3. 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
  • @flutter-ui: Apply UI text
  • @feature: Feature module integration
  • @test: Translation testing