Add Hungarian English language switcher
This commit is contained in:
+138
-16
@@ -18,6 +18,7 @@ class _OtthonAppState extends State<OtthonApp> {
|
||||
String googleServerClientId = googleCalendarServerClientId;
|
||||
WeatherSnapshot? weather;
|
||||
String themeId = 'sage';
|
||||
String languageCode = defaultLanguageCode;
|
||||
bool loaded = false;
|
||||
|
||||
AppThemeStyle get activeTheme => appThemes.firstWhere(
|
||||
@@ -43,6 +44,7 @@ class _OtthonAppState extends State<OtthonApp> {
|
||||
jarvisSettings = settings.jarvisSettings;
|
||||
googleServerClientId = settings.googleServerClientId;
|
||||
themeId = settings.themeId;
|
||||
languageCode = settings.languageCode;
|
||||
loaded = true;
|
||||
});
|
||||
_loadRemoteAppConfig();
|
||||
@@ -53,6 +55,7 @@ class _OtthonAppState extends State<OtthonApp> {
|
||||
AppSettings(
|
||||
people: people,
|
||||
themeId: themeId,
|
||||
languageCode: languageCode,
|
||||
googleConnections: googleConnections,
|
||||
syncedEvents: syncedEvents,
|
||||
todoSuggestions: todoSuggestions,
|
||||
@@ -100,6 +103,11 @@ class _OtthonAppState extends State<OtthonApp> {
|
||||
_saveSettings();
|
||||
}
|
||||
|
||||
void _updateLanguage(String nextLanguageCode) {
|
||||
setState(() => languageCode = nextLanguageCode == 'en' ? 'en' : 'hu');
|
||||
_saveSettings();
|
||||
}
|
||||
|
||||
void _updateGoogleConnections(
|
||||
List<GoogleCalendarConnection> nextConnections,
|
||||
) {
|
||||
@@ -132,9 +140,17 @@ class _OtthonAppState extends State<OtthonApp> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = activeTheme;
|
||||
final text = AppText.of(languageCode);
|
||||
return MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
title: 'K\u00f6z\u00f6sT\u00e9r',
|
||||
title: text.appTitle,
|
||||
locale: text.locale,
|
||||
supportedLocales: const [Locale('hu'), Locale('en')],
|
||||
localizationsDelegates: const [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
theme: ThemeData(
|
||||
useMaterial3: true,
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
@@ -168,9 +184,11 @@ class _OtthonAppState extends State<OtthonApp> {
|
||||
googleServerClientId: googleServerClientId,
|
||||
weather: weather,
|
||||
themeId: themeId,
|
||||
languageCode: languageCode,
|
||||
loaded: loaded,
|
||||
onPeopleChanged: _updatePeople,
|
||||
onThemeChanged: _updateTheme,
|
||||
onLanguageChanged: _updateLanguage,
|
||||
onGoogleConnectionsChanged: _updateGoogleConnections,
|
||||
onSyncedEventsChanged: _updateSyncedEvents,
|
||||
onTodoSuggestionsChanged: _updateTodoSuggestions,
|
||||
@@ -191,9 +209,11 @@ class HomeShell extends StatefulWidget {
|
||||
required this.googleServerClientId,
|
||||
required this.weather,
|
||||
required this.themeId,
|
||||
required this.languageCode,
|
||||
required this.loaded,
|
||||
required this.onPeopleChanged,
|
||||
required this.onThemeChanged,
|
||||
required this.onLanguageChanged,
|
||||
required this.onGoogleConnectionsChanged,
|
||||
required this.onSyncedEventsChanged,
|
||||
required this.onTodoSuggestionsChanged,
|
||||
@@ -208,9 +228,11 @@ class HomeShell extends StatefulWidget {
|
||||
final String googleServerClientId;
|
||||
final WeatherSnapshot? weather;
|
||||
final String themeId;
|
||||
final String languageCode;
|
||||
final bool loaded;
|
||||
final ValueChanged<List<Person>> onPeopleChanged;
|
||||
final ValueChanged<String> onThemeChanged;
|
||||
final ValueChanged<String> onLanguageChanged;
|
||||
final ValueChanged<List<GoogleCalendarConnection>> onGoogleConnectionsChanged;
|
||||
final ValueChanged<List<CalendarEvent>> onSyncedEventsChanged;
|
||||
final ValueChanged<List<String>> onTodoSuggestionsChanged;
|
||||
@@ -328,15 +350,6 @@ class _HomeShellState extends State<HomeShell> {
|
||||
|
||||
List<CalendarEvent> get allEvents => [...events, ...widget.syncedEvents];
|
||||
|
||||
final labels = const [
|
||||
'Napt\u00e1r',
|
||||
'Bev\u00e1s\u00e1rl\u00e1s',
|
||||
'K\u00e9szlet',
|
||||
'Csal\u00e1dtagok',
|
||||
'St\u00edlus',
|
||||
'Fi\u00f3kok',
|
||||
];
|
||||
|
||||
final icons = const [
|
||||
Icons.calendar_month_rounded,
|
||||
Icons.shopping_basket_outlined,
|
||||
@@ -349,6 +362,15 @@ class _HomeShellState extends State<HomeShell> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final wide = MediaQuery.sizeOf(context).width >= 850;
|
||||
final text = AppText.of(widget.languageCode);
|
||||
final labels = [
|
||||
text.calendar,
|
||||
text.shopping,
|
||||
text.stock,
|
||||
text.familyMembers,
|
||||
text.style,
|
||||
text.accounts,
|
||||
];
|
||||
final body = IndexedStack(
|
||||
index: selected,
|
||||
children: [
|
||||
@@ -362,11 +384,13 @@ class _HomeShellState extends State<HomeShell> {
|
||||
),
|
||||
ShoppingPage(
|
||||
items: shopping,
|
||||
languageCode: widget.languageCode,
|
||||
onChanged: () => setState(() {}),
|
||||
onAdd: _addShopping,
|
||||
),
|
||||
StockPage(
|
||||
items: stock,
|
||||
languageCode: widget.languageCode,
|
||||
onChanged: () => setState(() {}),
|
||||
onAdd: _addStock,
|
||||
onEdit: _editStock,
|
||||
@@ -375,12 +399,14 @@ class _HomeShellState extends State<HomeShell> {
|
||||
PersonsPage(
|
||||
people: widget.people,
|
||||
events: allEvents,
|
||||
languageCode: widget.languageCode,
|
||||
onAdd: _addPerson,
|
||||
onEdit: _editPerson,
|
||||
onDelete: _deletePerson,
|
||||
),
|
||||
StylePage(
|
||||
themeId: widget.themeId,
|
||||
languageCode: widget.languageCode,
|
||||
onThemeChanged: widget.onThemeChanged,
|
||||
),
|
||||
AccountsPage(
|
||||
@@ -389,6 +415,7 @@ class _HomeShellState extends State<HomeShell> {
|
||||
people: widget.people,
|
||||
jarvisSettings: widget.jarvisSettings,
|
||||
serverClientId: widget.googleServerClientId,
|
||||
languageCode: widget.languageCode,
|
||||
onChanged: widget.onGoogleConnectionsChanged,
|
||||
onSyncedEventsChanged: widget.onSyncedEventsChanged,
|
||||
),
|
||||
@@ -451,11 +478,11 @@ class _HomeShellState extends State<HomeShell> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text(
|
||||
'K\u00f6z\u00f6sT\u00e9r',
|
||||
Text(
|
||||
text.appTitle,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w900,
|
||||
color: ink,
|
||||
@@ -464,8 +491,8 @@ class _HomeShellState extends State<HomeShell> {
|
||||
),
|
||||
Text(
|
||||
widget.loaded
|
||||
? 'Tervez\u0151'
|
||||
: 'JSON bet\u00f6lt\u00e9se\u2026',
|
||||
? text.appSubtitle
|
||||
: text.loadingJson,
|
||||
style: const TextStyle(
|
||||
fontSize: 11,
|
||||
color: Colors.black45,
|
||||
@@ -473,6 +500,12 @@ class _HomeShellState extends State<HomeShell> {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
LanguageSwitcher(
|
||||
languageCode: widget.languageCode,
|
||||
onChanged: widget.onLanguageChanged,
|
||||
labels: text,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
const Text(
|
||||
appVersionLabel,
|
||||
style: TextStyle(
|
||||
@@ -485,7 +518,7 @@ class _HomeShellState extends State<HomeShell> {
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
tooltip: 'JARVIS be\u00e1ll\u00edt\u00e1sok',
|
||||
tooltip: text.jarvisSettings,
|
||||
onPressed: _openJarvisSettings,
|
||||
icon: const Icon(
|
||||
Icons.settings_outlined,
|
||||
@@ -1215,3 +1248,92 @@ class _HomeShellState extends State<HomeShell> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LanguageSwitcher extends StatelessWidget {
|
||||
const LanguageSwitcher({
|
||||
super.key,
|
||||
required this.languageCode,
|
||||
required this.onChanged,
|
||||
required this.labels,
|
||||
});
|
||||
|
||||
final String languageCode;
|
||||
final ValueChanged<String> onChanged;
|
||||
final AppText labels;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 24,
|
||||
padding: const EdgeInsets.all(2),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
border: Border.all(color: sage.withValues(alpha: .16)),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_LanguagePill(
|
||||
selected: languageCode != 'en',
|
||||
flag: '🇭🇺',
|
||||
label: labels.hunShort,
|
||||
onTap: () => onChanged('hu'),
|
||||
),
|
||||
_LanguagePill(
|
||||
selected: languageCode == 'en',
|
||||
flag: '🇬🇧',
|
||||
label: labels.engShort,
|
||||
onTap: () => onChanged('en'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LanguagePill extends StatelessWidget {
|
||||
const _LanguagePill({
|
||||
required this.selected,
|
||||
required this.flag,
|
||||
required this.label,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
final bool selected;
|
||||
final String flag;
|
||||
final String label;
|
||||
final VoidCallback onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
onTap: selected ? null : onTap,
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 180),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: selected ? sage : Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(flag, style: const TextStyle(fontSize: 11)),
|
||||
const SizedBox(width: 3),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 9,
|
||||
height: 1,
|
||||
fontWeight: FontWeight.w900,
|
||||
color: selected ? Colors.white : Colors.black45,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user