1
0
Fork 0
mirror of https://github.com/YunoHost/apps.git synced 2024-09-03 20:06:07 +02:00

Merge branch 'master' into deprecated

This commit is contained in:
Alexandre Aubin 2024-05-31 12:42:12 +02:00 committed by GitHub
commit 78c1a4b139
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
296 changed files with 30642 additions and 5120 deletions

29
.github/diff_pot_files.py vendored Normal file
View file

@ -0,0 +1,29 @@
#! /usr/bin/env python3
"""
Super small script for github action to detect if 2 .pot files have changed for
github/workflows/auto_messages_pot.yml
"""
import sys
from babel.messages.pofile import PoFileParser
def load_pot_file(file_path):
poparser = PoFileParser({})
poparser.parse(open(file_path))
return poparser.catalog
def main():
file_1 = load_pot_file(sys.argv[1])
file_2 = load_pot_file(sys.argv[2])
if [x for x in file_1.keys() if x] == [x for x in file_2.keys() if x]:
print("false")
else:
print("true")
if __name__ == "__main__":
main()

36
.github/workflows/added_dates.yml vendored Normal file
View file

@ -0,0 +1,36 @@
name: Add Added dates to the catalog files
on:
push:
branches: [master]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.YUNOHOST_BOT_TOKEN }}
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: 3.11
- name: Install toml python lib
run: |
pip3 install toml tomlkit gitpython
- name: Add added dates to catalog files
run: |
./tools/save_added_date.py
- uses: uncenter/setup-taplo@v1
- run: taplo fmt
- uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "Automatically add dates to the catalog files"
file_pattern: 'apps.toml wishlist.toml graveyard.toml'
commit_user_name: yunohost-bot
commit_user_email: yunohost-bot@users.noreply.github.com
commit_author: 'yunohost-bot <yunohost-bot@users.noreply.github.com>'

44
.github/workflows/auto_messages_pot.yml vendored Normal file
View file

@ -0,0 +1,44 @@
name: Auto updates messages.pot for readme_generator
on:
push:
branches:
- master
jobs:
pybabel:
name: Auto updates messages.pot for readme_generator
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: 3.11
- name: Install dependencies
run: |
cd tools/readme_generator/
pip install -r requirements.txt
- name: Save old messges.pot for diffing later
run: |
cd tools/readme_generator/
cp messages.pot messages.pot.old
- name: Try to generate messages.pot
run: |
cd tools/readme_generator/
pybabel extract --ignore-dirs venv -F babel.cfg -o messages.pot .
- shell: pwsh
id: check_files_changed
run: |
$HasDiff = python .github/diff_pot_files.py tools/readme_generator/messages.pot.old tools/readme_generator/messages.pot
Write-Host "::set-output name=files_changed::$HasDiff"
- name: Create Pull Request
if: steps.check_files_changed.outputs.files_changed == 'true'
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: "Update messages.pot for readme_generator"
commit-message: "chore(readme_generator): update messages.pot"
body: |
This pull request has been generated using the command `pybabel extract --ignore-dirs venv -F babel.cfg -o messages.pot .`
base: ${{ github.head_ref }} # Creates pull request onto pull request or commit branch
branch: actions/auto_messages_pot

31
.github/workflows/test_toml.yaml vendored Normal file
View file

@ -0,0 +1,31 @@
name: Check formatting
on:
pull_request:
push:
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: uncenter/setup-taplo@v1
- run: taplo fmt
- shell: pwsh
id: check_files_changed
run: |
# Diff HEAD with the previous commit
$diff = git diff
$HasDiff = $diff.Length -gt 0
Write-Host "::set-output name=files_changed::$HasDiff"
- name: Create Pull Request
if: steps.check_files_changed.outputs.files_changed == 'true'
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: "Format TOML with Taplo"
commit-message: ":art: Format TOML with Taplo"
body: |
This pull request uses the [Taplo](https://taplo.tamasfe.dev) formatter.
base: ${{ github.head_ref }} # Creates pull request onto pull request or commit branch
branch: actions/toml

22
.github/workflows/tests_make_readme.yml vendored Normal file
View file

@ -0,0 +1,22 @@
name: Run tests for make_readme.py
on: [push]
jobs:
test:
name: Run tests for make_readme.py
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 'Set up Python 3.9'
uses: actions/setup-python@v5
with:
python-version: '3.9'
cache: 'pip'
- name: install dependencies
run: |
python -m pip install --upgrade pip
pip install -r tools/readme_generator/requirements.txt
pip install pytest
- name: launch pytest
run: cd tools/readme_generator && pytest tests

8
.gitignore vendored
View file

@ -11,14 +11,8 @@ __pycache__/
.mypy_cache/
# Github authentication files
/.github_*
/tools/.github_*
# yunohost specific cache/output dirs
.apps_cache
builds*
tools/bot-repo-cleanup/.github_token
tools/autoupdater-upgrader/.*
tools/autopatches/login
tools/autopatches/token

View file

@ -31,16 +31,17 @@ them such as their category or maintenance state. This file is regularly read by
To add your application to the catalog:
* Fork [this repository](https://github.com/YunoHost/apps)
* Edit the [`apps.toml`](/apps.toml) file
* Add your app's ID and git information at the right alphabetical place
* Indicate the app's functioning state: `notworking`, `inprogress`, or `working`
* Indicate the app category, which you can pick from `categories.toml`
* Indicate any anti-feature that your app may be subject to, see `antifeatures.toml` (or remove the `antifeatures` key if there's none)
* Indicate if your app can be thought of as an alternative to popular proprietary services (or remove the `potential_alternative_to` key if there's none)
* *Do not* add the `level` entry by yourself. Our automatic test suite ("the CI") will handle it.
* Commit and push your modifications to your repository
* Create a [Pull Request](https://github.com/YunoHost/apps/pulls/)
- Fork [this repository](https://github.com/YunoHost/apps)
- Edit the [`apps.toml`](/apps.toml) file
- Add your app's ID and git information at the right alphabetical place
- Indicate the app's functioning state: `notworking`, `inprogress`, or `working`
- Indicate the app category, which you can pick from `categories.toml`
- Indicate any anti-feature that your app may be subject to, see `antifeatures.toml` (or remove the `antifeatures` key if there's none)
- Indicate if your app can be thought of as an alternative to popular proprietary services (or remove the `potential_alternative_to` key if there's none)
- *Do not* add the `level` entry by yourself. Our automatic test suite ("the CI") will handle it.
- Add the app's logo inside the `logos` folder. Please keep this logo as small as possible. It also must be square (or almost square). The filename must be the name of the app in lower case.
- Commit and push your modifications to your repository
- Create a [Pull Request](https://github.com/YunoHost/apps/pulls/)
App example addition:

View file

@ -1,151 +1,153 @@
#:schema https://github.com/YunoHost/apps/blob/master/schemas/antifeatures.toml.schema.json
[tracking]
icon = "user-secret"
title.en = "Tracking"
title.eu = "Jarraipena"
title.fr = "Pistage"
title.it = "Tracciamento"
description.en = "Tracks you and/or reports your activity to upstream maintainer or third parties, either without your permission or by default."
description.eu = "Zure jardueraren jarraipena egiten du eta/edo jardueraren berri ematen die aplikazioaren arduradunari edo hirugarrenei, baimenik gabe edo defektuz."
description.fr = "Vous piste et/ou rapporte vos activités au mainteneur source ou à des tiers, sans votre permission ou par défaut."
description.it = "Ti traccia e/o riporta la tua attività a chi mantiene il codice sorgente o a terze parti, facendolo senza il tuo permesso o di default."
icon = "user-secret"
title.en = "Tracking"
title.eu = "Jarraipena"
title.fr = "Pistage "
title.it = "Tracciamento"
[non-free-network]
icon = "sitemap"
title.en = "Non-free Network Services"
title.eu = "Libreak ez diren sareko zerbitzuak"
title.fr = "Services réseau non libres"
title.it = "Servizi di rete non liberi"
description.en = "Promotes or depends entirely on a non-free network service."
description.eu = "Librea ez den sare-zerbitzu bat sustatzen du edo horren mende dago erabat."
description.fr = "Promeut ou utilise des services réseau non libres."
description.it = "Promuove o dipende interamente da servizi di rete non liberi."
icon = "sitemap"
title.en = "Non-free Network Services"
title.eu = "Libreak ez diren sareko zerbitzuak"
title.fr = "Services réseau non libres "
title.it = "Servizi di rete non liberi"
[non-free-addons]
icon = "puzzle-piece"
title.en = "Non-free Addons"
title.eu = "Libreak ez diren gehigarriak"
title.fr = "Extensions non libres"
title.it = "Estensioni non libere"
description.en = "Promotes other non-free applications or plugins."
description.eu = "Libreak ez diren beste aplikazio edo gehigarri batzuk sustatzen ditu."
description.fr = "Promeut d'autres applications ou plugins non libres."
description.it = "Promoove altre applicazioni o plugin non liberi"
icon = "puzzle-piece"
title.en = "Non-free Addons"
title.eu = "Libreak ez diren gehigarriak"
title.fr = "Extensions non libres "
title.it = "Estensioni non libere"
[non-free-dependencies]
icon = "book"
title.en = "Non-free dependencies"
title.eu = "Libreak ez diren dependentziak"
title.fr = "Dépendances non libres"
title.it = "Dipendenze non libere"
description.en = "Relies on software dependencies that are not free in order to run."
description.eu = "Libreak ez diren dependentzien mende dago exekutatu ahal izateko."
description.fr = "Dépend pour fonctionner de dépendances logicielles non libres."
description.it = "Per funzionare, si basa su dipendenze software non libere."
icon = "book"
title.en = "Non-free dependencies"
title.eu = "Libreak ez diren dependentziak"
title.fr = "Dépendances non libres "
title.it = "Dipendenze non libere"
[non-free-assets]
icon = "file-image-o"
title.en = "Non-free assets"
title.eu = "Libreak ez diren baliabideak"
title.fr = "Ressources non libres"
title.it = "Risorse non libere"
description.en = "Contains and makes use of non-free assets. The most common case is apps using artwork - images, sounds, music, etc. - under a commercial license."
description.eu = "Libreak ez diren baliabideak ditu eta erabiltzen ditu. Kasurik ohikoena artelanak (irudiak, soinuak, musika, etab.) erabiltzen dituzten aplikazioak dira. - jabedun-lizentziapean."
description.fr = "Contient ou utilise des médias non libres. Le cas le plus fréquent concerne des applications utilisant des œuvres (images, sons, musiques, etc.) sous une licence commerciale."
description.it = "Contiene ed utilizza risorse mediatiche non libere. Il caso più comune è lutilizzo da parte dellapp di contenuti artistici (immagini, suoni, musica, ecc.) coperti da licenza commerciale."
icon = "file-image-o"
title.en = "Non-free assets"
title.eu = "Libreak ez diren baliabideak"
title.fr = "Ressources non libres "
title.it = "Risorse non libere"
[bad-security-reputation]
icon = "bug"
title.en = "Bad security reputation"
title.eu = "Segurtasun txarreko ospea"
title.fr = "Mauvaise réputation en matière de sécurité"
title.it = "Cattiva reputazione di sicurezza"
description.en = "Has a bad security reputation, such as deprecated addons."
description.eu = "Segurtasun ospe txarra du, utzitako gehigarriak esaterako."
description.fr = "A une mauvaise réputation en matière de sécurité, en utilisant des plugins dépréciés par exemple."
description.it = "Ha una cattiva reputazione in termini di sicurezza (per esempio, potrebbe utilizzare addon obsoleti)."
icon = "bug"
title.en = "Bad security reputation"
title.eu = "Segurtasun txarreko ospea"
title.fr = "Mauvaise réputation en matière de sécurité "
title.it = "Cattiva reputazione di sicurezza"
[deprecated-software]
icon = "trash-o"
title.en = "Upstream not maintained"
title.eu = "Jatorrizko garapena utzita"
title.fr = "Application non maintenue"
title.it = "Applicazione non mantenuta"
description.en = "This software is not maintained anymore. Expect it to break down over time, be exposed to unfixed security breaches, etc."
description.eu = "Software honek ez du arduradunik. Denborak aurrera egin ahala funtzionatzeari utziko dio, konpondu gabeko segurtasun arazoak izango ditu, etab."
description.fr = "Ce logiciel n'est plus maintenu. Attendez-vous à ce qu'il ne fonctionne plus avec le temps, et que l'on découvre des failles de sécurité qui ne seront pas corrigées, etc."
description.it = "Questo software non è più mantenuto. Ci si può aspettare che con il passare del tempo smetta di funzionare, sia esposto a falle di sicurezza, ecc."
icon = "trash-o"
title.en = "Upstream not maintained"
title.eu = "Jatorrizko garapena utzita"
title.fr = "Application non maintenue "
title.it = "Applicazione non mantenuta"
[package-not-maintained]
description.en = "This YunoHost package is not actively maintained and needs adoption. This means that minimal maintenance is made by volunteers who don't use the app, so you should expect the app to lose reliability over time. You can [learn how to package](https://yunohost.org/packaging_apps_intro) if you'd like to adopt it."
description.eu = "YunoHost pakete honek ez du mantenduko duenik, bere gain hartuko duen norbaiten beharra dauka. Honek esan nahi duena da mantentze-lanak minimoak izango direla eta aplikazioa erabiltzen ez duten boluntarioek egingo dituztela lanok; denborak aurrera egin ahala fidagarri izateari utziko dio. [Aplikazioak nola paketatu](https://yunohost.org/packaging_apps_intro) ikas dezakezu, zure gain hartu nahi baduzu."
description.fr = "Ce package YunoHost n'est pas activement maintenu et a besoin d'être adopté. Cela veut dire que la maintenance minimale est réalisée par des bénévoles qui n'utilisent pas l'application, il faut donc s'attendre à ce que l'app perde en fiabilité avec le temps. Vous pouvez [apprendre comment packager](https://yunohost.org/packaging_apps_intro) si vous voulez l'adopter."
description.it = "Questo pacchetto YunoHost non viene mantenuto attivamente e deve essere adottato. Ciò significa che la manutenzione minima è effettuata da volontari che non usano l'applicazione, quindi ci si deve aspettare che l'applicazione perda affidabilità nel tempo. È possibile [imparare a pacchettizzare](https://yunohost.org/packaging_apps_intro) se si desidera adottarla."
icon = "user-times"
title.en = "Package not maintained"
title.eu = "Mantendu gabeko paketea"
title.fr = "Paquet non maintenu"
title.fr = "Package non maintenu "
title.it = "Pacchetto non mantenuto"
description.en = "This YunoHost package is not maintained and needs adoption."
description.eu = "Pakete honek ez du mantenduko duenik, boluntario baten beharra dauka."
description.fr = "Ce package YunoHost n'est plus maintenu et doit être adopté."
description.it = "Questo pacchetto di YunoHost non è più mantenuto e necessita di essere adottato."
[paid-content]
icon = "money"
title.en = "Paid content"
title.eu = "Ordainpeko edukia"
title.fr = "Contenu payant"
title.it = "Contenuti a pagamento"
description.en = "Promotes or depends, entirely or partially, on a paid service."
description.eu = "Ordainpeko zerbitzu bat sustatzen du edo bere mende dago, osorik edo neurri batean."
description.fr = "Promeut ou dépend, entièrement ou partiellement, d'un service payant."
description.it = "Promuove o dipende, interamente o parzialmente, da un servizio a pagamento."
icon = "money"
title.en = "Paid content"
title.eu = "Ordainpeko edukia"
title.fr = "Contenu payant "
title.it = "Contenuti a pagamento"
[arbitrary-limitations]
icon = "star-half-empty"
title.en = "Arbitrary limitations"
title.eu = "Muga arbitrarioak"
title.fr = "Limitations arbitraires"
title.it = "Limitazioni arbitrarie"
description.en = "Features arbitrary limitations. Please refer to the README."
description.eu = "Muga arbitrarioak ditu. Irakurri README fitxategia."
description.fr = "Contient des limitations arbitraires. Se référer au fichier README."
description.it = "Contiene limitazioni arbitrarie. Fare riferimento al file “README”."
icon = "star-half-empty"
title.en = "Arbitrary limitations"
title.eu = "Muga arbitrarioak"
title.fr = "Limitations arbitraires "
title.it = "Limitazioni arbitrarie"
[replaced-by-another-app]
icon = "repeat"
title.en = "Replaced by another app"
title.eu = "Beste aplikazio batek ordeztu du"
title.fr = "Remplacé par une autre application"
title.it = "Sostituita da unaltra app"
description.en = "Was replaced by another app. Please refer to the README."
description.eu = "Beste aplikazio batek ordeztu du. Irakurri README fitxategia."
description.fr = "A été remplacé par une autre application. Se référer au fichier README."
description.it = "Questapp è stata sostituita da unaltra app. Fare riferimento al file “README”."
icon = "repeat"
title.en = "Replaced by another app"
title.eu = "Beste aplikazio batek ordeztu du"
title.fr = "Remplacé par une autre application "
title.it = "Sostituita da unaltra app"
[alpha-software]
icon = "flask"
title.en = "Alpha software"
title.eu = "Alfa softwarea"
title.fr = "Logiciel en version alpha"
title.it = "Software in versione alpha"
description.en = "Early development stage. May contain changing or unstable features, bugs, and security vulnerability."
description.eu = "Garapenaren hasierako fasean dago. Ezaugarri aldakor edo ezegonkorrak, erroreak eta segurtasuneko arazoak izan ditzazke."
description.fr = "Le logiciel est au tout début de son développement. Il pourrait contenir des fonctionnalités changeantes ou instables, des bugs, et des failles de sécurité."
description.it = "Questo software è allinizio della sua fase di sviluppo. Potrebbe dunque essere instabile, contenere bug e vulnerabilità di sicurezza."
icon = "flask"
title.en = "Alpha software"
title.eu = "Alfa softwarea"
title.fr = "Logiciel en version alpha "
title.it = "Software in versione alpha"
[not-totally-free-upstream]
icon = "lock"
title.en = "Not totally free upstream"
title.eu = "Jatorrizkoa ez da erabat librea"
title.fr = "Application sous licence libre restreinte"
title.it = "Applicazione con licenza parzialmente libera"
description.en = "The packaged app is under an overall free licence, but with clauses that restrict its use."
description.en = "The packaged app is under an overall free license, but with clauses that may restrict its use."
description.eu = "Aplikazioak lizentzia librea du orokorrean, baina bere erabilera mugatzen duten klausulekin."
description.fr = "L'application packagée est sous une licence globalement libre, mais avec des clauses qui pourraient restreindre son utilisation."
description.it = "Questapplicazione è protetta da licenza generalmente libera, ma con delle clausole che potrebbero limitare il suo utilizzo."
icon = "lock"
title.en = "Not totally free upstream"
title.eu = "Jatorrizkoa ez da erabat librea"
title.fr = "Application sous licence libre restreinte "
title.it = "Applicazione con licenza parzialmente libera"
[not-totally-free-package]
description.en = "The YunoHost package of this app is under an overall free license, but with clauses that may restrict its use."
description.eu = "Aplikazio honen YunoHost paketeak lizentzia librea du orokorrean, baina bere erabilera mugatzen duten klausulekin."
description.fr = "Le package YunoHost de cette application est sous une licence globalement libre, mais avec des clauses qui pourraient restreindre son utilisation."
icon = "archive"
title.en = "Not totally free package"
title.eu = "Paketea ez da erabat librea"
title.fr = "Package sous licence libre restreinte"
description.en = "The YunoHost package of this app is under an overall free licence, but with clauses that restrict its use."
description.eu = "Aplikazio honen YunoHost paketeak lizentzia librea du orokorrean, baina bere erabilera mugatzen duten klausulekin."
description.fr = "Le package YunoHost de cette application est sous une licence globalement libre, mais avec des clauses qui pourraient restreindre son utilisation."
title.fr = "Package sous licence libre restreinte "

1105
apps.toml

File diff suppressed because it is too large Load diff

View file

@ -1,454 +1,456 @@
#:schema https://raw.githubusercontent.com/YunoHost/apps/master/schemas/categories.toml.schema.json
[synchronization]
description.en = "Files sync, contact, calendar, password managers..."
description.es = "Sincronización, contactos, calendario, gestor de contraseñas..."
description.eu = "Sinkronizazioa, kontaktuak, egutegia, pasahitzen kudeaketa..."
description.fr = "Fichiers, contacts, calendrier, mots de passe..."
description.it = "Sincronizzazione di file, contatti, calendari, gestione password…"
icon = "cloud"
title.en = "Synchronization"
title.es = "Sincronización"
title.eu = "Sinkronizazioa"
title.fr = "Synchronisation"
title.it = "Sincronizzazione"
description.en = "Files sync, contact, calendar, password managers..."
description.es = "Sincronización, contactos, calendario, gestor de contraseñas..."
description.eu = "Sinkronizazioa, kontaktuak, egutegia, pasahitzen kudeaketa..."
description.fr = "Fichiers, contacts, calendrier, mots de passe..."
description.it = "Sincronizzazione di file, contatti, calendari, gestione password…"
[synchronization.subtags.files]
title.en = "Files"
title.es = "Archivos"
title.eu = "Fitxategiak"
title.fr = "Fichiers"
title.it = "File"
[synchronization.subtags.files]
title.en = "Files"
title.es = "Archivos"
title.eu = "Fitxategiak"
title.fr = "Fichiers"
title.it = "File"
[synchronization.subtags.calendar]
title.en = "Calendar"
title.es = "Calendario"
title.eu = "Egutegia"
title.fr = "Calendrier"
title.it = "Calendario"
[synchronization.subtags.calendar]
title.en = "Calendar"
title.es = "Calendario"
title.eu = "Egutegia"
title.fr = "Calendrier"
title.it = "Calendario"
[synchronization.subtags.contacts]
title.en = "Contacts"
title.es = "Contactos"
title.eu = "Kontaktuak"
title.fr = "Contacts"
title.it = "Contatti"
[synchronization.subtags.contacts]
title.en = "Contacts"
title.es = "Contactos"
title.eu = "Kontaktuak"
title.fr = "Contacts"
title.it = "Contatti"
[synchronization.subtags.password]
title.en = "Passwords"
title.es = "Contraseñas"
title.eu = "Pasahitzak"
title.fr = "Mots de passe"
title.it = "Password"
[synchronization.subtags.password]
title.en = "Passwords"
title.es = "Contraseñas"
title.eu = "Pasahitzak"
title.fr = "Mots de passe"
title.it = "Password"
[publishing]
description.en = "Websites, blog, wiki, CMS..."
description.es = "Paginas Web, blog, wiki, CMS..."
description.eu = "Web orriak, blogak, wikiak, CMSak..."
description.fr = "Site web, blog, wiki, CMS..."
description.it = "Siti web, blog, wiki, CMS…"
icon = "globe"
title.en = "Publishing"
title.es = "Publicaciones"
title.eu = "Argitalpenak"
title.fr = "Publication"
title.it = "Pubblicazione"
description.en = "Websites, blog, wiki, CMS..."
description.es = "Paginas Web, blog, wiki, CMS..."
description.eu = "Web orriak, blogak, wikiak, CMSak..."
description.fr = "Site web, blog, wiki, CMS..."
description.it = "Siti web, blog, wiki, CMS…"
[publishing.subtags.website]
title.en = "Website"
title.es = "Paginas web"
title.eu = "Web orriak"
title.fr = "Site web"
title.it = "Siti web"
[publishing.subtags.website]
title.en = "Website"
title.es = "Paginas web"
title.eu = "Web orriak"
title.fr = "Site web"
title.it = "Siti web"
[publishing.subtags.blog]
title.en = "Blog"
title.es = "blog"
title.eu = "Blogak"
title.fr = "Blog"
title.it = "Blog"
[publishing.subtags.blog]
title.en = "Blog"
title.es = "blog"
title.eu = "Blogak"
title.fr = "Blog"
title.it = "Blog"
[publishing.subtags.wiki]
title.en = "Wiki"
title.es = "Wiki"
title.eu = "Wikiak"
title.fr = "Wiki"
title.it = "Wiki"
[publishing.subtags.wiki]
title.en = "Wiki"
title.es = "Wiki"
title.eu = "Wikiak"
title.fr = "Wiki"
title.it = "Wiki"
[publishing.subtags.ecommerce]
title.en = "E-commerce"
title.es = "Comercio eletronico"
title.eu = "Merkataritza elektronikoa"
title.fr = "Vente en ligne"
title.it = "Vendite online"
[publishing.subtags.ecommerce]
title.en = "E-commerce"
title.es = "Comercio eletronico"
title.eu = "Merkataritza elektronikoa"
title.fr = "Vente en ligne"
title.it = "Vendite online"
[publishing.subtags.analytics]
title.en = "Analytics"
title.es = "Estadisticas"
title.eu = "Estatistikak"
title.fr = "Statistiques"
title.it = "Analisi del traffico"
[publishing.subtags.analytics]
title.en = "Analytics"
title.es = "Estadisticas"
title.eu = "Estatistikak"
title.fr = "Statistiques"
title.it = "Analisi del traffico"
[communication]
description.en = "Chat, email, forum, meetings..."
description.es = "Chat, email, foro, reuniones en grupo..."
description.eu = "Txata, ePosta, foroak, talde-bilerak..."
description.fr = "Chat, email, forum, meetings..."
description.it = "Messaggistica, posta elettronica, forum, riunioni…"
icon = "comments-o"
title.en = "Communication"
title.es = "Comunicacion"
title.eu = "Komunikazioa"
title.fr = "Communication"
title.it = "Comunicazione"
description.en = "Chat, email, forum, meetings..."
description.es = "Chat, email, foro, reuniones en grupo..."
description.eu = "Txata, ePosta, foroak, talde-bilerak..."
description.fr = "Chat, email, forum, meetings..."
description.it = "Messaggistica, posta elettronica, forum, riunioni…"
[communication.subtags.chat]
title.en = "Instant messaging"
title.es = "Mensajeria Instantanea"
title.eu = "Bat-bateko mezularitza"
title.fr = "Messagerie instantannée"
title.it = "Messaggistica istantanea"
[communication.subtags.chat]
title.en = "Instant messaging"
title.es = "Mensajeria Instantanea"
title.eu = "Bat-bateko mezularitza"
title.fr = "Messagerie instantannée"
title.it = "Messaggistica istantanea"
[communication.subtags.forum]
title.en = "Forum"
title.es = "Foro"
title.eu = "Foroak"
title.fr = "Forum"
title.it = "Forum"
[communication.subtags.forum]
title.en = "Forum"
title.es = "Foro"
title.eu = "Foroak"
title.fr = "Forum"
title.it = "Forum"
[communication.subtags.email]
title.en = "Email"
title.es = "Email"
title.eu = "ePosta"
title.fr = "Email"
title.it = "Posta elettronica"
[communication.subtags.email]
title.en = "Email"
title.es = "Email"
title.eu = "ePosta"
title.fr = "Email"
title.it = "Posta elettronica"
[communication.subtags.meeting]
title.en = "Meetings"
title.es = "Reuniones"
title.eu = "Bilerak"
title.fr = "Meetings"
title.it = "Riunioni"
[communication.subtags.meeting]
title.en = "Meetings"
title.es = "Reuniones"
title.eu = "Bilerak"
title.fr = "Meetings"
title.it = "Riunioni"
[office]
description.en = "Collaborative text editing, spreadsheets..."
description.es = "Edición de texto colaborativo, hojas de cálculo..."
description.eu = "Testu eta kalkulu-orrien edizioa..."
description.fr = "Édition de texte collaborative, tableurs..."
description.it = "Modifica di testo collaborativa, tabelle…"
icon = "file-text-o"
title.en = "Office"
title.es = "Ofimatica"
title.eu = "Bulegoa"
title.fr = "Bureautique"
title.it = "Burocrazia"
description.en = "Collaborative text editing, spreadsheets..."
description.es = "Edición de texto colaborativo, hojas de cálculo..."
description.eu = "Testu eta kalkulu-orrien edizioa..."
description.fr = "Édition de texte collaborative, tableurs..."
description.it = "Modifica di testo collaborativa, tabelle…"
[office.subtags.text]
title.en = "Text"
title.es = "Texto"
title.eu = "Testua"
title.fr = "Texte"
title.it = "Testo"
[office.subtags.text]
title.en = "Text"
title.es = "Texto"
title.eu = "Testua"
title.fr = "Texte"
title.it = "Testo"
[office.subtags.spreadsheet]
title.en = "Spreadsheet"
title.es = "Hoja de cálculo"
title.eu = "Kalkulu-orriak"
title.fr = "Tableur"
title.it = "Tabelle"
[office.subtags.spreadsheet]
title.en = "Spreadsheet"
title.es = "Hoja de cálculo"
title.eu = "Kalkulu-orriak"
title.fr = "Tableur"
title.it = "Tabelle"
[office.subtags.impress]
title.en = "Slide show"
title.es = "Diapositivas"
title.eu = "Diapositiba-aurkezpenak"
title.fr = "Diaporama"
title.it = "Diapositive"
[office.subtags.impress]
title.en = "Slide show"
title.es = "Diapositivas"
title.eu = "Diapositiba-aurkezpenak"
title.fr = "Diaporama"
title.it = "Diapositive"
[office.subtags.draw]
title.en = "Graphism"
title.es = "Graficos"
title.eu = "Grafikoak"
title.fr = "Graphisme"
title.it = "Grafica"
[office.subtags.draw]
title.en = "Graphism"
title.es = "Graficos"
title.eu = "Grafikoak"
title.fr = "Graphisme"
title.it = "Grafica"
[office.subtags.mindmap]
title.en = "Mindmap"
title.eu = "Ideia-zuhaitzak"
title.fr = "Cartes mentale"
title.it = "Mappe mentali"
[office.subtags.mindmap]
title.en = "Mindmap"
title.eu = "Ideia-zuhaitzak"
title.fr = "Cartes mentale"
title.it = "Mappe mentali"
[productivity_and_management]
description.en = "Tasks, polls, accounting, ERP..."
description.eu = "Zereginak, inkestak, kontabilitatea, enpresa-baliabideen plangintza (ERP)..."
description.fr = "Tâches, sondages, comptabilité, ERP..."
description.it = "Gestione attività, sondaggi, contabilità, ERP…"
icon = "area-chart"
title.en = "Productivity & management"
title.eu = "Produktibitatea eta kudeaketa"
title.fr = "Productivité & gestion"
title.it = "Produttività & gestionale"
description.en = "Tasks, polls, accounting, ERP..."
description.eu = "Zereginak, inkestak, kontabilitatea, enpresa-baliabideen plangintza (ERP)..."
description.fr = "Tâches, sondages, comptabilité, ERP..."
description.it = "Gestione attività, sondaggi, contabilità, ERP…"
[productivity_and_management.subtags.task]
title.en = "Task"
title.eu = "Zereginak"
title.fr = "Tâches"
title.it = "Gestione attività"
[productivity_and_management.subtags.task]
title.en = "Task"
title.eu = "Zereginak"
title.fr = "Tâches"
title.it = "Gestione attività"
[productivity_and_management.subtags.poll]
title.en = "Poll"
title.eu = "Inkestak"
title.fr = "Sondage"
title.it = "Sondaggi"
[productivity_and_management.subtags.poll]
title.en = "Poll"
title.eu = "Inkestak"
title.fr = "Sondage"
title.it = "Sondaggi"
[productivity_and_management.subtags.accounting]
title.en = "Accounting"
title.eu = "Kontabilitatea"
title.fr = "Comptabilité"
title.it = "Contabilità"
[productivity_and_management.subtags.accounting]
title.en = "Accounting"
title.eu = "Kontabilitatea"
title.fr = "Comptabilité"
title.it = "Contabilità"
[productivity_and_management.subtags.business_and_ngos]
title.en = "Business and NGOs"
title.eu = "Korporazio eta GKEak"
title.fr = "Entreprises et associations"
title.it = "Imprese e associazioni"
[productivity_and_management.subtags.business_and_ngos]
title.en = "Business and NGOs"
title.eu = "Korporazio eta GKEak"
title.fr = "Entreprises et associations"
title.it = "Imprese e associazioni"
[small_utilities]
description.en = "Pastebins, URL shortener, proxies..."
description.eu = "Pastebinak, URL laburtzaileak, proxyak..."
description.fr = "Pastebins, raccourcisseurs d'URL, proxys..."
description.it = "Pastebin, accorciamento di URL, proxy…"
icon = "umbrella"
title.en = "Small utilities"
title.eu = "Tresna txikiak"
title.fr = "Petits utilitaires"
title.it = "Piccoli strumenti"
description.en = "Pastebins, URL shortener, proxies..."
description.eu = "Pastebinak, URL laburtzaileak, proxyak..."
description.fr = "Pastebins, raccourcisseurs d'URL, proxys..."
description.it = "Pastebin, accorciamento di URL, proxy…"
[small_utilities.subtags.pastebin]
title.en = "Pastebin"
title.eu = "Pastebinak"
title.fr = "Pastebin"
title.it = "Pastebin"
[small_utilities.subtags.pastebin]
title.en = "Pastebin"
title.eu = "Pastebinak"
title.fr = "Pastebin"
title.it = "Pastebin"
[small_utilities.subtags.url_shortener]
title.en = "URL shortener"
title.eu = "URL laburtzaileak"
title.fr = "Raccourcisseurs d'URL"
title.it = "Accorciatore di URL"
[small_utilities.subtags.url_shortener]
title.en = "URL shortener"
title.eu = "URL laburtzaileak"
title.fr = "Raccourcisseurs d'URL"
title.it = "Accorciatore di URL"
[small_utilities.subtags.proxy]
title.en = "Proxy"
title.eu = "Proxyak"
title.fr = "Proxy (Intermédiaire)"
title.it = "Proxy"
[small_utilities.subtags.proxy]
title.en = "Proxy"
title.eu = "Proxyak"
title.fr = "Proxy (Intermédiaire)"
title.it = "Proxy"
[reading]
description.en = "Newsfeed readers, books library..."
description.eu = "Albiste-jarioak, liburutegiak..."
description.fr = "Fils d'actualité, livres..."
description.it = "Notizie, libri…"
icon = "newspaper-o"
title.en = "Reading"
title.eu = "Irakurketa"
title.fr = "Lecture"
title.it = "Lettura"
description.en = "Newsfeed readers, books library..."
description.eu = "Albiste-jarioak, liburutegiak..."
description.fr = "Fils d'actualité, livres..."
description.it = "Notizie, libri…"
[reading.subtags.rssreader]
title.en = "RSS readers"
title.eu = "RSS irakurleak"
title.fr = "Lecteurs RSS"
title.it = "Lettore RSS"
[reading.subtags.rssreader]
title.en = "RSS readers"
title.eu = "RSS irakurleak"
title.fr = "Lecteurs RSS"
title.it = "Lettore RSS"
[reading.subtags.books]
title.en = "Books"
title.eu = "Liburuak"
title.fr = "Livres"
title.it = "Libri"
[reading.subtags.books]
title.en = "Books"
title.eu = "Liburuak"
title.fr = "Livres"
title.it = "Libri"
[multimedia]
description.en = "Music library, pictures gallery, P2P, TV shows..."
description.eu = "Musika liburutegiak, argazki-bildumak, P2P, TB saioak..."
description.fr = "Bibliothèque de musique, d'images, P2P, séries..."
description.it = "Librerie musicali, gallerie dimmagini, P2P, serie TV…"
icon = "music"
title.en = "Multimedia"
title.eu = "Multimedia"
title.fr = "Multimédia"
title.it = "Multimedia"
description.en = "Music library, pictures gallery, P2P, TV shows..."
description.eu = "Musika liburutegiak, argazki-bildumak, P2P, TB saioak..."
description.fr = "Bibliothèque de musique, d'images, P2P, séries..."
description.it = "Librerie musicali, gallerie dimmagini, P2P, serie TV…"
[multimedia.subtags.mediacenter]
title.en = "Media center"
title.eu = "Multimedia"
title.fr = "Centre multimédia"
title.it = "Centro multimediale"
[multimedia.subtags.mediacenter]
title.en = "Media center"
title.eu = "Multimedia"
title.fr = "Centre multimédia"
title.it = "Centro multimediale"
[multimedia.subtags.download]
title.en = "Download"
title.eu = "Deskargak"
title.fr = "Téléchargement"
title.it = "Download"
[multimedia.subtags.download]
title.en = "Download"
title.eu = "Deskargak"
title.fr = "Téléchargement"
title.it = "Download"
[multimedia.subtags.music]
title.en = "Music"
title.eu = "Musika"
title.fr = "Musique"
title.it = "Musica"
[multimedia.subtags.music]
title.en = "Music"
title.eu = "Musika"
title.fr = "Musique"
title.it = "Musica"
[multimedia.subtags.pictures]
title.en = "Pictures"
title.eu = "Irudiak"
title.fr = "Images"
title.it = "Immagini"
[multimedia.subtags.pictures]
title.en = "Pictures"
title.eu = "Irudiak"
title.fr = "Images"
title.it = "Immagini"
[multimedia.subtags.videos]
title.en = "Videos"
title.eu = "Bideoak"
title.fr = "Vidéos"
title.it = "Video"
[multimedia.subtags.videos]
title.en = "Videos"
title.eu = "Bideoak"
title.fr = "Vidéos"
title.it = "Video"
[social_media]
description.en = "Microblogging, federated media"
description.eu = "Mikroblogak, federatutako media"
description.fr = "Microblogging, médias fédérés"
description.it = "Microblogging, media federati"
icon = "users"
title.en = "Social media"
title.eu = "Sare sozialak"
title.fr = "Médias sociaux"
title.it = "Social media"
description.en = "Microblogging, federated media"
description.eu = "Mikroblogak, federatutako media"
description.fr = "Microblogging, médias fédérés"
description.it = "Microblogging, media federati"
[social_media.subtags.microblogging]
title.en = "Microblogging"
title.eu = "Mikroblogintza"
title.fr = "Microblogging"
title.it = "Microblogging"
[social_media.subtags.microblogging]
title.en = "Microblogging"
title.eu = "Mikroblogintza"
title.fr = "Microblogging"
title.it = "Microblogging"
[social_media.subtags.blogging]
title.en = "Blogging"
title.eu = "Blogintza"
title.fr = "Blogging"
title.it = "Blogging"
[social_media.subtags.blogging]
title.en = "Blogging"
title.eu = "Blogintza"
title.fr = "Blogging"
title.it = "Blogging"
[social_media.subtags.events]
title.en = "Events"
title.eu = "Gertaerak"
title.fr = "Événements"
title.it = "Eventi"
[social_media.subtags.events]
title.en = "Events"
title.eu = "Gertaerak"
title.fr = "Événements"
title.it = "Eventi"
[social_media.subtags.videos]
title.en = "Videos"
title.eu = "Bideoak"
title.fr = "Vidéos"
title.it = "Video"
[social_media.subtags.videos]
title.en = "Videos"
title.eu = "Bideoak"
title.fr = "Vidéos"
title.it = "Video"
[social_media.subtags.pictures]
title.en = "Pictures"
title.eu = "Irudiak"
title.fr = "Images"
title.it = "Immagini"
[social_media.subtags.pictures]
title.en = "Pictures"
title.eu = "Irudiak"
title.fr = "Images"
title.it = "Immagini"
[social_media.subtags.music]
title.en = "Music"
title.eu = "Musika"
title.fr = "Musique"
title.it = "Musica"
[social_media.subtags.music]
title.en = "Music"
title.eu = "Musika"
title.fr = "Musique"
title.it = "Musica"
[games]
description.en = "Wanna have some fun? ;)"
description.eu = "Dibertitu nahi duzu? ;)"
description.fr = "Envie de s'amuser ? ;)"
description.it = "Voglia di divertirti? ;)"
icon = "gamepad"
title.en = "Games"
title.eu = "Jolasak"
title.fr = "Jeux"
title.it = "Giochi"
description.en = "Wanna have some fun? ;)"
description.eu = "Dibertitu nahi duzu? ;)"
description.fr = "Envie de s'amuser ? ;)"
description.it = "Voglia di divertirti? ;)"
[dev]
description.en = "Git forges, apps skeleton, CI, translation..."
description.eu = "Forge Git, aplikazioen eskematizazioa, CI, itzulpengintza..."
description.fr = "Forges Git, squelette d'apps, CI, traduction..."
description.it = "Forge Git, schematizzazione di applicazioni, CI, traduzioni…"
icon = "flask"
title.en = "Development"
title.eu = "Garapena"
title.fr = "Développement"
title.it = "Sviluppo"
description.en = "Git forges, apps skeleton, CI, translation..."
description.eu = "Forge Git, aplikazioen eskematizazioa, CI, itzulpengintza..."
description.fr = "Forges Git, squelette d'apps, CI, traduction..."
description.it = "Forge Git, schematizzazione di applicazioni, CI, traduzioni…"
[dev.subtags.forge]
title.en = "Forge"
title.eu = "Forge"
title.fr = "Forge"
title.it = "Forgia"
[dev.subtags.forge]
title.en = "Forge"
title.eu = "Forge"
title.fr = "Forge"
title.it = "Forgia"
[dev.subtags.skeleton]
title.en = "Skeleton"
title.eu = "Eskematizazioa"
title.fr = "Squelettes"
title.it = "Schematizzazione"
[dev.subtags.skeleton]
title.en = "Skeleton"
title.eu = "Eskematizazioa"
title.fr = "Squelettes"
title.it = "Schematizzazione"
[dev.subtags.programming]
title.en = "Programming"
title.eu = "Programazioa"
title.fr = "Programmation"
title.it = "Programmazione"
[dev.subtags.programming]
title.en = "Programming"
title.eu = "Programazioa"
title.fr = "Programmation"
title.it = "Programmazione"
[dev.subtags.design]
title.en = "Design"
title.eu = "Diseinua"
title.fr = "Design"
title.it = "Progettazione"
[dev.subtags.design]
title.en = "Design"
title.eu = "Diseinua"
title.fr = "Design"
title.it = "Progettazione"
[system_tools]
description.en = "Monitoring, backup, network, DB tools..."
description.eu = "Monitorizazioa, babeskopiak, sarea, datu-baseen tresnak..."
description.fr = "Monitoring, sauvegardes, outils réseau, bases de données..."
description.it = "Monitoraggio, backup, servizi di rete, database…"
icon = "wrench"
title.en = "System tools"
title.eu = "Sistemaren tresnak"
title.fr = "Outils système"
title.it = "Strumenti di sistema"
description.en = "Monitoring, backup, network, DB tools..."
description.eu = "Monitorizazioa, babeskopiak, sarea, datu-baseen tresnak..."
description.fr = "Monitoring, sauvegardes, outils réseau, bases de données..."
description.it = "Monitoraggio, backup, servizi di rete, database…"
[system_tools.subtags.backup]
title.en = "Backup"
title.eu = "Babeskopiak"
title.fr = "Sauvegardes"
title.it = "Backup"
[system_tools.subtags.backup]
title.en = "Backup"
title.eu = "Babeskopiak"
title.fr = "Sauvegardes"
title.it = "Backup"
[system_tools.subtags.monitoring]
title.en = "Monitoring"
title.eu = "Monitorizazioa"
title.fr = "Monitoring"
title.it = "Monitoraggio"
[system_tools.subtags.monitoring]
title.en = "Monitoring"
title.eu = "Monitorizazioa"
title.fr = "Monitoring"
title.it = "Monitoraggio"
[system_tools.subtags.network]
title.en = "Network"
title.eu = "Sarea"
title.fr = "Réseau"
title.it = "Rete"
[system_tools.subtags.network]
title.en = "Network"
title.eu = "Sarea"
title.fr = "Réseau"
title.it = "Rete"
[system_tools.subtags.db]
title.en = "Databases"
title.eu = "Datu-baseak"
title.fr = "Bases de données"
title.it = "Database"
[system_tools.subtags.db]
title.en = "Databases"
title.eu = "Datu-baseak"
title.fr = "Bases de données"
title.it = "Database"
[iot]
description.en = "Home automation, energy dashboard..."
description.eu = "Domotika, automatizazioa, energiaren kudeaketa..."
description.fr = "Domotique, énergie..."
description.it = "Domotica, controllo energia…"
icon = "home"
title.en = "Internet of Things (IoT)"
title.eu = "Gauzen internet (IoT)"
title.fr = "Internet des objets (IoT)"
title.it = "Interned delle Cose (IoT)"
description.en = "Home automation, energy dashboard..."
description.eu = "Domotika, automatizazioa, energiaren kudeaketa..."
description.fr = "Domotique, énergie..."
description.it = "Domotica, controllo energia…"
[wat]
description.en = "Weird experimental or very-custom stuff"
description.eu = "Esperimentuak, kontu arraroak edo gauza oso bereziak"
description.fr = "Trucs expérimentaux et autres projets spécifiques"
description.it = "Esperimenti e altri progetti particolari"
icon = "tree"
title.en = "Wat"
title.eu = "Wat"
title.fr = "Wat"
title.it = "Wat"
description.en = "Weird experimental or very-custom stuff"
description.eu = "Esperimentuak, kontu arraroak edo gauza oso bereziak"
description.fr = "Trucs expérimentaux et autres projets spécifiques"
description.it = "Esperimenti e altri progetti particolari"

16
cron
View file

@ -1,8 +1,14 @@
# Every 4 hours
0 */4 * * * root /bin/bash __BASEDIR__/rebuild.sh
0 */4 * * * root /bin/bash __BASEDIR__/maintenance.sh rebuild_catalog
# Everyday at 20:30
30 20 * * * root /bin/bash __BASEDIR__/sourcesautoupdate.sh
# Everyday at 01:30 UTC
30 1 * * * root /bin/bash __BASEDIR__/maintenance.sh autoupdate_app_sources
# Every friday at 6pm
0 17 * * 5 root /usr/bin/python3 __BASEDIR__/tools/update_app_levels/update_app_levels.py
# Every friday at 6 PM UTC
0 17 * * 5 root /bin/bash __BASEDIR__/maintenance.sh update_app_levels
# Every 6 hours
0 */6 * * * root /bin/bash __BASEDIR__/maintenance.sh fetch_main_dashboard
# Every day at 2AM
0 2 * * * root /bin/bash __BASEDIR__/maintenance.sh fetch_level_history

View file

@ -1,257 +1,399 @@
#:schema https://github.com/YunoHost/apps/raw/master/schemas/graveyard.toml.schema.json
[anfora]
added_date = 1554588215 # 2019/04/07
category = "social_media"
killed_date = 1703600553 # 2023/12/26
subtags = [ "pictures" ]
url = "https://github.com/YunoHost-Apps/anfora_ynh"
[bibliogram]
added_date = 1597045792 # 2020/08/10
category = "social_media"
killed_date = 1703600553 # 2023/12/26
potential_alternative_to = [ "Instagram" ]
subtags = [ "pictures" ]
url = "https://github.com/YunoHost-Apps/bibliogram_ynh"
[democracyos]
added_date = 1554588215 # 2019/04/07
category = "communication"
killed_date = 1703600553 # 2023/12/26
subtags = [ "forum" ]
url = "https://github.com/YunoHost-Apps/democracyos_ynh"
[dockerui]
added_date = 1554588215 # 2019/04/07
category = "system_tools"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/dockerui_ynh"
[dynette]
added_date = 1554588215 # 2019/04/07
category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/dynette_ynh"
[ecko]
added_date = 1636827596 # 2021/11/13
category = "social_media"
killed_date = 1703600553 # 2023/12/26
subtags = [ "microblogging" ]
url = "https://github.com/YunoHost-Apps/ecko_ynh"
[fallback]
added_date = 1554588215 # 2019/04/07
category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "backup" ]
url = "https://github.com/YunoHost-Apps/fallback_ynh"
[ffsync]
added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software", "replaced-by-another-app" ]
category = "synchronization"
deprecated_date = 1660842060 # 2022/08/18
killed_date = 1716321298 # 2024/05/21
url = "https://github.com/YunoHost-Apps/ffsync_ynh"
[flask]
added_date = 1554588215 # 2019/04/07
category = "dev"
killed_date = 1703600553 # 2023/12/26
subtags = [ "skeleton" ]
url = "https://github.com/YunoHost-Apps/flask_ynh"
[flusio]
added_date = 1660509055 # 2022/08/14
category = "reading"
killed_date = 1703600553 # 2023/12/26
subtags = [ "rssreader" ]
url = "https://github.com/YunoHost-Apps/flusio_ynh"
[foodsoft]
added_date = 1564517377 # 2019/07/30
category = "productivity_and_management"
killed_date = 1703600553 # 2023/12/26
subtags = [ "business_and_ngos" ]
url = "https://github.com/YunoHost-Apps/foodsoft_ynh"
[framaestro]
added_date = 1554588215 # 2019/04/07
category = "communication"
killed_date = 1703600553 # 2023/12/26
subtags = [ "meeting" ]
url = "https://github.com/YunoHost-Apps/framaestro_ynh"
[framaestro_hub]
added_date = 1554588215 # 2019/04/07
category = "communication"
killed_date = 1703600553 # 2023/12/26
subtags = [ "meeting" ]
url = "https://github.com/YunoHost-Apps/framaestro_hub_ynh"
[freeboard]
added_date = 1554588215 # 2019/04/07
category = "iot"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/freeboard_ynh"
[freepbx]
added_date = 1590399842 # 2020/05/25
category = "communication"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/freepbx_ynh"
[ftp_webapp]
added_date = 1554588215 # 2019/04/07
category = "small_utilities"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/ftp_support_webapp_ynh"
[ftssolr]
added_date = 1590399842 # 2020/05/25
category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/ftssolr_ynh"
[garradin]
added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software", "replaced-by-another-app" ]
category = "productivity_and_management"
deprecated_date = 1703700580 # 2023/12/27
killed_date = 1716321350 # 2024/05/21
potential_alternative_to = [ "Ciel Associations" ]
subtags = [ "business_and_ngos" ]
url = "https://github.com/YunoHost-Apps/garradin_ynh"
[gekko]
added_date = 1590399842 # 2020/05/25
category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/gekko_ynh"
[gitrepositories]
added_date = 1554588215 # 2019/04/07
category = "dev"
killed_date = 1703600553 # 2023/12/26
subtags = [ "forge" ]
url = "https://github.com/YunoHost-Apps/gitrepositories_ynh"
[gnusocial]
added_date = 1554588215 # 2019/04/07
category = "social_media"
killed_date = 1703600553 # 2023/12/26
potential_alternative_to = [ "X" ]
subtags = [ "microblogging" ]
url = "https://github.com/YunoHost-Apps/gnusocial_ynh"
[gogswebhost]
added_date = 1590399842 # 2020/05/25
category = "publishing"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/gogs_webhost_ynh"
[internetarchive]
added_date = 1569663577 # 2019/09/28
category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/internetarchive_ynh"
[jappix_mini]
added_date = 1554588215 # 2019/04/07
category = "communication"
killed_date = 1703600553 # 2023/12/26
subtags = [ "chat" ]
url = "https://github.com/YunoHost-Apps/jappix_mini_ynh"
[lbcalerte]
added_date = 1554588215 # 2019/04/07
category = "small_utilities"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/lbcalerte_ynh"
[lektor]
added_date = 1554588215 # 2019/04/07
category = "publishing"
killed_date = 1703600553 # 2023/12/26
subtags = [ "website" ]
url = "https://github.com/YunoHost-Apps/lektor_ynh"
[mailman]
added_date = 1554588215 # 2019/04/07
category = "communication"
killed_date = 1703600553 # 2023/12/26
potential_alternative_to = [ "Google Groups" ]
subtags = [ "email" ]
url = "https://github.com/yunohost-apps/mailman_ynh"
[mediadrop]
added_date = 1554588215 # 2019/04/07
category = "multimedia"
killed_date = 1703600553 # 2023/12/26
subtags = [ "mediacenter" ]
url = "https://github.com/YunoHost-Apps/mediadrop_ynh"
[menu]
added_date = 1554588215 # 2019/04/07
category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/menu_ynh"
[modernpaste]
added_date = 1554588215 # 2019/04/07
category = "small_utilities"
killed_date = 1703600553 # 2023/12/26
subtags = [ "pastebin" ]
url = "https://github.com/YunoHost-Apps/modernpaste_ynh"
[monit]
added_date = 1554588215 # 2019/04/07
category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "monitoring" ]
url = "https://github.com/YunoHost-Apps/monit_ynh"
[multi_webapp]
added_date = 1554588215 # 2019/04/07
category = "publishing"
killed_date = 1703600553 # 2023/12/26
subtags = [ "website" ]
url = "https://github.com/YunoHost-Apps/multi_webapp_ynh"
[munin]
added_date = 1554588215 # 2019/04/07
category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "monitoring" ]
url = "https://github.com/YunoHost-Apps/munin_ynh"
[nexusoss]
added_date = 1554588215 # 2019/04/07
category = "dev"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/nexusoss_ynh"
[ntopng]
added_date = 1590399842 # 2020/05/25
category = "system_tools"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/ntopng_ynh"
[osmw]
added_date = 1554588215 # 2019/04/07
category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/osmw_ynh"
[peachpub]
added_date = 1655358480 # 2022/06/16
category = "communication"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/peachpub_ynh"
[piratebox]
added_date = 1554588215 # 2019/04/07
category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "network" ]
url = "https://github.com/labriqueinternet/piratebox_ynh"
[plonecms]
added_date = 1554588215 # 2019/04/07
category = "publishing"
killed_date = 1703600553 # 2023/12/26
subtags = [ "website" ]
url = "https://github.com/YunoHost-Apps/plonecms_ynh"
[portainer]
added_date = 1554588215 # 2019/04/07
category = "system_tools"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/portainer_ynh"
[rainloop]
added_date = 1674232499 # 2023/01/20
antifeatures = [ "bad-security-reputation", "deprecated-software", "replaced-by-another-app" ]
category = "communication"
deprecated_date = 1676378222 # 2023/02/14
killed_date = 1715300302 # 2024/05/10
potential_alternative_to = [ "GMail", "Hotmail", "Microsoft Outlook", "Yahoo! Mail" ]
subtags = [ "email" ]
url = "https://github.com/YunoHost-Apps/rainloop_ynh"
[reel2bits]
added_date = 1554588215 # 2019/04/07
category = "social_media"
killed_date = 1703600553 # 2023/12/26
potential_alternative_to = [ "Soundcloud" ]
subtags = [ "music" ]
url = "https://github.com/YunoHost-Apps/reel2bits_ynh"
[remotestorage]
added_date = 1554588215 # 2019/04/07
category = "small_utilities"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/remotestorage_ynh"
[roadiz]
added_date = 1554588215 # 2019/04/07
category = "publishing"
killed_date = 1703600553 # 2023/12/26
subtags = [ "website" ]
url = "https://github.com/YunoHost-Apps/roadiz_ynh"
[shsd]
added_date = 1554588215 # 2019/04/07
category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "monitoring" ]
url = "https://github.com/YunoHost-Apps/shsd_ynh"
[sickbeard]
added_date = 1554588215 # 2019/04/07
category = "multimedia"
killed_date = 1703600553 # 2023/12/26
subtags = [ "download" ]
url = "https://github.com/YunoHost-Apps/sickbeard_ynh"
[sickrage]
added_date = 1554588215 # 2019/04/07
category = "multimedia"
killed_date = 1703600553 # 2023/12/26
subtags = [ "download" ]
url = "https://github.com/YunoHost-Apps/sickrage_ynh"
[sonerezh]
added_date = 1554588215 # 2019/04/07
category = "multimedia"
killed_date = 1703600553 # 2023/12/26
subtags = [ "music" ]
url = "https://github.com/YunoHost-Apps/sonerezh_ynh"
[staticwebapp]
added_date = 1554588215 # 2019/04/07
category = "publishing"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/staticwebapp_ynh"
[subscribe]
added_date = 1590399842 # 2020/05/25
category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/subscribe_ynh"
[tagspaces]
added_date = 1554588215 # 2019/04/07
category = "synchronization"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/tagspaces_ynh"
[telegram_chatbot]
added_date = 1554588215 # 2019/04/07
category = "dev"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/telegram_chatbot_ynh"
[tes3mp]
added_date = 1554588215 # 2019/04/07
category = "games"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/tes3mp_ynh"
[transpay]
added_date = 1571446958 # 2019/10/19
category = "productivity_and_management"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/transpay_ynh"
[unbound]
added_date = 1590399842 # 2020/05/25
category = "system_tools"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/unbound_ynh"
[vpnserver]
added_date = 1564314757 # 2019/07/28
category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "network" ]
url = "https://github.com/YunoHost-Apps/vpnserver_ynh"
[wildfly]
added_date = 1554588215 # 2019/04/07
category = "dev"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/wildfly_ynh"
[youtube-dl-webui]
added_date = 1554588215 # 2019/04/07
category = "multimedia"
killed_date = 1703600553 # 2023/12/26
subtags = [ "download" ]
url = "https://github.com/YunoHost-Apps/youtube-dl-webui_ynh"
[yunofav]
added_date = 1554588215 # 2019/04/07
category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/yunofav_ynh"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 28 KiB

BIN
logos/crabfit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
logos/flohmarkt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
logos/glance.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 29 KiB

BIN
logos/incus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
logos/microbin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

BIN
logos/yarr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

98
maintenance.sh Normal file
View file

@ -0,0 +1,98 @@
#!/usr/bin/env bash
workdir=$(realpath $(dirname "$0"))
cd $workdir
function git_pull_and_update_cron_and_restart_services_if_needed()
{
git pull &>/dev/null
# Cron
cat cron | sed "s@__BASEDIR__@$workdir@g" > /etc/cron.d/app_list
# App store
chown -R appstore store
pushd store >/dev/null
modified_after_service_start="$(find *.py translations/ templates/ assets/ -newermt "$(systemctl show --property=ActiveEnterTimestamp appstore | cut -d= -f2 | cut -d' ' -f2-3)")"
if [ -n "$modified_after_service_start" ]
then
pushd assets >/dev/null
./tailwindcss-linux-x64 --input tailwind-local.css --output tailwind.css --minify
popd >/dev/null
systemctl restart appstore
sleep 3
fi
popd >/dev/null
systemctl --quiet is-active appstore || sendxmpppy "[appstore] Uhoh, failed to (re)start the appstore service?"
# App generator
chown -R appgenerator tools/app_generator
pushd tools/app_generator >/dev/null
modified_after_service_start="$(find *.py translations/ templates/ static/ -newermt "$(systemctl show --property=ActiveEnterTimestamp appgenerator | cut -d= -f2 | cut -d' ' -f2-3)")"
if [ -n "$modified_after_service_start" ]
then
pushd assets >/dev/null
./tailwindcss-linux-x64 --input tailwind-local.css --output tailwind.css --minify
popd >/dev/null
systemctl restart appgenerator
sleep 3
fi
popd >/dev/null
systemctl --quiet is-active appgenerator || sendxmpppy "[appgenerator] Uhoh, failed to (re)start the appgenerator service?"
# Autoreadme
pushd tools/readme_generator >/dev/null
modified_after_service_start="$(find *.py translations/ templates/ -newermt "$(systemctl show --property=ActiveEnterTimestamp autoreadme | cut -d= -f2 | cut -d' ' -f2-3)")"
if [ -n "$modified_after_service_start" ]
then
systemctl restart autoreadme
sleep 3
fi
popd >/dev/null
systemctl --quiet is-active autoreadme || sendxmpppy "[autoreadme] Uhoh, failed to (re)start the autoreadme service?"
}
function rebuild_catalog()
{
log=$workdir/app_list_auto_update.log
date >> $log
git_pull_and_update_cron_and_restart_services_if_needed
./tools/list_builder.py &>> $log || sendxmpppy "[listbuilder] Rebuilding the application list failed miserably"
}
function autoupdate_app_sources()
{
log=$workdir/app_sources_auto_update.log
date >> $log
git_pull_and_update_cron_and_restart_services_if_needed
tools/autoupdate_app_sources/venv/bin/python3 tools/autoupdate_app_sources/autoupdate_app_sources.py \
--edit --commit --pr --paste -j1 \
&> $log || sendxmpppy "[appsourcesautoupdate] App sources auto-update failed miserably"
}
function update_app_levels()
{
pushd tools/update_app_levels >/dev/null
python3 update_app_levels.py
popd >/dev/null
}
function fetch_main_dashboard()
{
pushd store >/dev/null
venv/bin/python3 fetch_main_dashboard.py 2>&1 | grep -v 'Following Github server redirection'
popd >/dev/null
}
function fetch_level_history()
{
pushd store >/dev/null
venv/bin/python3 fetch_level_history.py
popd >/dev/null
}
$1

View file

@ -1,11 +0,0 @@
#!/usr/bin/env bash
workdir=$(realpath $(dirname "$0"))
log=$workdir/app_list_auto_update.log
cd $workdir
date >> $log
git pull &>/dev/null
cat cron | sed "s@__BASEDIR__@$workdir@g" > /etc/cron.d/app_list
./tools/list_builder.py &>> $log || sendxmpppy "[listbuilder] Rebuilding the application list failed miserably"

View file

@ -0,0 +1,63 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://github.com/YunoHost/apps/blob/master/schemas/antifeatures.toml.schema.json",
"title": "Yunohost's antifeatures.toml schema",
"version": "0",
"$defs": {
"translated_string": {
"type": "object",
"required": [
"en"
],
"additionalProperties": false,
"patternProperties": {
"^[a-z]{2}$": {
"type": "string"
}
}
}
},
"type": "object",
"required": [],
"additionalProperties": false,
"patternProperties": {
"^[a-z0-9_-]*$": {
"type": "object",
"required": [
"icon",
"title",
"description"
],
"additionalProperties": false,
"properties": {
"icon": {
"type": "string"
},
"title": {
"$ref": "#/$defs/translated_string"
},
"description": {
"$ref": "#/$defs/translated_string"
},
"subtags": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-z_]*$": {
"type": "object",
"required": [
"title"
],
"additionalProperties": false,
"properties": {
"title": {
"$ref": "#/$defs/translated_string"
}
}
}
}
}
}
}
}
}

