Merge Tanemaki → Tane rename into main
This commit is contained in:
commit
f31f58cc7e
66 changed files with 293 additions and 293 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
# CI for Tanemaki. Mirrors the local verification gate (analyze + test +
|
# CI for Tane. Mirrors the local verification gate (analyze + test +
|
||||||
# coverage) from docs/design/testing.md. Adapt to GitHub Actions if the
|
# coverage) from docs/design/testing.md. Adapt to GitHub Actions if the
|
||||||
# canonical remote changes; the commands are the same.
|
# canonical remote changes; the commands are the same.
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
All notable changes to Tanemaki are recorded here. Human-readable, newest
|
All notable changes to Tane are recorded here. Human-readable, newest
|
||||||
first. Dates are ISO (YYYY-MM-DD).
|
first. Dates are ISO (YYYY-MM-DD).
|
||||||
|
|
||||||
## [Unreleased] — Block 1 beta prep
|
## [Unreleased] — Block 1 beta prep
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
# CLAUDE.md — Tanemaki
|
# CLAUDE.md — Tane
|
||||||
|
|
||||||
Context for AI agents (Claude Code) working in this repo. Read this first, then [`docs/design/open-decisions.md`](docs/design/open-decisions.md) (the **live decision log**).
|
Context for AI agents (Claude Code) working in this repo. Read this first, then [`docs/design/open-decisions.md`](docs/design/open-decisions.md) (the **live decision log**).
|
||||||
|
|
||||||
## What this is
|
## What this is
|
||||||
|
|
||||||
**Tanemaki** (種まき, "sow/scatter seeds"; short: **Tane**) — a **local-first, decentralized** app to manage and share traditional seeds. First app on a generic commons engine. Web: `tanemaki.app`. Package id: `org.comunes.tane`. See [`VISION.md`](VISION.md) for the human explanation and [`PLAN.md`](PLAN.md) for the origin analysis (with a "Nota de vigencia" reconciling evolved decisions).
|
**Tane** (種, "seed"; full name **Tanemaki** 種まき, "sow/scatter seeds") — a **local-first, decentralized** app to manage and share traditional seeds. First app on a generic commons engine. Web: `tane.comunes.org`. Package id: `org.comunes.tane`. See [`VISION.md`](VISION.md) for the human explanation and [`PLAN.md`](PLAN.md) for the origin analysis (with a "Nota de vigencia" reconciling evolved decisions).
|
||||||
|
|
||||||
## Golden rules (do not violate)
|
## Golden rules (do not violate)
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ tane/
|
||||||
packages/
|
packages/
|
||||||
commons_core/ # identity, Party/Group, TrustEdge, Offer, Pledge, transport (Nostr)+CRDT+sync, geohash discovery. NO seed specifics.
|
commons_core/ # identity, Party/Group, TrustEdge, Offer, Pledge, transport (Nostr)+CRDT+sync, geohash discovery. NO seed specifics.
|
||||||
apps/
|
apps/
|
||||||
app_seeds/ # Tanemaki: Variety/Lot/Movement/Species, germination, plant-family units, UI, i18n, commons_ui (embedded for now)
|
app_seeds/ # Tane: Variety/Lot/Movement/Species, germination, plant-family units, UI, i18n, commons_ui (embedded for now)
|
||||||
```
|
```
|
||||||
Dependency direction: **`app_seeds` → `commons_core`, never the reverse.** Boundary rules in [`docs/design/core-domain-boundary.md`](docs/design/core-domain-boundary.md).
|
Dependency direction: **`app_seeds` → `commons_core`, never the reverse.** Boundary rules in [`docs/design/core-domain-boundary.md`](docs/design/core-domain-boundary.md).
|
||||||
|
|
||||||
|
|
|
||||||
12
PLAN.md
12
PLAN.md
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Plan de análisis y desarrollo
|
# Tane — Plan de análisis y desarrollo
|
||||||
|
|
||||||
*App descentralizada para la gestión personal y la compartición de semillas y plantel*
|
*App descentralizada para la gestión personal y la compartición de semillas y plantel*
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@ Documento de trabajo · Julio 2026 · Autor del proyecto: vjrj (Comunes)
|
||||||
Licencia del proyecto: **AGPL-3.0** (software) · docs y assets CC-BY-SA.
|
Licencia del proyecto: **AGPL-3.0** (software) · docs y assets CC-BY-SA.
|
||||||
|
|
||||||
> **Nota de vigencia.** Este PLAN es el documento *origen*. Varias decisiones han evolucionado en `docs/design/`; la **lista viva de decisiones** es [docs/design/open-decisions.md](docs/design/open-decisions.md). En particular, actualizan/matizan este texto:
|
> **Nota de vigencia.** Este PLAN es el documento *origen*. Varias decisiones han evolucionado en `docs/design/`; la **lista viva de decisiones** es [docs/design/open-decisions.md](docs/design/open-decisions.md). En particular, actualizan/matizan este texto:
|
||||||
> - **Nombre:** Tanemaki (種まき), apodo Tane; dominio `tanemaki.app`.
|
> - **Nombre:** **Tane** (種; nombre completo Tanemaki 種まき); dominio `tane.comunes.org`. (2026-07-12: se soltó el "-maki"; el §5-ter de abajo, que eligió "Tanemaki" y descartó "Tane a secas" + `tanemaki.app`, quedó **superado**.)
|
||||||
> - **Identidad:** *una sola clave* raíz estilo Duniter/Ğ1, de la que se **deriva** la clave secp256k1 para el transporte (Nostr). No "solo Nostr". → [g1-integration.md](docs/design/g1-integration.md)
|
> - **Identidad:** *una sola clave* raíz estilo Duniter/Ğ1, de la que se **deriva** la clave secp256k1 para el transporte (Nostr). No "solo Nostr". → [g1-integration.md](docs/design/g1-integration.md)
|
||||||
> - **"¿Blockchain?" (§4):** sigue siendo *no* para los datos de semillas (locales/CRDT), pero **sí interoperamos con la cadena de Duniter v2** para identidad, red de confianza y moneda **opcionales** (Ğ1). No es contradicción: la blockchain no es el libro mayor de las semillas, es una capa opcional de identidad/confianza/pago.
|
> - **"¿Blockchain?" (§4):** sigue siendo *no* para los datos de semillas (locales/CRDT), pero **sí interoperamos con la cadena de Duniter v2** para identidad, red de confianza y moneda **opcionales** (Ğ1). No es contradicción: la blockchain no es el libro mayor de las semillas, es una capa opcional de identidad/confianza/pago.
|
||||||
> - **Transporte social:** Nostr sigue siendo la vía (viable con la clave derivada); datapods de Duniter descartados (no en servicio).
|
> - **Transporte social:** Nostr sigue siendo la vía (viable con la clave derivada); datapods de Duniter descartados (no en servicio).
|
||||||
|
|
@ -16,7 +16,7 @@ Licencia del proyecto: **AGPL-3.0** (software) · docs y assets CC-BY-SA.
|
||||||
|
|
||||||
## 0. Resumen ejecutivo
|
## 0. Resumen ejecutivo
|
||||||
|
|
||||||
Tanemaki es una app **local-first, multilingüe y descentralizada** para que personas y colectivos gestionen su banco de semillas y plantel, decidan qué ofrecen, y lo compartan localmente sin un intermediario central. La motivación es política además de práctica: contrarrestar el monopolio de las semillas privativas y sostener las variedades tradicionales, en la línea de [Plantare](http://plantare.ourproject.org/) y del relato "Las semillas del conocimiento libre" que ya escribiste en *Diagonal* (2005).
|
Tane es una app **local-first, multilingüe y descentralizada** para que personas y colectivos gestionen su banco de semillas y plantel, decidan qué ofrecen, y lo compartan localmente sin un intermediario central. La motivación es política además de práctica: contrarrestar el monopolio de las semillas privativas y sostener las variedades tradicionales, en la línea de [Plantare](http://plantare.ourproject.org/) y del relato "Las semillas del conocimiento libre" que ya escribiste en *Diagonal* (2005).
|
||||||
|
|
||||||
La decisión de partida acordada:
|
La decisión de partida acordada:
|
||||||
|
|
||||||
|
|
@ -213,7 +213,9 @@ En una frase: **Plantare ya resolvió, en papel y en 2009, el problema de la con
|
||||||
|
|
||||||
## 5-ter. Nombre de la app y pantalla "Acerca de"
|
## 5-ter. Nombre de la app y pantalla "Acerca de"
|
||||||
|
|
||||||
**Nombre (decidido): Tanemaki** (種まき, japonés: "sembrar / esparcir semillas"), con apodo corto **"Tane"** (種, "semilla") — que es el identificador que usamos en repo y código. Honra la tradición japonesa de ayuda mutua que inspiró el Plantare original, viaja bien en cualquier idioma (no es ni anglo ni latina), y su significado —*esparcir semillas*— captura literalmente la faceta vírica y descentralizada del proyecto (§5-bis). Alternativas descartadas por colisión o encaje: Tane a secas como nombre público (genérico, dominios cortos en manos de brokers), Plantare (solo funciona en español/latín), Spora (suena fúngico), Semia (demasiado "semiótica").
|
> **Superado (2026-07-12):** el nombre público es ahora **Tane** (se soltó el "-maki") y el dominio es `tane.comunes.org`. Lo que sigue documenta la decisión original y se conserva como registro histórico.
|
||||||
|
|
||||||
|
**Nombre (decidido en su momento): Tanemaki** (種まき, japonés: "sembrar / esparcir semillas"), con apodo corto **"Tane"** (種, "semilla") — que es el identificador que usamos en repo y código. Honra la tradición japonesa de ayuda mutua que inspiró el Plantare original, viaja bien en cualquier idioma (no es ni anglo ni latina), y su significado —*esparcir semillas*— captura literalmente la faceta vírica y descentralizada del proyecto (§5-bis). Alternativas descartadas por colisión o encaje: Tane a secas como nombre público (genérico, dominios cortos en manos de brokers), Plantare (solo funciona en español/latín), Spora (suena fúngico), Semia (demasiado "semiótica").
|
||||||
|
|
||||||
**Identidad digital (decidida):**
|
**Identidad digital (decidida):**
|
||||||
- **Dominio:** `tanemaki.app` (libre, barato, fuerza HTTPS). Descartados `.eco` (caro ~70 €/año + Eco Profile obligatorio anual) y los `tane.*` cortos (cogidos o aparcados para reventa).
|
- **Dominio:** `tanemaki.app` (libre, barato, fuerza HTTPS). Descartados `.eco` (caro ~70 €/año + Eco Profile obligatorio anual) y los `tane.*` cortos (cogidos o aparcados para reventa).
|
||||||
|
|
@ -288,7 +290,7 @@ El mayor riesgo de este proyecto no es técnico, es de *continuidad*. Los proyec
|
||||||
- **Descartar** el intento en Meteor (`meteor-old`, `seedks/`): Meteor es cliente-servidor centralizado, justo lo contrario de local-first, y el ecosistema está en declive. No arrastres esa base.
|
- **Descartar** el intento en Meteor (`meteor-old`, `seedks/`): Meteor es cliente-servidor centralizado, justo lo contrario de local-first, y el ecosistema está en declive. No arrastres esa base.
|
||||||
- **Conservar y tratar como oro** los **mockups** (`docs/mockups/`) — como tú mismo dices, es lo valioso. Ya definen: inicio, menús, búsqueda con tarjetas y precio/trueque, inventario por categorías con miembros del banco, ítem con historial/docs/comentarios, perfil público con mapa y valoraciones, chat. Son un *product spec* casi completo de las capas 1–3.
|
- **Conservar y tratar como oro** los **mockups** (`docs/mockups/`) — como tú mismo dices, es lo valioso. Ya definen: inicio, menús, búsqueda con tarjetas y precio/trueque, inventario por categorías con miembros del banco, ítem con historial/docs/comentarios, perfil público con mapa y valoraciones, chat. Son un *product spec* casi completo de las capas 1–3.
|
||||||
- **Conservar** los iconos SVG propios (`docs/icons.svg`, la fuente `seedks.ttf`) y el logo — identidad visual ya hecha.
|
- **Conservar** los iconos SVG propios (`docs/icons.svg`, la fuente `seedks.ttf`) y el logo — identidad visual ya hecha.
|
||||||
- El nombre **Tanemaki** (apodo **Tane**) ya está decidido — ver §5-ter para el razonamiento y las alternativas descartadas. El antiguo nombre de trabajo "seedks" queda solo como nombre heredado de algún asset (p.ej. la fuente `seedks.ttf`), no como nombre del proyecto.
|
- El nombre **Tane** (antes Tanemaki, 種まき) ya está decidido — ver §5-ter para el razonamiento histórico y las alternativas descartadas. El antiguo nombre de trabajo "seedks" queda solo como nombre heredado de algún asset (p.ej. la fuente `seedks.ttf`), no como nombre del proyecto.
|
||||||
|
|
||||||
**Nota operativa sobre esta carpeta:** está sincronizada con Seafile. Para el desarrollo con git, tu idea de un *bare repo* en `~/repos` es la correcta: evita meter un `.git` dentro de una carpeta sincronizada por Seafile (conflictos entre los dos sistemas de sincronización). Trabaja el código en un clon fuera de Seafile, con el bare repo como origen. Puedo ayudarte a montarlo.
|
**Nota operativa sobre esta carpeta:** está sincronizada con Seafile. Para el desarrollo con git, tu idea de un *bare repo* en `~/repos` es la correcta: evita meter un `.git` dentro de una carpeta sincronizada por Seafile (conflictos entre los dos sistemas de sincronización). Trabaja el código en un clon fuera de Seafile, con el bare repo como origen. Puedo ayudarte a montarlo.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
# Tanemaki 種まき
|
# Tane 種
|
||||||
|
|
||||||
*A local-first, decentralized app for managing and sharing traditional seeds and seedlings.*
|
*A local-first, decentralized app for managing and sharing traditional seeds and seedlings.*
|
||||||
|
|
||||||
**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.
|
**Tane** (種, "seed" in Japanese) 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. Its name comes from **tanemaki** (種まき), "to sow / scatter seeds". The goal is both practical and political: to support traditional seed varieties and push back against the seed monopoly.
|
||||||
|
|
||||||
The name honors the old Japanese mutual-aid traditions around rice — *yui* (shared community labor) 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.
|
The name honors the old Japanese mutual-aid traditions around rice — *yui* (shared community labor) and *tanomoshi* (reciprocity funds) — that inspired the paper **Plantare**, the "community currency for seed exchange" (BAH-Semillero, 2009, CC-BY-SA). Tane is the digital Plantare.
|
||||||
|
|
||||||
- Web: https://tanemaki.app
|
- Web: https://tane.comunes.org
|
||||||
- Package id: `org.comunes.tane`
|
- Package id: `org.comunes.tane`
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
|
||||||
18
VISION.md
18
VISION.md
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Visión
|
# Tane — Visión
|
||||||
|
|
||||||
*Explicación para personas. Fuente de la que derivar el README, la web y las solicitudes de financiación. Lengua: español (se derivará versión en inglés para NLnet/comunidad internacional).*
|
*Explicación para personas. Fuente de la que derivar el README, la web y las solicitudes de financiación. Lengua: español (se derivará versión en inglés para NLnet/comunidad internacional).*
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
## En una frase
|
## En una frase
|
||||||
|
|
||||||
**Tanemaki es una app libre para cuidar y compartir semillas tradicionales, que funciona sin conexión y sin intermediarios: tu banco de semillas en el bolsillo, y una red vecinal para hacerlas circular.**
|
**Tane es una app libre para cuidar y compartir semillas tradicionales, que funciona sin conexión y sin intermediarios: tu banco de semillas en el bolsillo, y una red vecinal para hacerlas circular.**
|
||||||
|
|
||||||
## El problema
|
## El problema
|
||||||
|
|
||||||
|
|
@ -18,13 +18,13 @@ Quien quiere resistir esto —redes de semillas, colectivos agroecológicos, hor
|
||||||
|
|
||||||
## La idea
|
## La idea
|
||||||
|
|
||||||
Tanemaki hace dos cosas, y las hace fáciles:
|
Tane hace dos cosas, y las hace fáciles:
|
||||||
|
|
||||||
**Gestionar.** Llevar, de forma sencilla y hasta agradable, el inventario de tu banco de semillas y tu plantel: qué tienes, de qué año, cuánto, de dónde vino, con el nombre que tú usas (no hace falta saber latín). Sirve igual para una persona con cuatro sobres en un cajón que para un banco comunitario con cientos de variedades.
|
**Gestionar.** Llevar, de forma sencilla y hasta agradable, el inventario de tu banco de semillas y tu plantel: qué tienes, de qué año, cuánto, de dónde vino, con el nombre que tú usas (no hace falta saber latín). Sirve igual para una persona con cuatro sobres en un cajón que para un banco comunitario con cientos de variedades.
|
||||||
|
|
||||||
**Compartir.** Decir qué ofreces y qué no, y que alguien cerca lo encuentre y te contacte —para regalar, intercambiar, o vender si así lo quieres— **sin una empresa en medio** que controle, censure o se lleve una comisión. La app presenta; el trato lo cierran las personas.
|
**Compartir.** Decir qué ofreces y qué no, y que alguien cerca lo encuentre y te contacte —para regalar, intercambiar, o vender si así lo quieres— **sin una empresa en medio** que controle, censure o se lleve una comisión. La app presenta; el trato lo cierran las personas.
|
||||||
|
|
||||||
Detrás de todo late una idea: las semillas tradicionales son un bien común de la humanidad. Frente a su privatización, Tanemaki quiere ponértelo fácil para conservarlas, multiplicarlas y hacerlas circular.
|
Detrás de todo late una idea: las semillas tradicionales son un bien común de la humanidad. Frente a su privatización, Tane quiere ponértelo fácil para conservarlas, multiplicarlas y hacerlas circular.
|
||||||
|
|
||||||
## Para quién
|
## Para quién
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ Para todo el mundo, **de los 10 a los 80 años**. Para la persona mayor que guar
|
||||||
|
|
||||||
## Cómo funciona (sin tecnicismos)
|
## Cómo funciona (sin tecnicismos)
|
||||||
|
|
||||||
Tanemaki está pensada por **capas**, y cada una es útil por sí sola:
|
Tane está pensada por **capas**, y cada una es útil por sí sola:
|
||||||
|
|
||||||
1. **Tu inventario.** Vive en tu teléfono. Funciona sin internet, sin crear ninguna cuenta. Añades una semilla con una foto y un nombre en veinte segundos; si quieres, le pones año, cantidad, procedencia, notas, o hasta su nombre científico (que la app te sugiere, no te obliga a teclear). Y una **"varilla"** puede ofrecerte rellenar el resto por ti —nombres, cuidados, cómo conservarla, años de viabilidad— a partir de lo poco que has escrito, como propuestas que confirmas o corriges.
|
1. **Tu inventario.** Vive en tu teléfono. Funciona sin internet, sin crear ninguna cuenta. Añades una semilla con una foto y un nombre en veinte segundos; si quieres, le pones año, cantidad, procedencia, notas, o hasta su nombre científico (que la app te sugiere, no te obliga a teclear). Y una **"varilla"** puede ofrecerte rellenar el resto por ti —nombres, cuidados, cómo conservarla, años de viabilidad— a partir de lo poco que has escrito, como propuestas que confirmas o corriges.
|
||||||
|
|
||||||
|
|
@ -61,15 +61,15 @@ Software libre (copyleft). Funciona sin conexión y sin cuenta. Tus datos, en tu
|
||||||
|
|
||||||
## El nombre y su herencia
|
## El nombre y su herencia
|
||||||
|
|
||||||
**Tanemaki** (種まき) significa "sembrar, esparcir semillas" en japonés. Es un homenaje a las antiguas tradiciones japonesas de ayuda mutua en torno al arroz —el *yui*, el trabajo comunitario compartido, y el *tanomoshi*, los fondos vecinales de reciprocidad— que inspiraron el Plantare original. El apodo corto es **Tane** ("semilla"). Tanemaki continúa el camino del Plantare (BAH-Semillero, 2009), de la Red de Semillas "Resembrando e Intercambiando" y de la cultura libre. *Las semillas del conocimiento libre ya están plantadas.*
|
**Tane** (種, "semilla") toma su nombre de **tanemaki** (種まき), "sembrar, esparcir semillas" en japonés. Es un homenaje a las antiguas tradiciones japonesas de ayuda mutua en torno al arroz —el *yui*, el trabajo comunitario compartido, y el *tanomoshi*, los fondos vecinales de reciprocidad— que inspiraron el Plantare original. Tane continúa el camino del Plantare (BAH-Semillero, 2009), de la Red de Semillas "Resembrando e Intercambiando" y de la cultura libre. *Las semillas del conocimiento libre ya están plantadas.*
|
||||||
|
|
||||||
## Sostenibilidad
|
## Sostenibilidad
|
||||||
|
|
||||||
Tanemaki no tiene modelo de negocio, y es a propósito. Al ser local-first, sigue siendo útil aunque nadie la mantenga ni haya servidores encendidos: la utilidad no caduca. Al ser libre y con datos abiertos, cualquiera puede continuarla. Su desarrollo se sostiene con trabajo voluntario, comunidad (redes de semillas, colectivos) y financiación de bien común (fondos europeos de tecnología libre como NLnet/NGI Zero), nunca cobrando por uso ni extrayendo valor de quien la usa.
|
Tane no tiene modelo de negocio, y es a propósito. Al ser local-first, sigue siendo útil aunque nadie la mantenga ni haya servidores encendidos: la utilidad no caduca. Al ser libre y con datos abiertos, cualquiera puede continuarla. Su desarrollo se sostiene con trabajo voluntario, comunidad (redes de semillas, colectivos) y financiación de bien común (fondos europeos de tecnología libre como NLnet/NGI Zero), nunca cobrando por uso ni extrayendo valor de quien la usa.
|
||||||
|
|
||||||
## La visión mayor
|
## La visión mayor
|
||||||
|
|
||||||
Bajo Tanemaki hay un motor común (`commons_core`) que resuelve lo difícil: identidad propia, red descentralizada, confianza, y el préstamo-con-devolución. Ese motor sirve para más que semillas. La misma idea —"qué tengo, qué comparto, con confianza y devolución"— vale para una **biblioteca vecinal de cosas y herramientas**. Tanemaki es la primera app sobre ese motor; otras podrán venir. Generalizamos el motor, no el producto: cada app sigue siendo simple y de un solo propósito.
|
Bajo Tane hay un motor común (`commons_core`) que resuelve lo difícil: identidad propia, red descentralizada, confianza, y el préstamo-con-devolución. Ese motor sirve para más que semillas. La misma idea —"qué tengo, qué comparto, con confianza y devolución"— vale para una **biblioteca vecinal de cosas y herramientas**. Tane es la primera app sobre ese motor; otras podrán venir. Generalizamos el motor, no el producto: cada app sigue siendo simple y de un solo propósito.
|
||||||
|
|
||||||
## Estado y camino
|
## Estado y camino
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ En diseño temprano. El orden previsto: primero un **inventario usable** (útil
|
||||||
|
|
||||||
## Cómo participar
|
## Cómo participar
|
||||||
|
|
||||||
Tanemaki es un proyecto abierto. Se puede contribuir cultivando y probándolo en una red de semillas real, traduciéndolo, aportando conocimiento sobre variedades, o programando. El código y su documentación son públicos.
|
Tane es un proyecto abierto. Se puede contribuir cultivando y probándolo en una red de semillas real, traduciéndolo, aportando conocimiento sobre variedades, o programando. El código y su documentación son públicos.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
asks the user at runtime). -->
|
asks the user at runtime). -->
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
<application
|
<application
|
||||||
android:label="tane"
|
android:label="Tane"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
Tanemaki (種まき, "to sow seeds") is a local-first, decentralized app for
|
Tane (種, "seed"; from tanemaki 種まき, "to sow seeds") is a local-first, decentralized app for
|
||||||
keeping and sharing traditional seeds.
|
keeping and sharing traditional seeds.
|
||||||
|
|
||||||
Every traditional seed is a letter written by thousands of generations, passed
|
Every traditional seed is a letter written by thousands of generations, passed
|
||||||
from hand to hand. Tanemaki helps people and seed-saver collectives keep a
|
from hand to hand. Tane helps people and seed-saver collectives keep a
|
||||||
friendly inventory of their bank, decide what they offer, and share it locally
|
friendly inventory of their bank, decide what they offer, and share it locally
|
||||||
— without a central intermediary that could control, censor, or be fined for
|
— without a central intermediary that could control, censor, or be fined for
|
||||||
it.
|
it.
|
||||||
|
|
@ -22,6 +22,6 @@ SHARE, THE WAY IT'S ALWAYS BEEN DONE
|
||||||
• Mark what you have spare to give away, swap or sell.
|
• Mark what you have spare to give away, swap or sell.
|
||||||
• Print a catalog of what you share to take to a seed fair.
|
• Print a catalog of what you share to take to a seed fair.
|
||||||
|
|
||||||
Tanemaki is free software (AGPL-3.0). No ads, no commissions, no business model
|
Tane is free software (AGPL-3.0). No ads, no commissions, no business model
|
||||||
— it exists to support traditional varieties and push back against the seed
|
— it exists to support traditional varieties and push back against the seed
|
||||||
monopoly.
|
monopoly.
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Tanemaki
|
Tane
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
Tanemaki (種まき, "sembrar semillas") es una app local-first y descentralizada
|
Tane (種, "semilla"; de tanemaki 種まき, "sembrar semillas") es una app local-first y descentralizada
|
||||||
para guardar y compartir semillas tradicionales.
|
para guardar y compartir semillas tradicionales.
|
||||||
|
|
||||||
Cada semilla tradicional es una carta escrita por miles de generaciones, que
|
Cada semilla tradicional es una carta escrita por miles de generaciones, que
|
||||||
pasa de mano en mano. Tanemaki ayuda a personas y colectivos de guardianas de
|
pasa de mano en mano. Tane ayuda a personas y colectivos de guardianas de
|
||||||
semillas a llevar un inventario amable de su banco, decidir qué ofrecen y
|
semillas a llevar un inventario amable de su banco, decidir qué ofrecen y
|
||||||
compartirlo localmente, sin un intermediario central que pueda controlarlo,
|
compartirlo localmente, sin un intermediario central que pueda controlarlo,
|
||||||
censurarlo o ser multado por ello.
|
censurarlo o ser multado por ello.
|
||||||
|
|
@ -22,6 +22,6 @@ COMPARTIR, COMO SE HA HECHO SIEMPRE
|
||||||
• Marca lo que te sobra para regalar, intercambiar o vender.
|
• Marca lo que te sobra para regalar, intercambiar o vender.
|
||||||
• Imprime un catálogo de lo que compartes para llevar a una feria de semillas.
|
• Imprime un catálogo de lo que compartes para llevar a una feria de semillas.
|
||||||
|
|
||||||
Tanemaki es software libre (AGPL-3.0). Sin anuncios, sin comisiones, sin modelo
|
Tane es software libre (AGPL-3.0). Sin anuncios, sin comisiones, sin modelo
|
||||||
de negocio: existe para apoyar las variedades tradicionales y plantar cara al
|
de negocio: existe para apoyar las variedades tradicionales y plantar cara al
|
||||||
monopolio de las semillas.
|
monopolio de las semillas.
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Tanemaki
|
Tane
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ class InventoryJsonCodec {
|
||||||
throw const FormatException('Not a valid JSON file.');
|
throw const FormatException('Not a valid JSON file.');
|
||||||
}
|
}
|
||||||
if (root is! Map<String, dynamic>) {
|
if (root is! Map<String, dynamic>) {
|
||||||
throw const FormatException('Not a Tanemaki inventory file.');
|
throw const FormatException('Not a Tane inventory file.');
|
||||||
}
|
}
|
||||||
final version = root['formatVersion'];
|
final version = root['formatVersion'];
|
||||||
if (version is! int) {
|
if (version is! int) {
|
||||||
|
|
|
||||||
|
|
@ -38,16 +38,16 @@ class SeedLabelData extends Equatable {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encodes/decodes [SeedLabelData] as a compact, versioned `tanemaki://seed`
|
/// Encodes/decodes [SeedLabelData] as a compact, versioned `tane://seed`
|
||||||
/// URI — self-describing and parseable, so a future scan-to-import feature can
|
/// URI — self-describing and parseable, so a future scan-to-import feature can
|
||||||
/// read a label a keeper printed today. Unicode and RTL text are percent-encoded
|
/// read a label a keeper printed today. Unicode and RTL text are percent-encoded
|
||||||
/// by [Uri], so any QR reader round-trips them safely.
|
/// by [Uri], so any QR reader round-trips them safely.
|
||||||
///
|
///
|
||||||
/// Shape: `tanemaki://seed?v=<variety>&s=<scientific>&c=<common>&y=<year>&o=<origin>`
|
/// Shape: `tane://seed?v=<variety>&s=<scientific>&c=<common>&y=<year>&o=<origin>`
|
||||||
/// Absent fields are omitted, keeping the payload (and the QR) as small as the
|
/// Absent fields are omitted, keeping the payload (and the QR) as small as the
|
||||||
/// data allows.
|
/// data allows.
|
||||||
abstract final class SeedLabelCodec {
|
abstract final class SeedLabelCodec {
|
||||||
static const _scheme = 'tanemaki';
|
static const _scheme = 'tane';
|
||||||
static const _host = 'seed';
|
static const _host = 'seed';
|
||||||
|
|
||||||
static String encode(SeedLabelData data) {
|
static String encode(SeedLabelData data) {
|
||||||
|
|
@ -65,7 +65,7 @@ abstract final class SeedLabelCodec {
|
||||||
).toString();
|
).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a `tanemaki://seed` URI back to [SeedLabelData]. Returns null when
|
/// Parses a `tane://seed` URI back to [SeedLabelData]. Returns null when
|
||||||
/// [input] is not a well-formed seed label (wrong scheme/host, or no variety).
|
/// [input] is not a well-formed seed label (wrong scheme/host, or no variety).
|
||||||
static SeedLabelData? decode(String input) {
|
static SeedLabelData? decode(String input) {
|
||||||
final uri = Uri.tryParse(input.trim());
|
final uri = Uri.tryParse(input.trim());
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,10 @@
|
||||||
"nothing": "Nada anotao pa {month}."
|
"nothing": "Nada anotao pa {month}."
|
||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"title": "Tanemaki"
|
"title": "Tane"
|
||||||
},
|
},
|
||||||
"bootstrap": {
|
"bootstrap": {
|
||||||
"failed": "Tanemaki nun pudo aniciar",
|
"failed": "Tane nun pudo aniciar",
|
||||||
"retry": "Reintentar"
|
"retry": "Reintentar"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
"langAst": "Asturianu",
|
"langAst": "Asturianu",
|
||||||
"about": "Tocante a",
|
"about": "Tocante a",
|
||||||
"aboutText": "Inventariu llocal y cifráu pa simiente tradicional. AGPL-3.0.",
|
"aboutText": "Inventariu llocal y cifráu pa simiente tradicional. AGPL-3.0.",
|
||||||
"aboutOpen": "Tocante a Tanemaki"
|
"aboutOpen": "Tocante a Tane"
|
||||||
},
|
},
|
||||||
"backup": {
|
"backup": {
|
||||||
"title": "Copia de seguranza",
|
"title": "Copia de seguranza",
|
||||||
|
|
@ -114,24 +114,24 @@
|
||||||
"cancelled": "Encaboxáu",
|
"cancelled": "Encaboxáu",
|
||||||
"importDone": "Importáu: {added} nueves, {updated} anovaes",
|
"importDone": "Importáu: {added} nueves, {updated} anovaes",
|
||||||
"importCsvDone": "Amestaes {count} entraes",
|
"importCsvDone": "Amestaes {count} entraes",
|
||||||
"importFailed": "Esti ficheru nun se pudo lleer como una copia de Tanemaki",
|
"importFailed": "Esti ficheru nun se pudo lleer como una copia de Tane",
|
||||||
"failed": "Daqué salió mal",
|
"failed": "Daqué salió mal",
|
||||||
"recoveryTitle": "El to códigu de recuperación",
|
"recoveryTitle": "El to códigu de recuperación",
|
||||||
"recoverySubtitle": "Imprémelu y guárdalu bien: abre les tos copies n'otru preséu",
|
"recoverySubtitle": "Imprémelu y guárdalu bien: abre les tos copies n'otru preséu",
|
||||||
"recoveryIntro": "Esti códigu abre les tos copies guardaes y recupera'l to bancu en cualquier preséu. Guarda dos copies en papel en sitios seguros, como la to meyor simiente. Quien lu tenga pue lleer les tos copies, asina que nun lu compartas con naide.",
|
"recoveryIntro": "Esti códigu abre les tos copies guardaes y recupera'l to bancu en cualquier preséu. Guarda dos copies en papel en sitios seguros, como la to meyor simiente. Quien lu tenga pue lleer les tos copies, asina que nun lu compartas con naide.",
|
||||||
"recoveryCopy": "Copiar",
|
"recoveryCopy": "Copiar",
|
||||||
"recoverySave": "Guardar la fueya",
|
"recoverySave": "Guardar la fueya",
|
||||||
"recoverySheetTitle": "Tanemaki — la to fueya de recuperación",
|
"recoverySheetTitle": "Tane — la to fueya de recuperación",
|
||||||
"recoveryPromptTitle": "Escribi'l to códigu de recuperación",
|
"recoveryPromptTitle": "Escribi'l to códigu de recuperación",
|
||||||
"recoveryPromptBody": "Esta copia guardóse con otru códigu. Escribi'l códigu de la to fueya de recuperación p'abrilla.",
|
"recoveryPromptBody": "Esta copia guardóse con otru códigu. Escribi'l códigu de la to fueya de recuperación p'abrilla.",
|
||||||
"recoveryWrongCode": "Esi códigu nun abre esta copia"
|
"recoveryWrongCode": "Esi códigu nun abre esta copia"
|
||||||
},
|
},
|
||||||
"about": {
|
"about": {
|
||||||
"title": "Tocante a",
|
"title": "Tocante a",
|
||||||
"kanji": "種まき",
|
"kanji": "種",
|
||||||
"tagline": "Una app local-first y descentralizada pa remanar y compartir simiente y plantones tradicionales.",
|
"tagline": "Una app local-first y descentralizada pa remanar y compartir simiente y plantones tradicionales.",
|
||||||
"intro": "Tanemaki (種まき, «semar / esparder simiente» en xaponés; nome curtiu Tane, 種 «grana») ayuda a persones y coleutivos a llevar un inventariu amable del so bancu de simiente, decidir qué ufierten y compartilo llocalmente — ensin un intermediariu central que pueda controlalo, censuralo o ser multáu por ello. L'oxetivu ye a la vez práuticu y políticu: sofitar les variedaes tradicionales de simiente y plantar cara al monopoliu simienteru.",
|
"intro": "Tane (種, «grana» en xaponés) ayuda a persones y coleutivos a llevar un inventariu amable del so bancu de simiente, decidir qué ufierten y compartilo llocalmente — ensin un intermediariu central que pueda controlalo, censuralo o ser multáu por ello. El so nome vien de tanemaki (種まき), «semar / esparder simiente». L'oxetivu ye a la vez práuticu y políticu: sofitar les variedaes tradicionales de simiente y plantar cara al monopoliu simienteru.",
|
||||||
"heritage": "El nome honra les vieyes tradiciones xaponeses d'ayuda mutua alredor del arroz — yui (trabayu comunitariu compartíu) y tanomoshi (fondos de reciprocidá) — qu'inspiraron el papel Plantare, la «moneda comunitaria pal intercambiu de simiente» (BAH-Semilleru, 2009, CC-BY-SA). Tanemaki ye'l Plantare dixital.",
|
"heritage": "El nome honra les vieyes tradiciones xaponeses d'ayuda mutua alredor del arroz — yui (trabayu comunitariu compartíu) y tanomoshi (fondos de reciprocidá) — qu'inspiraron el papel Plantare, la «moneda comunitaria pal intercambiu de simiente» (BAH-Semilleru, 2009, CC-BY-SA). Tane ye'l Plantare dixital.",
|
||||||
"version": "Versión",
|
"version": "Versión",
|
||||||
"license": "Llicencia",
|
"license": "Llicencia",
|
||||||
"licenseValue": "AGPL-3.0",
|
"licenseValue": "AGPL-3.0",
|
||||||
|
|
@ -144,7 +144,7 @@
|
||||||
"skip": "Saltar",
|
"skip": "Saltar",
|
||||||
"next": "Siguiente",
|
"next": "Siguiente",
|
||||||
"start": "Entamar",
|
"start": "Entamar",
|
||||||
"menuEntry": "Cómo furrula Tanemaki",
|
"menuEntry": "Cómo furrula Tane",
|
||||||
"slides": {
|
"slides": {
|
||||||
"welcome": {
|
"welcome": {
|
||||||
"title": "La grana que te traxo hasta equí",
|
"title": "La grana que te traxo hasta equí",
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,10 @@
|
||||||
"nothing": "Nothing noted for {month}."
|
"nothing": "Nothing noted for {month}."
|
||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"title": "Tanemaki"
|
"title": "Tane"
|
||||||
},
|
},
|
||||||
"bootstrap": {
|
"bootstrap": {
|
||||||
"failed": "Tanemaki couldn't start",
|
"failed": "Tane couldn't start",
|
||||||
"retry": "Try again"
|
"retry": "Try again"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
|
@ -91,7 +91,7 @@
|
||||||
"langAst": "Asturianu",
|
"langAst": "Asturianu",
|
||||||
"about": "About",
|
"about": "About",
|
||||||
"aboutText": "Local-first, encrypted inventory for traditional seeds. AGPL-3.0.",
|
"aboutText": "Local-first, encrypted inventory for traditional seeds. AGPL-3.0.",
|
||||||
"aboutOpen": "About Tanemaki"
|
"aboutOpen": "About Tane"
|
||||||
},
|
},
|
||||||
"backup": {
|
"backup": {
|
||||||
"title": "Backup & restore",
|
"title": "Backup & restore",
|
||||||
|
|
@ -115,24 +115,24 @@
|
||||||
"cancelled": "Cancelled",
|
"cancelled": "Cancelled",
|
||||||
"importDone": "Imported: {added} new, {updated} updated",
|
"importDone": "Imported: {added} new, {updated} updated",
|
||||||
"importCsvDone": "Added {count} entries",
|
"importCsvDone": "Added {count} entries",
|
||||||
"importFailed": "This file could not be read as a Tanemaki copy",
|
"importFailed": "This file could not be read as a Tane copy",
|
||||||
"failed": "Something went wrong",
|
"failed": "Something went wrong",
|
||||||
"recoveryTitle": "Your recovery code",
|
"recoveryTitle": "Your recovery code",
|
||||||
"recoverySubtitle": "Print it and keep it safe — it opens your copies on a new device",
|
"recoverySubtitle": "Print it and keep it safe — it opens your copies on a new device",
|
||||||
"recoveryIntro": "This code opens your saved copies and brings your bank back on any device. Keep two paper copies in safe places, like your best seed. Anyone holding it can read your copies, so share it with no one.",
|
"recoveryIntro": "This code opens your saved copies and brings your bank back on any device. Keep two paper copies in safe places, like your best seed. Anyone holding it can read your copies, so share it with no one.",
|
||||||
"recoveryCopy": "Copy",
|
"recoveryCopy": "Copy",
|
||||||
"recoverySave": "Save the sheet",
|
"recoverySave": "Save the sheet",
|
||||||
"recoverySheetTitle": "Tanemaki — your recovery sheet",
|
"recoverySheetTitle": "Tane — your recovery sheet",
|
||||||
"recoveryPromptTitle": "Enter your recovery code",
|
"recoveryPromptTitle": "Enter your recovery code",
|
||||||
"recoveryPromptBody": "This copy was saved with another code. Type the code from your recovery sheet to open it.",
|
"recoveryPromptBody": "This copy was saved with another code. Type the code from your recovery sheet to open it.",
|
||||||
"recoveryWrongCode": "That code doesn't open this copy"
|
"recoveryWrongCode": "That code doesn't open this copy"
|
||||||
},
|
},
|
||||||
"about": {
|
"about": {
|
||||||
"title": "About",
|
"title": "About",
|
||||||
"kanji": "種まき",
|
"kanji": "種",
|
||||||
"tagline": "A local-first, decentralized app for managing and sharing traditional seeds and seedlings.",
|
"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.",
|
"intro": "Tane (種, \"seed\" in Japanese) 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. Its name comes from tanemaki (種まき), \"to sow / scatter seeds\". 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.",
|
"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). Tane is the digital Plantare.",
|
||||||
"version": "Version",
|
"version": "Version",
|
||||||
"license": "License",
|
"license": "License",
|
||||||
"licenseValue": "AGPL-3.0",
|
"licenseValue": "AGPL-3.0",
|
||||||
|
|
@ -145,7 +145,7 @@
|
||||||
"skip": "Skip",
|
"skip": "Skip",
|
||||||
"next": "Next",
|
"next": "Next",
|
||||||
"start": "Get started",
|
"start": "Get started",
|
||||||
"menuEntry": "How Tanemaki works",
|
"menuEntry": "How Tane works",
|
||||||
"slides": {
|
"slides": {
|
||||||
"welcome": {
|
"welcome": {
|
||||||
"title": "The seed that brought you here",
|
"title": "The seed that brought you here",
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,10 @@
|
||||||
"nothing": "Nada anotado para {month}."
|
"nothing": "Nada anotado para {month}."
|
||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"title": "Tanemaki"
|
"title": "Tane"
|
||||||
},
|
},
|
||||||
"bootstrap": {
|
"bootstrap": {
|
||||||
"failed": "Tanemaki no pudo arrancar",
|
"failed": "Tane no pudo arrancar",
|
||||||
"retry": "Reintentar"
|
"retry": "Reintentar"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
"langPt": "Português",
|
"langPt": "Português",
|
||||||
"about": "Acerca de",
|
"about": "Acerca de",
|
||||||
"aboutText": "Inventario local y cifrado para semillas tradicionales. AGPL-3.0.",
|
"aboutText": "Inventario local y cifrado para semillas tradicionales. AGPL-3.0.",
|
||||||
"aboutOpen": "Acerca de Tanemaki"
|
"aboutOpen": "Acerca de Tane"
|
||||||
},
|
},
|
||||||
"backup": {
|
"backup": {
|
||||||
"title": "Copia de seguridad",
|
"title": "Copia de seguridad",
|
||||||
|
|
@ -114,24 +114,24 @@
|
||||||
"cancelled": "Cancelado",
|
"cancelled": "Cancelado",
|
||||||
"importDone": "Importado: {added} nuevas, {updated} actualizadas",
|
"importDone": "Importado: {added} nuevas, {updated} actualizadas",
|
||||||
"importCsvDone": "Añadidas {count} entradas",
|
"importCsvDone": "Añadidas {count} entradas",
|
||||||
"importFailed": "Este fichero no se pudo leer como una copia de Tanemaki",
|
"importFailed": "Este fichero no se pudo leer como una copia de Tane",
|
||||||
"failed": "Algo ha salido mal",
|
"failed": "Algo ha salido mal",
|
||||||
"recoveryTitle": "Tu código de recuperación",
|
"recoveryTitle": "Tu código de recuperación",
|
||||||
"recoverySubtitle": "Imprímelo y guárdalo bien: abre tus copias en otro dispositivo",
|
"recoverySubtitle": "Imprímelo y guárdalo bien: abre tus copias en otro dispositivo",
|
||||||
"recoveryIntro": "Este código abre tus copias guardadas y recupera tu banco en cualquier dispositivo. Guarda dos copias en papel en sitios seguros, como tu mejor semilla. Quien lo tenga puede leer tus copias, así que no lo compartas con nadie.",
|
"recoveryIntro": "Este código abre tus copias guardadas y recupera tu banco en cualquier dispositivo. Guarda dos copias en papel en sitios seguros, como tu mejor semilla. Quien lo tenga puede leer tus copias, así que no lo compartas con nadie.",
|
||||||
"recoveryCopy": "Copiar",
|
"recoveryCopy": "Copiar",
|
||||||
"recoverySave": "Guardar la hoja",
|
"recoverySave": "Guardar la hoja",
|
||||||
"recoverySheetTitle": "Tanemaki — tu hoja de recuperación",
|
"recoverySheetTitle": "Tane — tu hoja de recuperación",
|
||||||
"recoveryPromptTitle": "Escribe tu código de recuperación",
|
"recoveryPromptTitle": "Escribe tu código de recuperación",
|
||||||
"recoveryPromptBody": "Esta copia se guardó con otro código. Escribe el código de tu hoja de recuperación para abrirla.",
|
"recoveryPromptBody": "Esta copia se guardó con otro código. Escribe el código de tu hoja de recuperación para abrirla.",
|
||||||
"recoveryWrongCode": "Ese código no abre esta copia"
|
"recoveryWrongCode": "Ese código no abre esta copia"
|
||||||
},
|
},
|
||||||
"about": {
|
"about": {
|
||||||
"title": "Acerca de",
|
"title": "Acerca de",
|
||||||
"kanji": "種まき",
|
"kanji": "種",
|
||||||
"tagline": "Una app local-first y descentralizada para gestionar y compartir semillas y plantones tradicionales.",
|
"tagline": "Una app local-first y descentralizada para gestionar y compartir semillas y plantones tradicionales.",
|
||||||
"intro": "Tanemaki (種まき, «sembrar / esparcir semillas» en japonés; nombre corto Tane, 種 «semilla») ayuda a personas y colectivos a llevar un inventario amable de su banco de semillas, decidir qué ofrecen y compartirlo localmente — sin un intermediario central que pueda controlarlo, censurarlo o ser multado por ello. El objetivo es a la vez práctico y político: apoyar las variedades tradicionales de semillas y plantar cara al monopolio semillero.",
|
"intro": "Tane (種, «semilla» en japonés) ayuda a personas y colectivos a llevar un inventario amable de su banco de semillas, decidir qué ofrecen y compartirlo localmente — sin un intermediario central que pueda controlarlo, censurarlo o ser multado por ello. Su nombre viene de tanemaki (種まき), «sembrar / esparcir semillas». El objetivo es a la vez práctico y político: apoyar las variedades tradicionales de semillas y plantar cara al monopolio semillero.",
|
||||||
"heritage": "El nombre honra las viejas tradiciones japonesas de ayuda mutua en torno al arroz — yui (trabajo comunitario compartido) y tanomoshi (fondos de reciprocidad) — que inspiraron el papel Plantare, la «moneda comunitaria para el intercambio de semillas» (BAH-Semillero, 2009, CC-BY-SA). Tanemaki es el Plantare digital.",
|
"heritage": "El nombre honra las viejas tradiciones japonesas de ayuda mutua en torno al arroz — yui (trabajo comunitario compartido) y tanomoshi (fondos de reciprocidad) — que inspiraron el papel Plantare, la «moneda comunitaria para el intercambio de semillas» (BAH-Semillero, 2009, CC-BY-SA). Tane es el Plantare digital.",
|
||||||
"version": "Versión",
|
"version": "Versión",
|
||||||
"license": "Licencia",
|
"license": "Licencia",
|
||||||
"licenseValue": "AGPL-3.0",
|
"licenseValue": "AGPL-3.0",
|
||||||
|
|
@ -144,7 +144,7 @@
|
||||||
"skip": "Saltar",
|
"skip": "Saltar",
|
||||||
"next": "Siguiente",
|
"next": "Siguiente",
|
||||||
"start": "Empezar",
|
"start": "Empezar",
|
||||||
"menuEntry": "Cómo funciona Tanemaki",
|
"menuEntry": "Cómo funciona Tane",
|
||||||
"slides": {
|
"slides": {
|
||||||
"welcome": {
|
"welcome": {
|
||||||
"title": "La semilla que te trajo hasta aquí",
|
"title": "La semilla que te trajo hasta aquí",
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,10 @@
|
||||||
"nothing": "Nada anotado para {month}."
|
"nothing": "Nada anotado para {month}."
|
||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"title": "Tanemaki"
|
"title": "Tane"
|
||||||
},
|
},
|
||||||
"bootstrap": {
|
"bootstrap": {
|
||||||
"failed": "O Tanemaki não conseguiu iniciar",
|
"failed": "O Tane não conseguiu iniciar",
|
||||||
"retry": "Tentar de novo"
|
"retry": "Tentar de novo"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
|
@ -91,7 +91,7 @@
|
||||||
"langAst": "Asturianu",
|
"langAst": "Asturianu",
|
||||||
"about": "Acerca de",
|
"about": "Acerca de",
|
||||||
"aboutText": "Inventário local e cifrado para sementes tradicionais. AGPL-3.0.",
|
"aboutText": "Inventário local e cifrado para sementes tradicionais. AGPL-3.0.",
|
||||||
"aboutOpen": "Acerca do Tanemaki"
|
"aboutOpen": "Acerca do Tane"
|
||||||
},
|
},
|
||||||
"backup": {
|
"backup": {
|
||||||
"title": "Cópia de segurança",
|
"title": "Cópia de segurança",
|
||||||
|
|
@ -115,24 +115,24 @@
|
||||||
"cancelled": "Cancelado",
|
"cancelled": "Cancelado",
|
||||||
"importDone": "Importado: {added} novas, {updated} atualizadas",
|
"importDone": "Importado: {added} novas, {updated} atualizadas",
|
||||||
"importCsvDone": "{count} entradas acrescentadas",
|
"importCsvDone": "{count} entradas acrescentadas",
|
||||||
"importFailed": "Este ficheiro não pôde ser lido como uma cópia do Tanemaki",
|
"importFailed": "Este ficheiro não pôde ser lido como uma cópia do Tane",
|
||||||
"failed": "Algo correu mal",
|
"failed": "Algo correu mal",
|
||||||
"recoveryTitle": "O teu código de recuperação",
|
"recoveryTitle": "O teu código de recuperação",
|
||||||
"recoverySubtitle": "Imprime-o e guarda-o bem: abre as tuas cópias noutro aparelho",
|
"recoverySubtitle": "Imprime-o e guarda-o bem: abre as tuas cópias noutro aparelho",
|
||||||
"recoveryIntro": "Este código abre as tuas cópias guardadas e recupera o teu banco em qualquer aparelho. Guarda duas cópias em papel em sítios seguros, como a tua melhor semente. Quem o tiver pode ler as tuas cópias, por isso não o partilhes com ninguém.",
|
"recoveryIntro": "Este código abre as tuas cópias guardadas e recupera o teu banco em qualquer aparelho. Guarda duas cópias em papel em sítios seguros, como a tua melhor semente. Quem o tiver pode ler as tuas cópias, por isso não o partilhes com ninguém.",
|
||||||
"recoveryCopy": "Copiar",
|
"recoveryCopy": "Copiar",
|
||||||
"recoverySave": "Guardar a folha",
|
"recoverySave": "Guardar a folha",
|
||||||
"recoverySheetTitle": "Tanemaki — a tua folha de recuperação",
|
"recoverySheetTitle": "Tane — a tua folha de recuperação",
|
||||||
"recoveryPromptTitle": "Escreve o teu código de recuperação",
|
"recoveryPromptTitle": "Escreve o teu código de recuperação",
|
||||||
"recoveryPromptBody": "Esta cópia foi guardada com outro código. Escreve o código da tua folha de recuperação para a abrir.",
|
"recoveryPromptBody": "Esta cópia foi guardada com outro código. Escreve o código da tua folha de recuperação para a abrir.",
|
||||||
"recoveryWrongCode": "Esse código não abre esta cópia"
|
"recoveryWrongCode": "Esse código não abre esta cópia"
|
||||||
},
|
},
|
||||||
"about": {
|
"about": {
|
||||||
"title": "Acerca de",
|
"title": "Acerca de",
|
||||||
"kanji": "種まき",
|
"kanji": "種",
|
||||||
"tagline": "Uma aplicação local e descentralizada para gerir e partilhar sementes e plântulas tradicionais.",
|
"tagline": "Uma aplicação local e descentralizada para gerir e partilhar sementes e plântulas tradicionais.",
|
||||||
"intro": "O Tanemaki (種まき, \"semear / espalhar sementes\" em japonês; nome curto Tane, 種 \"semente\") ajuda pessoas e coletivos a manter um inventário amigável do seu banco de sementes, decidir o que oferecem e partilhá-lo localmente — sem um intermediário central que possa controlar, censurar ou ser multado por isso. O objetivo é prático e político ao mesmo tempo: apoiar as variedades tradicionais e fazer frente ao monopólio das sementes.",
|
"intro": "O Tane (種, \"semente\" em japonês) ajuda pessoas e coletivos a manter um inventário amigável do seu banco de sementes, decidir o que oferecem e partilhá-lo localmente — sem um intermediário central que possa controlar, censurar ou ser multado por isso. O seu nome vem de tanemaki (種まき), \"semear / espalhar sementes\". O objetivo é prático e político ao mesmo tempo: apoiar as variedades tradicionais e fazer frente ao monopólio das sementes.",
|
||||||
"heritage": "O nome honra as antigas tradições japonesas de ajuda mútua à volta do arroz — yui (trabalho comunitário partilhado) e tanomoshi (fundos de reciprocidade) — que inspiraram o Plantare em papel, a \"moeda comunitária de troca de sementes\" (BAH-Semillero, 2009, CC-BY-SA). O Tanemaki é o Plantare digital.",
|
"heritage": "O nome honra as antigas tradições japonesas de ajuda mútua à volta do arroz — yui (trabalho comunitário partilhado) e tanomoshi (fundos de reciprocidade) — que inspiraram o Plantare em papel, a \"moeda comunitária de troca de sementes\" (BAH-Semillero, 2009, CC-BY-SA). O Tane é o Plantare digital.",
|
||||||
"version": "Versão",
|
"version": "Versão",
|
||||||
"license": "Licença",
|
"license": "Licença",
|
||||||
"licenseValue": "AGPL-3.0",
|
"licenseValue": "AGPL-3.0",
|
||||||
|
|
@ -145,7 +145,7 @@
|
||||||
"skip": "Saltar",
|
"skip": "Saltar",
|
||||||
"next": "Seguinte",
|
"next": "Seguinte",
|
||||||
"start": "Começar",
|
"start": "Começar",
|
||||||
"menuEntry": "Como funciona o Tanemaki",
|
"menuEntry": "Como funciona o Tane",
|
||||||
"slides": {
|
"slides": {
|
||||||
"welcome": {
|
"welcome": {
|
||||||
"title": "A semente que te trouxe até aqui",
|
"title": "A semente que te trouxe até aqui",
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
/// Locales: 4
|
/// Locales: 4
|
||||||
/// Strings: 2032 (508 per locale)
|
/// Strings: 2032 (508 per locale)
|
||||||
///
|
///
|
||||||
/// Built on 2026-07-12 at 00:47 UTC
|
/// Built on 2026-07-12 at 10:59 UTC
|
||||||
|
|
||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint, unused_import
|
// ignore_for_file: type=lint, unused_import
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ class _Translations$app$ast extends Translations$app$en {
|
||||||
final TranslationsAst _root; // ignore: unused_field
|
final TranslationsAst _root; // ignore: unused_field
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
@override String get title => 'Tanemaki';
|
@override String get title => 'Tane';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: bootstrap
|
// Path: bootstrap
|
||||||
|
|
@ -164,7 +164,7 @@ class _Translations$bootstrap$ast extends Translations$bootstrap$en {
|
||||||
final TranslationsAst _root; // ignore: unused_field
|
final TranslationsAst _root; // ignore: unused_field
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
@override String get failed => 'Tanemaki nun pudo aniciar';
|
@override String get failed => 'Tane nun pudo aniciar';
|
||||||
@override String get retry => 'Reintentar';
|
@override String get retry => 'Reintentar';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,7 +246,7 @@ class _Translations$settings$ast extends Translations$settings$en {
|
||||||
@override String get langAst => 'Asturianu';
|
@override String get langAst => 'Asturianu';
|
||||||
@override String get about => 'Tocante a';
|
@override String get about => 'Tocante a';
|
||||||
@override String get aboutText => 'Inventariu llocal y cifráu pa simiente tradicional. AGPL-3.0.';
|
@override String get aboutText => 'Inventariu llocal y cifráu pa simiente tradicional. AGPL-3.0.';
|
||||||
@override String get aboutOpen => 'Tocante a Tanemaki';
|
@override String get aboutOpen => 'Tocante a Tane';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: backup
|
// Path: backup
|
||||||
|
|
@ -277,14 +277,14 @@ class _Translations$backup$ast extends Translations$backup$en {
|
||||||
@override String get cancelled => 'Encaboxáu';
|
@override String get cancelled => 'Encaboxáu';
|
||||||
@override String importDone({required Object added, required Object updated}) => 'Importáu: ${added} nueves, ${updated} anovaes';
|
@override String importDone({required Object added, required Object updated}) => 'Importáu: ${added} nueves, ${updated} anovaes';
|
||||||
@override String importCsvDone({required Object count}) => 'Amestaes ${count} entraes';
|
@override String importCsvDone({required Object count}) => 'Amestaes ${count} entraes';
|
||||||
@override String get importFailed => 'Esti ficheru nun se pudo lleer como una copia de Tanemaki';
|
@override String get importFailed => 'Esti ficheru nun se pudo lleer como una copia de Tane';
|
||||||
@override String get failed => 'Daqué salió mal';
|
@override String get failed => 'Daqué salió mal';
|
||||||
@override String get recoveryTitle => 'El to códigu de recuperación';
|
@override String get recoveryTitle => 'El to códigu de recuperación';
|
||||||
@override String get recoverySubtitle => 'Imprémelu y guárdalu bien: abre les tos copies n\'otru preséu';
|
@override String get recoverySubtitle => 'Imprémelu y guárdalu bien: abre les tos copies n\'otru preséu';
|
||||||
@override String get recoveryIntro => 'Esti códigu abre les tos copies guardaes y recupera\'l to bancu en cualquier preséu. Guarda dos copies en papel en sitios seguros, como la to meyor simiente. Quien lu tenga pue lleer les tos copies, asina que nun lu compartas con naide.';
|
@override String get recoveryIntro => 'Esti códigu abre les tos copies guardaes y recupera\'l to bancu en cualquier preséu. Guarda dos copies en papel en sitios seguros, como la to meyor simiente. Quien lu tenga pue lleer les tos copies, asina que nun lu compartas con naide.';
|
||||||
@override String get recoveryCopy => 'Copiar';
|
@override String get recoveryCopy => 'Copiar';
|
||||||
@override String get recoverySave => 'Guardar la fueya';
|
@override String get recoverySave => 'Guardar la fueya';
|
||||||
@override String get recoverySheetTitle => 'Tanemaki — la to fueya de recuperación';
|
@override String get recoverySheetTitle => 'Tane — la to fueya de recuperación';
|
||||||
@override String get recoveryPromptTitle => 'Escribi\'l to códigu de recuperación';
|
@override String get recoveryPromptTitle => 'Escribi\'l to códigu de recuperación';
|
||||||
@override String get recoveryPromptBody => 'Esta copia guardóse con otru códigu. Escribi\'l códigu de la to fueya de recuperación p\'abrilla.';
|
@override String get recoveryPromptBody => 'Esta copia guardóse con otru códigu. Escribi\'l códigu de la to fueya de recuperación p\'abrilla.';
|
||||||
@override String get recoveryWrongCode => 'Esi códigu nun abre esta copia';
|
@override String get recoveryWrongCode => 'Esi códigu nun abre esta copia';
|
||||||
|
|
@ -298,10 +298,10 @@ class _Translations$about$ast extends Translations$about$en {
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
@override String get title => 'Tocante a';
|
@override String get title => 'Tocante a';
|
||||||
@override String get kanji => '種まき';
|
@override String get kanji => '種';
|
||||||
@override String get tagline => 'Una app local-first y descentralizada pa remanar y compartir simiente y plantones tradicionales.';
|
@override String get tagline => 'Una app local-first y descentralizada pa remanar y compartir simiente y plantones tradicionales.';
|
||||||
@override String get intro => 'Tanemaki (種まき, «semar / esparder simiente» en xaponés; nome curtiu Tane, 種 «grana») ayuda a persones y coleutivos a llevar un inventariu amable del so bancu de simiente, decidir qué ufierten y compartilo llocalmente — ensin un intermediariu central que pueda controlalo, censuralo o ser multáu por ello. L\'oxetivu ye a la vez práuticu y políticu: sofitar les variedaes tradicionales de simiente y plantar cara al monopoliu simienteru.';
|
@override String get intro => 'Tane (種, «grana» en xaponés) ayuda a persones y coleutivos a llevar un inventariu amable del so bancu de simiente, decidir qué ufierten y compartilo llocalmente — ensin un intermediariu central que pueda controlalo, censuralo o ser multáu por ello. El so nome vien de tanemaki (種まき), «semar / esparder simiente». L\'oxetivu ye a la vez práuticu y políticu: sofitar les variedaes tradicionales de simiente y plantar cara al monopoliu simienteru.';
|
||||||
@override String get heritage => 'El nome honra les vieyes tradiciones xaponeses d\'ayuda mutua alredor del arroz — yui (trabayu comunitariu compartíu) y tanomoshi (fondos de reciprocidá) — qu\'inspiraron el papel Plantare, la «moneda comunitaria pal intercambiu de simiente» (BAH-Semilleru, 2009, CC-BY-SA). Tanemaki ye\'l Plantare dixital.';
|
@override String get heritage => 'El nome honra les vieyes tradiciones xaponeses d\'ayuda mutua alredor del arroz — yui (trabayu comunitariu compartíu) y tanomoshi (fondos de reciprocidá) — qu\'inspiraron el papel Plantare, la «moneda comunitaria pal intercambiu de simiente» (BAH-Semilleru, 2009, CC-BY-SA). Tane ye\'l Plantare dixital.';
|
||||||
@override String get version => 'Versión';
|
@override String get version => 'Versión';
|
||||||
@override String get license => 'Llicencia';
|
@override String get license => 'Llicencia';
|
||||||
@override String get licenseValue => 'AGPL-3.0';
|
@override String get licenseValue => 'AGPL-3.0';
|
||||||
|
|
@ -321,7 +321,7 @@ class _Translations$intro$ast extends Translations$intro$en {
|
||||||
@override String get skip => 'Saltar';
|
@override String get skip => 'Saltar';
|
||||||
@override String get next => 'Siguiente';
|
@override String get next => 'Siguiente';
|
||||||
@override String get start => 'Entamar';
|
@override String get start => 'Entamar';
|
||||||
@override String get menuEntry => 'Cómo furrula Tanemaki';
|
@override String get menuEntry => 'Cómo furrula Tane';
|
||||||
@override late final _Translations$intro$slides$ast slides = _Translations$intro$slides$ast._(_root);
|
@override late final _Translations$intro$slides$ast slides = _Translations$intro$slides$ast._(_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1342,8 +1342,8 @@ extension on TranslationsAst {
|
||||||
'calendar.filterChip' => 'Esti mes',
|
'calendar.filterChip' => 'Esti mes',
|
||||||
'calendar.selfNote' => 'Lo qu\'anotasti nes tos variedaes.',
|
'calendar.selfNote' => 'Lo qu\'anotasti nes tos variedaes.',
|
||||||
'calendar.nothing' => ({required Object month}) => 'Nada anotao pa ${month}.',
|
'calendar.nothing' => ({required Object month}) => 'Nada anotao pa ${month}.',
|
||||||
'app.title' => 'Tanemaki',
|
'app.title' => 'Tane',
|
||||||
'bootstrap.failed' => 'Tanemaki nun pudo aniciar',
|
'bootstrap.failed' => 'Tane nun pudo aniciar',
|
||||||
'bootstrap.retry' => 'Reintentar',
|
'bootstrap.retry' => 'Reintentar',
|
||||||
'common.save' => 'Guardar',
|
'common.save' => 'Guardar',
|
||||||
'common.cancel' => 'Encaboxar',
|
'common.cancel' => 'Encaboxar',
|
||||||
|
|
@ -1380,7 +1380,7 @@ extension on TranslationsAst {
|
||||||
'settings.langAst' => 'Asturianu',
|
'settings.langAst' => 'Asturianu',
|
||||||
'settings.about' => 'Tocante a',
|
'settings.about' => 'Tocante a',
|
||||||
'settings.aboutText' => 'Inventariu llocal y cifráu pa simiente tradicional. AGPL-3.0.',
|
'settings.aboutText' => 'Inventariu llocal y cifráu pa simiente tradicional. AGPL-3.0.',
|
||||||
'settings.aboutOpen' => 'Tocante a Tanemaki',
|
'settings.aboutOpen' => 'Tocante a Tane',
|
||||||
'backup.title' => 'Copia de seguranza',
|
'backup.title' => 'Copia de seguranza',
|
||||||
'backup.autoBackupTitle' => 'Copies automátiques',
|
'backup.autoBackupTitle' => 'Copies automátiques',
|
||||||
'backup.autoBackupLast' => ({required Object date}) => 'Cabera copia guardada\'l ${date}',
|
'backup.autoBackupLast' => ({required Object date}) => 'Cabera copia guardada\'l ${date}',
|
||||||
|
|
@ -1402,22 +1402,22 @@ extension on TranslationsAst {
|
||||||
'backup.cancelled' => 'Encaboxáu',
|
'backup.cancelled' => 'Encaboxáu',
|
||||||
'backup.importDone' => ({required Object added, required Object updated}) => 'Importáu: ${added} nueves, ${updated} anovaes',
|
'backup.importDone' => ({required Object added, required Object updated}) => 'Importáu: ${added} nueves, ${updated} anovaes',
|
||||||
'backup.importCsvDone' => ({required Object count}) => 'Amestaes ${count} entraes',
|
'backup.importCsvDone' => ({required Object count}) => 'Amestaes ${count} entraes',
|
||||||
'backup.importFailed' => 'Esti ficheru nun se pudo lleer como una copia de Tanemaki',
|
'backup.importFailed' => 'Esti ficheru nun se pudo lleer como una copia de Tane',
|
||||||
'backup.failed' => 'Daqué salió mal',
|
'backup.failed' => 'Daqué salió mal',
|
||||||
'backup.recoveryTitle' => 'El to códigu de recuperación',
|
'backup.recoveryTitle' => 'El to códigu de recuperación',
|
||||||
'backup.recoverySubtitle' => 'Imprémelu y guárdalu bien: abre les tos copies n\'otru preséu',
|
'backup.recoverySubtitle' => 'Imprémelu y guárdalu bien: abre les tos copies n\'otru preséu',
|
||||||
'backup.recoveryIntro' => 'Esti códigu abre les tos copies guardaes y recupera\'l to bancu en cualquier preséu. Guarda dos copies en papel en sitios seguros, como la to meyor simiente. Quien lu tenga pue lleer les tos copies, asina que nun lu compartas con naide.',
|
'backup.recoveryIntro' => 'Esti códigu abre les tos copies guardaes y recupera\'l to bancu en cualquier preséu. Guarda dos copies en papel en sitios seguros, como la to meyor simiente. Quien lu tenga pue lleer les tos copies, asina que nun lu compartas con naide.',
|
||||||
'backup.recoveryCopy' => 'Copiar',
|
'backup.recoveryCopy' => 'Copiar',
|
||||||
'backup.recoverySave' => 'Guardar la fueya',
|
'backup.recoverySave' => 'Guardar la fueya',
|
||||||
'backup.recoverySheetTitle' => 'Tanemaki — la to fueya de recuperación',
|
'backup.recoverySheetTitle' => 'Tane — la to fueya de recuperación',
|
||||||
'backup.recoveryPromptTitle' => 'Escribi\'l to códigu de recuperación',
|
'backup.recoveryPromptTitle' => 'Escribi\'l to códigu de recuperación',
|
||||||
'backup.recoveryPromptBody' => 'Esta copia guardóse con otru códigu. Escribi\'l códigu de la to fueya de recuperación p\'abrilla.',
|
'backup.recoveryPromptBody' => 'Esta copia guardóse con otru códigu. Escribi\'l códigu de la to fueya de recuperación p\'abrilla.',
|
||||||
'backup.recoveryWrongCode' => 'Esi códigu nun abre esta copia',
|
'backup.recoveryWrongCode' => 'Esi códigu nun abre esta copia',
|
||||||
'about.title' => 'Tocante a',
|
'about.title' => 'Tocante a',
|
||||||
'about.kanji' => '種まき',
|
'about.kanji' => '種',
|
||||||
'about.tagline' => 'Una app local-first y descentralizada pa remanar y compartir simiente y plantones tradicionales.',
|
'about.tagline' => 'Una app local-first y descentralizada pa remanar y compartir simiente y plantones tradicionales.',
|
||||||
'about.intro' => 'Tanemaki (種まき, «semar / esparder simiente» en xaponés; nome curtiu Tane, 種 «grana») ayuda a persones y coleutivos a llevar un inventariu amable del so bancu de simiente, decidir qué ufierten y compartilo llocalmente — ensin un intermediariu central que pueda controlalo, censuralo o ser multáu por ello. L\'oxetivu ye a la vez práuticu y políticu: sofitar les variedaes tradicionales de simiente y plantar cara al monopoliu simienteru.',
|
'about.intro' => 'Tane (種, «grana» en xaponés) ayuda a persones y coleutivos a llevar un inventariu amable del so bancu de simiente, decidir qué ufierten y compartilo llocalmente — ensin un intermediariu central que pueda controlalo, censuralo o ser multáu por ello. El so nome vien de tanemaki (種まき), «semar / esparder simiente». L\'oxetivu ye a la vez práuticu y políticu: sofitar les variedaes tradicionales de simiente y plantar cara al monopoliu simienteru.',
|
||||||
'about.heritage' => 'El nome honra les vieyes tradiciones xaponeses d\'ayuda mutua alredor del arroz — yui (trabayu comunitariu compartíu) y tanomoshi (fondos de reciprocidá) — qu\'inspiraron el papel Plantare, la «moneda comunitaria pal intercambiu de simiente» (BAH-Semilleru, 2009, CC-BY-SA). Tanemaki ye\'l Plantare dixital.',
|
'about.heritage' => 'El nome honra les vieyes tradiciones xaponeses d\'ayuda mutua alredor del arroz — yui (trabayu comunitariu compartíu) y tanomoshi (fondos de reciprocidá) — qu\'inspiraron el papel Plantare, la «moneda comunitaria pal intercambiu de simiente» (BAH-Semilleru, 2009, CC-BY-SA). Tane ye\'l Plantare dixital.',
|
||||||
'about.version' => 'Versión',
|
'about.version' => 'Versión',
|
||||||
'about.license' => 'Llicencia',
|
'about.license' => 'Llicencia',
|
||||||
'about.licenseValue' => 'AGPL-3.0',
|
'about.licenseValue' => 'AGPL-3.0',
|
||||||
|
|
@ -1428,7 +1428,7 @@ extension on TranslationsAst {
|
||||||
'intro.skip' => 'Saltar',
|
'intro.skip' => 'Saltar',
|
||||||
'intro.next' => 'Siguiente',
|
'intro.next' => 'Siguiente',
|
||||||
'intro.start' => 'Entamar',
|
'intro.start' => 'Entamar',
|
||||||
'intro.menuEntry' => 'Cómo furrula Tanemaki',
|
'intro.menuEntry' => 'Cómo furrula Tane',
|
||||||
'intro.slides.welcome.title' => 'La grana que te traxo hasta equí',
|
'intro.slides.welcome.title' => 'La grana que te traxo hasta equí',
|
||||||
'intro.slides.welcome.body' => 'Cada simiente tradicional ye una carta escrita por miles de xeneraciones, que pasó de mano en mano. Somos lo que somos gracies a esi intercambiu.',
|
'intro.slides.welcome.body' => 'Cada simiente tradicional ye una carta escrita por miles de xeneraciones, que pasó de mano en mano. Somos lo que somos gracies a esi intercambiu.',
|
||||||
'intro.slides.inventory.title' => 'El to bancu de simiente, nel bolsu',
|
'intro.slides.inventory.title' => 'El to bancu de simiente, nel bolsu',
|
||||||
|
|
|
||||||
|
|
@ -224,8 +224,8 @@ class Translations$app$en {
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
|
|
||||||
/// en: 'Tanemaki'
|
/// en: 'Tane'
|
||||||
String get title => 'Tanemaki';
|
String get title => 'Tane';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: bootstrap
|
// Path: bootstrap
|
||||||
|
|
@ -236,8 +236,8 @@ class Translations$bootstrap$en {
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
|
|
||||||
/// en: 'Tanemaki couldn't start'
|
/// en: 'Tane couldn't start'
|
||||||
String get failed => 'Tanemaki couldn\'t start';
|
String get failed => 'Tane couldn\'t start';
|
||||||
|
|
||||||
/// en: 'Try again'
|
/// en: 'Try again'
|
||||||
String get retry => 'Try again';
|
String get retry => 'Try again';
|
||||||
|
|
@ -395,8 +395,8 @@ class Translations$settings$en {
|
||||||
/// en: 'Local-first, encrypted inventory for traditional seeds. AGPL-3.0.'
|
/// en: 'Local-first, encrypted inventory for traditional seeds. AGPL-3.0.'
|
||||||
String get aboutText => 'Local-first, encrypted inventory for traditional seeds. AGPL-3.0.';
|
String get aboutText => 'Local-first, encrypted inventory for traditional seeds. AGPL-3.0.';
|
||||||
|
|
||||||
/// en: 'About Tanemaki'
|
/// en: 'About Tane'
|
||||||
String get aboutOpen => 'About Tanemaki';
|
String get aboutOpen => 'About Tane';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: backup
|
// Path: backup
|
||||||
|
|
@ -470,8 +470,8 @@ class Translations$backup$en {
|
||||||
/// en: 'Added {count} entries'
|
/// en: 'Added {count} entries'
|
||||||
String importCsvDone({required Object count}) => 'Added ${count} entries';
|
String importCsvDone({required Object count}) => 'Added ${count} entries';
|
||||||
|
|
||||||
/// en: 'This file could not be read as a Tanemaki copy'
|
/// en: 'This file could not be read as a Tane copy'
|
||||||
String get importFailed => 'This file could not be read as a Tanemaki copy';
|
String get importFailed => 'This file could not be read as a Tane copy';
|
||||||
|
|
||||||
/// en: 'Something went wrong'
|
/// en: 'Something went wrong'
|
||||||
String get failed => 'Something went wrong';
|
String get failed => 'Something went wrong';
|
||||||
|
|
@ -491,8 +491,8 @@ class Translations$backup$en {
|
||||||
/// en: 'Save the sheet'
|
/// en: 'Save the sheet'
|
||||||
String get recoverySave => 'Save the sheet';
|
String get recoverySave => 'Save the sheet';
|
||||||
|
|
||||||
/// en: 'Tanemaki — your recovery sheet'
|
/// en: 'Tane — your recovery sheet'
|
||||||
String get recoverySheetTitle => 'Tanemaki — your recovery sheet';
|
String get recoverySheetTitle => 'Tane — your recovery sheet';
|
||||||
|
|
||||||
/// en: 'Enter your recovery code'
|
/// en: 'Enter your recovery code'
|
||||||
String get recoveryPromptTitle => 'Enter your recovery code';
|
String get recoveryPromptTitle => 'Enter your recovery code';
|
||||||
|
|
@ -515,17 +515,17 @@ class Translations$about$en {
|
||||||
/// en: 'About'
|
/// en: 'About'
|
||||||
String get title => 'About';
|
String get title => 'About';
|
||||||
|
|
||||||
/// en: '種まき'
|
/// en: '種'
|
||||||
String get kanji => '種まき';
|
String get kanji => '種';
|
||||||
|
|
||||||
/// en: 'A local-first, decentralized app for managing and sharing traditional seeds and seedlings.'
|
/// en: 'A local-first, decentralized app for managing and sharing traditional seeds and seedlings.'
|
||||||
String get tagline => 'A local-first, decentralized app for managing and sharing traditional seeds and seedlings.';
|
String get tagline => 'A local-first, decentralized app for managing and sharing traditional seeds and seedlings.';
|
||||||
|
|
||||||
/// en: '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.'
|
/// en: 'Tane (種, "seed" in Japanese) 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. Its name comes from tanemaki (種まき), "to sow / scatter seeds". The goal is both practical and political: to support traditional seed varieties and push back against the seed monopoly.'
|
||||||
String get 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.';
|
String get intro => 'Tane (種, "seed" in Japanese) 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. Its name comes from tanemaki (種まき), "to sow / scatter seeds". The goal is both practical and political: to support traditional seed varieties and push back against the seed monopoly.';
|
||||||
|
|
||||||
/// en: '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.'
|
/// en: '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). Tane is the digital Plantare.'
|
||||||
String get 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.';
|
String get 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). Tane is the digital Plantare.';
|
||||||
|
|
||||||
/// en: 'Version'
|
/// en: 'Version'
|
||||||
String get version => 'Version';
|
String get version => 'Version';
|
||||||
|
|
@ -566,8 +566,8 @@ class Translations$intro$en {
|
||||||
/// en: 'Get started'
|
/// en: 'Get started'
|
||||||
String get start => 'Get started';
|
String get start => 'Get started';
|
||||||
|
|
||||||
/// en: 'How Tanemaki works'
|
/// en: 'How Tane works'
|
||||||
String get menuEntry => 'How Tanemaki works';
|
String get menuEntry => 'How Tane works';
|
||||||
|
|
||||||
late final Translations$intro$slides$en slides = Translations$intro$slides$en.internal(_root);
|
late final Translations$intro$slides$en slides = Translations$intro$slides$en.internal(_root);
|
||||||
}
|
}
|
||||||
|
|
@ -2345,8 +2345,8 @@ extension on Translations {
|
||||||
'calendar.filterChip' => 'This month',
|
'calendar.filterChip' => 'This month',
|
||||||
'calendar.selfNote' => 'What you\'ve noted in your varieties.',
|
'calendar.selfNote' => 'What you\'ve noted in your varieties.',
|
||||||
'calendar.nothing' => ({required Object month}) => 'Nothing noted for ${month}.',
|
'calendar.nothing' => ({required Object month}) => 'Nothing noted for ${month}.',
|
||||||
'app.title' => 'Tanemaki',
|
'app.title' => 'Tane',
|
||||||
'bootstrap.failed' => 'Tanemaki couldn\'t start',
|
'bootstrap.failed' => 'Tane couldn\'t start',
|
||||||
'bootstrap.retry' => 'Try again',
|
'bootstrap.retry' => 'Try again',
|
||||||
'common.save' => 'Save',
|
'common.save' => 'Save',
|
||||||
'common.cancel' => 'Cancel',
|
'common.cancel' => 'Cancel',
|
||||||
|
|
@ -2384,7 +2384,7 @@ extension on Translations {
|
||||||
'settings.langAst' => 'Asturianu',
|
'settings.langAst' => 'Asturianu',
|
||||||
'settings.about' => 'About',
|
'settings.about' => 'About',
|
||||||
'settings.aboutText' => 'Local-first, encrypted inventory for traditional seeds. AGPL-3.0.',
|
'settings.aboutText' => 'Local-first, encrypted inventory for traditional seeds. AGPL-3.0.',
|
||||||
'settings.aboutOpen' => 'About Tanemaki',
|
'settings.aboutOpen' => 'About Tane',
|
||||||
'backup.title' => 'Backup & restore',
|
'backup.title' => 'Backup & restore',
|
||||||
'backup.autoBackupTitle' => 'Automatic backups',
|
'backup.autoBackupTitle' => 'Automatic backups',
|
||||||
'backup.autoBackupLast' => ({required Object date}) => 'Last copy saved ${date}',
|
'backup.autoBackupLast' => ({required Object date}) => 'Last copy saved ${date}',
|
||||||
|
|
@ -2406,22 +2406,22 @@ extension on Translations {
|
||||||
'backup.cancelled' => 'Cancelled',
|
'backup.cancelled' => 'Cancelled',
|
||||||
'backup.importDone' => ({required Object added, required Object updated}) => 'Imported: ${added} new, ${updated} updated',
|
'backup.importDone' => ({required Object added, required Object updated}) => 'Imported: ${added} new, ${updated} updated',
|
||||||
'backup.importCsvDone' => ({required Object count}) => 'Added ${count} entries',
|
'backup.importCsvDone' => ({required Object count}) => 'Added ${count} entries',
|
||||||
'backup.importFailed' => 'This file could not be read as a Tanemaki copy',
|
'backup.importFailed' => 'This file could not be read as a Tane copy',
|
||||||
'backup.failed' => 'Something went wrong',
|
'backup.failed' => 'Something went wrong',
|
||||||
'backup.recoveryTitle' => 'Your recovery code',
|
'backup.recoveryTitle' => 'Your recovery code',
|
||||||
'backup.recoverySubtitle' => 'Print it and keep it safe — it opens your copies on a new device',
|
'backup.recoverySubtitle' => 'Print it and keep it safe — it opens your copies on a new device',
|
||||||
'backup.recoveryIntro' => 'This code opens your saved copies and brings your bank back on any device. Keep two paper copies in safe places, like your best seed. Anyone holding it can read your copies, so share it with no one.',
|
'backup.recoveryIntro' => 'This code opens your saved copies and brings your bank back on any device. Keep two paper copies in safe places, like your best seed. Anyone holding it can read your copies, so share it with no one.',
|
||||||
'backup.recoveryCopy' => 'Copy',
|
'backup.recoveryCopy' => 'Copy',
|
||||||
'backup.recoverySave' => 'Save the sheet',
|
'backup.recoverySave' => 'Save the sheet',
|
||||||
'backup.recoverySheetTitle' => 'Tanemaki — your recovery sheet',
|
'backup.recoverySheetTitle' => 'Tane — your recovery sheet',
|
||||||
'backup.recoveryPromptTitle' => 'Enter your recovery code',
|
'backup.recoveryPromptTitle' => 'Enter your recovery code',
|
||||||
'backup.recoveryPromptBody' => 'This copy was saved with another code. Type the code from your recovery sheet to open it.',
|
'backup.recoveryPromptBody' => 'This copy was saved with another code. Type the code from your recovery sheet to open it.',
|
||||||
'backup.recoveryWrongCode' => 'That code doesn\'t open this copy',
|
'backup.recoveryWrongCode' => 'That code doesn\'t open this copy',
|
||||||
'about.title' => 'About',
|
'about.title' => 'About',
|
||||||
'about.kanji' => '種まき',
|
'about.kanji' => '種',
|
||||||
'about.tagline' => 'A local-first, decentralized app for managing and sharing traditional seeds and seedlings.',
|
'about.tagline' => 'A local-first, decentralized app for managing and sharing traditional seeds and seedlings.',
|
||||||
'about.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.',
|
'about.intro' => 'Tane (種, "seed" in Japanese) 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. Its name comes from tanemaki (種まき), "to sow / scatter seeds". The goal is both practical and political: to support traditional seed varieties and push back against the seed monopoly.',
|
||||||
'about.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.',
|
'about.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). Tane is the digital Plantare.',
|
||||||
'about.version' => 'Version',
|
'about.version' => 'Version',
|
||||||
'about.license' => 'License',
|
'about.license' => 'License',
|
||||||
'about.licenseValue' => 'AGPL-3.0',
|
'about.licenseValue' => 'AGPL-3.0',
|
||||||
|
|
@ -2432,7 +2432,7 @@ extension on Translations {
|
||||||
'intro.skip' => 'Skip',
|
'intro.skip' => 'Skip',
|
||||||
'intro.next' => 'Next',
|
'intro.next' => 'Next',
|
||||||
'intro.start' => 'Get started',
|
'intro.start' => 'Get started',
|
||||||
'intro.menuEntry' => 'How Tanemaki works',
|
'intro.menuEntry' => 'How Tane works',
|
||||||
'intro.slides.welcome.title' => 'The seed that brought you here',
|
'intro.slides.welcome.title' => 'The seed that brought you here',
|
||||||
'intro.slides.welcome.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.',
|
'intro.slides.welcome.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.',
|
||||||
'intro.slides.inventory.title' => 'Your seed bank, in your pocket',
|
'intro.slides.inventory.title' => 'Your seed bank, in your pocket',
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ class _Translations$app$es extends Translations$app$en {
|
||||||
final TranslationsEs _root; // ignore: unused_field
|
final TranslationsEs _root; // ignore: unused_field
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
@override String get title => 'Tanemaki';
|
@override String get title => 'Tane';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: bootstrap
|
// Path: bootstrap
|
||||||
|
|
@ -164,7 +164,7 @@ class _Translations$bootstrap$es extends Translations$bootstrap$en {
|
||||||
final TranslationsEs _root; // ignore: unused_field
|
final TranslationsEs _root; // ignore: unused_field
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
@override String get failed => 'Tanemaki no pudo arrancar';
|
@override String get failed => 'Tane no pudo arrancar';
|
||||||
@override String get retry => 'Reintentar';
|
@override String get retry => 'Reintentar';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,7 +246,7 @@ class _Translations$settings$es extends Translations$settings$en {
|
||||||
@override String get langPt => 'Português';
|
@override String get langPt => 'Português';
|
||||||
@override String get about => 'Acerca de';
|
@override String get about => 'Acerca de';
|
||||||
@override String get aboutText => 'Inventario local y cifrado para semillas tradicionales. AGPL-3.0.';
|
@override String get aboutText => 'Inventario local y cifrado para semillas tradicionales. AGPL-3.0.';
|
||||||
@override String get aboutOpen => 'Acerca de Tanemaki';
|
@override String get aboutOpen => 'Acerca de Tane';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: backup
|
// Path: backup
|
||||||
|
|
@ -277,14 +277,14 @@ class _Translations$backup$es extends Translations$backup$en {
|
||||||
@override String get cancelled => 'Cancelado';
|
@override String get cancelled => 'Cancelado';
|
||||||
@override String importDone({required Object added, required Object updated}) => 'Importado: ${added} nuevas, ${updated} actualizadas';
|
@override String importDone({required Object added, required Object updated}) => 'Importado: ${added} nuevas, ${updated} actualizadas';
|
||||||
@override String importCsvDone({required Object count}) => 'Añadidas ${count} entradas';
|
@override String importCsvDone({required Object count}) => 'Añadidas ${count} entradas';
|
||||||
@override String get importFailed => 'Este fichero no se pudo leer como una copia de Tanemaki';
|
@override String get importFailed => 'Este fichero no se pudo leer como una copia de Tane';
|
||||||
@override String get failed => 'Algo ha salido mal';
|
@override String get failed => 'Algo ha salido mal';
|
||||||
@override String get recoveryTitle => 'Tu código de recuperación';
|
@override String get recoveryTitle => 'Tu código de recuperación';
|
||||||
@override String get recoverySubtitle => 'Imprímelo y guárdalo bien: abre tus copias en otro dispositivo';
|
@override String get recoverySubtitle => 'Imprímelo y guárdalo bien: abre tus copias en otro dispositivo';
|
||||||
@override String get recoveryIntro => 'Este código abre tus copias guardadas y recupera tu banco en cualquier dispositivo. Guarda dos copias en papel en sitios seguros, como tu mejor semilla. Quien lo tenga puede leer tus copias, así que no lo compartas con nadie.';
|
@override String get recoveryIntro => 'Este código abre tus copias guardadas y recupera tu banco en cualquier dispositivo. Guarda dos copias en papel en sitios seguros, como tu mejor semilla. Quien lo tenga puede leer tus copias, así que no lo compartas con nadie.';
|
||||||
@override String get recoveryCopy => 'Copiar';
|
@override String get recoveryCopy => 'Copiar';
|
||||||
@override String get recoverySave => 'Guardar la hoja';
|
@override String get recoverySave => 'Guardar la hoja';
|
||||||
@override String get recoverySheetTitle => 'Tanemaki — tu hoja de recuperación';
|
@override String get recoverySheetTitle => 'Tane — tu hoja de recuperación';
|
||||||
@override String get recoveryPromptTitle => 'Escribe tu código de recuperación';
|
@override String get recoveryPromptTitle => 'Escribe tu código de recuperación';
|
||||||
@override String get recoveryPromptBody => 'Esta copia se guardó con otro código. Escribe el código de tu hoja de recuperación para abrirla.';
|
@override String get recoveryPromptBody => 'Esta copia se guardó con otro código. Escribe el código de tu hoja de recuperación para abrirla.';
|
||||||
@override String get recoveryWrongCode => 'Ese código no abre esta copia';
|
@override String get recoveryWrongCode => 'Ese código no abre esta copia';
|
||||||
|
|
@ -298,10 +298,10 @@ class _Translations$about$es extends Translations$about$en {
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
@override String get title => 'Acerca de';
|
@override String get title => 'Acerca de';
|
||||||
@override String get kanji => '種まき';
|
@override String get kanji => '種';
|
||||||
@override String get tagline => 'Una app local-first y descentralizada para gestionar y compartir semillas y plantones tradicionales.';
|
@override String get tagline => 'Una app local-first y descentralizada para gestionar y compartir semillas y plantones tradicionales.';
|
||||||
@override String get intro => 'Tanemaki (種まき, «sembrar / esparcir semillas» en japonés; nombre corto Tane, 種 «semilla») ayuda a personas y colectivos a llevar un inventario amable de su banco de semillas, decidir qué ofrecen y compartirlo localmente — sin un intermediario central que pueda controlarlo, censurarlo o ser multado por ello. El objetivo es a la vez práctico y político: apoyar las variedades tradicionales de semillas y plantar cara al monopolio semillero.';
|
@override String get intro => 'Tane (種, «semilla» en japonés) ayuda a personas y colectivos a llevar un inventario amable de su banco de semillas, decidir qué ofrecen y compartirlo localmente — sin un intermediario central que pueda controlarlo, censurarlo o ser multado por ello. Su nombre viene de tanemaki (種まき), «sembrar / esparcir semillas». El objetivo es a la vez práctico y político: apoyar las variedades tradicionales de semillas y plantar cara al monopolio semillero.';
|
||||||
@override String get heritage => 'El nombre honra las viejas tradiciones japonesas de ayuda mutua en torno al arroz — yui (trabajo comunitario compartido) y tanomoshi (fondos de reciprocidad) — que inspiraron el papel Plantare, la «moneda comunitaria para el intercambio de semillas» (BAH-Semillero, 2009, CC-BY-SA). Tanemaki es el Plantare digital.';
|
@override String get heritage => 'El nombre honra las viejas tradiciones japonesas de ayuda mutua en torno al arroz — yui (trabajo comunitario compartido) y tanomoshi (fondos de reciprocidad) — que inspiraron el papel Plantare, la «moneda comunitaria para el intercambio de semillas» (BAH-Semillero, 2009, CC-BY-SA). Tane es el Plantare digital.';
|
||||||
@override String get version => 'Versión';
|
@override String get version => 'Versión';
|
||||||
@override String get license => 'Licencia';
|
@override String get license => 'Licencia';
|
||||||
@override String get licenseValue => 'AGPL-3.0';
|
@override String get licenseValue => 'AGPL-3.0';
|
||||||
|
|
@ -321,7 +321,7 @@ class _Translations$intro$es extends Translations$intro$en {
|
||||||
@override String get skip => 'Saltar';
|
@override String get skip => 'Saltar';
|
||||||
@override String get next => 'Siguiente';
|
@override String get next => 'Siguiente';
|
||||||
@override String get start => 'Empezar';
|
@override String get start => 'Empezar';
|
||||||
@override String get menuEntry => 'Cómo funciona Tanemaki';
|
@override String get menuEntry => 'Cómo funciona Tane';
|
||||||
@override late final _Translations$intro$slides$es slides = _Translations$intro$slides$es._(_root);
|
@override late final _Translations$intro$slides$es slides = _Translations$intro$slides$es._(_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1344,8 +1344,8 @@ extension on TranslationsEs {
|
||||||
'calendar.filterChip' => 'Este mes',
|
'calendar.filterChip' => 'Este mes',
|
||||||
'calendar.selfNote' => 'Lo que has anotado en tus variedades.',
|
'calendar.selfNote' => 'Lo que has anotado en tus variedades.',
|
||||||
'calendar.nothing' => ({required Object month}) => 'Nada anotado para ${month}.',
|
'calendar.nothing' => ({required Object month}) => 'Nada anotado para ${month}.',
|
||||||
'app.title' => 'Tanemaki',
|
'app.title' => 'Tane',
|
||||||
'bootstrap.failed' => 'Tanemaki no pudo arrancar',
|
'bootstrap.failed' => 'Tane no pudo arrancar',
|
||||||
'bootstrap.retry' => 'Reintentar',
|
'bootstrap.retry' => 'Reintentar',
|
||||||
'common.save' => 'Guardar',
|
'common.save' => 'Guardar',
|
||||||
'common.cancel' => 'Cancelar',
|
'common.cancel' => 'Cancelar',
|
||||||
|
|
@ -1382,7 +1382,7 @@ extension on TranslationsEs {
|
||||||
'settings.langPt' => 'Português',
|
'settings.langPt' => 'Português',
|
||||||
'settings.about' => 'Acerca de',
|
'settings.about' => 'Acerca de',
|
||||||
'settings.aboutText' => 'Inventario local y cifrado para semillas tradicionales. AGPL-3.0.',
|
'settings.aboutText' => 'Inventario local y cifrado para semillas tradicionales. AGPL-3.0.',
|
||||||
'settings.aboutOpen' => 'Acerca de Tanemaki',
|
'settings.aboutOpen' => 'Acerca de Tane',
|
||||||
'backup.title' => 'Copia de seguridad',
|
'backup.title' => 'Copia de seguridad',
|
||||||
'backup.autoBackupTitle' => 'Copias automáticas',
|
'backup.autoBackupTitle' => 'Copias automáticas',
|
||||||
'backup.autoBackupLast' => ({required Object date}) => 'Última copia guardada el ${date}',
|
'backup.autoBackupLast' => ({required Object date}) => 'Última copia guardada el ${date}',
|
||||||
|
|
@ -1404,22 +1404,22 @@ extension on TranslationsEs {
|
||||||
'backup.cancelled' => 'Cancelado',
|
'backup.cancelled' => 'Cancelado',
|
||||||
'backup.importDone' => ({required Object added, required Object updated}) => 'Importado: ${added} nuevas, ${updated} actualizadas',
|
'backup.importDone' => ({required Object added, required Object updated}) => 'Importado: ${added} nuevas, ${updated} actualizadas',
|
||||||
'backup.importCsvDone' => ({required Object count}) => 'Añadidas ${count} entradas',
|
'backup.importCsvDone' => ({required Object count}) => 'Añadidas ${count} entradas',
|
||||||
'backup.importFailed' => 'Este fichero no se pudo leer como una copia de Tanemaki',
|
'backup.importFailed' => 'Este fichero no se pudo leer como una copia de Tane',
|
||||||
'backup.failed' => 'Algo ha salido mal',
|
'backup.failed' => 'Algo ha salido mal',
|
||||||
'backup.recoveryTitle' => 'Tu código de recuperación',
|
'backup.recoveryTitle' => 'Tu código de recuperación',
|
||||||
'backup.recoverySubtitle' => 'Imprímelo y guárdalo bien: abre tus copias en otro dispositivo',
|
'backup.recoverySubtitle' => 'Imprímelo y guárdalo bien: abre tus copias en otro dispositivo',
|
||||||
'backup.recoveryIntro' => 'Este código abre tus copias guardadas y recupera tu banco en cualquier dispositivo. Guarda dos copias en papel en sitios seguros, como tu mejor semilla. Quien lo tenga puede leer tus copias, así que no lo compartas con nadie.',
|
'backup.recoveryIntro' => 'Este código abre tus copias guardadas y recupera tu banco en cualquier dispositivo. Guarda dos copias en papel en sitios seguros, como tu mejor semilla. Quien lo tenga puede leer tus copias, así que no lo compartas con nadie.',
|
||||||
'backup.recoveryCopy' => 'Copiar',
|
'backup.recoveryCopy' => 'Copiar',
|
||||||
'backup.recoverySave' => 'Guardar la hoja',
|
'backup.recoverySave' => 'Guardar la hoja',
|
||||||
'backup.recoverySheetTitle' => 'Tanemaki — tu hoja de recuperación',
|
'backup.recoverySheetTitle' => 'Tane — tu hoja de recuperación',
|
||||||
'backup.recoveryPromptTitle' => 'Escribe tu código de recuperación',
|
'backup.recoveryPromptTitle' => 'Escribe tu código de recuperación',
|
||||||
'backup.recoveryPromptBody' => 'Esta copia se guardó con otro código. Escribe el código de tu hoja de recuperación para abrirla.',
|
'backup.recoveryPromptBody' => 'Esta copia se guardó con otro código. Escribe el código de tu hoja de recuperación para abrirla.',
|
||||||
'backup.recoveryWrongCode' => 'Ese código no abre esta copia',
|
'backup.recoveryWrongCode' => 'Ese código no abre esta copia',
|
||||||
'about.title' => 'Acerca de',
|
'about.title' => 'Acerca de',
|
||||||
'about.kanji' => '種まき',
|
'about.kanji' => '種',
|
||||||
'about.tagline' => 'Una app local-first y descentralizada para gestionar y compartir semillas y plantones tradicionales.',
|
'about.tagline' => 'Una app local-first y descentralizada para gestionar y compartir semillas y plantones tradicionales.',
|
||||||
'about.intro' => 'Tanemaki (種まき, «sembrar / esparcir semillas» en japonés; nombre corto Tane, 種 «semilla») ayuda a personas y colectivos a llevar un inventario amable de su banco de semillas, decidir qué ofrecen y compartirlo localmente — sin un intermediario central que pueda controlarlo, censurarlo o ser multado por ello. El objetivo es a la vez práctico y político: apoyar las variedades tradicionales de semillas y plantar cara al monopolio semillero.',
|
'about.intro' => 'Tane (種, «semilla» en japonés) ayuda a personas y colectivos a llevar un inventario amable de su banco de semillas, decidir qué ofrecen y compartirlo localmente — sin un intermediario central que pueda controlarlo, censurarlo o ser multado por ello. Su nombre viene de tanemaki (種まき), «sembrar / esparcir semillas». El objetivo es a la vez práctico y político: apoyar las variedades tradicionales de semillas y plantar cara al monopolio semillero.',
|
||||||
'about.heritage' => 'El nombre honra las viejas tradiciones japonesas de ayuda mutua en torno al arroz — yui (trabajo comunitario compartido) y tanomoshi (fondos de reciprocidad) — que inspiraron el papel Plantare, la «moneda comunitaria para el intercambio de semillas» (BAH-Semillero, 2009, CC-BY-SA). Tanemaki es el Plantare digital.',
|
'about.heritage' => 'El nombre honra las viejas tradiciones japonesas de ayuda mutua en torno al arroz — yui (trabajo comunitario compartido) y tanomoshi (fondos de reciprocidad) — que inspiraron el papel Plantare, la «moneda comunitaria para el intercambio de semillas» (BAH-Semillero, 2009, CC-BY-SA). Tane es el Plantare digital.',
|
||||||
'about.version' => 'Versión',
|
'about.version' => 'Versión',
|
||||||
'about.license' => 'Licencia',
|
'about.license' => 'Licencia',
|
||||||
'about.licenseValue' => 'AGPL-3.0',
|
'about.licenseValue' => 'AGPL-3.0',
|
||||||
|
|
@ -1430,7 +1430,7 @@ extension on TranslationsEs {
|
||||||
'intro.skip' => 'Saltar',
|
'intro.skip' => 'Saltar',
|
||||||
'intro.next' => 'Siguiente',
|
'intro.next' => 'Siguiente',
|
||||||
'intro.start' => 'Empezar',
|
'intro.start' => 'Empezar',
|
||||||
'intro.menuEntry' => 'Cómo funciona Tanemaki',
|
'intro.menuEntry' => 'Cómo funciona Tane',
|
||||||
'intro.slides.welcome.title' => 'La semilla que te trajo hasta aquí',
|
'intro.slides.welcome.title' => 'La semilla que te trajo hasta aquí',
|
||||||
'intro.slides.welcome.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.',
|
'intro.slides.welcome.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.',
|
||||||
'intro.slides.inventory.title' => 'Tu banco de semillas, en el bolsillo',
|
'intro.slides.inventory.title' => 'Tu banco de semillas, en el bolsillo',
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ class _Translations$app$pt extends Translations$app$en {
|
||||||
final TranslationsPt _root; // ignore: unused_field
|
final TranslationsPt _root; // ignore: unused_field
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
@override String get title => 'Tanemaki';
|
@override String get title => 'Tane';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: bootstrap
|
// Path: bootstrap
|
||||||
|
|
@ -164,7 +164,7 @@ class _Translations$bootstrap$pt extends Translations$bootstrap$en {
|
||||||
final TranslationsPt _root; // ignore: unused_field
|
final TranslationsPt _root; // ignore: unused_field
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
@override String get failed => 'O Tanemaki não conseguiu iniciar';
|
@override String get failed => 'O Tane não conseguiu iniciar';
|
||||||
@override String get retry => 'Tentar de novo';
|
@override String get retry => 'Tentar de novo';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,7 +247,7 @@ class _Translations$settings$pt extends Translations$settings$en {
|
||||||
@override String get langAst => 'Asturianu';
|
@override String get langAst => 'Asturianu';
|
||||||
@override String get about => 'Acerca de';
|
@override String get about => 'Acerca de';
|
||||||
@override String get aboutText => 'Inventário local e cifrado para sementes tradicionais. AGPL-3.0.';
|
@override String get aboutText => 'Inventário local e cifrado para sementes tradicionais. AGPL-3.0.';
|
||||||
@override String get aboutOpen => 'Acerca do Tanemaki';
|
@override String get aboutOpen => 'Acerca do Tane';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path: backup
|
// Path: backup
|
||||||
|
|
@ -278,14 +278,14 @@ class _Translations$backup$pt extends Translations$backup$en {
|
||||||
@override String get cancelled => 'Cancelado';
|
@override String get cancelled => 'Cancelado';
|
||||||
@override String importDone({required Object added, required Object updated}) => 'Importado: ${added} novas, ${updated} atualizadas';
|
@override String importDone({required Object added, required Object updated}) => 'Importado: ${added} novas, ${updated} atualizadas';
|
||||||
@override String importCsvDone({required Object count}) => '${count} entradas acrescentadas';
|
@override String importCsvDone({required Object count}) => '${count} entradas acrescentadas';
|
||||||
@override String get importFailed => 'Este ficheiro não pôde ser lido como uma cópia do Tanemaki';
|
@override String get importFailed => 'Este ficheiro não pôde ser lido como uma cópia do Tane';
|
||||||
@override String get failed => 'Algo correu mal';
|
@override String get failed => 'Algo correu mal';
|
||||||
@override String get recoveryTitle => 'O teu código de recuperação';
|
@override String get recoveryTitle => 'O teu código de recuperação';
|
||||||
@override String get recoverySubtitle => 'Imprime-o e guarda-o bem: abre as tuas cópias noutro aparelho';
|
@override String get recoverySubtitle => 'Imprime-o e guarda-o bem: abre as tuas cópias noutro aparelho';
|
||||||
@override String get recoveryIntro => 'Este código abre as tuas cópias guardadas e recupera o teu banco em qualquer aparelho. Guarda duas cópias em papel em sítios seguros, como a tua melhor semente. Quem o tiver pode ler as tuas cópias, por isso não o partilhes com ninguém.';
|
@override String get recoveryIntro => 'Este código abre as tuas cópias guardadas e recupera o teu banco em qualquer aparelho. Guarda duas cópias em papel em sítios seguros, como a tua melhor semente. Quem o tiver pode ler as tuas cópias, por isso não o partilhes com ninguém.';
|
||||||
@override String get recoveryCopy => 'Copiar';
|
@override String get recoveryCopy => 'Copiar';
|
||||||
@override String get recoverySave => 'Guardar a folha';
|
@override String get recoverySave => 'Guardar a folha';
|
||||||
@override String get recoverySheetTitle => 'Tanemaki — a tua folha de recuperação';
|
@override String get recoverySheetTitle => 'Tane — a tua folha de recuperação';
|
||||||
@override String get recoveryPromptTitle => 'Escreve o teu código de recuperação';
|
@override String get recoveryPromptTitle => 'Escreve o teu código de recuperação';
|
||||||
@override String get recoveryPromptBody => 'Esta cópia foi guardada com outro código. Escreve o código da tua folha de recuperação para a abrir.';
|
@override String get recoveryPromptBody => 'Esta cópia foi guardada com outro código. Escreve o código da tua folha de recuperação para a abrir.';
|
||||||
@override String get recoveryWrongCode => 'Esse código não abre esta cópia';
|
@override String get recoveryWrongCode => 'Esse código não abre esta cópia';
|
||||||
|
|
@ -299,10 +299,10 @@ class _Translations$about$pt extends Translations$about$en {
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
@override String get title => 'Acerca de';
|
@override String get title => 'Acerca de';
|
||||||
@override String get kanji => '種まき';
|
@override String get kanji => '種';
|
||||||
@override String get tagline => 'Uma aplicação local e descentralizada para gerir e partilhar sementes e plântulas tradicionais.';
|
@override String get tagline => 'Uma aplicação local e descentralizada para gerir e partilhar sementes e plântulas tradicionais.';
|
||||||
@override String get intro => 'O Tanemaki (種まき, "semear / espalhar sementes" em japonês; nome curto Tane, 種 "semente") ajuda pessoas e coletivos a manter um inventário amigável do seu banco de sementes, decidir o que oferecem e partilhá-lo localmente — sem um intermediário central que possa controlar, censurar ou ser multado por isso. O objetivo é prático e político ao mesmo tempo: apoiar as variedades tradicionais e fazer frente ao monopólio das sementes.';
|
@override String get intro => 'O Tane (種, "semente" em japonês) ajuda pessoas e coletivos a manter um inventário amigável do seu banco de sementes, decidir o que oferecem e partilhá-lo localmente — sem um intermediário central que possa controlar, censurar ou ser multado por isso. O seu nome vem de tanemaki (種まき), "semear / espalhar sementes". O objetivo é prático e político ao mesmo tempo: apoiar as variedades tradicionais e fazer frente ao monopólio das sementes.';
|
||||||
@override String get heritage => 'O nome honra as antigas tradições japonesas de ajuda mútua à volta do arroz — yui (trabalho comunitário partilhado) e tanomoshi (fundos de reciprocidade) — que inspiraram o Plantare em papel, a "moeda comunitária de troca de sementes" (BAH-Semillero, 2009, CC-BY-SA). O Tanemaki é o Plantare digital.';
|
@override String get heritage => 'O nome honra as antigas tradições japonesas de ajuda mútua à volta do arroz — yui (trabalho comunitário partilhado) e tanomoshi (fundos de reciprocidade) — que inspiraram o Plantare em papel, a "moeda comunitária de troca de sementes" (BAH-Semillero, 2009, CC-BY-SA). O Tane é o Plantare digital.';
|
||||||
@override String get version => 'Versão';
|
@override String get version => 'Versão';
|
||||||
@override String get license => 'Licença';
|
@override String get license => 'Licença';
|
||||||
@override String get licenseValue => 'AGPL-3.0';
|
@override String get licenseValue => 'AGPL-3.0';
|
||||||
|
|
@ -322,7 +322,7 @@ class _Translations$intro$pt extends Translations$intro$en {
|
||||||
@override String get skip => 'Saltar';
|
@override String get skip => 'Saltar';
|
||||||
@override String get next => 'Seguinte';
|
@override String get next => 'Seguinte';
|
||||||
@override String get start => 'Começar';
|
@override String get start => 'Começar';
|
||||||
@override String get menuEntry => 'Como funciona o Tanemaki';
|
@override String get menuEntry => 'Como funciona o Tane';
|
||||||
@override late final _Translations$intro$slides$pt slides = _Translations$intro$slides$pt._(_root);
|
@override late final _Translations$intro$slides$pt slides = _Translations$intro$slides$pt._(_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1341,8 +1341,8 @@ extension on TranslationsPt {
|
||||||
'calendar.filterChip' => 'Este mês',
|
'calendar.filterChip' => 'Este mês',
|
||||||
'calendar.selfNote' => 'O que anotaste nas tuas variedades.',
|
'calendar.selfNote' => 'O que anotaste nas tuas variedades.',
|
||||||
'calendar.nothing' => ({required Object month}) => 'Nada anotado para ${month}.',
|
'calendar.nothing' => ({required Object month}) => 'Nada anotado para ${month}.',
|
||||||
'app.title' => 'Tanemaki',
|
'app.title' => 'Tane',
|
||||||
'bootstrap.failed' => 'O Tanemaki não conseguiu iniciar',
|
'bootstrap.failed' => 'O Tane não conseguiu iniciar',
|
||||||
'bootstrap.retry' => 'Tentar de novo',
|
'bootstrap.retry' => 'Tentar de novo',
|
||||||
'common.save' => 'Guardar',
|
'common.save' => 'Guardar',
|
||||||
'common.cancel' => 'Cancelar',
|
'common.cancel' => 'Cancelar',
|
||||||
|
|
@ -1380,7 +1380,7 @@ extension on TranslationsPt {
|
||||||
'settings.langAst' => 'Asturianu',
|
'settings.langAst' => 'Asturianu',
|
||||||
'settings.about' => 'Acerca de',
|
'settings.about' => 'Acerca de',
|
||||||
'settings.aboutText' => 'Inventário local e cifrado para sementes tradicionais. AGPL-3.0.',
|
'settings.aboutText' => 'Inventário local e cifrado para sementes tradicionais. AGPL-3.0.',
|
||||||
'settings.aboutOpen' => 'Acerca do Tanemaki',
|
'settings.aboutOpen' => 'Acerca do Tane',
|
||||||
'backup.title' => 'Cópia de segurança',
|
'backup.title' => 'Cópia de segurança',
|
||||||
'backup.autoBackupTitle' => 'Cópias automáticas',
|
'backup.autoBackupTitle' => 'Cópias automáticas',
|
||||||
'backup.autoBackupLast' => ({required Object date}) => 'Última cópia guardada em ${date}',
|
'backup.autoBackupLast' => ({required Object date}) => 'Última cópia guardada em ${date}',
|
||||||
|
|
@ -1402,22 +1402,22 @@ extension on TranslationsPt {
|
||||||
'backup.cancelled' => 'Cancelado',
|
'backup.cancelled' => 'Cancelado',
|
||||||
'backup.importDone' => ({required Object added, required Object updated}) => 'Importado: ${added} novas, ${updated} atualizadas',
|
'backup.importDone' => ({required Object added, required Object updated}) => 'Importado: ${added} novas, ${updated} atualizadas',
|
||||||
'backup.importCsvDone' => ({required Object count}) => '${count} entradas acrescentadas',
|
'backup.importCsvDone' => ({required Object count}) => '${count} entradas acrescentadas',
|
||||||
'backup.importFailed' => 'Este ficheiro não pôde ser lido como uma cópia do Tanemaki',
|
'backup.importFailed' => 'Este ficheiro não pôde ser lido como uma cópia do Tane',
|
||||||
'backup.failed' => 'Algo correu mal',
|
'backup.failed' => 'Algo correu mal',
|
||||||
'backup.recoveryTitle' => 'O teu código de recuperação',
|
'backup.recoveryTitle' => 'O teu código de recuperação',
|
||||||
'backup.recoverySubtitle' => 'Imprime-o e guarda-o bem: abre as tuas cópias noutro aparelho',
|
'backup.recoverySubtitle' => 'Imprime-o e guarda-o bem: abre as tuas cópias noutro aparelho',
|
||||||
'backup.recoveryIntro' => 'Este código abre as tuas cópias guardadas e recupera o teu banco em qualquer aparelho. Guarda duas cópias em papel em sítios seguros, como a tua melhor semente. Quem o tiver pode ler as tuas cópias, por isso não o partilhes com ninguém.',
|
'backup.recoveryIntro' => 'Este código abre as tuas cópias guardadas e recupera o teu banco em qualquer aparelho. Guarda duas cópias em papel em sítios seguros, como a tua melhor semente. Quem o tiver pode ler as tuas cópias, por isso não o partilhes com ninguém.',
|
||||||
'backup.recoveryCopy' => 'Copiar',
|
'backup.recoveryCopy' => 'Copiar',
|
||||||
'backup.recoverySave' => 'Guardar a folha',
|
'backup.recoverySave' => 'Guardar a folha',
|
||||||
'backup.recoverySheetTitle' => 'Tanemaki — a tua folha de recuperação',
|
'backup.recoverySheetTitle' => 'Tane — a tua folha de recuperação',
|
||||||
'backup.recoveryPromptTitle' => 'Escreve o teu código de recuperação',
|
'backup.recoveryPromptTitle' => 'Escreve o teu código de recuperação',
|
||||||
'backup.recoveryPromptBody' => 'Esta cópia foi guardada com outro código. Escreve o código da tua folha de recuperação para a abrir.',
|
'backup.recoveryPromptBody' => 'Esta cópia foi guardada com outro código. Escreve o código da tua folha de recuperação para a abrir.',
|
||||||
'backup.recoveryWrongCode' => 'Esse código não abre esta cópia',
|
'backup.recoveryWrongCode' => 'Esse código não abre esta cópia',
|
||||||
'about.title' => 'Acerca de',
|
'about.title' => 'Acerca de',
|
||||||
'about.kanji' => '種まき',
|
'about.kanji' => '種',
|
||||||
'about.tagline' => 'Uma aplicação local e descentralizada para gerir e partilhar sementes e plântulas tradicionais.',
|
'about.tagline' => 'Uma aplicação local e descentralizada para gerir e partilhar sementes e plântulas tradicionais.',
|
||||||
'about.intro' => 'O Tanemaki (種まき, "semear / espalhar sementes" em japonês; nome curto Tane, 種 "semente") ajuda pessoas e coletivos a manter um inventário amigável do seu banco de sementes, decidir o que oferecem e partilhá-lo localmente — sem um intermediário central que possa controlar, censurar ou ser multado por isso. O objetivo é prático e político ao mesmo tempo: apoiar as variedades tradicionais e fazer frente ao monopólio das sementes.',
|
'about.intro' => 'O Tane (種, "semente" em japonês) ajuda pessoas e coletivos a manter um inventário amigável do seu banco de sementes, decidir o que oferecem e partilhá-lo localmente — sem um intermediário central que possa controlar, censurar ou ser multado por isso. O seu nome vem de tanemaki (種まき), "semear / espalhar sementes". O objetivo é prático e político ao mesmo tempo: apoiar as variedades tradicionais e fazer frente ao monopólio das sementes.',
|
||||||
'about.heritage' => 'O nome honra as antigas tradições japonesas de ajuda mútua à volta do arroz — yui (trabalho comunitário partilhado) e tanomoshi (fundos de reciprocidade) — que inspiraram o Plantare em papel, a "moeda comunitária de troca de sementes" (BAH-Semillero, 2009, CC-BY-SA). O Tanemaki é o Plantare digital.',
|
'about.heritage' => 'O nome honra as antigas tradições japonesas de ajuda mútua à volta do arroz — yui (trabalho comunitário partilhado) e tanomoshi (fundos de reciprocidade) — que inspiraram o Plantare em papel, a "moeda comunitária de troca de sementes" (BAH-Semillero, 2009, CC-BY-SA). O Tane é o Plantare digital.',
|
||||||
'about.version' => 'Versão',
|
'about.version' => 'Versão',
|
||||||
'about.license' => 'Licença',
|
'about.license' => 'Licença',
|
||||||
'about.licenseValue' => 'AGPL-3.0',
|
'about.licenseValue' => 'AGPL-3.0',
|
||||||
|
|
@ -1428,7 +1428,7 @@ extension on TranslationsPt {
|
||||||
'intro.skip' => 'Saltar',
|
'intro.skip' => 'Saltar',
|
||||||
'intro.next' => 'Seguinte',
|
'intro.next' => 'Seguinte',
|
||||||
'intro.start' => 'Começar',
|
'intro.start' => 'Começar',
|
||||||
'intro.menuEntry' => 'Como funciona o Tanemaki',
|
'intro.menuEntry' => 'Como funciona o Tane',
|
||||||
'intro.slides.welcome.title' => 'A semente que te trouxe até aqui',
|
'intro.slides.welcome.title' => 'A semente que te trouxe até aqui',
|
||||||
'intro.slides.welcome.body' => 'Cada semente tradicional é uma carta escrita por milhares de gerações, passada de mão em mão. Somos o que somos graças a essa partilha.',
|
'intro.slides.welcome.body' => 'Cada semente tradicional é uma carta escrita por milhares de gerações, passada de mão em mão. Somos o que somos graças a essa partilha.',
|
||||||
'intro.slides.inventory.title' => 'O teu banco de sementes, no bolso',
|
'intro.slides.inventory.title' => 'O teu banco de sementes, no bolso',
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ class AutoBackupService {
|
||||||
|
|
||||||
/// Filename prefix so rotation only ever touches automatic copies, never a
|
/// Filename prefix so rotation only ever touches automatic copies, never a
|
||||||
/// backup the user saved by hand.
|
/// backup the user saved by hand.
|
||||||
static const _prefix = 'tanemaki-auto-';
|
static const _prefix = 'tane-auto-';
|
||||||
|
|
||||||
/// How many automatic copies to keep. A rotating window (not a single file)
|
/// How many automatic copies to keep. A rotating window (not a single file)
|
||||||
/// so a corrupt copy can't overwrite the only backup.
|
/// so a corrupt copy can't overwrite the only backup.
|
||||||
|
|
@ -62,7 +62,7 @@ class AutoBackupService {
|
||||||
await dir.create(recursive: true);
|
await dir.create(recursive: true);
|
||||||
final sealed = await _exporter.buildSealedBackup();
|
final sealed = await _exporter.buildSealedBackup();
|
||||||
final date = now.toIso8601String().substring(0, 10);
|
final date = now.toIso8601String().substring(0, 10);
|
||||||
final file = File('${dir.path}/$_prefix$date.tanemaki');
|
final file = File('${dir.path}/$_prefix$date.tane');
|
||||||
await file.writeAsBytes(sealed, flush: true);
|
await file.writeAsBytes(sealed, flush: true);
|
||||||
|
|
||||||
await _rotate(dir);
|
await _rotate(dir);
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ class ExportImportService implements InventorySnapshotIO {
|
||||||
static const _csvCodec = InventoryCsvCodec();
|
static const _csvCodec = InventoryCsvCodec();
|
||||||
|
|
||||||
/// The backup file extension. The content is the sealed interchange JSON.
|
/// The backup file extension. The content is the sealed interchange JSON.
|
||||||
static const backupExtension = 'tanemaki';
|
static const backupExtension = 'tane';
|
||||||
|
|
||||||
/// Raw (unsealed) interchange snapshot for device-to-device sync: includes
|
/// Raw (unsealed) interchange snapshot for device-to-device sync: includes
|
||||||
/// tombstones (so deletions replicate) and omits photo bytes (kept device-
|
/// tombstones (so deletions replicate) and omits photo bytes (kept device-
|
||||||
|
|
@ -150,7 +150,7 @@ class ExportImportService implements InventorySnapshotIO {
|
||||||
|
|
||||||
String _fileName(String extension) {
|
String _fileName(String extension) {
|
||||||
final date = _now().toIso8601String().substring(0, 10);
|
final date = _now().toIso8601String().substring(0, 10);
|
||||||
return 'tanemaki-backup-$date.$extension';
|
return 'tane-backup-$date.$extension';
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<int> _hexToBytes(String hex) => [
|
static List<int> _hexToBytes(String hex) => [
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class LabelSheetLabel {
|
||||||
/// The batch facts line ("2006 · Perales · 2 cobs"), if any.
|
/// The batch facts line ("2006 · Perales · 2 cobs"), if any.
|
||||||
final String? details;
|
final String? details;
|
||||||
|
|
||||||
/// The QR payload (a `tanemaki://seed` URI), so the seed's data rides on the
|
/// The QR payload (a `tane://seed` URI), so the seed's data rides on the
|
||||||
/// physical packet.
|
/// physical packet.
|
||||||
final String qrData;
|
final String qrData;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@ import '../i18n/strings.g.dart';
|
||||||
import 'theme.dart';
|
import 'theme.dart';
|
||||||
|
|
||||||
/// The app's public website. Shown as a tappable row in [AboutScreen].
|
/// The app's public website. Shown as a tappable row in [AboutScreen].
|
||||||
const String _websiteUrl = 'https://tanemaki.app';
|
const String _websiteUrl = 'https://tane.comunes.org';
|
||||||
|
|
||||||
/// The year Tanemaki's copyright starts. Ğ1nkgo uses its own first year (2023);
|
/// The year Tane's copyright starts. Ğ1nkgo uses its own first year (2023);
|
||||||
/// Tanemaki's is 2026.
|
/// Tane's is 2026.
|
||||||
const int _copyrightStartYear = 2026;
|
const int _copyrightStartYear = 2026;
|
||||||
|
|
||||||
/// A single year (`2026`) until the calendar rolls over, then a range
|
/// A single year (`2026`) until the calendar rolls over, then a range
|
||||||
|
|
@ -22,7 +22,7 @@ String _copyrightYears() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An "about" screen à la Ğ1nkgo: brand header, the human explanation of what
|
/// An "about" screen à la Ğ1nkgo: brand header, the human explanation of what
|
||||||
/// Tanemaki is and where its name comes from, the app version, license, the
|
/// Tane is and where its name comes from, the app version, license, the
|
||||||
/// website, and the bundled open-source licenses page.
|
/// website, and the bundled open-source licenses page.
|
||||||
class AboutScreen extends StatelessWidget {
|
class AboutScreen extends StatelessWidget {
|
||||||
const AboutScreen({super.key});
|
const AboutScreen({super.key});
|
||||||
|
|
@ -99,7 +99,7 @@ class AboutScreen extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Brand block: the logo, the app name and its 種まき kanji.
|
/// Brand block: the logo, the app name and its 種 kanji.
|
||||||
class _Header extends StatelessWidget {
|
class _Header extends StatelessWidget {
|
||||||
const _Header();
|
const _Header();
|
||||||
|
|
||||||
|
|
@ -133,7 +133,7 @@ class _Header extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The two explanatory paragraphs: what Tanemaki is, and the heritage of its
|
/// The two explanatory paragraphs: what Tane is, and the heritage of its
|
||||||
/// name (yui / tanomoshi / the paper Plantare).
|
/// name (yui / tanomoshi / the paper Plantare).
|
||||||
class _Paragraph extends StatelessWidget {
|
class _Paragraph extends StatelessWidget {
|
||||||
const _Paragraph();
|
const _Paragraph();
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ class BackupSection extends StatelessWidget {
|
||||||
title: t.backup.recoverySheetTitle,
|
title: t.backup.recoverySheetTitle,
|
||||||
intro: t.backup.recoveryIntro,
|
intro: t.backup.recoveryIntro,
|
||||||
code: code,
|
code: code,
|
||||||
suggestedName: 'tanemaki-recovery.pdf',
|
suggestedName: 'tane-recovery.pdf',
|
||||||
);
|
);
|
||||||
_show(messenger, saved ? t.backup.exportSaved : t.backup.cancelled);
|
_show(messenger, saved ? t.backup.exportSaved : t.backup.cancelled);
|
||||||
} on Object {
|
} on Object {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class _Slide {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The first-run intro carousel (also reachable later from the drawer): a few
|
/// The first-run intro carousel (also reachable later from the drawer): a few
|
||||||
/// swipeable cards explaining what Tanemaki is, how privacy works, how sharing
|
/// swipeable cards explaining what Tane is, how privacy works, how sharing
|
||||||
/// works and the Plantare. [onDone] fires when the user skips or finishes, and
|
/// works and the Plantare. [onDone] fires when the user skips or finishes, and
|
||||||
/// is where the caller marks the intro as seen and leaves the screen.
|
/// is where the caller marks the intro as seen and leaves the screen.
|
||||||
class IntroScreen extends StatefulWidget {
|
class IntroScreen extends StatefulWidget {
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ class InventoryListScreen extends StatelessWidget {
|
||||||
title: t.share.catalogTitle,
|
title: t.share.catalogTitle,
|
||||||
date: dateLabel,
|
date: dateLabel,
|
||||||
suggestedName:
|
suggestedName:
|
||||||
'tanemaki-catalog-${date.toIso8601String().substring(0, 10)}.pdf',
|
'tane-catalog-${date.toIso8601String().substring(0, 10)}.pdf',
|
||||||
rows: rows,
|
rows: rows,
|
||||||
);
|
);
|
||||||
messenger.showSnackBar(
|
messenger.showSnackBar(
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ class _LabelPrintSheetState extends State<_LabelPrintSheet> {
|
||||||
final saved = await getIt<LabelSheetService>().saveLabels(
|
final saved = await getIt<LabelSheetService>().saveLabels(
|
||||||
labels: labels,
|
labels: labels,
|
||||||
format: _format,
|
format: _format,
|
||||||
suggestedName: 'tanemaki-labels-${_today()}.pdf',
|
suggestedName: 'tane-labels-${_today()}.pdf',
|
||||||
rtl: rtl,
|
rtl: rtl,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
name: tane
|
name: tane
|
||||||
description: "Tanemaki — local-first, encrypted, decentralized traditional-seed inventory."
|
description: "Tane — local-first, encrypted, decentralized traditional-seed inventory."
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 0.1.0+1
|
version: 0.1.0+1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import 'package:tane/data/export_import/seed_label_codec.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('SeedLabelCodec.encode', () {
|
group('SeedLabelCodec.encode', () {
|
||||||
test('encodes all fields as a tanemaki://seed URI', () {
|
test('encodes all fields as a tane://seed URI', () {
|
||||||
final uri = SeedLabelCodec.encode(
|
final uri = SeedLabelCodec.encode(
|
||||||
const SeedLabelData(
|
const SeedLabelData(
|
||||||
varietyLabel: 'Acelga de Perales',
|
varietyLabel: 'Acelga de Perales',
|
||||||
|
|
@ -13,9 +13,9 @@ void main() {
|
||||||
origin: 'Perales',
|
origin: 'Perales',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(uri, startsWith('tanemaki://seed?'));
|
expect(uri, startsWith('tane://seed?'));
|
||||||
final parsed = Uri.parse(uri);
|
final parsed = Uri.parse(uri);
|
||||||
expect(parsed.scheme, 'tanemaki');
|
expect(parsed.scheme, 'tane');
|
||||||
expect(parsed.host, 'seed');
|
expect(parsed.host, 'seed');
|
||||||
expect(parsed.queryParameters, {
|
expect(parsed.queryParameters, {
|
||||||
'v': 'Acelga de Perales',
|
'v': 'Acelga de Perales',
|
||||||
|
|
@ -74,15 +74,15 @@ void main() {
|
||||||
group('SeedLabelCodec.decode', () {
|
group('SeedLabelCodec.decode', () {
|
||||||
test('rejects a foreign scheme', () {
|
test('rejects a foreign scheme', () {
|
||||||
expect(SeedLabelCodec.decode('https://seed?v=x'), isNull);
|
expect(SeedLabelCodec.decode('https://seed?v=x'), isNull);
|
||||||
expect(SeedLabelCodec.decode('tanemaki://other?v=x'), isNull);
|
expect(SeedLabelCodec.decode('tane://other?v=x'), isNull);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('rejects a payload without a variety', () {
|
test('rejects a payload without a variety', () {
|
||||||
expect(SeedLabelCodec.decode('tanemaki://seed?s=Beta%20vulgaris'), isNull);
|
expect(SeedLabelCodec.decode('tane://seed?s=Beta%20vulgaris'), isNull);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('ignores an unparseable year rather than throwing', () {
|
test('ignores an unparseable year rather than throwing', () {
|
||||||
final decoded = SeedLabelCodec.decode('tanemaki://seed?v=Maíz&y=old');
|
final decoded = SeedLabelCodec.decode('tane://seed?v=Maíz&y=old');
|
||||||
expect(decoded?.varietyLabel, 'Maíz');
|
expect(decoded?.varietyLabel, 'Maíz');
|
||||||
expect(decoded?.year, isNull);
|
expect(decoded?.year, isNull);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ void main() {
|
||||||
.listSync()
|
.listSync()
|
||||||
.whereType<File>()
|
.whereType<File>()
|
||||||
.map((f) => f.uri.pathSegments.last)
|
.map((f) => f.uri.pathSegments.last)
|
||||||
.where((n) => n.startsWith('tanemaki-auto-'))
|
.where((n) => n.startsWith('tane-auto-'))
|
||||||
.toList()
|
.toList()
|
||||||
..sort();
|
..sort();
|
||||||
|
|
||||||
|
|
@ -89,7 +89,7 @@ void main() {
|
||||||
expect(await service.runIfDue(), isTrue);
|
expect(await service.runIfDue(), isTrue);
|
||||||
|
|
||||||
final copies = autoCopies();
|
final copies = autoCopies();
|
||||||
expect(copies, ['tanemaki-auto-2026-07-10.tanemaki']);
|
expect(copies, ['tane-auto-2026-07-10.tane']);
|
||||||
final bytes = File('${dir.path}/${copies.single}').readAsBytesSync();
|
final bytes = File('${dir.path}/${copies.single}').readAsBytesSync();
|
||||||
expect(BackupBox.looksSealed(bytes), isTrue);
|
expect(BackupBox.looksSealed(bytes), isTrue);
|
||||||
});
|
});
|
||||||
|
|
@ -117,12 +117,12 @@ void main() {
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(await service.runIfDue(), isTrue);
|
expect(await service.runIfDue(), isTrue);
|
||||||
expect(autoCopies(), ['tanemaki-auto-2026-07-10.tanemaki']);
|
expect(autoCopies(), ['tane-auto-2026-07-10.tane']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('rotation keeps only the newest three copies', () async {
|
test('rotation keeps only the newest three copies', () async {
|
||||||
for (final d in ['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04']) {
|
for (final d in ['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04']) {
|
||||||
File('${dir.path}/tanemaki-auto-$d.tanemaki').writeAsBytesSync([0]);
|
File('${dir.path}/tane-auto-$d.tane').writeAsBytesSync([0]);
|
||||||
}
|
}
|
||||||
final service = newService(
|
final service = newService(
|
||||||
newExporter(),
|
newExporter(),
|
||||||
|
|
@ -133,9 +133,9 @@ void main() {
|
||||||
await service.runIfDue();
|
await service.runIfDue();
|
||||||
|
|
||||||
expect(autoCopies(), [
|
expect(autoCopies(), [
|
||||||
'tanemaki-auto-2020-01-03.tanemaki',
|
'tane-auto-2020-01-03.tane',
|
||||||
'tanemaki-auto-2020-01-04.tanemaki',
|
'tane-auto-2020-01-04.tane',
|
||||||
'tanemaki-auto-2026-07-10.tanemaki',
|
'tane-auto-2026-07-10.tane',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -151,7 +151,7 @@ void main() {
|
||||||
// runIfDue is a no-op today, but an explicit tap still makes a copy.
|
// runIfDue is a no-op today, but an explicit tap still makes a copy.
|
||||||
expect(await service.runIfDue(), isFalse);
|
expect(await service.runIfDue(), isFalse);
|
||||||
expect(await service.backupNow(), isTrue);
|
expect(await service.backupNow(), isTrue);
|
||||||
expect(autoCopies(), ['tanemaki-auto-2026-07-10.tanemaki']);
|
expect(autoCopies(), ['tane-auto-2026-07-10.tane']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('a failed backup returns false and never throws', () async {
|
test('a failed backup returns false and never throws', () async {
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ void main() {
|
||||||
|
|
||||||
await service.exportBackup();
|
await service.exportBackup();
|
||||||
|
|
||||||
expect(files.savedName, endsWith('.tanemaki'));
|
expect(files.savedName, endsWith('.tane'));
|
||||||
expect(BackupBox.looksSealed(files.saved!), isTrue);
|
expect(BackupBox.looksSealed(files.saved!), isTrue);
|
||||||
expect(String.fromCharCodes(files.saved!).contains('Secret'), isFalse);
|
expect(String.fromCharCodes(files.saved!).contains('Secret'), isFalse);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,11 @@ const _labels = [
|
||||||
commonName: 'Acelga',
|
commonName: 'Acelga',
|
||||||
scientificName: 'Beta vulgaris',
|
scientificName: 'Beta vulgaris',
|
||||||
details: '2006 · Perales',
|
details: '2006 · Perales',
|
||||||
qrData: 'tanemaki://seed?v=Acelga+de+Perales&y=2006',
|
qrData: 'tane://seed?v=Acelga+de+Perales&y=2006',
|
||||||
),
|
),
|
||||||
LabelSheetLabel(
|
LabelSheetLabel(
|
||||||
varietyLabel: 'Alubia de Tolosa',
|
varietyLabel: 'Alubia de Tolosa',
|
||||||
qrData: 'tanemaki://seed?v=Alubia+de+Tolosa',
|
qrData: 'tane://seed?v=Alubia+de+Tolosa',
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ void main() {
|
||||||
final service = LabelSheetService(files: _RecordingFileService());
|
final service = LabelSheetService(files: _RecordingFileService());
|
||||||
final bytes = await service.buildPdf(
|
final bytes = await service.buildPdf(
|
||||||
labels: const [
|
labels: const [
|
||||||
LabelSheetLabel(varietyLabel: 'Maíz', qrData: 'tanemaki://seed?v=Maíz'),
|
LabelSheetLabel(varietyLabel: 'Maíz', qrData: 'tane://seed?v=Maíz'),
|
||||||
],
|
],
|
||||||
format: LabelSheetFormat.stickers,
|
format: LabelSheetFormat.stickers,
|
||||||
);
|
);
|
||||||
|
|
@ -68,7 +68,7 @@ void main() {
|
||||||
final service = LabelSheetService(files: _RecordingFileService());
|
final service = LabelSheetService(files: _RecordingFileService());
|
||||||
final bytes = await service.buildPdf(
|
final bytes = await service.buildPdf(
|
||||||
labels: const [
|
labels: const [
|
||||||
LabelSheetLabel(varietyLabel: 'بامية', qrData: 'tanemaki://seed?v=x'),
|
LabelSheetLabel(varietyLabel: 'بامية', qrData: 'tane://seed?v=x'),
|
||||||
],
|
],
|
||||||
format: LabelSheetFormat.cards,
|
format: LabelSheetFormat.cards,
|
||||||
rtl: true,
|
rtl: true,
|
||||||
|
|
@ -82,11 +82,11 @@ void main() {
|
||||||
final saved = await service.saveLabels(
|
final saved = await service.saveLabels(
|
||||||
labels: _labels,
|
labels: _labels,
|
||||||
format: LabelSheetFormat.cards,
|
format: LabelSheetFormat.cards,
|
||||||
suggestedName: 'tanemaki-labels-2026-07-10.pdf',
|
suggestedName: 'tane-labels-2026-07-10.pdf',
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(saved, isTrue);
|
expect(saved, isTrue);
|
||||||
expect(files.savedName, 'tanemaki-labels-2026-07-10.pdf');
|
expect(files.savedName, 'tane-labels-2026-07-10.pdf');
|
||||||
expect(String.fromCharCodes(files.saved!.take(5)), '%PDF-');
|
expect(String.fromCharCodes(files.saved!.take(5)), '%PDF-');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,12 +55,12 @@ void main() {
|
||||||
final saved = await service.saveCatalog(
|
final saved = await service.saveCatalog(
|
||||||
title: 'What I share',
|
title: 'What I share',
|
||||||
date: 'July 9, 2026',
|
date: 'July 9, 2026',
|
||||||
suggestedName: 'tanemaki-catalog-2026-07-09.pdf',
|
suggestedName: 'tane-catalog-2026-07-09.pdf',
|
||||||
rows: const [ShareCatalogRow(name: 'Maize', mode: 'To give away')],
|
rows: const [ShareCatalogRow(name: 'Maize', mode: 'To give away')],
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(saved, isTrue);
|
expect(saved, isTrue);
|
||||||
expect(files.savedName, 'tanemaki-catalog-2026-07-09.pdf');
|
expect(files.savedName, 'tane-catalog-2026-07-09.pdf');
|
||||||
expect(String.fromCharCodes(files.saved!.take(5)), '%PDF-');
|
expect(String.fromCharCodes(files.saved!.take(5)), '%PDF-');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ void main() {
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
PackageInfo.setMockInitialValues(
|
PackageInfo.setMockInitialValues(
|
||||||
appName: 'Tanemaki',
|
appName: 'Tane',
|
||||||
packageName: 'org.comunes.tane',
|
packageName: 'org.comunes.tane',
|
||||||
version: '0.1.0',
|
version: '0.1.0',
|
||||||
buildNumber: '1',
|
buildNumber: '1',
|
||||||
|
|
@ -38,7 +38,7 @@ void main() {
|
||||||
await tester.tap(find.text('About')); // drawer entry
|
await tester.tap(find.text('About')); // drawer entry
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(find.text('種まき'), findsOneWidget);
|
expect(find.text('種'), findsOneWidget);
|
||||||
expect(find.textContaining('digital Plantare'), findsOneWidget);
|
expect(find.textContaining('digital Plantare'), findsOneWidget);
|
||||||
await disposeTree(tester);
|
await disposeTree(tester);
|
||||||
});
|
});
|
||||||
|
|
@ -57,12 +57,12 @@ void main() {
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// The backup section pushed the About tile below the fold.
|
// The backup section pushed the About tile below the fold.
|
||||||
await tester.scrollUntilVisible(find.text('About Tanemaki'), 200);
|
await tester.scrollUntilVisible(find.text('About Tane'), 200);
|
||||||
await tester.tap(find.text('About Tanemaki'));
|
await tester.tap(find.text('About Tane'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// Explanation text and kanji are shown above the fold.
|
// Explanation text and kanji are shown above the fold.
|
||||||
expect(find.text('種まき'), findsOneWidget);
|
expect(find.text('種'), findsOneWidget);
|
||||||
expect(find.textContaining('helps people and collectives'), findsOneWidget);
|
expect(find.textContaining('helps people and collectives'), findsOneWidget);
|
||||||
expect(find.textContaining('digital Plantare'), findsOneWidget);
|
expect(find.textContaining('digital Plantare'), findsOneWidget);
|
||||||
|
|
||||||
|
|
@ -87,8 +87,8 @@ void main() {
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
await tester.tap(find.text('Settings'));
|
await tester.tap(find.text('Settings'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
await tester.scrollUntilVisible(find.text('About Tanemaki'), 200);
|
await tester.scrollUntilVisible(find.text('About Tane'), 200);
|
||||||
await tester.tap(find.text('About Tanemaki'));
|
await tester.tap(find.text('About Tane'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
await tester.scrollUntilVisible(find.text('Open-source licenses'), 200);
|
await tester.scrollUntilVisible(find.text('Open-source licenses'), 200);
|
||||||
|
|
|
||||||
|
|
@ -109,12 +109,12 @@ void main() {
|
||||||
expect(find.text('Copy saved'), findsOneWidget);
|
expect(find.text('Copy saved'), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('saving a backup writes a sealed .tanemaki file', (tester) async {
|
testWidgets('saving a backup writes a sealed .tane file', (tester) async {
|
||||||
await tester.pumpWidget(section());
|
await tester.pumpWidget(section());
|
||||||
await tester.tap(find.text('Save a backup'));
|
await tester.tap(find.text('Save a backup'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(files.savedName, endsWith('.tanemaki'));
|
expect(files.savedName, endsWith('.tane'));
|
||||||
expect(BackupBox.looksSealed(files.savedBytes!), isTrue);
|
expect(BackupBox.looksSealed(files.savedBytes!), isTrue);
|
||||||
expect(find.text('Copy saved'), findsOneWidget);
|
expect(find.text('Copy saved'), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
@ -210,7 +210,7 @@ void main() {
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
find.text('This file could not be read as a Tanemaki copy'),
|
find.text('This file could not be read as a Tane copy'),
|
||||||
findsOneWidget,
|
findsOneWidget,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -228,7 +228,7 @@ void main() {
|
||||||
await tester.tap(find.byKey(const Key('backup.recoverySave')));
|
await tester.tap(find.byKey(const Key('backup.recoverySave')));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(files.savedName, 'tanemaki-recovery.pdf');
|
expect(files.savedName, 'tane-recovery.pdf');
|
||||||
expect(String.fromCharCodes(files.savedBytes!.take(5)), '%PDF-');
|
expect(String.fromCharCodes(files.savedBytes!.take(5)), '%PDF-');
|
||||||
// The seed itself never appears in the clear in the PDF stream metadata;
|
// The seed itself never appears in the clear in the PDF stream metadata;
|
||||||
// the QR encodes the human code, which IS the secret — that's the point
|
// the QR encodes the human code, which IS the secret — that's the point
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ void main() {
|
||||||
const longLocales = [AppLocale.es, AppLocale.pt, AppLocale.ast];
|
const longLocales = [AppLocale.es, AppLocale.pt, AppLocale.ast];
|
||||||
|
|
||||||
setUpAll(() => PackageInfo.setMockInitialValues(
|
setUpAll(() => PackageInfo.setMockInitialValues(
|
||||||
appName: 'Tanemaki',
|
appName: 'Tane',
|
||||||
packageName: 'org.comunes.tane',
|
packageName: 'org.comunes.tane',
|
||||||
version: '0.1.0',
|
version: '0.1.0',
|
||||||
buildNumber: '1',
|
buildNumber: '1',
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ const String _endpoint = 'https://query.wikidata.org/sparql';
|
||||||
|
|
||||||
/// Wikimedia asks bots to send a descriptive, contactable User-Agent.
|
/// Wikimedia asks bots to send a descriptive, contactable User-Agent.
|
||||||
const String _userAgent =
|
const String _userAgent =
|
||||||
'TanemakiSpeciesCatalogBot/1.0 (https://tanemaki.app; vjrj@comunes.org)';
|
'TaneSpeciesCatalogBot/1.0 (https://tane.comunes.org; vjrj@comunes.org)';
|
||||||
|
|
||||||
const String _catalogNote =
|
const String _catalogNote =
|
||||||
'Edible / cultivated plant species, generated from Wikidata (CC0) by '
|
'Edible / cultivated plant species, generated from Wikidata (CC0) by '
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,13 @@
|
||||||
<!-- iOS meta tags & icons -->
|
<!-- iOS meta tags & icons -->
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||||
<meta name="apple-mobile-web-app-title" content="Tanemaki">
|
<meta name="apple-mobile-web-app-title" content="Tane">
|
||||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||||
|
|
||||||
<!-- Favicon -->
|
<!-- Favicon -->
|
||||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||||
|
|
||||||
<title>Tanemaki</title>
|
<title>Tane</title>
|
||||||
<link rel="manifest" href="manifest.json">
|
<link rel="manifest" href="manifest.json">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "Tanemaki",
|
"name": "Tane",
|
||||||
"short_name": "Tane",
|
"short_name": "Tane",
|
||||||
"start_url": ".",
|
"start_url": ".",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
|
|
|
||||||
|
|
@ -90,12 +90,12 @@ BEGIN
|
||||||
BLOCK "040904e4"
|
BLOCK "040904e4"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Comunes" "\0"
|
VALUE "CompanyName", "Comunes" "\0"
|
||||||
VALUE "FileDescription", "Tanemaki — local-first traditional-seed inventory" "\0"
|
VALUE "FileDescription", "Tane — local-first traditional-seed inventory" "\0"
|
||||||
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
||||||
VALUE "InternalName", "tane" "\0"
|
VALUE "InternalName", "tane" "\0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2026 Comunes. Licensed under AGPL-3.0." "\0"
|
VALUE "LegalCopyright", "Copyright (C) 2026 Comunes. Licensed under AGPL-3.0." "\0"
|
||||||
VALUE "OriginalFilename", "tane.exe" "\0"
|
VALUE "OriginalFilename", "tane.exe" "\0"
|
||||||
VALUE "ProductName", "Tanemaki" "\0"
|
VALUE "ProductName", "Tane" "\0"
|
||||||
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
# Tanemaki — Copias de seguridad y recuperación
|
# Tane — Copias de seguridad y recuperación
|
||||||
|
|
||||||
*Nota de diseño (discusión). Responde al hueco crítico nº 1 de [VISION.md](../../VISION.md): si cada persona es su propio banco, perder el móvil no puede significar perder el banco.*
|
*Nota de diseño (discusión). Responde al hueco crítico nº 1 de [VISION.md](../../VISION.md): si cada persona es su propio banco, perder el móvil no puede significar perder el banco.*
|
||||||
|
|
||||||
## El planteamiento
|
## El planteamiento
|
||||||
|
|
||||||
"El banco eres tú." Tu inventario, tu identidad (tu clave) y tu historial viven en tu teléfono. Si el móvil se rompe, se pierde o se cambia, hace falta poder **recuperarlo todo** en otro. Y como Tanemaki **no tiene servidor central** (por sostenibilidad y por privacidad), la copia no puede vivir "en la nube de Tanemaki": tiene que ir a un sitio que **tú** elijas y controles.
|
"El banco eres tú." Tu inventario, tu identidad (tu clave) y tu historial viven en tu teléfono. Si el móvil se rompe, se pierde o se cambia, hace falta poder **recuperarlo todo** en otro. Y como Tane **no tiene servidor central** (por sostenibilidad y por privacidad), la copia no puede vivir "en la nube de Tane": tiene que ir a un sitio que **tú** elijas y controles.
|
||||||
|
|
||||||
Qué debe entrar en una copia completa: los datos del inventario (variedades, lotes, movimientos, notas), las **fotos**, la **identidad (par de claves)** y la red de confianza/Plantares que tienes. Sin la clave, recuperarías los datos pero perderías tu identidad y tu reputación; por eso viajan juntos, cifrados.
|
Qué debe entrar en una copia completa: los datos del inventario (variedades, lotes, movimientos, notas), las **fotos**, la **identidad (par de claves)** y la red de confianza/Plantares que tienes. Sin la clave, recuperarías los datos pero perderías tu identidad y tu reputación; por eso viajan juntos, cifrados.
|
||||||
|
|
||||||
## Principios (coherentes con el proyecto)
|
## Principios (coherentes con el proyecto)
|
||||||
|
|
||||||
- **Sin infraestructura de Tanemaki.** El destino de la copia lo pone la persona: un archivo, su propia nube, otro dispositivo. Nada obligatorio en servidores nuestros.
|
- **Sin infraestructura de Tane.** El destino de la copia lo pone la persona: un archivo, su propia nube, otro dispositivo. Nada obligatorio en servidores nuestros.
|
||||||
- **Privada por defecto.** La copia va cifrada (lleva tu clave privada y tus datos). Nadie más debería poder leerla.
|
- **Privada por defecto.** La copia va cifrada (lleva tu clave privada y tus datos). Nadie más debería poder leerla.
|
||||||
- **Para humanos de 10 a 80.** "Guarda una copia de tu banco", no "exporta la base de datos cifrada". Metáfora amable: guardar las semillas a buen recaudo. Recordatorios suaves ("hace 2 meses que no haces copia").
|
- **Para humanos de 10 a 80.** "Guarda una copia de tu banco", no "exporta la base de datos cifrada". Metáfora amable: guardar las semillas a buen recaudo. Recordatorios suaves ("hace 2 meses que no haces copia").
|
||||||
- **Degrada con elegancia.** La copia más simple (un archivo) funciona sin red y sin cuentas. Las opciones más cómodas se añaden encima, nunca como requisito.
|
- **Degrada con elegancia.** La copia más simple (un archivo) funciona sin red y sin cuentas. Las opciones más cómodas se añaden encima, nunca como requisito.
|
||||||
|
|
@ -18,7 +18,7 @@ Qué debe entrar en una copia completa: los datos del inventario (variedades, lo
|
||||||
## Mecanismos, en capas (de lo simple a lo potente)
|
## Mecanismos, en capas (de lo simple a lo potente)
|
||||||
|
|
||||||
### 1. Exportar / importar un archivo *(base, Fase 1)*
|
### 1. Exportar / importar un archivo *(base, Fase 1)*
|
||||||
Un botón: **"Guardar una copia de mi banco"** → un único archivo `.tanemaki` (un zip con los datos + fotos + la clave, cifrado con una frase de paso). La persona lo guarda donde quiera: se lo manda a su propio correo, a un USB, a su nube, lo copia a otro móvil. **"Restaurar desde una copia"** en el móvil nuevo lo devuelve todo, identidad incluida. Sin infraestructura, sin cuentas, totalmente privado. Es la red de seguridad mínima y debe existir desde el inventario (Fase 1).
|
Un botón: **"Guardar una copia de mi banco"** → un único archivo `.tane` (un zip con los datos + fotos + la clave, cifrado con una frase de paso). La persona lo guarda donde quiera: se lo manda a su propio correo, a un USB, a su nube, lo copia a otro móvil. **"Restaurar desde una copia"** en el móvil nuevo lo devuelve todo, identidad incluida. Sin infraestructura, sin cuentas, totalmente privado. Es la red de seguridad mínima y debe existir desde el inventario (Fase 1).
|
||||||
*Contra:* es manual (la gente se olvida) y el archivo es sensible (por eso, cifrado).
|
*Contra:* es manual (la gente se olvida) y el archivo es sensible (por eso, cifrado).
|
||||||
|
|
||||||
### 2. Copia a una carpeta que tú sincronizas *(muy alineado con tu ethos)*
|
### 2. Copia a una carpeta que tú sincronizas *(muy alineado con tu ethos)*
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ keystore), so "no plaintext at rest" holds.
|
||||||
### Why a *separate* database, not a new table in `AppDatabase`
|
### Why a *separate* database, not a new table in `AppDatabase`
|
||||||
|
|
||||||
Chat is **not inventory**. It is an ephemeral, per-device cache of what the
|
Chat is **not inventory**. It is an ephemeral, per-device cache of what the
|
||||||
relays delivered; it never enters an inventory snapshot, a `.tanemaki` backup,
|
relays delivered; it never enters an inventory snapshot, a `.tane` backup,
|
||||||
or the device-to-device sync. Keeping it out of `AppDatabase` means:
|
or the device-to-device sync. Keeping it out of `AppDatabase` means:
|
||||||
|
|
||||||
- It carries **no CRDT metadata** (no HLC `updatedAt`, tombstones, `lastAuthor`,
|
- It carries **no CRDT metadata** (no HLC `updatedAt`, tombstones, `lastAuthor`,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# Tanemaki — Frontera `commons_core` ↔ dominio semillas
|
# Tane — Frontera `commons_core` ↔ dominio semillas
|
||||||
|
|
||||||
*Nota de diseño (discusión). Desarrolla la Parte B de [usability-and-architecture.md](usability-and-architecture.md) y reparte las entidades de [data-model.md](data-model.md) entre el motor genérico y el dominio de semillas.*
|
*Nota de diseño (discusión). Desarrolla la Parte B de [usability-and-architecture.md](usability-and-architecture.md) y reparte las entidades de [data-model.md](data-model.md) entre el motor genérico y el dominio de semillas.*
|
||||||
|
|
||||||
Aquí decidimos **qué vive en el motor común y qué en la app de semillas**, y con qué mecanismo se enchufan. Es la decisión que más amarra el resto, porque fija la costura que permitirá añadir mañana la "biblioteca de cosas" sin tocar Tanemaki.
|
Aquí decidimos **qué vive en el motor común y qué en la app de semillas**, y con qué mecanismo se enchufan. Es la decisión que más amarra el resto, porque fija la costura que permitirá añadir mañana la "biblioteca de cosas" sin tocar Tane.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@ tane/ (repo, hogar: ~/dev/tane)
|
||||||
commons_ui/ (opcional) ← kit de widgets accesibles (targets grandes, foto-first,
|
commons_ui/ (opcional) ← kit de widgets accesibles (targets grandes, foto-first,
|
||||||
icono+palabra) reutilizable por futuras apps.
|
icono+palabra) reutilizable por futuras apps.
|
||||||
apps/
|
apps/
|
||||||
app_seeds/ ← Tanemaki: Species, SeedItem/SeedHolding, germinación,
|
app_seeds/ ← Tane: Species, SeedItem/SeedHolding, germinación,
|
||||||
cosecha, unidades por familia, UI e i18n de semillas.
|
cosecha, unidades por familia, UI e i18n de semillas.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -88,7 +88,7 @@ Drift: tablas del core en `commons_core`, tablas de extensión en `app_seeds`, m
|
||||||
|
|
||||||
## 7. Pragmatismo: no sobre-diseñar el motor ahora
|
## 7. Pragmatismo: no sobre-diseñar el motor ahora
|
||||||
|
|
||||||
- **Construye Tanemaki concreto primero.** Mete en `commons_core` solo lo *ya conocido-compartido* (identidad, Party, Offer, Pledge, trust, sync, discovery). Para `Item/Holding`, empieza con tabla base del core + tabla de extensión de semillas; si al llegar la app de cosas resulta incómodo, **refactorizar dentro del monorepo es barato** (todo el código está junto y se mueve de un tirón).
|
- **Construye Tane concreto primero.** Mete en `commons_core` solo lo *ya conocido-compartido* (identidad, Party, Offer, Pledge, trust, sync, discovery). Para `Item/Holding`, empieza con tabla base del core + tabla de extensión de semillas; si al llegar la app de cosas resulta incómodo, **refactorizar dentro del monorepo es barato** (todo el código está junto y se mueve de un tirón).
|
||||||
- No inventes interfaces genéricas "por si acaso" para partes cuya forma real solo conocerás cuando exista la segunda app. La regla del §1 ("en la duda, al dominio") protege de la abstracción prematura.
|
- No inventes interfaces genéricas "por si acaso" para partes cuya forma real solo conocerás cuando exista la segunda app. La regla del §1 ("en la duda, al dominio") protege de la abstracción prematura.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -110,7 +110,7 @@ tane/
|
||||||
transport (OfferTransport/Nostr), CRDT+sync, geohash.
|
transport (OfferTransport/Nostr), CRDT+sync, geohash.
|
||||||
(Item/Holding se añadirán aquí al llegar la 2ª app.)
|
(Item/Holding se añadirán aquí al llegar la 2ª app.)
|
||||||
apps/
|
apps/
|
||||||
app_seeds/ ← Tanemaki: Variety, Lot, Movement, Species, germinación,
|
app_seeds/ ← Tane: Variety, Lot, Movement, Species, germinación,
|
||||||
cosecha, unidades por familia, UI e i18n, commons_ui embebido.
|
cosecha, unidades por familia, UI e i18n, commons_ui embebido.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Data model (v0 draft)
|
# Tane — Data model (v0 draft)
|
||||||
|
|
||||||
*Technical spec feeding the Flutter/Drift implementation. Written in English (project convention). Implements the concepts discussed in [data-notes.md](data-notes.md) and PLAN §3 / §5-bis.*
|
*Technical spec feeding the Flutter/Drift implementation. Written in English (project convention). Implements the concepts discussed in [data-notes.md](data-notes.md) and PLAN §3 / §5-bis.*
|
||||||
|
|
||||||
|
|
@ -172,7 +172,7 @@ The *shop window*: a signed statement published to the network so others can dis
|
||||||
| `author_key` | TEXT | Publishing public key. |
|
| `author_key` | TEXT | Publishing public key. |
|
||||||
| *(+ common columns)* | | |
|
| *(+ common columns)* | | |
|
||||||
|
|
||||||
A closed deal may produce a `Movement` (`given`) and, if it is an exchange with a return promise, a `Plantare`. The app never processes payments, takes commissions, or holds funds (keeps Tanemaki neutral infrastructure, not a central market operator).
|
A closed deal may produce a `Movement` (`given`) and, if it is an exchange with a return promise, a `Plantare`. The app never processes payments, takes commissions, or holds funds (keeps Tane neutral infrastructure, not a central market operator).
|
||||||
|
|
||||||
## 3. Entity map
|
## 3. Entity map
|
||||||
|
|
||||||
|
|
@ -229,7 +229,7 @@ Together: Drift handles the *local database* migration; the compatibility rules
|
||||||
|
|
||||||
## 7. Interchange export/import (Phase 1) — decided & implemented
|
## 7. Interchange export/import (Phase 1) — decided & implemented
|
||||||
|
|
||||||
The user-triggered **interchange export** (Settings → Backup). Distinct from the future encrypted full backup (`.tanemaki`, [backup-and-recovery.md](backup-and-recovery.md) mechanism 1): the interchange files are the *only* plaintext the app ever writes, and only because the user explicitly asks for them. Import reads the picked file straight into memory — no temp copies.
|
The user-triggered **interchange export** (Settings → Backup). Distinct from the future encrypted full backup (`.tane`, [backup-and-recovery.md](backup-and-recovery.md) mechanism 1): the interchange files are the *only* plaintext the app ever writes, and only because the user explicitly asks for them. Import reads the picked file straight into memory — no temp copies.
|
||||||
|
|
||||||
Two formats, one canonical:
|
Two formats, one canonical:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Notas de diseño: nombres, ciencia, notas y registro de banco
|
# Tane — Notas de diseño: nombres, ciencia, notas y registro de banco
|
||||||
|
|
||||||
*Documento de reflexión previo al modelo de datos formal. Lengua: español (el código irá en inglés).*
|
*Documento de reflexión previo al modelo de datos formal. Lengua: español (el código irá en inglés).*
|
||||||
*Refina y expande la Capa 1 del [PLAN.md](../../PLAN.md) §3.*
|
*Refina y expande la Capa 1 del [PLAN.md](../../PLAN.md) §3.*
|
||||||
|
|
@ -73,7 +73,7 @@ Con eso, el **catálogo empaquetado se licencia CC-BY** (Wikidata CC0 + GBIF CC-
|
||||||
|
|
||||||
### Consecuencia de diseño: los nombres de variedad los pone la comunidad
|
### Consecuencia de diseño: los nombres de variedad los pone la comunidad
|
||||||
|
|
||||||
El **banco de nombres de especie** (capa 4 de §2) viene de Wikidata/GBIF. Pero la **variedad/cultivar** (capa 3, la que más importa a quien guarda semillas) **la teclea la gente**, no una autoridad. Con el tiempo, los nombres de variedad compartidos entre usuarios de Tanemaki (de forma agregada/opcional) van formando **el propio banco folclórico de nombres de Tanemaki** — descentralizado, vivo, y que ninguna base oficial puede darte. Es coherente con todo el proyecto: la ciencia formal se toma prestada (CC0/CC-BY), pero el conocimiento de las variedades tradicionales es de la red, no de un registro.
|
El **banco de nombres de especie** (capa 4 de §2) viene de Wikidata/GBIF. Pero la **variedad/cultivar** (capa 3, la que más importa a quien guarda semillas) **la teclea la gente**, no una autoridad. Con el tiempo, los nombres de variedad compartidos entre usuarios de Tane (de forma agregada/opcional) van formando **el propio banco folclórico de nombres de Tane** — descentralizado, vivo, y que ninguna base oficial puede darte. Es coherente con todo el proyecto: la ciencia formal se toma prestada (CC0/CC-BY), pero el conocimiento de las variedades tradicionales es de la red, no de un registro.
|
||||||
|
|
||||||
Nota (posible puente futuro, no ahora): como anclamos a GBIF/Wikidata, ese banco folclórico —taxonomía de variedades y nombres vernáculos— es justo lo que los portales abiertos de biodiversidad (GBIF, atlas ALA) tienen más flojo. Deja la puerta a un export *opt-in* estilo Darwin Core, con guardas estrictas de privacidad. No es fase ni modelo; detalle e intención en [open-decisions.md](open-decisions.md) §C.
|
Nota (posible puente futuro, no ahora): como anclamos a GBIF/Wikidata, ese banco folclórico —taxonomía de variedades y nombres vernáculos— es justo lo que los portales abiertos de biodiversidad (GBIF, atlas ALA) tienen más flojo. Deja la puerta a un export *opt-in* estilo Darwin Core, con guardas estrictas de privacidad. No es fase ni modelo; detalle e intención en [open-decisions.md](open-decisions.md) §C.
|
||||||
|
|
||||||
|
|
@ -95,7 +95,7 @@ Principios (coherentes con todo lo demás):
|
||||||
- **Fuentes y privacidad.** Prioriza datos abiertos (Wikidata/GBIF/Permapeople). Si en el futuro se usa reconocimiento de foto (sugerir especie a partir de una imagen de semilla/planta) o un servicio de IA para resumir cuidados, es **opcional, con consentimiento** (la foto/el nombre solo salen del dispositivo si la persona lo pide) y **sustituible** (nada atado a un proveedor cerrado).
|
- **Fuentes y privacidad.** Prioriza datos abiertos (Wikidata/GBIF/Permapeople). Si en el futuro se usa reconocimiento de foto (sugerir especie a partir de una imagen de semilla/planta) o un servicio de IA para resumir cuidados, es **opcional, con consentimiento** (la foto/el nombre solo salen del dispositivo si la persona lo pide) y **sustituible** (nada atado a un proveedor cerrado).
|
||||||
- **Datos de conservación** (viabilidad en años, secado, guardado) merecen una pequeña tabla curada por especie/familia, empaquetada y ampliable online — es justo el saber que se está perdiendo y que la app puede ayudar a preservar.
|
- **Datos de conservación** (viabilidad en años, secado, guardado) merecen una pequeña tabla curada por especie/familia, empaquetada y ampliable online — es justo el saber que se está perdiendo y que la app puede ayudar a preservar.
|
||||||
|
|
||||||
Encaje con la arquitectura: la varilla es **de dominio** (`app_seeds`), porque "cuidados" y "conservación" son específicos de semillas; el motor genérico no sabe de eso. Es una de las piezas que más diferencian a Tanemaki de una libreta: reduce a un toque lo que en papel era investigar y copiar a mano.
|
Encaje con la arquitectura: la varilla es **de dominio** (`app_seeds`), porque "cuidados" y "conservación" son específicos de semillas; el motor genérico no sabe de eso. Es una de las piezas que más diferencian a Tane de una libreta: reduce a un toque lo que en papel era investigar y copiar a mano.
|
||||||
|
|
||||||
### ¿Es viable la "varilla mágica" con datos abiertos? Sí
|
### ¿Es viable la "varilla mágica" con datos abiertos? Sí
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Primer sprint (Fase 1: inventario)
|
# Tane — Primer sprint (Fase 1: inventario)
|
||||||
|
|
||||||
*Guía de arranque para desarrollar en **Claude Code** (en la máquina, donde Flutter corre y git funciona). Objetivo: un **inventario usable, offline y cifrado**. Nada de capa social todavía. Convenciones y decisiones en [`../../CLAUDE.md`](../../CLAUDE.md) y [`open-decisions.md`](open-decisions.md).*
|
*Guía de arranque para desarrollar en **Claude Code** (en la máquina, donde Flutter corre y git funciona). Objetivo: un **inventario usable, offline y cifrado**. Nada de capa social todavía. Convenciones y decisiones en [`../../CLAUDE.md`](../../CLAUDE.md) y [`open-decisions.md`](open-decisions.md).*
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Integración opcional de Ğ1 (moneda libre)
|
# Tane — Integración opcional de Ğ1 (moneda libre)
|
||||||
|
|
||||||
*Nota de diseño (discusión). Explora integrar opcionalmente la moneda libre Ğ1 (Duniter) para facilitar intercambios, sin excluir el regalo, el Plantare, el trueque ni otras monedas. Conecta con [sharing-model.md](sharing-model.md) §4 y con [network-trust.md](network-trust.md) §2.*
|
*Nota de diseño (discusión). Explora integrar opcionalmente la moneda libre Ğ1 (Duniter) para facilitar intercambios, sin excluir el regalo, el Plantare, el trueque ni otras monedas. Conecta con [sharing-model.md](sharing-model.md) §4 y con [network-trust.md](network-trust.md) §2.*
|
||||||
|
|
||||||
|
|
@ -6,13 +6,13 @@
|
||||||
|
|
||||||
No es un añadido oportunista: hay **tres coincidencias profundas**.
|
No es un añadido oportunista: hay **tres coincidencias profundas**.
|
||||||
|
|
||||||
1. **Misma red de confianza.** Tanemaki ya adopta una WoT **estilo Duniter** (network-trust §2). Ğ1 *es* esa WoT hecha moneda. Integrarla no es pegar un sistema ajeno: es la misma filosofía expresada como dinero.
|
1. **Misma red de confianza.** Tane ya adopta una WoT **estilo Duniter** (network-trust §2). Ğ1 *es* esa WoT hecha moneda. Integrarla no es pegar un sistema ajeno: es la misma filosofía expresada como dinero.
|
||||||
2. **Misma ética.** Ğ1 es libre, descentralizada, no especulativa (dividendo universal, no acumulativa). Casa con el proyecto donde el euro no llega, y resuena con el espíritu del Plantare ("mantener en circulación, no acaparar").
|
2. **Misma ética.** Ğ1 es libre, descentralizada, no especulativa (dividendo universal, no acumulativa). Casa con el proyecto donde el euro no llega, y resuena con el espíritu del Plantare ("mantener en circulación, no acaparar").
|
||||||
3. **Mismo stack, y experiencia propia.** Duniter v2 (lanzado el 7 de marzo de 2026, sobre Substrate) trae **Ğecko**, cartera móvil en **Flutter** —igual que Tanemaki—, y **Ğ1nkgo**, del propio autor de este proyecto. Hay código Dart/Flutter y conocimiento directo que reutilizar: la integración **no parte de cero**.
|
3. **Mismo stack, y experiencia propia.** Duniter v2 (lanzado el 7 de marzo de 2026, sobre Substrate) trae **Ğecko**, cartera móvil en **Flutter** —igual que Tane—, y **Ğ1nkgo**, del propio autor de este proyecto. Hay código Dart/Flutter y conocimiento directo que reutilizar: la integración **no parte de cero**.
|
||||||
|
|
||||||
## El gradiente de reciprocidad
|
## El gradiente de reciprocidad
|
||||||
|
|
||||||
Tanemaki no elige "regalo vs. dinero": ofrece un **abanico**, del más procomún al más convencional, y la interfaz lo presenta en ese orden (lo comunitario primero):
|
Tane no elige "regalo vs. dinero": ofrece un **abanico**, del más procomún al más convencional, y la interfaz lo presenta en ese orden (lo comunitario primero):
|
||||||
|
|
||||||
**regalo → Plantare (devolver algo similar) → trueque → Ğ1 (moneda libre) → euro (moneda convencional)**
|
**regalo → Plantare (devolver algo similar) → trueque → Ğ1 (moneda libre) → euro (moneda convencional)**
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ Tanemaki no elige "regalo vs. dinero": ofrece un **abanico**, del más procomún
|
||||||
|
|
||||||
## Ğ1 como primer campo de prueba (y solución al arranque en frío)
|
## Ğ1 como primer campo de prueba (y solución al arranque en frío)
|
||||||
|
|
||||||
En la comunidad Ğ1 **ya hay grupos de semillas**, pero lo que falla es justo **la app y la red para intercambiar**. Es decir: existe una comunidad motivada, afín en valores, **ya en red y con confianza montada (la WoT) y con moneda (Ğ1)** — a la que solo le falta la herramienta que Tanemaki construye. Esto convierte a los grupos de semillas de Ğ1 en el **piloto perfecto**:
|
En la comunidad Ğ1 **ya hay grupos de semillas**, pero lo que falla es justo **la app y la red para intercambiar**. Es decir: existe una comunidad motivada, afín en valores, **ya en red y con confianza montada (la WoT) y con moneda (Ğ1)** — a la que solo le falta la herramienta que Tane construye. Esto convierte a los grupos de semillas de Ğ1 en el **piloto perfecto**:
|
||||||
|
|
||||||
- **Resuelve el arranque en frío (hueco 2 de VISION)** para ese subconjunto casi de un plumazo: no hay que crear la comunidad ni la confianza, ya existen; se les da la pieza que falta.
|
- **Resuelve el arranque en frío (hueco 2 de VISION)** para ese subconjunto casi de un plumazo: no hay que crear la comunidad ni la confianza, ya existen; se les da la pieza que falta.
|
||||||
- **Prueba las tres capas a la vez con gente real:** inventario, compartición y —único sitio donde podemos probarlo de verdad— la **integración Ğ1** (niveles 1–3) y la WoT compartida.
|
- **Prueba las tres capas a la vez con gente real:** inventario, compartición y —único sitio donde podemos probarlo de verdad— la **integración Ğ1** (niveles 1–3) y la WoT compartida.
|
||||||
|
|
@ -31,9 +31,9 @@ Estrategia sugerida: **primer piloto dentro de los grupos de semillas de Ğ1**,
|
||||||
## Principios de la integración
|
## Principios de la integración
|
||||||
|
|
||||||
- **Opcional y plural.** Ğ1 es *una* opción más. Nunca obligatoria, nunca el defecto. El regalo y el Plantare siguen siendo de primera clase.
|
- **Opcional y plural.** Ğ1 es *una* opción más. Nunca obligatoria, nunca el defecto. El regalo y el Plantare siguen siendo de primera clase.
|
||||||
- **Sin custodia ni rieles de pago en la app** (coherente con sharing-model §4.3). Tanemaki **no** mueve fondos: anuncia y conecta; el valor se transfiere en la **cartera del usuario** (Ğecko/Cesium²/Ğ1nkgo), fuera de la app. Así seguimos siendo infraestructura neutral, sin KYC/AML.
|
- **Sin custodia ni rieles de pago en la app** (coherente con sharing-model §4.3). Tane **no** mueve fondos: anuncia y conecta; el valor se transfiere en la **cartera del usuario** (Ğecko/Cesium²/Ğ1nkgo), fuera de la app. Así seguimos siendo infraestructura neutral, sin KYC/AML.
|
||||||
- **Inclusión intacta.** Usar Tanemaki **no** exige ser miembro de Ğ1. La persona de 80 que solo cambia tomates no toca Ğ1 jamás. Ğ1 es una **capa opcional** para quien ya está en ese mundo.
|
- **Inclusión intacta.** Usar Tane **no** exige ser miembro de Ğ1. La persona de 80 que solo cambia tomates no toca Ğ1 jamás. Ğ1 es una **capa opcional** para quien ya está en ese mundo.
|
||||||
- **Acoplamiento con cuidado.** Reusar la WoT/identidad de Ğ1 es potente, pero no debe volver a Tanemaki dependiente de Duniter para funcionar. Ğ1 informa/enriquece; no manda.
|
- **Acoplamiento con cuidado.** Reusar la WoT/identidad de Ğ1 es potente, pero no debe volver a Tane dependiente de Duniter para funcionar. Ğ1 informa/enriquece; no manda.
|
||||||
|
|
||||||
## Niveles de integración (de menos a más)
|
## Niveles de integración (de menos a más)
|
||||||
|
|
||||||
|
|
@ -41,19 +41,19 @@ Estrategia sugerida: **primer piloto dentro de los grupos de semillas de Ğ1**,
|
||||||
|
|
||||||
2. **Enlace a la cartera (deep-link).** Botón "Pagar en Ğ1" que abre **Ğecko / Cesium² / Ğ1nkgo** con destinatario e importe ya rellenos (URI de pago). La app no toca fondos; solo entrega el testigo. Riesgo bajo, UX buena — y conoces esos esquemas de URI de primera mano.
|
2. **Enlace a la cartera (deep-link).** Botón "Pagar en Ğ1" que abre **Ğecko / Cesium² / Ğ1nkgo** con destinatario e importe ya rellenos (URI de pago). La app no toca fondos; solo entrega el testigo. Riesgo bajo, UX buena — y conoces esos esquemas de URI de primera mano.
|
||||||
|
|
||||||
3. **Identidad y confianza compartidas (la sinergia profunda).** Como la WoT de Duniter v2 está en cadena e indexada (duniter-squid, GraphQL), Tanemaki podría **opcionalmente** vincular tu identidad Ğ1 e **importar tu pertenencia y certificaciones** como señal de confianza: un miembro Ğ1 llega **pre-avalado** a Tanemaki. Pero manteniendo la WoT propia y ligera para quien no es de Ğ1 (inclusión). Ğ1 como **fuente opcional de confianza que suma**, no como requisito.
|
3. **Identidad y confianza compartidas (la sinergia profunda).** Como la WoT de Duniter v2 está en cadena e indexada (duniter-squid, GraphQL), Tane podría **opcionalmente** vincular tu identidad Ğ1 e **importar tu pertenencia y certificaciones** como señal de confianza: un miembro Ğ1 llega **pre-avalado** a Tane. Pero manteniendo la WoT propia y ligera para quien no es de Ğ1 (inclusión). Ğ1 como **fuente opcional de confianza que suma**, no como requisito.
|
||||||
|
|
||||||
4. **Pago dentro de la app (descartado).** Firmar transferencias Ğ1 desde Tanemaki cruzaría la línea de "sin rieles de pago" y añadiría custodia/complejidad. Mejor el nivel 2 (delegar en la cartera).
|
4. **Pago dentro de la app (descartado).** Firmar transferencias Ğ1 desde Tane cruzaría la línea de "sin rieles de pago" y añadiría custodia/complejidad. Mejor el nivel 2 (delegar en la cartera).
|
||||||
|
|
||||||
## La WoT: independiente pero compatible (respuesta a "¿podría ser compatible?")
|
## La WoT: independiente pero compatible (respuesta a "¿podría ser compatible?")
|
||||||
|
|
||||||
La disyuntiva no es "depender de Ğ1" (fácil, pero excluye a los no-Ğ1 y acopla) contra "independiente" (inclusivo, pero costoso de construir). Hay un **punto medio**, como el correo electrónico —tu propio servidor, pero compatible con SMTP—: **una WoT propia de Tanemaki, estructuralmente compatible con la de Duniter.** Y ser compatible **abarata** lo difícil, porque reutilizas diseño probado y tu propio código.
|
La disyuntiva no es "depender de Ğ1" (fácil, pero excluye a los no-Ğ1 y acopla) contra "independiente" (inclusivo, pero costoso de construir). Hay un **punto medio**, como el correo electrónico —tu propio servidor, pero compatible con SMTP—: **una WoT propia de Tane, estructuralmente compatible con la de Duniter.** Y ser compatible **abarata** lo difícil, porque reutilizas diseño probado y tu propio código.
|
||||||
|
|
||||||
Cómo se logra:
|
Cómo se logra:
|
||||||
|
|
||||||
1. **Mismo primitivo de identidad.** Usar el mismo tipo de clave que Duniter v2 (cuentas Substrate). Así una identidad Ğ1 es técnicamente comprensible por Tanemaki y **reutilizas la cripto de Ğ1nkgo/Ğecko**, sin depender de la red Ğ1.
|
1. **Mismo primitivo de identidad.** Usar el mismo tipo de clave que Duniter v2 (cuentas Substrate). Así una identidad Ğ1 es técnicamente comprensible por Tane y **reutilizas la cripto de Ğ1nkgo/Ğecko**, sin depender de la red Ğ1.
|
||||||
2. **Mismo modelo de certificación.** Modelar la WoT de Tanemaki como la de Duniter (certificaciones firmadas "A avala a B", regla de N certificaciones + distancia). Es una WoT estilo Duniter, pero **tu propia instancia/grafo**. Esto abarata el "hazlo independiente": reutilizas un diseño probado desde 2017, no inventas uno.
|
2. **Mismo modelo de certificación.** Modelar la WoT de Tane como la de Duniter (certificaciones firmadas "A avala a B", regla de N certificaciones + distancia). Es una WoT estilo Duniter, pero **tu propia instancia/grafo**. Esto abarata el "hazlo independiente": reutilizas un diseño probado desde 2017, no inventas uno.
|
||||||
3. **Importar la WoT de Ğ1 en un solo sentido.** Leer el grafo on-chain de Ğ1 (duniter-squid, GraphQL) para *informar* la confianza en Tanemaki: un miembro Ğ1 llega **pre-avalado**. Tanemaki **no escribe** en la cadena de Ğ1 (eso sí acoplaría). Import unidireccional = compatible **sin** dependencia.
|
3. **Importar la WoT de Ğ1 en un solo sentido.** Leer el grafo on-chain de Ğ1 (duniter-squid, GraphQL) para *informar* la confianza en Tane: un miembro Ğ1 llega **pre-avalado**. Tane **no escribe** en la cadena de Ğ1 (eso sí acoplaría). Import unidireccional = compatible **sin** dependencia.
|
||||||
4. **Una sola clave para todo (como en Duniter).** Una única identidad —una clave Duniter-v2/Substrate— hace *todo*: perfil, ofertas, mensajes, certificaciones y, si te opt-in, pagos Ğ1 y pertenencia a la WoT. Nada de claves separadas por función. **Tener la clave ≠ ser miembro de Ğ1:** una persona no-Ğ1 (la abuela) tiene una clave que simplemente **no está certificada** en la WoT (= "desconocida", encaja con network-trust §2) y nunca toca la moneda. Un miembro Ğ1 **reusa su misma clave** y llega pre-avalado. Así, una sola clave *e* inclusión total.
|
4. **Una sola clave para todo (como en Duniter).** Una única identidad —una clave Duniter-v2/Substrate— hace *todo*: perfil, ofertas, mensajes, certificaciones y, si te opt-in, pagos Ğ1 y pertenencia a la WoT. Nada de claves separadas por función. **Tener la clave ≠ ser miembro de Ğ1:** una persona no-Ğ1 (la abuela) tiene una clave que simplemente **no está certificada** en la WoT (= "desconocida", encaja con network-trust §2) y nunca toca la moneda. Un miembro Ğ1 **reusa su misma clave** y llega pre-avalado. Así, una sola clave *e* inclusión total.
|
||||||
|
|
||||||
*Privacidad y peor caso legal:* usar la misma clave enlaza tu actividad de semillas con tu identidad Ğ1 pública. Para la mayoría (tomates en España) es indiferente. Para el caso sensible, la protección real es que **tener no es publicar**: las variedades delicadas viven **locales y cifradas**, y publicar una oferta es opt-in por ítem — así la clave nunca las expone en la red. Como escape adicional, quien *publique* algo sensible y no quiera ligarlo a su Ğ1 puede usar una **clave seudónima distinta** (opción avanzada), pero la norma es **una sola clave**.
|
*Privacidad y peor caso legal:* usar la misma clave enlaza tu actividad de semillas con tu identidad Ğ1 pública. Para la mayoría (tomates en España) es indiferente. Para el caso sensible, la protección real es que **tener no es publicar**: las variedades delicadas viven **locales y cifradas**, y publicar una oferta es opt-in por ítem — así la clave nunca las expone en la red. Como escape adicional, quien *publique* algo sensible y no quiera ligarlo a su Ğ1 puede usar una **clave seudónima distinta** (opción avanzada), pero la norma es **una sola clave**.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Red, confianza y mensajería (capa social descentralizada)
|
# Tane — Red, confianza y mensajería (capa social descentralizada)
|
||||||
|
|
||||||
*Nota de diseño (discusión). Resuelve los huecos 2–6 del anexo de [VISION.md](../../VISION.md): cómo arranca la red, cómo se teje la confianza, quién sostiene el descubrimiento y cómo se comunican las personas. Se apoya en la Capa 3–4 del [PLAN.md](../../PLAN.md) y en [sharing-model.md](sharing-model.md).*
|
*Nota de diseño (discusión). Resuelve los huecos 2–6 del anexo de [VISION.md](../../VISION.md): cómo arranca la red, cómo se teje la confianza, quién sostiene el descubrimiento y cómo se comunican las personas. Se apoya en la Capa 3–4 del [PLAN.md](../../PLAN.md) y en [sharing-model.md](sharing-model.md).*
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Decisiones abiertas y "qué chirría"
|
# Tane — Decisiones abiertas y "qué chirría"
|
||||||
|
|
||||||
*Revisión de conjunto antes de seguir construyendo. Reúne los cabos sueltos repartidos por los docs de diseño, ordenados por cuándo hay que decidirlos, y nombra las tensiones del plan que conviene mirar de frente.*
|
*Revisión de conjunto antes de seguir construyendo. Reúne los cabos sueltos repartidos por los docs de diseño, ordenados por cuándo hay que decidirlos, y nombra las tensiones del plan que conviene mirar de frente.*
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@ Estas fijan `schemaVersion = 1` y el arranque técnico:
|
||||||
|
|
||||||
1. **La capa social es indivisible y grande.** "MVP = inventario + compartición local" subestima que "compartir" de verdad = **ofertas + mensajería + relays + red de confianza**, todo junto e interdependiente. Propuesta: replantear las fases como **(1) inventario** —entregable, sólido, en solitario— y **(2) el salto social** —un bloque grande, no un incremento—. Ser honestos con esto en el plan y en la financiación.
|
1. **La capa social es indivisible y grande.** "MVP = inventario + compartición local" subestima que "compartir" de verdad = **ofertas + mensajería + relays + red de confianza**, todo junto e interdependiente. Propuesta: replantear las fases como **(1) inventario** —entregable, sólido, en solitario— y **(2) el salto social** —un bloque grande, no un incremento—. Ser honestos con esto en el plan y en la financiación.
|
||||||
|
|
||||||
2. **Casi toda la dificultad vive en `commons_core`.** Identidad, sync CRDT, ofertas, pledge, red de confianza, **mensajería**, relays… `app_seeds` es, en comparación, ligero. En el fondo Tanemaki es **infraestructura de procomún** con las semillas como primera aplicación. Es buena noticia para NLnet/NGI Zero (financian infraestructura), pero hay que asumir que lo "sencillo" (semillas) es la punta del iceberg y comunicar el proyecto en consecuencia.
|
2. **Casi toda la dificultad vive en `commons_core`.** Identidad, sync CRDT, ofertas, pledge, red de confianza, **mensajería**, relays… `app_seeds` es, en comparación, ligero. En el fondo Tane es **infraestructura de procomún** con las semillas como primera aplicación. Es buena noticia para NLnet/NGI Zero (financian infraestructura), pero hay que asumir que lo "sencillo" (semillas) es la punta del iceberg y comunicar el proyecto en consecuencia.
|
||||||
|
|
||||||
3. **Apuesta fuerte por Nostr.** Ofertas, mensajes y confianza dependerían de NIPs en evolución (99 / 17 / 85). La abstracción `OfferTransport` amortigua las ofertas, pero mensajería y confianza también se apoyan en Nostr → más acoplamiento del que sugería el plan. Revisar si un solo protocolo lo cubre bien o si conviene aislar también mensajería y confianza tras interfaces.
|
3. **Apuesta fuerte por Nostr.** Ofertas, mensajes y confianza dependerían de NIPs en evolución (99 / 17 / 85). La abstracción `OfferTransport` amortigua las ofertas, pero mensajería y confianza también se apoyan en Nostr → más acoplamiento del que sugería el plan. Revisar si un solo protocolo lo cubre bien o si conviene aislar también mensajería y confianza tras interfaces.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Seguridad y privacidad (modelo de amenaza)
|
# Tane — Seguridad y privacidad (modelo de amenaza)
|
||||||
|
|
||||||
*Nota de diseño (discusión). Nace del "peor caso legal": una persona en un país donde una variedad (p.ej. cannabis) está prohibida debe poder usar la app **sin dejar datos en claro**. Extiende y matiza [backup-and-recovery.md](backup-and-recovery.md) y la postura legal del [PLAN.md](../../PLAN.md) §6.*
|
*Nota de diseño (discusión). Nace del "peor caso legal": una persona en un país donde una variedad (p.ej. cannabis) está prohibida debe poder usar la app **sin dejar datos en claro**. Extiende y matiza [backup-and-recovery.md](backup-and-recovery.md) y la postura legal del [PLAN.md](../../PLAN.md) §6.*
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Modelo de compartición y mercado (nota de diseño)
|
# Tane — Modelo de compartición y mercado (nota de diseño)
|
||||||
|
|
||||||
*Documento de reflexión. Lengua: español (discusión). Desarrolla la Capa 3 del [PLAN.md](../../PLAN.md) §3–§4 y §6, y conecta con el modelo de datos ([data-model.md](data-model.md)).*
|
*Documento de reflexión. Lengua: español (discusión). Desarrolla la Capa 3 del [PLAN.md](../../PLAN.md) §3–§4 y §6, y conecta con el modelo de datos ([data-model.md](data-model.md)).*
|
||||||
|
|
||||||
|
|
@ -56,13 +56,13 @@ Permitir vender es legítimo y realista —hay quien produce semilla artesanal,
|
||||||
### 4.2 Legal: vender reengancha justo el problema Kokopelli
|
### 4.2 Legal: vender reengancha justo el problema Kokopelli
|
||||||
Esto es lo delicado. La **venta** de variedades tradicionales no registradas es exactamente lo que multó a Kokopelli; el regalo/trueque entre aficionados o agricultores está mucho más protegido (PLAN §6). Al añadir "venta" aumentas la exposición legal *de tus usuarios*. Mitigaciones de diseño:
|
Esto es lo delicado. La **venta** de variedades tradicionales no registradas es exactamente lo que multó a Kokopelli; el regalo/trueque entre aficionados o agricultores está mucho más protegido (PLAN §6). Al añadir "venta" aumentas la exposición legal *de tus usuarios*. Mitigaciones de diseño:
|
||||||
|
|
||||||
- **Tanemaki no es un mercado, es infraestructura neutral.** La app no opera el mercado, no publica un catálogo central, no pone en venta nada: son las personas, entre iguales (como flohmarkt). Esta neutralidad es la mejor defensa (replica por qué Kokopelli fue vulnerable —venta + operador central identificable— y evita ambas).
|
- **Tane no es un mercado, es infraestructura neutral.** La app no opera el mercado, no publica un catálogo central, no pone en venta nada: son las personas, entre iguales (como flohmarkt). Esta neutralidad es la mejor defensa (replica por qué Kokopelli fue vulnerable —venta + operador central identificable— y evita ambas).
|
||||||
- **Aviso contextual por región, no policía.** Al marcar una Offer como "venta", la app puede mostrar una nota suave y dependiente del país ("vender semilla de variedades no registradas puede estar restringido en tu país"). Informar, no bloquear, no vigilar.
|
- **Aviso contextual por región, no policía.** Al marcar una Offer como "venta", la app puede mostrar una nota suave y dependiente del país ("vender semilla de variedades no registradas puede estar restringido en tu país"). Informar, no bloquear, no vigilar.
|
||||||
- **La venta prioriza el marco de conservación/compartición** en el discurso y el diseño; el dinero es una opción, no la portada.
|
- **La venta prioriza el marco de conservación/compartición** en el discurso y el diseño; el dinero es una opción, no la portada.
|
||||||
|
|
||||||
### 4.3 Nada de rieles de pago (esto es innegociable)
|
### 4.3 Nada de rieles de pago (esto es innegociable)
|
||||||
- **La app NO procesa pagos, NO cobra comisión, NO retiene dinero, NO muestra publicidad.** El pago se acuerda **directamente entre las personas** (efectivo, su propia transferencia, lo que sea), *fuera* de la app.
|
- **La app NO procesa pagos, NO cobra comisión, NO retiene dinero, NO muestra publicidad.** El pago se acuerda **directamente entre las personas** (efectivo, su propia transferencia, lo que sea), *fuera* de la app.
|
||||||
- Meter pagos dentro convertiría a Tanemaki en operador central: obligaciones KYC/AML, custodia de fondos, y reintroduce justo la centralización que se quiere evitar. Además mataría la sostenibilidad (§7: financiación por subvenciones/donaciones, no por comisiones).
|
- Meter pagos dentro convertiría a Tane en operador central: obligaciones KYC/AML, custodia de fondos, y reintroduce justo la centralización que se quiere evitar. Además mataría la sostenibilidad (§7: financiación por subvenciones/donaciones, no por comisiones).
|
||||||
- Resultado: es el "efecto Wallapop sin Wallapop" también para la venta — anuncia y conecta; el dinero cambia de manos entre personas.
|
- Resultado: es el "efecto Wallapop sin Wallapop" también para la venta — anuncia y conecta; el dinero cambia de manos entre personas.
|
||||||
|
|
||||||
### 4.4 Representación del precio
|
### 4.4 Representación del precio
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Estrategia de pruebas (casi-TDD, sin depender de pruebas manuales)
|
# Tane — Estrategia de pruebas (casi-TDD, sin depender de pruebas manuales)
|
||||||
|
|
||||||
*Convención del proyecto. Objetivo: **cada comportamiento cubierto por una prueba automática**; las pruebas manuales son la excepción, no la red de seguridad.*
|
*Convención del proyecto. Objetivo: **cada comportamiento cubierto por una prueba automática**; las pruebas manuales son la excepción, no la red de seguridad.*
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Usabilidad y generalización (nota de diseño)
|
# Tane — Usabilidad y generalización (nota de diseño)
|
||||||
|
|
||||||
*Documento de reflexión. Lengua: español (discusión). Afecta a la estructura del primer commit de código, por eso conviene decidirlo ahora.*
|
*Documento de reflexión. Lengua: español (discusión). Afecta a la estructura del primer commit de código, por eso conviene decidirlo ahora.*
|
||||||
|
|
||||||
|
|
@ -56,17 +56,17 @@ Prior art que lo confirma: el software de "Library of Things" (Lend Engine, myTu
|
||||||
|
|
||||||
### La reconciliación: generaliza el MOTOR, no el PRODUCTO
|
### La reconciliación: generaliza el MOTOR, no el PRODUCTO
|
||||||
|
|
||||||
Usabilidad y reutilización apuntan **a la misma respuesta**. Tanemaki (semillas) y la futura app de cosas son **productos separados, simples, monotema**, cada uno con su nombre y su cara; por debajo comparten un **motor común** que resuelve una sola vez la fontanería P2P/confianza/préstamo. Generalizas donde nadie lo ve (el engine), no donde todo el mundo lo sufre (el producto).
|
Usabilidad y reutilización apuntan **a la misma respuesta**. Tane (semillas) y la futura app de cosas son **productos separados, simples, monotema**, cada uno con su nombre y su cara; por debajo comparten un **motor común** que resuelve una sola vez la fontanería P2P/confianza/préstamo. Generalizas donde nadie lo ve (el engine), no donde todo el mundo lo sufre (el producto).
|
||||||
|
|
||||||
### ¿Ahora o después? "Diseña para generalizar, implementa uno"
|
### ¿Ahora o después? "Diseña para generalizar, implementa uno"
|
||||||
|
|
||||||
- **Construye solo Tanemaki ahora.** No hagas la plataforma genérica de forma especulativa (riesgo de abstracción prematura: te sale la abstracción equivocada).
|
- **Construye solo Tane ahora.** No hagas la plataforma genérica de forma especulativa (riesgo de abstracción prematura: te sale la abstracción equivocada).
|
||||||
- **Pero estructura el repo desde el primer commit como workspace** con un paquete `core/` + `app_seeds/`, respetando una **costura de dominio limpia**. Extraer más adelante la app de cosas es barato si la costura se respeta; retrofitear un motor genérico dentro de un monolito es caro.
|
- **Pero estructura el repo desde el primer commit como workspace** con un paquete `core/` + `app_seeds/`, respetando una **costura de dominio limpia**. Extraer más adelante la app de cosas es barato si la costura se respeta; retrofitear un motor genérico dentro de un monolito es caro.
|
||||||
- **En `core` va solo lo obviamente compartido** (identidad, sync, `Offer`, `Party`, confianza, `Pledge`/registro de préstamo). Lo específico de semillas (`Species`, germinación, cosecha) se queda en el dominio de semillas. Se sube más a `core` solo cuando la segunda app revele la forma real compartida (regla del tres — pero el núcleo P2P/confianza/pagaré es conocido-compartido de antemano, así que extraerlo ya está justificado).
|
- **En `core` va solo lo obviamente compartido** (identidad, sync, `Offer`, `Party`, confianza, `Pledge`/registro de préstamo). Lo específico de semillas (`Species`, germinación, cosecha) se queda en el dominio de semillas. Se sube más a `core` solo cuando la segunda app revele la forma real compartida (regla del tres — pero el núcleo P2P/confianza/pagaré es conocido-compartido de antemano, así que extraerlo ya está justificado).
|
||||||
|
|
||||||
### Cómo generalizan las entidades (mapa)
|
### Cómo generalizan las entidades (mapa)
|
||||||
|
|
||||||
| Genérico (`core`) | Semillas (Tanemaki) | Cosas (futura) |
|
| Genérico (`core`) | Semillas (Tane) | Cosas (futura) |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `Item` / holding | `Variety` + `Lot` | herramienta / objeto |
|
| `Item` / holding | `Variety` + `Lot` | herramienta / objeto |
|
||||||
| `Offer` (+ tipo **`lend`**: devolver *el mismo* objeto) | gift/exchange/sale/wanted | lend/gift/sale/wanted |
|
| `Offer` (+ tipo **`lend`**: devolver *el mismo* objeto) | gift/exchange/sale/wanted | lend/gift/sale/wanted |
|
||||||
|
|
@ -78,7 +78,7 @@ Nota: el `Plantare` es el caso semillas de un concepto genérico **`Pledge`** (p
|
||||||
|
|
||||||
### Nombres
|
### Nombres
|
||||||
|
|
||||||
- **Tanemaki** = el producto de semillas.
|
- **Tane** = el producto de semillas.
|
||||||
- El **núcleo** conviene que tenga nombre neutro. Tu organización **Comunes** encaja de libro ("motor del procomún"): p.ej. paquete `commons_core` o similar. La app de cosas tendrá su propio nombre cuando llegue.
|
- El **núcleo** conviene que tenga nombre neutro. Tu organización **Comunes** encaja de libro ("motor del procomún"): p.ej. paquete `commons_core` o similar. La app de cosas tendrá su propio nombre cuando llegue.
|
||||||
|
|
||||||
### Consecuencia técnica inmediata (por eso se decide ahora)
|
### Consecuencia técnica inmediata (por eso se decide ahora)
|
||||||
|
|
@ -86,14 +86,14 @@ Nota: el `Plantare` es el caso semillas de un concepto genérico **`Pledge`** (p
|
||||||
El **primer commit de código** no es "una app Flutter", sino un **workspace** (pub workspaces / melos) con:
|
El **primer commit de código** no es "una app Flutter", sino un **workspace** (pub workspaces / melos) con:
|
||||||
|
|
||||||
```
|
```
|
||||||
tanemaki/ (repo)
|
tane/ (repo)
|
||||||
packages/
|
packages/
|
||||||
commons_core/ ← identidad, sync, Offer, Party, Pledge, confianza, discovery
|
commons_core/ ← identidad, sync, Offer, Party, Pledge, confianza, discovery
|
||||||
apps/
|
apps/
|
||||||
app_seeds/ ← Tanemaki: Species, germinación, cosecha, UI de semillas, i18n
|
app_seeds/ ← Tane: Species, germinación, cosecha, UI de semillas, i18n
|
||||||
```
|
```
|
||||||
|
|
||||||
Drift: tablas de `core` + tablas de dominio de semillas, con las migraciones versionadas (§5 del modelo) por paquete. Así, el día que exista `app_things`, reusa `commons_core` sin tocar Tanemaki.
|
Drift: tablas de `core` + tablas de dominio de semillas, con las migraciones versionadas (§5 del modelo) por paquete. Así, el día que exista `app_things`, reusa `commons_core` sin tocar Tane.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Translating Tanemaki
|
# Translating Tane
|
||||||
|
|
||||||
Tanemaki is multilingual **by design** — international, not any-country-first
|
Tane is multilingual **by design** — international, not any-country-first
|
||||||
(see the golden rules in [`../CLAUDE.md`](../CLAUDE.md)). Translations live as
|
(see the golden rules in [`../CLAUDE.md`](../CLAUDE.md)). Translations live as
|
||||||
one JSON file per locale, a format Weblate (and any translation platform that
|
one JSON file per locale, a format Weblate (and any translation platform that
|
||||||
speaks nested JSON) handles natively.
|
speaks nested JSON) handles natively.
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,9 @@ Con el Plantare, quien recibe promete devolver semilla cuando pueda. Y como para
|
||||||
|
|
||||||
## Texto para "Acerca de" (una sola pantalla)
|
## Texto para "Acerca de" (una sola pantalla)
|
||||||
|
|
||||||
> **Tanemaki** (種まき, "sembrar" en japonés) es una app libre para cuidar y compartir semillas tradicionales.
|
> **Tane** (種 "semilla"; de *tanemaki*, 種まき, "sembrar" en japonés) es una app libre para cuidar y compartir semillas tradicionales.
|
||||||
>
|
>
|
||||||
> Las semillas son un bien común: llevan miles de años pasando de mano en mano, mejorando en cada vuelta. Tanemaki te ayuda a seguir esa cadena: tu inventario vive cifrado en tu dispositivo —sin cuenta, sin internet, sin rastreadores— y compartes solo lo que eliges, con quien está cerca, sin intermediarios.
|
> Las semillas son un bien común: llevan miles de años pasando de mano en mano, mejorando en cada vuelta. Tane te ayuda a seguir esa cadena: tu inventario vive cifrado en tu dispositivo —sin cuenta, sin internet, sin rastreadores— y compartes solo lo que eliges, con quien está cerca, sin intermediarios.
|
||||||
>
|
>
|
||||||
> Heredera del Plantare (2009) y de las tradiciones de ayuda mutua que le dan nombre. Software libre (AGPL-3.0), sin publicidad, sin comisiones, sin venta de datos.
|
> Heredera del Plantare (2009) y de las tradiciones de ayuda mutua que le dan nombre. Software libre (AGPL-3.0), sin publicidad, sin comisiones, sin venta de datos.
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Tanemaki — Una introducción para humanos
|
# Tane — Una introducción para humanos
|
||||||
|
|
||||||
*Texto de presentación (web, ferias, folleto). Deriva de [VISION.md](../VISION.md); esta versión es más narrativa y para todos los públicos.*
|
*Texto de presentación (web, ferias, folleto). Deriva de [VISION.md](../VISION.md); esta versión es más narrativa y para todos los públicos.*
|
||||||
|
|
||||||
|
|
@ -16,11 +16,11 @@ Ese común está en peligro. Hoy un puñado de empresas controla buena parte de
|
||||||
|
|
||||||
Y hay algo más extraño todavía: compartir semillas, la práctica más antigua y natural de la agricultura, se ha vuelto en algunos sitios sospechoso. En Francia multaron a la asociación Kokopelli por distribuir variedades no inscritas en el catálogo oficial. La ley tiende a proteger lo registrado y lo privativo, y a arrinconar lo que siempre fue de todos.
|
Y hay algo más extraño todavía: compartir semillas, la práctica más antigua y natural de la agricultura, se ha vuelto en algunos sitios sospechoso. En Francia multaron a la asociación Kokopelli por distribuir variedades no inscritas en el catálogo oficial. La ley tiende a proteger lo registrado y lo privativo, y a arrinconar lo que siempre fue de todos.
|
||||||
|
|
||||||
No hace falta gritar consignas para ver el problema: cuando guardar e intercambiar semilla necesita valentía, algo se ha torcido. Tanemaki nace para destorcerlo un poco.
|
No hace falta gritar consignas para ver el problema: cuando guardar e intercambiar semilla necesita valentía, algo se ha torcido. Tane nace para destorcerlo un poco.
|
||||||
|
|
||||||
## Qué es Tanemaki
|
## Qué es Tane
|
||||||
|
|
||||||
**Tanemaki** (種まき, "sembrar" en japonés; para las amigas, **Tane**) es una app libre y gratuita para **cuidar y compartir semillas tradicionales**. Hace dos cosas, y las hace fáciles:
|
**Tane** (種, "semilla" en japonés; nombre completo **Tanemaki**, 種まき, "sembrar") es una app libre y gratuita para **cuidar y compartir semillas tradicionales**. Hace dos cosas, y las hace fáciles:
|
||||||
|
|
||||||
**Gestionar.** Tu banco de semillas en el bolsillo: qué tienes, de qué año, cuánto, de dónde vino. Con el nombre que tú usas —no hace falta saber latín—. Añades una semilla con una foto y un nombre en veinte segundos; la profundidad (procedencia, germinación, notas, nombre científico) está ahí solo si la quieres. Sirve igual para quien guarda cuatro sobres en un cajón que para un banco comunitario con cientos de variedades.
|
**Gestionar.** Tu banco de semillas en el bolsillo: qué tienes, de qué año, cuánto, de dónde vino. Con el nombre que tú usas —no hace falta saber latín—. Añades una semilla con una foto y un nombre en veinte segundos; la profundidad (procedencia, germinación, notas, nombre científico) está ahí solo si la quieres. Sirve igual para quien guarda cuatro sobres en un cajón que para un banco comunitario con cientos de variedades.
|
||||||
|
|
||||||
|
|
@ -37,7 +37,7 @@ No hace falta gritar consignas para ver el problema: cuando guardar e intercambi
|
||||||
|
|
||||||
## Tu privacidad, en serio
|
## Tu privacidad, en serio
|
||||||
|
|
||||||
Tanemaki está construida al revés de casi todas las apps:
|
Tane está construida al revés de casi todas las apps:
|
||||||
|
|
||||||
- **Funciona sin internet y sin cuenta.** No te pedimos correo, ni teléfono, ni nombre. Abres la app y siembras.
|
- **Funciona sin internet y sin cuenta.** No te pedimos correo, ni teléfono, ni nombre. Abres la app y siembras.
|
||||||
- **Tus datos viven en tu dispositivo**, cifrados. No hay servidor central que los guarde, los analice o los venda. No hay publicidad ni rastreadores.
|
- **Tus datos viven en tu dispositivo**, cifrados. No hay servidor central que los guarde, los analice o los venda. No hay publicidad ni rastreadores.
|
||||||
|
|
@ -49,20 +49,20 @@ Y todo el código es **software libre** (AGPL): cualquiera puede leerlo, mejorar
|
||||||
|
|
||||||
## El Plantare: prestar semilla hace crecer el común
|
## El Plantare: prestar semilla hace crecer el común
|
||||||
|
|
||||||
Cuando das semillas con Tanemaki, puedes acompañarlas de un **Plantare**: una promesa —heredera de un pagaré de papel real que circuló en 2009— de devolver, cuando puedas, una cantidad parecida de semilla libre. No es una deuda con intereses; es un compromiso de mantener la semilla viva y en movimiento. Y aquí está la magia: para devolver semilla hay que cultivarla, y al cultivarla se multiplica. **Cada préstamo agranda el común en vez de agotarlo.** Es exactamente lo contrario de la semilla diseñada para no reproducirse.
|
Cuando das semillas con Tane, puedes acompañarlas de un **Plantare**: una promesa —heredera de un pagaré de papel real que circuló en 2009— de devolver, cuando puedas, una cantidad parecida de semilla libre. No es una deuda con intereses; es un compromiso de mantener la semilla viva y en movimiento. Y aquí está la magia: para devolver semilla hay que cultivarla, y al cultivarla se multiplica. **Cada préstamo agranda el común en vez de agotarlo.** Es exactamente lo contrario de la semilla diseñada para no reproducirse.
|
||||||
|
|
||||||
## Una herencia
|
## Una herencia
|
||||||
|
|
||||||
El nombre es un homenaje a las tradiciones japonesas de ayuda mutua en torno al arroz: el *yui*, el trabajo comunitario compartido, y el *tanomoshi*, los fondos vecinales de reciprocidad. Tanemaki continúa el camino del Plantare (BAH-Semillero, 2009) y de la cultura libre. No inventamos nada: le ponemos bolsillo a algo muy viejo.
|
El nombre es un homenaje a las tradiciones japonesas de ayuda mutua en torno al arroz: el *yui*, el trabajo comunitario compartido, y el *tanomoshi*, los fondos vecinales de reciprocidad. Tane continúa el camino del Plantare (BAH-Semillero, 2009) y de la cultura libre. No inventamos nada: le ponemos bolsillo a algo muy viejo.
|
||||||
|
|
||||||
## Para quién
|
## Para quién
|
||||||
|
|
||||||
Para todo el mundo, de los 10 a los 80 años. Para la persona mayor que guarda la semilla de toda la vida y apenas usa el móvil, y para quien coordina un banco comunitario y necesita potencia. Para hortelanas y hortelanos, redes de semillas, colectivos agroecológicos, ferias de intercambio, escuelas.
|
Para todo el mundo, de los 10 a los 80 años. Para la persona mayor que guarda la semilla de toda la vida y apenas usa el móvil, y para quien coordina un banco comunitario y necesita potencia. Para hortelanas y hortelanos, redes de semillas, colectivos agroecológicos, ferias de intercambio, escuelas.
|
||||||
|
|
||||||
Tanemaki no tiene modelo de negocio, y es a propósito: sin cuotas, sin comisiones, sin venta de datos. Se sostiene con trabajo voluntario, comunidad y financiación de bien común.
|
Tane no tiene modelo de negocio, y es a propósito: sin cuotas, sin comisiones, sin venta de datos. Se sostiene con trabajo voluntario, comunidad y financiación de bien común.
|
||||||
|
|
||||||
## Siembra
|
## Siembra
|
||||||
|
|
||||||
Una semilla guardada en un cajón es un recuerdo. Una semilla compartida es un futuro. Tanemaki existe para lo segundo: para que guardar sea fácil, compartir sea seguro, y la memoria de diez mil años siga pasando de mano en mano.
|
Una semilla guardada en un cajón es un recuerdo. Una semilla compartida es un futuro. Tane existe para lo segundo: para que guardar sea fácil, compartir sea seguro, y la memoria de diez mil años siga pasando de mano en mano.
|
||||||
|
|
||||||
*Las semillas del conocimiento libre ya están plantadas.*
|
*Las semillas del conocimiento libre ya están plantadas.*
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="robots" content="noindex,nofollow">
|
<meta name="robots" content="noindex,nofollow">
|
||||||
<title>Tanemaki — Material mockups (v3)</title>
|
<title>Tane — Material mockups (v3)</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500&family=Roboto+Mono:wght@400;500&family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0..1,0" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500&family=Roboto+Mono:wght@400;500&family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0..1,0" rel="stylesheet">
|
||||||
|
|
@ -23,9 +23,9 @@
|
||||||
<div style="min-height:100vh;background:#CFE0C4;padding:48px 40px 72px;font-family:Roboto">
|
<div style="min-height:100vh;background:#CFE0C4;padding:48px 40px 72px;font-family:Roboto">
|
||||||
<header style="max-width:1200px;margin:0 auto 44px">
|
<header style="max-width:1200px;margin:0 auto 44px">
|
||||||
<div style="display:flex;align-items:center;gap:16px">
|
<div style="display:flex;align-items:center;gap:16px">
|
||||||
<img src="seedees_material3_assets/logo.png" alt="Tanemaki" style="height:52px;width:auto;display:block">
|
<img src="seedees_material3_assets/logo.png" alt="Tane" style="height:52px;width:auto;display:block">
|
||||||
<div>
|
<div>
|
||||||
<div style="font:700 30px Roboto;color:#1a2a13;letter-spacing:-.01em">Tanemaki · Material mockups</div>
|
<div style="font:700 30px Roboto;color:#1a2a13;letter-spacing:-.01em">Tane · Material mockups</div>
|
||||||
<div style="font:400 15px Roboto;color:#38492e;margin-top:2px">Aligned with the real app — green app bars, botanical content, search, batches and action sheets.</div>
|
<div style="font:400 15px Roboto;color:#38492e;margin-top:2px">Aligned with the real app — green app bars, botanical content, search, batches and action sheets.</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
<figure data-screen-label="00 Home" style="margin:0;width:360px">
|
<figure data-screen-label="00 Home" style="margin:0;width:360px">
|
||||||
<div style="width:360px;height:740px;border-radius:34px;overflow:hidden;background:#E7F1E0;box-shadow:0 22px 55px -14px rgba(20,45,15,.4);border:1px solid rgba(0,0,0,.06);display:flex;flex-direction:column">
|
<div style="width:360px;height:740px;border-radius:34px;overflow:hidden;background:#E7F1E0;box-shadow:0 22px 55px -14px rgba(20,45,15,.4);border:1px solid rgba(0,0,0,.06);display:flex;flex-direction:column">
|
||||||
<div style="height:26px;background:#2E6E28;display:flex;justify-content:space-between;align-items:center;padding:0 16px;color:#fff;font:500 12px Roboto"><span>9:41</span><span style="display:flex;gap:5px;align-items:center"><span class="ms" style="font-size:15px">network_wifi</span><span class="ms" style="font-size:15px">signal_cellular_alt</span><span class="ms fill" style="font-size:15px">battery_full</span></span></div>
|
<div style="height:26px;background:#2E6E28;display:flex;justify-content:space-between;align-items:center;padding:0 16px;color:#fff;font:500 12px Roboto"><span>9:41</span><span style="display:flex;gap:5px;align-items:center"><span class="ms" style="font-size:15px">network_wifi</span><span class="ms" style="font-size:15px">signal_cellular_alt</span><span class="ms fill" style="font-size:15px">battery_full</span></span></div>
|
||||||
<header style="height:60px;background:#3E8C38;display:flex;align-items:center;gap:6px;padding:0 8px;color:#fff"><span class="ms" style="font-size:24px;color:#fff;width:44px;height:44px;display:flex;align-items:center;justify-content:center">menu</span><span style="flex:1;font:500 20px Roboto;color:#fff;margin-left:6px">Tanemaki</span><span class="ms" style="font-size:23px;color:#fff;width:42px;height:42px;display:flex;align-items:center;justify-content:center">search</span></header>
|
<header style="height:60px;background:#3E8C38;display:flex;align-items:center;gap:6px;padding:0 8px;color:#fff"><span class="ms" style="font-size:24px;color:#fff;width:44px;height:44px;display:flex;align-items:center;justify-content:center">menu</span><span style="flex:1;font:500 20px Roboto;color:#fff;margin-left:6px">Tane</span><span class="ms" style="font-size:23px;color:#fff;width:42px;height:42px;display:flex;align-items:center;justify-content:center">search</span></header>
|
||||||
<div style="flex:1;overflow:hidden;position:relative;display:flex;flex-direction:column">
|
<div style="flex:1;overflow:hidden;position:relative;display:flex;flex-direction:column">
|
||||||
<div style="position:absolute;inset:0;overflow:hidden;pointer-events:none;opacity:.5">
|
<div style="position:absolute;inset:0;overflow:hidden;pointer-events:none;opacity:.5">
|
||||||
<span class="sk" style="position:absolute;left:16px;bottom:74px;font-size:56px;color:#C3D9B2">a</span>
|
<span class="sk" style="position:absolute;left:16px;bottom:74px;font-size:56px;color:#C3D9B2">a</span>
|
||||||
|
|
@ -45,8 +45,8 @@
|
||||||
<span class="sk" style="position:absolute;right:124px;bottom:122px;font-size:44px;color:#C3D9B2">b</span>
|
<span class="sk" style="position:absolute;right:124px;bottom:122px;font-size:44px;color:#C3D9B2">b</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0 24px 28px;position:relative;z-index:1">
|
<div style="flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0 24px 28px;position:relative;z-index:1">
|
||||||
<div style="width:128px;height:128px;border-radius:50%;background:#DDF3CE;display:flex;align-items:center;justify-content:center;margin-bottom:10px"><img src="seedees_material3_assets/logo.png" alt="Tanemaki" style="height:84px;width:auto;display:block"></div>
|
<div style="width:128px;height:128px;border-radius:50%;background:#DDF3CE;display:flex;align-items:center;justify-content:center;margin-bottom:10px"><img src="seedees_material3_assets/logo.png" alt="Tane" style="height:84px;width:auto;display:block"></div>
|
||||||
<div style="font:500 26px Roboto;color:#1a2a13;letter-spacing:-.01em">Tanemaki</div>
|
<div style="font:500 26px Roboto;color:#1a2a13;letter-spacing:-.01em">Tane</div>
|
||||||
<div style="font:400 14px Roboto;color:#55624a;margin-bottom:34px">Share and grow local seeds</div>
|
<div style="font:400 14px Roboto;color:#55624a;margin-bottom:34px">Share and grow local seeds</div>
|
||||||
<button style="width:100%;border:none;cursor:pointer;background:#2f7d34;color:#fff;border-radius:18px;padding:19px 22px;display:flex;align-items:center;gap:16px;box-shadow:0 4px 12px rgba(47,125,52,.28);margin-bottom:16px;text-align:left"><span style="width:44px;height:44px;border-radius:50%;background:rgba(255,255,255,.18);display:flex;align-items:center;justify-content:center"><span class="ms" style="font-size:26px">inventory_2</span></span><span style="flex:1"><span style="display:block;font:500 19px Roboto">Your inventory</span><span style="display:block;font:400 13px Roboto;opacity:.85">Manage your seeds</span></span></button>
|
<button style="width:100%;border:none;cursor:pointer;background:#2f7d34;color:#fff;border-radius:18px;padding:19px 22px;display:flex;align-items:center;gap:16px;box-shadow:0 4px 12px rgba(47,125,52,.28);margin-bottom:16px;text-align:left"><span style="width:44px;height:44px;border-radius:50%;background:rgba(255,255,255,.18);display:flex;align-items:center;justify-content:center"><span class="ms" style="font-size:26px">inventory_2</span></span><span style="flex:1"><span style="display:block;font:500 19px Roboto">Your inventory</span><span style="display:block;font:400 13px Roboto;opacity:.85">Manage your seeds</span></span></button>
|
||||||
<button style="width:100%;border:1px solid #B8C4AC;cursor:pointer;background:#fff;color:#1b2416;border-radius:18px;padding:19px 22px;display:flex;align-items:center;gap:16px;text-align:left"><span style="width:44px;height:44px;border-radius:50%;background:#DDF3CE;display:flex;align-items:center;justify-content:center"><span class="ms" style="font-size:26px;color:#2f7d34">storefront</span></span><span style="flex:1"><span style="display:block;font:500 19px Roboto">Open market</span><span style="display:block;font:400 13px Roboto;color:#7b8a70">Browse and exchange</span></span><span style="font:500 11px Roboto;color:#b3bda8;letter-spacing:.05em">SOON</span></button>
|
<button style="width:100%;border:1px solid #B8C4AC;cursor:pointer;background:#fff;color:#1b2416;border-radius:18px;padding:19px 22px;display:flex;align-items:center;gap:16px;text-align:left"><span style="width:44px;height:44px;border-radius:50%;background:#DDF3CE;display:flex;align-items:center;justify-content:center"><span class="ms" style="font-size:26px;color:#2f7d34">storefront</span></span><span style="flex:1"><span style="display:block;font:500 19px Roboto">Open market</span><span style="display:block;font:400 13px Roboto;color:#7b8a70">Browse and exchange</span></span><span style="font:500 11px Roboto;color:#b3bda8;letter-spacing:.05em">SOON</span></button>
|
||||||
|
|
@ -159,7 +159,7 @@
|
||||||
<div style="flex:1;position:relative;overflow:hidden">
|
<div style="flex:1;position:relative;overflow:hidden">
|
||||||
<div style="position:absolute;inset:0;background:rgba(20,35,12,.4)"></div>
|
<div style="position:absolute;inset:0;background:rgba(20,35,12,.4)"></div>
|
||||||
<div style="position:absolute;top:0;left:0;bottom:0;width:300px;background:#fff;box-shadow:2px 0 24px rgba(0,0,0,.2);display:flex;flex-direction:column">
|
<div style="position:absolute;top:0;left:0;bottom:0;width:300px;background:#fff;box-shadow:2px 0 24px rgba(0,0,0,.2);display:flex;flex-direction:column">
|
||||||
<div style="display:flex;align-items:center;gap:12px;padding:18px 22px 16px;border-bottom:1px solid #E4E9DD"><img src="seedees_material3_assets/logo.png" alt="" style="height:34px;width:auto"><span style="font:700 22px Roboto;color:#2f7d34;letter-spacing:-.01em">Tanemaki</span></div>
|
<div style="display:flex;align-items:center;gap:12px;padding:18px 22px 16px;border-bottom:1px solid #E4E9DD"><img src="seedees_material3_assets/logo.png" alt="" style="height:34px;width:auto"><span style="font:700 22px Roboto;color:#2f7d34;letter-spacing:-.01em">Tane</span></div>
|
||||||
<nav style="flex:1;padding:8px 0">
|
<nav style="flex:1;padding:8px 0">
|
||||||
<div style="display:flex;align-items:center;gap:18px;height:52px;padding:0 22px;color:#1b2416"><span class="sk" style="font-size:23px;color:#2f7d34">b</span><span style="font:500 15px Roboto">Inventory</span></div>
|
<div style="display:flex;align-items:center;gap:18px;height:52px;padding:0 22px;color:#1b2416"><span class="sk" style="font-size:23px;color:#2f7d34">b</span><span style="font:500 15px Roboto">Inventory</span></div>
|
||||||
<div style="display:flex;align-items:center;gap:18px;height:52px;padding:0 22px;color:#9aa88f;border-bottom:1px solid #E4E9DD"><span class="ms" style="font-size:23px">storefront</span><span style="font:400 15px Roboto;flex:1">Market</span><span style="font:500 11px Roboto;color:#b3bda8;letter-spacing:.05em">SOON</span></div>
|
<div style="display:flex;align-items:center;gap:18px;height:52px;padding:0 22px;color:#9aa88f;border-bottom:1px solid #E4E9DD"><span class="ms" style="font-size:23px">storefront</span><span style="font:400 15px Roboto;flex:1">Market</span><span style="font:500 11px Roboto;color:#b3bda8;letter-spacing:.05em">SOON</span></div>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
# Tanemaki — qué es
|
# Tane — qué es
|
||||||
|
|
||||||
> *Texto divulgativo para todos los públicos, sin dar por sabidos los conceptos.
|
> *Texto divulgativo para todos los públicos, sin dar por sabidos los conceptos.*
|
||||||
> El nombre es **provisional**.*
|
|
||||||
|
|
||||||
**Tanemaki** · *(nombre provisional)* — apodo: **Tane**.
|
**Tane** (種) es «semilla» en japonés; el nombre completo, *tanemaki* (種まき), es «sembrar / esparcir semillas».
|
||||||
種まき significa «sembrar semillas» en japonés.
|
|
||||||
|
|
||||||
## En una frase
|
## En una frase
|
||||||
|
|
||||||
|
|
@ -63,9 +61,9 @@ persona con unos sobres guardados. Para todas las edades, de 10 a 80.
|
||||||
|
|
||||||
## El nombre
|
## El nombre
|
||||||
|
|
||||||
種まき («tanemaki») es «sembrar semillas» en japonés, un guiño a viejas costumbres de ayuda
|
**Tane** quiere decir «semilla» (種). Viene de *tanemaki* (種まき), «sembrar semillas» en
|
||||||
mutua entre vecinos (compartir el trabajo, ahorrar juntos). El apodo, «Tane», quiere decir
|
japonés, un guiño a viejas costumbres de ayuda mutua entre vecinos (compartir el trabajo,
|
||||||
«semilla». **El nombre es provisional** y todavía puede cambiar.
|
ahorrar juntos).
|
||||||
|
|
||||||
## En qué punto está y cómo ayudar
|
## En qué punto está y cómo ayudar
|
||||||
|
|
||||||
|
|
@ -77,5 +75,5 @@ a proyectos de interés común.
|
||||||
---
|
---
|
||||||
|
|
||||||
> *Idea de fondo: las semillas de toda la vida son un patrimonio de la humanidad —de todos
|
> *Idea de fondo: las semillas de toda la vida son un patrimonio de la humanidad —de todos
|
||||||
> y de nadie—. Frente a quien quiere privatizarlas, Tanemaki busca ponértelo fácil para
|
> y de nadie—. Frente a quien quiere privatizarlas, Tane busca ponértelo fácil para
|
||||||
> guardarlas, multiplicarlas y hacerlas circular.*
|
> guardarlas, multiplicarlas y hacerlas circular.*
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Releasing Tanemaki (manual, no CI yet)
|
# Releasing Tane (manual, no CI yet)
|
||||||
|
|
||||||
Block 1 ships as a self-contained Android app (desktop builds also work). There
|
Block 1 ships as a self-contained Android app (desktop builds also work). There
|
||||||
is no release pipeline yet — this page is the by-hand checklist.
|
is no release pipeline yet — this page is the by-hand checklist.
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ abstract final class RecoveryCode {
|
||||||
static String decode(String code) {
|
static String decode(String code) {
|
||||||
final compact = code.toUpperCase().replaceAll(RegExp(r'[\s-]'), '');
|
final compact = code.toUpperCase().replaceAll(RegExp(r'[\s-]'), '');
|
||||||
if (!compact.startsWith(_tag)) {
|
if (!compact.startsWith(_tag)) {
|
||||||
throw const FormatException('Not a Tanemaki recovery code');
|
throw const FormatException('Not a Tane recovery code');
|
||||||
}
|
}
|
||||||
final payload = compact.substring(_tag.length);
|
final payload = compact.substring(_tag.length);
|
||||||
final bytes = _unbase32(payload);
|
final bytes = _unbase32(payload);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class NostrRatingTransport implements RatingTransport {
|
||||||
|
|
||||||
final NostrChannel _conn;
|
final NostrChannel _conn;
|
||||||
|
|
||||||
/// Custom Tanemaki rating kind (addressable range, next to trust's 30777).
|
/// Custom Tane rating kind (addressable range, next to trust's 30777).
|
||||||
static const kindRating = 30778;
|
static const kindRating = 30778;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class NostrTrustTransport implements TrustTransport {
|
||||||
|
|
||||||
final NostrChannel _conn;
|
final NostrChannel _conn;
|
||||||
|
|
||||||
/// Custom Tanemaki certification kind (addressable range).
|
/// Custom Tane certification kind (addressable range).
|
||||||
static const kindCertification = 30777;
|
static const kindCertification = 30777;
|
||||||
|
|
||||||
int get _now => DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
int get _now => DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Pub workspace root for Tanemaki (Tane).
|
# Pub workspace root for Tane.
|
||||||
# Members share a single lockfile and .dart_tool. See CLAUDE.md and
|
# Members share a single lockfile and .dart_tool. See CLAUDE.md and
|
||||||
# docs/design/core-domain-boundary.md for the package boundary rules.
|
# docs/design/core-domain-boundary.md for the package boundary rules.
|
||||||
name: tane_workspace
|
name: tane_workspace
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue