flutter_pipwave_localization 0.0.4+1
flutter_pipwave_localization: ^0.0.4+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 LocalizationExampleApp());
}
class LocalizationExampleApp extends StatelessWidget {
const LocalizationExampleApp({super.key});
@override
Widget build(BuildContext context) {
return LocalizationProvider(
startLocale: const Locale('en'),
assetPath: 'assets/sdk_translations',
downloadedPath: 'example/translations',
supportedLocales: const [Locale('en'), Locale('id'), Locale('zh', 'CN')],
child: const MyApp(),
);
}
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: LocalizationService.instance,
builder: (context, _) {
final locale =
LocalizationService.instance.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,
CustomLocalizationDelegate(
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 LocalizationService.instance.downloadLanguageFiles(_baseUrl, [tag]);
}
await LocalizationProvider.of(context).initialize(
assetPath: _assetPath,
downloadedPath: _downloadedPath,
defaultLanguage: _defaultLocaleTag,
locale: LocalizationService.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 = LocalizationService.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.tr('newMessages', args: [_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),
),
);
}
}