tane/apps/app_seeds/test/ui/asturian_locale_test.dart
vjrj c9c764e624 feat(i18n): add Asturian (asturianu) as a language
Adds Asturianu, translated in full (345 strings), plus the wiring to
make a minority language work end to end — the OS language picker is an
unreliable way to reach it, so the in-app choice must be explicit and
remembered.

- Model Asturian as the real `ast` locale (honest, international-by-design),
  not a fake `es-AST` region — slang rejects a 3-letter region anyway.
- Flutter ships no Material/Cupertino/intl localizations for `ast`, so map
  the framework chrome to Spanish (`materialLocaleFor`); the app's own text
  stays Asturian via slang. Fixes an "Invalid locale ast" crash when the
  auto-backup date was formatted with intl.
- Persist the picked language in the keystore (LocaleStore) and restore it
  at startup so it survives restarts and wins over the device locale.
- Settings: add the Asturianu tile; compare the full AppLocale so `es` and
  `ast` aren't both marked selected.

Tests: LocaleStore round-trip, locale switch + Spanish-chrome fallback,
and a regression for the intl date crash under Asturian.
2026-07-10 15:43:33 +02:00

73 lines
3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tane/app.dart';
import 'package:tane/i18n/strings.g.dart';
import 'package:tane/services/locale_store.dart';
import 'package:tane/ui/settings_screen.dart';
import '../support/test_support.dart';
/// Asturian (`ast`) is a first-class language, but Flutter ships no
/// Material/Cupertino localizations for it. The app carries the honest `ast`
/// locale for its own strings and borrows Spanish for the framework chrome
/// (see [materialLocaleFor]). These tests pin both halves of that contract.
void main() {
testWidgets('picking Asturian switches app text to Asturian, keeps Material '
'chrome resolvable in Spanish, and persists the choice', (tester) async {
LocaleSettings.setLocaleSync(AppLocale.en);
final store = LocaleStore(InMemorySecretStore());
late Locale materialLocale;
await tester.pumpWidget(
TranslationProvider(
child: Builder(
builder: (context) {
final appLocale = TranslationProvider.of(context).flutterLocale;
return MaterialApp(
// Mirrors app.dart: the framework localizations follow the mapped
// locale, the app's own strings follow slang.
locale: materialLocaleFor(appLocale),
supportedLocales: AppLocaleUtils.supportedLocales,
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
home: Builder(
builder: (context) {
// Resolving these must never throw for the Asturian locale.
materialLocale = Localizations.localeOf(context);
MaterialLocalizations.of(context);
return SettingsScreen(localeStore: store);
},
),
);
},
),
),
);
// Starts in English.
expect(find.text('Language'), findsOneWidget);
expect(materialLocale.languageCode, 'en');
await tester.tap(find.text('Asturianu'));
await tester.pumpAndSettle();
// App strings are now Asturian…
expect(find.text('Llingua'), findsOneWidget);
// …the framework chrome fell back to Spanish (not the unsupported `ast`)…
expect(materialLocale.languageCode, 'es');
// …and the choice was remembered for next launch.
expect(await store.saved(), AppLocale.ast);
});
test('materialLocaleFor maps Asturian to Spanish and passes others through',
() {
expect(materialLocaleFor(const Locale('ast')), const Locale('es'));
expect(materialLocaleFor(const Locale('es')), const Locale('es'));
expect(materialLocaleFor(const Locale('en')), const Locale('en'));
expect(materialLocaleFor(const Locale('pt')), const Locale('pt'));
});
}