Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add language setting #1461

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions assets/l10n/app_en.arb
Original file line number Diff line number Diff line change
@@ -883,5 +883,13 @@
"zulipAppTitle": "Zulip",
"@zulipAppTitle": {
"description": "The name of Zulip. This should be either 'Zulip' or a transliteration."
},
"languageSettingsTitle": "Language",
"@languageSettingsTitle": {
"description": "Title for the language settings section in the app settings."
},
"systemDefaultLanguage": "System default",
"@systemDefaultLanguage": {
"description": "Option to use the system default language setting."
}
}
12 changes: 12 additions & 0 deletions lib/generated/l10n/zulip_localizations.dart
Original file line number Diff line number Diff line change
@@ -1286,6 +1286,18 @@ abstract class ZulipLocalizations {
/// In en, this message translates to:
/// **'Zulip'**
String get zulipAppTitle;

/// Title for the language settings section in the app settings.
///
/// In en, this message translates to:
/// **'Language'**
String get languageSettingsTitle;

/// Option to use the system default language setting.
///
/// In en, this message translates to:
/// **'System default'**
String get systemDefaultLanguage;
}

class _ZulipLocalizationsDelegate extends LocalizationsDelegate<ZulipLocalizations> {
6 changes: 6 additions & 0 deletions lib/generated/l10n/zulip_localizations_ar.dart
Original file line number Diff line number Diff line change
@@ -686,4 +686,10 @@ class ZulipLocalizationsAr extends ZulipLocalizations {

@override
String get zulipAppTitle => 'Zulip';

@override
String get languageSettingsTitle => 'Language';

@override
String get systemDefaultLanguage => 'System default';
}
6 changes: 6 additions & 0 deletions lib/generated/l10n/zulip_localizations_en.dart
Original file line number Diff line number Diff line change
@@ -686,4 +686,10 @@ class ZulipLocalizationsEn extends ZulipLocalizations {

@override
String get zulipAppTitle => 'Zulip';

@override
String get languageSettingsTitle => 'Language';

@override
String get systemDefaultLanguage => 'System default';
}
6 changes: 6 additions & 0 deletions lib/generated/l10n/zulip_localizations_ja.dart
Original file line number Diff line number Diff line change
@@ -686,4 +686,10 @@ class ZulipLocalizationsJa extends ZulipLocalizations {

@override
String get zulipAppTitle => 'Zulip';

@override
String get languageSettingsTitle => 'Language';

@override
String get systemDefaultLanguage => 'System default';
}
6 changes: 6 additions & 0 deletions lib/generated/l10n/zulip_localizations_nb.dart
Original file line number Diff line number Diff line change
@@ -686,4 +686,10 @@ class ZulipLocalizationsNb extends ZulipLocalizations {

@override
String get zulipAppTitle => 'Zulip';

@override
String get languageSettingsTitle => 'Language';

@override
String get systemDefaultLanguage => 'System default';
}
6 changes: 6 additions & 0 deletions lib/generated/l10n/zulip_localizations_pl.dart
Original file line number Diff line number Diff line change
@@ -686,4 +686,10 @@ class ZulipLocalizationsPl extends ZulipLocalizations {

@override
String get zulipAppTitle => 'Zulip';

@override
String get languageSettingsTitle => 'Language';

@override
String get systemDefaultLanguage => 'System default';
}
6 changes: 6 additions & 0 deletions lib/generated/l10n/zulip_localizations_ru.dart
Original file line number Diff line number Diff line change
@@ -686,4 +686,10 @@ class ZulipLocalizationsRu extends ZulipLocalizations {

@override
String get zulipAppTitle => 'Zulip';

@override
String get languageSettingsTitle => 'Language';

@override
String get systemDefaultLanguage => 'System default';
}
6 changes: 6 additions & 0 deletions lib/generated/l10n/zulip_localizations_sk.dart
Original file line number Diff line number Diff line change
@@ -686,4 +686,10 @@ class ZulipLocalizationsSk extends ZulipLocalizations {

@override
String get zulipAppTitle => 'Zulip';

@override
String get languageSettingsTitle => 'Language';

@override
String get systemDefaultLanguage => 'System default';
}
73 changes: 73 additions & 0 deletions lib/widgets/app.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:path_provider/path_provider.dart';

import '../generated/l10n/zulip_localizations.dart';
import '../log.dart';
@@ -47,6 +50,63 @@ class ZulipApp extends StatefulWidget {
return completer.future;
}

// static Locale? currentLocale;
// static final ValueNotifier<Locale?> _localeNotifier = ValueNotifier(currentLocale);
//
// static void setLocale(Locale? locale) {
// currentLocale = locale;
// _localeNotifier.value = locale;
// }

static Locale? currentLocale;
static final ValueNotifier<Locale?> _localeNotifier = ValueNotifier(currentLocale);
static File? _prefsFile;

static Future<File> _getPrefsFile() async {
if (_prefsFile == null) {
final dir = await getApplicationDocumentsDirectory();
_prefsFile = File('${dir.path}/language_prefs.json');
if (!await _prefsFile!.exists()) {
await _prefsFile!.create();
}
}
return _prefsFile!;
}

static Future<void> setLocale(Locale? locale) async {
currentLocale = locale;
_localeNotifier.value = locale;

try {
final file = await _getPrefsFile();
await file.writeAsString(
jsonEncode({'locale': locale?.toString()}),
flush: true,
);
} catch (e) {
debugPrint('Error saving locale: $e');
}
}

static Future<void> loadSavedLocale() async {
try {
final file = await _getPrefsFile();
final content = await file.readAsString();
if (content.isNotEmpty) {
final data = jsonDecode(content) as Map<String, dynamic>;
final localeString = data['locale'] as String?;
if (localeString != null && localeString.isNotEmpty) {
final parts = localeString.split('_');
currentLocale = parts.length == 2
? Locale(parts[0], parts[1])
: Locale(parts[0]);
_localeNotifier.value = currentLocale;
}
}
} catch (e) {
debugPrint('Error loading locale: $e');
}
}
/// A key for the navigator for the whole app.
///
/// For code that exists entirely outside the widget tree and has no natural
@@ -160,14 +220,26 @@ class _ZulipAppState extends State<ZulipApp> with WidgetsBindingObserver {
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
ZulipApp._localeNotifier.addListener(_handleLocaleChange);
_initializeApp();
}

Future<void> _initializeApp() async {
await ZulipApp.loadSavedLocale(); // Load saved locale first
ZulipApp._localeNotifier.addListener(_handleLocaleChange);
}

@override
void dispose() {
ZulipApp._localeNotifier.removeListener(_handleLocaleChange);
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}

void _handleLocaleChange() {
if (mounted) setState(() {});
}

List<Route<dynamic>> _handleGenerateInitialRoutes(String initialRoute) {
// The `_ZulipAppState.context` lacks the required ancestors. Instead
// we use the Navigator which should be available when this callback is
@@ -220,6 +292,7 @@ class _ZulipAppState extends State<ZulipApp> with WidgetsBindingObserver {
return GlobalStoreWidget(
child: Builder(builder: (context) {
return MaterialApp(
locale: ZulipApp.currentLocale,
onGenerateTitle: (BuildContext context) {
return ZulipLocalizations.of(context).zulipAppTitle;
},
Loading