Stand up the Tanemaki monorepo and the first end-to-end vertical slice of Block 1 (offline, encrypted inventory): add a seed → see it in a categorized, searchable list → it persists → reopen and it's still there. Architecture (state management like G1nkgo, adapted to Tane's reality): - flutter_bloc (Cubit-first), but the encrypted Drift DB is the single source of truth; cubits stream from repositories (no hydrated_bloc/Hive, which would write plaintext at rest). - get_it composition root; go_router; slang i18n (ES/EN, Weblate-friendly JSON). Workspace & core: - pub workspace: packages/commons_core (pure Dart) + apps/app_seeds (Flutter). - commons_core primitives: UUIDv7 IdGen, Hybrid Logical Clock, Quantity value type (+ plant-aware QuantityKind), IdentityService root-seed stub. Data & security: - Drift schemaVersion=1 with all 10 Block-1 tables + common CRDT columns (HLC updated_at, last_author, tombstones); Movement append-only. - SQLCipher via an injectable executor that refuses to open a plaintext DB; DB key + root seed in the OS keystore (separate secrets). - Exported drift_schema_v1.json + migration scaffold. Tests (near-TDD; nothing merges without tests): - commons_core units (24), Drift migration test, "no plaintext at rest" security guard (runs where SQLCipher is present, skips otherwise), repository, widget, full quick-add flow, file-reopen persistence, and a no-hardcoded-strings i18n guard. GitLab CI: format + analyze + test + coverage. Follow-on Block-1 stories (item detail/edit, species catalog, germination UI) and all of Block 2 remain out of scope.
220 lines
5.8 KiB
Dart
220 lines
5.8 KiB
Dart
///
|
|
/// Generated file. Do not edit.
|
|
///
|
|
// coverage:ignore-file
|
|
// ignore_for_file: type=lint, unused_import
|
|
// dart format off
|
|
|
|
part of 'strings.g.dart';
|
|
|
|
// Path: <root>
|
|
typedef TranslationsEn = Translations; // ignore: unused_element
|
|
class Translations with 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
|
|
late final Translations$app$en app = Translations$app$en.internal(_root);
|
|
late final Translations$inventory$en inventory = Translations$inventory$en.internal(_root);
|
|
late final Translations$quickAdd$en quickAdd = Translations$quickAdd$en.internal(_root);
|
|
late final Translations$quantityKind$en quantityKind = Translations$quantityKind$en.internal(_root);
|
|
}
|
|
|
|
// Path: app
|
|
class Translations$app$en {
|
|
Translations$app$en.internal(this._root);
|
|
|
|
final Translations _root; // ignore: unused_field
|
|
|
|
// Translations
|
|
|
|
/// en: 'Tanemaki'
|
|
String get title => 'Tanemaki';
|
|
}
|
|
|
|
// Path: inventory
|
|
class Translations$inventory$en {
|
|
Translations$inventory$en.internal(this._root);
|
|
|
|
final Translations _root; // ignore: unused_field
|
|
|
|
// Translations
|
|
|
|
/// en: 'Inventory'
|
|
String get title => 'Inventory';
|
|
|
|
/// en: 'Search seeds'
|
|
String get searchHint => 'Search seeds';
|
|
|
|
/// en: 'No seeds yet. Tap + to add your first.'
|
|
String get empty => 'No seeds yet. Tap + to add your first.';
|
|
|
|
/// en: 'Uncategorized'
|
|
String get uncategorized => 'Uncategorized';
|
|
}
|
|
|
|
// Path: quickAdd
|
|
class Translations$quickAdd$en {
|
|
Translations$quickAdd$en.internal(this._root);
|
|
|
|
final Translations _root; // ignore: unused_field
|
|
|
|
// Translations
|
|
|
|
/// en: 'Add a seed'
|
|
String get title => 'Add a seed';
|
|
|
|
/// en: 'Name'
|
|
String get labelField => 'Name';
|
|
|
|
/// en: 'Give it a name'
|
|
String get labelRequired => 'Give it a name';
|
|
|
|
/// en: 'Add photo'
|
|
String get addPhoto => 'Add photo';
|
|
|
|
/// en: 'How much?'
|
|
String get quantity => 'How much?';
|
|
|
|
/// en: 'Add more…'
|
|
String get more => 'Add more…';
|
|
|
|
/// en: 'Save'
|
|
String get save => 'Save';
|
|
|
|
/// en: 'Cancel'
|
|
String get cancel => 'Cancel';
|
|
}
|
|
|
|
// Path: quantityKind
|
|
class Translations$quantityKind$en {
|
|
Translations$quantityKind$en.internal(this._root);
|
|
|
|
final Translations _root; // ignore: unused_field
|
|
|
|
// Translations
|
|
|
|
/// en: 'a few'
|
|
String get aFew => 'a few';
|
|
|
|
/// en: 'some'
|
|
String get some => 'some';
|
|
|
|
/// en: 'plenty'
|
|
String get plenty => 'plenty';
|
|
|
|
/// en: 'a handful'
|
|
String get handful => 'a handful';
|
|
|
|
/// en: 'a pinch'
|
|
String get pinch => 'a pinch';
|
|
|
|
/// en: 'a jar'
|
|
String get jar => 'a jar';
|
|
|
|
/// en: 'a packet'
|
|
String get packet => 'a packet';
|
|
|
|
/// en: 'a cob'
|
|
String get cob => 'a cob';
|
|
|
|
/// en: 'a head'
|
|
String get head => 'a head';
|
|
|
|
/// en: 'a pod'
|
|
String get pod => 'a pod';
|
|
|
|
/// en: 'an ear'
|
|
String get ear => 'an ear';
|
|
|
|
/// en: 'a fruit'
|
|
String get fruit => 'a fruit';
|
|
|
|
/// en: 'a bulb'
|
|
String get bulb => 'a bulb';
|
|
|
|
/// en: 'a tuber'
|
|
String get tuber => 'a tuber';
|
|
|
|
/// en: 'a seed head'
|
|
String get seedHead => 'a seed head';
|
|
|
|
/// en: 'a bunch'
|
|
String get bunch => 'a bunch';
|
|
|
|
/// en: 'grams'
|
|
String get grams => 'grams';
|
|
|
|
/// en: 'count'
|
|
String get count => 'count';
|
|
}
|
|
|
|
/// The flat map containing all translations for locale <en>.
|
|
/// Only for edge cases! For simple maps, use the map function of this library.
|
|
///
|
|
/// The Dart AOT compiler has issues with very large switch statements,
|
|
/// so the map is split into smaller functions (512 entries each).
|
|
extension on Translations {
|
|
dynamic _flatMapFunction(String path) {
|
|
return switch (path) {
|
|
'app.title' => 'Tanemaki',
|
|
'inventory.title' => 'Inventory',
|
|
'inventory.searchHint' => 'Search seeds',
|
|
'inventory.empty' => 'No seeds yet. Tap + to add your first.',
|
|
'inventory.uncategorized' => 'Uncategorized',
|
|
'quickAdd.title' => 'Add a seed',
|
|
'quickAdd.labelField' => 'Name',
|
|
'quickAdd.labelRequired' => 'Give it a name',
|
|
'quickAdd.addPhoto' => 'Add photo',
|
|
'quickAdd.quantity' => 'How much?',
|
|
'quickAdd.more' => 'Add more…',
|
|
'quickAdd.save' => 'Save',
|
|
'quickAdd.cancel' => 'Cancel',
|
|
'quantityKind.aFew' => 'a few',
|
|
'quantityKind.some' => 'some',
|
|
'quantityKind.plenty' => 'plenty',
|
|
'quantityKind.handful' => 'a handful',
|
|
'quantityKind.pinch' => 'a pinch',
|
|
'quantityKind.jar' => 'a jar',
|
|
'quantityKind.packet' => 'a packet',
|
|
'quantityKind.cob' => 'a cob',
|
|
'quantityKind.head' => 'a head',
|
|
'quantityKind.pod' => 'a pod',
|
|
'quantityKind.ear' => 'an ear',
|
|
'quantityKind.fruit' => 'a fruit',
|
|
'quantityKind.bulb' => 'a bulb',
|
|
'quantityKind.tuber' => 'a tuber',
|
|
'quantityKind.seedHead' => 'a seed head',
|
|
'quantityKind.bunch' => 'a bunch',
|
|
'quantityKind.grams' => 'grams',
|
|
'quantityKind.count' => 'count',
|
|
_ => null,
|
|
};
|
|
}
|
|
}
|