mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 05:26:47 +00:00
Locale switch (#200)
* Add function to set app locale * Setting for selecting app language - Adds requirement for "flutter_localized_locales" - Change main app to stateless * Reload entire app tree when language is changed * Update release notes * linting
This commit is contained in:
parent
19ff6eb526
commit
9559b8602e
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
- Allow serial numbers to be specified when creating new stock items
|
- Allow serial numbers to be specified when creating new stock items
|
||||||
- Allow serial numbers to be edited for existing stock items
|
- Allow serial numbers to be edited for existing stock items
|
||||||
|
- Allow app locale to be changed manually
|
||||||
|
|
||||||
### 0.8.1 - August 2022
|
### 0.8.1 - August 2022
|
||||||
---
|
---
|
||||||
|
@ -473,6 +473,16 @@
|
|||||||
"labelTemplate": "Label Template",
|
"labelTemplate": "Label Template",
|
||||||
"@labelTemplate": {},
|
"@labelTemplate": {},
|
||||||
|
|
||||||
|
"language": "Language",
|
||||||
|
"@language": {},
|
||||||
|
|
||||||
|
"languageDefault": "Default system language",
|
||||||
|
"@languageDefault": {},
|
||||||
|
|
||||||
|
"languageSelect": "Select Language",
|
||||||
|
"@languageSelect": {},
|
||||||
|
|
||||||
|
|
||||||
"lastStocktake": "Last Stocktake",
|
"lastStocktake": "Last Stocktake",
|
||||||
"@lastStocktake": {},
|
"@lastStocktake": {},
|
||||||
|
|
||||||
|
@ -4,12 +4,14 @@ import "package:flutter_localizations/flutter_localizations.dart";
|
|||||||
import "package:flutter_gen/gen_l10n/app_localizations.dart";
|
import "package:flutter_gen/gen_l10n/app_localizations.dart";
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_localized_locales/flutter_localized_locales.dart";
|
||||||
import "package:one_context/one_context.dart";
|
import "package:one_context/one_context.dart";
|
||||||
import "package:package_info_plus/package_info_plus.dart";
|
import "package:package_info_plus/package_info_plus.dart";
|
||||||
import "package:sentry_flutter/sentry_flutter.dart";
|
import "package:sentry_flutter/sentry_flutter.dart";
|
||||||
|
|
||||||
import "package:inventree/inventree/sentry.dart";
|
import "package:inventree/inventree/sentry.dart";
|
||||||
import "package:inventree/dsn.dart";
|
import "package:inventree/dsn.dart";
|
||||||
|
import "package:inventree/preferences.dart";
|
||||||
import "package:inventree/widget/home.dart";
|
import "package:inventree/widget/home.dart";
|
||||||
|
|
||||||
// Supported translations are automatically updated
|
// Supported translations are automatically updated
|
||||||
@ -60,9 +62,43 @@ Future<void> main() async {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class InvenTreeApp extends StatelessWidget {
|
class InvenTreeApp extends StatefulWidget {
|
||||||
// This widget is the root of your application.
|
// This widget is the root of your application.
|
||||||
|
|
||||||
|
@override
|
||||||
|
InvenTreeAppState createState() => InvenTreeAppState();
|
||||||
|
|
||||||
|
static InvenTreeAppState? of(BuildContext context) => context.findAncestorStateOfType<InvenTreeAppState>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class InvenTreeAppState extends State<StatefulWidget> {
|
||||||
|
|
||||||
|
// Custom _locale (default = null; use system default)
|
||||||
|
Locale? _locale;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
// Load selected locale
|
||||||
|
loadDefaultLocale();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the default app locale
|
||||||
|
Future<void> loadDefaultLocale() async {
|
||||||
|
Locale? locale = await InvenTreeSettingsManager().getSelectedLocale();
|
||||||
|
setLocale(locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the app locale
|
||||||
|
void setLocale(Locale? locale) {
|
||||||
|
setState(() {
|
||||||
|
_locale = locale;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
@ -78,11 +114,13 @@ class InvenTreeApp extends StatelessWidget {
|
|||||||
home: InvenTreeHomePage(),
|
home: InvenTreeHomePage(),
|
||||||
localizationsDelegates: [
|
localizationsDelegates: [
|
||||||
I18N.delegate,
|
I18N.delegate,
|
||||||
|
LocaleNamesLocalizationsDelegate(),
|
||||||
GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
GlobalCupertinoLocalizations.delegate,
|
GlobalCupertinoLocalizations.delegate,
|
||||||
GlobalWidgetsLocalizations.delegate,
|
GlobalWidgetsLocalizations.delegate,
|
||||||
],
|
],
|
||||||
supportedLocales: supported_locales,
|
supportedLocales: supported_locales,
|
||||||
|
locale: _locale,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
import "dart:async";
|
import "dart:async";
|
||||||
|
import "dart:ui";
|
||||||
|
|
||||||
|
import "package:inventree/l10n/supported_locales.dart";
|
||||||
import "package:path_provider/path_provider.dart";
|
import "package:path_provider/path_provider.dart";
|
||||||
import "package:sembast/sembast.dart";
|
import "package:sembast/sembast.dart";
|
||||||
import "package:sembast/sembast_io.dart";
|
import "package:sembast/sembast_io.dart";
|
||||||
@ -83,6 +85,26 @@ class InvenTreeSettingsManager {
|
|||||||
|
|
||||||
Future<Database> get _db async => InvenTreePreferencesDB.instance.database;
|
Future<Database> get _db async => InvenTreePreferencesDB.instance.database;
|
||||||
|
|
||||||
|
Future<Locale?> getSelectedLocale() async {
|
||||||
|
final String locale_name = await getValue("customLocale", "") as String;
|
||||||
|
|
||||||
|
if (locale_name.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var locale in supported_locales) {
|
||||||
|
if (locale.toString() == locale_name) {
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No matching locale found
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setSelectedLocale(Locale? locale) async {
|
||||||
|
await setValue("customLocale", locale?.toString() ?? "");
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> removeValue(String key) async {
|
Future<void> removeValue(String key) async {
|
||||||
await store.record(key).delete(await _db);
|
await store.record(key).delete(await _db);
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
|
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:font_awesome_flutter/font_awesome_flutter.dart";
|
import "package:font_awesome_flutter/font_awesome_flutter.dart";
|
||||||
|
import "package:flutter_localized_locales/flutter_localized_locales.dart";
|
||||||
|
|
||||||
|
import "package:inventree/api_form.dart";
|
||||||
import "package:inventree/l10.dart";
|
import "package:inventree/l10.dart";
|
||||||
|
import "package:inventree/l10n/supported_locales.dart";
|
||||||
|
import "package:inventree/main.dart";
|
||||||
import "package:inventree/preferences.dart";
|
import "package:inventree/preferences.dart";
|
||||||
|
|
||||||
|
|
||||||
@ -27,6 +31,8 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
|
|||||||
bool reportErrors = true;
|
bool reportErrors = true;
|
||||||
bool strictHttps = false;
|
bool strictHttps = false;
|
||||||
|
|
||||||
|
Locale? locale;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -46,14 +52,78 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
|
|||||||
reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool;
|
reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool;
|
||||||
strictHttps = await InvenTreeSettingsManager().getValue(INV_STRICT_HTTPS, false) as bool;
|
strictHttps = await InvenTreeSettingsManager().getValue(INV_STRICT_HTTPS, false) as bool;
|
||||||
|
|
||||||
|
locale = await InvenTreeSettingsManager().getSelectedLocale();
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _selectLocale(BuildContext context) async {
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> options = [
|
||||||
|
{
|
||||||
|
"display_name": L10().languageDefault,
|
||||||
|
"value": null,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Construct a list of available locales
|
||||||
|
for (var locale in supported_locales) {
|
||||||
|
options.add({
|
||||||
|
"display_name": LocaleNames.of(context)!.nameOf(locale.toString()),
|
||||||
|
"value": locale.toString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> fields = {
|
||||||
|
"locale": {
|
||||||
|
"label": L10().language,
|
||||||
|
"type": "choice",
|
||||||
|
"choices": options,
|
||||||
|
"value": locale?.toString(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
launchApiForm(
|
||||||
|
context,
|
||||||
|
L10().languageSelect,
|
||||||
|
"",
|
||||||
|
fields,
|
||||||
|
icon: FontAwesomeIcons.checkCircle,
|
||||||
|
onSuccess: (Map<String, dynamic> data) async {
|
||||||
|
|
||||||
|
String locale_name = (data["locale"] ?? "") as String;
|
||||||
|
Locale? selected_locale;
|
||||||
|
|
||||||
|
for (var locale in supported_locales) {
|
||||||
|
if (locale.toString() == locale_name) {
|
||||||
|
selected_locale = locale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await InvenTreeSettingsManager().setSelectedLocale(selected_locale);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
locale = selected_locale;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Refresh the entire app locale
|
||||||
|
InvenTreeApp.of(context)?.setLocale(locale);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
String languageName = L10().languageDefault;
|
||||||
|
|
||||||
|
if (locale != null) {
|
||||||
|
languageName = LocaleNames.of(context)!.nameOf(locale.toString()) ?? L10().languageDefault;
|
||||||
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
key: _settingsKey,
|
key: _settingsKey,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@ -142,6 +212,14 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text(L10().language),
|
||||||
|
subtitle: Text(languageName),
|
||||||
|
leading: FaIcon(FontAwesomeIcons.language),
|
||||||
|
onTap: () async {
|
||||||
|
_selectLocale(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(L10().errorReportUpload),
|
title: Text(L10().errorReportUpload),
|
||||||
subtitle: Text(L10().errorReportUploadDetails),
|
subtitle: Text(L10().errorReportUploadDetails),
|
||||||
|
@ -284,6 +284,13 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_localized_locales:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_localized_locales
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
flutter_markdown:
|
flutter_markdown:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -21,6 +21,7 @@ dependencies:
|
|||||||
flutter_cache_manager: ^3.3.0
|
flutter_cache_manager: ^3.3.0
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_localized_locales: 2.0.3
|
||||||
flutter_markdown: ^0.6.9 # Rendering markdown
|
flutter_markdown: ^0.6.9 # Rendering markdown
|
||||||
flutter_overlay_loader: ^2.0.0 # Overlay screen support
|
flutter_overlay_loader: ^2.0.0 # Overlay screen support
|
||||||
font_awesome_flutter: ^9.1.0 # FontAwesome icon set
|
font_awesome_flutter: ^9.1.0 # FontAwesome icon set
|
||||||
|
Loading…
x
Reference in New Issue
Block a user