tane/apps/app_seeds/lib/i18n/en.i18n.json
vjrj 6809dc6143 feat(inventory): photo-first drafts + on-device OCR (digitization R2+R4)
Lower the bulk-digitization cliff with two more routes on top of the
already-landed CSV import and "save and add another":

- Photo-first drafts (capture now, catalogue later): burst-capture
  photos (camera or multi-gallery) into unnamed draft varieties, shown
  in a "to catalogue" tray, hidden from the main list until named.
  Adds Variety.isDraft (schema), addDraftVariety/watchDrafts/nameDraft,
  the triage sheet and the inventory banner.
- On-device OCR label suggestion (Tesseract, offline, no Google): a
  "Suggest name from photo" button in the naming dialog behind a
  LabelTextExtractor interface (Tesseract on Android/iOS, no-op
  elsewhere). Reads the largest print via hOCR bounding boxes, drops
  boilerplate/low-confidence noise, preprocesses (grayscale, contrast,
  upscale) and sweeps rotations (0-315 deg) so tilted packets still
  read. Bundles tessdata_fast eng+spa; validated on-device against real
  packets. The photo is written to a temp file deleted immediately in a
  finally block (the plugin needs a path) - a bounded, documented
  exception to no-plaintext-at-rest.

This commit also carries the co-developed schema evolution v5 to v8 that
shares these files (organic flag, species viability years, crop
calendar, lot provenance/abundance/preservation format, condition
checks) plus their exports/migrations and i18n.

Tests: CSV/draft/OCR unit + widget + migration green in isolation.
Note: the full widget suite currently hangs (>10 min) - under investigation.
2026-07-09 21:23:46 +02:00

303 lines
11 KiB
JSON