View file

@ -56,6 +56,12 @@
},
"branch": {
"type": "string"
},
"added_date": {
"type": "integer"
},
"deprecated_date": {
"type": "integer"
}
}
}

View file

@ -0,0 +1,57 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://github.com/YunoHost/apps/blob/master/schemas/graveyard.toml.schema.json",
"title": "Yunohost's graveyard.toml schema",
"version": "0",
"type": "object",
"required": [],
"additionalProperties": false,
"patternProperties": {
"^[a-z0-9_-]*$": {
"type": "object",
"required": [
"url"
],
"additionalProperties": false,
"properties": {
"category": {
"type": "string"
},
"subtags": {
"type": "array",
"items": {
"type": "string"
},
"additionalItems": false
},
"url": {
"type": "string",
"format": "url"
},
"antifeatures": {
"type": "array",
"items": {
"type": "string"
},
"additionalItems": false
},
"potential_alternative_to": {
"type": "array",
"items": {
"type": "string"
},
"additionalItems": false
},
"added_date": {
"type": "integer"
},
"deprecated_date": {
"type": "integer"
},
"killed_date": {
"type": "integer"
}
}
}
}
}

View file

@ -3,14 +3,15 @@
"$id": "https://raw.githubusercontent.com/YunoHost/apps/master/schemas/manifest.v2.schema.json",
"title": "Yunohost app manifest.toml schema",
"version": "0",
"type": "object",
"$defs": {
"translated_string": {
"anyOf": [
{
"type": "object",
"required": ["en"],
"required": [
"en"
],
"additionalProperties": false,
"patternProperties": {
"^[a-z]{2}$": {
@ -68,7 +69,6 @@
]
}
},
"properties": {
"packaging_format": {
"description": "Packaging format / version",
@ -87,32 +87,64 @@
"type": "string",
"pattern": "^[0-9a-z]*([\\.+-][0-9a-z]*)*~ynh[0-9]*$"
},
"description": {"$ref": "#/$defs/translated_string"},
"description": {
"$ref": "#/$defs/translated_string"
},
"maintainers": {
"description": "List of maintainers",
"type": "array",
"items": {
"type": "string"
"type": "string"
}
},
"upstream": {
"type": "object",
"required": ["license"],
"required": [
"license"
],
"additionalProperties": false,
"properties": {
"license": {"type": "string"},
"website": {"type": "string", "format": "uri-reference"},
"demo": {"type": "string", "format": "uri-reference"},
"admindoc": {"type": "string", "format": "uri-reference"},
"userdoc": {"type": "string", "format": "uri-reference"},
"code": {"type": "string", "format": "uri-reference"},
"fund": {"type": "string", "format": "uri-reference"},
"cpe": {"$ref": "#/$defs/cpe_id"}
"license": {
"type": "string"
},
"website": {
"type": "string",
"format": "uri-reference"
},
"demo": {
"type": "string",
"format": "uri-reference"
},
"admindoc": {
"type": "string",
"format": "uri-reference"
},
"userdoc": {
"type": "string",
"format": "uri-reference"
},
"code": {
"type": "string",
"format": "uri-reference"
},
"fund": {
"type": "string",
"format": "uri-reference"
},
"cpe": {
"$ref": "#/$defs/cpe_id"
}
}
},
"integration": {
"type": "object",
"required": ["yunohost", "architectures", "multi_instance", "ldap", "sso"],
"required": [
"yunohost",
"architectures",
"multi_instance",
"ldap",
"sso"
],
"additionalProperties": false,
"properties": {
"yunohost": {
@ -129,22 +161,39 @@
"type": "array",
"items": {
"type": "string",
"enum": ["amd64", "i386", "armhf", "arm64"]
"enum": [
"amd64",
"i386",
"armhf",
"arm64"
]
}
}
]
},
"multi_instance": {"$ref": "#/$defs/boolean_or_not_relevant"},
"ldap": {"$ref": "#/$defs/boolean_or_not_relevant"},
"sso": {"$ref": "#/$defs/boolean_or_not_relevant"},
"disk": {"$ref": "#/$defs/byte_size"},
"multi_instance": {
"$ref": "#/$defs/boolean_or_not_relevant"
},
"ldap": {
"$ref": "#/$defs/boolean_or_not_relevant"
},
"sso": {
"$ref": "#/$defs/boolean_or_not_relevant"
},
"disk": {
"$ref": "#/$defs/byte_size"
},
"ram": {
"type": "object",
"required": [],
"additionalProperties": false,
"properties": {
"build": {"$ref": "#/$defs/byte_size"},
"runtime": {"$ref": "#/$defs/byte_size"}
"build": {
"$ref": "#/$defs/byte_size"
},
"runtime": {
"$ref": "#/$defs/byte_size"
}
}
}
}
@ -154,7 +203,9 @@
"required": [],
"additionalProperties": false,
"patternProperties": {
"^[a-zA-Z0-9_-]*$": {"$ref": "#/$defs/translated_string"}
"^[a-zA-Z0-9_-]*$": {
"$ref": "#/$defs/translated_string"
}
}
},
"install": {
@ -164,22 +215,60 @@
"patternProperties": {
"^[a-z][a-z0-9_]*$": {
"type": "object",
"required": ["type"],
"required": [
"type"
],
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"enum": [
"string", "text", "select", "tags", "email", "url", "date", "time",
"color", "password", "path", "boolean", "domain", "user", "group",
"number", "range", "alert", "markdown", "file", "app"
"string",
"text",
"select",
"tags",
"email",
"url",
"date",
"time",
"color",
"password",
"path",
"boolean",
"domain",
"user",
"group",
"number",
"range",
"alert",
"markdown",
"file",
"app"
]
},
"default": {"type": ["string", "number", "boolean"]},
"example": {"type": ["string", "number", "boolean"]},
"optional": {"type": "boolean"},
"ask": {"$ref": "#/$defs/translated_string"},
"help": {"$ref": "#/$defs/translated_string"},
"default": {
"type": [
"string",
"number",
"boolean"
]
},
"example": {
"type": [
"string",
"number",
"boolean"
]
},
"optional": {
"type": "boolean"
},
"ask": {
"$ref": "#/$defs/translated_string"
},
"help": {
"$ref": "#/$defs/translated_string"
},
"choices": {
"anyOf": [
{
@ -228,7 +317,9 @@
"required": [],
"additionalProperties": false,
"properties": {
"packages": {"$ref": "#/$defs/string_or_array_of"},
"packages": {
"$ref": "#/$defs/string_or_array_of"
},
"packages_from_raw_bash": {
"type": "string"
},
@ -237,7 +328,10 @@
"patternProperties": {
"^.[a-z][a-z0-9_]*$": {
"type": "object",
"required": ["repo", "packages"],
"required": [
"repo",
"packages"
],
"additionalProperties": false,
"properties": {
"repo": {
@ -246,7 +340,9 @@
"key": {
"type": "string"
},
"packages": {"$ref": "#/$defs/string_or_array_of"}
"packages": {
"$ref": "#/$defs/string_or_array_of"
}
}
}
}
@ -258,25 +354,36 @@
"required": [],
"additionalProperties": false,
"properties": {
"dir": {"$ref": "#/$defs/path_absolute"},
"dir": {
"$ref": "#/$defs/path_absolute"
},
"subdirs": {
"type": "array",
"items": {
"type": "string"
}
},
"owner": {"$ref": "#/$defs/name_and_permission"},
"group": {"$ref": "#/$defs/name_and_permission"}
"owner": {
"$ref": "#/$defs/name_and_permission"
},
"group": {
"$ref": "#/$defs/name_and_permission"
}
}
},
"database": {
"type": "object",
"required": ["type"],
"required": [
"type"
],
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"enum": ["mysql", "postgresql"]
"enum": [
"mysql",
"postgresql"
]
}
}
},
@ -285,9 +392,15 @@
"required": [],
"additionalProperties": false,
"properties": {
"dir": {"$ref": "#/$defs/path_absolute"},
"owner": {"$ref": "#/$defs/name_and_permission"},
"group": {"$ref": "#/$defs/name_and_permission"}
"dir": {
"$ref": "#/$defs/path_absolute"
},
"owner": {
"$ref": "#/$defs/name_and_permission"
},
"group": {
"$ref": "#/$defs/name_and_permission"
}
}
},
"permissions": {
@ -300,7 +413,10 @@
"required": [],
"additionalProperties": false,
"properties": {
"url": {"$ref": "#/$defs/path_absolute"},
"url": {
"type": "string",
"pattern": "^((re:.*)?|(__[A-Z_]*__)?\/.*)$"
},
"show_tile": {
"type": "boolean"
},
@ -315,7 +431,9 @@
},
"additional_urls": {
"type": "array",
"items": {"$ref": "#/$defs/path_absolute"}
"items": {
"$ref": "#/$defs/path_absolute"
}
},
"label": {
"type": "string"
@ -344,7 +462,11 @@
},
{
"type": "string",
"enum": ["TCP", "UDP", "Both"]
"enum": [
"TCP",
"UDP",
"Both"
]
}
]
},
@ -369,7 +491,9 @@
"type": "string",
"format": "uri"
},
"sha256": {"$ref": "#/$defs/sha256sum"},
"sha256": {
"$ref": "#/$defs/sha256sum"
},
"in_subdir": {
"anyOf": [
{
@ -451,6 +575,14 @@
},
"force_version": {
"type": "string"
},
"allow_prereleases": {
"type": "boolean",
"description": "Allow prereleases when using strategy = latest_X_release"
},
"needs_manual_tweaks": {
"type": "boolean",
"description": "Inform the maintainer of manual steps to make autoupdate PRs work"
}
}
}
@ -465,7 +597,9 @@
"type": "string",
"format": "uri"
},
"sha256": {"$ref": "#/$defs/sha256sum"}
"sha256": {
"$ref": "#/$defs/sha256sum"
}
}
}
}
@ -486,12 +620,13 @@
"allow_email": {
"type": "boolean"
},
"home": {"$ref": "#/$defs/path_absolute"}
"home": {
"$ref": "#/$defs/path_absolute"
}
}
}
}
}
},
"required": [
"packaging_format",

View file

@ -3,14 +3,16 @@
"$id": "https://github.com/YunoHost/apps/blob/master/schemas/wishlist.toml.schema.json",
"title": "Yunohost's wishlist.toml schema",
"version": "0",
"type": "object",
"required": [],
"additionalProperties": false,
"patternProperties": {
"^[a-z0-9_-]*$": {
"type": "object",
"required": ["name", "upstream"],
"required": [
"name",
"upstream"
],
"additionalProperties": false,
"properties": {
"name": {
@ -26,9 +28,15 @@
"website": {
"type": "string",
"format": "url"
},
"draft": {
"type": "string",
"format": "url"
},
"added_date": {
"type": "integer"
}
}
}
}
}

View file

@ -1,13 +0,0 @@
#!/bin/bash
workdir=$(realpath $(dirname "$0"))
log=$workdir/app_sources_auto_update.log
cd $workdir
date >> $log
git pull &>/dev/null
cat cron | sed "s@__BASEDIR__@$workdir@g" > /etc/cron.d/app_list
python3 tools/autoupdate_app_sources/autoupdate_app_sources.py \
--edit --commit --pr --paste -j1 \
&> $log || sendxmpppy "[appsourcesautoupdate] App sources auto-update failed miserably"

0
store/.cache/.gitkeep Normal file
View file

10
store/.gitignore vendored
View file

@ -1,8 +1,6 @@
config.toml
.stars
assets/fork-awesome.*
assets/forkawesome-webfont.*
assets/tailwind.css
assets/tailwindcss-linux-x64
assets/ynh_logo_*
.wishlist_ratelimit
.cache
.tmp
assets/*

View file

@ -31,18 +31,21 @@ And then start the dev server:
```bash
source venv/bin/activate
FLASK_APP=app.py FLASK_ENV=development flask run
FLASK_APP=app.py FLASK_ENV=development flask --debug run
# In another term, launch the tailwindcss process to autorebuild css:
cd assets; ./tailwindcss-linux-x64 --input tailwind-local.css --output tailwind.css --watch
```
## Translation
It's based on Flask-Babel : <https://python-babel.github.io>
It's based on Flask-Babel : <https://python-babel.github.io/flask-babel/>
```bash
source venv/bin/activate
# Extract the english sentences from the code, needed if you modified it
pybabel extract --ignore-dirs venv -F babel.cfg -o messages.pot .
pybabel extract -F babel.cfg -o messages.pot *.py templates/*.html
# If working on a new locale: initialize it (in this example: fr)
pybabel init -i messages.pot -d translations -l fr

View file

@ -1,15 +1,17 @@
import time
import os
import sys
import re
import time
import json
import toml
import tomlkit
import base64
import hashlib
import hmac
import os
import string
import random
import urllib
import json
import sys
from datetime import datetime
from slugify import slugify
from flask import (
Flask,
@ -18,6 +20,7 @@ from flask import (
session,
redirect,
request,
make_response,
)
from flask_babel import Babel
from flask_babel import gettext as _
@ -30,6 +33,7 @@ from utils import (
get_catalog,
get_wishlist,
get_stars,
get_dashboard_data,
get_app_md_and_screenshots,
save_wishlist_submit_for_ratelimit,
check_wishlist_submit_ratelimit,
@ -61,9 +65,7 @@ for key in mandatory_config_keys:
print(f"Missing key in config.toml: {key}")
sys.exit(1)
if config.get("DEBUG"):
app.debug = True
app.config["DEBUG"] = True
if app.config.get("DEBUG"):
app.config["TEMPLATES_AUTO_RELOAD"] = True
# This is the secret key used for session signing
@ -84,6 +86,39 @@ def localize(d):
return d["en"]
@app.template_filter("days_ago")
def days_ago(timestamp):
return int((time.time() - timestamp) / (60 * 60 * 24))
@app.template_filter("hours_ago")
def hours_ago(timestamp):
d = datetime.now() - datetime.fromtimestamp(timestamp)
hours = int(divmod(d.total_seconds(), 3600)[0])
minutes = int(divmod(d.total_seconds(), 60)[1])
return f"{hours}:{minutes}h"
@app.template_filter("format_datetime")
def format_datetime(value, format="%d %b %Y %I:%M %p"):
if value is None:
return ""
return datetime.strptime(value, "%b %d %Y").strftime(format)
@app.context_processor
def utils():
d = {
"user": session.get("user", {}),
"locale": get_locale(),
}
if app.config.get("DEBUG"):
d["tailwind_local"] = open("assets/tailwind-local.css").read()
return d
###############################################################################
@ -96,8 +131,6 @@ def favicon():
def index():
return render_template(
"index.html",
locale=get_locale(),
user=session.get("user", {}),
catalog=get_catalog(),
)
@ -106,12 +139,10 @@ def index():
def browse_catalog():
return render_template(
"catalog.html",
locale=get_locale(),
init_sort=request.args.get("sort"),
init_search=request.args.get("search"),
init_category=request.args.get("category"),
init_starsonly=request.args.get("starsonly"),
user=session.get("user", {}),
catalog=get_catalog(),
timestamp_now=int(time.time()),
stars=get_stars(),
@ -134,8 +165,6 @@ def app_info(app_id):
return render_template(
"app.html",
locale=get_locale(),
user=session.get("user", {}),
app_id=app_id,
infos=infos,
catalog=get_catalog(),
@ -147,9 +176,16 @@ def app_info(app_id):
def star_app(app_id, action):
assert action in ["star", "unstar"]
if app_id not in get_catalog()["apps"] and app_id not in get_wishlist():
return _("App %(app_id) not found", app_id=app_id), 404
return _("App %(app_id)s not found", app_id=app_id), 404
if not session.get("user", {}):
return _("You must be logged in to be able to star an app") + "<br/><br/>" + _("Note that, due to various abuses, we restricted login on the app store to 'trust level 1' users.<br/><br/>'Trust level 1' is obtained after interacting a minimum with the forum, and more specifically: entering at least 5 topics, reading at least 30 posts, and spending at least 10 minutes reading posts."), 401
return (
_("You must be logged in to be able to star an app")
+ "<br/><br/>"
+ _(
"Note that, due to various abuses, we restricted login on the app store to 'trust level 1' users.<br/><br/>'Trust level 1' is obtained after interacting a minimum with the forum, and more specifically: entering at least 5 topics, reading at least 30 posts, and spending at least 10 minutes reading posts."
),
401,
)
app_star_folder = os.path.join(".stars", app_id)
app_star_for_this_user = os.path.join(
@ -177,11 +213,6 @@ def star_app(app_id, action):
def browse_wishlist():
return render_template(
"wishlist.html",
init_sort=request.args.get("sort"),
init_search=request.args.get("search"),
init_starsonly=request.args.get("starsonly"),
locale=get_locale(),
user=session.get("user", {}),
wishlist=get_wishlist(),
stars=get_stars(),
)
@ -192,11 +223,15 @@ def add_to_wishlist():
if request.method == "POST":
user = session.get("user", {})
if not user:
errormsg = _("You must be logged in to submit an app to the wishlist") + "<br/><br/>" + _("Note that, due to various abuses, we restricted login on the app store to 'trust level 1' users.<br/><br/>'Trust level 1' is obtained after interacting a minimum with the forum, and more specifically: entering at least 5 topics, reading at least 30 posts, and spending at least 10 minutes reading posts.")
errormsg = (
_("You must be logged in to submit an app to the wishlist")
+ "<br/><br/>"
+ _(
"Note that, due to various abuses, we restricted login on the app store to 'trust level 1' users.<br/><br/>'Trust level 1' is obtained after interacting a minimum with the forum, and more specifically: entering at least 5 topics, reading at least 30 posts, and spending at least 10 minutes reading posts."
)
)
return render_template(
"wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=None,
successmsg=None,
errormsg=errormsg,
@ -207,8 +242,6 @@ def add_to_wishlist():
errormsg = _("Invalid CSRF token, please refresh the page and try again")
return render_template(
"wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=csrf_token,
successmsg=None,
errormsg=errormsg,
@ -220,12 +253,33 @@ def add_to_wishlist():
website = request.form["website"].strip().replace("\n", "")
license = request.form["license"].strip().replace("\n", "")
boring_keywords_to_check_for_people_not_reading_the_instructions = ["free", "open source", "open-source", "self-hosted", "simple", "lightweight", "light-weight", "léger", "best", "most", "fast", "rapide", "flexible", "puissante", "puissant", "powerful", "secure"]
boring_keywords_to_check_for_people_not_reading_the_instructions = [
"free",
"open source",
"open-source",
"self-hosted",
"simple",
"lightweight",
"light-weight",
"léger",
"best",
"most",
"fast",
"rapide",
"flexible",
"puissante",
"puissant",
"powerful",
"secure",
]
checks = [
(
check_wishlist_submit_ratelimit(session['user']['username']) is True and session['user']['bypass_ratelimit'] is False,
_("Proposing wishlist additions is limited to once every 15 days per user. Please try again in a few days.")
check_wishlist_submit_ratelimit(session["user"]["username"]) is True
or session["user"]["bypass_ratelimit"] is True,
_(
"Proposing wishlist additions is limited to once every 15 days per user. Please try again in a few days."
),
),
(len(name) >= 3, _("App name should be at least 3 characters")),
(len(name) <= 30, _("App name should be less than 30 characters")),
@ -259,21 +313,28 @@ def add_to_wishlist():
_("App name contains special characters"),
),
(
all(keyword not in description.lower() for keyword in boring_keywords_to_check_for_people_not_reading_the_instructions),
_("Please focus on what the app does, without using marketing, fuzzy terms, or repeating that the app is 'free' and 'self-hostable'.")
all(
keyword not in description.lower()
for keyword in boring_keywords_to_check_for_people_not_reading_the_instructions
),
_(
"Please focus on what the app does, without using marketing, fuzzy terms, or repeating that the app is 'free' and 'self-hostable'."
),
),
(
description.lower().split()[0] != name and (len(description.split()) == 1 or description.lower().split()[1] not in ["is", "est"]),
_("No need to repeat the name of the app. Focus on what the app does.")
)
description.lower().split()[0] != name
and (
len(description.split()) == 1
or description.lower().split()[1] not in ["is", "est"]
),
_("No need to repeat the name of the app. Focus on what the app does."),
),
]
for check, errormsg in checks:
if not check:
return render_template(
"wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=csrf_token,
successmsg=None,
errormsg=errormsg,
@ -288,19 +349,33 @@ def add_to_wishlist():
)
current_wishlist_sha = current_wishlist_rawtoml.sha
current_wishlist_rawtoml = current_wishlist_rawtoml.decoded_content.decode()
new_wishlist = toml.loads(current_wishlist_rawtoml)
new_wishlist = tomlkit.loads(current_wishlist_rawtoml)
if slug in new_wishlist:
url = f"https://apps.yunohost.org/wishlist?search={slug}"
return render_template(
"wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=csrf_token,
successmsg=None,
errormsg=_(
"An entry with the name %(slug)s already exists in the wishlist, instead, you can <a href='%(url)s'>add a star to the app to show your interest</a>.",
slug=slug, url=url,
slug=slug,
url=url,
),
)
app_catalog = get_catalog()["apps"]
if slug in app_catalog:
url = f"https://apps.yunohost.org/app/{slug}"
return render_template(
"wishlist_add.html",
csrf_token=csrf_token,
successmsg=None,
errormsg=_(
"An app with the name %(slug)s already exists in the catalog, <a href='%(url)s'>you can see its page here</a>.",
slug=slug,
url=url,
),
)
@ -312,24 +387,22 @@ def add_to_wishlist():
}
new_wishlist = dict(sorted(new_wishlist.items()))
new_wishlist_rawtoml = toml.dumps(new_wishlist)
new_wishlist_rawtoml = tomlkit.dumps(new_wishlist)
new_branch = f"add-to-wishlist-{slug}"
try:
# Get the commit base for the new branch, and create it
commit_sha = repo.get_branch(repo.default_branch).commit.sha
repo.create_git_ref(ref=f"refs/heads/{new_branch}", sha=commit_sha)
except exception as e:
except Exception as e:
print("… Failed to create branch ?")
print(e)
url = "https://github.com/YunoHost/apps/pulls?q=is%3Apr+is%3Aopen+wishlist"
url = "https://github.com/YunoHost/apps/pulls?q=is%3Apr+is%3Aopen+label%3AWishlist"
errormsg = _(
"Failed to create the pull request to add the app to the wishlist… Maybe there's already <a href='%(url)s'>a waiting PR for this app</a>? Else, please report the issue to the YunoHost team.",
url=url
url=url,
)
return render_template(
"wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=csrf_token,
successmsg=None,
errormsg=errormsg,
@ -370,6 +443,7 @@ Description: {description}
head=new_branch,
base=repo.default_branch,
)
pr.add_to_labels("Wishlist")
url = f"https://github.com/YunoHost/apps/pull/{pr.number}"
@ -378,12 +452,10 @@ Description: {description}
url=url,
)
save_wishlist_submit_for_ratelimit(session['user']['username'])
save_wishlist_submit_for_ratelimit(session["user"]["username"])
return render_template(
"wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
successmsg=successmsg,
)
else:
@ -392,14 +464,125 @@ Description: {description}
session["csrf_token"] = csrf_token
return render_template(
"wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=csrf_token,
successmsg=None,
errormsg=None,
)
@app.route("/dash")
def dash():
# Sort by popularity by default
stars = get_stars()
data = dict(
sorted(
get_dashboard_data().items(),
key=lambda app: len(stars.get(app[0], [])),
reverse=True,
)
)
return render_template(
"dash.html", data=data, stars=stars, last_data_update=get_dashboard_data.mtime
)
@app.route("/charts")
def charts():
dashboard_data = get_dashboard_data()
level_summary = {}
for i in range(0, 9):
level_summary[i] = len(
[
infos
for infos in dashboard_data.values()
if infos.get("ci_results", {}).get("main").get("level") == i
]
)
level_summary["unknown"] = len(
[
infos
for infos in dashboard_data.values()
if infos.get("ci_results", {}).get("main").get("level") in [None, "?"]
]
)
return render_template(
"charts.html",
level_summary=level_summary,
history=json.loads(open(".cache/history.json").read()),
news_per_date=json.loads(open(".cache/news.json").read()),
)
@app.route("/news.rss")
def news_rss():
news_per_date = json.loads(open(".cache/news.json").read())
# Keepy only the last N entries
news_per_date = {
d: infos for d, infos in reversed(list(news_per_date.items())[-2:])
}
rss_xml = render_template(
"news_rss.xml", news_per_date=news_per_date, catalog=get_catalog()
)
response = make_response(rss_xml)
response.headers["Content-Type"] = "application/rss+xml"
response.headers["Content-Disposition"] = "inline; filename=news_rss.xml"
return response
# Badges
@app.route("/integration/<app>")
@app.route("/integration/<app>.svg")
@app.route("/badge/<type>/<app>")
@app.route("/badge/<type>/<app>.svg")
def badge(app, type="integration"):
data = get_dashboard_data()
catalog = get_catalog()["apps"]
catalog_level = catalog.get(app, {}).get("level")
main_ci_level = (
data.get(app, {}).get("ci_results", {}).get("main", {}).get("level", "?")
)
if type == "integration":
if app in catalog and main_ci_level:
badge = f"level{main_ci_level}"
else:
badge = "unknown"
elif type == "state":
if app not in catalog:
badge = "state-unknown"
else:
if catalog_level in [None, "?"]:
badge = "state-just-got-added-to-catalog"
elif catalog_level in [0, -1]:
badge = "state-broken"
else:
badge = "state-working"
elif type == "maintained":
if app in catalog and catalog.get(app, {}).get("maintained") is False:
badge = "unmaintained"
else:
badge = "empty"
else:
badge = "empty"
svg = open(f"assets/badges/{badge}.svg").read()
response = make_response(svg)
response.content_type = "image/svg+xml"
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
response.headers["Pragma"] = "no-cache"
return response
###############################################################################
# Session / SSO using Discourse #
###############################################################################
@ -427,7 +610,6 @@ def login_using_discourse():
@app.route("/sso_login_callback")
def sso_login_callback():
computed_sig = hmac.new(
config["DISCOURSE_SSO_SECRET"].encode(),
msg=request.args["sso"].encode(),
@ -445,10 +627,17 @@ def sso_login_callback():
uri_to_redirect_to_after_login = session.get("uri_to_redirect_to_after_login")
if "trust_level_1" not in user_data['groups'][0].split(','):
return _("Unfortunately, login was denied.") + "<br/><br/>" + _("Note that, due to various abuses, we restricted login on the app store to 'trust level 1' users.<br/><br/>'Trust level 1' is obtained after interacting a minimum with the forum, and more specifically: entering at least 5 topics, reading at least 30 posts, and spending at least 10 minutes reading posts."), 403
if "trust_level_1" not in user_data["groups"][0].split(","):
return (
_("Unfortunately, login was denied.")
+ "<br/><br/>"
+ _(
"Note that, due to various abuses, we restricted login on the app store to 'trust level 1' users.<br/><br/>'Trust level 1' is obtained after interacting a minimum with the forum, and more specifically: entering at least 5 topics, reading at least 30 posts, and spending at least 10 minutes reading posts."
),
403,
)
if "staff" in user_data['groups'][0].split(','):
if "staff" in user_data["groups"][0].split(","):
bypass_ratelimit = True
else:
bypass_ratelimit = False
@ -467,6 +656,22 @@ def sso_login_callback():
return redirect("/")
@app.route("/toggle_packaging")
def toggle_packaging():
if session and "user" in session:
user = session["user"]
if not session["user"].get("packaging_enabled"):
# Use this trick to force the change to be registered
# because this session["user"]["foobar"] = value doesn't actually change the state ? idk
user["packaging_enabled"] = True
session["user"] = user
return redirect("/dash")
else:
user["packaging_enabled"] = False
session["user"] = user
return redirect("/")
@app.route("/logout")
def logout():
session.clear()

View file

@ -0,0 +1,20 @@
wget -O - https://img.shields.io/badge/Integration-Level_9-blue.svg > level9.svg
wget -O - https://img.shields.io/badge/Integration-Level_8-brightgreen.svg > level8.svg
wget -O - https://img.shields.io/badge/Integration-Level_7-green.svg > level7.svg
wget -O - https://img.shields.io/badge/Integration-Level_6-yellowgreen.svg > level6.svg
wget -O - https://img.shields.io/badge/Integration-Level_5-yellowgreen.svg > level5.svg
wget -O - https://img.shields.io/badge/Integration-Level_4-yellow.svg > level4.svg
wget -O - https://img.shields.io/badge/Integration-Level_3-yellow.svg > level3.svg
wget -O - https://img.shields.io/badge/Integration-Level_2-orange.svg > level2.svg
wget -O - https://img.shields.io/badge/Integration-Level_1-orange.svg > level1.svg
wget -O - https://img.shields.io/badge/Integration-Level_0-red.svg > level0.svg
wget -O - https://img.shields.io/badge/Integration-Unknown-lightgrey.svg > unknown.svg
wget -O - https://upload.wikimedia.org/wikipedia/commons/1/1d/No_image.svg > empty.svg
wget -O - https://img.shields.io/badge/Status-Package%20not%20maintained-red.svg > unmaintained.svg
wget -O - https://img.shields.io/badge/Status-working-brightgreen.svg > state-working.svg
wget -O - https://img.shields.io/badge/Status-Just%20got%20added%20to%20catalog-yellowgreen.svg > state-just-got-added-to-catalog.svg
wget -O - https://img.shields.io/badge/Status-In%20progress-orange.svg > state-inprogress.svg
wget -O - https://img.shields.io/badge/Status-Not%20working-red.svg > state-notworking.svg
wget -O - https://img.shields.io/badge/Status-Broken-red.svg > state-broken.svg

View file

@ -1,13 +1,25 @@
# Download standalone tailwind to compile what we need
wget https://github.com/tailwindlabs/tailwindcss/releases/download/v3.3.3/tailwindcss-linux-x64
# Production -> download standalone tailwind to compile only what we need
wget https://github.com/tailwindlabs/tailwindcss/releases/download/v3.4.3/tailwindcss-linux-x64
chmod +x tailwindcss-linux-x64
./tailwindcss-linux-x64 --input tailwind-local.css --output tailwind.css --minify
# Development -> we use the JS magic thingy
#curl -L https://cdn.tailwindcss.com?plugins=forms > tailwind-css.js
# Dark theme stuff
git clone https://github.com/jjranalli/nightwind
# Canvasjs (for the chart page only)
curl -L https://cdn.canvasjs.com/ga/canvasjs.min.js > canvasjs.min.js
# Icons / Forkawesome
curl https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/css/fork-awesome.min.css > fork-awesome.min.css
sed -i 's@../fonts/@@g' ./fork-awesome.min.css
curl https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/fonts/forkawesome-webfont.woff2?v=1.2.0 > forkawesome-webfont.woff2
curl https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/fonts/forkawesome-webfont.woff?v=1.2.0 > forkawesome-webfont.woff
curl https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/fonts/forkawesome-webfont.ttf?v=1.2.0 > forkawesome-webfont.ttf
# Logos
curl https://raw.githubusercontent.com/YunoHost/doc/master/images/logo_roundcorner.png > ynh_logo_roundcorner.png
curl https://raw.githubusercontent.com/YunoHost/doc/master/images/ynh_logo_black.svg > ynh_logo_black.svg

View file

@ -3,6 +3,9 @@
@tailwind utilities;
@layer utilities {
input, textarea, select {
@apply !rounded-md shadow-sm !border-gray-200 !bg-neutral-50;
}
.btn {
@apply text-sm font-medium rounded-md px-4 py-2 transition;
}

View file

@ -1,11 +1,10 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['../templates/*.html'],
theme: {
extend: {},
},
darkMode: 'selector',
plugins: [
require('@tailwindcss/forms'),
require('./nightwind/src/index.js'),
],
safelist: [
'safelisted',

View file

@ -1,5 +1,7 @@
COOKIE_SECRET = "abcdefghijklmnopqrstuvwxyz1234567890"
# This secret is configured in Discourse
# This secret is configured in Discourse, "discourse connect provider secret"
# For development, a secret for "localhost" exists.
# But then be sure to access your dev server using localhost:5000, not 127.0.0.1:5000
DISCOURSE_SSO_SECRET = "abcdefghijklmnopqrstuvwxyz1234567890"
DISCOURSE_SSO_ENDPOINT = "https://forum.yunohost.org/session/sso_provider"
CALLBACK_URL_AFTER_LOGIN_ON_DISCOURSE = "http://localhost:5000/sso_login_callback"

View file

@ -0,0 +1,200 @@
import toml
import json
import os
from datetime import datetime
def _time_points_until_today():
year = 2017
month = 1
day = 1
today = datetime.today()
date = datetime(year, month, day)
while date < today:
yield date
day += 14
if day > 15:
day = 1
month += 1
if month > 12:
month = 1
year += 1
date = datetime(year, month, day)
time_points_until_today = list(_time_points_until_today())
def get_lists_history():
os.system("rm -rf ./.tmp")
os.system("git clone https://github.com/YunoHost/apps ./.tmp/apps")
for t in time_points_until_today:
print(t.strftime("%b %d %Y"))
# Fetch repo at this date
cmd = 'cd ./.tmp/apps; git checkout `git rev-list -1 --before="%s" master`'
os.system(cmd % t.strftime("%b %d %Y"))
if t < datetime(2019, 4, 4):
# Merge community and official
community = json.loads(open("./.tmp/apps/community.json").read())
official = json.loads(open("./.tmp/apps/official.json").read())
for key in official:
official[key]["state"] = "official"
merged = {}
merged.update(community)
merged.update(official)
else:
try:
merged = toml.loads(open("./.tmp/apps/apps.toml").read())
except Exception:
try:
merged = json.loads(open("./.tmp/apps/apps.json").read())
except Exception:
pass
# Save it
json.dump(
merged, open("./.tmp/merged_lists.json.%s" % t.strftime("%y-%m-%d"), "w")
)
def make_count_summary():
history = []
last_time_point = time_points_until_today[-1]
json_at_last_time_point = json.loads(
open(
"./.tmp/merged_lists.json.%s" % last_time_point.strftime("%y-%m-%d")
).read()
)
relevant_apps_to_track = [
app
for app, infos in json_at_last_time_point.items()
if infos.get("state") in ["working", "official"]
]
for d in time_points_until_today:
print("Analyzing %s ..." % d.strftime("%y-%m-%d"))
# Load corresponding json
j = json.loads(
open("./.tmp/merged_lists.json.%s" % d.strftime("%y-%m-%d")).read()
)
d_label = d.strftime("%b %d %Y")
summary = {}
summary["date"] = d_label
for level in range(0, 10):
summary["level-%s" % level] = len(
[
k
for k, infos in j.items()
if infos.get("state") in ["working", "official"]
and infos.get("level", None) == level
]
)
history.append(summary)
for app in relevant_apps_to_track:
infos = j.get(app, {})
if not infos or infos.get("state") not in ["working", "official"]:
level = -1
else:
level = infos.get("level", -1)
try:
level = int(level)
except Exception:
level = -1
json.dump(history, open(".cache/history.json", "w"))
def make_news():
news_per_date = {
d.strftime("%b %d %Y"): {
"broke": [],
"repaired": [],
"removed": [],
"added": [],
}
for d in time_points_until_today
}
previous_j = {}
def level(infos):
lev = infos.get("level")
if lev is None or (isinstance(lev, str) and not lev.isdigit()):
return -1
else:
return int(lev)
for d in time_points_until_today:
d_label = d.strftime("%b %d %Y")
print("Analyzing %s ..." % d.strftime("%y-%m-%d"))
# Load corresponding json
j = json.loads(
open("./.tmp/merged_lists.json.%s" % d.strftime("%y-%m-%d")).read()
)
apps_current = set(
k
for k, infos in j.items()
if infos.get("state") in ["working", "official"] and level(infos) != -1
)
apps_current_good = set(
k for k, infos in j.items() if k in apps_current and level(infos) > 4
)
apps_current_broken = set(
k for k, infos in j.items() if k in apps_current and level(infos) <= 4
)
apps_previous = set(
k
for k, infos in previous_j.items()
if infos.get("state") in ["working", "official"] and level(infos) != -1
)
apps_previous_good = set(
k
for k, infos in previous_j.items()
if k in apps_previous and level(infos) > 4
)
apps_previous_broken = set(
k
for k, infos in previous_j.items()
if k in apps_previous and level(infos) <= 4
)
news = news_per_date[d_label]
for app in set(apps_previous_good & apps_current_broken):
news["broke"].append((app, j[app]["url"]))
for app in set(apps_previous_broken & apps_current_good):
news["repaired"].append((app, j[app]["url"]))
for app in set(apps_current - apps_previous):
news["added"].append((app, j[app]["url"]))
for app in set(apps_previous - apps_current):
news["removed"].append((app, previous_j[app]["url"]))
previous_j = j
json.dump(news_per_date, open(".cache/news.json", "w"))
get_lists_history()
make_count_summary()
make_news()

View file

@ -0,0 +1,124 @@
import os
import sys
import requests
import json
import toml
from github import Github
sys.path = [os.path.dirname(__file__)] + sys.path
from utils import get_catalog
try:
config = toml.loads(open("config.toml").read())
except Exception:
print(
"You should create a config.toml with the appropriate key/values, cf config.toml.example"
)
sys.exit(1)
github_token = config.get("GITHUB_TOKEN")
if github_token is None:
print("You should add a GITHUB_TOKEN to config.toml")
sys.exit(1)
g = Github(github_token)
catalog = get_catalog()
main_ci_apps_results = requests.get(
"https://ci-apps.yunohost.org/ci/api/results"
).json()
nextdebian_ci_apps_results = requests.get(
"https://ci-apps-bookworm.yunohost.org/ci/api/results"
).json()
def get_github_infos(github_orga_and_repo):
repo = g.get_repo(github_orga_and_repo)
infos = {}
pulls = [p for p in repo.get_pulls()]
infos["nb_prs"] = len(pulls)
infos["nb_issues"] = repo.open_issues_count - infos["nb_prs"]
testings = [p for p in pulls if p.head.ref == "testing"]
testing = testings[0] if testings else None
ci_auto_updates = [p for p in pulls if p.head.ref.startswith("ci-auto-update")]
ci_auto_update = (
sorted(ci_auto_updates, key=lambda p: p.created_at, reverse=True)[0]
if ci_auto_updates
else None
)
for p in ([testing] if testing else []) + (
[ci_auto_update] if ci_auto_update else []
):
if p.head.label != "YunoHost-Apps:testing" and not (
p.user.login == "yunohost-bot" and p.head.ref.startswith("ci-auto-update-")
):
continue
infos["testing" if p.head.ref == "testing" else "ci-auto-update"] = {
"branch": p.head.ref,
"url": p.html_url,
"timestamp_created": int(p.created_at.timestamp()),
"timestamp_updated": int(p.updated_at.timestamp()),
"statuses": [
{
"state": s.state,
"context": s.context,
"url": s.target_url,
"timestamp": int(s.updated_at.timestamp()),
}
for s in repo.get_commit(p.head.sha).get_combined_status().statuses
],
}
return infos
consolidated_infos = {}
for app, infos in catalog["apps"].items():
if infos["state"] != "working":
continue
consolidated_infos[app] = {
"public_level": infos["level"],
"url": infos["git"]["url"],
"timestamp_latest_commit": infos["lastUpdate"],
"maintainers": infos["manifest"]["maintainers"],
"antifeatures": infos["antifeatures"],
"packaging_format": infos["manifest"]["packaging_format"],
"ci_results": {
"main": (
{
"level": main_ci_apps_results[app]["level"],
"timestamp": main_ci_apps_results[app]["timestamp"],
}
if app in main_ci_apps_results
else None
),
"nextdebian": (
{
"level": nextdebian_ci_apps_results[app]["level"],
"timestamp": nextdebian_ci_apps_results[app]["timestamp"],
}
if app in nextdebian_ci_apps_results
else None
),
},
}
if infos["git"]["url"].lower().startswith("https://github.com/"):
consolidated_infos[app].update(
get_github_infos(
infos["git"]["url"].lower().replace("https://github.com/", "")
)
)
open(".cache/dashboard.json", "w").write(json.dumps(consolidated_infos))

View file

@ -1,13 +1,14 @@
import os
install_dir = os.path.dirname(__file__)
command = f'{install_dir}/venv/bin/gunicorn'
command = f"{install_dir}/venv/bin/gunicorn"
pythonpath = install_dir
workers = 4
user = 'appstore'
bind = f'unix:{install_dir}/sock'
pid = '/run/gunicorn/appstore-pid'
errorlog = '/var/log/appstore/error.log'
accesslog = '/var/log/appstore/access.log'
user = "appstore"
bind = f"unix:{install_dir}/sock"
pid = "/run/gunicorn/appstore-pid"
errorlog = "/var/log/appstore/error.log"
accesslog = "/var/log/appstore/access.log"
access_log_format = '%({X-Real-IP}i)s %({X-Forwarded-For}i)s %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
loglevel = 'warning'
loglevel = "warning"
capture_output = True

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-05 19:36+0100\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,15 +17,16 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.14.0\n"
#: app.py:150
msgid "App %(app_id) not found"
#: app.py:162
#, python-format
msgid "App %(app_id)s not found"
msgstr ""
#: app.py:152
#: app.py:165
msgid "You must be logged in to be able to star an app"
msgstr ""
#: app.py:152 app.py:195 app.py:449 templates/wishlist_add.html:33
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid ""
"Note that, due to various abuses, we restricted login on the app store to"
" 'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -34,71 +35,71 @@ msgid ""
"minutes reading posts."
msgstr ""
#: app.py:195
#: app.py:210
msgid "You must be logged in to submit an app to the wishlist"
msgstr ""
#: app.py:207
#: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again"
msgstr ""
#: app.py:228
#: app.py:263
msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days."
msgstr ""
#: app.py:230
#: app.py:267
msgid "App name should be at least 3 characters"
msgstr ""
#: app.py:231
#: app.py:268
msgid "App name should be less than 30 characters"
msgstr ""
#: app.py:234
#: app.py:271
msgid "App description should be at least 5 characters"
msgstr ""
#: app.py:238
#: app.py:275
msgid "App description should be less than 100 characters"
msgstr ""
#: app.py:242
#: app.py:279
msgid "Upstream code repo URL should be at least 10 characters"
msgstr ""
#: app.py:246
#: app.py:283
msgid "Upstream code repo URL should be less than 150 characters"
msgstr ""
#: app.py:250
#: app.py:287
msgid "License URL should be at least 10 characters"
msgstr ""
#: app.py:254
#: app.py:291
msgid "License URL should be less than 250 characters"
msgstr ""
#: app.py:256
#: app.py:293
msgid "Website URL should be less than 150 characters"
msgstr ""
#: app.py:259
#: app.py:296
msgid "App name contains special characters"
msgstr ""
#: app.py:263
#: app.py:303
msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, "
"or repeating that the app is 'free' and 'self-hostable'."
msgstr ""
#: app.py:267
#: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr ""
#: app.py:301
#: app.py:343
#, python-format
msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, "
@ -106,7 +107,14 @@ msgid ""
"interest</a>."
msgstr ""
#: app.py:325
#: app.py:358
#, python-format
msgid ""
"An app with the name %(slug)s already exists in the catalog, <a "
"href='%(url)s'>you can see its page here</a>."
msgstr ""
#: app.py:383
#, python-format
msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe "
@ -114,7 +122,7 @@ msgid ""
"please report the issue to the YunoHost team."
msgstr ""
#: app.py:376
#: app.py:433
#, python-format
msgid ""
"Your proposed app has succesfully been submitted. It must now be "
@ -122,7 +130,7 @@ msgid ""
"href='%(url)s'>%(url)s</a>"
msgstr ""
#: app.py:449
#: app.py:528
msgid "Unfortunately, login was denied."
msgstr ""
@ -194,7 +202,7 @@ msgid "Important infos before installing"
msgstr ""
#: templates/app.html:124
msgid "Anti-features"
msgid "Antifeatures"
msgstr ""
#: templates/app.html:125
@ -234,47 +242,65 @@ msgstr ""
msgid "YunoHost package license"
msgstr ""
#: templates/base.html:5
#: templates/base.html:11
msgid "YunoHost app store"
msgstr ""
#: templates/base.html:18 templates/base.html:113 templates/index.html:3
#: templates/base.html:31 templates/base.html:154 templates/index.html:3
msgid "Home"
msgstr ""
#: templates/base.html:27 templates/base.html:122
#: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog"
msgstr ""
#: templates/base.html:33 templates/base.html:131
#: templates/base.html:46 templates/base.html:172
msgid "Wishlist"
msgstr ""
#: templates/base.html:46 templates/base.html:141
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr ""
#: templates/base.html:57
msgid "Charts & history"
msgstr ""
#: templates/base.html:71 templates/base.html:182
msgid "YunoHost documentation"
msgstr ""
#: templates/base.html:54 templates/base.html:151
#: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum"
msgstr ""
#: templates/base.html:86 templates/base.html:179
#: templates/base.html:111 templates/base.html:120 templates/base.html:220
#: templates/base.html:229
msgid "Packaging boards"
msgstr ""
#: templates/base.html:127 templates/base.html:237
msgid "Logout"
msgstr ""
#: templates/base.html:99
#: templates/base.html:140
msgid "Toggle menu"
msgstr ""
#: templates/base.html:197
#: templates/base.html:255
msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> "
"using <a class='text-blue-800' "
"href='https://flask.palletsprojects.com'>Flask</a> and <a class='text-"
"blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> - <a class"
"='text-blue-800' "
"href='https://github.com/YunoHost/apps/tree/master/store'><i class='fa "
"fa-code fa-fw' aria-hidden='true'></i> Source</a>"
"blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
msgstr ""
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80
@ -293,7 +319,7 @@ msgstr ""
msgid "All apps"
msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39
#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by"
msgstr ""
@ -306,16 +332,16 @@ msgstr ""
msgid "Newest"
msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46
#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical"
msgstr ""
#: templates/catalog.html:128 templates/wishlist.html:49
#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49
msgid "Requires to be logged-in"
msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139
#: templates/wishlist.html:51 templates/wishlist.html:60
#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred"
msgstr ""
@ -349,10 +375,208 @@ msgstr ""
#: templates/catalog.html:188
msgid ""
"This means that the developer will no longer update them. We strongly "
"This means that the developer will no longer update them. We strongly "
"advise against their installation and advise users to find alternatives."
msgstr ""
#: templates/charts.html:5
msgid "Apps quality level from automatic tests"
msgstr ""
#: templates/charts.html:9
msgid "Apps quality level history"
msgstr ""
#: templates/charts.html:14
msgid "History"
msgstr ""
#: templates/charts.html:22
msgid "Added"
msgstr ""
#: templates/charts.html:28
msgid "Repaired"
msgstr ""
#: templates/charts.html:34
msgid "Broke"
msgstr ""
#: templates/charts.html:40
msgid "Removed"
msgstr ""
#: templates/charts.html:80
msgid "Unknown"
msgstr ""
#: templates/charts.html:81
msgid "Level 0"
msgstr ""
#: templates/charts.html:82
msgid "Level 1"
msgstr ""
#: templates/charts.html:83
msgid "Level 2"
msgstr ""
#: templates/charts.html:84
msgid "Level 3"
msgstr ""
#: templates/charts.html:85
msgid "Level 4"
msgstr ""
#: templates/charts.html:86
msgid "Level 5"
msgstr ""
#: templates/charts.html:87
msgid "Level 6"
msgstr ""
#: templates/charts.html:88
msgid "Level 7"
msgstr ""
#: templates/charts.html:89
msgid "Level 8"
msgstr ""
#: templates/charts.html:107
#, python-format
msgid "Level %(level)s:"
msgstr ""
#: templates/charts.html:107
msgid "Total:"
msgstr ""
#: templates/charts.html:108
#, python-format
msgid "Level %(level)s"
msgstr ""
#: templates/dash.html:3 templates/dash.html:9
msgid "App packaging dashboard"
msgstr ""
#: templates/dash.html:11
msgid ""
"This is where packagers can monitor the status of automatic tests (CI) "
"and ongoing major pull requests accross all apps. If you want to get "
"started with app packaging in YunoHost, please check out the <a class"
"='text-blue-500' href='https://yunohost.org/packaging_apps'>packaging "
"documentation</a> and come say hi to us on the <a class='text-blue-500' "
"href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!"
msgstr ""
#: templates/dash.html:17
msgid "Filter"
msgstr ""
#: templates/dash.html:23
msgid "(None)"
msgstr ""
#: templates/dash.html:24
msgid "Regressions on main CI"
msgstr ""
#: templates/dash.html:25
msgid "Broken / low quality apps"
msgstr ""
#: templates/dash.html:26
msgid "Outdated tests on main CI"
msgstr ""
#: templates/dash.html:27
msgid "Major regressions on Bookworm CI"
msgstr ""
#: templates/dash.html:28
msgid "Apps with testings PRs"
msgstr ""
#: templates/dash.html:29
msgid "Apps with autoupdate PRs"
msgstr ""
#: templates/dash.html:30
msgid "Packaging v1 apps"
msgstr ""
#: templates/dash.html:41
msgid "Quality level"
msgstr ""
#: templates/dash.html:42 templates/dash.html:173
msgid "Popularity stars"
msgstr ""
#: templates/dash.html:43
msgid "Last update on main/master branch"
msgstr ""
#: templates/dash.html:44
msgid "Last update on testing branch"
msgstr ""
#: templates/dash.html:65
msgid "App"
msgstr ""
#: templates/dash.html:67
msgid "Main CI"
msgstr ""
#: templates/dash.html:68
msgid "Bookworm CI"
msgstr ""
#: templates/dash.html:69
msgid "Testing PR"
msgstr ""
#: templates/dash.html:70
msgid "Autoupdate PR"
msgstr ""
#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131
msgid "Broken"
msgstr ""
#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133
msgid "Low quality"
msgstr ""
#: templates/dash.html:112 templates/dash.html:127
#, python-format
msgid "Outdated test (%(days)s days ago)"
msgstr ""
#: templates/dash.html:150 templates/dash.html:165
#, python-format
msgid "Inactive (%(days)s days ago)"
msgstr ""
#: templates/dash.html:177
msgid "Packaging v1"
msgstr ""
#: templates/dash.html:180
msgid "Deprecated"
msgstr ""
#: templates/dash.html:183
msgid "Not maintained"
msgstr ""
#: templates/index.html:10
msgid "Application Store"
msgstr ""
@ -361,44 +585,10 @@ msgstr ""
msgid "Browse all applications"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote "
"for apps that they would like to see packaged and made available in "
"YunoHost's official apps catalog. Nevertheless, the fact that apps are "
"listed here should by no mean be interpreted as a fact that the YunoHost "
"project plans to integrate it, and is merely a source of inspiration for "
"packaging volunteers."
msgstr ""
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr ""
@ -417,6 +607,10 @@ msgid ""
"send every random nerdy stuff you find on the Internet."
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr ""
@ -461,3 +655,33 @@ msgstr ""
msgid "Submit"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote "
"for apps that they would like to see packaged and made available in "
"YunoHost's official apps catalog. Nevertheless, the fact that apps are "
"listed here should by no mean be interpreted as a fact that the YunoHost "
"project plans to integrate it, and is merely a source of inspiration for "
"packaging volunteers."
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""

View file

@ -1,9 +1,32 @@
Flask==2.3.2
python-slugify
PyGithub
toml
pycmarkgfm
gunicorn
emoji
Babel
Flask-Babel
Babel==2.14.0
blinker==1.8.1
certifi==2024.2.2
cffi==1.16.0
charset-normalizer==3.3.2
click==8.1.7
cryptography==42.0.5
Deprecated==1.2.14
emoji==2.11.1
Flask==3.0.3
flask-babel==4.0.0
gunicorn==22.0.0
idna==3.7
itsdangerous==2.2.0
Jinja2==3.1.4
MarkupSafe==2.1.5
packaging==24.0
pycmarkgfm==1.2.1
pycparser==2.22
PyGithub==2.3.0
PyJWT==2.8.0
PyNaCl==1.5.0
python-slugify==8.0.4
pytz==2024.1
requests==2.32.0
text-unidecode==1.3
toml==0.10.2
tomlkit==0.12.4
typing_extensions==4.11.0
urllib3==2.2.1
Werkzeug==3.0.3
wrapt==1.16.0

View file

@ -16,7 +16,7 @@
loading="lazy"
class="h-12 w-12 rounded-lg object-cover shadow-sm mt-1"
>
<h1 class="flex-0 pl-2 pt-3 {% if infos["manifest"]["name"]|length > 12 %}text-2xl{% else %}text-3xl{% endif %} font-bold text-gray-900">{{ infos["manifest"]["name"] }}</h1>
<h1 class="flex-0 pl-2 pt-3 {% if infos["manifest"]["name"]|length > 12 %}text-2xl{% else %}text-3xl{% endif %} font-bold">{{ infos["manifest"]["name"] }}</h1>
{% if infos['category'] %}
<span class="ml-2 mb-1 rounded-full px-2.5 py-0.5 text-[10px] border text-{{ catalog['categories'][infos['category']]['color'] }}-600 border-{{ catalog['categories'][infos['category']]['color'] }}-400 ">
@ -82,7 +82,7 @@
<span class="inline sm:hidden">{{ _("Demo") }}</span>
</a>
{% endif %}
<a aria-label="{{ _('Install with YunoHost') }}" title="{{ _('Install with YunoHost') }}" class="h-9.5 inline-block rounded-md border p-0 bg-gray-900 text-white " href="https://install-app.yunohost.org/?app={{ app_id }}">
<a aria-label="{{ _('Install with YunoHost') }}" title="{{ _('Install with YunoHost') }}" class="h-9.5 inline-block rounded-md border border-gray-300 p-0 bg-gray-900 dark:bg-gray-50 text-white dark:text-black" href="https://install-app.yunohost.org/?app={{ app_id }}">
<span class="inline-block text-[11px] leading-3 text-center py-1.5 pl-2">Install<br/>with</span>
<span class="inline-block pr-2 pt-1"><img alt="YunoHost" src="{{ url_for('static', filename='horizontal-yunohost.svg') }}"></span>
</a>
@ -121,7 +121,7 @@
{% endif %}
{% if infos["antifeatures"] %}
<h2 class="inline-block text-xl mb-2 font-semibold">{{ _("Anti-features") }}</h2>
<h2 class="inline-block text-xl mb-2 font-semibold">{{ _("Antifeatures") }}</h2>
<p class="inline-block text-sm">{{ _("(This app has features you may not like)") }}</p>
<div class="my-3 rounded-md bg-red-100 text-red-800 px-5 py-2">
<ul>

View file

@ -1,3 +1,9 @@
{% if user and user.get('packaging_enabled') or request.endpoint in ["dash", "charts"] %}
{% set packaging_enabled = True %}
{% else %}
{% set packaging_enabled = False %}
{% endif %}
<!DOCTYPE html>
<html lang="{{ locale }}">
@ -7,9 +13,16 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{{ url_for('static', filename='fork-awesome.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='tailwind.css') }}">
<script>
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
</script>
</head>
<body>
<body class="bg-neutral-50 text-gray-800">
<header class="pb-2 shadow-sm">
<div
class="flex h-12 items-center gap-8 pt-2 px-4 sm:px-6 lg:px-8"
@ -23,16 +36,28 @@
<nav class="hidden md:block">
<ul class="flex items-center gap-6 text-sm">
<li>
<a class="text-gray-800 font-bold transition hover:text-gray-500/75" href="{{ url_for('browse_catalog') }}">
<a class="font-bold transition hover:opacity-75" href="{{ url_for('browse_catalog') }}">
{{ _("Catalog") }}
</a>
</li>
<li>
<a class="text-gray-800 font-bold transition hover:text-gray-500/75" href="{{ url_for('browse_wishlist') }}">
<a class="font-bold transition hover:opacity-75" href="{{ url_for('browse_wishlist') }}">
{{ _("Wishlist") }}
</a>
</li>
{% if packaging_enabled %}
<li>
<a class="font-bold transition hover:opacity-75" href="{{ url_for('dash') }}">
{{ _("Packaging dashboard") }}
</a>
</li>
<li>
<a class="font-bold transition hover:opacity-75" href="{{ url_for('charts') }}">
{{ _("Charts & history") }}
</a>
</li>
{% endif %}
</ul>
</nav>
@ -45,6 +70,15 @@
<i class="fa fa-external-link fa-fw" aria-hidden="true"></i>
{{ _("YunoHost documentation") }}
</a>
<a
class="inline-block"
role="button"
target="_blank"
id="toggleDarkMode"
>
<i class="fa fa-sun-o inline-block dark:hidden rounded-md border border-gray-300 px-3 py-2.5 hover:bg-gray-100" aria-hidden="true" title="{{ _('Toggle light/dark mode') }}"></i>
<i class="fa fa-moon-o hidden dark:inline-block rounded-md border border-gray-300 px-3 py-2.5 hover:bg-gray-100" aria-hidden="true" title="{{ _('Toggle light/dark mode') }}"></i>
</a>
{% if not user %}
<a
class="btn btn-primary inline-block"
@ -78,9 +112,25 @@
role="menu"
>
<div class="p-2">
<a href="/toggle_packaging"
class="block rounded-md px-4 py-2 text-sm hover:bg-gray-50 hover:text-gray-700"
role="menuitem"
>
<label for="toggle_packaging" class="inline-block relative mr-1 h-3 w-6 cursor-pointer">
<span class="sr-only">{{ _("Packaging boards") }} {{ user }}</span>
<input type="checkbox" id="toggle_packaging" class="peer sr-only" {% if user and user.get('packaging_enabled') %}checked{% endif %} disabled>
<span class="absolute inset-0 rounded-full bg-gray-300 transition peer-checked:bg-green-500">
</span>
<span class="absolute inset-y-0 start-0 my-0.5 ml-1 h-2 w-2 rounded-full bg-white transition-all peer-checked:start-2">
</span>
</label>
{{ _("Packaging boards") }}
</a>
<a
href="/logout"
class="block rounded-md px-4 py-2 text-sm text-gray-800 hover:bg-gray-50 hover:text-gray-700"
class="block rounded-md px-4 py-2 text-sm hover:bg-gray-50 hover:text-gray-700"
role="menuitem"
>
{{ _("Logout") }}
@ -101,7 +151,7 @@
</button>
<div
id="menu"
class="hidden absolute end-0 z-10 mt-2 p-2 w-64 rounded-md border border-gray-100 text-gray-800 bg-white shadow-lg"
class="hidden absolute end-0 z-10 mt-2 p-2 w-64 rounded-md border border-gray-100 bg-white shadow-lg"
role="menu"
>
<div class="px-2 py-0.5">
@ -171,6 +221,23 @@
</span>
</div>
<div class="px-2 py-0.5">
<a href="/toggle_packaging"
class="block rounded-md px-4 py-3 text-sm hover:bg-gray-100"
role="menuitem"
>
<label for="toggle_packaging" class="inline-block relative mr-1 h-3 w-6 cursor-pointer">
<span class="sr-only">{{ _("Packaging boards") }}</span>
<input type="checkbox" id="toggle_packaging" class="peer sr-only" {% if user and user.get('packaging_enabled') %}checked{% endif%} disabled>
<span class="absolute inset-0 rounded-full bg-gray-300 transition peer-checked:bg-green-500">
</span>
<span class="absolute inset-y-0 start-0 my-0.5 ml-1 h-2 w-2 rounded-full bg-white transition-all peer-checked:start-2">
</span>
</label>
{{ _("Packaging boards") }}
</a>
<a
href="/logout"
class="block rounded-md px-4 py-3 text-sm hover:bg-gray-100"
@ -187,19 +254,32 @@
</div>
</header>
<main>
<main class="mx-auto max-w-screen-lg">
{% block main %}
{% endblock %}
</main>
<footer class="h-5 my-5 text-center">
<p>
{{ _("Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using <a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> - <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>") }}
</p>
<p>
{{ _("Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using <a class='text-blue-800 dark:text-blue-400' href='https://flask.palletsprojects.com'>Flask</a> and <a class='text-blue-800 dark:text-blue-400' href='https://tailwindcss.com/'>TailwindCSS</a>") }}
<a class='text-blue-800 dark:text-blue-400' href='https://github.com/YunoHost/apps/tree/master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> {{ _("Source") }}</a>
<a class='text-blue-800 dark:text-blue-400' href='https://yunohost.org/tos'>{{ _("Terms of Services") }}</a>
</p>
</footer>
</body>
<script type="text/javascript">
document.getElementById('toggleDarkMode').addEventListener('click', () => {
document.documentElement.classList.toggle('dark')
if (document.documentElement.classList.contains("dark") == true)
{
localStorage.theme = 'dark';
}
else
{
localStorage.theme = 'light';
}
});
{% if user %}
document.getElementById('toggleUserMenu').addEventListener('click', () => {
document.getElementById('userMenu').classList.toggle("hidden");
@ -209,5 +289,4 @@
document.getElementById('menu').classList.toggle("hidden");
});
</script>
</html>

View file

@ -16,7 +16,7 @@
>
<a
href="{{ url_for('app_info', app_id=app) }}"
class="relative block overflow-hidden rounded-lg py-2 px-4 hover:bg-gray-100 mx-2 md:mx-0"
class="relative block overflow-hidden rounded-lg py-2 px-4 hover:bg-neutral-100 mx-2 md:mx-0"
>
<div class="flex justify-between gap-4">
<div class="shrink-0">
@ -27,12 +27,12 @@
src="{{ url_for('static', filename='app_logo_placeholder.png') }}"
{% endif %}
loading="lazy"
class="h-12 w-12 rounded-lg object-cover shadow-sm mt-1"
class="h-12 w-12 rounded-lg object-cover shadow mt-1"
>
</div>
<div class="w-full">
<span class="flex">
<h3 class="grow text-md font-bold text-gray-900">
<h3 class="grow text-md font-bold">
{{ infos['manifest']['name'] }}
</h3>
<span class="text-xs">
@ -53,14 +53,16 @@
</span>
</span>
</span>
<p class="max-w-[40ch] text-xs text-gray-700">
<p class="max-w-[40ch] text-xs opacity-75">
{{ infos['manifest']['description']|localize }}
</p>
<div class="hidden">
{{ infos["potential_alternative_to"]|join(', ') }}
</div>
{% if infos['category'] %}
<span class="rounded-full px-2.5 py-0.5 text-[10px] border text-{{ catalog['categories'][infos['category']]['color'] }}-600 border-{{ catalog['categories'][infos['category']]['color'] }}-400 ">
<span class="rounded-full px-2.5 py-0.5 text-[10px] border
text-{{ catalog['categories'][infos['category']]['color'] }}-600
border-{{ catalog['categories'][infos['category']]['color'] }}-400 ">
{{ catalog['categories'][infos['category']]['title']|localize|lower }}
</span>
{% endif %}
@ -76,7 +78,7 @@
{% endblock %}
{% block main %}
<div class="mt-5 text-center">
<h1 class="text-2xl font-bold text-gray-900">
<h1 class="text-2xl font-bold">
{{ _("Application Catalog") }}
</h1>
</div>
@ -89,8 +91,8 @@
type="text"
id="search"
placeholder="{{ _('Search for…') }}"
{% if init_search %}value="{{ init_search }}"{% endif %}
class="w-full rounded-md border-gray-200 shadow-sm sm:text-sm py-2 pe-10"
{% if request.args.get("search") %}value="{{ request.args.get("search") }}"{% endif %}
class="w-full sm:text-sm py-2 pe-10"
>
<span class="absolute inset-y-0 end-0 grid w-10 place-content-center pr-4">
@ -102,11 +104,11 @@
<select
name="selectcategory"
id="selectcategory"
class="w-full rounded-md border-gray-200 shadow-sm sm:test-sm px-2 py-1.5"
class="w-full sm:text-sm px-2 py-1.5"
>
<option value="">{{ _("All apps") }}</option>
{% for id, category in catalog['categories'].items() %}
<option {% if id == init_category %}selected{% endif %} value="{{ id }}">{{ category['title']|localize }}</option>
<option {% if id == request.args.get("category") %}selected{% endif %} value="{{ id }}">{{ category['title']|localize }}</option>
{% endfor %}
</select>
</div>
@ -118,17 +120,17 @@
<select
name="selectsort"
id="selectsort"
class="inline-block rounded-md border-gray-200 text-sm ml-1 pl-1 pr-7 h-8 py-0"
class="inline-block text-sm ml-1 pl-1 pr-7 h-8 py-0"
>
<option {% if not init_sort or init_sort == "popularity" %}selected{% endif %} value="popularity">{{ _("Popularity") }}</option>
<option {% if init_sort == "newest" %}selected{% endif %} value="newest">{{ _("Newest") }}</option>
<option {% if init_sort == "alpha" %}selected{% endif %} value="alpha">{{ _("Alphabetical") }}</option>
<option {% if request.args.get("sort") in [None, "popularity"] %}selected{% endif %} value="popularity">{{ _("Popularity") }}</option>
<option {% if request.args.get("sort") == "newest" %}selected{% endif %} value="newest">{{ _("Newest") }}</option>
<option {% if request.args.get("sort") == "alpha" %}selected{% endif %} value="alpha">{{ _("Alphabetical") }}</option>
</select>
</div>
<div class="inline-block flex items-center px-2 pt-2 md:pt-0 {% if not user %}text-gray-500{% endif %}" {% if not user %}title="{{ _('Requires to be logged-in') }}" aria-label="{{ _('Requires to be logged-in') }}"{% endif %}>
<div class="inline-block flex items-center px-2 pt-2 md:pt-0 {% if not user %}opacity-75{% endif %}" {% if not user %}title="{{ _('Requires to be logged-in') }}" aria-label="{{ _('Requires to be logged-in') }}"{% endif %}>
<label for="starsonly" class="inline-block relative mr-2 h-4 w-7 cursor-pointer">
<span class="sr-only">{{ _("Show only apps you starred") }}</span>
<input type="checkbox" id="starsonly" class="peer sr-only" {% if user and init_starsonly %}checked{% endif %} {% if not user%}disabled{% endif %} >
<input type="checkbox" id="starsonly" class="peer sr-only" {% if user and request.args.get("starsonly") %}checked{% endif %} {% if not user%}disabled{% endif %} >
<span class="absolute inset-0 rounded-full bg-gray-300 transition peer-checked:bg-green-500">
</span>
@ -151,10 +153,10 @@
<div id="noResultFound" class="text-center pt-5 hidden">
<p class="text-lg font-bold text-gray-900 mb-5">
<p class="text-lg font-bold mb-5">
{{ _("No results found.") }}
</p>
<p class="text-md text-gray-900">
<p class="text-md">
{{ _("Not finding what you are looking for?") }}<br/>
{{ _("Checkout the wishlist!") }}
</p>
@ -162,7 +164,7 @@
<div id="lowQualityAppTitle" class="text-center pt-10 mx-4 md:mx-0">
<h2 class="text-lg font-bold text-gray-900">
<h2 class="text-lg font-bold">
{{ _("Applications currently flagged as broken") }}
</h2>
<p class="text-sm">
@ -180,7 +182,7 @@
</div>
<div id="deprecatedAppTitle" class="text-center pt-10 mx-4 md:mx-0">
<h2 class="text-lg font-bold text-gray-900">
<h2 class="text-lg font-bold">
{{ _("Deprecated applications") }}
</h2>
<p class="text-sm">

140
store/templates/charts.html Normal file
View file

@ -0,0 +1,140 @@
{% extends "base.html" %}
{% block main %}
<div class="w-full">
<h1 class="text-center font-medium text-2xl py-2">{{ _("Apps quality level from automatic tests") }}</h1>
<div id="levelRing" class="h-80"></div>
</div>
<div class="w-full">
<h1 class="text-center font-medium text-2xl py-2">{{ _("Apps quality level history") }}</h1>
<div id="levelHistory" class="h-80"></div>
</div>
<div class="mx-auto w-80 py-2">
<h1 class="text-center font-medium text-2xl pt-4">
{{ _("History") }}
<link rel="alternate" type="application/rss+xml" title="YunoHost apps catalog news" href="{{ url_for('news_rss')}}" />
<a href="{{ url_for('news_rss')}}" class="btn btn-sm h-6 bg-orange-500 text-white !font-bold align-middle !px-2 !py-1"><i class="fa fa-rss-square" aria-hidden="true"></i> Suscribe via RSS</a>
</h1>
<div>
{% for date, news in news_per_date.items()|reverse %}
<h2 class="text-center font-medium text-xl py-4">{{ date }}</h2>
<ul>
{% for app, url in news["added"] %}
<li>
<span class="text-sm text-center inline-block w-24 rounded border border-blue-600 text-blue-600 mr-1"><i class="fa fa-plus" aria-hidden="true"></i> {{ _("Added") }}</span>
<a href="{{url}}">{{app}}</a>
</li>
{% endfor %}
{% for app, url in news["repaired"] %}
<li>
<span class="text-sm text-center inline-block w-24 rounded border border-green-600 text-green-600 mr-1"><i class="fa fa-check" aria-hidden="true"></i> {{ _("Repaired") }}</span>
<a href="{{url}}">{{app}}</a>
</li>
{% endfor %}
{% for app, url in news["broke"] %}
<li>
<span class="text-sm text-center inline-block w-24 rounded border border-amber-600 text-amber-600 mr-1"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> {{ _("Broke") }}</span>
<a href="{{url}}">{{app}}</a>
</li>
{% endfor %}
{% for app, url in news["removed"] %}
<li>
<span class="text-sm text-center inline-block w-24 rounded border border-red-600 text-red-600 mr-1"><i class="fa fa-times" aria-hidden="true"></i> {{ _("Removed") }}</span>
<a href="{{url}}">{{app}}</a>
</li>
{% endfor %}
</ul>
{% endfor %}
</div>
</div>
<script src="{{ url_for('static', filename='canvasjs.min.js') }}"></script>
<script>
window.onload = function () {
var theme = "light1";
if (document.documentElement.classList.contains("dark") == true)
{
theme = "dark1";
}
var colors_per_level = [
"#d9534f",
"#E26D4F",
"#E98D4E",
"#f0ad4e",
"#CBB052",
"#A6B255",
"#7AB659",
"#5cb85c",
"#4695d5",
"#8960b3"
];
new CanvasJS.Chart("levelRing", {
backgroundColor: 'transparent',
theme: theme,
animationEnabled: false,
data: [{
type: "doughnut",
startAngle: -90,
//innerRadius: 60,
indexLabelFontSize: 17,
indexLabel: "{label} - {y}",
toolTipContent: "<b>{label}:</b> {y}",
dataPoints: [
{ y: {{ level_summary["unknown"] }}, label: "{{ _("Unknown") }}", color: "#cccccc" },
{ y: {{ level_summary[0] }}, label: "{{ _("Level 0") }}", color: colors_per_level[0] },
{ y: {{ level_summary[1] }}, label: "{{ _("Level 1") }}", color: colors_per_level[1] },
{ y: {{ level_summary[2] }}, label: "{{ _("Level 2") }}", color: colors_per_level[2] },
{ y: {{ level_summary[3] }}, label: "{{ _("Level 3") }}", color: colors_per_level[3] },
{ y: {{ level_summary[4] }}, label: "{{ _("Level 4") }}", color: colors_per_level[4] },
{ y: {{ level_summary[5] }}, label: "{{ _("Level 5") }}", color: colors_per_level[5] },
{ y: {{ level_summary[6] }}, label: "{{ _("Level 6") }}", color: colors_per_level[6] },
{ y: {{ level_summary[7] }}, label: "{{ _("Level 7") }}", color: colors_per_level[7] },
{ y: {{ level_summary[8] }}, label: "{{ _("Level 8") }}", color: colors_per_level[8] },
]
}]
}).render();
new CanvasJS.Chart("levelHistory", {
backgroundColor: 'transparent',
theme: theme,
animationEnabled: false,
toolTip: {
reversed: true,
shared: true
},
data: [
{% for level in range(8,-1,-1) %}
{
color: colors_per_level[{{ level }}],
type: "stackedArea",
showInLegend: true,
toolTipContent: "<span style=\"color:"+colors_per_level[{{ level }}]+"\"><strong>{{ _("Level %(level)s:", level=level) }}</strong></span> {y}{% if loop.first %}<br><b>{{ _("Total:") }} #total</b> @ {label}{% endif %}",
name: "{{ _("Level %(level)s", level=level) }}",
dataPoints: [
{% for d in history %}
{ label: "{{ d.date }}", y: {{ d["level-"+level|string] }} },
{% endfor %}
]
},
{% endfor %}
]
}).render();
}
</script>
{% endblock %}

446
store/templates/dash.html Normal file
View file

@ -0,0 +1,446 @@
{% extends "base.html" %}
{% block title %}
{{ _("App packaging dashboard") }}
{% endblock %}
{% block main %}
<div class="mx-auto w-full text-center px-4 py-8">
<h1 class="text-2xl font-bold">
{{ _("App packaging dashboard") }}
</h1>
<p class="text-sm text-gray-700 mx-2 md:mx-32 mt-2">{{ _("This is where packagers can monitor the status of automatic tests (CI) and ongoing major pull requests accross all apps. If you want to get started with app packaging in YunoHost, please check out the <a class='text-blue-500' href='https://yunohost.org/packaging_apps'>packaging documentation</a> and come say hi to us on the <a class='text-blue-500' href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!") }}</p>
</div>
<div class="text-center justify-center space-y-3 md:space-y-0 md:space-x-3 px-2 md:px-10 lg:px-20 flex flex-col flex-wrap md:flex-row pb-5">
<div>
{{ _("Filter") }}
<select
name="selectfilter"
id="selectfilter"
class="rounded-md border-gray-200 text-sm h-8 py-0 max-w-72 sm:max-none"
>
<option {% if request.args.get("filter") in [None, "none"] %}selected{% endif %} value="none">{{ _("(None)") }}</option>
<option {% if request.args.get("filter") == "regressions_main_ci" %}selected{% endif %} value="regressions_main_ci">{{ _("Regressions on main CI") }}</option>
<option {% if request.args.get("filter") == "broken_low_quality" %}selected{% endif %} value="broken_low_quality">{{ _("Broken / low quality apps") }}</option>
<option {% if request.args.get("filter") == "outdated" %}selected{% endif %} value="outdated">{{ _("Outdated tests on main CI") }}</option>
<option {% if request.args.get("filter") == "regressions_bookworm" %}selected{% endif %} value="regressions_bookworm">{{ _("Major regressions on Bookworm CI") }}</option>
<option {% if request.args.get("filter") == "testings" %}selected{% endif %} value="testings">{{ _("Apps with testings PRs") }}</option>
<option {% if request.args.get("filter") == "autoupdate" %}selected{% endif %} value="autoupdate">{{ _("Apps with autoupdate PRs") }}</option>
<option {% if request.args.get("filter") == "packagingv1" %}selected{% endif %} value="packagingv1">{{ _("Packaging v1 apps") }}</option>
</select>
</div>
<div>
{{ _("Sort by") }}
<select
name="selectsort"
id="selectsort"
class="rounded-md border-gray-200 text-sm h-8 py-0 max-w-72 sm:max-none"
>
<option {% if request.args.get("sort") == "alpha" %}selected{% endif %} value="alpha">{{ _("Alphabetical") }}</option>
<option {% if request.args.get("sort") == "level" %}selected{% endif %} value="level">{{ _("Quality level") }}</option>
<option {% if request.args.get("sort") in [None, "stars"] %}selected{% endif %} value="stars">{{ _("Popularity stars") }}</option>
<option {% if request.args.get("sort") == "main_branch_update" %}selected{% endif %} value="main_branch_update">{{ _("Last update on main/master branch") }}</option>
<option {% if request.args.get("sort") == "testing_branch_update" %}selected{% endif %} value="testing_branch_update">{{ _("Last update on testing branch") }}</option>
</select>
</div>
<div class="w-fit mx-auto flex items-center px-2 pt-2">
<label for="hidedeprecated" class="inline-block relative mr-2 h-4 w-7 cursor-pointer">
<span class="sr-only">{{ _("Hide deprecated/unmaintained apps") }}</span>
<input type="checkbox" id="hidedeprecated" class="peer sr-only" {% if request.args.get("hidedeprecated") %}checked{% endif %} >
<span class="absolute inset-0 rounded-full bg-gray-300 transition peer-checked:bg-green-500">
</span>
<span class="absolute inset-y-0 start-0 m-1 h-2 w-2 rounded-full bg-white transition-all peer-checked:start-3">
</span>
</label>
{{ _("Hide deprecated/unmaintained apps") }}
</div>
<div class="w-fit mx-auto flex items-center px-2 pt-2 {% if not user %}text-gray-500{% endif %}" {% if not user %}title="{{ _('Requires to be logged-in') }}" aria-label="{{ _('Requires to be logged-in') }}"{% endif %}>
<label for="starsonly" class="inline-block relative mr-2 h-4 w-7 cursor-pointer">
<span class="sr-only">{{ _("Show only apps you starred") }}</span>
<input type="checkbox" id="starsonly" class="peer sr-only" {% if user and request.args.get("starsonly") %}checked{% endif %} {% if not user%}disabled{% endif %} >
<span class="absolute inset-0 rounded-full bg-gray-300 transition peer-checked:bg-green-500">
</span>
<span class="absolute inset-y-0 start-0 m-1 h-2 w-2 rounded-full bg-white transition-all peer-checked:start-3">
</span>
</label>
{{ _("Show only apps you starred") }}
</div>
</div>
<table id="appTable" class="mx-auto text-sm sm:text-base">
<tr class="h-40 md:h-20">
<th class="max-w-24 md:max-w-32">{{ _("App") }}</th>
<th class="-rotate-90 md:-rotate-45 max-w-10 md:max-w-16 text-left text-nowrap">{{ _("Catalog") }}</th>
<th class="-rotate-90 md:-rotate-45 max-w-10 md:max-w-16 text-left text-nowrap">{{ _("Main CI") }}</th>
<th class="-rotate-90 md:-rotate-45 max-w-10 md:max-w-16 text-left text-nowrap">{{ _("Bookworm CI") }}</th>
<th class="-rotate-90 md:-rotate-45 max-w-10 md:max-w-16 text-left text-nowrap">{{ _("Testing PR") }}</th>
<th class="-rotate-90 md:-rotate-45 max-w-10 md:max-w-16 text-left text-nowrap">{{ _("Autoupdate PR") }}</th>
<th></th>
</tr>
{% for app, infos in data.items() %}
{% set this_app_stars = stars.get(app, {})|length %}
{% if user %}
{% set user_starred_this_app = user['id'] in stars.get(app, {}) %}
{% else %}
{% set user_starred_this_app = False %}
{% endif %}
<tr
class="app h-8 hover:bg-gray-100
{% if "deprecated-software" in infos["antifeatures"] or "replaced-by-another-app" in infos["antifeatures"] or "package-not-maintained" in infos["antifeatures"] %}
opacity-50
{% endif %}"
data-app="{{ app }}"
data-popularity-stars="{{ this_app_stars }}"
data-starred="{{ user_starred_this_app }}"
data-public-level="{{ infos["public_level"] if infos["public_level"] != "?" else -1 }}"
data-main-ci-level="{% if infos["ci_results"]["main"] %}{{ infos["ci_results"]["main"]["level"] }}{% else %}-1{% endif %}"
data-main-ci-daysago="{% if infos["ci_results"]["main"] %}{{ infos["ci_results"]["main"]["timestamp"] | days_ago }}{% else %}-9999{% endif %}"
data-nextdebian-ci-level="{% if infos["ci_results"]["nextdebian"] %}{{ infos["ci_results"]["nextdebian"]["level"] }}{% else %}-1{% endif %}"
data-last-update-master="{{ infos["ci_results"]["main"]["timestamp"] }}"
data-last-update-testing="{% if infos["testing"] %}{{ infos["testing"]["timestamp_updated"] }}{% else %}-1{% endif %}"
data-last-update-autoupdate="{% if infos["ci-auto-update"] %}{{ infos["ci-auto-update"]["timestamp_updated"] }}{% else %}-1{% endif %}"
data-packaging-format="{{ infos["packaging_format"] }}"
data-deprecated="{% if "deprecated-software" in infos["antifeatures"] or "replaced-by-another-app" in infos["antifeatures"] or "package-not-maintained" in infos["antifeatures"] %}True{% else %}False{% endif %}"
>
<td class="truncate max-w-24 md:max-w-64 text-center text-blue-600 font-medium">
<a href="{{ infos["url"] }}">{{ app }}</a>
</td>
<td class="font-bold text-center">
<a href="{{ url_for('app_info', app_id=app) }}">
{{ infos["public_level"] }}
{% if infos["public_level"] == "?" %}
{% elif infos["public_level"] == 0 %}
<i class="fa fa-exclamation-circle text-red-500" title="{{ _("Broken") }}"></i>
{% elif infos["public_level"] <= 4 %}
<i class="fa fa-exclamation-triangle text-amber-500" title="{{ _("Low quality") }}"></i>
{% endif %}
</a>
</td>
<td class="border-l-2 border-gray-100 text-center">
<a class="{% if infos["public_level"] == infos["ci_results"]["main"]["level"] or infos["ci_results"]["main"]["timestamp"] | days_ago > 30 %}opacity-50{% endif %}" href="https://ci-apps.yunohost.org/ci/apps/{{ app }}/">
{% if infos["public_level"] == infos["ci_results"]["main"]["level"] %}
=
{% else %}
{{ infos["ci_results"]["main"]["level"] }}
{% endif %}
{% if infos["ci_results"]["main"]["timestamp"] | days_ago > 30 %}
<i class="fa fa-hourglass-o" title="{{ _("Outdated test (%(days)s days ago)", days=infos["ci_results"]["main"]["timestamp"] | days_ago) }}"></i>
{% endif %}
{% if infos["public_level"] == "?" %}
{% elif infos["ci_results"]["main"]["level"] < infos["public_level"] and infos["ci_results"]["main"]["level"] == 0 %}
<i class="fa fa-exclamation-circle text-red-500" title="{{ _("Broken") }}"></i>
{% elif infos["ci_results"]["main"]["level"] < infos["public_level"] and infos["ci_results"]["main"]["level"] <= 4 %}
<i class="fa fa-exclamation-triangle text-amber-500" title="{{ _("Low quality") }}"></i>
{% endif %}
</a>
</td>
<td class="text-center">
<a class="{% if infos["ci_results"]["nextdebian"] and ((infos["public_level"] == infos["ci_results"]["nextdebian"]["level"]) or (infos["ci_results"]["nextdebian"]["timestamp"] | days_ago) > 30) %}opacity-50{% endif %}" href="https://ci-apps-bookworm.yunohost.org/ci/apps/{{ app }}/">
{% if infos["ci_results"]["nextdebian"] %}
{% if infos["public_level"] == infos["ci_results"]["nextdebian"]["level"] %}
=
{% else %}
{{ infos["ci_results"]["nextdebian"]["level"] }}
{% endif %}
{% if infos["ci_results"]["nextdebian"]["timestamp"] | days_ago > 30 %}
<i class="fa fa-hourglass-o" title="{{ _("Outdated test (%(days)s days ago)", days=infos["ci_results"]["nextdebian"]["timestamp"] | days_ago) }}"></i>
{% endif %}
{% if infos["public_level"] == "?" %}
{% elif infos["ci_results"]["nextdebian"]["level"] < infos["public_level"] and infos["ci_results"]["nextdebian"]["level"] == 0 %}
<i class="fa fa-exclamation-circle text-red-500" title="{{ _("Broken") }}"></i>
{% elif infos["ci_results"]["nextdebian"]["level"] < infos["public_level"] and infos["ci_results"]["nextdebian"]["level"] <= 4 %}
<i class="fa fa-exclamation-triangle text-amber-500" title="{{ _("Low quality") }}"></i>
{% endif %}
{% else %}
?
{% endif %}
</a>
</td>
<td class="border-l-2 border-gray-100 text-center">
{% if "testing" in infos %}
<a href="{{ infos["testing"]["url"] }}">
<i class="fa fa-flask"></i>
{% for s in infos["testing"]["statuses"] %}
{% if s["context"] == "ci-apps-dev" %}
<i class="fa fa-{% if s["state"] == "success" %}check-circle text-green-600{% else %}times-circle text-red-500{% endif %}"></i>
{% endif %}
{% endfor %}
{% if infos["testing"]["timestamp_updated"] | days_ago > 30 %}
<i class="text-gray-500 fa fa-clock-o" title="{{ _("Inactive (%(days)s days ago)", days=infos["testing"]["timestamp_updated"] | days_ago) }}"></i>
{% endif %}
</a>
{% endif %}
</td>
<td class="border-r-2 border-gray-100 text-center"
{% if "ci-auto-update" in infos %}
<a href="{{ infos["ci-auto-update"]["url"] }}">
<i class="fa fa-arrow-up"></i>
{% for s in infos["ci-auto-update"]["statuses"] %}
{% if s["context"] == "ci-apps-dev" %}
<i class="fa fa-{% if s["state"] == "success" %}check-circle text-green-600{% else %}times-circle text-red-500{% endif %}"></i>
{% endif %}
{% endfor %}
{% if infos["ci-auto-update"]["timestamp_updated"] | days_ago > 30 %}
<i class="text-gray-500 fa fa-clock-o" title="{{ _("Inactive (%(days)s days ago)", days=infos["ci-auto-update"]["timestamp_updated"] | days_ago) }}"></i>
{% endif %}
</a>
{% endif %}
</td>
<td class="px-3 truncate text-sm max-w-16 sm:max-w-full">
{% if this_app_stars > 0 %}
<span class="text-xs border-purple-400 text-purple-600 px-1 py-0 border rounded">{{ this_app_stars }}
<i class="fa {% if not user_starred_this_app %}fa-star-o{% else %}fa-star{% endif %}" aria-hidden="true" title="{{ _("Popularity stars") }}"></i>
</span>
{% endif %}
{% if infos["packaging_format"] == 1 %}
<span class="text-xs border-gray-400 px-1 py-0 border rounded"><i class="fa fa-meh-o"></i> {{ _("Packaging v1") }}</span>
{% endif %}
{% if "deprecated-software" in infos["antifeatures"] or "replaced-by-another-app" in infos["antifeatures"] %}
<span class="text-xs border-gray-400 px-1 py-0 border rounded"><i class="fa fa-flag-o"></i> {{ _("Deprecated") }}</span>
{% endif %}
{% if "package-not-maintained" in infos["antifeatures"] %}
<span class="text-xs border-gray-400 px-1 py-0 border rounded"><i class="fa fa-flag-o"></i> {{ _("Not maintained") }}</span>
{% endif %}
<!--
Maintainers
NB issues, PRs
Autoupdate enabled?
-->
</td>
</tr>
{% endfor %}
</table>
<div id="nbEntriesFound" class="text-center text-gray-600 text-sm py-3"></div>
<div class="text-center text-gray-600 text-sm py-3">{{ _("Last data update %(time)s ago", time=last_data_update|hours_ago) }}</div>
<script type="text/javascript">
function updateFilter() {
// Locate the card elements
let entries = document.getElementsByClassName('app')
let filterName = selectFilter.value.trim();
let nb_found = 0;
let starsOnly = toggleStarsonly.checked;
let hideDeprecated = toggleHidedeprecated.checked;
// Loop through the entries
for (var i = 0; i < entries.length; i++) {
if ((starsOnly) && (entries[i].dataset.starred != "True"))
{
entries[i].classList.add("hidden");
continue;
}
if ((hideDeprecated) && (entries[i].dataset.deprecated != "False"))
{
entries[i].classList.add("hidden");
continue;
}
if (filterName == "none")
{
entries[i].classList.remove("hidden");
nb_found++;
}
else if (filterName == "regressions_main_ci")
{
if (entries[i].dataset.publicLevel > entries[i].dataset.mainCiLevel)
{
entries[i].classList.remove("hidden");
nb_found++;
}
else
{
entries[i].classList.add("hidden");
}
}
else if (filterName == "broken_low_quality")
{
if (entries[i].dataset.publicLevel <= 4)
{
entries[i].classList.remove("hidden");
nb_found++;
}
else
{
entries[i].classList.add("hidden");
}
}
else if (filterName == "outdated")
{
if (entries[i].dataset.mainCiDaysago >= 30)
{
entries[i].classList.remove("hidden");
nb_found++;
}
else
{
entries[i].classList.add("hidden");
}
}
else if (filterName == "regressions_bookworm")
{
if ((entries[i].dataset.publicLevel >= 6) && (entries[i].dataset.nextdebianCiLevel < 6) && (entries[i].dataset.nextdebianCiLevel != entries[i].dataset.mainCiLevel))
{
entries[i].classList.remove("hidden");
nb_found++;
}
else
{
entries[i].classList.add("hidden");
}
}
else if (filterName == "testings")
{
if (parseInt(entries[i].dataset.lastUpdateTesting) > -1)
{
entries[i].classList.remove("hidden");
nb_found++;
}
else
{
entries[i].classList.add("hidden");
}
}
else if (filterName == "autoupdate")
{
if (parseInt(entries[i].dataset.lastUpdateAutoupdate) > -1)
{
entries[i].classList.remove("hidden");
nb_found++;
}
else
{
entries[i].classList.add("hidden");
}
}
else if (filterName == "packagingv1")
{
if (entries[i].dataset.packagingFormat == "1")
{
entries[i].classList.remove("hidden");
nb_found++;
}
else
{
entries[i].classList.add("hidden");
}
}
}
document.getElementById('nbEntriesFound').innerHTML = "(" + nb_found + " apps)";
updateQueryArgsInURL()
}
function updateSort() {
let table = document.getElementById('appTable')
let toSort = document.getElementsByClassName('app')
let sortBy = selectSort.value.trim();
toSort = Array.prototype.slice.call(toSort, 0);
if (sortBy === "level") {
toSort.sort(function(a, b) {
return a.dataset.publicLevel - b.dataset.publicLevel;
});
}
else if (sortBy === "stars") {
toSort.sort(function(a, b) {
return parseInt(a.dataset.popularityStars) < parseInt(b.dataset.popularityStars) ? 1 : -1;
});
}
else if (sortBy === "main_branch_update") {
toSort.sort(function(a, b) {
return parseInt(a.dataset.lastUpdateMaster) < parseInt(b.dataset.lastUpdateMaster) ? 1 : -1;
});
}
else if (sortBy === "testing_branch_update") {
toSort.sort(function(a, b) {
return parseInt(a.dataset.lastUpdateTesting) < parseInt(b.dataset.lastUpdateTesting) ? 1 : -1;
});
}
else if (sortBy === "alpha") {
toSort.sort(function(a, b) {
return a.dataset.app > b.dataset.app ? 1 : -1;
});
}
for(var i = 0, l = toSort.length; i < l; i++) {
toSort[i].remove()
table.appendChild(toSort[i]);
}
updateQueryArgsInURL()
}
function updateQueryArgsInURL() {
let sortBy = selectSort.value.trim();
let filterName = selectFilter.value.trim();
let starsOnly = toggleStarsonly.checked;
let hideDeprecated = toggleHidedeprecated.checked;
if ('URLSearchParams' in window) {
var queryArgs = new URLSearchParams(window.location.search)
if (filterName != "none") { queryArgs.set("filter", filterName) } else { queryArgs.delete("filter"); };
if (sortBy != "stars") { queryArgs.set("sort", sortBy) } else { queryArgs.delete("sort"); };
if (starsOnly) { queryArgs.set("starsonly", true) } else { queryArgs.delete("starsonly"); };
if (hideDeprecated) { queryArgs.set("hidedeprecated", true) } else { queryArgs.delete("hidedeprecated"); };
let newUrl;
if (queryArgs.toString())
{
newUrl = window.location.pathname + '?' + queryArgs.toString();
}
else
{
newUrl = window.location.pathname;
}
if (newUrl != window.location.pathname + window.location.search)
{
history.pushState(null, '', newUrl);
}
}
}
let selectFilter = document.getElementById('selectfilter');
let selectSort = document.getElementById('selectsort');
let toggleStarsonly = document.getElementById('starsonly');
let toggleHidedeprecated = document.getElementById('hidedeprecated');
selectFilter.addEventListener('change', () => {
updateFilter();
});
selectSort.addEventListener('change', () => {
updateSort();
});
toggleStarsonly.addEventListener('change', () => {
updateFilter();
});
toggleHidedeprecated.addEventListener('change', () => {
updateFilter();
});
updateFilter();
updateSort();
</script>
{% endblock %}

View file

@ -5,34 +5,34 @@
{% block main %}
<div class="mx-auto w-full text-center p-8">
<img alt="YunoHost logo" src="{{ url_for('static', filename='ynh_logo_black.svg') }}" class="w-32 mx-auto">
<h1 class="text-2xl font-bold text-gray-900">
<img alt="YunoHost logo" src="{{ url_for('static', filename='ynh_logo_black.svg') }}" class="w-32 mx-auto dark:invert">
<h1 class="text-2xl font-bold">
{{ _("Application Store") }}
</h1>
</div>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 max-w-screen-lg mx-auto pt-5">
<div class="text-center border rounded-lg h-32 mx-3 sm:mx-0">
<div class="text-center border rounded-lg h-32 mx-3 sm:mx-0 border-gray-200">
<a
href="{{ url_for('browse_catalog') }}"
class="h-full relative block overflow-hidden hover:bg-gray-200 pt-12"
>
<h2 class="text-md font-bold text-gray-900">
<h2 class="text-md font-bold">
{{ _("Browse all applications") }}
</h2>
</a>
</div>
{% for id, category in catalog['categories'].items() %}
<div class="text-center border rounded-lg h-32 mx-3 sm:mx-0">
<div class="text-center border rounded-lg h-32 mx-3 sm:mx-0 border-gray-200">
<a
href="{{ url_for('browse_catalog', category=id) }}"
class="h-full relative block overflow-hidden hover:bg-gray-200 pt-10"
>
<h2 class="text-md font-bold text-gray-900">
<h2 class="text-md font-bold">
<i class="fa fa-{{ category['icon'] }}" aria-hidden="true"></i>
{{ category['title']|localize }}
</h2>
<p class="mx-auto max-w-[40ch] text-xs text-gray-500">
<p class="mx-auto max-w-[40ch] text-xs opacity-75">
{{ category['description']|localize }}
</p>
</a>

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>
<channel>
<title>YunoHost apps catalog News</title>
<link>{{ url_for('news_rss', _external=True)}}</link>
<atom:link href="{{ url_for('news_rss', _external=True)}}" rel="self" type="application/rss+xml" />
<description>YunoHost apps catalog news</description>
{%- for date, news in news_per_date.items() %}
{%- for status in ("added", "repaired", "broke", "removed") %}
{%- for app, url in news[status] %}
{% set manifest = catalog["apps"].get(app, {}).get("manifest", {}) %}
<item>
<title>[{{ status|capitalize }}] {% if manifest %}{{ manifest['name'] }}{% else %}{{ app }}{% endif %}</title>
<link>{{ url_for('app_info', app_id=app, _external=True) }}</link>
<guid isPermaLink="false">{{ app }}#{{ date|format_datetime("%Y%m%d") }}</guid>
<pubDate>{{ date|format_datetime("%a, %d %b %Y %H:%M:%S +0000") }}</pubDate>
<description>{{ manifest.get("description", {}).get("en") }}</description>
<content:encoded>{{ manifest.get("description", {}).get("en") }}</content:encoded>
</item>
{% endfor -%}
{% endfor -%}
{% endfor %}
</channel>
</rss>

View file

@ -4,25 +4,25 @@
{% endblock %}
{% block main %}
<div class="text-center max-w-screen-md mx-auto mt-5 mx-2">
<h1 class="text-2xl font-bold text-gray-900">
<h1 class="text-2xl font-bold">
{{ _("Application Wishlist") }}
</h1>
<p class="text-sm text-gray-700 mx-10 mt-2">{{ _("The wishlist is the place where people can collectively suggest and vote for apps that they would like to see packaged and made available in YunoHost's official apps catalog. Nevertheless, the fact that apps are listed here should by no mean be interpreted as a fact that the YunoHost project plans to integrate it, and is merely a source of inspiration for packaging volunteers.") }}</p>
<p class="text-sm opacity-75 mx-10 mt-2">{{ _("The wishlist is the place where people can collectively suggest and vote for apps that they would like to see packaged and made available in YunoHost's official apps catalog. Nevertheless, the fact that apps are listed here should by no mean be interpreted as a fact that the YunoHost project plans to integrate it, and is merely a source of inspiration for packaging volunteers.") }}</p>
</div>
<div class="max-w-screen-md mx-auto mt-3 mb-3">
<div class="flex flex-col md:flex-row items-center">
<div class="px-2 inline-block relative basis-2/3 text-gray-700">
<div class="px-2 inline-block relative basis-2/3">
<label for="search" class="sr-only"> {{ _("Search") }} </label>
<input
type="text"
id="search"
placeholder="{{ _('Search for…') }}"
class="w-full rounded-md border-gray-200 shadow-sm sm:text-sm py-2 pe-10"
class="w-full sm:text-sm py-2 pe-10"
>
<span class="absolute inset-y-0 end-0 grid w-10 place-content-center pr-4">
<span class="absolute inset-y-0 end-0 grid w-10 place-content-center pr-4 opacity-75">
<i class="fa fa-search" aria-hidden="true"></i>
</span>
</div>
@ -40,16 +40,16 @@
<select
name="selectsort"
id="selectsort"
class="inline-block rounded-md border-gray-200 text-sm ml-1 pl-1 pr-7 h-8 py-0"
class="inline-block text-sm ml-1 pl-1 pr-7 h-8 py-0"
>
<option {% if not init_sort or init_sort == "popularity" %}selected{% endif %} value="popularity">{{ _("Popularity") }}</option>
<option {% if init_sort == "alpha" %}selected{% endif %} value="alpha">{{ _("Alphabetical") }}</option>
<option {% if request.args.get("sort") in [None, "popularity"] %}selected{% endif %} value="popularity">{{ _("Popularity") }}</option>
<option {% if request.args.get("sort") == "alpha" %}selected{% endif %} value="alpha">{{ _("Alphabetical") }}</option>
</select>
</div>
<div class="inline-block flex items-center px-2 pt-2 md:pt-0 {% if not user %}text-gray-500{% endif %}" {% if not user %}title="{{ _('Requires to be logged-in') }}" aria-label="{{ _('Requires to be logged-in') }}"{% endif %}>
<div class="inline-block flex items-center px-2 pt-2 md:pt-0 {% if not user %}opacity-75{% endif %}" {% if not user %}title="{{ _('Requires to be logged-in') }}" aria-label="{{ _('Requires to be logged-in') }}"{% endif %}>
<label for="starsonly" class="inline-block relative mr-2 h-4 w-7 cursor-pointer">
<span class="sr-only">{{ _("Show only apps you starred") }}</span>
<input type="checkbox" id="starsonly" class="peer sr-only" {% if user and init_starsonly %}checked{% endif %} {% if not user%}disabled{% endif %}>
<input type="checkbox" id="starsonly" class="peer sr-only" {% if user and request.args.get("starsonly") %}checked{% endif %} {% if not user%}disabled{% endif %}>
<span class="absolute inset-0 rounded-full bg-gray-300 transition peer-checked:bg-green-500">
</span>
@ -64,22 +64,22 @@
</div>
<div class="overflow-x-auto max-w-screen-lg mx-auto pt-5">
<table class="min-w-full divide-y-2 divide-gray-200 bg-white text-sm">
<table class="min-w-full divide-y-2 divide-gray-100 dark:divide-gray-700 text-sm">
<thead>
<tr>
<th class="hidden sm:table-cell whitespace-nowrap px-4 py-2 font-medium text-gray-900">
<th class="hidden sm:table-cell whitespace-nowrap px-4 py-2 font-medium">
{{ _("Name") }}
</th>
<th class="hidden sm:table-cell whitespace-nowrap px-4 py-2 font-medium text-gray-900">
<th class="hidden sm:table-cell whitespace-nowrap px-4 py-2 font-medium">
{{ _("Description") }}
</th>
<th class="hidden sm:table-cell py-2"></th>
<th class="hidden sm:table-cell py-2"></th>
<th class="hidden sm:table-cell whitespace-nowrap px-4 py-2 font-medium text-gray-900 max-w-[5em]">{{ _("Popularity") }}</th>
<th class="hidden sm:table-cell whitespace-nowrap px-4 py-2 font-medium max-w-[5em]">{{ _("Popularity") }}</th>
</tr>
</thead>
<tbody id="wishlist" class="divide-y divide-gray-200">
<tbody id="wishlist" class="divide-y divide-gray-100 dark:divide-gray-700">
{% for app, infos in wishlist.items() %}
{% set this_app_stars = stars.get(app, {})|length %}
{% if user %}
@ -92,10 +92,10 @@
data-stars="{{ this_app_stars }}"
data-starred="{{ user_starred_this_app }}"
>
<td class="inline-block sm:table-cell px-4 py-2 font-bold text-gray-900 sm:max-w-[10em]">
<td class="inline-block sm:table-cell px-4 py-2 font-bold sm:max-w-[10em]">
{{ infos['name'] }}
</td>
<td class="block sm:table-cell px-4 py-0 sm:py-2 text-gray-700 max-w-md">{{ infos['description'] }}</td>
<td class="block sm:table-cell px-4 py-0 sm:py-2 opacity-75 max-w-md">{{ infos['description'] }}</td>
<td class="float-right sm:float-none sm:table-cell py-2 px-1 sm:px-0">
{% if infos['website'] %}
<a
@ -105,7 +105,7 @@
class="inline-block"
target="_blank"
>
<i class="fa fa-globe rounded-md border px-3 py-2 hover:bg-gray-100" aria-hidden="true"></i>
<i class="fa fa-globe rounded-md border border-gray-300 px-3 py-2 hover:bg-gray-100" aria-hidden="true"></i>
</a>
{% endif %}
</td>
@ -118,7 +118,7 @@
class="inline-block"
target="_blank"
>
<i class="fa fa-code rounded-md border px-3 py-2 hover:bg-gray-100" aria-hidden="true"></i>
<i class="fa fa-code rounded-md border border-gray-300 px-3 py-2 hover:bg-gray-100" aria-hidden="true"></i>
</a>
{% endif %}
</td>
@ -150,7 +150,7 @@
</table>
<div id="noResultFound" class="text-center pt-5 hidden">
<p class="text-lg font-bold text-gray-900 mb-5">
<p class="text-lg font-bold mb-5">
{{ _("No results found.") }}
</p>
</div>

View file

@ -4,7 +4,7 @@
{% endblock %}
{% block main %}
<div class="mt-5 text-center px-3 sm:px-0">
<h1 class="text-2xl font-bold text-gray-900">
<h1 class="text-2xl font-bold">
{{ _("Suggest an application to be added to YunoHost's catalog") }}
</h1>
</div>
@ -59,21 +59,21 @@
<input name="csrf_token" type="text" class="hidden" value="{{ csrf_token }}" >
<label for="name" class="mt-5 block font-bold text-gray-700">{{ _("Name") }}</label>
<input name="name" type="text" class="w-full mt-1 rounded-md border-gray-200 text-gray-700 shadow-sm" maxlength="30" required onkeyup="this.value = this.value.replace(/[^a-zA-Z0-9.-\\(\\)\\ ]/, '')" >
<input name="name" type="text" class="w-full mt-1" maxlength="30" required onkeyup="this.value = this.value.replace(/[^a-zA-Z0-9.-\\(\\)\\ ]/, '')" >
<label for="description" class="mt-5 block font-bold text-gray-700">{{ _("App's description") }}</label>
<textarea name="description" type="text" class="w-full mt-1 rounded-md border-gray-200 text-gray-700 shadow-sm" required rows='3' maxlength='100'></textarea>
<span class="text-xs text-gray-600"><span class="font-bold">{{ _("Please be concise and focus on what the app does.") }}</span> {{ _("No need to repeat '[App] is …'. No need to state that it is free/open-source or self-hosted (otherwise it wouldn't be packaged for YunoHost). Avoid marketing stuff like 'the most', or vague properties like 'easy', 'simple', 'lightweight'.") }}</span>
<label for="upstream" class="mt-5 block font-bold text-gray-700">{{ _("Project code repository") }}</label>
<input name="upstream" type="url" class="w-full mt-1 rounded-md border-gray-200 text-gray-700 shadow-sm" maxlength="150" required >
<input name="upstream" type="url" class="w-full mt-1" maxlength="150" required >
<label for="license" class="mt-5 block font-bold text-gray-700">{{ _("Link to the project's LICENSE") }}</label>
<input name="license" type="url" class="w-full mt-1 rounded-md border-gray-200 text-gray-700 shadow-sm" required maxlength="250"></input>
<input name="license" type="url" class="w-full mt-1" required maxlength="250"></input>
<span class="text-xs text-gray-600 font-bold">{{ _("The YunoHost project will only package free/open-source software (with possible case-by-case exceptions for apps which are not-totally-free)") }}</span>
<label for="website" class="mt-5 block font-bold text-gray-700">{{ _("Project website") }}</label>
<input name="website" type="url" class="w-full mt-1 rounded-md border-gray-200 text-gray-700 shadow-sm" maxlength="150" >
<input name="website" type="url" class="w-full mt-1" maxlength="150" >
<span class="text-xs text-gray-600">{{ _("Please *do not* just copy-paste the code repository URL. If the project has no proper website, then leave the field empty.") }}</span>
<button

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-05 19:36+0100\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-02-21 06:04+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: ar <LL@li.org>\n"
@ -19,15 +19,16 @@ msgstr ""
"&& n%100<=10 ? 3 : n%100>=0 && n%100<=2 ? 4 : 5);\n"
"Generated-By: Babel 2.14.0\n"
#: app.py:150
msgid "App %(app_id) not found"
#: app.py:162
#, python-format
msgid "App %(app_id)s not found"
msgstr ""
#: app.py:152
#: app.py:165
msgid "You must be logged in to be able to star an app"
msgstr ""
#: app.py:152 app.py:195 app.py:449 templates/wishlist_add.html:33
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid ""
"Note that, due to various abuses, we restricted login on the app store to "
"'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -36,78 +37,85 @@ msgid ""
"reading posts."
msgstr ""
#: app.py:195
#: app.py:210
msgid "You must be logged in to submit an app to the wishlist"
msgstr ""
#: app.py:207
#: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again"
msgstr ""
#: app.py:228
#: app.py:263
msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days."
msgstr ""
#: app.py:230
#: app.py:267
msgid "App name should be at least 3 characters"
msgstr ""
#: app.py:231
#: app.py:268
msgid "App name should be less than 30 characters"
msgstr ""
#: app.py:234
#: app.py:271
msgid "App description should be at least 5 characters"
msgstr ""
#: app.py:238
#: app.py:275
msgid "App description should be less than 100 characters"
msgstr ""
#: app.py:242
#: app.py:279
msgid "Upstream code repo URL should be at least 10 characters"
msgstr ""
#: app.py:246
#: app.py:283
msgid "Upstream code repo URL should be less than 150 characters"
msgstr ""
#: app.py:250
#: app.py:287
msgid "License URL should be at least 10 characters"
msgstr ""
#: app.py:254
#: app.py:291
msgid "License URL should be less than 250 characters"
msgstr ""
#: app.py:256
#: app.py:293
msgid "Website URL should be less than 150 characters"
msgstr ""
#: app.py:259
#: app.py:296
msgid "App name contains special characters"
msgstr ""
#: app.py:263
#: app.py:303
msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'."
msgstr ""
#: app.py:267
#: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr ""
#: app.py:301
#: app.py:343
#, python-format
msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you "
"can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr ""
#: app.py:325
#: app.py:358
#, python-format
msgid ""
"An app with the name %(slug)s already exists in the catalog, <a "
"href='%(url)s'>you can see its page here</a>."
msgstr ""
#: app.py:383
#, python-format
msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe "
@ -115,7 +123,7 @@ msgid ""
"please report the issue to the YunoHost team."
msgstr ""
#: app.py:376
#: app.py:433
#, python-format
msgid ""
"Your proposed app has succesfully been submitted. It must now be validated "
@ -123,7 +131,7 @@ msgid ""
"%(url)s</a>"
msgstr ""
#: app.py:449
#: app.py:528
msgid "Unfortunately, login was denied."
msgstr ""
@ -196,7 +204,7 @@ msgid "Important infos before installing"
msgstr ""
#: templates/app.html:124
msgid "Anti-features"
msgid "Antifeatures"
msgstr ""
#: templates/app.html:125
@ -236,45 +244,64 @@ msgstr ""
msgid "YunoHost package license"
msgstr ""
#: templates/base.html:5
#: templates/base.html:11
msgid "YunoHost app store"
msgstr ""
#: templates/base.html:18 templates/base.html:113 templates/index.html:3
#: templates/base.html:31 templates/base.html:154 templates/index.html:3
msgid "Home"
msgstr ""
#: templates/base.html:27 templates/base.html:122
#: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog"
msgstr ""
#: templates/base.html:33 templates/base.html:131
#: templates/base.html:46 templates/base.html:172
msgid "Wishlist"
msgstr ""
#: templates/base.html:46 templates/base.html:141
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr ""
#: templates/base.html:57
msgid "Charts & history"
msgstr ""
#: templates/base.html:71 templates/base.html:182
msgid "YunoHost documentation"
msgstr ""
#: templates/base.html:54 templates/base.html:151
#: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum"
msgstr ""
#: templates/base.html:86 templates/base.html:179
#: templates/base.html:111 templates/base.html:120 templates/base.html:220
#: templates/base.html:229
msgid "Packaging boards"
msgstr ""
#: templates/base.html:127 templates/base.html:237
msgid "Logout"
msgstr ""
#: templates/base.html:99
#: templates/base.html:140
msgid "Toggle menu"
msgstr ""
#: templates/base.html:197
#: templates/base.html:255
msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using "
"<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> "
"- <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/"
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
msgstr ""
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80
@ -293,7 +320,7 @@ msgstr ""
msgid "All apps"
msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39
#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by"
msgstr ""
@ -306,16 +333,16 @@ msgstr ""
msgid "Newest"
msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46
#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical"
msgstr ""
#: templates/catalog.html:128 templates/wishlist.html:49
#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49
msgid "Requires to be logged-in"
msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139
#: templates/wishlist.html:51 templates/wishlist.html:60
#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred"
msgstr ""
@ -349,8 +376,206 @@ msgstr ""
#: templates/catalog.html:188
msgid ""
"This means that the developer will no longer update them. We strongly "
"advise against their installation and advise users to find alternatives."
"This means that the developer will no longer update them. We strongly advise "
"against their installation and advise users to find alternatives."
msgstr ""
#: templates/charts.html:5
msgid "Apps quality level from automatic tests"
msgstr ""
#: templates/charts.html:9
msgid "Apps quality level history"
msgstr ""
#: templates/charts.html:14
msgid "History"
msgstr ""
#: templates/charts.html:22
msgid "Added"
msgstr ""
#: templates/charts.html:28
msgid "Repaired"
msgstr ""
#: templates/charts.html:34
msgid "Broke"
msgstr ""
#: templates/charts.html:40
msgid "Removed"
msgstr ""
#: templates/charts.html:80
msgid "Unknown"
msgstr ""
#: templates/charts.html:81
msgid "Level 0"
msgstr ""
#: templates/charts.html:82
msgid "Level 1"
msgstr ""
#: templates/charts.html:83
msgid "Level 2"
msgstr ""
#: templates/charts.html:84
msgid "Level 3"
msgstr ""
#: templates/charts.html:85
msgid "Level 4"
msgstr ""
#: templates/charts.html:86
msgid "Level 5"
msgstr ""
#: templates/charts.html:87
msgid "Level 6"
msgstr ""
#: templates/charts.html:88
msgid "Level 7"
msgstr ""
#: templates/charts.html:89
msgid "Level 8"
msgstr ""
#: templates/charts.html:107
#, python-format
msgid "Level %(level)s:"
msgstr ""
#: templates/charts.html:107
msgid "Total:"
msgstr ""
#: templates/charts.html:108
#, python-format
msgid "Level %(level)s"
msgstr ""
#: templates/dash.html:3 templates/dash.html:9
msgid "App packaging dashboard"
msgstr ""
#: templates/dash.html:11
msgid ""
"This is where packagers can monitor the status of automatic tests (CI) and "
"ongoing major pull requests accross all apps. If you want to get started "
"with app packaging in YunoHost, please check out the <a class='text-"
"blue-500' href='https://yunohost.org/packaging_apps'>packaging "
"documentation</a> and come say hi to us on the <a class='text-blue-500' "
"href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!"
msgstr ""
#: templates/dash.html:17
msgid "Filter"
msgstr ""
#: templates/dash.html:23
msgid "(None)"
msgstr ""
#: templates/dash.html:24
msgid "Regressions on main CI"
msgstr ""
#: templates/dash.html:25
msgid "Broken / low quality apps"
msgstr ""
#: templates/dash.html:26
msgid "Outdated tests on main CI"
msgstr ""
#: templates/dash.html:27
msgid "Major regressions on Bookworm CI"
msgstr ""
#: templates/dash.html:28
msgid "Apps with testings PRs"
msgstr ""
#: templates/dash.html:29
msgid "Apps with autoupdate PRs"
msgstr ""
#: templates/dash.html:30
msgid "Packaging v1 apps"
msgstr ""
#: templates/dash.html:41
msgid "Quality level"
msgstr ""
#: templates/dash.html:42 templates/dash.html:173
msgid "Popularity stars"
msgstr ""
#: templates/dash.html:43
msgid "Last update on main/master branch"
msgstr ""
#: templates/dash.html:44
msgid "Last update on testing branch"
msgstr ""
#: templates/dash.html:65
msgid "App"
msgstr ""
#: templates/dash.html:67
msgid "Main CI"
msgstr ""
#: templates/dash.html:68
msgid "Bookworm CI"
msgstr ""
#: templates/dash.html:69
msgid "Testing PR"
msgstr ""
#: templates/dash.html:70
msgid "Autoupdate PR"
msgstr ""
#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131
msgid "Broken"
msgstr ""
#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133
msgid "Low quality"
msgstr ""
#: templates/dash.html:112 templates/dash.html:127
#, python-format
msgid "Outdated test (%(days)s days ago)"
msgstr ""
#: templates/dash.html:150 templates/dash.html:165
#, python-format
msgid "Inactive (%(days)s days ago)"
msgstr ""
#: templates/dash.html:177
msgid "Packaging v1"
msgstr ""
#: templates/dash.html:180
msgid "Deprecated"
msgstr ""
#: templates/dash.html:183
msgid "Not maintained"
msgstr ""
#: templates/index.html:10
@ -361,44 +586,10 @@ msgstr ""
msgid "Browse all applications"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr ""
@ -417,6 +608,10 @@ msgid ""
"every random nerdy stuff you find on the Internet."
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr ""
@ -460,3 +655,33 @@ msgstr ""
#: templates/wishlist_add.html:84
msgid "Submit"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-05 19:36+0100\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-02-21 06:05+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: bn_BD <LL@li.org>\n"
@ -18,15 +18,16 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.14.0\n"
#: app.py:150
msgid "App %(app_id) not found"
#: app.py:162
#, python-format
msgid "App %(app_id)s not found"
msgstr ""
#: app.py:152
#: app.py:165
msgid "You must be logged in to be able to star an app"
msgstr ""
#: app.py:152 app.py:195 app.py:449 templates/wishlist_add.html:33
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid ""
"Note that, due to various abuses, we restricted login on the app store to "
"'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts."
msgstr ""
#: app.py:195
#: app.py:210
msgid "You must be logged in to submit an app to the wishlist"
msgstr ""
#: app.py:207
#: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again"
msgstr ""
#: app.py:228
#: app.py:263
msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days."
msgstr ""
#: app.py:230
#: app.py:267
msgid "App name should be at least 3 characters"
msgstr ""
#: app.py:231
#: app.py:268
msgid "App name should be less than 30 characters"
msgstr ""
#: app.py:234
#: app.py:271
msgid "App description should be at least 5 characters"
msgstr ""
#: app.py:238
#: app.py:275
msgid "App description should be less than 100 characters"
msgstr ""
#: app.py:242
#: app.py:279
msgid "Upstream code repo URL should be at least 10 characters"
msgstr ""
#: app.py:246
#: app.py:283
msgid "Upstream code repo URL should be less than 150 characters"
msgstr ""
#: app.py:250
#: app.py:287
msgid "License URL should be at least 10 characters"
msgstr ""
#: app.py:254
#: app.py:291
msgid "License URL should be less than 250 characters"
msgstr ""
#: app.py:256
#: app.py:293
msgid "Website URL should be less than 150 characters"
msgstr ""
#: app.py:259
#: app.py:296
msgid "App name contains special characters"
msgstr ""
#: app.py:263
#: app.py:303
msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'."
msgstr ""
#: app.py:267
#: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr ""
#: app.py:301
#: app.py:343
#, python-format
msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you "
"can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr ""
#: app.py:325
#: app.py:358
#, python-format
msgid ""
"An app with the name %(slug)s already exists in the catalog, <a "
"href='%(url)s'>you can see its page here</a>."
msgstr ""
#: app.py:383
#, python-format
msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe "
@ -114,7 +122,7 @@ msgid ""
"please report the issue to the YunoHost team."
msgstr ""
#: app.py:376
#: app.py:433
#, python-format
msgid ""
"Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>"
msgstr ""
#: app.py:449
#: app.py:528
msgid "Unfortunately, login was denied."
msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr ""
#: templates/app.html:124
msgid "Anti-features"
msgid "Antifeatures"
msgstr ""
#: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license"
msgstr ""
#: templates/base.html:5
#: templates/base.html:11
msgid "YunoHost app store"
msgstr ""
#: templates/base.html:18 templates/base.html:113 templates/index.html:3
#: templates/base.html:31 templates/base.html:154 templates/index.html:3
msgid "Home"
msgstr ""
#: templates/base.html:27 templates/base.html:122
#: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog"
msgstr ""
#: templates/base.html:33 templates/base.html:131
#: templates/base.html:46 templates/base.html:172
msgid "Wishlist"
msgstr ""
#: templates/base.html:46 templates/base.html:141
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr ""
#: templates/base.html:57
msgid "Charts & history"
msgstr ""
#: templates/base.html:71 templates/base.html:182
msgid "YunoHost documentation"
msgstr ""
#: templates/base.html:54 templates/base.html:151
#: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum"
msgstr ""
#: templates/base.html:86 templates/base.html:179
#: templates/base.html:111 templates/base.html:120 templates/base.html:220
#: templates/base.html:229
msgid "Packaging boards"
msgstr ""
#: templates/base.html:127 templates/base.html:237
msgid "Logout"
msgstr ""
#: templates/base.html:99
#: templates/base.html:140
msgid "Toggle menu"
msgstr ""
#: templates/base.html:197
#: templates/base.html:255
msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using "
"<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> "
"- <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/"
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
msgstr ""
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps"
msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39
#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by"
msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest"
msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46
#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical"
msgstr ""
#: templates/catalog.html:128 templates/wishlist.html:49
#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49
msgid "Requires to be logged-in"
msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139
#: templates/wishlist.html:51 templates/wishlist.html:60
#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred"
msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188
msgid ""
"This means that the developer will no longer update them. We strongly "
"advise against their installation and advise users to find alternatives."
"This means that the developer will no longer update them. We strongly advise "
"against their installation and advise users to find alternatives."
msgstr ""
#: templates/charts.html:5
msgid "Apps quality level from automatic tests"
msgstr ""
#: templates/charts.html:9
msgid "Apps quality level history"
msgstr ""
#: templates/charts.html:14
msgid "History"
msgstr ""
#: templates/charts.html:22
msgid "Added"
msgstr ""
#: templates/charts.html:28
msgid "Repaired"
msgstr ""
#: templates/charts.html:34
msgid "Broke"
msgstr ""
#: templates/charts.html:40
msgid "Removed"
msgstr ""
#: templates/charts.html:80
msgid "Unknown"
msgstr ""
#: templates/charts.html:81
msgid "Level 0"
msgstr ""
#: templates/charts.html:82
msgid "Level 1"
msgstr ""
#: templates/charts.html:83
msgid "Level 2"
msgstr ""
#: templates/charts.html:84
msgid "Level 3"
msgstr ""
#: templates/charts.html:85
msgid "Level 4"
msgstr ""
#: templates/charts.html:86
msgid "Level 5"
msgstr ""
#: templates/charts.html:87
msgid "Level 6"
msgstr ""
#: templates/charts.html:88
msgid "Level 7"
msgstr ""
#: templates/charts.html:89
msgid "Level 8"
msgstr ""
#: templates/charts.html:107
#, python-format
msgid "Level %(level)s:"
msgstr ""
#: templates/charts.html:107
msgid "Total:"
msgstr ""
#: templates/charts.html:108
#, python-format
msgid "Level %(level)s"
msgstr ""
#: templates/dash.html:3 templates/dash.html:9
msgid "App packaging dashboard"
msgstr ""
#: templates/dash.html:11
msgid ""
"This is where packagers can monitor the status of automatic tests (CI) and "
"ongoing major pull requests accross all apps. If you want to get started "
"with app packaging in YunoHost, please check out the <a class='text-"
"blue-500' href='https://yunohost.org/packaging_apps'>packaging "
"documentation</a> and come say hi to us on the <a class='text-blue-500' "
"href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!"
msgstr ""
#: templates/dash.html:17
msgid "Filter"
msgstr ""
#: templates/dash.html:23
msgid "(None)"
msgstr ""
#: templates/dash.html:24
msgid "Regressions on main CI"
msgstr ""
#: templates/dash.html:25
msgid "Broken / low quality apps"
msgstr ""
#: templates/dash.html:26
msgid "Outdated tests on main CI"
msgstr ""
#: templates/dash.html:27
msgid "Major regressions on Bookworm CI"
msgstr ""
#: templates/dash.html:28
msgid "Apps with testings PRs"
msgstr ""
#: templates/dash.html:29
msgid "Apps with autoupdate PRs"
msgstr ""
#: templates/dash.html:30
msgid "Packaging v1 apps"
msgstr ""
#: templates/dash.html:41
msgid "Quality level"
msgstr ""
#: templates/dash.html:42 templates/dash.html:173
msgid "Popularity stars"
msgstr ""
#: templates/dash.html:43
msgid "Last update on main/master branch"
msgstr ""
#: templates/dash.html:44
msgid "Last update on testing branch"
msgstr ""
#: templates/dash.html:65
msgid "App"
msgstr ""
#: templates/dash.html:67
msgid "Main CI"
msgstr ""
#: templates/dash.html:68
msgid "Bookworm CI"
msgstr ""
#: templates/dash.html:69
msgid "Testing PR"
msgstr ""
#: templates/dash.html:70
msgid "Autoupdate PR"
msgstr ""
#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131
msgid "Broken"
msgstr ""
#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133
msgid "Low quality"
msgstr ""
#: templates/dash.html:112 templates/dash.html:127
#, python-format
msgid "Outdated test (%(days)s days ago)"
msgstr ""
#: templates/dash.html:150 templates/dash.html:165
#, python-format
msgid "Inactive (%(days)s days ago)"
msgstr ""
#: templates/dash.html:177
msgid "Packaging v1"
msgstr ""
#: templates/dash.html:180
msgid "Deprecated"
msgstr ""
#: templates/dash.html:183
msgid "Not maintained"
msgstr ""
#: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet."
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84
msgid "Submit"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-05 19:36+0100\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-02-21 06:05+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: br <LL@li.org>\n"
@ -22,15 +22,16 @@ msgstr ""
"3 : n%1000000==0 ? 4 : 5);\n"
"Generated-By: Babel 2.14.0\n"
#: app.py:150
msgid "App %(app_id) not found"
#: app.py:162
#, python-format
msgid "App %(app_id)s not found"
msgstr ""
#: app.py:152
#: app.py:165
msgid "You must be logged in to be able to star an app"
msgstr ""
#: app.py:152 app.py:195 app.py:449 templates/wishlist_add.html:33
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid ""
"Note that, due to various abuses, we restricted login on the app store to "
"'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -39,78 +40,85 @@ msgid ""
"reading posts."
msgstr ""
#: app.py:195
#: app.py:210
msgid "You must be logged in to submit an app to the wishlist"
msgstr ""
#: app.py:207
#: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again"
msgstr ""
#: app.py:228
#: app.py:263
msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days."
msgstr ""
#: app.py:230
#: app.py:267
msgid "App name should be at least 3 characters"
msgstr ""
#: app.py:231
#: app.py:268
msgid "App name should be less than 30 characters"
msgstr ""
#: app.py:234
#: app.py:271
msgid "App description should be at least 5 characters"
msgstr ""
#: app.py:238
#: app.py:275
msgid "App description should be less than 100 characters"
msgstr ""
#: app.py:242
#: app.py:279
msgid "Upstream code repo URL should be at least 10 characters"
msgstr ""
#: app.py:246
#: app.py:283
msgid "Upstream code repo URL should be less than 150 characters"
msgstr ""
#: app.py:250
#: app.py:287
msgid "License URL should be at least 10 characters"
msgstr ""
#: app.py:254
#: app.py:291
msgid "License URL should be less than 250 characters"
msgstr ""
#: app.py:256
#: app.py:293
msgid "Website URL should be less than 150 characters"
msgstr ""
#: app.py:259
#: app.py:296
msgid "App name contains special characters"
msgstr ""
#: app.py:263
#: app.py:303
msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'."
msgstr ""
#: app.py:267
#: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr ""
#: app.py:301
#: app.py:343
#, python-format
msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you "
"can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr ""
#: app.py:325
#: app.py:358
#, python-format
msgid ""
"An app with the name %(slug)s already exists in the catalog, <a "
"href='%(url)s'>you can see its page here</a>."
msgstr ""
#: app.py:383
#, python-format
msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe "
@ -118,7 +126,7 @@ msgid ""
"please report the issue to the YunoHost team."
msgstr ""
#: app.py:376
#: app.py:433
#, python-format
msgid ""
"Your proposed app has succesfully been submitted. It must now be validated "
@ -126,7 +134,7 @@ msgid ""
"%(url)s</a>"
msgstr ""
#: app.py:449
#: app.py:528
msgid "Unfortunately, login was denied."
msgstr ""
@ -199,7 +207,7 @@ msgid "Important infos before installing"
msgstr ""
#: templates/app.html:124
msgid "Anti-features"
msgid "Antifeatures"
msgstr ""
#: templates/app.html:125
@ -239,45 +247,64 @@ msgstr ""
msgid "YunoHost package license"
msgstr ""
#: templates/base.html:5
#: templates/base.html:11
msgid "YunoHost app store"
msgstr ""
#: templates/base.html:18 templates/base.html:113 templates/index.html:3
#: templates/base.html:31 templates/base.html:154 templates/index.html:3
msgid "Home"
msgstr ""
#: templates/base.html:27 templates/base.html:122
#: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog"
msgstr ""
#: templates/base.html:33 templates/base.html:131
#: templates/base.html:46 templates/base.html:172
msgid "Wishlist"
msgstr ""
#: templates/base.html:46 templates/base.html:141
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr ""
#: templates/base.html:57
msgid "Charts & history"
msgstr ""
#: templates/base.html:71 templates/base.html:182
msgid "YunoHost documentation"
msgstr ""
#: templates/base.html:54 templates/base.html:151
#: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum"
msgstr ""
#: templates/base.html:86 templates/base.html:179
#: templates/base.html:111 templates/base.html:120 templates/base.html:220
#: templates/base.html:229
msgid "Packaging boards"
msgstr ""
#: templates/base.html:127 templates/base.html:237
msgid "Logout"
msgstr ""
#: templates/base.html:99
#: templates/base.html:140
msgid "Toggle menu"
msgstr ""
#: templates/base.html:197
#: templates/base.html:255
msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using "
"<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> "
"- <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/"
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
msgstr ""
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80
@ -296,7 +323,7 @@ msgstr ""
msgid "All apps"
msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39
#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by"
msgstr ""
@ -309,16 +336,16 @@ msgstr ""
msgid "Newest"
msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46
#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical"
msgstr ""
#: templates/catalog.html:128 templates/wishlist.html:49
#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49
msgid "Requires to be logged-in"
msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139
#: templates/wishlist.html:51 templates/wishlist.html:60
#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred"
msgstr ""
@ -352,8 +379,206 @@ msgstr ""
#: templates/catalog.html:188
msgid ""
"This means that the developer will no longer update them. We strongly "
"advise against their installation and advise users to find alternatives."
"This means that the developer will no longer update them. We strongly advise "
"against their installation and advise users to find alternatives."
msgstr ""
#: templates/charts.html:5
msgid "Apps quality level from automatic tests"
msgstr ""
#: templates/charts.html:9
msgid "Apps quality level history"
msgstr ""
#: templates/charts.html:14
msgid "History"
msgstr ""
#: templates/charts.html:22
msgid "Added"
msgstr ""
#: templates/charts.html:28
msgid "Repaired"
msgstr ""
#: templates/charts.html:34
msgid "Broke"
msgstr ""
#: templates/charts.html:40
msgid "Removed"
msgstr ""
#: templates/charts.html:80
msgid "Unknown"
msgstr ""
#: templates/charts.html:81
msgid "Level 0"
msgstr ""
#: templates/charts.html:82
msgid "Level 1"
msgstr ""
#: templates/charts.html:83
msgid "Level 2"
msgstr ""
#: templates/charts.html:84
msgid "Level 3"
msgstr ""
#: templates/charts.html:85
msgid "Level 4"
msgstr ""
#: templates/charts.html:86
msgid "Level 5"
msgstr ""
#: templates/charts.html:87
msgid "Level 6"
msgstr ""
#: templates/charts.html:88
msgid "Level 7"
msgstr ""
#: templates/charts.html:89
msgid "Level 8"
msgstr ""
#: templates/charts.html:107
#, python-format
msgid "Level %(level)s:"
msgstr ""
#: templates/charts.html:107
msgid "Total:"
msgstr ""
#: templates/charts.html:108
#, python-format
msgid "Level %(level)s"
msgstr ""
#: templates/dash.html:3 templates/dash.html:9
msgid "App packaging dashboard"
msgstr ""
#: templates/dash.html:11
msgid ""
"This is where packagers can monitor the status of automatic tests (CI) and "
"ongoing major pull requests accross all apps. If you want to get started "
"with app packaging in YunoHost, please check out the <a class='text-"
"blue-500' href='https://yunohost.org/packaging_apps'>packaging "
"documentation</a> and come say hi to us on the <a class='text-blue-500' "
"href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!"
msgstr ""
#: templates/dash.html:17
msgid "Filter"
msgstr ""
#: templates/dash.html:23
msgid "(None)"
msgstr ""
#: templates/dash.html:24
msgid "Regressions on main CI"
msgstr ""
#: templates/dash.html:25
msgid "Broken / low quality apps"
msgstr ""
#: templates/dash.html:26
msgid "Outdated tests on main CI"
msgstr ""
#: templates/dash.html:27
msgid "Major regressions on Bookworm CI"
msgstr ""
#: templates/dash.html:28
msgid "Apps with testings PRs"
msgstr ""
#: templates/dash.html:29
msgid "Apps with autoupdate PRs"
msgstr ""
#: templates/dash.html:30
msgid "Packaging v1 apps"
msgstr ""
#: templates/dash.html:41
msgid "Quality level"
msgstr ""
#: templates/dash.html:42 templates/dash.html:173
msgid "Popularity stars"
msgstr ""
#: templates/dash.html:43
msgid "Last update on main/master branch"
msgstr ""
#: templates/dash.html:44
msgid "Last update on testing branch"
msgstr ""
#: templates/dash.html:65
msgid "App"
msgstr ""
#: templates/dash.html:67
msgid "Main CI"
msgstr ""
#: templates/dash.html:68
msgid "Bookworm CI"
msgstr ""
#: templates/dash.html:69
msgid "Testing PR"
msgstr ""
#: templates/dash.html:70
msgid "Autoupdate PR"
msgstr ""
#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131
msgid "Broken"
msgstr ""
#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133
msgid "Low quality"
msgstr ""
#: templates/dash.html:112 templates/dash.html:127
#, python-format
msgid "Outdated test (%(days)s days ago)"
msgstr ""
#: templates/dash.html:150 templates/dash.html:165
#, python-format
msgid "Inactive (%(days)s days ago)"
msgstr ""
#: templates/dash.html:177
msgid "Packaging v1"
msgstr ""
#: templates/dash.html:180
msgid "Deprecated"
msgstr ""
#: templates/dash.html:183
msgid "Not maintained"
msgstr ""
#: templates/index.html:10
@ -364,44 +589,10 @@ msgstr ""
msgid "Browse all applications"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr ""
@ -420,6 +611,10 @@ msgid ""
"every random nerdy stuff you find on the Internet."
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr ""
@ -463,3 +658,33 @@ msgstr ""
#: templates/wishlist_add.html:84
msgid "Submit"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""

View file

@ -7,26 +7,28 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-05 19:36+0100\n"
"PO-Revision-Date: 2024-02-21 06:05+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: ca <LL@li.org>\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-03-23 19:04+0000\n"
"Last-Translator: OniriCorpe <oniricorpe@disroot.org>\n"
"Language-Team: Catalan <https://translate.yunohost.org/projects/yunohost/"
"apps/ca/>\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"Generated-By: Babel 2.14.0\n"
#: app.py:150
msgid "App %(app_id) not found"
msgstr ""
#: app.py:162
#, python-format
msgid "App %(app_id)s not found"
msgstr "No es troba l'aplicació %(app_id)s"
#: app.py:152
#: app.py:165
msgid "You must be logged in to be able to star an app"
msgstr ""
msgstr "Heu d'iniciar sessió per poder destacar una aplicació"
#: app.py:152 app.py:195 app.py:449 templates/wishlist_add.html:33
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid ""
"Note that, due to various abuses, we restricted login on the app store to "
"'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -34,102 +36,133 @@ msgid ""
"least 5 topics, reading at least 30 posts, and spending at least 10 minutes "
"reading posts."
msgstr ""
"Tingueu en compte que, a causa de diversos abusos, vam restringir l'inici de "
"sessió a la botiga d'aplicacions als usuaris del «nivell de confiança 1».<br/"
"><br/>El «nivell de confiança 1» s'obté després d'interaccionar com a mínim "
"amb el fòrum, i més concretament: introduir almenys 5 temes, llegir almenys "
"30 publicacions i dedicar almenys 10 minuts llegint publicacions."
#: app.py:195
#: app.py:210
msgid "You must be logged in to submit an app to the wishlist"
msgstr ""
msgstr "Heu d'iniciar sessió per enviar una aplicació a la llista de desitjos"
#: app.py:207
#: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again"
msgstr ""
"El testimoni CSRF no és vàlid; actualitzeu la pàgina i torneu-ho a provar"
#: app.py:228
#: app.py:263
msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days."
msgstr ""
"La proposta d'addicions a la llista de desitjos està limitada a un cop cada "
"15 dies per usuari. Si us plau, torna-ho a provar d'aquí a uns dies."
#: app.py:230
#: app.py:267
msgid "App name should be at least 3 characters"
msgstr ""
msgstr "El nom de l'aplicació ha de tenir com a mínim 3 caràcters"
#: app.py:231
#: app.py:268
msgid "App name should be less than 30 characters"
msgstr ""
msgstr "El nom de l'aplicació ha de tenir menys de 30 caràcters"
#: app.py:234
#: app.py:271
msgid "App description should be at least 5 characters"
msgstr ""
msgstr "La descripció de l'aplicació ha de tenir almenys 5 caràcters"
#: app.py:238
#: app.py:275
msgid "App description should be less than 100 characters"
msgstr ""
msgstr "La descripció de l'aplicació ha de tenir menys de 100 caràcters"
#: app.py:242
#: app.py:279
msgid "Upstream code repo URL should be at least 10 characters"
msgstr ""
msgstr "L'URL del dipòsit de codi amunt ha de tenir com a mínim 10 caràcters"
#: app.py:246
#: app.py:283
msgid "Upstream code repo URL should be less than 150 characters"
msgstr ""
msgstr "L'URL del dipòsit de codi amunt ha de tenir menys de 150 caràcters"
#: app.py:250
#: app.py:287
msgid "License URL should be at least 10 characters"
msgstr ""
msgstr "L'URL de la llicència ha de tenir com a mínim 10 caràcters"
#: app.py:254
#: app.py:291
msgid "License URL should be less than 250 characters"
msgstr ""
msgstr "L'URL de la llicència ha de tenir menys de 250 caràcters"
#: app.py:256
#: app.py:293
msgid "Website URL should be less than 150 characters"
msgstr ""
msgstr "L'URL del lloc web ha de tenir menys de 150 caràcters"
#: app.py:259
#: app.py:296
msgid "App name contains special characters"
msgstr ""
msgstr "El nom de l'aplicació conté caràcters especials"
#: app.py:263
#: app.py:303
msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'."
msgstr ""
"Si us plau, centreu-vos en el que fa l'aplicació, sense fer servir "
"màrqueting, termes difusos ni repetir que l'aplicació és «gratuïta» i "
"«autohostatjada»."
#: app.py:267
#: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr ""
"No cal repetir el nom de l'aplicació. Centra't en el que fa l'aplicació."
#: app.py:301
#: app.py:343
#, python-format
msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you "
"can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr ""
"Una entrada amb el nom %(slug)s ja existeix a la llista de desitjos; en "
"canvi, podeu <a href='%(url)s'>afegir una estrella a l'aplicació per mostrar "
"el vostre interès</a>."
#: app.py:325
#: app.py:358
#, python-format
msgid ""
"An app with the name %(slug)s already exists in the catalog, <a "
"href='%(url)s'>you can see its page here</a>."
msgstr ""
"Una aplicació amb el nom %(slug)s ja existeix al catàleg, <a "
"href='%(url)s'>podeu veure la seva pàgina aquí</a>."
#: app.py:383
#, python-format
msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe "
"there's already <a href='%(url)s'>a waiting PR for this app</a>? Else, "
"please report the issue to the YunoHost team."
msgstr ""
"No s'ha pogut crear la sol·licitud d'extracció per afegir l'aplicació a la "
"llista de desitjos… Potser ja hi ha <a href='%(url)s'>un PR esperant per a "
"aquesta aplicació</a>? En cas contrari, si us plau, informeu el problema a "
"l'equip de YunoHost."
#: app.py:376
#: app.py:433
#, python-format
msgid ""
"Your proposed app has succesfully been submitted. It must now be validated "
"by the YunoHost team. You can track progress here: <a href='%(url)s'>"
"%(url)s</a>"
msgstr ""
"La vostra aplicació proposada s'ha enviat correctament. Ara ha de ser "
"validat per l'equip de YunoHost. Podeu fer un seguiment del progrés aquí: <a "
"href='%(url)s'>%(url)s</a>"
#: app.py:449
#: app.py:528
msgid "Unfortunately, login was denied."
msgstr ""
msgstr "Malauradament s'ha denegat l'inici de sessió."
#: templates/app.html:10 templates/catalog.html:23
#, python-format
msgid "Logo for %(app)s"
msgstr ""
msgstr "Logotip de %(app)s"
#: templates/app.html:30 templates/app.html:31 templates/catalog.html:41
#: templates/catalog.html:42
@ -137,6 +170,8 @@ msgid ""
"This app is currently flagged as broken because it failed our automatic "
"tests."
msgstr ""
"Actualment aquesta aplicació està marcada com a trencada perquè no ha passat "
"les nostres proves automàtiques."
#: templates/app.html:30 templates/app.html:31 templates/catalog.html:41
#: templates/catalog.html:42 templates/catalog.html:170
@ -144,6 +179,8 @@ msgid ""
"This is usually a temporary situation which requires packagers to fix "
"something in the app."
msgstr ""
"Normalment aquesta és una situació temporal que requereix que els "
"empaquetadors solucionin alguna cosa a l'aplicació."
#: templates/app.html:37 templates/app.html:38 templates/catalog.html:46
#: templates/catalog.html:47
@ -151,218 +188,537 @@ msgid ""
"This app has been good quality according to our automatic tests over at "
"least one year."
msgstr ""
"Aquesta aplicació ha estat de bona qualitat segons les nostres proves "
"automàtiques durant almenys un any."
#: templates/app.html:81
msgid "Try the demo"
msgstr ""
msgstr "Prova la demostració"
#: templates/app.html:82
msgid "Demo"
msgstr ""
msgstr "Demostració"
#: templates/app.html:85
msgid "Install with YunoHost"
msgstr ""
msgstr "Instal·leu amb YunoHost"
#: templates/app.html:93
#, python-format
msgid "Current version: %(version)s"
msgstr ""
msgstr "Versió actual: %(version)s"
#: templates/app.html:95
#, python-format
msgid "Potential alternative to: %(alternatives)s"
msgstr ""
msgstr "Alternativa potencial a: %(alternatives)s"
#: templates/app.html:101
#, python-format
msgid "Screenshot for %(app)s"
msgstr ""
msgstr "Captura de pantalla de %(app)s"
#: templates/app.html:106
#, python-format
msgid ""
"This app is only compatible with these specific architectures: %(archs)s"
msgstr ""
"Aquesta aplicació només és compatible amb aquestes arquitectures "
"específiques: %(archs)s"
#: templates/app.html:112
#, python-format
msgid "This app requires an unusual amount of RAM to install: %(ram)s"
msgstr ""
"Aquesta aplicació requereix una quantitat inusual de RAM per instal·lar-se: "
"%(ram)s"
#: templates/app.html:118
msgid "Important infos before installing"
msgstr ""
msgstr "Informació important abans d'instal·lar"
# | msgid "Anti-features"
#: templates/app.html:124
msgid "Anti-features"
msgstr ""
#, fuzzy
msgid "Antifeatures"
msgstr "Anticaracterístiques"
#: templates/app.html:125
msgid "(This app has features you may not like)"
msgstr ""
msgstr "(Aquesta aplicació té funcions que potser no us agraden)"
#: templates/app.html:136
msgid "Useful links"
msgstr ""
msgstr "Vincles útils"
#: templates/app.html:139
#, python-format
msgid "App license: %(license)s"
msgstr ""
msgstr "Llicència de l'aplicació: %(license)s"
#: templates/app.html:140
msgid " Official website"
msgstr ""
msgstr " Pàgina web oficial"
#: templates/app.html:141
msgid "Official admin documentation"
msgstr ""
msgstr "Documentació oficial d'administració"
#: templates/app.html:142
msgid "Official user documentation"
msgstr ""
msgstr "Documentació oficial d'usuari"
#: templates/app.html:143
msgid "Official code repository"
msgstr ""
msgstr "Repositori de codi oficial"
#: templates/app.html:144
msgid "YunoHost package repository"
msgstr ""
msgstr "Repositori de paquets YunoHost"
#: templates/app.html:145
msgid "YunoHost package license"
msgstr ""
msgstr "Llicència del paquet YunoHost"
#: templates/base.html:5
#: templates/base.html:11
msgid "YunoHost app store"
msgstr ""
msgstr "Botiga d'aplicacions YunoHost"
#: templates/base.html:18 templates/base.html:113 templates/index.html:3
#: templates/base.html:31 templates/base.html:154 templates/index.html:3
msgid "Home"
msgstr ""
msgstr "Inici"
#: templates/base.html:27 templates/base.html:122
#: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog"
msgstr ""
msgstr "Catàleg"
#: templates/base.html:33 templates/base.html:131
#: templates/base.html:46 templates/base.html:172
msgid "Wishlist"
msgstr "Llista de desitjos"
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr ""
#: templates/base.html:46 templates/base.html:141
#: templates/base.html:57
msgid "Charts & history"
msgstr ""
#: templates/base.html:71 templates/base.html:182
msgid "YunoHost documentation"
msgstr ""
msgstr "Documentació de YunoHost"
#: templates/base.html:54 templates/base.html:151
#: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum"
msgstr "Inicieu sessió mitjançant el fòrum de YunoHost"
#: templates/base.html:111 templates/base.html:120 templates/base.html:220
#: templates/base.html:229
msgid "Packaging boards"
msgstr ""
#: templates/base.html:86 templates/base.html:179
#: templates/base.html:127 templates/base.html:237
msgid "Logout"
msgstr ""
msgstr "Tancar sessió"
#: templates/base.html:99
#: templates/base.html:140
msgid "Toggle menu"
msgstr ""
msgstr "Canvia el menú"
#: templates/base.html:197
#: templates/base.html:255
msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using "
"<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> "
"- <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/"
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
msgstr ""
"Fet amb <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> fent "
"servir <a class='text-blue-800' href='https://flask.palletsprojects."
"com'>Flask</a> i <a class='text-blue-800' href='https://tailwindcss."
"com/'>TailwindCSS</a>"
#: templates/base.html:256
msgid "Source"
msgstr "Font"
#: templates/base.html:257
msgid "Terms of Services"
msgstr "Condicions dels serveis"
#: templates/catalog.html:75 templates/catalog.html:80
msgid "Application Catalog"
msgstr ""
msgstr "Catàleg d'aplicacions"
#: templates/catalog.html:86 templates/wishlist.html:16
msgid "Search"
msgstr ""
msgstr "Cercar"
#: templates/catalog.html:91 templates/wishlist.html:21
msgid "Search for…"
msgstr ""
msgstr "Buscar…"
#: templates/catalog.html:107
msgid "All apps"
msgstr ""
msgstr "Totes les aplicacions"
#: templates/catalog.html:117 templates/wishlist.html:39
#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by"
msgstr ""
msgstr "Ordenar per"
#: templates/catalog.html:123 templates/wishlist.html:45
#: templates/wishlist.html:78
msgid "Popularity"
msgstr ""
msgstr "Popularitat"
#: templates/catalog.html:124
msgid "Newest"
msgstr ""
msgstr "Novetat"
#: templates/catalog.html:125 templates/wishlist.html:46
#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical"
msgstr ""
msgstr "Alfabèticament"
#: templates/catalog.html:128 templates/wishlist.html:49
#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49
msgid "Requires to be logged-in"
msgstr ""
msgstr "Requereix estar connectat"
#: templates/catalog.html:130 templates/catalog.html:139
#: templates/wishlist.html:51 templates/wishlist.html:60
#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred"
msgstr ""
msgstr "Mostra només les aplicacions que has destacat"
#: templates/catalog.html:155 templates/wishlist.html:154
msgid "No results found."
msgstr ""
msgstr "Sense resultats."
#: templates/catalog.html:158
msgid "Not finding what you are looking for?"
msgstr ""
msgstr "No trobes el que estàs buscant?"
#: templates/catalog.html:159
msgid "Checkout the wishlist!"
msgstr ""
msgstr "Fes una ullada a la llista de desitjos!"
#: templates/catalog.html:166
msgid "Applications currently flagged as broken"
msgstr ""
msgstr "Aplicacions marcades actualment com a trencades"
#: templates/catalog.html:169
msgid "These are apps which failed our automatic tests."
msgstr ""
"Aquestes són aplicacions que no han passat les nostres proves automàtiques."
#: templates/catalog.html:184
msgid "Deprecated applications"
msgstr ""
msgstr "Aplicacions obsoletes"
#: templates/catalog.html:187
msgid "These are apps who are not maintained anymore."
msgstr ""
msgstr "Aquestes són aplicacions que ja no es mantenen."
#: templates/catalog.html:188
msgid ""
"This means that the developer will no longer update them. We strongly "
"advise against their installation and advise users to find alternatives."
"This means that the developer will no longer update them. We strongly advise "
"against their installation and advise users to find alternatives."
msgstr ""
"Això vol dir que el desenvolupador ja no els actualitzarà. Desaconsellem "
"fermament la seva instal·lació i aconsellem als usuaris que trobin "
"alternatives."
#: templates/charts.html:5
msgid "Apps quality level from automatic tests"
msgstr ""
#: templates/charts.html:9
msgid "Apps quality level history"
msgstr ""
#: templates/charts.html:14
msgid "History"
msgstr ""
#: templates/charts.html:22
msgid "Added"
msgstr ""
#: templates/charts.html:28
msgid "Repaired"
msgstr ""
#: templates/charts.html:34
msgid "Broke"
msgstr ""
#: templates/charts.html:40
msgid "Removed"
msgstr ""
#: templates/charts.html:80
msgid "Unknown"
msgstr ""
#: templates/charts.html:81
msgid "Level 0"
msgstr ""
#: templates/charts.html:82
msgid "Level 1"
msgstr ""
#: templates/charts.html:83
msgid "Level 2"
msgstr ""
#: templates/charts.html:84
msgid "Level 3"
msgstr ""
#: templates/charts.html:85
msgid "Level 4"
msgstr ""
#: templates/charts.html:86
msgid "Level 5"
msgstr ""
#: templates/charts.html:87
msgid "Level 6"
msgstr ""
#: templates/charts.html:88
msgid "Level 7"
msgstr ""
#: templates/charts.html:89
msgid "Level 8"
msgstr ""
#: templates/charts.html:107
#, python-format
msgid "Level %(level)s:"
msgstr ""
#: templates/charts.html:107
msgid "Total:"
msgstr ""
#: templates/charts.html:108
#, python-format
msgid "Level %(level)s"
msgstr ""
#: templates/dash.html:3 templates/dash.html:9
msgid "App packaging dashboard"
msgstr ""
#: templates/dash.html:11
msgid ""
"This is where packagers can monitor the status of automatic tests (CI) and "
"ongoing major pull requests accross all apps. If you want to get started "
"with app packaging in YunoHost, please check out the <a class='text-"
"blue-500' href='https://yunohost.org/packaging_apps'>packaging "
"documentation</a> and come say hi to us on the <a class='text-blue-500' "
"href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!"
msgstr ""
#: templates/dash.html:17
msgid "Filter"
msgstr ""
#: templates/dash.html:23
msgid "(None)"
msgstr ""
#: templates/dash.html:24
msgid "Regressions on main CI"
msgstr ""
#: templates/dash.html:25
msgid "Broken / low quality apps"
msgstr ""
#: templates/dash.html:26
msgid "Outdated tests on main CI"
msgstr ""
#: templates/dash.html:27
msgid "Major regressions on Bookworm CI"
msgstr ""
#: templates/dash.html:28
msgid "Apps with testings PRs"
msgstr ""
#: templates/dash.html:29
msgid "Apps with autoupdate PRs"
msgstr ""
#: templates/dash.html:30
msgid "Packaging v1 apps"
msgstr ""
#: templates/dash.html:41
msgid "Quality level"
msgstr ""
#: templates/dash.html:42 templates/dash.html:173
#, fuzzy
msgid "Popularity stars"
msgstr "Popularitat"
#: templates/dash.html:43
msgid "Last update on main/master branch"
msgstr ""
#: templates/dash.html:44
msgid "Last update on testing branch"
msgstr ""
#: templates/dash.html:65
msgid "App"
msgstr ""
#: templates/dash.html:67
msgid "Main CI"
msgstr ""
#: templates/dash.html:68
msgid "Bookworm CI"
msgstr ""
#: templates/dash.html:69
msgid "Testing PR"
msgstr ""
#: templates/dash.html:70
msgid "Autoupdate PR"
msgstr ""
#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131
msgid "Broken"
msgstr ""
#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133
msgid "Low quality"
msgstr ""
#: templates/dash.html:112 templates/dash.html:127
#, python-format
msgid "Outdated test (%(days)s days ago)"
msgstr ""
#: templates/dash.html:150 templates/dash.html:165
#, python-format
msgid "Inactive (%(days)s days ago)"
msgstr ""
#: templates/dash.html:177
msgid "Packaging v1"
msgstr ""
#: templates/dash.html:180
#, fuzzy
msgid "Deprecated"
msgstr "Aplicacions obsoletes"
#: templates/dash.html:183
msgid "Not maintained"
msgstr ""
#: templates/index.html:10
msgid "Application Store"
msgstr ""
msgstr "Botiga d'aplicacions"
#: templates/index.html:21
msgid "Browse all applications"
msgstr "Exploreu totes les aplicacions"
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr "Suggerir una aplicació"
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr "Suggerir una aplicació per afegir al catàleg de YunoHost"
#: templates/wishlist_add.html:29
msgid "You must first login to be allowed to submit an app to the wishlist"
msgstr ""
"Primer heu d'iniciar sessió per poder enviar una aplicació a la llista de "
"desitjos"
#: templates/wishlist_add.html:40
msgid "Due to abuses, only one proposal every 15 days per user is allowed."
msgstr ""
"A causa dels abusos, només es permet una proposta cada 15 dies per usuari."
#: templates/wishlist_add.html:43
msgid ""
"Reviewing those proposals is tiring for volunteers, please don't yolo-send "
"every random nerdy stuff you find on the Internet."
msgstr ""
"Revisar aquestes propostes és cansador per als voluntaris, si us plau, no "
"envieu a la babalà totes les coses frikis a l'atzar que trobeu a Internet."
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr "Nom"
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr "Descripció de l'aplicació"
#: templates/wishlist_add.html:66
msgid "Please be concise and focus on what the app does."
msgstr "Sigues concís/a i centra't en el que fa l'aplicació."
#: templates/wishlist_add.html:66
msgid ""
"No need to repeat '[App] is …'. No need to state that it is free/open-source "
"or self-hosted (otherwise it wouldn't be packaged for YunoHost). Avoid "
"marketing stuff like 'the most', or vague properties like 'easy', 'simple', "
"'lightweight'."
msgstr ""
"No cal repetir «[L'aplicació] és…». No cal indicar que és gratuït/de codi "
"obert o que és autoallotjat (en cas contrari, no s'empaquetaria per a "
"YunoHost). Eviteu coses de màrqueting com «el més» o propietats vagues com "
"«fàcil», «simple», «lleuger»."
#: templates/wishlist_add.html:68
msgid "Project code repository"
msgstr "Repositori de codi del projecte"
#: templates/wishlist_add.html:71
msgid "Link to the project's LICENSE"
msgstr "Vincle a la LLICÈNCIA del projecte (arxiu LICENSE)"
#: templates/wishlist_add.html:73
msgid ""
"The YunoHost project will only package free/open-source software (with "
"possible case-by-case exceptions for apps which are not-totally-free)"
msgstr ""
"El projecte YunoHost només empaquetarà programari gratuït/de codi obert (amb "
"possibles excepcions cas per cas per a aplicacions que no són totalment "
"gratuïtes)"
#: templates/wishlist_add.html:75
msgid "Project website"
msgstr "Web del projecte"
#: templates/wishlist_add.html:77
msgid ""
"Please *do not* just copy-paste the code repository URL. If the project has "
"no proper website, then leave the field empty."
msgstr ""
"Si us plau, *no* només copieu i enganxeu l'URL del dipòsit de codi. Si el "
"projecte no té un lloc web adequat, deixeu el camp buit."
#: templates/wishlist_add.html:84
msgid "Submit"
msgstr "Enviar"
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
msgstr "Llista de desitjos d'aplicacions"
#: templates/wishlist.html:10
msgid ""
@ -373,89 +729,25 @@ msgid ""
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
"La llista de desitjos és el lloc on les persones poden suggerir i votar "
"col·lectivament les aplicacions que els agradaria veure empaquetades i "
"disponibles al catàleg oficial d'aplicacions de YunoHost. No obstant això, "
"el fet que les aplicacions s'enumeren aquí no s'ha d'interpretar de cap "
"manera com un fet que el projecte YunoHost té previst integrar-lo, i és "
"només una font d'inspiració per als voluntaris d'embalatge."
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
msgstr "Descripció"
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
msgstr "Pàgina web oficial"
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
msgstr "Repositori de codi"
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr ""
#: templates/wishlist_add.html:29
msgid "You must first login to be allowed to submit an app to the wishlist"
msgstr ""
#: templates/wishlist_add.html:40
msgid "Due to abuses, only one proposal every 15 days per user is allowed."
msgstr ""
#: templates/wishlist_add.html:43
msgid ""
"Reviewing those proposals is tiring for volunteers, please don't yolo-send "
"every random nerdy stuff you find on the Internet."
msgstr ""
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr ""
#: templates/wishlist_add.html:66
msgid "Please be concise and focus on what the app does."
msgstr ""
#: templates/wishlist_add.html:66
msgid ""
"No need to repeat '[App] is …'. No need to state that it is free/open-source "
"or self-hosted (otherwise it wouldn't be packaged for YunoHost). Avoid "
"marketing stuff like 'the most', or vague properties like 'easy', 'simple', "
"'lightweight'."
msgstr ""
#: templates/wishlist_add.html:68
msgid "Project code repository"
msgstr ""
#: templates/wishlist_add.html:71
msgid "Link to the project's LICENSE"
msgstr ""
#: templates/wishlist_add.html:73
msgid ""
"The YunoHost project will only package free/open-source software (with "
"possible case-by-case exceptions for apps which are not-totally-free)"
msgstr ""
#: templates/wishlist_add.html:75
msgid "Project website"
msgstr ""
#: templates/wishlist_add.html:77
msgid ""
"Please *do not* just copy-paste the code repository URL. If the project has "
"no proper website, then leave the field empty."
msgstr ""
#: templates/wishlist_add.html:84
msgid "Submit"
msgstr ""
msgstr "Destaca aquesta aplicació"

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-05 19:36+0100\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-02-21 06:08+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: ckb <LL@li.org>\n"
@ -18,15 +18,16 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.14.0\n"
#: app.py:150
msgid "App %(app_id) not found"
#: app.py:162
#, python-format
msgid "App %(app_id)s not found"
msgstr ""
#: app.py:152
#: app.py:165
msgid "You must be logged in to be able to star an app"
msgstr ""
#: app.py:152 app.py:195 app.py:449 templates/wishlist_add.html:33
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid ""
"Note that, due to various abuses, we restricted login on the app store to "
"'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts."
msgstr ""
#: app.py:195
#: app.py:210
msgid "You must be logged in to submit an app to the wishlist"
msgstr ""
#: app.py:207
#: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again"
msgstr ""
#: app.py:228
#: app.py:263
msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days."
msgstr ""
#: app.py:230
#: app.py:267
msgid "App name should be at least 3 characters"
msgstr ""
#: app.py:231
#: app.py:268
msgid "App name should be less than 30 characters"
msgstr ""
#: app.py:234
#: app.py:271
msgid "App description should be at least 5 characters"
msgstr ""
#: app.py:238
#: app.py:275
msgid "App description should be less than 100 characters"
msgstr ""
#: app.py:242
#: app.py:279
msgid "Upstream code repo URL should be at least 10 characters"
msgstr ""
#: app.py:246
#: app.py:283
msgid "Upstream code repo URL should be less than 150 characters"
msgstr ""
#: app.py:250
#: app.py:287
msgid "License URL should be at least 10 characters"
msgstr ""
#: app.py:254
#: app.py:291
msgid "License URL should be less than 250 characters"
msgstr ""
#: app.py:256
#: app.py:293
msgid "Website URL should be less than 150 characters"
msgstr ""
#: app.py:259
#: app.py:296
msgid "App name contains special characters"
msgstr ""
#: app.py:263
#: app.py:303
msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'."
msgstr ""
#: app.py:267
#: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr ""
#: app.py:301
#: app.py:343
#, python-format
msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you "
"can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr ""
#: app.py:325
#: app.py:358
#, python-format
msgid ""
"An app with the name %(slug)s already exists in the catalog, <a "
"href='%(url)s'>you can see its page here</a>."
msgstr ""
#: app.py:383
#, python-format
msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe "
@ -114,7 +122,7 @@ msgid ""
"please report the issue to the YunoHost team."
msgstr ""
#: app.py:376
#: app.py:433
#, python-format
msgid ""
"Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>"
msgstr ""
#: app.py:449
#: app.py:528
msgid "Unfortunately, login was denied."
msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr ""
#: templates/app.html:124
msgid "Anti-features"
msgid "Antifeatures"
msgstr ""
#: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license"
msgstr ""
#: templates/base.html:5
#: templates/base.html:11
msgid "YunoHost app store"
msgstr ""
#: templates/base.html:18 templates/base.html:113 templates/index.html:3
#: templates/base.html:31 templates/base.html:154 templates/index.html:3
msgid "Home"
msgstr ""
#: templates/base.html:27 templates/base.html:122
#: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog"
msgstr ""
#: templates/base.html:33 templates/base.html:131
#: templates/base.html:46 templates/base.html:172
msgid "Wishlist"
msgstr ""
#: templates/base.html:46 templates/base.html:141
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr ""
#: templates/base.html:57
msgid "Charts & history"
msgstr ""
#: templates/base.html:71 templates/base.html:182
msgid "YunoHost documentation"
msgstr ""
#: templates/base.html:54 templates/base.html:151
#: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum"
msgstr ""
#: templates/base.html:86 templates/base.html:179
#: templates/base.html:111 templates/base.html:120 templates/base.html:220
#: templates/base.html:229
msgid "Packaging boards"
msgstr ""
#: templates/base.html:127 templates/base.html:237
msgid "Logout"
msgstr ""
#: templates/base.html:99
#: templates/base.html:140
msgid "Toggle menu"
msgstr ""
#: templates/base.html:197
#: templates/base.html:255
msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using "
"<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> "
"- <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/"
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
msgstr ""
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps"
msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39
#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by"
msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest"
msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46
#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical"
msgstr ""
#: templates/catalog.html:128 templates/wishlist.html:49
#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49
msgid "Requires to be logged-in"
msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139
#: templates/wishlist.html:51 templates/wishlist.html:60
#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred"
msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188
msgid ""
"This means that the developer will no longer update them. We strongly "
"advise against their installation and advise users to find alternatives."
"This means that the developer will no longer update them. We strongly advise "
"against their installation and advise users to find alternatives."
msgstr ""
#: templates/charts.html:5
msgid "Apps quality level from automatic tests"
msgstr ""
#: templates/charts.html:9
msgid "Apps quality level history"
msgstr ""
#: templates/charts.html:14
msgid "History"
msgstr ""
#: templates/charts.html:22
msgid "Added"
msgstr ""
#: templates/charts.html:28
msgid "Repaired"
msgstr ""
#: templates/charts.html:34
msgid "Broke"
msgstr ""
#: templates/charts.html:40
msgid "Removed"
msgstr ""
#: templates/charts.html:80
msgid "Unknown"
msgstr ""
#: templates/charts.html:81
msgid "Level 0"
msgstr ""
#: templates/charts.html:82
msgid "Level 1"
msgstr ""
#: templates/charts.html:83
msgid "Level 2"
msgstr ""
#: templates/charts.html:84
msgid "Level 3"
msgstr ""
#: templates/charts.html:85
msgid "Level 4"
msgstr ""
#: templates/charts.html:86
msgid "Level 5"
msgstr ""
#: templates/charts.html:87
msgid "Level 6"
msgstr ""
#: templates/charts.html:88
msgid "Level 7"
msgstr ""
#: templates/charts.html:89
msgid "Level 8"
msgstr ""
#: templates/charts.html:107
#, python-format
msgid "Level %(level)s:"
msgstr ""
#: templates/charts.html:107
msgid "Total:"
msgstr ""
#: templates/charts.html:108
#, python-format
msgid "Level %(level)s"
msgstr ""
#: templates/dash.html:3 templates/dash.html:9
msgid "App packaging dashboard"
msgstr ""
#: templates/dash.html:11
msgid ""
"This is where packagers can monitor the status of automatic tests (CI) and "
"ongoing major pull requests accross all apps. If you want to get started "
"with app packaging in YunoHost, please check out the <a class='text-"
"blue-500' href='https://yunohost.org/packaging_apps'>packaging "
"documentation</a> and come say hi to us on the <a class='text-blue-500' "
"href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!"
msgstr ""
#: templates/dash.html:17
msgid "Filter"
msgstr ""
#: templates/dash.html:23
msgid "(None)"
msgstr ""
#: templates/dash.html:24
msgid "Regressions on main CI"
msgstr ""
#: templates/dash.html:25
msgid "Broken / low quality apps"
msgstr ""
#: templates/dash.html:26
msgid "Outdated tests on main CI"
msgstr ""
#: templates/dash.html:27
msgid "Major regressions on Bookworm CI"
msgstr ""
#: templates/dash.html:28
msgid "Apps with testings PRs"
msgstr ""
#: templates/dash.html:29
msgid "Apps with autoupdate PRs"
msgstr ""
#: templates/dash.html:30
msgid "Packaging v1 apps"
msgstr ""
#: templates/dash.html:41
msgid "Quality level"
msgstr ""
#: templates/dash.html:42 templates/dash.html:173
msgid "Popularity stars"
msgstr ""
#: templates/dash.html:43
msgid "Last update on main/master branch"
msgstr ""
#: templates/dash.html:44
msgid "Last update on testing branch"
msgstr ""
#: templates/dash.html:65
msgid "App"
msgstr ""
#: templates/dash.html:67
msgid "Main CI"
msgstr ""
#: templates/dash.html:68
msgid "Bookworm CI"
msgstr ""
#: templates/dash.html:69
msgid "Testing PR"
msgstr ""
#: templates/dash.html:70
msgid "Autoupdate PR"
msgstr ""
#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131
msgid "Broken"
msgstr ""
#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133
msgid "Low quality"
msgstr ""
#: templates/dash.html:112 templates/dash.html:127
#, python-format
msgid "Outdated test (%(days)s days ago)"
msgstr ""
#: templates/dash.html:150 templates/dash.html:165
#, python-format
msgid "Inactive (%(days)s days ago)"
msgstr ""
#: templates/dash.html:177
msgid "Packaging v1"
msgstr ""
#: templates/dash.html:180
msgid "Deprecated"
msgstr ""
#: templates/dash.html:183
msgid "Not maintained"
msgstr ""
#: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet."
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84
msgid "Submit"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-05 19:36+0100\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-02-21 06:09+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: cs <LL@li.org>\n"
@ -18,15 +18,16 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);\n"
"Generated-By: Babel 2.14.0\n"
#: app.py:150
msgid "App %(app_id) not found"
#: app.py:162
#, python-format
msgid "App %(app_id)s not found"
msgstr ""
#: app.py:152
#: app.py:165
msgid "You must be logged in to be able to star an app"
msgstr ""
#: app.py:152 app.py:195 app.py:449 templates/wishlist_add.html:33
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid ""
"Note that, due to various abuses, we restricted login on the app store to "
"'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts."
msgstr ""
#: app.py:195
#: app.py:210
msgid "You must be logged in to submit an app to the wishlist"
msgstr ""
#: app.py:207
#: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again"
msgstr ""
#: app.py:228
#: app.py:263
msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days."
msgstr ""
#: app.py:230
#: app.py:267
msgid "App name should be at least 3 characters"
msgstr ""
#: app.py:231
#: app.py:268
msgid "App name should be less than 30 characters"
msgstr ""
#: app.py:234
#: app.py:271
msgid "App description should be at least 5 characters"
msgstr ""
#: app.py:238
#: app.py:275
msgid "App description should be less than 100 characters"
msgstr ""
#: app.py:242
#: app.py:279
msgid "Upstream code repo URL should be at least 10 characters"
msgstr ""
#: app.py:246
#: app.py:283
msgid "Upstream code repo URL should be less than 150 characters"
msgstr ""
#: app.py:250
#: app.py:287
msgid "License URL should be at least 10 characters"
msgstr ""
#: app.py:254
#: app.py:291
msgid "License URL should be less than 250 characters"
msgstr ""
#: app.py:256
#: app.py:293
msgid "Website URL should be less than 150 characters"
msgstr ""
#: app.py:259
#: app.py:296
msgid "App name contains special characters"
msgstr ""
#: app.py:263
#: app.py:303
msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'."
msgstr ""
#: app.py:267
#: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr ""
#: app.py:301
#: app.py:343
#, python-format
msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you "
"can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr ""
#: app.py:325
#: app.py:358
#, python-format
msgid ""
"An app with the name %(slug)s already exists in the catalog, <a "
"href='%(url)s'>you can see its page here</a>."
msgstr ""
#: app.py:383
#, python-format
msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe "
@ -114,7 +122,7 @@ msgid ""
"please report the issue to the YunoHost team."
msgstr ""
#: app.py:376
#: app.py:433
#, python-format
msgid ""
"Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>"
msgstr ""
#: app.py:449
#: app.py:528
msgid "Unfortunately, login was denied."
msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr ""
#: templates/app.html:124
msgid "Anti-features"
msgid "Antifeatures"
msgstr ""
#: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license"
msgstr ""
#: templates/base.html:5
#: templates/base.html:11
msgid "YunoHost app store"
msgstr ""
#: templates/base.html:18 templates/base.html:113 templates/index.html:3
#: templates/base.html:31 templates/base.html:154 templates/index.html:3
msgid "Home"
msgstr ""
#: templates/base.html:27 templates/base.html:122
#: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog"
msgstr ""
#: templates/base.html:33 templates/base.html:131
#: templates/base.html:46 templates/base.html:172
msgid "Wishlist"
msgstr ""
#: templates/base.html:46 templates/base.html:141
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr ""
#: templates/base.html:57
msgid "Charts & history"
msgstr ""
#: templates/base.html:71 templates/base.html:182
msgid "YunoHost documentation"
msgstr ""
#: templates/base.html:54 templates/base.html:151
#: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum"
msgstr ""
#: templates/base.html:86 templates/base.html:179
#: templates/base.html:111 templates/base.html:120 templates/base.html:220
#: templates/base.html:229
msgid "Packaging boards"
msgstr ""
#: templates/base.html:127 templates/base.html:237
msgid "Logout"
msgstr ""
#: templates/base.html:99
#: templates/base.html:140
msgid "Toggle menu"
msgstr ""
#: templates/base.html:197
#: templates/base.html:255
msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using "
"<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> "
"- <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/"
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
msgstr ""
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps"
msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39
#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by"
msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest"
msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46
#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical"
msgstr ""
#: templates/catalog.html:128 templates/wishlist.html:49
#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49
msgid "Requires to be logged-in"
msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139
#: templates/wishlist.html:51 templates/wishlist.html:60
#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred"
msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188
msgid ""
"This means that the developer will no longer update them. We strongly "
"advise against their installation and advise users to find alternatives."
"This means that the developer will no longer update them. We strongly advise "
"against their installation and advise users to find alternatives."
msgstr ""
#: templates/charts.html:5
msgid "Apps quality level from automatic tests"
msgstr ""
#: templates/charts.html:9
msgid "Apps quality level history"
msgstr ""
#: templates/charts.html:14
msgid "History"
msgstr ""
#: templates/charts.html:22
msgid "Added"
msgstr ""
#: templates/charts.html:28
msgid "Repaired"
msgstr ""
#: templates/charts.html:34
msgid "Broke"
msgstr ""
#: templates/charts.html:40
msgid "Removed"
msgstr ""
#: templates/charts.html:80
msgid "Unknown"
msgstr ""
#: templates/charts.html:81
msgid "Level 0"
msgstr ""
#: templates/charts.html:82
msgid "Level 1"
msgstr ""
#: templates/charts.html:83
msgid "Level 2"
msgstr ""
#: templates/charts.html:84
msgid "Level 3"
msgstr ""
#: templates/charts.html:85
msgid "Level 4"
msgstr ""
#: templates/charts.html:86
msgid "Level 5"
msgstr ""
#: templates/charts.html:87
msgid "Level 6"
msgstr ""
#: templates/charts.html:88
msgid "Level 7"
msgstr ""
#: templates/charts.html:89
msgid "Level 8"
msgstr ""
#: templates/charts.html:107
#, python-format
msgid "Level %(level)s:"
msgstr ""
#: templates/charts.html:107
msgid "Total:"
msgstr ""
#: templates/charts.html:108
#, python-format
msgid "Level %(level)s"
msgstr ""
#: templates/dash.html:3 templates/dash.html:9
msgid "App packaging dashboard"
msgstr ""
#: templates/dash.html:11
msgid ""
"This is where packagers can monitor the status of automatic tests (CI) and "
"ongoing major pull requests accross all apps. If you want to get started "
"with app packaging in YunoHost, please check out the <a class='text-"
"blue-500' href='https://yunohost.org/packaging_apps'>packaging "
"documentation</a> and come say hi to us on the <a class='text-blue-500' "
"href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!"
msgstr ""
#: templates/dash.html:17
msgid "Filter"
msgstr ""
#: templates/dash.html:23
msgid "(None)"
msgstr ""
#: templates/dash.html:24
msgid "Regressions on main CI"
msgstr ""
#: templates/dash.html:25
msgid "Broken / low quality apps"
msgstr ""
#: templates/dash.html:26
msgid "Outdated tests on main CI"
msgstr ""
#: templates/dash.html:27
msgid "Major regressions on Bookworm CI"
msgstr ""
#: templates/dash.html:28
msgid "Apps with testings PRs"
msgstr ""
#: templates/dash.html:29
msgid "Apps with autoupdate PRs"
msgstr ""
#: templates/dash.html:30
msgid "Packaging v1 apps"
msgstr ""
#: templates/dash.html:41
msgid "Quality level"
msgstr ""
#: templates/dash.html:42 templates/dash.html:173
msgid "Popularity stars"
msgstr ""
#: templates/dash.html:43
msgid "Last update on main/master branch"
msgstr ""
#: templates/dash.html:44
msgid "Last update on testing branch"
msgstr ""
#: templates/dash.html:65
msgid "App"
msgstr ""
#: templates/dash.html:67
msgid "Main CI"
msgstr ""
#: templates/dash.html:68
msgid "Bookworm CI"
msgstr ""
#: templates/dash.html:69
msgid "Testing PR"
msgstr ""
#: templates/dash.html:70
msgid "Autoupdate PR"
msgstr ""
#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131
msgid "Broken"
msgstr ""
#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133
msgid "Low quality"
msgstr ""
#: templates/dash.html:112 templates/dash.html:127
#, python-format
msgid "Outdated test (%(days)s days ago)"
msgstr ""
#: templates/dash.html:150 templates/dash.html:165
#, python-format
msgid "Inactive (%(days)s days ago)"
msgstr ""
#: templates/dash.html:177
msgid "Packaging v1"
msgstr ""
#: templates/dash.html:180
msgid "Deprecated"
msgstr ""
#: templates/dash.html:183
msgid "Not maintained"
msgstr ""
#: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet."
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84
msgid "Submit"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-05 19:36+0100\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-02-21 06:05+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: da <LL@li.org>\n"
@ -18,15 +18,16 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.14.0\n"
#: app.py:150
msgid "App %(app_id) not found"
#: app.py:162
#, python-format
msgid "App %(app_id)s not found"
msgstr ""
#: app.py:152
#: app.py:165
msgid "You must be logged in to be able to star an app"
msgstr ""
#: app.py:152 app.py:195 app.py:449 templates/wishlist_add.html:33
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid ""
"Note that, due to various abuses, we restricted login on the app store to "
"'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts."
msgstr ""
#: app.py:195
#: app.py:210
msgid "You must be logged in to submit an app to the wishlist"
msgstr ""
#: app.py:207
#: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again"
msgstr ""
#: app.py:228
#: app.py:263
msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days."
msgstr ""
#: app.py:230
#: app.py:267
msgid "App name should be at least 3 characters"
msgstr ""
#: app.py:231
#: app.py:268
msgid "App name should be less than 30 characters"
msgstr ""
#: app.py:234
#: app.py:271
msgid "App description should be at least 5 characters"
msgstr ""
#: app.py:238
#: app.py:275
msgid "App description should be less than 100 characters"
msgstr ""
#: app.py:242
#: app.py:279
msgid "Upstream code repo URL should be at least 10 characters"
msgstr ""
#: app.py:246
#: app.py:283
msgid "Upstream code repo URL should be less than 150 characters"
msgstr ""
#: app.py:250
#: app.py:287
msgid "License URL should be at least 10 characters"
msgstr ""
#: app.py:254
#: app.py:291
msgid "License URL should be less than 250 characters"
msgstr ""
#: app.py:256
#: app.py:293
msgid "Website URL should be less than 150 characters"
msgstr ""
#: app.py:259
#: app.py:296
msgid "App name contains special characters"
msgstr ""
#: app.py:263
#: app.py:303
msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'."
msgstr ""
#: app.py:267
#: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr ""
#: app.py:301
#: app.py:343
#, python-format
msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you "
"can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr ""
#: app.py:325
#: app.py:358
#, python-format
msgid ""
"An app with the name %(slug)s already exists in the catalog, <a "
"href='%(url)s'>you can see its page here</a>."
msgstr ""
#: app.py:383
#, python-format
msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe "
@ -114,7 +122,7 @@ msgid ""
"please report the issue to the YunoHost team."
msgstr ""
#: app.py:376
#: app.py:433
#, python-format
msgid ""
"Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>"
msgstr ""
#: app.py:449
#: app.py:528
msgid "Unfortunately, login was denied."
msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr ""
#: templates/app.html:124
msgid "Anti-features"
msgid "Antifeatures"
msgstr ""
#: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license"
msgstr ""
#: templates/base.html:5
#: templates/base.html:11
msgid "YunoHost app store"
msgstr ""
#: templates/base.html:18 templates/base.html:113 templates/index.html:3
#: templates/base.html:31 templates/base.html:154 templates/index.html:3
msgid "Home"
msgstr ""
#: templates/base.html:27 templates/base.html:122
#: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog"
msgstr ""
#: templates/base.html:33 templates/base.html:131
#: templates/base.html:46 templates/base.html:172
msgid "Wishlist"
msgstr ""
#: templates/base.html:46 templates/base.html:141
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr ""
#: templates/base.html:57
msgid "Charts & history"
msgstr ""
#: templates/base.html:71 templates/base.html:182
msgid "YunoHost documentation"
msgstr ""
#: templates/base.html:54 templates/base.html:151
#: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum"
msgstr ""
#: templates/base.html:86 templates/base.html:179
#: templates/base.html:111 templates/base.html:120 templates/base.html:220
#: templates/base.html:229
msgid "Packaging boards"
msgstr ""
#: templates/base.html:127 templates/base.html:237
msgid "Logout"
msgstr ""
#: templates/base.html:99
#: templates/base.html:140
msgid "Toggle menu"
msgstr ""
#: templates/base.html:197
#: templates/base.html:255
msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using "
"<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> "
"- <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/"
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
msgstr ""
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps"
msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39
#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by"
msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest"
msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46
#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical"
msgstr ""
#: templates/catalog.html:128 templates/wishlist.html:49
#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49
msgid "Requires to be logged-in"
msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139
#: templates/wishlist.html:51 templates/wishlist.html:60
#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred"
msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188
msgid ""
"This means that the developer will no longer update them. We strongly "
"advise against their installation and advise users to find alternatives."
"This means that the developer will no longer update them. We strongly advise "
"against their installation and advise users to find alternatives."
msgstr ""
#: templates/charts.html:5
msgid "Apps quality level from automatic tests"
msgstr ""
#: templates/charts.html:9
msgid "Apps quality level history"
msgstr ""
#: templates/charts.html:14
msgid "History"
msgstr ""
#: templates/charts.html:22
msgid "Added"
msgstr ""
#: templates/charts.html:28
msgid "Repaired"
msgstr ""
#: templates/charts.html:34
msgid "Broke"
msgstr ""
#: templates/charts.html:40
msgid "Removed"
msgstr ""
#: templates/charts.html:80
msgid "Unknown"
msgstr ""
#: templates/charts.html:81
msgid "Level 0"
msgstr ""
#: templates/charts.html:82
msgid "Level 1"
msgstr ""
#: templates/charts.html:83
msgid "Level 2"
msgstr ""
#: templates/charts.html:84
msgid "Level 3"
msgstr ""
#: templates/charts.html:85
msgid "Level 4"
msgstr ""
#: templates/charts.html:86
msgid "Level 5"
msgstr ""
#: templates/charts.html:87
msgid "Level 6"
msgstr ""
#: templates/charts.html:88
msgid "Level 7"
msgstr ""
#: templates/charts.html:89
msgid "Level 8"
msgstr ""
#: templates/charts.html:107
#, python-format
msgid "Level %(level)s:"
msgstr ""
#: templates/charts.html:107
msgid "Total:"
msgstr ""
#: templates/charts.html:108
#, python-format
msgid "Level %(level)s"
msgstr ""
#: templates/dash.html:3 templates/dash.html:9
msgid "App packaging dashboard"
msgstr ""
#: templates/dash.html:11
msgid ""
"This is where packagers can monitor the status of automatic tests (CI) and "
"ongoing major pull requests accross all apps. If you want to get started "
"with app packaging in YunoHost, please check out the <a class='text-"
"blue-500' href='https://yunohost.org/packaging_apps'>packaging "
"documentation</a> and come say hi to us on the <a class='text-blue-500' "
"href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!"
msgstr ""
#: templates/dash.html:17
msgid "Filter"
msgstr ""
#: templates/dash.html:23
msgid "(None)"
msgstr ""
#: templates/dash.html:24
msgid "Regressions on main CI"
msgstr ""
#: templates/dash.html:25
msgid "Broken / low quality apps"
msgstr ""
#: templates/dash.html:26
msgid "Outdated tests on main CI"
msgstr ""
#: templates/dash.html:27
msgid "Major regressions on Bookworm CI"
msgstr ""
#: templates/dash.html:28
msgid "Apps with testings PRs"
msgstr ""
#: templates/dash.html:29
msgid "Apps with autoupdate PRs"
msgstr ""
#: templates/dash.html:30
msgid "Packaging v1 apps"
msgstr ""
#: templates/dash.html:41
msgid "Quality level"
msgstr ""
#: templates/dash.html:42 templates/dash.html:173
msgid "Popularity stars"
msgstr ""
#: templates/dash.html:43
msgid "Last update on main/master branch"
msgstr ""
#: templates/dash.html:44
msgid "Last update on testing branch"
msgstr ""
#: templates/dash.html:65
msgid "App"
msgstr ""
#: templates/dash.html:67
msgid "Main CI"
msgstr ""
#: templates/dash.html:68
msgid "Bookworm CI"
msgstr ""
#: templates/dash.html:69
msgid "Testing PR"
msgstr ""
#: templates/dash.html:70
msgid "Autoupdate PR"
msgstr ""
#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131
msgid "Broken"
msgstr ""
#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133
msgid "Low quality"
msgstr ""
#: templates/dash.html:112 templates/dash.html:127
#, python-format
msgid "Outdated test (%(days)s days ago)"
msgstr ""
#: templates/dash.html:150 templates/dash.html:165
#, python-format
msgid "Inactive (%(days)s days ago)"
msgstr ""
#: templates/dash.html:177
msgid "Packaging v1"
msgstr ""
#: templates/dash.html:180
msgid "Deprecated"
msgstr ""
#: templates/dash.html:183
msgid "Not maintained"
msgstr ""
#: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet."
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84
msgid "Submit"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""

View file

@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-05 19:36+0100\n"
"PO-Revision-Date: 2024-03-06 17:37+0000\n"
"Last-Translator: Christian Wehrli <christian@chw.onl>\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-03-23 19:04+0000\n"
"Last-Translator: OniriCorpe <oniricorpe@disroot.org>\n"
"Language-Team: German <https://translate.yunohost.org/projects/yunohost/apps/"
"de/>\n"
"Language: de\n"
@ -17,18 +17,18 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.3.1\n"
"Generated-By: Babel 2.14.0\n"
#: app.py:150
msgid "App %(app_id) not found"
msgstr "App %(app_id) nicht gefunden"
#: app.py:162
#, python-format
msgid "App %(app_id)s not found"
msgstr "App %(app_id)s nicht gefunden"
#: app.py:152
#: app.py:165
msgid "You must be logged in to be able to star an app"
msgstr "Sie müssen angemeldet sein, um eine App markieren zu können"
#: app.py:152 app.py:195 app.py:449 templates/wishlist_add.html:33
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid ""
"Note that, due to various abuses, we restricted login on the app store to "
"'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -43,17 +43,17 @@ msgstr ""
"Beiträge gelesen und mindestens 10 Minuten damit verbracht haben, Beiträge "
"zu lesen."
#: app.py:195
#: app.py:210
msgid "You must be logged in to submit an app to the wishlist"
msgstr "Sie müssen angemeldet sein, um eine App auf die Wunschliste zu setzen"
#: app.py:207
#: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again"
msgstr ""
"Ungültiges CSRF-Token. Bitte aktualisieren Sie die Seite und versuchen Sie "
"es erneut"
#: app.py:228
#: app.py:263
msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days."
@ -62,49 +62,49 @@ msgstr ""
"pro Benutzer beschränkt. Bitte versuchen Sie es in ein paar Tagen noch "
"einmal."
#: app.py:230
#: app.py:267
msgid "App name should be at least 3 characters"
msgstr "Der App-Name sollte mindestens 3 Zeichen lang sein"
#: app.py:231
#: app.py:268
msgid "App name should be less than 30 characters"
msgstr "Der App-Name sollte weniger als 30 Zeichen lang sein"
#: app.py:234
#: app.py:271
msgid "App description should be at least 5 characters"
msgstr "Die App-Beschreibung sollte mindestens 5 Zeichen lang sein"
#: app.py:238
#: app.py:275
msgid "App description should be less than 100 characters"
msgstr "Die App-Beschreibung sollte weniger als 100 Zeichen umfassen"
#: app.py:242
#: app.py:279
msgid "Upstream code repo URL should be at least 10 characters"
msgstr ""
"Die Upstream-Code-Repository-URL sollte mindestens 10 Zeichen lang sein"
#: app.py:246
#: app.py:283
msgid "Upstream code repo URL should be less than 150 characters"
msgstr ""
"Die Upstream-Code-Repository-URL sollte weniger als 150 Zeichen lang sein"
#: app.py:250
#: app.py:287
msgid "License URL should be at least 10 characters"
msgstr "Die Lizenz-URL sollte mindestens 10 Zeichen lang sein"
#: app.py:254
#: app.py:291
msgid "License URL should be less than 250 characters"
msgstr "Die Lizenz-URL sollte weniger als 250 Zeichen lang sein"
#: app.py:256
#: app.py:293
msgid "Website URL should be less than 150 characters"
msgstr "Die Website-URL sollte weniger als 150 Zeichen lang sein"
#: app.py:259
#: app.py:296
msgid "App name contains special characters"
msgstr "Der App-Name enthält Sonderzeichen"
#: app.py:263
#: app.py:303
msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'."
@ -113,13 +113,13 @@ msgstr ""
"unpräzise Begriffe zu verwenden oder zu wiederholen, dass die App 'frei' und "
"'selbsthostbar' ist."
#: app.py:267
#: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr ""
"Bitte wiederholen Sie den Namen der Anwendung nicht. Es geht darum, was die "
"App tut."
#: app.py:301
#: app.py:343
#, python-format
msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you "
@ -129,7 +129,22 @@ msgstr ""
"Sie können stattdessen der App <a href='%(url)s'>einen Stern hinzufügen</a>, "
"um Ihr Interesse zu zeigen."
#: app.py:325
# | msgid ""
# | "An entry with the name %(slug)s already exists in the wishlist, instead,
# "
# | "you can <a href='%(url)s'>add a star to the app to show your
# interest</a>."
#: app.py:358
#, fuzzy, python-format
msgid ""
"An app with the name %(slug)s already exists in the catalog, <a "
"href='%(url)s'>you can see its page here</a>."
msgstr ""
"In der Wunschliste ist bereits ein Eintrag mit dem Namen %(slug)s vorhanden. "
"Sie können stattdessen der App <a href='%(url)s'>einen Stern hinzufügen</a>, "
"um Ihr Interesse zu zeigen."
#: app.py:383
#, python-format
msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe "
@ -137,11 +152,10 @@ msgid ""
"please report the issue to the YunoHost team."
msgstr ""
"Pull-Request zum Hinzufügen der App zur Wunschliste konnte nicht erstellt "
"werden... Vielleicht gibt es bereits <a href='%(url)s'>einen wartenden PR "
"für diese App</a>? Andernfalls melden Sie das Problem bitte dem YunoHost-"
"Team."
"werden… Vielleicht gibt es bereits <a href='%(url)s'>einen wartenden PR für "
"diese App</a>? Andernfalls melden Sie das Problem bitte dem YunoHost-Team."
#: app.py:376
#: app.py:433
#, python-format
msgid ""
"Your proposed app has succesfully been submitted. It must now be validated "
@ -152,7 +166,7 @@ msgstr ""
"YunoHost-Team validiert werden. Sie können den Fortschritt hier verfolgen: "
"<a href='%(url)s'>%(url)s</a>"
#: app.py:449
#: app.py:528
msgid "Unfortunately, login was denied."
msgstr "Leider wurde die Anmeldung verweigert."
@ -234,8 +248,10 @@ msgstr ""
msgid "Important infos before installing"
msgstr "Wichtige Informationen vor der Installation"
# | msgid "Anti-features"
#: templates/app.html:124
msgid "Anti-features"
#, fuzzy
msgid "Antifeatures"
msgstr "Anti-Funktionen"
#: templates/app.html:125
@ -276,52 +292,69 @@ msgstr "YunoHost Paket-Repository"
msgid "YunoHost package license"
msgstr "YunoHost Paket-Lizenz"
#: templates/base.html:5
#: templates/base.html:11
msgid "YunoHost app store"
msgstr "YunoHost App-Store"
#: templates/base.html:18 templates/base.html:113 templates/index.html:3
#: templates/base.html:31 templates/base.html:154 templates/index.html:3
msgid "Home"
msgstr "Home"
#: templates/base.html:27 templates/base.html:122
#: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog"
msgstr "Katalog"
#: templates/base.html:33 templates/base.html:131
#: templates/base.html:46 templates/base.html:172
msgid "Wishlist"
msgstr "Wunschliste"
#: templates/base.html:46 templates/base.html:141
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr ""
#: templates/base.html:57
msgid "Charts & history"
msgstr ""
#: templates/base.html:71 templates/base.html:182
msgid "YunoHost documentation"
msgstr "YunoHost-Dokumentation"
#: templates/base.html:54 templates/base.html:151
#: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum"
msgstr "Login über YunoHost-Forum"
#: templates/base.html:86 templates/base.html:179
#: templates/base.html:111 templates/base.html:120 templates/base.html:220
#: templates/base.html:229
msgid "Packaging boards"
msgstr ""
#: templates/base.html:127 templates/base.html:237
msgid "Logout"
msgstr "Ausloggen"
#: templates/base.html:99
#: templates/base.html:140
msgid "Toggle menu"
msgstr "Menu umschalten"
#: templates/base.html:197
#: templates/base.html:255
msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using "
"<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> "
"- <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/"
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
msgstr ""
"Hergestellt mit <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> "
"mit Hilfe von <a class='text-blue-800' href='https://flask.palletsprojects."
"com'>Flask</a> und <a class='text-blue-800' href='https://tailwindcss."
"com/'>TailwindCSS</a> - <a class='text-blue-800' href='https://github.com/"
"YunoHost/apps/tree/master/store'><i class='fa fa-code fa-fw' aria-"
"hidden='true'></i> Source</a>"
"com/'>TailwindCSS</a>"
#: templates/base.html:256
msgid "Source"
msgstr "Quelle"
#: templates/base.html:257
msgid "Terms of Services"
msgstr "Nutzungsbedingungen"
#: templates/catalog.html:75 templates/catalog.html:80
msgid "Application Catalog"
@ -339,7 +372,7 @@ msgstr "Suchen nach…"
msgid "All apps"
msgstr "Alle Apps"
#: templates/catalog.html:117 templates/wishlist.html:39
#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by"
msgstr "Sortieren nach"
@ -352,16 +385,16 @@ msgstr "Popularität"
msgid "Newest"
msgstr "Neueste"
#: templates/catalog.html:125 templates/wishlist.html:46
#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical"
msgstr "Alphabetisch"
#: templates/catalog.html:128 templates/wishlist.html:49
#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49
msgid "Requires to be logged-in"
msgstr "Erfordert eingeloggt zu sein"
#: templates/catalog.html:130 templates/catalog.html:139
#: templates/wishlist.html:51 templates/wishlist.html:60
#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred"
msgstr "Zeige nur meine Favoriten"
@ -386,25 +419,221 @@ msgid "These are apps which failed our automatic tests."
msgstr "Das sind Apps, welche die automatischen Tests nicht bestanden haben."
#: templates/catalog.html:184
#, fuzzy
#| msgid "Browse all applications"
msgid "Deprecated applications"
msgstr "Alle Applikationen"
msgstr "Veraltete Applikationen"
#: templates/catalog.html:187
#, fuzzy
#| msgid "These are apps which failed our automatic tests."
msgid "These are apps who are not maintained anymore."
msgstr "Das sind Apps, welche die automatischen Tests nicht bestanden haben."
msgstr "Dies sind Apps, die nicht mehr betreut werden."
#: templates/catalog.html:188
msgid ""
"This means that the developer will no longer update them. We strongly "
"advise against their installation and advise users to find alternatives."
"This means that the developer will no longer update them. We strongly advise "
"against their installation and advise users to find alternatives."
msgstr ""
"Das bedeutet, dass der/die Entwickler:in sie nicht mehr aktualisieren wird. "
"Wir raten dringend von deren Installation ab und empfehlen Benutzer:innen, "
"nach Alternativen zu suchen."
#: templates/charts.html:5
msgid "Apps quality level from automatic tests"
msgstr ""
#: templates/charts.html:9
msgid "Apps quality level history"
msgstr ""
#: templates/charts.html:14
msgid "History"
msgstr ""
#: templates/charts.html:22
msgid "Added"
msgstr ""
#: templates/charts.html:28
msgid "Repaired"
msgstr ""
#: templates/charts.html:34
msgid "Broke"
msgstr ""
#: templates/charts.html:40
msgid "Removed"
msgstr ""
#: templates/charts.html:80
msgid "Unknown"
msgstr ""
#: templates/charts.html:81
msgid "Level 0"
msgstr ""
#: templates/charts.html:82
msgid "Level 1"
msgstr ""
#: templates/charts.html:83
msgid "Level 2"
msgstr ""
#: templates/charts.html:84
msgid "Level 3"
msgstr ""
#: templates/charts.html:85
msgid "Level 4"
msgstr ""
#: templates/charts.html:86
msgid "Level 5"
msgstr ""
#: templates/charts.html:87
msgid "Level 6"
msgstr ""
#: templates/charts.html:88
msgid "Level 7"
msgstr ""
#: templates/charts.html:89
msgid "Level 8"
msgstr ""
#: templates/charts.html:107
#, python-format
msgid "Level %(level)s:"
msgstr ""
#: templates/charts.html:107
msgid "Total:"
msgstr ""
#: templates/charts.html:108
#, python-format
msgid "Level %(level)s"
msgstr ""
#: templates/dash.html:3 templates/dash.html:9
msgid "App packaging dashboard"
msgstr ""
#: templates/dash.html:11
msgid ""
"This is where packagers can monitor the status of automatic tests (CI) and "
"ongoing major pull requests accross all apps. If you want to get started "
"with app packaging in YunoHost, please check out the <a class='text-"
"blue-500' href='https://yunohost.org/packaging_apps'>packaging "
"documentation</a> and come say hi to us on the <a class='text-blue-500' "
"href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!"
msgstr ""
#: templates/dash.html:17
msgid "Filter"
msgstr ""
#: templates/dash.html:23
msgid "(None)"
msgstr ""
#: templates/dash.html:24
msgid "Regressions on main CI"
msgstr ""
#: templates/dash.html:25
msgid "Broken / low quality apps"
msgstr ""
#: templates/dash.html:26
msgid "Outdated tests on main CI"
msgstr ""
#: templates/dash.html:27
msgid "Major regressions on Bookworm CI"
msgstr ""
#: templates/dash.html:28
msgid "Apps with testings PRs"
msgstr ""
#: templates/dash.html:29
msgid "Apps with autoupdate PRs"
msgstr ""
#: templates/dash.html:30
msgid "Packaging v1 apps"
msgstr ""
#: templates/dash.html:41
msgid "Quality level"
msgstr ""
#: templates/dash.html:42 templates/dash.html:173
#, fuzzy
msgid "Popularity stars"
msgstr "Popularität"
#: templates/dash.html:43
msgid "Last update on main/master branch"
msgstr ""
#: templates/dash.html:44
msgid "Last update on testing branch"
msgstr ""
#: templates/dash.html:65
msgid "App"
msgstr ""
#: templates/dash.html:67
msgid "Main CI"
msgstr ""
#: templates/dash.html:68
msgid "Bookworm CI"
msgstr ""
#: templates/dash.html:69
msgid "Testing PR"
msgstr ""
#: templates/dash.html:70
msgid "Autoupdate PR"
msgstr ""
#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131
msgid "Broken"
msgstr ""
#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133
msgid "Low quality"
msgstr ""
#: templates/dash.html:112 templates/dash.html:127
#, python-format
msgid "Outdated test (%(days)s days ago)"
msgstr ""
#: templates/dash.html:150 templates/dash.html:165
#, python-format
msgid "Inactive (%(days)s days ago)"
msgstr ""
#: templates/dash.html:177
msgid "Packaging v1"
msgstr ""
#: templates/dash.html:180
#, fuzzy
msgid "Deprecated"
msgstr "Veraltete Applikationen"
#: templates/dash.html:183
msgid "Not maintained"
msgstr ""
"Das bedeutet, dass der Entwickler sie nicht mehr aktualisieren wird. Wir "
"raten dringend von deren Installation ab und empfehlen Benutzern, nach "
"Alternativen zu suchen."
#: templates/index.html:10
msgid "Application Store"
@ -414,50 +643,10 @@ msgstr "Applikations-Store"
msgid "Browse all applications"
msgstr "Alle Applikationen"
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr "Wunschliste für Applikationen"
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
"Die Wunschliste ist der Ort, an dem Menschen gemeinsam Apps, die ihrer "
"Meinung nach paketiert und im offiziellen App-Katalog von YunoHost verfügbar "
"gemacht werden sollen, vorschlagen und für sie stimmen können. Trotzdem ist "
"die Tatsache, dass Apps hier aufgeführt sind, keineswegs so zu "
"interpretieren, dass das YunoHost-Projekt eine Integration plant, sondern "
"lediglich eine Inspirationsquelle für ehrenamtliche Paketierer:innen."
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr "Eine App vorschlagen"
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr "Name"
#: templates/wishlist.html:74
msgid "Description"
msgstr "Beschreibung"
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr "Offizielle Website"
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr "Code-Repository"
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr "Dieser App einen Stern geben"
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr ""
@ -485,6 +674,10 @@ msgstr ""
"verschicken Sie nicht jedes beliebige nerdige Zeug, das Sie im Internet "
"finden."
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr "Name"
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr "App Beschreibung"
@ -501,7 +694,7 @@ msgid ""
"marketing stuff like 'the most', or vague properties like 'easy', 'simple', "
"'lightweight'."
msgstr ""
"Es ist nicht nötig, '[App] ist …' zu wiederholen. Es muss nicht angegeben "
"Es ist nicht nötig, '[App] ist…' zu wiederholen. Es muss nicht angegeben "
"werden, dass sie kostenlos/Open-Source oder selbst gehostet ist (andernfalls "
"wäre es nicht für YunoHost paketiert). Vermeiden Sie es, Dinge zu vermarkten "
"mit 'am meisten' oder vage Eigenschaften wie 'einfach', 'simpel', 'leicht'."
@ -537,3 +730,39 @@ msgstr ""
#: templates/wishlist_add.html:84
msgid "Submit"
msgstr "Einreichen"
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr "Wunschliste für Applikationen"
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
"Die Wunschliste ist der Ort, an dem Menschen gemeinsam Apps, die ihrer "
"Meinung nach paketiert und im offiziellen App-Katalog von YunoHost verfügbar "
"gemacht werden sollen, vorschlagen und für sie stimmen können. Trotzdem ist "
"die Tatsache, dass Apps hier aufgeführt sind, keineswegs so zu "
"interpretieren, dass das YunoHost-Projekt eine Integration plant, sondern "
"lediglich eine Inspirationsquelle für ehrenamtliche Paketierer:innen."
#: templates/wishlist.html:74
msgid "Description"
msgstr "Beschreibung"
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr "Offizielle Website"
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr "Code-Repository"
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr "Dieser App einen Stern geben"

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-05 19:36+0100\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-02-21 06:06+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: el <LL@li.org>\n"
@ -18,15 +18,16 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.14.0\n"
#: app.py:150
msgid "App %(app_id) not found"
#: app.py:162
#, python-format
msgid "App %(app_id)s not found"
msgstr ""
#: app.py:152
#: app.py:165
msgid "You must be logged in to be able to star an app"
msgstr ""
#: app.py:152 app.py:195 app.py:449 templates/wishlist_add.html:33
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid ""
"Note that, due to various abuses, we restricted login on the app store to "
"'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts."
msgstr ""
#: app.py:195
#: app.py:210
msgid "You must be logged in to submit an app to the wishlist"
msgstr ""
#: app.py:207
#: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again"
msgstr ""
#: app.py:228
#: app.py:263
msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days."
msgstr ""
#: app.py:230
#: app.py:267
msgid "App name should be at least 3 characters"
msgstr ""
#: app.py:231
#: app.py:268
msgid "App name should be less than 30 characters"
msgstr ""
#: app.py:234
#: app.py:271
msgid "App description should be at least 5 characters"
msgstr ""
#: app.py:238
#: app.py:275
msgid "App description should be less than 100 characters"
msgstr ""
#: app.py:242
#: app.py:279
msgid "Upstream code repo URL should be at least 10 characters"
msgstr ""
#: app.py:246
#: app.py:283
msgid "Upstream code repo URL should be less than 150 characters"
msgstr ""
#: app.py:250
#: app.py:287
msgid "License URL should be at least 10 characters"
msgstr ""
#: app.py:254
#: app.py:291
msgid "License URL should be less than 250 characters"
msgstr ""
#: app.py:256
#: app.py:293
msgid "Website URL should be less than 150 characters"
msgstr ""
#: app.py:259
#: app.py:296
msgid "App name contains special characters"
msgstr ""
#: app.py:263
#: app.py:303
msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'."
msgstr ""
#: app.py:267
#: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr ""
#: app.py:301
#: app.py:343
#, python-format
msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you "
"can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr ""
#: app.py:325
#: app.py:358
#, python-format
msgid ""
"An app with the name %(slug)s already exists in the catalog, <a "
"href='%(url)s'>you can see its page here</a>."
msgstr ""
#: app.py:383
#, python-format
msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe "
@ -114,7 +122,7 @@ msgid ""
"please report the issue to the YunoHost team."
msgstr ""
#: app.py:376
#: app.py:433
#, python-format
msgid ""
"Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>"
msgstr ""
#: app.py:449
#: app.py:528
msgid "Unfortunately, login was denied."
msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr ""
#: templates/app.html:124
msgid "Anti-features"
msgid "Antifeatures"
msgstr ""
#: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license"
msgstr ""
#: templates/base.html:5
#: templates/base.html:11
msgid "YunoHost app store"
msgstr ""
#: templates/base.html:18 templates/base.html:113 templates/index.html:3
#: templates/base.html:31 templates/base.html:154 templates/index.html:3
msgid "Home"
msgstr ""
#: templates/base.html:27 templates/base.html:122
#: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog"
msgstr ""
#: templates/base.html:33 templates/base.html:131
#: templates/base.html:46 templates/base.html:172
msgid "Wishlist"
msgstr ""
#: templates/base.html:46 templates/base.html:141
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr ""
#: templates/base.html:57
msgid "Charts & history"
msgstr ""
#: templates/base.html:71 templates/base.html:182
msgid "YunoHost documentation"
msgstr ""
#: templates/base.html:54 templates/base.html:151
#: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum"
msgstr ""
#: templates/base.html:86 templates/base.html:179
#: templates/base.html:111 templates/base.html:120 templates/base.html:220
#: templates/base.html:229
msgid "Packaging boards"
msgstr ""
#: templates/base.html:127 templates/base.html:237
msgid "Logout"
msgstr ""
#: templates/base.html:99
#: templates/base.html:140
msgid "Toggle menu"
msgstr ""
#: templates/base.html:197
#: templates/base.html:255
msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using "
"<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> "
"- <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/"
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
msgstr ""
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps"
msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39
#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by"
msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest"
msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46
#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical"
msgstr ""
#: templates/catalog.html:128 templates/wishlist.html:49
#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49
msgid "Requires to be logged-in"
msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139
#: templates/wishlist.html:51 templates/wishlist.html:60
#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred"
msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188
msgid ""
"This means that the developer will no longer update them. We strongly "
"advise against their installation and advise users to find alternatives."
"This means that the developer will no longer update them. We strongly advise "
"against their installation and advise users to find alternatives."
msgstr ""
#: templates/charts.html:5
msgid "Apps quality level from automatic tests"
msgstr ""
#: templates/charts.html:9
msgid "Apps quality level history"
msgstr ""
#: templates/charts.html:14
msgid "History"
msgstr ""
#: templates/charts.html:22
msgid "Added"
msgstr ""
#: templates/charts.html:28
msgid "Repaired"
msgstr ""
#: templates/charts.html:34
msgid "Broke"
msgstr ""
#: templates/charts.html:40
msgid "Removed"
msgstr ""
#: templates/charts.html:80
msgid "Unknown"
msgstr ""
#: templates/charts.html:81
msgid "Level 0"
msgstr ""
#: templates/charts.html:82
msgid "Level 1"
msgstr ""
#: templates/charts.html:83
msgid "Level 2"
msgstr ""
#: templates/charts.html:84
msgid "Level 3"
msgstr ""
#: templates/charts.html:85
msgid "Level 4"
msgstr ""
#: templates/charts.html:86
msgid "Level 5"
msgstr ""
#: templates/charts.html:87
msgid "Level 6"
msgstr ""
#: templates/charts.html:88
msgid "Level 7"
msgstr ""
#: templates/charts.html:89
msgid "Level 8"
msgstr ""
#: templates/charts.html:107
#, python-format
msgid "Level %(level)s:"
msgstr ""
#: templates/charts.html:107
msgid "Total:"
msgstr ""
#: templates/charts.html:108
#, python-format
msgid "Level %(level)s"
msgstr ""
#: templates/dash.html:3 templates/dash.html:9
msgid "App packaging dashboard"
msgstr ""
#: templates/dash.html:11
msgid ""
"This is where packagers can monitor the status of automatic tests (CI) and "
"ongoing major pull requests accross all apps. If you want to get started "
"with app packaging in YunoHost, please check out the <a class='text-"
"blue-500' href='https://yunohost.org/packaging_apps'>packaging "
"documentation</a> and come say hi to us on the <a class='text-blue-500' "
"href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!"
msgstr ""
#: templates/dash.html:17
msgid "Filter"
msgstr ""
#: templates/dash.html:23
msgid "(None)"
msgstr ""
#: templates/dash.html:24
msgid "Regressions on main CI"
msgstr ""
#: templates/dash.html:25
msgid "Broken / low quality apps"
msgstr ""
#: templates/dash.html:26
msgid "Outdated tests on main CI"
msgstr ""
#: templates/dash.html:27
msgid "Major regressions on Bookworm CI"
msgstr ""
#: templates/dash.html:28
msgid "Apps with testings PRs"
msgstr ""
#: templates/dash.html:29
msgid "Apps with autoupdate PRs"
msgstr ""
#: templates/dash.html:30
msgid "Packaging v1 apps"
msgstr ""
#: templates/dash.html:41
msgid "Quality level"
msgstr ""
#: templates/dash.html:42 templates/dash.html:173
msgid "Popularity stars"
msgstr ""
#: templates/dash.html:43
msgid "Last update on main/master branch"
msgstr ""
#: templates/dash.html:44
msgid "Last update on testing branch"
msgstr ""
#: templates/dash.html:65
msgid "App"
msgstr ""
#: templates/dash.html:67
msgid "Main CI"
msgstr ""
#: templates/dash.html:68
msgid "Bookworm CI"
msgstr ""
#: templates/dash.html:69
msgid "Testing PR"
msgstr ""
#: templates/dash.html:70
msgid "Autoupdate PR"
msgstr ""
#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131
msgid "Broken"
msgstr ""
#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133
msgid "Low quality"
msgstr ""
#: templates/dash.html:112 templates/dash.html:127
#, python-format
msgid "Outdated test (%(days)s days ago)"
msgstr ""
#: templates/dash.html:150 templates/dash.html:165
#, python-format
msgid "Inactive (%(days)s days ago)"
msgstr ""
#: templates/dash.html:177
msgid "Packaging v1"
msgstr ""
#: templates/dash.html:180
msgid "Deprecated"
msgstr ""
#: templates/dash.html:183
msgid "Not maintained"
msgstr ""
#: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet."
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84
msgid "Submit"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-05 19:36+0100\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-02-21 06:06+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: eo <LL@li.org>\n"
@ -18,15 +18,16 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.14.0\n"
#: app.py:150
msgid "App %(app_id) not found"
#: app.py:162
#, python-format
msgid "App %(app_id)s not found"
msgstr ""
#: app.py:152
#: app.py:165
msgid "You must be logged in to be able to star an app"
msgstr ""
#: app.py:152 app.py:195 app.py:449 templates/wishlist_add.html:33
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid ""
"Note that, due to various abuses, we restricted login on the app store to "
"'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts."
msgstr ""
#: app.py:195
#: app.py:210
msgid "You must be logged in to submit an app to the wishlist"
msgstr ""
#: app.py:207
#: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again"
msgstr ""
#: app.py:228
#: app.py:263
msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days."
msgstr ""
#: app.py:230
#: app.py:267
msgid "App name should be at least 3 characters"
msgstr ""
#: app.py:231
#: app.py:268
msgid "App name should be less than 30 characters"
msgstr ""
#: app.py:234
#: app.py:271
msgid "App description should be at least 5 characters"
msgstr ""
#: app.py:238
#: app.py:275
msgid "App description should be less than 100 characters"
msgstr ""
#: app.py:242
#: app.py:279
msgid "Upstream code repo URL should be at least 10 characters"
msgstr ""
#: app.py:246
#: app.py:283
msgid "Upstream code repo URL should be less than 150 characters"
msgstr ""
#: app.py:250
#: app.py:287
msgid "License URL should be at least 10 characters"
msgstr ""
#: app.py:254
#: app.py:291
msgid "License URL should be less than 250 characters"
msgstr ""
#: app.py:256
#: app.py:293
msgid "Website URL should be less than 150 characters"
msgstr ""
#: app.py:259
#: app.py:296
msgid "App name contains special characters"
msgstr ""
#: app.py:263
#: app.py:303
msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'."
msgstr ""
#: app.py:267
#: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr ""
#: app.py:301
#: app.py:343
#, python-format
msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you "
"can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr ""
#: app.py:325
#: app.py:358
#, python-format
msgid ""
"An app with the name %(slug)s already exists in the catalog, <a "
"href='%(url)s'>you can see its page here</a>."
msgstr ""
#: app.py:383
#, python-format
msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe "
@ -114,7 +122,7 @@ msgid ""
"please report the issue to the YunoHost team."
msgstr ""
#: app.py:376
#: app.py:433
#, python-format
msgid ""
"Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>"
msgstr ""
#: app.py:449
#: app.py:528
msgid "Unfortunately, login was denied."
msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr ""
#: templates/app.html:124
msgid "Anti-features"
msgid "Antifeatures"
msgstr ""
#: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license"
msgstr ""
#: templates/base.html:5
#: templates/base.html:11
msgid "YunoHost app store"
msgstr ""
#: templates/base.html:18 templates/base.html:113 templates/index.html:3
#: templates/base.html:31 templates/base.html:154 templates/index.html:3
msgid "Home"
msgstr ""
#: templates/base.html:27 templates/base.html:122
#: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog"
msgstr ""
#: templates/base.html:33 templates/base.html:131
#: templates/base.html:46 templates/base.html:172
msgid "Wishlist"
msgstr ""
#: templates/base.html:46 templates/base.html:141
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr ""
#: templates/base.html:57
msgid "Charts & history"
msgstr ""
#: templates/base.html:71 templates/base.html:182
msgid "YunoHost documentation"
msgstr ""
#: templates/base.html:54 templates/base.html:151
#: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum"
msgstr ""
#: templates/base.html:86 templates/base.html:179
#: templates/base.html:111 templates/base.html:120 templates/base.html:220
#: templates/base.html:229
msgid "Packaging boards"
msgstr ""
#: templates/base.html:127 templates/base.html:237
msgid "Logout"
msgstr ""
#: templates/base.html:99
#: templates/base.html:140
msgid "Toggle menu"
msgstr ""
#: templates/base.html:197
#: templates/base.html:255
msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using "
"<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> "
"- <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/"
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
msgstr ""
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps"
msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39
#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by"
msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest"
msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46
#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical"
msgstr ""
#: templates/catalog.html:128 templates/wishlist.html:49
#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49
msgid "Requires to be logged-in"
msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139
#: templates/wishlist.html:51 templates/wishlist.html:60
#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred"
msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188
msgid ""
"This means that the developer will no longer update them. We strongly "
"advise against their installation and advise users to find alternatives."
"This means that the developer will no longer update them. We strongly advise "
"against their installation and advise users to find alternatives."
msgstr ""
#: templates/charts.html:5
msgid "Apps quality level from automatic tests"
msgstr ""
#: templates/charts.html:9
msgid "Apps quality level history"
msgstr ""
#: templates/charts.html:14
msgid "History"
msgstr ""
#: templates/charts.html:22
msgid "Added"
msgstr ""
#: templates/charts.html:28
msgid "Repaired"
msgstr ""
#: templates/charts.html:34
msgid "Broke"
msgstr ""
#: templates/charts.html:40
msgid "Removed"
msgstr ""
#: templates/charts.html:80
msgid "Unknown"
msgstr ""
#: templates/charts.html:81
msgid "Level 0"
msgstr ""
#: templates/charts.html:82
msgid "Level 1"
msgstr ""
#: templates/charts.html:83
msgid "Level 2"
msgstr ""
#: templates/charts.html:84
msgid "Level 3"
msgstr ""
#: templates/charts.html:85
msgid "Level 4"
msgstr ""
#: templates/charts.html:86
msgid "Level 5"
msgstr ""
#: templates/charts.html:87
msgid "Level 6"
msgstr ""
#: templates/charts.html:88
msgid "Level 7"
msgstr ""
#: templates/charts.html:89
msgid "Level 8"
msgstr ""
#: templates/charts.html:107
#, python-format
msgid "Level %(level)s:"
msgstr ""
#: templates/charts.html:107
msgid "Total:"
msgstr ""
#: templates/charts.html:108
#, python-format
msgid "Level %(level)s"
msgstr ""
#: templates/dash.html:3 templates/dash.html:9
msgid "App packaging dashboard"
msgstr ""
#: templates/dash.html:11
msgid ""
"This is where packagers can monitor the status of automatic tests (CI) and "
"ongoing major pull requests accross all apps. If you want to get started "
"with app packaging in YunoHost, please check out the <a class='text-"
"blue-500' href='https://yunohost.org/packaging_apps'>packaging "
"documentation</a> and come say hi to us on the <a class='text-blue-500' "
"href='https://yunohost.org/chat_rooms'>app packaging chatroom</a>!"
msgstr ""
#: templates/dash.html:17
msgid "Filter"
msgstr ""
#: templates/dash.html:23
msgid "(None)"
msgstr ""
#: templates/dash.html:24
msgid "Regressions on main CI"
msgstr ""
#: templates/dash.html:25
msgid "Broken / low quality apps"
msgstr ""
#: templates/dash.html:26
msgid "Outdated tests on main CI"
msgstr ""
#: templates/dash.html:27
msgid "Major regressions on Bookworm CI"
msgstr ""
#: templates/dash.html:28
msgid "Apps with testings PRs"
msgstr ""
#: templates/dash.html:29
msgid "Apps with autoupdate PRs"
msgstr ""
#: templates/dash.html:30
msgid "Packaging v1 apps"
msgstr ""
#: templates/dash.html:41
msgid "Quality level"
msgstr ""
#: templates/dash.html:42 templates/dash.html:173
msgid "Popularity stars"
msgstr ""
#: templates/dash.html:43
msgid "Last update on main/master branch"
msgstr ""
#: templates/dash.html:44
msgid "Last update on testing branch"
msgstr ""
#: templates/dash.html:65
msgid "App"
msgstr ""
#: templates/dash.html:67
msgid "Main CI"
msgstr ""
#: templates/dash.html:68
msgid "Bookworm CI"
msgstr ""
#: templates/dash.html:69
msgid "Testing PR"
msgstr ""
#: templates/dash.html:70
msgid "Autoupdate PR"
msgstr ""
#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131
msgid "Broken"
msgstr ""
#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133
msgid "Low quality"
msgstr ""
#: templates/dash.html:112 templates/dash.html:127
#, python-format
msgid "Outdated test (%(days)s days ago)"
msgstr ""
#: templates/dash.html:150 templates/dash.html:165
#, python-format
msgid "Inactive (%(days)s days ago)"
msgstr ""
#: templates/dash.html:177
msgid "Packaging v1"
msgstr ""
#: templates/dash.html:180
msgid "Deprecated"
msgstr ""
#: templates/dash.html:183
msgid "Not maintained"
msgstr ""
#: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app"
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""
#: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog"
msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet."
msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64
msgid "App's description"
msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84
msgid "Submit"
msgstr ""
#: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist"
msgstr ""
#: templates/wishlist.html:10
msgid ""
"The wishlist is the place where people can collectively suggest and vote for "
"apps that they would like to see packaged and made available in YunoHost's "
"official apps catalog. Nevertheless, the fact that apps are listed here "
"should by no mean be interpreted as a fact that the YunoHost project plans "
"to integrate it, and is merely a source of inspiration for packaging "
"volunteers."
msgstr ""
#: templates/wishlist.html:74
msgid "Description"
msgstr ""
#: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website"
msgstr ""
#: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository"
msgstr ""
#: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app"
msgstr ""

Some files were not shown because too many files have changed in this diff Show more