@@ -271,6 +271,7 @@ class SettingsService extends BaseSharedPreferencesService {
|
||||
static const sleepTimerDuration = IntPref('sleep_timer_duration', defaultValue: 30);
|
||||
static const audioSyncOffset = IntPref('audio_sync_offset');
|
||||
static const subtitleSyncOffset = IntPref('subtitle_sync_offset');
|
||||
static const subtitleSearchLanguage = NullableStringPref('subtitle_search_language');
|
||||
static const volume = DoublePref('volume', defaultValue: 100.0);
|
||||
static const rotationLocked = BoolPref('rotation_locked', defaultValue: true);
|
||||
static const subtitleFontSize = IntPref('subtitle_font_size', defaultValue: 38);
|
||||
@@ -655,6 +656,7 @@ class SettingsService extends BaseSharedPreferencesService {
|
||||
sleepTimerDuration,
|
||||
audioSyncOffset,
|
||||
subtitleSyncOffset,
|
||||
subtitleSearchLanguage,
|
||||
volume,
|
||||
maxVolume,
|
||||
subtitleFontSize,
|
||||
|
||||
@@ -25,6 +25,12 @@ class LanguageCodes {
|
||||
return variations.toList();
|
||||
}
|
||||
|
||||
static String? getIso6391Code(String code) {
|
||||
final normalized = code.toLowerCase().trim().split(RegExp('[-_]')).first;
|
||||
if (normalized.isEmpty) return null;
|
||||
return _resolve(normalized)?.code1;
|
||||
}
|
||||
|
||||
/// Get a display name for a language/locale code.
|
||||
/// Handles plain codes ("en" → "English") and locale codes ("en-US" → "English",
|
||||
/// "en-AU" → "English (Australia)").
|
||||
|
||||
@@ -10,6 +10,7 @@ import '../../../i18n/strings.g.dart';
|
||||
import '../../../mixins/controller_disposer_mixin.dart';
|
||||
import '../../../models/plex/plex_subtitle_search_result.dart';
|
||||
import '../../../services/plex_client.dart';
|
||||
import '../../../services/settings_service.dart';
|
||||
import '../../../utils/language_codes.dart';
|
||||
import '../../../utils/provider_extensions.dart';
|
||||
import '../../../utils/snackbar_helper.dart';
|
||||
@@ -20,6 +21,13 @@ import '../../../widgets/pill_input_decoration.dart';
|
||||
import 'base_video_control_sheet.dart';
|
||||
import '../../loading_indicator_box.dart';
|
||||
|
||||
@visibleForTesting
|
||||
String resolveSubtitleSearchLanguageCode({String? savedLanguageCode, required Locale systemLocale}) {
|
||||
return LanguageCodes.getIso6391Code(savedLanguageCode ?? '') ??
|
||||
LanguageCodes.getIso6391Code(systemLocale.languageCode) ??
|
||||
'en';
|
||||
}
|
||||
|
||||
class SubtitleSearchSheet extends StatefulWidget {
|
||||
final String ratingKey;
|
||||
final String serverId;
|
||||
@@ -62,13 +70,14 @@ class _SubtitleSearchSheetState extends State<SubtitleSearchSheet> with Controll
|
||||
}
|
||||
|
||||
void _initDefaultLanguage() {
|
||||
final locale = WidgetsBinding.instance.platformDispatcher.locale;
|
||||
final code = locale.languageCode;
|
||||
final code = resolveSubtitleSearchLanguageCode(
|
||||
savedLanguageCode: SettingsService.instanceOrNull?.read(SettingsService.subtitleSearchLanguage),
|
||||
systemLocale: WidgetsBinding.instance.platformDispatcher.locale,
|
||||
);
|
||||
final name = LanguageCodes.getLanguageName(code);
|
||||
if (name != null) {
|
||||
_languageCode = code;
|
||||
_languageName = name;
|
||||
}
|
||||
if (name == null) return;
|
||||
_languageCode = code;
|
||||
_languageName = name;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -153,6 +162,10 @@ class _SubtitleSearchSheetState extends State<SubtitleSearchSheet> with Controll
|
||||
_languageName = name;
|
||||
_showLanguagePicker = false;
|
||||
});
|
||||
final settings = SettingsService.instanceOrNull;
|
||||
if (settings != null) {
|
||||
unawaited(settings.write(SettingsService.subtitleSearchLanguage, code));
|
||||
}
|
||||
OverlaySheetController.of(context).refocus();
|
||||
_search();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:plezy/widgets/video_controls/sheets/subtitle_search_sheet.dart';
|
||||
|
||||
void main() {
|
||||
group('resolveSubtitleSearchLanguageCode', () {
|
||||
test('prefers saved language over system language', () {
|
||||
expect(resolveSubtitleSearchLanguageCode(savedLanguageCode: 'fr', systemLocale: const Locale('nl')), 'fr');
|
||||
});
|
||||
|
||||
test('normalizes saved locale or three-letter language', () {
|
||||
expect(resolveSubtitleSearchLanguageCode(savedLanguageCode: 'pt_BR', systemLocale: const Locale('nl')), 'pt');
|
||||
expect(resolveSubtitleSearchLanguageCode(savedLanguageCode: 'eng', systemLocale: const Locale('nl')), 'en');
|
||||
});
|
||||
|
||||
test('falls back to system language when saved language is invalid', () {
|
||||
expect(resolveSubtitleSearchLanguageCode(savedLanguageCode: 'zz', systemLocale: const Locale('nl')), 'nl');
|
||||
});
|
||||
|
||||
test('falls back to English when saved and system languages are invalid', () {
|
||||
expect(resolveSubtitleSearchLanguageCode(savedLanguageCode: 'zz', systemLocale: const Locale('xx')), 'en');
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user