{
"app": {
"title": "Tanemaki"
},
"common": {
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"edit": "Edit",
"type": "Type",
"comingSoon": "Coming soon"
},
"home": {
"tagline": "Share and grow local seeds",
"openMarket": "Open market",
"openMarketSubtitle": "Browse and exchange",
"yourInventory": "Your inventory",
"yourInventorySubtitle": "Manage your seeds"
},
"photo": {
"camera": "Take a photo",
"gallery": "Choose from gallery",
"setAsCover": "Set as cover",
"isCover": "Cover photo",
"deleteConfirm": "Delete this photo?"
},
"menu": {
"tagline": "your seed bank",
"inventory": "Inventory",
"market": "Market",
"profile": "Your profile",
"chat": "Chat",
"wishlist": "Wishlist",
"following": "Following",
"settings": "Settings"
},
"settings": {
"language": "Language",
"systemLanguage": "System language",
"langEs": "Español",
"langEn": "English",
"about": "About",
"aboutText": "Local-first, encrypted inventory for traditional seeds. AGPL-3.0.",
"aboutOpen": "About Tanemaki"
},
"backup": {
"title": "Backup & restore",
"exportJson": "Save a backup",
"exportJsonSubtitle": "A complete copy to keep safe, restore later or move to another device",
"importJson": "Restore a backup",
"importJsonSubtitle": "Bring a saved copy back — nothing gets duplicated",
"exportCsv": "Export to a spreadsheet",
"exportCsvSubtitle": "A simple list for Excel or LibreOffice — no photos",
"importCsv": "Import a list",
"importCsvSubtitle": "Add entries from a spreadsheet",
"importConfirmTitle": "Restore a backup?",
"importConfirmBody": "Entries merge with your inventory; when the same entry exists on both sides, the newest version wins. Nothing gets duplicated.",
"importCsvConfirmTitle": "Import a 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": "Added {count} entries",
"importFailed": "This file could not be read as a Tanemaki copy",
"failed": "Something went wrong"
},
"about": {
"title": "About",
"kanji": "種まき",
"tagline": "A local-first, decentralized app for managing and sharing traditional seeds and seedlings.",
"intro": "Tanemaki (種まき, \"to sow / scatter seeds\" in Japanese; short name Tane, 種 \"seed\") helps people and collectives keep a friendly inventory of their seed bank, decide what they offer, and share it locally — without a central intermediary that could control, censor, or be fined for it. The goal is both practical and political: to support traditional seed varieties and push back against the seed monopoly.",
"heritage": "The name honors the old Japanese mutual-aid traditions around rice — yui (shared community labour) and tanomoshi (reciprocity funds) — that inspired the paper Plantare, the \"community currency for seed exchange\" (BAH-Semillero, 2009, CC-BY-SA). Tanemaki is the digital Plantare.",
"version": "Version",
"license": "License",
"licenseValue": "AGPL-3.0",
"website": "Website",
"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",
"empty": "No seeds yet. Tap + to add your first.",
"noMatches": "No seeds match your filters.",
"clearFilters": "Clear filters",
"uncategorized": "Uncategorized",
"needsReproductionFilter": "To regrow"
},
"draft": {
"capture": "Capture photos",
"captured": "{n} captured to catalogue",
"triageTitle": "To catalogue",
"triageCount": "{n} to catalogue",
"untitled": "Unnamed",
"nameField": "Name this seed",
"nameHint": "What is it?",
"suggestFromPhoto": "Suggest name from photo",
"discard": "Discard"
},
"quickAdd": {
"title": "Add a seed",
"labelField": "Name",
"labelRequired": "Give it a name",
"addPhoto": "Add photo",
"quantity": "How much?",
"more": "Add more…",
"save": "Save",
"saveAndAddAnother": "Save & add another",
"addedCount": "{n} added",
"cancel": "Cancel"
},
"detail": {
"notFound": "This seed is no longer here.",
"lots": "Lots",
"noLots": "No lots yet.",
"names": "Also known as",
"addName": "Add name",
"links": "Links",
"addLink": "Add link",
"linkUrl": "URL",
"linkTitle": "Title (optional)",
"notes": "Notes",
"addLot": "Add lot",
"editLot": "Edit lot",
"deleteConfirm": "Delete this seed?",
"year": "Year {year}",
"noYear": "Year unknown"
},
"germination": {
"title": "Germination",
"add": "Add test",
"sampleSize": "Sample size",
"germinated": "Germinated",
"none": "No germination tests yet.",
"result": "{percent}%"
},
"viability": {
"expiringSoon": "Use or reproduce this season",
"expiringSoonYears": "Use or reproduce this season · keeps ~{years} yr",
"expired": "Past typical viability — reproduce",
"expiredYears": "Past typical viability (~{years} yr) — reproduce"
},
"editVariety": {
"title": "Edit seed",
"name": "Name",
"category": "Category",
"notes": "Notes",
"species": "Species (from catalog)",
"speciesHint": "Search a species…",
"organic": "Organic",
"organicHint": "Grown organically (eco)"
},
"addLot": {
"title": "Add lot",
"year": "Harvest date",
"quantity": "How much?",
"amount": "Amount"
},
"harvest": {
"pickTitle": "Select month / year",
"anyMonth": "Any month",
"noDate": "Set harvest date",
"monthNames": [
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
]
},
"lotType": {
"seed": "Seeds",
"plant": "Plant",
"seedling": "Seedling",
"tree": "Tree / shrub",
"bulb": "Bulb / tuber",
"cutting": "Cutting"
},
"presentation": {
"title": "Packaging",
"none": "Unspecified",
"pot": "Pot",
"tray": "Tray",
"plug": "Plug",
"bareRoot": "Bare-root",
"rootBall": "Root-ball"
},
"provenance": {
"section": "Where it's from",
"seedsFrom": "Seeds from",
"seedsFromHint": "Who grew or gave them",
"place": "Place",
"placeHint": "Where they come from (with region)",
"addSeedsFrom": "Seeds from",
"addPlace": "Place"
},
"abundance": {
"add": "How much I have",
"title": "How much I have",
"none": "Not set",
"plentyToShare": "Plenty to share",
"enoughToShare": "Enough to share a little",
"enoughForMe": "Enough for me",
"runningLow": "Running low"
},
"cropCalendar": {
"add": "Crop calendar",
"title": "Crop calendar",
"sow": "Sow",
"transplant": "Transplant",
"flowering": "Flowering",
"fruiting": "Fruiting",
"seedHarvest": "Seed harvest",
"unset": "—"
},
"needsReproduction": {
"label": "To regrow this season",
"hint": "Grow it out before the seed runs out",
"badge": "To regrow"
},
"preservation": {
"add": "How it's kept",
"title": "How it's kept",
"none": "Unspecified",
"jarWithDesiccant": "Jar with drying agent",
"glassJar": "Glass jar",
"paperEnvelope": "Paper envelope",
"paperBag": "Paper bag",
"plasticBag": "Plastic bag"
},
"conditionCheck": {
"advanced": "Storage & seed-bank details",
"title": "Storage checks",
"add": "Add check",
"containers": "Jars / containers",
"desiccant": "Drying agent",
"none": "No storage checks yet.",
"summary": "{count} jar(s) · {state}"
},
"desiccant": {
"none": "None",
"add": "Add some",
"replace": "Replace it",
"dry": "Blue — dry",
"fresh": "Just renewed"
},
"unit": {
"aFew": "a few",
"some": "some",
"plenty": "plenty",
"pinch": "a pinch",
"handful": { "singular": "handful", "plural": "handfuls" },
"teaspoon": { "singular": "teaspoon", "plural": "teaspoons" },
"spoon": { "singular": "spoon", "plural": "spoons" },
"cup": { "singular": "cup", "plural": "cups" },
"jar": { "singular": "jar", "plural": "jars" },
"sack": { "singular": "sack", "plural": "sacks" },
"packet": { "singular": "packet", "plural": "packets" },
"cob": { "singular": "cob", "plural": "cobs" },
"pod": { "singular": "pod", "plural": "pods" },
"ear": { "singular": "ear", "plural": "ears" },
"head": { "singular": "head", "plural": "heads" },
"fruit": { "singular": "fruit", "plural": "fruits" },
"bulb": { "singular": "bulb", "plural": "bulbs" },
"tuber": { "singular": "tuber", "plural": "tubers" },
"seedHead": { "singular": "seed head", "plural": "seed heads" },
"bunch": { "singular": "bunch", "plural": "bunches" },
"plant": { "singular": "plant", "plural": "plants" },
"pot": { "singular": "pot", "plural": "pots" },
"tray": { "singular": "tray", "plural": "trays" },
"seedling": { "singular": "seedling", "plural": "seedlings" },
"tree": { "singular": "tree", "plural": "trees" },
"cutting": { "singular": "cutting", "plural": "cuttings" },
"grams": { "singular": "gram", "plural": "grams" },
"count": { "singular": "seed", "plural": "seeds" }
}
}