feat(links): surface source repo + Weblate links on site and in app
- site: set sourceURL (git.comunes.org/comunes/tane) and weblateURL (translate.comunes.org/projects/tane) — activates footer + collaborate links - app About screen: add 'Source code' and 'Help translate' link tiles - i18n: add about.sourceCode / about.translate / about.translateSubtitle (en base + es/pt/fr/de/ast; ja falls back to base), regenerate slang - docs: add TRANSLATIONS.md runbook for the Weblate app component + git token + slang-regeneration workflow
This commit is contained in:
parent
ea17ced152
commit
f844d7c4f6
16 changed files with 187 additions and 16 deletions
87
TRANSLATIONS.md
Normal file
87
TRANSLATIONS.md
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
# Translating Tane (Weblate)
|
||||||
|
|
||||||
|
Runbook for the translation setup. Written so another agent (or a human) can
|
||||||
|
reproduce it without prior context.
|
||||||
|
|
||||||
|
Tane is translated on **[translate.comunes.org/projects/tane](https://translate.comunes.org/projects/tane/)**
|
||||||
|
(a self-hosted **Weblate 5.x**, docker-compose at `/data/weblate` on host **tesla**).
|
||||||
|
The links to the repo and to Weblate are shown both on the landing site
|
||||||
|
(`site/config.toml` → `sourceURL`, `weblateURL`) and inside the app (About screen).
|
||||||
|
|
||||||
|
## What is translatable
|
||||||
|
|
||||||
|
| Surface | Files | Format | Base locale | Locales today |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| **App** (`app` component) | `apps/app_seeds/lib/i18n/*.i18n.json` | JSON **nested** (slang, `{param}` placeholders) | `en` | en, es, pt, fr, de, ast, ja |
|
||||||
|
| **Site** (deferred) | `site/i18n/*.toml` | Hugo TOML | `en` | en, es |
|
||||||
|
|
||||||
|
Only source strings live in git; app strings use `slang`, so `strings.g.dart` /
|
||||||
|
`strings_*.g.dart` are **generated** (see the slang caveat below).
|
||||||
|
|
||||||
|
## Git connection
|
||||||
|
|
||||||
|
- Repo: `https://git.comunes.org/comunes/tane.git`, branch **`main`** (private
|
||||||
|
Gitea/Forgejo behind Cloudflare).
|
||||||
|
- Weblate must use **HTTPS + an access token** — SSH port 22 is not reachable
|
||||||
|
through Cloudflare, so the stored `Comunes Translations` SSH key is unusable here.
|
||||||
|
- Repository URL in Weblate:
|
||||||
|
`https://<user>:<token>@git.comunes.org/comunes/tane.git`
|
||||||
|
where `<token>` is a git.comunes.org access token with **read + write** on
|
||||||
|
`comunes/tane` (Weblate pushes translations back). Generate it in Gitea/Forgejo
|
||||||
|
→ Settings → Applications.
|
||||||
|
|
||||||
|
## The `app` component (create once)
|
||||||
|
|
||||||
|
The `tane` project already exists on Weblate. Add a component (admin UI
|
||||||
|
*Add new translation component*, or `docker exec weblate-weblate-1 weblate shell`):
|
||||||
|
|
||||||
|
| Field | Value |
|
||||||
|
|---|---|
|
||||||
|
| Project | `tane` |
|
||||||
|
| Name / slug | `app` |
|
||||||
|
| Source code repository | `https://<user>:<token>@git.comunes.org/comunes/tane.git` |
|
||||||
|
| Repository branch | `main` |
|
||||||
|
| File mask | `apps/app_seeds/lib/i18n/*.i18n.json` |
|
||||||
|
| Monolingual base language file | `apps/app_seeds/lib/i18n/en.i18n.json` |
|
||||||
|
| Template for new translations | `apps/app_seeds/lib/i18n/en.i18n.json` |
|
||||||
|
| File format | **JSON nested structure** (`json-nested`) — not flat `json` |
|
||||||
|
| Source language | English (`en`) |
|
||||||
|
|
||||||
|
Weblate auto-discovers the existing locales from the mask. Leave push-on-commit on
|
||||||
|
so translations flow back to `main`.
|
||||||
|
|
||||||
|
Sanity check after creating it:
|
||||||
|
```sh
|
||||||
|
docker exec weblate-weblate-1 weblate shell -c \
|
||||||
|
'from weblate.trans.models import Project; \
|
||||||
|
print(Project.objects.get(slug="tane").component_set.count())' # expect 1
|
||||||
|
```
|
||||||
|
Then edit a test string in the UI and confirm a commit lands on
|
||||||
|
`git.comunes.org/comunes/tane` (`main`) — that validates the token has write.
|
||||||
|
|
||||||
|
## slang regeneration caveat (important)
|
||||||
|
|
||||||
|
Weblate only edits the `*.i18n.json` sources. The committed `strings.g.dart` /
|
||||||
|
`strings_*.g.dart` are generated and go **stale** on every Weblate commit, and
|
||||||
|
there is no CI to regenerate them. Before a release, a maintainer must:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git pull
|
||||||
|
cd apps/app_seeds && dart run slang # regenerates strings*.g.dart
|
||||||
|
cd ../.. && dart analyze # workspace gate
|
||||||
|
git add -A && git commit -m "chore(i18n): regenerate slang after Weblate sync"
|
||||||
|
```
|
||||||
|
|
||||||
|
(Adding a new source string manually? Same steps — edit `en.i18n.json` first, then
|
||||||
|
regenerate. `fallback_strategy: base_locale` means locales missing a key show the
|
||||||
|
English text until translators fill it in.)
|
||||||
|
|
||||||
|
## Site component — deferred
|
||||||
|
|
||||||
|
Weblate 5.x has no native Hugo-TOML format, and the site has only EN/ES (~3 KB).
|
||||||
|
Two options, decide later:
|
||||||
|
- (a) Switch Hugo i18n to a Weblate-supported format (Hugo also reads
|
||||||
|
`i18n/*.json` / `*.yaml`), then add a matching `site` component.
|
||||||
|
- (b) Keep translating the two `site/i18n/*.toml` files by hand.
|
||||||
|
|
||||||
|
For now the site is translated manually; only the `app` component is on Weblate.
|
||||||
|
|
@ -146,6 +146,9 @@
|
||||||
"license": "Llicencia",
|
"license": "Llicencia",
|
||||||
"licenseValue": "AGPL-3.0",
|
"licenseValue": "AGPL-3.0",
|
||||||
"website": "Sitiu web",
|
"website": "Sitiu web",
|
||||||
|
"sourceCode": "Códigu fonte",
|
||||||
|
"translate": "Ayuda a traducir",
|
||||||
|
"translateSubtitle": "Ayuda a traer Tane a la to llingua",
|
||||||
"openSourceLicenses": "Llicencies de códigu abiertu",
|
"openSourceLicenses": "Llicencies de códigu abiertu",
|
||||||
"openSourceLicensesSubtitle": "Biblioteques de terceros y les sos llicencies",
|
"openSourceLicensesSubtitle": "Biblioteques de terceros y les sos llicencies",
|
||||||
"copyright": "© {years} Asociación Comunes, baxo AGPLv3"
|
"copyright": "© {years} Asociación Comunes, baxo AGPLv3"
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,9 @@
|
||||||
"license": "Lizenz",
|
"license": "Lizenz",
|
||||||
"licenseValue": "AGPL-3.0",
|
"licenseValue": "AGPL-3.0",
|
||||||
"website": "Webseite",
|
"website": "Webseite",
|
||||||
|
"sourceCode": "Quellcode",
|
||||||
|
"translate": "Beim Übersetzen helfen",
|
||||||
|
"translateSubtitle": "Hilf, Tane in deine Sprache zu bringen",
|
||||||
"openSourceLicenses": "Open-Source-Lizenzen",
|
"openSourceLicenses": "Open-Source-Lizenzen",
|
||||||
"openSourceLicensesSubtitle": "Bibliotheken von Drittanbietern und ihre Lizenzen",
|
"openSourceLicensesSubtitle": "Bibliotheken von Drittanbietern und ihre Lizenzen",
|
||||||
"copyright": "© {years} Comunes Association, unter AGPLv3"
|
"copyright": "© {years} Comunes Association, unter AGPLv3"
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,9 @@
|
||||||
"license": "License",
|
"license": "License",
|
||||||
"licenseValue": "AGPL-3.0",
|
"licenseValue": "AGPL-3.0",
|
||||||
"website": "Website",
|
"website": "Website",
|
||||||
|
"sourceCode": "Source code",
|
||||||
|
"translate": "Help translate",
|
||||||
|
"translateSubtitle": "Help bring Tane to your language",
|
||||||
"openSourceLicenses": "Open-source licenses",
|
"openSourceLicenses": "Open-source licenses",
|
||||||
"openSourceLicensesSubtitle": "Third-party libraries and their licenses",
|
"openSourceLicensesSubtitle": "Third-party libraries and their licenses",
|
||||||
"copyright": "© {years} Comunes Association, under AGPLv3"
|
"copyright": "© {years} Comunes Association, under AGPLv3"
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,9 @@
|
||||||
"license": "Licencia",
|
"license": "Licencia",
|
||||||
"licenseValue": "AGPL-3.0",
|
"licenseValue": "AGPL-3.0",
|
||||||
"website": "Sitio web",
|
"website": "Sitio web",
|
||||||
|
"sourceCode": "Código fuente",
|
||||||
|
"translate": "Ayuda a traducir",
|
||||||
|
"translateSubtitle": "Ayuda a traer Tane a tu idioma",
|
||||||
"openSourceLicenses": "Licencias de código abierto",
|
"openSourceLicenses": "Licencias de código abierto",
|
||||||
"openSourceLicensesSubtitle": "Bibliotecas de terceros y sus licencias",
|
"openSourceLicensesSubtitle": "Bibliotecas de terceros y sus licencias",
|
||||||
"copyright": "© {years} Asociación Comunes, bajo AGPLv3"
|
"copyright": "© {years} Asociación Comunes, bajo AGPLv3"
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,9 @@
|
||||||
"license": "Licence",
|
"license": "Licence",
|
||||||
"licenseValue": "AGPL-3.0",
|
"licenseValue": "AGPL-3.0",
|
||||||
"website": "Site web",
|
"website": "Site web",
|
||||||
|
"sourceCode": "Code source",
|
||||||
|
"translate": "Aider à traduire",
|
||||||
|
"translateSubtitle": "Aidez à traduire Tane dans votre langue",
|
||||||
"openSourceLicenses": "Licences open source",
|
"openSourceLicenses": "Licences open source",
|
||||||
"openSourceLicensesSubtitle": "Bibliothèques tiers et leurs licences",
|
"openSourceLicensesSubtitle": "Bibliothèques tiers et leurs licences",
|
||||||
"copyright": "© {years} Association Comunes, sous AGPLv3"
|
"copyright": "© {years} Association Comunes, sous AGPLv3"
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,9 @@
|
||||||
"license": "Licença",
|
"license": "Licença",
|
||||||
"licenseValue": "AGPL-3.0",
|
"licenseValue": "AGPL-3.0",
|
||||||
"website": "Sítio web",
|
"website": "Sítio web",
|
||||||
|
"sourceCode": "Código-fonte",
|
||||||
|
"translate": "Ajuda a traduzir",
|
||||||
|
"translateSubtitle": "Ajuda a trazer o Tane para o teu idioma",
|
||||||
"openSourceLicenses": "Licenças de código aberto",
|
"openSourceLicenses": "Licenças de código aberto",
|
||||||
"openSourceLicensesSubtitle": "Bibliotecas de terceiros e as suas licenças",
|
"openSourceLicensesSubtitle": "Bibliotecas de terceiros e as suas licenças",
|
||||||
"copyright": "© {years} Associação Comunes, sob AGPLv3"
|
"copyright": "© {years} Associação Comunes, sob AGPLv3"
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
/// To regenerate, run: `dart run slang`
|
/// To regenerate, run: `dart run slang`
|
||||||
///
|
///
|
||||||
/// Locales: 7
|
/// Locales: 7
|
||||||
/// Strings: 3454 (493 per locale)
|
/// Strings: 3472 (496 per locale)
|
||||||
///
|
///
|
||||||
/// Built on 2026-07-15 at 13:17 UTC
|
/// Built on 2026-07-15 at 17:09 UTC
|
||||||
|
|
||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint, unused_import
|
// ignore_for_file: type=lint, unused_import
|
||||||
|
|
|
||||||
|
|
@ -328,6 +328,9 @@ class _Translations$about$ast extends Translations$about$en {
|
||||||
@override String get license => 'Llicencia';
|
@override String get license => 'Llicencia';
|
||||||
@override String get licenseValue => 'AGPL-3.0';
|
@override String get licenseValue => 'AGPL-3.0';
|
||||||
@override String get website => 'Sitiu web';
|
@override String get website => 'Sitiu web';
|
||||||
|
@override String get sourceCode => 'Códigu fonte';
|
||||||
|
@override String get translate => 'Ayuda a traducir';
|
||||||
|
@override String get translateSubtitle => 'Ayuda a traer Tane a la to llingua';
|
||||||
@override String get openSourceLicenses => 'Llicencies de códigu abiertu';
|
@override String get openSourceLicenses => 'Llicencies de códigu abiertu';
|
||||||
@override String get openSourceLicensesSubtitle => 'Biblioteques de terceros y les sos llicencies';
|
@override String get openSourceLicensesSubtitle => 'Biblioteques de terceros y les sos llicencies';
|
||||||
@override String copyright({required Object years}) => '© ${years} Asociación Comunes, baxo AGPLv3';
|
@override String copyright({required Object years}) => '© ${years} Asociación Comunes, baxo AGPLv3';
|
||||||
|
|
@ -1536,6 +1539,9 @@ extension on TranslationsAst {
|
||||||
'about.license' => 'Llicencia',
|
'about.license' => 'Llicencia',
|
||||||
'about.licenseValue' => 'AGPL-3.0',
|
'about.licenseValue' => 'AGPL-3.0',
|
||||||
'about.website' => 'Sitiu web',
|
'about.website' => 'Sitiu web',
|
||||||
|
'about.sourceCode' => 'Códigu fonte',
|
||||||
|
'about.translate' => 'Ayuda a traducir',
|
||||||
|
'about.translateSubtitle' => 'Ayuda a traer Tane a la to llingua',
|
||||||
'about.openSourceLicenses' => 'Llicencies de códigu abiertu',
|
'about.openSourceLicenses' => 'Llicencies de códigu abiertu',
|
||||||
'about.openSourceLicensesSubtitle' => 'Biblioteques de terceros y les sos llicencies',
|
'about.openSourceLicensesSubtitle' => 'Biblioteques de terceros y les sos llicencies',
|
||||||
'about.copyright' => ({required Object years}) => '© ${years} Asociación Comunes, baxo AGPLv3',
|
'about.copyright' => ({required Object years}) => '© ${years} Asociación Comunes, baxo AGPLv3',
|
||||||
|
|
@ -1923,11 +1929,11 @@ extension on TranslationsAst {
|
||||||
'handover.promiseReceived' => 'Voi devolver semiente',
|
'handover.promiseReceived' => 'Voi devolver semiente',
|
||||||
'sale.title' => 'Ventes',
|
'sale.title' => 'Ventes',
|
||||||
'sale.help' => 'Rexistra semilla vendida o mercada — dineru, Ğ1 o cualquier moneda. Un modelu aparte del regalu y del Plantare. Enxamás se cobra comisión poles semilles.',
|
'sale.help' => 'Rexistra semilla vendida o mercada — dineru, Ğ1 o cualquier moneda. Un modelu aparte del regalu y del Plantare. Enxamás se cobra comisión poles semilles.',
|
||||||
|
_ => null,
|
||||||
|
} ?? switch (path) {
|
||||||
'sale.add' => 'Rexistrar venta',
|
'sale.add' => 'Rexistrar venta',
|
||||||
'sale.empty' => 'Entá nun hai ventes. Anota equí lo que vendes o merques.',
|
'sale.empty' => 'Entá nun hai ventes. Anota equí lo que vendes o merques.',
|
||||||
'sale.iSold' => 'Vendí',
|
'sale.iSold' => 'Vendí',
|
||||||
_ => null,
|
|
||||||
} ?? switch (path) {
|
|
||||||
'sale.iBought' => 'Mercué',
|
'sale.iBought' => 'Mercué',
|
||||||
'sale.direction' => '¿Vendes o merques?',
|
'sale.direction' => '¿Vendes o merques?',
|
||||||
'sale.counterparty' => '¿Con quién?',
|
'sale.counterparty' => '¿Con quién?',
|
||||||
|
|
|
||||||
|
|
@ -329,6 +329,9 @@ class _Translations$about$de extends Translations$about$en {
|
||||||
@override String get license => 'Lizenz';
|
@override String get license => 'Lizenz';
|
||||||
@override String get licenseValue => 'AGPL-3.0';
|
@override String get licenseValue => 'AGPL-3.0';
|
||||||
@override String get website => 'Webseite';
|
@override String get website => 'Webseite';
|
||||||
|
@override String get sourceCode => 'Quellcode';
|
||||||
|
@override String get translate => 'Beim Übersetzen helfen';
|
||||||
|
@override String get translateSubtitle => 'Hilf, Tane in deine Sprache zu bringen';
|
||||||
@override String get openSourceLicenses => 'Open-Source-Lizenzen';
|
@override String get openSourceLicenses => 'Open-Source-Lizenzen';
|
||||||
@override String get openSourceLicensesSubtitle => 'Bibliotheken von Drittanbietern und ihre Lizenzen';
|
@override String get openSourceLicensesSubtitle => 'Bibliotheken von Drittanbietern und ihre Lizenzen';
|
||||||
@override String copyright({required Object years}) => '© ${years} Comunes Association, unter AGPLv3';
|
@override String copyright({required Object years}) => '© ${years} Comunes Association, unter AGPLv3';
|
||||||
|
|
@ -1533,6 +1536,9 @@ extension on TranslationsDe {
|
||||||
'about.license' => 'Lizenz',
|
'about.license' => 'Lizenz',
|
||||||
'about.licenseValue' => 'AGPL-3.0',
|
'about.licenseValue' => 'AGPL-3.0',
|
||||||
'about.website' => 'Webseite',
|
'about.website' => 'Webseite',
|
||||||
|
'about.sourceCode' => 'Quellcode',
|
||||||
|
'about.translate' => 'Beim Übersetzen helfen',
|
||||||
|
'about.translateSubtitle' => 'Hilf, Tane in deine Sprache zu bringen',
|
||||||
'about.openSourceLicenses' => 'Open-Source-Lizenzen',
|
'about.openSourceLicenses' => 'Open-Source-Lizenzen',
|
||||||
'about.openSourceLicensesSubtitle' => 'Bibliotheken von Drittanbietern und ihre Lizenzen',
|
'about.openSourceLicensesSubtitle' => 'Bibliotheken von Drittanbietern und ihre Lizenzen',
|
||||||
'about.copyright' => ({required Object years}) => '© ${years} Comunes Association, unter AGPLv3',
|
'about.copyright' => ({required Object years}) => '© ${years} Comunes Association, unter AGPLv3',
|
||||||
|
|
@ -1919,11 +1925,11 @@ extension on TranslationsDe {
|
||||||
'sale.empty' => 'Noch keine Verkäufe. Notiere hier, was du verkaufst oder kaufst.',
|
'sale.empty' => 'Noch keine Verkäufe. Notiere hier, was du verkaufst oder kaufst.',
|
||||||
'sale.iSold' => 'Ich verkaufte',
|
'sale.iSold' => 'Ich verkaufte',
|
||||||
'sale.iBought' => 'Ich kaufte',
|
'sale.iBought' => 'Ich kaufte',
|
||||||
|
_ => null,
|
||||||
|
} ?? switch (path) {
|
||||||
'sale.direction' => 'Verkauft oder gekauft?',
|
'sale.direction' => 'Verkauft oder gekauft?',
|
||||||
'sale.counterparty' => 'Mit wem?',
|
'sale.counterparty' => 'Mit wem?',
|
||||||
'sale.counterpartyHint' => 'Eine Person oder ein Kollektiv (optional)',
|
'sale.counterpartyHint' => 'Eine Person oder ein Kollektiv (optional)',
|
||||||
_ => null,
|
|
||||||
} ?? switch (path) {
|
|
||||||
'sale.amount' => 'Betrag',
|
'sale.amount' => 'Betrag',
|
||||||
'sale.currency' => 'Währung',
|
'sale.currency' => 'Währung',
|
||||||
'sale.currencyHint' => '€, Ğ1, Stunden… (optional)',
|
'sale.currencyHint' => '€, Ğ1, Stunden… (optional)',
|
||||||
|
|
|
||||||
|
|
@ -577,6 +577,15 @@ class Translations$about$en {
|
||||||
/// en: 'Website'
|
/// en: 'Website'
|
||||||
String get website => 'Website';
|
String get website => 'Website';
|
||||||
|
|
||||||
|
/// en: 'Source code'
|
||||||
|
String get sourceCode => 'Source code';
|
||||||
|
|
||||||
|
/// en: 'Help translate'
|
||||||
|
String get translate => 'Help translate';
|
||||||
|
|
||||||
|
/// en: 'Help bring Tane to your language'
|
||||||
|
String get translateSubtitle => 'Help bring Tane to your language';
|
||||||
|
|
||||||
/// en: 'Open-source licenses'
|
/// en: 'Open-source licenses'
|
||||||
String get openSourceLicenses => 'Open-source licenses';
|
String get openSourceLicenses => 'Open-source licenses';
|
||||||
|
|
||||||
|
|
@ -2721,6 +2730,9 @@ extension on Translations {
|
||||||
'about.license' => 'License',
|
'about.license' => 'License',
|
||||||
'about.licenseValue' => 'AGPL-3.0',
|
'about.licenseValue' => 'AGPL-3.0',
|
||||||
'about.website' => 'Website',
|
'about.website' => 'Website',
|
||||||
|
'about.sourceCode' => 'Source code',
|
||||||
|
'about.translate' => 'Help translate',
|
||||||
|
'about.translateSubtitle' => 'Help bring Tane to your language',
|
||||||
'about.openSourceLicenses' => 'Open-source licenses',
|
'about.openSourceLicenses' => 'Open-source licenses',
|
||||||
'about.openSourceLicensesSubtitle' => 'Third-party libraries and their licenses',
|
'about.openSourceLicensesSubtitle' => 'Third-party libraries and their licenses',
|
||||||
'about.copyright' => ({required Object years}) => '© ${years} Comunes Association, under AGPLv3',
|
'about.copyright' => ({required Object years}) => '© ${years} Comunes Association, under AGPLv3',
|
||||||
|
|
@ -3107,11 +3119,11 @@ extension on Translations {
|
||||||
'plantare.returnSimilar' => 'A similar amount of seed',
|
'plantare.returnSimilar' => 'A similar amount of seed',
|
||||||
'plantare.returnSimilarNote' => 'open-pollinated · non-GMO · organically grown',
|
'plantare.returnSimilarNote' => 'open-pollinated · non-GMO · organically grown',
|
||||||
'plantare.returnWork' => 'Some hours of work',
|
'plantare.returnWork' => 'Some hours of work',
|
||||||
|
_ => null,
|
||||||
|
} ?? switch (path) {
|
||||||
'plantare.returnOther' => 'Something else',
|
'plantare.returnOther' => 'Something else',
|
||||||
'plantare.workHoursLabel' => 'How many hours?',
|
'plantare.workHoursLabel' => 'How many hours?',
|
||||||
'plantare.proposalsSection' => 'Waiting for your reply',
|
'plantare.proposalsSection' => 'Waiting for your reply',
|
||||||
_ => null,
|
|
||||||
} ?? switch (path) {
|
|
||||||
'plantare.incomingFrom' => ({required Object name}) => '${name} proposes a Plantaré',
|
'plantare.incomingFrom' => ({required Object name}) => '${name} proposes a Plantaré',
|
||||||
'plantare.accept' => 'Accept & sign',
|
'plantare.accept' => 'Accept & sign',
|
||||||
'plantare.declineAction' => 'Decline',
|
'plantare.declineAction' => 'Decline',
|
||||||
|
|
|
||||||
|
|
@ -328,6 +328,9 @@ class _Translations$about$es extends Translations$about$en {
|
||||||
@override String get license => 'Licencia';
|
@override String get license => 'Licencia';
|
||||||
@override String get licenseValue => 'AGPL-3.0';
|
@override String get licenseValue => 'AGPL-3.0';
|
||||||
@override String get website => 'Sitio web';
|
@override String get website => 'Sitio web';
|
||||||
|
@override String get sourceCode => 'Código fuente';
|
||||||
|
@override String get translate => 'Ayuda a traducir';
|
||||||
|
@override String get translateSubtitle => 'Ayuda a traer Tane a tu idioma';
|
||||||
@override String get openSourceLicenses => 'Licencias de código abierto';
|
@override String get openSourceLicenses => 'Licencias de código abierto';
|
||||||
@override String get openSourceLicensesSubtitle => 'Bibliotecas de terceros y sus licencias';
|
@override String get openSourceLicensesSubtitle => 'Bibliotecas de terceros y sus licencias';
|
||||||
@override String copyright({required Object years}) => '© ${years} Asociación Comunes, bajo AGPLv3';
|
@override String copyright({required Object years}) => '© ${years} Asociación Comunes, bajo AGPLv3';
|
||||||
|
|
@ -1561,6 +1564,9 @@ extension on TranslationsEs {
|
||||||
'about.license' => 'Licencia',
|
'about.license' => 'Licencia',
|
||||||
'about.licenseValue' => 'AGPL-3.0',
|
'about.licenseValue' => 'AGPL-3.0',
|
||||||
'about.website' => 'Sitio web',
|
'about.website' => 'Sitio web',
|
||||||
|
'about.sourceCode' => 'Código fuente',
|
||||||
|
'about.translate' => 'Ayuda a traducir',
|
||||||
|
'about.translateSubtitle' => 'Ayuda a traer Tane a tu idioma',
|
||||||
'about.openSourceLicenses' => 'Licencias de código abierto',
|
'about.openSourceLicenses' => 'Licencias de código abierto',
|
||||||
'about.openSourceLicensesSubtitle' => 'Bibliotecas de terceros y sus licencias',
|
'about.openSourceLicensesSubtitle' => 'Bibliotecas de terceros y sus licencias',
|
||||||
'about.copyright' => ({required Object years}) => '© ${years} Asociación Comunes, bajo AGPLv3',
|
'about.copyright' => ({required Object years}) => '© ${years} Asociación Comunes, bajo AGPLv3',
|
||||||
|
|
@ -1948,11 +1954,11 @@ extension on TranslationsEs {
|
||||||
'plantare.returnSimilarNote' => 'polinización abierta · no transgénica · cultivada en ecológico',
|
'plantare.returnSimilarNote' => 'polinización abierta · no transgénica · cultivada en ecológico',
|
||||||
'plantare.returnWork' => 'Unas horas de trabajo',
|
'plantare.returnWork' => 'Unas horas de trabajo',
|
||||||
'plantare.returnOther' => 'Otra cosa',
|
'plantare.returnOther' => 'Otra cosa',
|
||||||
|
_ => null,
|
||||||
|
} ?? switch (path) {
|
||||||
'plantare.workHoursLabel' => '¿Cuántas horas?',
|
'plantare.workHoursLabel' => '¿Cuántas horas?',
|
||||||
'plantare.proposalsSection' => 'Esperando tu respuesta',
|
'plantare.proposalsSection' => 'Esperando tu respuesta',
|
||||||
'plantare.incomingFrom' => ({required Object name}) => '${name} te propone un Plantaré',
|
'plantare.incomingFrom' => ({required Object name}) => '${name} te propone un Plantaré',
|
||||||
_ => null,
|
|
||||||
} ?? switch (path) {
|
|
||||||
'plantare.accept' => 'Aceptar y firmar',
|
'plantare.accept' => 'Aceptar y firmar',
|
||||||
'plantare.declineAction' => 'Rechazar',
|
'plantare.declineAction' => 'Rechazar',
|
||||||
'plantare.declineReasonHint' => 'Motivo (opcional)',
|
'plantare.declineReasonHint' => 'Motivo (opcional)',
|
||||||
|
|
|
||||||
|
|
@ -329,6 +329,9 @@ class _Translations$about$fr extends Translations$about$en {
|
||||||
@override String get license => 'Licence';
|
@override String get license => 'Licence';
|
||||||
@override String get licenseValue => 'AGPL-3.0';
|
@override String get licenseValue => 'AGPL-3.0';
|
||||||
@override String get website => 'Site web';
|
@override String get website => 'Site web';
|
||||||
|
@override String get sourceCode => 'Code source';
|
||||||
|
@override String get translate => 'Aider à traduire';
|
||||||
|
@override String get translateSubtitle => 'Aidez à traduire Tane dans votre langue';
|
||||||
@override String get openSourceLicenses => 'Licences open source';
|
@override String get openSourceLicenses => 'Licences open source';
|
||||||
@override String get openSourceLicensesSubtitle => 'Bibliothèques tiers et leurs licences';
|
@override String get openSourceLicensesSubtitle => 'Bibliothèques tiers et leurs licences';
|
||||||
@override String copyright({required Object years}) => '© ${years} Association Comunes, sous AGPLv3';
|
@override String copyright({required Object years}) => '© ${years} Association Comunes, sous AGPLv3';
|
||||||
|
|
@ -1533,6 +1536,9 @@ extension on TranslationsFr {
|
||||||
'about.license' => 'Licence',
|
'about.license' => 'Licence',
|
||||||
'about.licenseValue' => 'AGPL-3.0',
|
'about.licenseValue' => 'AGPL-3.0',
|
||||||
'about.website' => 'Site web',
|
'about.website' => 'Site web',
|
||||||
|
'about.sourceCode' => 'Code source',
|
||||||
|
'about.translate' => 'Aider à traduire',
|
||||||
|
'about.translateSubtitle' => 'Aidez à traduire Tane dans votre langue',
|
||||||
'about.openSourceLicenses' => 'Licences open source',
|
'about.openSourceLicenses' => 'Licences open source',
|
||||||
'about.openSourceLicensesSubtitle' => 'Bibliothèques tiers et leurs licences',
|
'about.openSourceLicensesSubtitle' => 'Bibliothèques tiers et leurs licences',
|
||||||
'about.copyright' => ({required Object years}) => '© ${years} Association Comunes, sous AGPLv3',
|
'about.copyright' => ({required Object years}) => '© ${years} Association Comunes, sous AGPLv3',
|
||||||
|
|
@ -1919,11 +1925,11 @@ extension on TranslationsFr {
|
||||||
'sale.empty' => 'Pas encore de ventes. Notez ici ce que vous vendez ou achetez.',
|
'sale.empty' => 'Pas encore de ventes. Notez ici ce que vous vendez ou achetez.',
|
||||||
'sale.iSold' => 'J\'ai vendu',
|
'sale.iSold' => 'J\'ai vendu',
|
||||||
'sale.iBought' => 'J\'ai acheté',
|
'sale.iBought' => 'J\'ai acheté',
|
||||||
|
_ => null,
|
||||||
|
} ?? switch (path) {
|
||||||
'sale.direction' => 'Vendu ou acheté ?',
|
'sale.direction' => 'Vendu ou acheté ?',
|
||||||
'sale.counterparty' => 'Avec qui ?',
|
'sale.counterparty' => 'Avec qui ?',
|
||||||
'sale.counterpartyHint' => 'Une personne ou un collectif (optionnel)',
|
'sale.counterpartyHint' => 'Une personne ou un collectif (optionnel)',
|
||||||
_ => null,
|
|
||||||
} ?? switch (path) {
|
|
||||||
'sale.amount' => 'Montant',
|
'sale.amount' => 'Montant',
|
||||||
'sale.currency' => 'Monnaie',
|
'sale.currency' => 'Monnaie',
|
||||||
'sale.currencyHint' => '€, Ğ1, heures… (optionnel)',
|
'sale.currencyHint' => '€, Ğ1, heures… (optionnel)',
|
||||||
|
|
|
||||||
|
|
@ -329,6 +329,9 @@ class _Translations$about$pt extends Translations$about$en {
|
||||||
@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';
|
||||||
@override String get website => 'Sítio web';
|
@override String get website => 'Sítio web';
|
||||||
|
@override String get sourceCode => 'Código-fonte';
|
||||||
|
@override String get translate => 'Ajuda a traduzir';
|
||||||
|
@override String get translateSubtitle => 'Ajuda a trazer o Tane para o teu idioma';
|
||||||
@override String get openSourceLicenses => 'Licenças de código aberto';
|
@override String get openSourceLicenses => 'Licenças de código aberto';
|
||||||
@override String get openSourceLicensesSubtitle => 'Bibliotecas de terceiros e as suas licenças';
|
@override String get openSourceLicensesSubtitle => 'Bibliotecas de terceiros e as suas licenças';
|
||||||
@override String copyright({required Object years}) => '© ${years} Associação Comunes, sob AGPLv3';
|
@override String copyright({required Object years}) => '© ${years} Associação Comunes, sob AGPLv3';
|
||||||
|
|
@ -1536,6 +1539,9 @@ extension on TranslationsPt {
|
||||||
'about.license' => 'Licença',
|
'about.license' => 'Licença',
|
||||||
'about.licenseValue' => 'AGPL-3.0',
|
'about.licenseValue' => 'AGPL-3.0',
|
||||||
'about.website' => 'Sítio web',
|
'about.website' => 'Sítio web',
|
||||||
|
'about.sourceCode' => 'Código-fonte',
|
||||||
|
'about.translate' => 'Ajuda a traduzir',
|
||||||
|
'about.translateSubtitle' => 'Ajuda a trazer o Tane para o teu idioma',
|
||||||
'about.openSourceLicenses' => 'Licenças de código aberto',
|
'about.openSourceLicenses' => 'Licenças de código aberto',
|
||||||
'about.openSourceLicensesSubtitle' => 'Bibliotecas de terceiros e as suas licenças',
|
'about.openSourceLicensesSubtitle' => 'Bibliotecas de terceiros e as suas licenças',
|
||||||
'about.copyright' => ({required Object years}) => '© ${years} Associação Comunes, sob AGPLv3',
|
'about.copyright' => ({required Object years}) => '© ${years} Associação Comunes, sob AGPLv3',
|
||||||
|
|
@ -1922,11 +1928,11 @@ extension on TranslationsPt {
|
||||||
'sale.title' => 'Vendas',
|
'sale.title' => 'Vendas',
|
||||||
'sale.help' => 'Regista semente vendida ou comprada — dinheiro, Ğ1 ou qualquer moeda. Um modelo separado do presente e do Plantare. Nunca se cobra comissão pelas sementes.',
|
'sale.help' => 'Regista semente vendida ou comprada — dinheiro, Ğ1 ou qualquer moeda. Um modelo separado do presente e do Plantare. Nunca se cobra comissão pelas sementes.',
|
||||||
'sale.add' => 'Registar venda',
|
'sale.add' => 'Registar venda',
|
||||||
|
_ => null,
|
||||||
|
} ?? switch (path) {
|
||||||
'sale.empty' => 'Ainda não há vendas. Anota aqui o que vendes ou compras.',
|
'sale.empty' => 'Ainda não há vendas. Anota aqui o que vendes ou compras.',
|
||||||
'sale.iSold' => 'Vendi',
|
'sale.iSold' => 'Vendi',
|
||||||
'sale.iBought' => 'Comprei',
|
'sale.iBought' => 'Comprei',
|
||||||
_ => null,
|
|
||||||
} ?? switch (path) {
|
|
||||||
'sale.direction' => 'Vendes ou compras?',
|
'sale.direction' => 'Vendes ou compras?',
|
||||||
'sale.counterparty' => 'Com quem?',
|
'sale.counterparty' => 'Com quem?',
|
||||||
'sale.counterpartyHint' => 'Uma pessoa ou um coletivo (opcional)',
|
'sale.counterpartyHint' => 'Uma pessoa ou um coletivo (opcional)',
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,12 @@ 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://tane.comunes.org';
|
const String _websiteUrl = 'https://tane.comunes.org';
|
||||||
|
|
||||||
|
/// The public source repository (AGPL). Shown as a tappable row in [AboutScreen].
|
||||||
|
const String _sourceUrl = 'https://git.comunes.org/comunes/tane';
|
||||||
|
|
||||||
|
/// The translation platform where anyone can help translate Tane.
|
||||||
|
const String _translateUrl = 'https://translate.comunes.org/projects/tane/';
|
||||||
|
|
||||||
/// The year Tane's copyright starts. Ğ1nkgo uses its own first year (2023);
|
/// The year Tane's copyright starts. Ğ1nkgo uses its own first year (2023);
|
||||||
/// Tane's is 2026.
|
/// Tane's is 2026.
|
||||||
const int _copyrightStartYear = 2026;
|
const int _copyrightStartYear = 2026;
|
||||||
|
|
@ -69,6 +75,24 @@ class AboutScreen extends StatelessWidget {
|
||||||
mode: LaunchMode.externalApplication,
|
mode: LaunchMode.externalApplication,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.code, color: seedGreen),
|
||||||
|
title: Text(t.about.sourceCode),
|
||||||
|
subtitle: const Text(_sourceUrl),
|
||||||
|
onTap: () => launchUrl(
|
||||||
|
Uri.parse(_sourceUrl),
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.translate, color: seedGreen),
|
||||||
|
title: Text(t.about.translate),
|
||||||
|
subtitle: Text(t.about.translateSubtitle),
|
||||||
|
onTap: () => launchUrl(
|
||||||
|
Uri.parse(_translateUrl),
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
),
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.privacy_tip_outlined, color: seedGreen),
|
leading: const Icon(Icons.privacy_tip_outlined, color: seedGreen),
|
||||||
title: Text(t.legal.title),
|
title: Text(t.legal.title),
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ enableGitInfo = false
|
||||||
# Links rendered only when set, so nothing broken shows before they exist:
|
# Links rendered only when set, so nothing broken shows before they exist:
|
||||||
playStoreURL = "" # Google Play, once published
|
playStoreURL = "" # Google Play, once published
|
||||||
fdroidURL = "" # F-Droid, once published
|
fdroidURL = "" # F-Droid, once published
|
||||||
sourceURL = "" # public source repository (AGPL) — set when available
|
sourceURL = "https://git.comunes.org/comunes/tane" # public source repository (AGPL)
|
||||||
weblateURL = "" # translation platform — set when hosting is ready
|
weblateURL = "https://translate.comunes.org/projects/tane/" # translation platform
|
||||||
|
|
||||||
[languages]
|
[languages]
|
||||||
[languages.en]
|
[languages.en]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue