feat(inventory): additive CSV import for bulk digitization
Import a spreadsheet list (the same 21-column schema the CSV export already produces) as new varieties/lots. Tolerant reader: columns matched by header name in any order, only variety_label required, unknown enums fall back to a safe default, rows sharing variety_id collapse into one variety with several lots. Species re-linked by scientific name. Additive by design (fresh ids + HLC), so it never overwrites existing rows; JSON stays the canonical id-reconciling import. Adds a hand-rolled RFC 4180 parser (no new dependency), an importCsv path in VarietyRepository/ExportImportService, an 'Import from CSV' tile in the backup section, and en/es strings. Note: i18n .g.dart also carries pre-existing About/intro strings from the working tree (regenerated by slang).
This commit is contained in:
parent
21072633b5
commit
89b61bc9e4
11 changed files with 1070 additions and 2 deletions
|
|
@ -51,12 +51,17 @@
|
|||
"exportJsonSubtitle": "Complete copy, can be imported back",
|
||||
"importJson": "Import from JSON",
|
||||
"importJsonSubtitle": "Merge a saved copy into this inventory",
|
||||
"importCsv": "Import from CSV",
|
||||
"importCsvSubtitle": "Add a list from a spreadsheet",
|
||||
"importConfirmTitle": "Import a saved copy?",
|
||||
"importConfirmBody": "Entries merge with your inventory; when the same entry exists on both sides, the newest version wins. Nothing gets duplicated.",
|
||||
"importCsvConfirmTitle": "Import a CSV list?",
|
||||
"importCsvConfirmBody": "Every row is added as a new entry. This does not merge or replace, so importing the same file twice adds it twice.",
|
||||
"importAction": "Import",
|
||||
"exportSaved": "Copy saved",
|
||||
"cancelled": "Cancelled",
|
||||
"importDone": "Imported: {added} new, {updated} updated",
|
||||
"importCsvDone": "Imported {count} from CSV",
|
||||
"importFailed": "This file could not be read as a Tanemaki copy",
|
||||
"failed": "Something went wrong"
|
||||
},
|
||||
|
|
@ -73,6 +78,34 @@
|
|||
"openSourceLicenses": "Open-source licenses",
|
||||
"openSourceLicensesSubtitle": "Third-party libraries and their licenses"
|
||||
},
|
||||
"intro": {
|
||||
"skip": "Skip",
|
||||
"next": "Next",
|
||||
"start": "Get started",
|
||||
"menuEntry": "How Tanemaki works",
|
||||
"slides": {
|
||||
"welcome": {
|
||||
"title": "The seed that brought you here",
|
||||
"body": "Every traditional seed is a letter written by thousands of generations, passed from hand to hand. We are what we are thanks to that sharing."
|
||||
},
|
||||
"inventory": {
|
||||
"title": "Your seed bank, in your pocket",
|
||||
"body": "Note what you have, from which year, how much and where it came from — with the name you use. A photo and a name are enough to start."
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Yours, and only yours",
|
||||
"body": "No account, no internet, no trackers. Your data lives encrypted on your device, and only what you choose is ever shared."
|
||||
},
|
||||
"share": {
|
||||
"title": "Share, the way it's always been done",
|
||||
"body": "Offer what you have spare — gift, swap or sell — and let someone nearby find it. Only an approximate distance is shown, never your address; you close the deal in person."
|
||||
},
|
||||
"plantare": {
|
||||
"title": "To sow is to multiply",
|
||||
"body": "With a Plantare, whoever receives seed promises to return some later. And since returning it means growing it, every loan multiplies the commons."
|
||||
}
|
||||
}
|
||||
},
|
||||
"inventory": {
|
||||
"title": "Inventory",
|
||||
"searchHint": "Search seeds",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue