flutter_pipwave_localization 0.2.1
flutter_pipwave_localization: ^0.2.1 copied to clipboard
Powerful and flexible localization package for Pipwave Flutter projects, featuring ICU message formatting, runtime locale switching, asset and dynamic translation file support.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_pipwave_localization/flutter_pipwave_localization.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
final localizationService = PWLocalizationService.instance;
return AnimatedBuilder(
animation: localizationService,
builder: (context, _) {
final locale = localizationService.currentLocale ?? const Locale('en');
const supported = [Locale('en'), Locale('id'), Locale('zh', 'CN')];
return MaterialApp(
title: 'PW Localization Example (Download test)',
theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
home: const HomePage(),
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
PWLocalizationDelegate(
instance: localizationService,
locale: locale,
supportedLocales: supported,
assetPath: 'assets/sdk_translations',
downloadedPath: 'example/translations',
defaultLocaleTag: 'en',
),
],
supportedLocales: supported,
locale: locale,
);
},
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
static const _assetPath = 'assets/sdk_translations';
static const _downloadedPath = 'example/translations';
static const _defaultLocaleTag = 'en';
static const _baseUrl =
'https://staging-assets.pipwave.com/locale/translation/sdk/ai-agent/mobile';
int _count = 0;
bool _switching = false;
String _selectedTag = 'en';
void _incrementCounter() {
setState(() {
_count++;
});
}
Future<void> _selectLocaleTag(String tag) async {
if (_switching) return;
setState(() {
_switching = true;
_selectedTag = tag;
});
try {
// Requirement: use en.json as default (asset), and when selecting `id`
// or `zh-CN`, download then rebuild using the notifier.
if (tag != _defaultLocaleTag) {
await PWLocalizationService.instance.downloadLanguageFiles(_baseUrl, [
tag,
]);
}
await PWLocalizationProvider.of(context).initialize(
assetPath: _assetPath,
downloadedPath: _downloadedPath,
defaultLanguage: _defaultLocaleTag,
locale: PWLocalizationService.localeFromTag(tag),
);
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('Locale switch failed: $e')));
}
} finally {
if (mounted) {
setState(() {
_switching = false;
});
}
}
}
@override
Widget build(BuildContext context) {
final currentTag = PWLocalizationService.instance.currentLocaleTag ?? 'en';
return Scaffold(
appBar: AppBar(
title: Text(context.tr('supportAssistant')),
actions: [
PopupMenuButton<String>(
onSelected: _selectLocaleTag,
itemBuilder: (context) => const [
PopupMenuItem(value: 'en', child: Text('English (en)')),
PopupMenuItem(value: 'id', child: Text('Bahasa Indonesia (id)')),
PopupMenuItem(value: 'zh-CN', child: Text('中文(简体)(zh-CN)')),
],
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
context.tr('aiResponseDisclaimer'),
style: Theme.of(context).textTheme.headlineSmall,
textAlign: TextAlign.center,
),
const SizedBox(height: 20),
Text(
context.plural('newMessages', _count),
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
Text(
context.plural(
'amountUpdated',
_count,
namedArgs: {'number': _count},
),
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
Text(
context.tr('serverIsBusy'),
style: Theme.of(context).textTheme.bodyLarge,
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
Text('currentLocaleTag: $currentTag'),
Text('selectedTag: $_selectedTag'),
Text('downloading: $_switching'),
const SizedBox(height: 24),
Text(
_switching ? context.tr('loading') : context.tr('today'),
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: _switching ? null : _incrementCounter,
child: Text(context.tr('confirm')),
),
const SizedBox(height: 8),
OutlinedButton(
onPressed: _switching
? null
: () => _selectLocaleTag(_selectedTag),
child: Text(context.tr('retry')),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _switching ? null : () => _selectLocaleTag(_selectedTag),
tooltip: 'Download + apply $_selectedTag',
child: _switching
? const CircularProgressIndicator.adaptive()
: const Icon(Icons.download),
),
);
}
}