Feature: Add support for localization, introduce slang for translations, and integrate German and English locale support throughout the app
This commit is contained in:
182
finlog_app/app/lib/core/i18n/translations.g.dart
Normal file
182
finlog_app/app/lib/core/i18n/translations.g.dart
Normal file
@@ -0,0 +1,182 @@
|
||||
/// Generated file. Do not edit.
|
||||
///
|
||||
/// Source: assets/i18n
|
||||
/// To regenerate, run: `dart run slang`
|
||||
///
|
||||
/// Locales: 2
|
||||
/// Strings: 28 (14 per locale)
|
||||
///
|
||||
/// Built on 2025-09-27 at 09:55 UTC
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint, unused_import
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:slang/generated.dart';
|
||||
import 'package:slang_flutter/slang_flutter.dart';
|
||||
export 'package:slang_flutter/slang_flutter.dart';
|
||||
|
||||
import 'translations_de.g.dart' deferred as l_de;
|
||||
part 'translations_en.g.dart';
|
||||
|
||||
/// Supported locales.
|
||||
///
|
||||
/// Usage:
|
||||
/// - LocaleSettings.setLocale(AppLocale.en) // set locale
|
||||
/// - Locale locale = AppLocale.en.flutterLocale // get flutter locale from enum
|
||||
/// - if (LocaleSettings.currentLocale == AppLocale.en) // locale check
|
||||
enum AppLocale with BaseAppLocale<AppLocale, Translations> {
|
||||
en(languageCode: 'en'),
|
||||
de(languageCode: 'de');
|
||||
|
||||
const AppLocale({
|
||||
required this.languageCode,
|
||||
this.scriptCode, // ignore: unused_element, unused_element_parameter
|
||||
this.countryCode, // ignore: unused_element, unused_element_parameter
|
||||
});
|
||||
|
||||
@override final String languageCode;
|
||||
@override final String? scriptCode;
|
||||
@override final String? countryCode;
|
||||
|
||||
@override
|
||||
Future<Translations> build({
|
||||
Map<String, Node>? overrides,
|
||||
PluralResolver? cardinalResolver,
|
||||
PluralResolver? ordinalResolver,
|
||||
}) async {
|
||||
switch (this) {
|
||||
case AppLocale.en:
|
||||
return TranslationsEn(
|
||||
overrides: overrides,
|
||||
cardinalResolver: cardinalResolver,
|
||||
ordinalResolver: ordinalResolver,
|
||||
);
|
||||
case AppLocale.de:
|
||||
await l_de.loadLibrary();
|
||||
return l_de.TranslationsDe(
|
||||
overrides: overrides,
|
||||
cardinalResolver: cardinalResolver,
|
||||
ordinalResolver: ordinalResolver,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Translations buildSync({
|
||||
Map<String, Node>? overrides,
|
||||
PluralResolver? cardinalResolver,
|
||||
PluralResolver? ordinalResolver,
|
||||
}) {
|
||||
switch (this) {
|
||||
case AppLocale.en:
|
||||
return TranslationsEn(
|
||||
overrides: overrides,
|
||||
cardinalResolver: cardinalResolver,
|
||||
ordinalResolver: ordinalResolver,
|
||||
);
|
||||
case AppLocale.de:
|
||||
return l_de.TranslationsDe(
|
||||
overrides: overrides,
|
||||
cardinalResolver: cardinalResolver,
|
||||
ordinalResolver: ordinalResolver,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets current instance managed by [LocaleSettings].
|
||||
Translations get translations => LocaleSettings.instance.getTranslations(this);
|
||||
}
|
||||
|
||||
/// Method A: Simple
|
||||
///
|
||||
/// No rebuild after locale change.
|
||||
/// Translation happens during initialization of the widget (call of t).
|
||||
/// Configurable via 'translate_var'.
|
||||
///
|
||||
/// Usage:
|
||||
/// String a = t.someKey.anotherKey;
|
||||
/// String b = t['someKey.anotherKey']; // Only for edge cases!
|
||||
Translations get t => LocaleSettings.instance.currentTranslations;
|
||||
|
||||
/// Method B: Advanced
|
||||
///
|
||||
/// All widgets using this method will trigger a rebuild when locale changes.
|
||||
/// Use this if you have e.g. a settings page where the user can select the locale during runtime.
|
||||
///
|
||||
/// Step 1:
|
||||
/// wrap your App with
|
||||
/// TranslationProvider(
|
||||
/// child: MyApp()
|
||||
/// );
|
||||
///
|
||||
/// Step 2:
|
||||
/// final t = Translations.of(context); // Get t variable.
|
||||
/// String a = t.someKey.anotherKey; // Use t variable.
|
||||
/// String b = t['someKey.anotherKey']; // Only for edge cases!
|
||||
class TranslationProvider extends BaseTranslationProvider<AppLocale, Translations> {
|
||||
TranslationProvider({required super.child}) : super(settings: LocaleSettings.instance);
|
||||
|
||||
static InheritedLocaleData<AppLocale, Translations> of(BuildContext context) => InheritedLocaleData.of<AppLocale, Translations>(context);
|
||||
}
|
||||
|
||||
/// Method B shorthand via [BuildContext] extension method.
|
||||
/// Configurable via 'translate_var'.
|
||||
///
|
||||
/// Usage (e.g. in a widget's build method):
|
||||
/// context.t.someKey.anotherKey
|
||||
extension BuildContextTranslationsExtension on BuildContext {
|
||||
Translations get t => TranslationProvider.of(this).translations;
|
||||
}
|
||||
|
||||
/// Manages all translation instances and the current locale
|
||||
class LocaleSettings extends BaseFlutterLocaleSettings<AppLocale, Translations> {
|
||||
LocaleSettings._() : super(
|
||||
utils: AppLocaleUtils.instance,
|
||||
lazy: true,
|
||||
);
|
||||
|
||||
static final instance = LocaleSettings._();
|
||||
|
||||
// static aliases (checkout base methods for documentation)
|
||||
static AppLocale get currentLocale => instance.currentLocale;
|
||||
static Stream<AppLocale> getLocaleStream() => instance.getLocaleStream();
|
||||
static Future<AppLocale> setLocale(AppLocale locale, {bool? listenToDeviceLocale = false}) => instance.setLocale(locale, listenToDeviceLocale: listenToDeviceLocale);
|
||||
static Future<AppLocale> setLocaleRaw(String rawLocale, {bool? listenToDeviceLocale = false}) => instance.setLocaleRaw(rawLocale, listenToDeviceLocale: listenToDeviceLocale);
|
||||
static Future<AppLocale> useDeviceLocale() => instance.useDeviceLocale();
|
||||
static Future<void> setPluralResolver({String? language, AppLocale? locale, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) => instance.setPluralResolver(
|
||||
language: language,
|
||||
locale: locale,
|
||||
cardinalResolver: cardinalResolver,
|
||||
ordinalResolver: ordinalResolver,
|
||||
);
|
||||
|
||||
// synchronous versions
|
||||
static AppLocale setLocaleSync(AppLocale locale, {bool? listenToDeviceLocale = false}) => instance.setLocaleSync(locale, listenToDeviceLocale: listenToDeviceLocale);
|
||||
static AppLocale setLocaleRawSync(String rawLocale, {bool? listenToDeviceLocale = false}) => instance.setLocaleRawSync(rawLocale, listenToDeviceLocale: listenToDeviceLocale);
|
||||
static AppLocale useDeviceLocaleSync() => instance.useDeviceLocaleSync();
|
||||
static void setPluralResolverSync({String? language, AppLocale? locale, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) => instance.setPluralResolverSync(
|
||||
language: language,
|
||||
locale: locale,
|
||||
cardinalResolver: cardinalResolver,
|
||||
ordinalResolver: ordinalResolver,
|
||||
);
|
||||
}
|
||||
|
||||
/// Provides utility functions without any side effects.
|
||||
class AppLocaleUtils extends BaseAppLocaleUtils<AppLocale, Translations> {
|
||||
AppLocaleUtils._() : super(
|
||||
baseLocale: AppLocale.en,
|
||||
locales: AppLocale.values,
|
||||
);
|
||||
|
||||
static final instance = AppLocaleUtils._();
|
||||
|
||||
// static aliases (checkout base methods for documentation)
|
||||
static AppLocale parse(String rawLocale) => instance.parse(rawLocale);
|
||||
static AppLocale parseLocaleParts({required String languageCode, String? scriptCode, String? countryCode}) => instance.parseLocaleParts(languageCode: languageCode, scriptCode: scriptCode, countryCode: countryCode);
|
||||
static AppLocale findDeviceLocale() => instance.findDeviceLocale();
|
||||
static List<Locale> get supportedLocales => instance.supportedLocales;
|
||||
static List<String> get supportedLocalesRaw => instance.supportedLocalesRaw;
|
||||
}
|
||||
128
finlog_app/app/lib/core/i18n/translations_de.g.dart
Normal file
128
finlog_app/app/lib/core/i18n/translations_de.g.dart
Normal file
@@ -0,0 +1,128 @@
|
||||
///
|
||||
/// Generated file. Do not edit.
|
||||
///
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint, unused_import
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:slang/generated.dart';
|
||||
import 'translations.g.dart';
|
||||
|
||||
// Path: <root>
|
||||
class TranslationsDe implements Translations {
|
||||
/// You can call this constructor and build your own translation instance of this locale.
|
||||
/// Constructing via the enum [AppLocale.build] is preferred.
|
||||
TranslationsDe({Map<String, Node>? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver, TranslationMetadata<AppLocale, Translations>? meta})
|
||||
: assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'),
|
||||
$meta = meta ?? TranslationMetadata(
|
||||
locale: AppLocale.de,
|
||||
overrides: overrides ?? {},
|
||||
cardinalResolver: cardinalResolver,
|
||||
ordinalResolver: ordinalResolver,
|
||||
) {
|
||||
$meta.setFlatMapFunction(_flatMapFunction);
|
||||
}
|
||||
|
||||
/// Metadata for the translations of <de>.
|
||||
@override final TranslationMetadata<AppLocale, Translations> $meta;
|
||||
|
||||
/// Access flat map
|
||||
@override dynamic operator[](String key) => $meta.getTranslation(key);
|
||||
|
||||
late final TranslationsDe _root = this; // ignore: unused_field
|
||||
|
||||
@override
|
||||
TranslationsDe $copyWith({TranslationMetadata<AppLocale, Translations>? meta}) => TranslationsDe(meta: meta ?? this.$meta);
|
||||
|
||||
// Translations
|
||||
@override String hello({required Object name}) => 'Hallo ${name}';
|
||||
@override late final _TranslationsLoginDe login = _TranslationsLoginDe._(_root);
|
||||
@override late final _TranslationsSettingsDe settings = _TranslationsSettingsDe._(_root);
|
||||
}
|
||||
|
||||
// Path: login
|
||||
class _TranslationsLoginDe implements TranslationsLoginEn {
|
||||
_TranslationsLoginDe._(this._root);
|
||||
|
||||
final TranslationsDe _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
@override String get success => 'Login erfolgreich';
|
||||
}
|
||||
|
||||
// Path: settings
|
||||
class _TranslationsSettingsDe implements TranslationsSettingsEn {
|
||||
_TranslationsSettingsDe._(this._root);
|
||||
|
||||
final TranslationsDe _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
@override String get title => 'Einstellungen';
|
||||
@override late final _TranslationsSettingsSectionsDe sections = _TranslationsSettingsSectionsDe._(_root);
|
||||
@override late final _TranslationsSettingsItemsDe items = _TranslationsSettingsItemsDe._(_root);
|
||||
@override late final _TranslationsSettingsMessagesDe messages = _TranslationsSettingsMessagesDe._(_root);
|
||||
}
|
||||
|
||||
// Path: settings.sections
|
||||
class _TranslationsSettingsSectionsDe implements TranslationsSettingsSectionsEn {
|
||||
_TranslationsSettingsSectionsDe._(this._root);
|
||||
|
||||
final TranslationsDe _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
@override String get account => 'Konto & Daten';
|
||||
@override String get app => 'App';
|
||||
@override String get help => 'Hilfe & Rechtliches';
|
||||
}
|
||||
|
||||
// Path: settings.items
|
||||
class _TranslationsSettingsItemsDe implements TranslationsSettingsItemsEn {
|
||||
_TranslationsSettingsItemsDe._(this._root);
|
||||
|
||||
final TranslationsDe _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
@override String get appSettings => 'App-Einstellungen';
|
||||
@override String get personalData => 'Persönliche Daten';
|
||||
@override String get accountManagement => 'Kontoverwaltung';
|
||||
@override String get helpCenter => 'Hilfe';
|
||||
@override String get feedback => 'Feedback';
|
||||
@override String get legalPrivacy => 'Rechtliches & Datenschutz';
|
||||
@override String get logout => 'Abmelden';
|
||||
}
|
||||
|
||||
// Path: settings.messages
|
||||
class _TranslationsSettingsMessagesDe implements TranslationsSettingsMessagesEn {
|
||||
_TranslationsSettingsMessagesDe._(this._root);
|
||||
|
||||
final TranslationsDe _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
@override String get logoutNotImplemented => 'Logout… (noch nicht implementiert)';
|
||||
}
|
||||
|
||||
/// Flat map(s) containing all translations.
|
||||
/// Only for edge cases! For simple maps, use the map function of this library.
|
||||
extension on TranslationsDe {
|
||||
dynamic _flatMapFunction(String path) {
|
||||
switch (path) {
|
||||
case 'hello': return ({required Object name}) => 'Hallo ${name}';
|
||||
case 'login.success': return 'Login erfolgreich';
|
||||
case 'settings.title': return 'Einstellungen';
|
||||
case 'settings.sections.account': return 'Konto & Daten';
|
||||
case 'settings.sections.app': return 'App';
|
||||
case 'settings.sections.help': return 'Hilfe & Rechtliches';
|
||||
case 'settings.items.appSettings': return 'App-Einstellungen';
|
||||
case 'settings.items.personalData': return 'Persönliche Daten';
|
||||
case 'settings.items.accountManagement': return 'Kontoverwaltung';
|
||||
case 'settings.items.helpCenter': return 'Hilfe';
|
||||
case 'settings.items.feedback': return 'Feedback';
|
||||
case 'settings.items.legalPrivacy': return 'Rechtliches & Datenschutz';
|
||||
case 'settings.items.logout': return 'Abmelden';
|
||||
case 'settings.messages.logoutNotImplemented': return 'Logout… (noch nicht implementiert)';
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
161
finlog_app/app/lib/core/i18n/translations_en.g.dart
Normal file
161
finlog_app/app/lib/core/i18n/translations_en.g.dart
Normal file
@@ -0,0 +1,161 @@
|
||||
///
|
||||
/// Generated file. Do not edit.
|
||||
///
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint, unused_import
|
||||
|
||||
part of 'translations.g.dart';
|
||||
|
||||
// Path: <root>
|
||||
typedef TranslationsEn = Translations; // ignore: unused_element
|
||||
class Translations implements BaseTranslations<AppLocale, Translations> {
|
||||
/// Returns the current translations of the given [context].
|
||||
///
|
||||
/// Usage:
|
||||
/// final t = Translations.of(context);
|
||||
static Translations of(BuildContext context) => InheritedLocaleData.of<AppLocale, Translations>(context).translations;
|
||||
|
||||
/// You can call this constructor and build your own translation instance of this locale.
|
||||
/// Constructing via the enum [AppLocale.build] is preferred.
|
||||
Translations({Map<String, Node>? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver, TranslationMetadata<AppLocale, Translations>? meta})
|
||||
: assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'),
|
||||
$meta = meta ?? TranslationMetadata(
|
||||
locale: AppLocale.en,
|
||||
overrides: overrides ?? {},
|
||||
cardinalResolver: cardinalResolver,
|
||||
ordinalResolver: ordinalResolver,
|
||||
) {
|
||||
$meta.setFlatMapFunction(_flatMapFunction);
|
||||
}
|
||||
|
||||
/// Metadata for the translations of <en>.
|
||||
@override final TranslationMetadata<AppLocale, Translations> $meta;
|
||||
|
||||
/// Access flat map
|
||||
dynamic operator[](String key) => $meta.getTranslation(key);
|
||||
|
||||
late final Translations _root = this; // ignore: unused_field
|
||||
|
||||
Translations $copyWith({TranslationMetadata<AppLocale, Translations>? meta}) => Translations(meta: meta ?? this.$meta);
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'Hello $name'
|
||||
String hello({required Object name}) => 'Hello ${name}';
|
||||
|
||||
late final TranslationsLoginEn login = TranslationsLoginEn._(_root);
|
||||
late final TranslationsSettingsEn settings = TranslationsSettingsEn._(_root);
|
||||
}
|
||||
|
||||
// Path: login
|
||||
class TranslationsLoginEn {
|
||||
TranslationsLoginEn._(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'Logged in successfully'
|
||||
String get success => 'Logged in successfully';
|
||||
}
|
||||
|
||||
// Path: settings
|
||||
class TranslationsSettingsEn {
|
||||
TranslationsSettingsEn._(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'Settings'
|
||||
String get title => 'Settings';
|
||||
|
||||
late final TranslationsSettingsSectionsEn sections = TranslationsSettingsSectionsEn._(_root);
|
||||
late final TranslationsSettingsItemsEn items = TranslationsSettingsItemsEn._(_root);
|
||||
late final TranslationsSettingsMessagesEn messages = TranslationsSettingsMessagesEn._(_root);
|
||||
}
|
||||
|
||||
// Path: settings.sections
|
||||
class TranslationsSettingsSectionsEn {
|
||||
TranslationsSettingsSectionsEn._(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'Account & Data'
|
||||
String get account => 'Account & Data';
|
||||
|
||||
/// en: 'App'
|
||||
String get app => 'App';
|
||||
|
||||
/// en: 'Help & Legal'
|
||||
String get help => 'Help & Legal';
|
||||
}
|
||||
|
||||
// Path: settings.items
|
||||
class TranslationsSettingsItemsEn {
|
||||
TranslationsSettingsItemsEn._(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'App settings'
|
||||
String get appSettings => 'App settings';
|
||||
|
||||
/// en: 'Personal data'
|
||||
String get personalData => 'Personal data';
|
||||
|
||||
/// en: 'Account management'
|
||||
String get accountManagement => 'Account management';
|
||||
|
||||
/// en: 'Help'
|
||||
String get helpCenter => 'Help';
|
||||
|
||||
/// en: 'Feedback'
|
||||
String get feedback => 'Feedback';
|
||||
|
||||
/// en: 'Legal & Privacy'
|
||||
String get legalPrivacy => 'Legal & Privacy';
|
||||
|
||||
/// en: 'Sign out'
|
||||
String get logout => 'Sign out';
|
||||
}
|
||||
|
||||
// Path: settings.messages
|
||||
class TranslationsSettingsMessagesEn {
|
||||
TranslationsSettingsMessagesEn._(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'Logout… (not implemented yet)'
|
||||
String get logoutNotImplemented => 'Logout… (not implemented yet)';
|
||||
}
|
||||
|
||||
/// Flat map(s) containing all translations.
|
||||
/// Only for edge cases! For simple maps, use the map function of this library.
|
||||
extension on Translations {
|
||||
dynamic _flatMapFunction(String path) {
|
||||
switch (path) {
|
||||
case 'hello': return ({required Object name}) => 'Hello ${name}';
|
||||
case 'login.success': return 'Logged in successfully';
|
||||
case 'settings.title': return 'Settings';
|
||||
case 'settings.sections.account': return 'Account & Data';
|
||||
case 'settings.sections.app': return 'App';
|
||||
case 'settings.sections.help': return 'Help & Legal';
|
||||
case 'settings.items.appSettings': return 'App settings';
|
||||
case 'settings.items.personalData': return 'Personal data';
|
||||
case 'settings.items.accountManagement': return 'Account management';
|
||||
case 'settings.items.helpCenter': return 'Help';
|
||||
case 'settings.items.feedback': return 'Feedback';
|
||||
case 'settings.items.legalPrivacy': return 'Legal & Privacy';
|
||||
case 'settings.items.logout': return 'Sign out';
|
||||
case 'settings.messages.logoutNotImplemented': return 'Logout… (not implemented yet)';
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user