feat(app,learn): the device's appearance and language, halkyon_app's, as Learn's Settings show them

The developer asked for Todo, Train and Meditate to offer Learn's
Appearance and Language (ADR 0014's amendment of 4 Nov 2026). Their
model, store, cubit and card move into halkyon_app: Appearance and Look
(a BCP 47 tag, null for the device's language), FileLookStore keeping it
in the app's support folder as JSON written by rename (per device, not
synced, read before the first frame), LookCubit for the apps to provide
above InstanceGate, and LookSettingsCard / DeviceLookCard with the texts
moved from Learn's arbs (look*, the same words). Each app passes the
languages it speaks, named in their own language.

Learn keeps its stored choice where it was, among its DeviceSettings,
and feeds the shared card from them: no migration, so nobody's language
or appearance moves, and nothing changes on its screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-04 22:30:29 +01:00
commit 23d3bcb4ca
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
5 changed files with 684 additions and 220 deletions

View file

@ -516,5 +516,11 @@
"publicProfileVerifyHint": "Ein Link bekommt ein Häkchen, sobald seine Seite mit rel=\"me\" auf deine Profilseite zurückverlinkt, wie Mastodon Links prüft.",
"profileAccount": "Konto",
"profileSheetLinkVerified": "Verlinkt zurück auf dieses Profil",
"speechNoRecognizer": "Auf diesem Gerät ist keine Spracherkennung installiert. Installiere eine, etwa FUTO Voice Input oder Googles Sprachdienste, und versuche es dann noch einmal."
"speechNoRecognizer": "Auf diesem Gerät ist keine Spracherkennung installiert. Installiere eine, etwa FUTO Voice Input oder Googles Sprachdienste, und versuche es dann noch einmal.",
"lookAppearance": "Darstellung",
"lookAppearanceDevice": "Gerätedesign",
"lookAppearanceLight": "Hell",
"lookAppearanceDark": "Dunkel",
"lookLanguage": "Sprache",
"lookLanguageDevice": "Gerätesprache"
}

View file

@ -1585,5 +1585,11 @@
"profileAccount": "Account",
"profileSheetLinkVerified": "Links back to this profile",
"speechNoRecognizer": "This device has no speech recognition installed. Install one, such as FUTO Voice Input or Google's speech services, then try again.",
"@speechNoRecognizer": {"description": "Shown when the microphone is tapped on a device without any speech recognition app (as GrapheneOS without Google's services), with a hint how to get one."}
"@speechNoRecognizer": {"description": "Shown when the microphone is tapped on a device without any speech recognition app (as GrapheneOS without Google's services), with a hint how to get one."},
"lookAppearance": "Appearance",
"lookAppearanceDevice": "Device theme",
"lookAppearanceLight": "Light",
"lookAppearanceDark": "Dark",
"lookLanguage": "Language",
"lookLanguageDevice": "Device language"
}

View file

@ -3204,6 +3204,42 @@ abstract class HalkyonAppLocalizations {
/// In en, this message translates to:
/// **'This device has no speech recognition installed. Install one, such as FUTO Voice Input or Google\'s speech services, then try again.'**
String get speechNoRecognizer;
/// No description provided for @lookAppearance.
///
/// In en, this message translates to:
/// **'Appearance'**
String get lookAppearance;
/// No description provided for @lookAppearanceDevice.
///
/// In en, this message translates to:
/// **'Device theme'**
String get lookAppearanceDevice;
/// No description provided for @lookAppearanceLight.
///
/// In en, this message translates to:
/// **'Light'**
String get lookAppearanceLight;
/// No description provided for @lookAppearanceDark.
///
/// In en, this message translates to:
/// **'Dark'**
String get lookAppearanceDark;
/// No description provided for @lookLanguage.
///
/// In en, this message translates to:
/// **'Language'**
String get lookLanguage;
/// No description provided for @lookLanguageDevice.
///
/// In en, this message translates to:
/// **'Device language'**
String get lookLanguageDevice;
}
class _HalkyonAppLocalizationsDelegate

View file

@ -2015,4 +2015,22 @@ class HalkyonAppLocalizationsDe extends HalkyonAppLocalizations {
@override
String get speechNoRecognizer =>
'Auf diesem Gerät ist keine Spracherkennung installiert. Installiere eine, etwa FUTO Voice Input oder Googles Sprachdienste, und versuche es dann noch einmal.';
@override
String get lookAppearance => 'Darstellung';
@override
String get lookAppearanceDevice => 'Gerätedesign';
@override
String get lookAppearanceLight => 'Hell';
@override
String get lookAppearanceDark => 'Dunkel';
@override
String get lookLanguage => 'Sprache';
@override
String get lookLanguageDevice => 'Gerätesprache';
}

View file

@ -1983,6 +1983,24 @@ class HalkyonAppLocalizationsEn extends HalkyonAppLocalizations {
@override
String get speechNoRecognizer =>
'This device has no speech recognition installed. Install one, such as FUTO Voice Input or Google\'s speech services, then try again.';
@override
String get lookAppearance => 'Appearance';
@override
String get lookAppearanceDevice => 'Device theme';
@override
String get lookAppearanceLight => 'Light';
@override
String get lookAppearanceDark => 'Dark';
@override
String get lookLanguage => 'Language';
@override
String get lookLanguageDevice => 'Device language';
}
/// The translations for English, as used in the United Kingdom (`en_GB`).