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": "Copia completa, se puede volver a importar",
|
||||
"importJson": "Importar desde JSON",
|
||||
"importJsonSubtitle": "Fusiona una copia guardada con este inventario",
|
||||
"importCsv": "Importar desde CSV",
|
||||
"importCsvSubtitle": "Añade una lista desde una hoja de cálculo",
|
||||
"importConfirmTitle": "¿Importar una copia guardada?",
|
||||
"importConfirmBody": "Las entradas se fusionan con tu inventario; si una entrada existe en ambos lados, gana la versión más reciente. No se duplica nada.",
|
||||
"importCsvConfirmTitle": "¿Importar una lista CSV?",
|
||||
"importCsvConfirmBody": "Cada fila se añade como una entrada nueva. No fusiona ni reemplaza, así que importar el mismo fichero dos veces lo añade dos veces.",
|
||||
"importAction": "Importar",
|
||||
"exportSaved": "Copia guardada",
|
||||
"cancelled": "Cancelado",
|
||||
"importDone": "Importado: {added} nuevas, {updated} actualizadas",
|
||||
"importCsvDone": "Importadas {count} desde CSV",
|
||||
"importFailed": "Este fichero no se pudo leer como una copia de Tanemaki",
|
||||
"failed": "Algo ha salido mal"
|
||||
},
|
||||
|
|
@ -73,6 +78,34 @@
|
|||
"openSourceLicenses": "Licencias de código abierto",
|
||||
"openSourceLicensesSubtitle": "Bibliotecas de terceros y sus licencias"
|
||||
},
|
||||
"intro": {
|
||||
"skip": "Saltar",
|
||||
"next": "Siguiente",
|
||||
"start": "Empezar",
|
||||
"menuEntry": "Cómo funciona Tanemaki",
|
||||
"slides": {
|
||||
"welcome": {
|
||||
"title": "La semilla que te trajo hasta aquí",
|
||||
"body": "Cada semilla tradicional es una carta escrita por miles de generaciones, que pasó de mano en mano. Somos lo que somos gracias a ese intercambio."
|
||||
},
|
||||
"inventory": {
|
||||
"title": "Tu banco de semillas, en el bolsillo",
|
||||
"body": "Apunta qué tienes, de qué año, cuánto y de dónde vino, con el nombre que tú usas. Una foto y un nombre bastan para empezar."
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Tuyo y solo tuyo",
|
||||
"body": "Sin cuenta, sin internet, sin rastreadores. Tus datos viven cifrados en tu dispositivo y solo se comparte lo que tú decidas."
|
||||
},
|
||||
"share": {
|
||||
"title": "Compartir, como siempre se hizo",
|
||||
"body": "Ofrece lo que te sobra —regalo, trueque o venta— y que alguien cerca lo encuentre. Solo se muestra la distancia aproximada, nunca tu dirección; el trato lo cierras en persona."
|
||||
},
|
||||
"plantare": {
|
||||
"title": "Sembrar es multiplicar",
|
||||
"body": "Con el Plantare, quien recibe promete devolver semilla más adelante. Y como para devolverla hay que cultivarla, cada préstamo multiplica el común."
|
||||
}
|
||||
}
|
||||
},
|
||||
"inventory": {
|
||||
"title": "Inventario",
|
||||
"searchHint": "Buscar semillas",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue