
** Made by 🦏 zoocityboy with ❤️ for the Jaspr community **
Jaspr Localizations
Internationalization and localization support for Jaspr applications with ARB file generation and Flutter-like APIs.
Features
- 🔒 Type-Safe Localization - Compile-time safety with generated Dart classes
- 📦 ARB File Support - Industry-standard format compatible with Flutter
- 🌐 Platform-Aware Detection - Automatic language detection from browser/system
- 🔄 Dynamic Locale Switching - Runtime locale changes with automatic UI rebuilding
- 📝 ICU MessageFormat - Support for plurals, selects, and complex formatting
- ⚡ Performance Optimized - Minimal runtime overhead using InheritedComponent
Installation
Add to your pubspec.yaml:
dependencies:
jaspr_localizations: ^1.0.0
dev_dependencies:
build_runner: ^2.4.0
Install dependencies:
dart pub get
Quick Start
1. Configure Localization
Create l10n.yaml in your project root:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: generated/l10n.dart
output-class: AppLocalizations
2. Create ARB Files
Create translation files in lib/l10n/:
lib/l10n/app_en.arb:
{
"@@locale": "en",
"appTitle": "My Application",
"welcomeMessage": "Welcome, {name}!",
"@welcomeMessage": {
"placeholders": {
"name": {"type": "String"}
}
}
}
lib/l10n/app_es.arb:
{
"@@locale": "es",
"appTitle": "Mi Aplicación",
"welcomeMessage": "¡Bienvenido, {name}!"
}
3. Generate Code
dart run build_runner build
Usage
Basic Setup
Wrap your app with JasprLocalizations:
import 'package:jaspr/jaspr.dart';
import 'package:jaspr_localizations/jaspr_localizations.dart';
import 'generated/l10n.dart';
@client
class App extends StatelessComponent {
@override
Component build(BuildContext context) {
return JasprLocalizations(
supportedLocales: [
Locale('en', 'US'),
Locale('es', 'ES'),
Locale('fr', 'FR'),
],
initialLocale: getCurrentLocale(), // Auto-detect user's language
delegates: [AppLocalizations.delegate],
builder: (context, locale) => HomePage(),
);
}
}
Accessing Translations
Use the generated localization class:
class HomePage extends StatelessComponent {
@override
Component build(BuildContext context) {
final l10n = AppLocalizations.of(context);
return div([
h1([text(l10n.appTitle)]),
p([text(l10n.welcomeMessage('Jaspr'))]),
]);
}
}
Changing Locale
Create a language switcher:
class LanguageSwitcher extends StatelessComponent {
@override
Component build(BuildContext context) {
final provider = JasprLocalizationProvider.of(context);
final currentLocale = provider.currentLocale;
return div([
for (final locale in provider.supportedLocales)
button(
classes: currentLocale == locale ? 'active' : '',
onClick: () => JasprLocalizationProvider.setLocale(context, locale),
[text(locale.languageCode.toUpperCase())],
),
]);
}
}
Locale Override with withLocale
The JasprLocalizations.withLocale method allows you to display specific content in a different locale without changing the app's global locale.
Use Cases
- Previews - Show content in multiple languages simultaneously
- Side-by-side translations - Compare translations
- Testing - Verify translations without app-wide changes
Example: Multi-Language Preview
class LanguagePreview extends StatelessComponent {
@override
Component build(BuildContext context) {
return div([
h2([text('Preview in Multiple Languages')]),
// English
div([
h3([text('English')]),
JasprLocalizations.withLocale(
locale: Locale('en', 'US'),
child: WelcomeMessage(),
),
]),
// Spanish
div([
h3([text('Spanish')]),
JasprLocalizations.withLocale(
locale: Locale('es', 'ES'),
child: WelcomeMessage(),
),
]),
// French
div([
h3([text('French')]),
JasprLocalizations.withLocale(
locale: Locale('fr', 'FR'),
child: WelcomeMessage(),
),
]),
]);
}
}
class WelcomeMessage extends StatelessComponent {
@override
Component build(BuildContext context) {
final l10n = AppLocalizations.of(context);
return p([text(l10n.welcomeMessage('User'))]);
}
}
Example: Side-by-Side Translation
class TranslationComparison extends StatelessComponent {
@override
Component build(BuildContext context) {
return div([
// Current language
div([
h4([text('Current')]),
ProductDescription(),
]),
// Preview in another language
div([
h4([text('Translation')]),
JasprLocalizations.withLocale(
locale: Locale('es', 'ES'),
child: ProductDescription(),
),
]),
]);
}
}
Important: The overridden locale must be in the supportedLocales list.
Platform-Aware Detection
Automatically detect user's language:
// Get current locale
final locale = getCurrentLocale();
// Use in app
JasprLocalizations(
initialLocale: getCurrentLocale(),
...
)
Detection sources:
- Browser:
navigator.language - Server:
Intl.getCurrentLocale() - Fallback:
'en'
ICU MessageFormat
Pluralization
{
"itemCount": "{count, plural, =0{No items} =1{One item} other{{count} items}}"
}
l10n.itemCount(0); // "No items"
l10n.itemCount(1); // "One item"
l10n.itemCount(5); // "5 items"
Select Messages
{
"greeting": "{gender, select, male{Mr.} female{Ms.} other{}} Hello"
}
l10n.greeting('male'); // "Mr. Hello"
l10n.greeting('female'); // "Ms. Hello"
Troubleshooting
Build fails:
dart run build_runner clean
dart run build_runner build --delete-conflicting-outputs
Translations missing:
- All ARB files must have the same keys
- Run
build_runnerafter changes
Locale not changing:
- Use
JasprLocalizations, not justJasprLocalizationProvider - Verify locale is in
supportedLocales
Resources
License
MIT License - see LICENSE
Libraries
- builder
- jaspr_localizations
- Jaspr Localizations - Internationalization and localization for Jaspr applications.