Initial support for localization
This commit is contained in:
parent
72103e1b48
commit
6f6bc29a72
|
|
@ -0,0 +1,20 @@
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: \n"
|
||||||
|
"POT-Creation-Date: 2021-09-29 09:59+0200\n"
|
||||||
|
"PO-Revision-Date: 2021-09-29 10:58+0200\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"Language: en\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: Poedit 3.0\n"
|
||||||
|
"X-Poedit-Basepath: .\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
msgid "Main menu"
|
||||||
|
msgstr "Main menu"
|
||||||
|
|
||||||
|
msgid "Use dark mode"
|
||||||
|
msgstr "Use dark mode"
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: \n"
|
||||||
|
"POT-Creation-Date: 2021-09-29 09:59+0200\n"
|
||||||
|
"PO-Revision-Date: 2021-09-29 10:58+0200\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"Language: en\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: Poedit 3.0\n"
|
||||||
|
"X-Poedit-Basepath: .\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
msgid "Main menu"
|
||||||
|
msgstr "Menu principal"
|
||||||
|
|
||||||
|
msgid "Use dark mode"
|
||||||
|
msgstr "Utiliser le mode sombre"
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: \n"
|
||||||
|
"POT-Creation-Date: 2021-09-29 09:59+0200\n"
|
||||||
|
"PO-Revision-Date: 2021-09-29 10:00+0200\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: Poedit 3.0\n"
|
||||||
|
"X-Poedit-Basepath: .\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"Language: en\n"
|
||||||
|
|
||||||
|
msgid "Main menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use dark mode"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -52,10 +52,12 @@ void main() async {
|
||||||
setWindowMaxSize(const Size(692, 580));
|
setWindowMaxSize(const Size(692, 580));
|
||||||
gOperatingSystems = await loadOperatingSystems(false);
|
gOperatingSystems = await loadOperatingSystems(false);
|
||||||
AppVersion.packageInfo = await PackageInfo.fromPlatform();
|
AppVersion.packageInfo = await PackageInfo.fromPlatform();
|
||||||
runApp(MultiProvider(
|
runApp(
|
||||||
providers: [
|
MultiProvider(
|
||||||
ChangeNotifierProvider(create: (_) => AppTheme()),
|
providers: [
|
||||||
],
|
ChangeNotifierProvider(create: (_) => AppTheme()),
|
||||||
builder: (context, _) => const App(),
|
],
|
||||||
));
|
builder: (context, _) => const App(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:quickgui/src/globals.dart';
|
import 'package:quickgui/src/globals.dart';
|
||||||
|
import 'package:quickgui/src/i18n/quickgui_localizations_delegate.dart';
|
||||||
import 'package:quickgui/src/mixins/preferences_mixin.dart';
|
import 'package:quickgui/src/mixins/preferences_mixin.dart';
|
||||||
import 'package:quickgui/src/model/app_theme.dart';
|
import 'package:quickgui/src/model/app_theme.dart';
|
||||||
import 'package:quickgui/src/pages/main_page.dart';
|
import 'package:quickgui/src/pages/main_page.dart';
|
||||||
|
|
@ -20,7 +22,7 @@ class _AppState extends State<App> with PreferencesMixin {
|
||||||
builder: (context, AsyncSnapshot<bool?> snapshot) {
|
builder: (context, AsyncSnapshot<bool?> snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
if (snapshot.data != null) {
|
if (snapshot.data != null) {
|
||||||
context.read<AppTheme>().useDarkMode = snapshot.data!;
|
context.read<AppTheme>().useDarkModeSilently = snapshot.data!;
|
||||||
}
|
}
|
||||||
return Consumer<AppTheme>(
|
return Consumer<AppTheme>(
|
||||||
builder: (context, appTheme, _) => MaterialApp(
|
builder: (context, appTheme, _) => MaterialApp(
|
||||||
|
|
@ -28,6 +30,33 @@ class _AppState extends State<App> with PreferencesMixin {
|
||||||
darkTheme: ThemeData.dark(),
|
darkTheme: ThemeData.dark(),
|
||||||
themeMode: appTheme.themeMode,
|
themeMode: appTheme.themeMode,
|
||||||
home: const MainPage(title: 'Quickgui - A Flutter frontend for Quickget and Quickemu'),
|
home: const MainPage(title: 'Quickgui - A Flutter frontend for Quickget and Quickemu'),
|
||||||
|
supportedLocales: const [
|
||||||
|
/// List of locales we have translations for.
|
||||||
|
Locale('en', ''),
|
||||||
|
Locale('fr', ''),
|
||||||
|
Locale('fr', 'CH'),
|
||||||
|
],
|
||||||
|
localizationsDelegates: [
|
||||||
|
QuickguiLocalizationsDelegate(),
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
],
|
||||||
|
localeListResolutionCallback: (locales, supportedLocales) {
|
||||||
|
if (locales != null) {
|
||||||
|
for (var locale in locales) {
|
||||||
|
var supportedLocale =
|
||||||
|
supportedLocales.where((element) => element.languageCode == locale.languageCode && element.countryCode == locale.countryCode);
|
||||||
|
if (supportedLocale.isNotEmpty) {
|
||||||
|
return supportedLocale.first;
|
||||||
|
}
|
||||||
|
supportedLocale = supportedLocales.where((element) => element.languageCode == locale.languageCode);
|
||||||
|
if (supportedLocale.isNotEmpty) {
|
||||||
|
return supportedLocale.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:quickgui/src/i18n/quickgui_localizations.dart';
|
||||||
|
|
||||||
|
extension I18nExt on BuildContext {
|
||||||
|
t(String key) => QuickguiLocalizations.of(this).t(key);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gettext/gettext.dart';
|
||||||
|
import 'package:gettext_parser/gettext_parser.dart' as gettext_parser;
|
||||||
|
|
||||||
|
class QuickguiLocalizations {
|
||||||
|
final _gt = Gettext(
|
||||||
|
onWarning: ((message) {
|
||||||
|
if (kDebugMode) {
|
||||||
|
// ignore: avoid_print
|
||||||
|
print('$message\n');
|
||||||
|
final r = RegExp(r'^No translation was found for msgid "(.*)" in msgctxt "(.*)" and domain "(.*)"$');
|
||||||
|
final matches = r.firstMatch(message);
|
||||||
|
var msgid = matches!.group(1);
|
||||||
|
// ignore: avoid_print
|
||||||
|
print('\nmsgid "$msgid"\nmsgstr ""\n \n');
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
QuickguiLocalizations.fromPO(String poContent) {
|
||||||
|
_gt.addLocale(gettext_parser.po.parse(poContent));
|
||||||
|
}
|
||||||
|
|
||||||
|
static QuickguiLocalizations of(BuildContext context) => Localizations.of<QuickguiLocalizations>(context, QuickguiLocalizations)!;
|
||||||
|
|
||||||
|
String t(String key) => _gt.gettext(key);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:quickgui/src/i18n/quickgui_localizations.dart';
|
||||||
|
|
||||||
|
class QuickguiLocalizationsDelegate extends LocalizationsDelegate<QuickguiLocalizations> {
|
||||||
|
@override
|
||||||
|
bool isSupported(Locale locale) => ['fr', 'en'].contains(locale.languageCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<QuickguiLocalizations> load(Locale locale) async {
|
||||||
|
var poContent = '';
|
||||||
|
try {
|
||||||
|
poContent = await rootBundle.loadString('assets/i18n/${locale.languageCode}_${locale.countryCode}.po');
|
||||||
|
} catch (e) {
|
||||||
|
poContent = await rootBundle.loadString('assets/i18n/${locale.languageCode}.po');
|
||||||
|
}
|
||||||
|
|
||||||
|
return QuickguiLocalizations.fromPO(poContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldReload(covariant LocalizationsDelegate<QuickguiLocalizations> old) => true;
|
||||||
|
}
|
||||||
|
|
@ -4,8 +4,13 @@ class AppTheme extends ChangeNotifier {
|
||||||
ThemeMode? _themeMode;
|
ThemeMode? _themeMode;
|
||||||
|
|
||||||
ThemeMode get themeMode => _themeMode ?? ThemeMode.system;
|
ThemeMode get themeMode => _themeMode ?? ThemeMode.system;
|
||||||
set useDarkMode(bool useDarkMode) {
|
|
||||||
|
set useDarkModeSilently(bool useDarkMode) {
|
||||||
_themeMode = useDarkMode ? ThemeMode.dark : ThemeMode.light;
|
_themeMode = useDarkMode ? ThemeMode.dark : ThemeMode.light;
|
||||||
|
}
|
||||||
|
|
||||||
|
set useDarkMode(bool useDarkMode) {
|
||||||
|
useDarkModeSilently = useDarkMode;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:quickgui/src/widgets/home_page/logo.dart';
|
import 'package:quickgui/src/widgets/home_page/logo.dart';
|
||||||
import 'package:quickgui/src/widgets/home_page/main_menu.dart';
|
import 'package:quickgui/src/widgets/home_page/main_menu.dart';
|
||||||
import 'package:quickgui/src/widgets/left_menu.dart';
|
import 'package:quickgui/src/widgets/left_menu.dart';
|
||||||
|
import 'package:quickgui/src/i18n/i18n_ext.dart';
|
||||||
|
|
||||||
class MainPage extends StatefulWidget {
|
class MainPage extends StatefulWidget {
|
||||||
const MainPage({Key? key, required this.title}) : super(key: key);
|
const MainPage({Key? key, required this.title}) : super(key: key);
|
||||||
|
|
@ -17,7 +18,7 @@ class _MainPageState extends State<MainPage> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Main menu'),
|
title: Text(context.t('Main menu')),
|
||||||
),
|
),
|
||||||
drawer: const LeftMenu(),
|
drawer: const LeftMenu(),
|
||||||
body: Column(
|
body: Column(
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import 'package:quickgui/src/globals.dart';
|
||||||
import 'package:quickgui/src/mixins/app_version.dart';
|
import 'package:quickgui/src/mixins/app_version.dart';
|
||||||
import 'package:quickgui/src/mixins/preferences_mixin.dart';
|
import 'package:quickgui/src/mixins/preferences_mixin.dart';
|
||||||
import 'package:quickgui/src/model/app_theme.dart';
|
import 'package:quickgui/src/model/app_theme.dart';
|
||||||
|
import 'package:quickgui/src/i18n/i18n_ext.dart';
|
||||||
|
|
||||||
class LeftMenu extends StatelessWidget with PreferencesMixin {
|
class LeftMenu extends StatelessWidget with PreferencesMixin {
|
||||||
const LeftMenu({Key? key}) : super(key: key);
|
const LeftMenu({Key? key}) : super(key: key);
|
||||||
|
|
@ -24,7 +25,7 @@ class LeftMenu extends StatelessWidget with PreferencesMixin {
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Text('Use dark mode'),
|
Text(context.t('Use dark mode')),
|
||||||
Switch(
|
Switch(
|
||||||
value: Theme.of(context).brightness == Brightness.dark,
|
value: Theme.of(context).brightness == Brightness.dark,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,11 @@ dependencies:
|
||||||
shared_preferences: ^2.0.8
|
shared_preferences: ^2.0.8
|
||||||
package_info_plus: ^1.3.0
|
package_info_plus: ^1.3.0
|
||||||
provider: ^6.0.1
|
provider: ^6.0.1
|
||||||
|
intl: ^0.17.0
|
||||||
|
gettext: ^1.2.0
|
||||||
|
gettext_parser: ^0.2.0
|
||||||
|
flutter_localizations:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
@ -74,6 +79,7 @@ flutter:
|
||||||
# - images/a_dot_ham.jpeg
|
# - images/a_dot_ham.jpeg
|
||||||
assets:
|
assets:
|
||||||
- assets/images/
|
- assets/images/
|
||||||
|
- assets/i18n/
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||||
|
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
name: quickgui
|
|
||||||
adopt-info: quickgui
|
|
||||||
summary: a Flutter frontend for (quickget)[https://github.com/wimpysworld/quickget]
|
|
||||||
description: |
|
|
||||||
The app is a frontend to quickget.
|
|
||||||
grade: stable
|
|
||||||
confinement: classic
|
|
||||||
base: core20
|
|
||||||
|
|
||||||
architectures:
|
|
||||||
- build-on: amd64
|
|
||||||
|
|
||||||
apps:
|
|
||||||
quickgui:
|
|
||||||
command: bin/quickgui
|
|
||||||
environment:
|
|
||||||
PATH: $SNAP/usr/bin:$SNAP/bin:$PATH
|
|
||||||
LIVE_RUN: 1
|
|
||||||
LOG_LEVEL: debug
|
|
||||||
|
|
||||||
parts:
|
|
||||||
quickgui-deps:
|
|
||||||
plugin: nil
|
|
||||||
stage-packages:
|
|
||||||
- libatk1.0-0
|
|
||||||
- libcairo-gobject2
|
|
||||||
- libcairo2
|
|
||||||
- libepoxy0
|
|
||||||
- libgtk-3-0
|
|
||||||
- libpango-1.0-0
|
|
||||||
- libpangocairo-1.0-0
|
|
||||||
|
|
||||||
quickgui:
|
|
||||||
source: .
|
|
||||||
source-type: git
|
|
||||||
plugin: nil
|
|
||||||
override-pull: |
|
|
||||||
snapcraftctl pull
|
|
||||||
snapcraftctl set-version "$(cat pubspec.yaml | grep '^version: ' | cut -c 10- | sed 's/+/-/')"
|
|
||||||
override-build: |
|
|
||||||
set -eux
|
|
||||||
mkdir -p $SNAPCRAFT_PART_INSTALL/bin/lib
|
|
||||||
flutter channel stable
|
|
||||||
flutter upgrade
|
|
||||||
flutter config --enable-linux-desktop
|
|
||||||
flutter doctor
|
|
||||||
flutter pub get
|
|
||||||
flutter build linux --release -v
|
|
||||||
cp -r build/linux/x64/release/bundle/* $SNAPCRAFT_PART_INSTALL/bin/
|
|
||||||
build-snaps:
|
|
||||||
- flutter/latest/stable
|
|
||||||
after:
|
|
||||||
- quickgui-deps
|
|
||||||
Loading…
Reference in New Issue