feat: cover seedlings (plantón) in copy + legal, backup cadence, server picker

Beta-tester feedback triage. The data model already had LotType.seedling as
first class; the gaps were copy and UX.

- Seedlings/plantones: broaden landing hero (EN/ES), in-app legal notice, and
  all legal texts (site + docs masters) from seeds-only to "seeds and
  seedlings", with a live-plant phytosanitary/transport caveat. Seeds stay the
  hero — targeted, not a blanket rename.
- Backups: settings line now states the 7-day cadence explicitly; cadence lives
  in AutoBackupService.backupInterval as the single source for text and schedule.
- Community servers: replace the manual wss:// text box with a checklist of the
  known servers (defaults visible/toggleable) plus an "add server" affordance
  with basic validation. No jargon in the UI.

i18n across en/es/pt/fr/de/ast (ja falls back). Tests updated + a new
server-picker widget test.
This commit is contained in:
vjrj 2026-07-15 15:57:23 +02:00
parent 7891a973f4
commit 1ce32c2b5c
36 changed files with 410 additions and 179 deletions

View file

@ -451,11 +451,11 @@ class Translations$backup$en {
/// en: 'Automatic backups'
String get autoBackupTitle => 'Automatic backups';
/// en: 'Last copy saved {date}'
String autoBackupLast({required Object date}) => 'Last copy saved ${date}';
/// en: 'Last copy saved {date} · every {days} days'
String autoBackupLast({required Object date, required Object days}) => 'Last copy saved ${date} · every ${days} days';
/// en: 'A copy is kept automatically in the background'
String get autoBackupNone => 'A copy is kept automatically in the background';
/// en: 'A copy is kept automatically every {days} days'
String autoBackupNone({required Object days}) => 'A copy is kept automatically every ${days} days';
/// en: 'Save a backup'
String get exportJson => 'Save a backup';
@ -1423,12 +1423,18 @@ class Translations$market$en {
/// en: 'Community servers'
String get serversLabel => 'Community servers';
/// en: 'One address per line (wss://…). Leave the defaults if unsure.'
String get serversHelp => 'One address per line (wss://…). Leave the defaults if unsure.';
/// en: 'Choose which servers to use. Leave the defaults if unsure.'
String get serversHelp => 'Choose which servers to use. Leave the defaults if unsure.';
/// en: 'Add another server'
String get serversAdvanced => 'Add another server';
/// en: 'Server address'
String get serverAddress => 'Server address';
/// en: 'Enter a valid address (wss://…)'
String get serverInvalid => 'Enter a valid address (wss://…)';
/// en: 'Save'
String get save => 'Save';
@ -2008,11 +2014,11 @@ class Translations$legal$en {
/// en: 'Tane is a tool, not a shop: exchanges are agreed directly between people, and nobody takes a cut. That also means you are responsible for what you offer and send. In the market: be honest about your seeds, only offer what you may share, treat people well, and don't spam. You can block anyone, and report offers or people that break the rules reports are acted on in the community servers.'
String get rulesBody => 'Tane is a tool, not a shop: exchanges are agreed directly between people, and nobody takes a cut. That also means you are responsible for what you offer and send.\n\nIn the market: be honest about your seeds, only offer what you may share, treat people well, and don\'t spam. You can block anyone, and report offers or people that break the rules — reports are acted on in the community servers.';
/// en: 'About sharing seeds'
String get seedsTitle => 'About sharing seeds';
/// en: 'About sharing seeds and seedlings'
String get seedsTitle => 'About sharing seeds and seedlings';
/// en: 'Gifting and swapping seeds between amateurs is broadly recognized in most countries. Selling can be different: in many places, selling seed of varieties that aren't officially registered is restricted check your local rules before asking a price. Sending seeds to another country is often restricted too, and commercially protected varieties must not be propagated without permission. When in doubt, keep it local and keep it a gift.'
String get seedsBody => 'Gifting and swapping seeds between amateurs is broadly recognized in most countries. Selling can be different: in many places, selling seed of varieties that aren\'t officially registered is restricted — check your local rules before asking a price.\n\nSending seeds to another country is often restricted too, and commercially protected varieties must not be propagated without permission. When in doubt, keep it local and keep it a gift.';
/// en: 'Gifting and swapping seeds between amateurs is broadly recognized in most countries. Selling can be different: in many places, selling seed of varieties that aren't officially registered is restricted check your local rules before asking a price. Sending seeds to another country is often restricted too, and commercially protected varieties must not be propagated without permission. When in doubt, keep it local and keep it a gift. The same spirit applies to seedlings and young plants, but live plants can carry stricter transport and plant-health rules than seeds moving them across regions or borders may need extra checks.'
String get seedsBody => 'Gifting and swapping seeds between amateurs is broadly recognized in most countries. Selling can be different: in many places, selling seed of varieties that aren\'t officially registered is restricted — check your local rules before asking a price.\n\nSending seeds to another country is often restricted too, and commercially protected varieties must not be propagated without permission. When in doubt, keep it local and keep it a gift.\n\nThe same spirit applies to seedlings and young plants, but live plants can carry stricter transport and plant-health rules than seeds — moving them across regions or borders may need extra checks.';
/// en: 'Read the full documents online'
String get readFull => 'Read the full documents online';
@ -2676,8 +2682,8 @@ extension on Translations {
'settings.aboutOpen' => 'About Tane',
'backup.title' => 'Backup & restore',
'backup.autoBackupTitle' => 'Automatic backups',
'backup.autoBackupLast' => ({required Object date}) => 'Last copy saved ${date}',
'backup.autoBackupNone' => 'A copy is kept automatically in the background',
'backup.autoBackupLast' => ({required Object date, required Object days}) => 'Last copy saved ${date} · every ${days} days',
'backup.autoBackupNone' => ({required Object days}) => 'A copy is kept automatically every ${days} days',
'backup.exportJson' => 'Save a backup',
'backup.exportJsonSubtitle' => 'A complete copy to keep safe, restore later or move to another device',
'backup.importJson' => 'Restore a backup',
@ -2984,8 +2990,10 @@ extension on Translations {
'market.areaCodeLabel' => 'Area code',
'market.areaCodeHint' => 'A short code like sp3e9 — not a place name',
'market.serversLabel' => 'Community servers',
'market.serversHelp' => 'One address per line (wss://…). Leave the defaults if unsure.',
'market.serversHelp' => 'Choose which servers to use. Leave the defaults if unsure.',
'market.serversAdvanced' => 'Add another server',
'market.serverAddress' => 'Server address',
'market.serverInvalid' => 'Enter a valid address (wss://…)',
'market.save' => 'Save',
'market.saved' => 'Saved',
'market.wanted' => 'Wanted',
@ -3102,10 +3110,10 @@ extension on Translations {
'plantare.returnOther' => 'Something else',
'plantare.workHoursLabel' => 'How many hours?',
'plantare.proposalsSection' => 'Waiting for your reply',
'plantare.incomingFrom' => ({required Object name}) => '${name} proposes a Plantaré',
'plantare.accept' => 'Accept & sign',
_ => null,
} ?? switch (path) {
'plantare.incomingFrom' => ({required Object name}) => '${name} proposes a Plantaré',
'plantare.accept' => 'Accept & sign',
'plantare.declineAction' => 'Decline',
'plantare.declineReasonHint' => 'Reason (optional)',
'plantare.acceptedToast' => 'Signed — you both hold it now',
@ -3148,8 +3156,8 @@ extension on Translations {
'legal.privacyBody' => 'Tane works without an account, and everything you record stays on your device, encrypted. There are no ads, no trackers, and no Tane server.\n\nNothing is shared unless you choose to: when you publish an offer or your profile, or send a message, it travels through community-run servers. Offers only ever carry a rough zone — never your address.\n\nWhat you publish is public, and copies may remain even after you remove it — so share with care.',
'legal.rulesTitle' => 'Rules of the road',
'legal.rulesBody' => 'Tane is a tool, not a shop: exchanges are agreed directly between people, and nobody takes a cut. That also means you are responsible for what you offer and send.\n\nIn the market: be honest about your seeds, only offer what you may share, treat people well, and don\'t spam. You can block anyone, and report offers or people that break the rules — reports are acted on in the community servers.',
'legal.seedsTitle' => 'About sharing seeds',
'legal.seedsBody' => 'Gifting and swapping seeds between amateurs is broadly recognized in most countries. Selling can be different: in many places, selling seed of varieties that aren\'t officially registered is restricted — check your local rules before asking a price.\n\nSending seeds to another country is often restricted too, and commercially protected varieties must not be propagated without permission. When in doubt, keep it local and keep it a gift.',
'legal.seedsTitle' => 'About sharing seeds and seedlings',
'legal.seedsBody' => 'Gifting and swapping seeds between amateurs is broadly recognized in most countries. Selling can be different: in many places, selling seed of varieties that aren\'t officially registered is restricted — check your local rules before asking a price.\n\nSending seeds to another country is often restricted too, and commercially protected varieties must not be propagated without permission. When in doubt, keep it local and keep it a gift.\n\nThe same spirit applies to seedlings and young plants, but live plants can carry stricter transport and plant-health rules than seeds — moving them across regions or borders may need extra checks.',
'legal.readFull' => 'Read the full documents online',
'marketGate.title' => 'Before you join the market',
'marketGate.intro' => 'The market is a shared space between neighbours. By continuing, you agree to a few simple rules:',