From 02ba12cc1c79b796ce713f80743db5520a067d21 Mon Sep 17 00:00:00 2001 From: Bruce Liu Date: Sat, 25 Jun 2022 15:07:47 -0700 Subject: [PATCH] add multiple locales --- android/app/build.gradle | 2 +- android/app/src/main/AndroidManifest.xml | 2 +- android/build.gradle | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- ios/Runner.xcodeproj/project.pbxproj | 12 + ios/Runner/fr.lproj/LaunchScreen.strings | 1 + ios/Runner/hr.lproj/LaunchScreen.strings | 1 + ios/Runner/pt-BR.lproj/LaunchScreen.strings | 1 + ios/Runner/uk.lproj/LaunchScreen.strings | 1 + lib/l10n/{intl_ptBR.arb => intl_pt.arb} | 0 lib/l10n/{intl_ua.arb => intl_uk.arb} | 0 lib/main.dart | 27 +- lib/pages/settings/general_page.dart | 268 ++++++++++-------- 13 files changed, 182 insertions(+), 139 deletions(-) create mode 100644 ios/Runner/fr.lproj/LaunchScreen.strings create mode 100644 ios/Runner/hr.lproj/LaunchScreen.strings create mode 100644 ios/Runner/pt-BR.lproj/LaunchScreen.strings create mode 100644 ios/Runner/uk.lproj/LaunchScreen.strings rename lib/l10n/{intl_ptBR.arb => intl_pt.arb} (100%) rename lib/l10n/{intl_ua.arb => intl_uk.arb} (100%) diff --git a/android/app/build.gradle b/android/app/build.gradle index bf79f92..948d1ea 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -32,7 +32,7 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion 29 + compileSdkVersion 31 sourceSets { main.java.srcDirs += 'src/main/kotlin' diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 15966b3..78dfa82 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -9,7 +9,7 @@ diff --git a/android/build.gradle b/android/build.gradle index 3100ad2..07d2fe3 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.7.0' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:7.0.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 296b146..b8793d3 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 817edbb..d03a6a2 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -50,6 +50,10 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E30184022867BA2B005DCAE6 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/LaunchScreen.strings; sourceTree = ""; }; + E30184032867BA70005DCAE6 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/LaunchScreen.strings; sourceTree = ""; }; + E30184042867BA7D005DCAE6 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/LaunchScreen.strings"; sourceTree = ""; }; + E30184052867BAB1005DCAE6 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/LaunchScreen.strings; sourceTree = ""; }; FA1C5CF9893C1976B07DEA5C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -179,6 +183,10 @@ "zh-Hans", es, de, + fr, + hr, + "pt-BR", + uk, ); mainGroup = 97C146E51CF9000F007C117D; productRefGroup = 97C146EF1CF9000F007C117D /* Products */; @@ -302,6 +310,10 @@ 3271990C25BBF9C8008EA00E /* zh-Hans */, 324ACECE25C909AD00CD3591 /* es */, 32AC73DE263AED42001F500B /* de */, + E30184022867BA2B005DCAE6 /* fr */, + E30184032867BA70005DCAE6 /* hr */, + E30184042867BA7D005DCAE6 /* pt-BR */, + E30184052867BAB1005DCAE6 /* uk */, ); name = LaunchScreen.storyboard; sourceTree = ""; diff --git a/ios/Runner/fr.lproj/LaunchScreen.strings b/ios/Runner/fr.lproj/LaunchScreen.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/ios/Runner/fr.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/ios/Runner/hr.lproj/LaunchScreen.strings b/ios/Runner/hr.lproj/LaunchScreen.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/ios/Runner/hr.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/ios/Runner/pt-BR.lproj/LaunchScreen.strings b/ios/Runner/pt-BR.lproj/LaunchScreen.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/ios/Runner/pt-BR.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/ios/Runner/uk.lproj/LaunchScreen.strings b/ios/Runner/uk.lproj/LaunchScreen.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/ios/Runner/uk.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/lib/l10n/intl_ptBR.arb b/lib/l10n/intl_pt.arb similarity index 100% rename from lib/l10n/intl_ptBR.arb rename to lib/l10n/intl_pt.arb diff --git a/lib/l10n/intl_ua.arb b/lib/l10n/intl_uk.arb similarity index 100% rename from lib/l10n/intl_ua.arb rename to lib/l10n/intl_uk.arb diff --git a/lib/main.dart b/lib/main.dart index bbfa6ef..a55e17c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -42,8 +42,9 @@ void main() async { SystemChannels.lifecycle.setMessageHandler((msg) { if (msg == AppLifecycleState.resumed.toString()) { if (Global.server != null) Global.server.restart(); - if (Global.globalModel.syncOnStart - && DateTime.now().difference(Global.syncModel.lastSynced).inMinutes >= 10) { + if (Global.globalModel.syncOnStart && + DateTime.now().difference(Global.syncModel.lastSynced).inMinutes >= + 10) { Global.syncModel.syncWithService(); } } @@ -67,7 +68,8 @@ class MyApp extends StatelessWidget { "/settings/service/inoreader": (context) => InoreaderPage(), "/settings/service/greader": (context) => GReaderPage(), "/settings/service": (context) { - var serviceType = SyncService.values[Store.sp.getInt(StoreKeys.SYNC_SERVICE) ?? 0]; + var serviceType = + SyncService.values[Store.sp.getInt(StoreKeys.SYNC_SERVICE) ?? 0]; switch (serviceType) { case SyncService.None: break; @@ -114,12 +116,19 @@ class MyApp extends StatelessWidget { const Locale("en"), const Locale("es"), const Locale("zh"), + const Locale("fr"), + const Locale("uk"), + const Locale("hr"), + const Locale("pt"), ], localeResolutionCallback: (_locale, supportedLocales) { _locale = Locale(_locale.languageCode); - if (globalModel.locale != null) return globalModel.locale; - else if (supportedLocales.contains(_locale)) return _locale; - else return Locale("en"); + if (globalModel.locale != null) + return globalModel.locale; + else if (supportedLocales.contains(_locale)) + return _locale; + else + return Locale("en"); }, theme: CupertinoThemeData( primaryColor: CupertinoColors.systemBlue, @@ -133,9 +142,9 @@ class MyApp extends StatelessWidget { final mediaQueryData = MediaQuery.of(context); if (Global.globalModel.textScale == null) return child; return MediaQuery( - data: mediaQueryData.copyWith(textScaleFactor: Global.globalModel.textScale), - child: child - ); + data: mediaQueryData.copyWith( + textScaleFactor: Global.globalModel.textScale), + child: child); }, ), ), diff --git a/lib/pages/settings/general_page.dart b/lib/pages/settings/general_page.dart index b45168a..7a833f4 100644 --- a/lib/pages/settings/general_page.dart +++ b/lib/pages/settings/general_page.dart @@ -18,137 +18,155 @@ class _GeneralPageState extends State { double textScale; void _clearCache() async { - setState(() { _clearingCache = true; }); + setState(() { + _clearingCache = true; + }); await DefaultCacheManager().emptyCache(); if (!mounted) return; - setState(() { _clearingCache = false; }); + setState(() { + _clearingCache = false; + }); } @override Widget build(BuildContext context) => CupertinoPageScaffold( - backgroundColor: MyColors.background, - navigationBar: CupertinoNavigationBar( - middle: Text(S.of(context).general), - ), - child: Consumer( - builder: (context, globalModel, child) { - final useSystemTextScale = globalModel.textScale == null; - final textScaleItems = ListTileGroup([ - MyListTile( - title: Text(S.of(context).followSystem), - trailing: CupertinoSwitch( - value: useSystemTextScale, - onChanged: (v) { - textScale = null; - globalModel.textScale = v ? null : 1; + backgroundColor: MyColors.background, + navigationBar: CupertinoNavigationBar( + middle: Text(S.of(context).general), + ), + child: Consumer( + builder: (context, globalModel, child) { + final useSystemTextScale = globalModel.textScale == null; + final textScaleItems = ListTileGroup([ + MyListTile( + title: Text(S.of(context).followSystem), + trailing: CupertinoSwitch( + value: useSystemTextScale, + onChanged: (v) { + textScale = null; + globalModel.textScale = v ? null : 1; + }, + ), + trailingChevron: false, + withDivider: !useSystemTextScale, + ), + if (!useSystemTextScale) + MyListTile( + title: Expanded( + child: CupertinoSlider( + min: 0.5, + max: 1.5, + divisions: 8, + value: textScale ?? globalModel.textScale, + onChanged: (v) { + setState(() { + textScale = v; + }); + }, + onChangeEnd: (v) { + textScale = null; + globalModel.textScale = v; + }, + )), + trailingChevron: false, + withDivider: false, + ), + ], title: S.of(context).fontSize); + final syncItems = ListTileGroup([ + MyListTile( + title: Text(S.of(context).syncOnStart), + trailing: CupertinoSwitch( + value: globalModel.syncOnStart, + onChanged: (v) { + globalModel.syncOnStart = v; + setState(() {}); + }, + ), + trailingChevron: false, + ), + MyListTile( + title: Text(S.of(context).inAppBrowser), + trailing: CupertinoSwitch( + value: globalModel.inAppBrowser, + onChanged: (v) { + globalModel.inAppBrowser = v; + setState(() {}); + }, + ), + trailingChevron: false, + withDivider: false, + ), + ], title: S.of(context).preferences); + final storageItems = ListTileGroup([ + MyListTile( + title: Text(S.of(context).clearCache), + onTap: _clearingCache ? null : _clearCache, + trailing: _clearingCache ? CupertinoActivityIndicator() : null, + trailingChevron: !_clearingCache, + ), + MyListTile( + title: Text(S.of(context).autoDelete), + trailing: + Text(S.of(context).daysAgo(globalModel.keepItemsDays)), + trailingChevron: false, + withDivider: false, + ), + MyListTile( + title: Expanded( + child: CupertinoSlider( + min: 1, + max: 4, + divisions: 3, + value: (globalModel.keepItemsDays ~/ 7).toDouble(), + onChanged: (v) { + globalModel.keepItemsDays = (v * 7).toInt(); + setState(() {}); + }, + )), + trailingChevron: false, + withDivider: false, + ), + ], title: S.of(context).storage); + final themeItems = ListTileGroup.fromOptions( + [ + Tuple2(S.of(context).followSystem, ThemeSetting.Default), + Tuple2(S.of(context).light, ThemeSetting.Light), + Tuple2(S.of(context).dark, ThemeSetting.Dark), + ], + globalModel.theme, + (t) { + globalModel.theme = t; }, - ), - trailingChevron: false, - withDivider: !useSystemTextScale, - ), - if (!useSystemTextScale) MyListTile( - title: Expanded(child: CupertinoSlider( - min: 0.5, - max: 1.5, - divisions: 8, - value: textScale ?? globalModel.textScale, - onChanged: (v) { - setState(() { textScale = v; }); + title: S.of(context).theme, + ); + final localeItems = ListTileGroup.fromOptions( + [ + Tuple2(S.of(context).followSystem, null), + const Tuple2("Deutsch", Locale("de")), + const Tuple2("English", Locale("en")), + const Tuple2("Español", Locale("es")), + const Tuple2("Français", Locale("fr")), + const Tuple2("hrvatski", Locale("hr")), + const Tuple2("Português do Brasil", Locale("pt")), + const Tuple2("Українська", Locale("uk")), + const Tuple2("中文(简体)", Locale("zh")), + ], + globalModel.locale, + (l) { + globalModel.locale = l; }, - onChangeEnd: (v) { - textScale = null; - globalModel.textScale = v; - }, - )), - trailingChevron: false, - withDivider: false, - ), - ], title: S.of(context).fontSize); - final syncItems = ListTileGroup([ - MyListTile( - title: Text(S.of(context).syncOnStart), - trailing: CupertinoSwitch( - value: globalModel.syncOnStart, - onChanged: (v) { - globalModel.syncOnStart = v; - setState(() {}); - }, - ), - trailingChevron: false, - ), - MyListTile( - title: Text(S.of(context).inAppBrowser), - trailing: CupertinoSwitch( - value: globalModel.inAppBrowser, - onChanged: (v) { - globalModel.inAppBrowser = v; - setState(() {}); - }, - ), - trailingChevron: false, - withDivider: false, - ), - ], title: S.of(context).preferences); - final storageItems = ListTileGroup([ - MyListTile( - title: Text(S.of(context).clearCache), - onTap: _clearingCache ? null : _clearCache, - trailing: _clearingCache ? CupertinoActivityIndicator() : null, - trailingChevron: !_clearingCache, - ), - MyListTile( - title: Text(S.of(context).autoDelete), - trailing: Text(S.of(context).daysAgo(globalModel.keepItemsDays)), - trailingChevron: false, - withDivider: false, - ), - MyListTile( - title: Expanded(child: CupertinoSlider( - min: 1, - max: 4, - divisions: 3, - value: (globalModel.keepItemsDays ~/ 7).toDouble(), - onChanged: (v) { - globalModel.keepItemsDays = (v * 7).toInt(); - setState(() { }); - }, - )), - trailingChevron: false, - withDivider: false, - ), - ], title: S.of(context).storage); - final themeItems = ListTileGroup.fromOptions( - [ - Tuple2(S.of(context).followSystem, ThemeSetting.Default), - Tuple2(S.of(context).light, ThemeSetting.Light), - Tuple2(S.of(context).dark, ThemeSetting.Dark), - ], - globalModel.theme, - (t) { globalModel.theme = t; }, - title: S.of(context).theme, - ); - final localeItems = ListTileGroup.fromOptions( - [ - Tuple2(S.of(context).followSystem, null), - const Tuple2("Deutsch", Locale("de")), - const Tuple2("English", Locale("en")), - const Tuple2("Español", Locale("es")), - const Tuple2("中文(简体)", Locale("zh")), - ], - globalModel.locale, - (l) { globalModel.locale = l; }, - title: S.of(context).language, - ); - return ListView( - children: [ - syncItems, - textScaleItems, - storageItems, - themeItems, - localeItems, - ], - ); - }, - ), - ); + title: S.of(context).language, + ); + return ListView( + children: [ + syncItems, + textScaleItems, + storageItems, + themeItems, + localeItems, + ], + ); + }, + ), + ); } -- 2.38.5