translocale_flutter 0.0.1
translocale_flutter: ^0.0.1 copied to clipboard
Flutter localization package for TransLocale service with over-the-air translations support. Simplifies internationalization and enables updating translations without app releases.
TransLocale Flutter #
A Flutter localization package for the TransLocale service with Over-The-Air (OTA) update support.
Features #
- Standard Flutter Localization Integration: Works with Flutter's built-in localization system
- Over-The-Air Updates: Update translations without releasing a new app version
- Caching: Efficiently caches translations for offline use
- Fallback Support: Gracefully falls back to embedded translations when needed
- Versioning: Smart update detection to minimize network usage
- Web Support: Works on all Flutter platforms including web
- Testable Architecture: Designed for easy testing with dependency injection
- Comprehensive API: Compatible with TransLocale server API structure
- Background Processing: Uses isolates for heavy operations to keep the UI responsive
- Flutter Gen-L10N Support: Seamless integration with Flutter's
flutter gen-l10n
tool
Getting Started #
Installation #
Add TransLocale to your pubspec.yaml
:
dependencies:
translocale_flutter: ^1.0.0
TransLocale CLI #
The TransLocale CLI is a command-line tool that helps you manage translations for your Flutter app. It's especially useful for downloading ARB files that can be used with Flutter's gen-l10n
tool.
Installing the CLI #
# Install globally via pub
dart pub global activate translocale_cli
Make sure the Dart SDK's bin directory is in your PATH environment variable. The CLI will be available as the translocale
command.
Setting Up Your Project #
- Initialize TransLocale in your project:
translocale init --api-key YOUR_API_KEY
This creates a translocale.yaml
configuration file in your project root.
- Download ARB files from TransLocale:
translocale download -a
This downloads the latest translations as ARB files to your lib/l10n
directory.
- You can specify options to customize the download:
# Download only specific languages
translocale download --languages en,es,fr
# Download to a custom directory
translocale download --output custom/path/l10n
# List available languages
translocale download --list
Complete Translation Workflow #
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Development │ │ TransLocale │ │ Production App │
│ Environment │ │ Server │ │ │
└───────┬────────┘ └───────┬────────┘ └───────┬────────┘
│ │ │
│ 1. Create initial │ │
│ ARB files │ │
│ │ │
│ 2. Upload translations│ │
│─────────────────────>│ │
│ │ │
│ │ 3. Translate in the │
│ │ TransLocale UI │
│ │ │
│ 4. Download latest │ │
│<─────────────────────│ │
│ translations │ │
│ │ │
│ 5. Generate Dart │ │
│ code with │ │
│ flutter gen-l10n │ │
│ │ │
│ 6. Build app with │ │
│ TransLocale │ │
│ Flutter package │ │
│ │ │
└──────────────────────┼──────────────────────>
│ │
│ 7. OTA updates │
│─────────────────────>│
│ │
Integrating with Flutter gen-l10n #
Once you have downloaded the ARB files, you can integrate them with Flutter's localization system:
- Configure
l10n.yaml
in your project root:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
synthetic-package: false
- Run the Flutter gen-l10n tool:
flutter gen-l10n
Alternatively, you can use the CLI wrapper:
translocale gen-l10n
- Initialize TransLocale Flutter with the downloaded locale support:
await TransLocale.initialize(
apiKey: 'YOUR_API_KEY',
apiUrl: 'https://api.translocale.io', // Optional: Pass in a custom API URL if you're using a self-hosted instance
);
Quick Setup #
For a one-command setup that runs init, download, and gen-l10n in sequence:
translocale setup --api-key YOUR_API_KEY
Continuous Integration Workflow #
For a complete translation workflow:
- Development: Create keys and base translations in your ARB files
- Upload to TransLocale: Upload base translations to the TransLocale platform
- Translation Process: Translate in the TransLocale platform
- Pre-build: Use
translocale download
to download latest translations - Build: Run
translocale gen-l10n
to generate Dart code - Runtime: Use TransLocale Flutter for OTA updates to translations
This workflow ensures you have type-safe translations during development while still benefiting from OTA updates.
CLI Commands #
Command | Description |
---|---|
translocale init |
Initialize TransLocale in your project |
translocale download |
Download translations as ARB files |
translocale gen-l10n |
Generate Dart classes from ARB files |
translocale setup |
One-command setup (init + download + gen-l10n) |
translocale fix-arb |
Fix problematic ARB files |
For detailed help on any command, use:
translocale --help
Simple Initialization #
The simplest way to initialize TransLocale is with the comprehensive initialize
method:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize TransLocale with everything you need in one call
await TransLocale.initialize(
apiKey: 'YOUR_API_KEY',
preloadTranslations: true, // Load translations during initialization
checkForUpdates: true, // Check for OTA updates during initialization
fallbackLocale: const Locale('en'), // Used if API connection fails
);
runApp(MyApp());
}
This method handles:
- Setting up configuration
- Automatically detecting available locales from the API
- Preloading translations for all locales
- Checking for OTA updates
You can also manually specify supportedLocales
if you want to limit which locales your app supports:
await TransLocale.initialize(
apiKey: 'YOUR_API_KEY',
supportedLocales: [const Locale('en'), const Locale('es')], // Optional, detected from API if not provided
fallbackLocale: const Locale('en'),
);
Add TransLocale's Delegate to Your App #
To use TransLocale in your app, add its localization delegate:
MaterialApp(
// ...
supportedLocales: TransLocale.supportedLocales,
localizationsDelegates: [
TransLocaleDelegate(
supportedLocales: TransLocale.supportedLocales,
otaEnabled: true,
),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
// ...
)
Access Translations #
You can access translations using the TransLocaleLocalizations
class:
final localizations = Localizations.of<TransLocaleLocalizations>(
context,
TransLocaleLocalizations,
);
if (localizations != null) {
// Simple translation
Text(localizations.translate('welcome'));
// Translation with parameters
Text(localizations.translateWithParams(
'greeting',
{'name': 'John'},
));
}
Update Translations #
To update translations from the server:
try {
final result = await TransLocale.updateTranslations();
if (result.isSuccess) {
print('Successfully updated translations');
} else {
print('No updates available: ${result.message}');
}
} catch (e) {
print('Error updating translations: $e');
}
Integration with Flutter gen-l10n #
TransLocale Flutter seamlessly integrates with Flutter's standard flutter gen-l10n
tool, allowing you to combine type-safe localization with OTA updates.
1. Set Up Flutter gen-l10n #
First, set up your project with standard Flutter localization:
- Create a
l10n.yaml
file in your project root:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
- Create your ARB files in the
lib/l10n
directory:
// lib/l10n/app_en.arb
{
"helloWorld": "Hello World",
"@helloWorld": {
"description": "The conventional greeting"
}
}
- Run the gen-l10n tool:
flutter gen-l10n
This will generate your app_localizations.dart
file as usual.
2. Wrap the Generated Delegates with TransLocale #
Update your MaterialApp
to use TransLocale with the generated delegates:
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:translocale_flutter/translocale_flutter.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// Wrap the standard delegates with TransLocale OTA support
localizationsDelegates: TransLocale.wrapDelegates([
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
]),
supportedLocales: AppLocalizations.supportedLocales,
home: MyHomePage(),
);
}
}
3. Access OTA Translations Directly #
If you prefer not to generate extension methods, you can use the direct OTA access method:
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:translocale_flutter/translocale_flutter.dart';
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final strings = AppLocalizations.of(context)!;
// Use the extension method to access OTA translations
final helloWorld = strings.otaString('helloWorld', strings.helloWorld);
return Text(helloWorld);
}
}
Updating Translations #
To fetch the latest translations from the TransLocale service:
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _isLoading = false;
Future<void> _updateTranslations() async {
setState(() {
_isLoading = true;
});
try {
final response = await TransLocale.updateTranslations();
if (response.isSuccess) {
// Translations updated successfully
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Translations updated successfully')),
);
} else {
// No updates available or error occurred
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(response.message)),
);
}
} finally {
setState(() {
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
// ...
}
}
Advanced Usage #
Performance Optimization with Isolates #
TransLocale Flutter uses isolates for heavy operations to keep your UI responsive:
- JSON Parsing: Large translation files are parsed in the background
- File I/O Operations: Reading and writing files happens off the main thread
- Translation Processing: Complex operations like updating translations run in isolates
This means that even with large translation sets across many languages, your app's UI will remain responsive during:
- Initial loading of translations
- Fetching updates from the API
- Processing and storing translation data
// The isolate implementation is used automatically, but you can
// also access it directly for custom operations if needed
import 'package:translocale_flutter/translocale_flutter.dart';
// Run your own heavy computation in an isolate
final result = await TransLocale.computeAsync(myHeavyFunction, myParameters);
Pre-release Translations #
// Enable pre-release translations
TransLocale.setPreRelease(true);
Working with Fallbacks #
The package supports locale fallbacks, as defined by the server:
// When a locale doesn't have translations for a specific key,
// it will automatically fall back to the server-defined fallback locale
// For example, 'en_CA' might fall back to 'en' for missing translations
// You can also access the fallbacks programmatically:
final translationService = TransLocale.translationService as TranslationService;
final fallbacks = translationService.getFallbacks();
print('Fallbacks: $fallbacks'); // Example: {en_CA: en, es_MX: es}
Server API Compatibility #
This package is designed to work with the official TransLocale server API. The implementation is compatible with the same API endpoints and response formats used by the TransLocale CLI tools.
Testing #
The TransLocale package is designed with testability in mind. You can easily mock the services for unit testing:
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:translocale_flutter/translocale_flutter.dart';
// Create mocks
class MockApiService extends Mock implements IApiService {}
class MockTranslationService extends Mock implements ITranslationService {}
class MockIsolateRunner extends Mock implements IsolateRunner {}
void main() {
test('TransLocale updateTranslations delegates to translation service', () async {
// Arrange
final mockApiService = MockApiService();
final mockTranslationService = MockTranslationService();
final mockIsolateRunner = MockIsolateRunner();
// Setup the mock response
when(() => mockTranslationService.updateTranslations(
locales: any(named: 'locales'),
forceUpdate: any(named: 'forceUpdate'),
)).thenAnswer((_) async => UpdateResponse.success({'en_US': true}));
// Initialize with mocks
TransLocale.init(
apiKey: 'test_key',
apiService: mockApiService,
translationService: mockTranslationService,
isolateRunner: mockIsolateRunner,
);
// Act
final response = await TransLocale.updateTranslations();
// Assert
expect(response.isSuccess, true);
verify(() => mockTranslationService.updateTranslations(
locales: null,
forceUpdate: false,
)).called(1);
// Reset for other tests
TransLocale.reset();
});
}
License #
This project is licensed under the MIT License - see the LICENSE file for details.