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/ .mypy_cache/
# Github authentication files # Github authentication files
/.github_* /tools/.github_*
# yunohost specific cache/output dirs # yunohost specific cache/output dirs
.apps_cache .apps_cache
builds* 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: To add your application to the catalog:
* Fork [this repository](https://github.com/YunoHost/apps) - Fork [this repository](https://github.com/YunoHost/apps)
* Edit the [`apps.toml`](/apps.toml) file - Edit the [`apps.toml`](/apps.toml) file
* Add your app's ID and git information at the right alphabetical place - 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's functioning state: `notworking`, `inprogress`, or `working`
* Indicate the app category, which you can pick from `categories.toml` - 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 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) - 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. - *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 - 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.
* Create a [Pull Request](https://github.com/YunoHost/apps/pulls/) - Commit and push your modifications to your repository
- Create a [Pull Request](https://github.com/YunoHost/apps/pulls/)
App example addition: App example addition:

View file

@ -1,151 +1,153 @@
#:schema https://github.com/YunoHost/apps/blob/master/schemas/antifeatures.toml.schema.json
[tracking] [tracking]
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" icon = "user-secret"
title.en = "Tracking" title.en = "Tracking"
title.eu = "Jarraipena" title.eu = "Jarraipena"
title.fr = "Pistage " title.fr = "Pistage "
title.it = "Tracciamento" 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."
[non-free-network] [non-free-network]
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" icon = "sitemap"
title.en = "Non-free Network Services" title.en = "Non-free Network Services"
title.eu = "Libreak ez diren sareko zerbitzuak" title.eu = "Libreak ez diren sareko zerbitzuak"
title.fr = "Services réseau non libres " title.fr = "Services réseau non libres "
title.it = "Servizi di rete non liberi" 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."
[non-free-addons] [non-free-addons]
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" icon = "puzzle-piece"
title.en = "Non-free Addons" title.en = "Non-free Addons"
title.eu = "Libreak ez diren gehigarriak" title.eu = "Libreak ez diren gehigarriak"
title.fr = "Extensions non libres " title.fr = "Extensions non libres "
title.it = "Estensioni non libere" 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"
[non-free-dependencies] [non-free-dependencies]
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" icon = "book"
title.en = "Non-free dependencies" title.en = "Non-free dependencies"
title.eu = "Libreak ez diren dependentziak" title.eu = "Libreak ez diren dependentziak"
title.fr = "Dépendances non libres " title.fr = "Dépendances non libres "
title.it = "Dipendenze non libere" 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."
[non-free-assets] [non-free-assets]
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" icon = "file-image-o"
title.en = "Non-free assets" title.en = "Non-free assets"
title.eu = "Libreak ez diren baliabideak" title.eu = "Libreak ez diren baliabideak"
title.fr = "Ressources non libres " title.fr = "Ressources non libres "
title.it = "Risorse non libere" 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."
[bad-security-reputation] [bad-security-reputation]
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" icon = "bug"
title.en = "Bad security reputation" title.en = "Bad security reputation"
title.eu = "Segurtasun txarreko ospea" title.eu = "Segurtasun txarreko ospea"
title.fr = "Mauvaise réputation en matière de sécurité " title.fr = "Mauvaise réputation en matière de sécurité "
title.it = "Cattiva reputazione di sicurezza" 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)."
[deprecated-software] [deprecated-software]
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" icon = "trash-o"
title.en = "Upstream not maintained" title.en = "Upstream not maintained"
title.eu = "Jatorrizko garapena utzita" title.eu = "Jatorrizko garapena utzita"
title.fr = "Application non maintenue " title.fr = "Application non maintenue "
title.it = "Applicazione non mantenuta" 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."
[package-not-maintained] [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" icon = "user-times"
title.en = "Package not maintained" title.en = "Package not maintained"
title.eu = "Mantendu gabeko paketea" title.eu = "Mantendu gabeko paketea"
title.fr = "Paquet non maintenu" title.fr = "Package non maintenu "
title.it = "Pacchetto non mantenuto" 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] [paid-content]
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" icon = "money"
title.en = "Paid content" title.en = "Paid content"
title.eu = "Ordainpeko edukia" title.eu = "Ordainpeko edukia"
title.fr = "Contenu payant " title.fr = "Contenu payant "
title.it = "Contenuti a pagamento" 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."
[arbitrary-limitations] [arbitrary-limitations]
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" icon = "star-half-empty"
title.en = "Arbitrary limitations" title.en = "Arbitrary limitations"
title.eu = "Muga arbitrarioak" title.eu = "Muga arbitrarioak"
title.fr = "Limitations arbitraires " title.fr = "Limitations arbitraires "
title.it = "Limitazioni arbitrarie" 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”."
[replaced-by-another-app] [replaced-by-another-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" icon = "repeat"
title.en = "Replaced by another app" title.en = "Replaced by another app"
title.eu = "Beste aplikazio batek ordeztu du" title.eu = "Beste aplikazio batek ordeztu du"
title.fr = "Remplacé par une autre application " title.fr = "Remplacé par une autre application "
title.it = "Sostituita da unaltra app" 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”."
[alpha-software] [alpha-software]
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" icon = "flask"
title.en = "Alpha software" title.en = "Alpha software"
title.eu = "Alfa softwarea" title.eu = "Alfa softwarea"
title.fr = "Logiciel en version alpha " title.fr = "Logiciel en version alpha "
title.it = "Software in versione 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."
[not-totally-free-upstream] [not-totally-free-upstream]
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" icon = "lock"
title.en = "Not totally free upstream" title.en = "Not totally free upstream"
title.eu = "Jatorrizkoa ez da erabat librea" title.eu = "Jatorrizkoa ez da erabat librea"
title.fr = "Application sous licence libre restreinte " title.fr = "Application sous licence libre restreinte "
title.it = "Applicazione con licenza parzialmente libera" 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.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."
[not-totally-free-package] [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" icon = "archive"
title.en = "Not totally free package" title.en = "Not totally free package"
title.eu = "Paketea ez da erabat librea" title.eu = "Paketea ez da erabat librea"
title.fr = "Package sous licence libre restreinte " 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."

1105
apps.toml

File diff suppressed because it is too large Load diff

View file

@ -1,15 +1,17 @@
#:schema https://raw.githubusercontent.com/YunoHost/apps/master/schemas/categories.toml.schema.json
[synchronization] [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" icon = "cloud"
title.en = "Synchronization" title.en = "Synchronization"
title.es = "Sincronización" title.es = "Sincronización"
title.eu = "Sinkronizazioa" title.eu = "Sinkronizazioa"
title.fr = "Synchronisation" title.fr = "Synchronisation"
title.it = "Sincronizzazione" 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] [synchronization.subtags.files]
title.en = "Files" title.en = "Files"
@ -40,17 +42,17 @@ description.it = "Sincronizzazione di file, contatti, calendari, gestione passwo
title.it = "Password" title.it = "Password"
[publishing] [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" icon = "globe"
title.en = "Publishing" title.en = "Publishing"
title.es = "Publicaciones" title.es = "Publicaciones"
title.eu = "Argitalpenak" title.eu = "Argitalpenak"
title.fr = "Publication" title.fr = "Publication"
title.it = "Pubblicazione" 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] [publishing.subtags.website]
title.en = "Website" title.en = "Website"
@ -88,17 +90,17 @@ description.it = "Siti web, blog, wiki, CMS…"
title.it = "Analisi del traffico" title.it = "Analisi del traffico"
[communication] [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" icon = "comments-o"
title.en = "Communication" title.en = "Communication"
title.es = "Comunicacion" title.es = "Comunicacion"
title.eu = "Komunikazioa" title.eu = "Komunikazioa"
title.fr = "Communication" title.fr = "Communication"
title.it = "Comunicazione" 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] [communication.subtags.chat]
title.en = "Instant messaging" title.en = "Instant messaging"
@ -129,17 +131,17 @@ description.it = "Messaggistica, posta elettronica, forum, riunioni…"
title.it = "Riunioni" title.it = "Riunioni"
[office] [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" icon = "file-text-o"
title.en = "Office" title.en = "Office"
title.es = "Ofimatica" title.es = "Ofimatica"
title.eu = "Bulegoa" title.eu = "Bulegoa"
title.fr = "Bureautique" title.fr = "Bureautique"
title.it = "Burocrazia" 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] [office.subtags.text]
title.en = "Text" title.en = "Text"
@ -176,15 +178,15 @@ description.it = "Modifica di testo collaborativa, tabelle…"
title.it = "Mappe mentali" title.it = "Mappe mentali"
[productivity_and_management] [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" icon = "area-chart"
title.en = "Productivity & management" title.en = "Productivity & management"
title.eu = "Produktibitatea eta kudeaketa" title.eu = "Produktibitatea eta kudeaketa"
title.fr = "Productivité & gestion" title.fr = "Productivité & gestion"
title.it = "Produttività & gestionale" 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] [productivity_and_management.subtags.task]
title.en = "Task" title.en = "Task"
@ -211,15 +213,15 @@ description.it = "Gestione attività, sondaggi, contabilità, ERP…"
title.it = "Imprese e associazioni" title.it = "Imprese e associazioni"
[small_utilities] [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" icon = "umbrella"
title.en = "Small utilities" title.en = "Small utilities"
title.eu = "Tresna txikiak" title.eu = "Tresna txikiak"
title.fr = "Petits utilitaires" title.fr = "Petits utilitaires"
title.it = "Piccoli strumenti" 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] [small_utilities.subtags.pastebin]
title.en = "Pastebin" title.en = "Pastebin"
@ -240,15 +242,15 @@ description.it = "Pastebin, accorciamento di URL, proxy…"
title.it = "Proxy" title.it = "Proxy"
[reading] [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" icon = "newspaper-o"
title.en = "Reading" title.en = "Reading"
title.eu = "Irakurketa" title.eu = "Irakurketa"
title.fr = "Lecture" title.fr = "Lecture"
title.it = "Lettura" 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] [reading.subtags.rssreader]
title.en = "RSS readers" title.en = "RSS readers"
@ -263,15 +265,15 @@ description.it = "Notizie, libri…"
title.it = "Libri" title.it = "Libri"
[multimedia] [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" icon = "music"
title.en = "Multimedia" title.en = "Multimedia"
title.eu = "Multimedia" title.eu = "Multimedia"
title.fr = "Multimédia" title.fr = "Multimédia"
title.it = "Multimedia" 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] [multimedia.subtags.mediacenter]
title.en = "Media center" title.en = "Media center"
@ -304,15 +306,15 @@ description.it = "Librerie musicali, gallerie dimmagini, P2P, serie TV…"
title.it = "Video" title.it = "Video"
[social_media] [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" icon = "users"
title.en = "Social media" title.en = "Social media"
title.eu = "Sare sozialak" title.eu = "Sare sozialak"
title.fr = "Médias sociaux" title.fr = "Médias sociaux"
title.it = "Social media" 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] [social_media.subtags.microblogging]
title.en = "Microblogging" title.en = "Microblogging"
@ -351,26 +353,26 @@ description.it = "Microblogging, media federati"
title.it = "Musica" title.it = "Musica"
[games] [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" icon = "gamepad"
title.en = "Games" title.en = "Games"
title.eu = "Jolasak" title.eu = "Jolasak"
title.fr = "Jeux" title.fr = "Jeux"
title.it = "Giochi" 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] [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" icon = "flask"
title.en = "Development" title.en = "Development"
title.eu = "Garapena" title.eu = "Garapena"
title.fr = "Développement" title.fr = "Développement"
title.it = "Sviluppo" 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] [dev.subtags.forge]
title.en = "Forge" title.en = "Forge"
@ -397,15 +399,15 @@ description.it = "Forge Git, schematizzazione di applicazioni, CI, traduzioni…
title.it = "Progettazione" title.it = "Progettazione"
[system_tools] [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" icon = "wrench"
title.en = "System tools" title.en = "System tools"
title.eu = "Sistemaren tresnak" title.eu = "Sistemaren tresnak"
title.fr = "Outils système" title.fr = "Outils système"
title.it = "Strumenti di sistema" 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] [system_tools.subtags.backup]
title.en = "Backup" title.en = "Backup"
@ -432,23 +434,23 @@ description.it = "Monitoraggio, backup, servizi di rete, database…"
title.it = "Database" title.it = "Database"
[iot] [iot]
description.en = "Home automation, energy dashboard..."
description.eu = "Domotika, automatizazioa, energiaren kudeaketa..."
description.fr = "Domotique, énergie..."
description.it = "Domotica, controllo energia…"
icon = "home" icon = "home"
title.en = "Internet of Things (IoT)" title.en = "Internet of Things (IoT)"
title.eu = "Gauzen internet (IoT)" title.eu = "Gauzen internet (IoT)"
title.fr = "Internet des objets (IoT)" title.fr = "Internet des objets (IoT)"
title.it = "Interned delle Cose (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] [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" icon = "tree"
title.en = "Wat" title.en = "Wat"
title.eu = "Wat" title.eu = "Wat"
title.fr = "Wat" title.fr = "Wat"
title.it = "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 # 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 # Everyday at 01:30 UTC
30 20 * * * root /bin/bash __BASEDIR__/sourcesautoupdate.sh 30 1 * * * root /bin/bash __BASEDIR__/maintenance.sh autoupdate_app_sources
# Every friday at 6pm # Every friday at 6 PM UTC
0 17 * * 5 root /usr/bin/python3 __BASEDIR__/tools/update_app_levels/update_app_levels.py 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] [anfora]
added_date = 1554588215 # 2019/04/07
category = "social_media" category = "social_media"
killed_date = 1703600553 # 2023/12/26
subtags = [ "pictures" ] subtags = [ "pictures" ]
url = "https://github.com/YunoHost-Apps/anfora_ynh" url = "https://github.com/YunoHost-Apps/anfora_ynh"
[bibliogram] [bibliogram]
added_date = 1597045792 # 2020/08/10
category = "social_media" category = "social_media"
killed_date = 1703600553 # 2023/12/26
potential_alternative_to = [ "Instagram" ] potential_alternative_to = [ "Instagram" ]
subtags = [ "pictures" ] subtags = [ "pictures" ]
url = "https://github.com/YunoHost-Apps/bibliogram_ynh" url = "https://github.com/YunoHost-Apps/bibliogram_ynh"
[democracyos] [democracyos]
added_date = 1554588215 # 2019/04/07
category = "communication" category = "communication"
killed_date = 1703600553 # 2023/12/26
subtags = [ "forum" ] subtags = [ "forum" ]
url = "https://github.com/YunoHost-Apps/democracyos_ynh" url = "https://github.com/YunoHost-Apps/democracyos_ynh"
[dockerui] [dockerui]
added_date = 1554588215 # 2019/04/07
category = "system_tools" category = "system_tools"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/dockerui_ynh" url = "https://github.com/YunoHost-Apps/dockerui_ynh"
[dynette] [dynette]
added_date = 1554588215 # 2019/04/07
category = "wat" category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/dynette_ynh" url = "https://github.com/YunoHost-Apps/dynette_ynh"
[ecko] [ecko]
added_date = 1636827596 # 2021/11/13
category = "social_media" category = "social_media"
killed_date = 1703600553 # 2023/12/26
subtags = [ "microblogging" ] subtags = [ "microblogging" ]
url = "https://github.com/YunoHost-Apps/ecko_ynh" url = "https://github.com/YunoHost-Apps/ecko_ynh"
[fallback] [fallback]
added_date = 1554588215 # 2019/04/07
category = "system_tools" category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "backup" ] subtags = [ "backup" ]
url = "https://github.com/YunoHost-Apps/fallback_ynh" 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] [flask]
added_date = 1554588215 # 2019/04/07
category = "dev" category = "dev"
killed_date = 1703600553 # 2023/12/26
subtags = [ "skeleton" ] subtags = [ "skeleton" ]
url = "https://github.com/YunoHost-Apps/flask_ynh" url = "https://github.com/YunoHost-Apps/flask_ynh"
[flusio] [flusio]
added_date = 1660509055 # 2022/08/14
category = "reading" category = "reading"
killed_date = 1703600553 # 2023/12/26
subtags = [ "rssreader" ] subtags = [ "rssreader" ]
url = "https://github.com/YunoHost-Apps/flusio_ynh" url = "https://github.com/YunoHost-Apps/flusio_ynh"
[foodsoft] [foodsoft]
added_date = 1564517377 # 2019/07/30
category = "productivity_and_management" category = "productivity_and_management"
killed_date = 1703600553 # 2023/12/26
subtags = [ "business_and_ngos" ] subtags = [ "business_and_ngos" ]
url = "https://github.com/YunoHost-Apps/foodsoft_ynh" url = "https://github.com/YunoHost-Apps/foodsoft_ynh"
[framaestro] [framaestro]
added_date = 1554588215 # 2019/04/07
category = "communication" category = "communication"
killed_date = 1703600553 # 2023/12/26
subtags = [ "meeting" ] subtags = [ "meeting" ]
url = "https://github.com/YunoHost-Apps/framaestro_ynh" url = "https://github.com/YunoHost-Apps/framaestro_ynh"
[framaestro_hub] [framaestro_hub]
added_date = 1554588215 # 2019/04/07
category = "communication" category = "communication"
killed_date = 1703600553 # 2023/12/26
subtags = [ "meeting" ] subtags = [ "meeting" ]
url = "https://github.com/YunoHost-Apps/framaestro_hub_ynh" url = "https://github.com/YunoHost-Apps/framaestro_hub_ynh"
[freeboard] [freeboard]
added_date = 1554588215 # 2019/04/07
category = "iot" category = "iot"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/freeboard_ynh" url = "https://github.com/YunoHost-Apps/freeboard_ynh"
[freepbx] [freepbx]
added_date = 1590399842 # 2020/05/25
category = "communication" category = "communication"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/freepbx_ynh" url = "https://github.com/YunoHost-Apps/freepbx_ynh"
[ftp_webapp] [ftp_webapp]
added_date = 1554588215 # 2019/04/07
category = "small_utilities" category = "small_utilities"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/ftp_support_webapp_ynh" url = "https://github.com/YunoHost-Apps/ftp_support_webapp_ynh"
[ftssolr] [ftssolr]
added_date = 1590399842 # 2020/05/25
category = "wat" category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/ftssolr_ynh" 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] [gekko]
added_date = 1590399842 # 2020/05/25
category = "wat" category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/gekko_ynh" url = "https://github.com/YunoHost-Apps/gekko_ynh"
[gitrepositories] [gitrepositories]
added_date = 1554588215 # 2019/04/07
category = "dev" category = "dev"
killed_date = 1703600553 # 2023/12/26
subtags = [ "forge" ] subtags = [ "forge" ]
url = "https://github.com/YunoHost-Apps/gitrepositories_ynh" url = "https://github.com/YunoHost-Apps/gitrepositories_ynh"
[gnusocial] [gnusocial]
added_date = 1554588215 # 2019/04/07
category = "social_media" category = "social_media"
killed_date = 1703600553 # 2023/12/26
potential_alternative_to = [ "X" ] potential_alternative_to = [ "X" ]
subtags = [ "microblogging" ] subtags = [ "microblogging" ]
url = "https://github.com/YunoHost-Apps/gnusocial_ynh" url = "https://github.com/YunoHost-Apps/gnusocial_ynh"
[gogswebhost] [gogswebhost]
added_date = 1590399842 # 2020/05/25
category = "publishing" category = "publishing"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/gogs_webhost_ynh" url = "https://github.com/YunoHost-Apps/gogs_webhost_ynh"
[internetarchive] [internetarchive]
added_date = 1569663577 # 2019/09/28
category = "wat" category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/internetarchive_ynh" url = "https://github.com/YunoHost-Apps/internetarchive_ynh"
[jappix_mini] [jappix_mini]
added_date = 1554588215 # 2019/04/07
category = "communication" category = "communication"
killed_date = 1703600553 # 2023/12/26
subtags = [ "chat" ] subtags = [ "chat" ]
url = "https://github.com/YunoHost-Apps/jappix_mini_ynh" url = "https://github.com/YunoHost-Apps/jappix_mini_ynh"
[lbcalerte] [lbcalerte]
added_date = 1554588215 # 2019/04/07
category = "small_utilities" category = "small_utilities"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/lbcalerte_ynh" url = "https://github.com/YunoHost-Apps/lbcalerte_ynh"
[lektor] [lektor]
added_date = 1554588215 # 2019/04/07
category = "publishing" category = "publishing"
killed_date = 1703600553 # 2023/12/26
subtags = [ "website" ] subtags = [ "website" ]
url = "https://github.com/YunoHost-Apps/lektor_ynh" url = "https://github.com/YunoHost-Apps/lektor_ynh"
[mailman] [mailman]
added_date = 1554588215 # 2019/04/07
category = "communication" category = "communication"
killed_date = 1703600553 # 2023/12/26
potential_alternative_to = [ "Google Groups" ] potential_alternative_to = [ "Google Groups" ]
subtags = [ "email" ] subtags = [ "email" ]
url = "https://github.com/yunohost-apps/mailman_ynh" url = "https://github.com/yunohost-apps/mailman_ynh"
[mediadrop] [mediadrop]
added_date = 1554588215 # 2019/04/07
category = "multimedia" category = "multimedia"
killed_date = 1703600553 # 2023/12/26
subtags = [ "mediacenter" ] subtags = [ "mediacenter" ]
url = "https://github.com/YunoHost-Apps/mediadrop_ynh" url = "https://github.com/YunoHost-Apps/mediadrop_ynh"
[menu] [menu]
added_date = 1554588215 # 2019/04/07
category = "wat" category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/menu_ynh" url = "https://github.com/YunoHost-Apps/menu_ynh"
[modernpaste] [modernpaste]
added_date = 1554588215 # 2019/04/07
category = "small_utilities" category = "small_utilities"
killed_date = 1703600553 # 2023/12/26
subtags = [ "pastebin" ] subtags = [ "pastebin" ]
url = "https://github.com/YunoHost-Apps/modernpaste_ynh" url = "https://github.com/YunoHost-Apps/modernpaste_ynh"
[monit] [monit]
added_date = 1554588215 # 2019/04/07
category = "system_tools" category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "monitoring" ] subtags = [ "monitoring" ]
url = "https://github.com/YunoHost-Apps/monit_ynh" url = "https://github.com/YunoHost-Apps/monit_ynh"
[multi_webapp] [multi_webapp]
added_date = 1554588215 # 2019/04/07
category = "publishing" category = "publishing"
killed_date = 1703600553 # 2023/12/26
subtags = [ "website" ] subtags = [ "website" ]
url = "https://github.com/YunoHost-Apps/multi_webapp_ynh" url = "https://github.com/YunoHost-Apps/multi_webapp_ynh"
[munin] [munin]
added_date = 1554588215 # 2019/04/07
category = "system_tools" category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "monitoring" ] subtags = [ "monitoring" ]
url = "https://github.com/YunoHost-Apps/munin_ynh" url = "https://github.com/YunoHost-Apps/munin_ynh"
[nexusoss] [nexusoss]
added_date = 1554588215 # 2019/04/07
category = "dev" category = "dev"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/nexusoss_ynh" url = "https://github.com/YunoHost-Apps/nexusoss_ynh"
[ntopng] [ntopng]
added_date = 1590399842 # 2020/05/25
category = "system_tools" category = "system_tools"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/ntopng_ynh" url = "https://github.com/YunoHost-Apps/ntopng_ynh"
[osmw] [osmw]
added_date = 1554588215 # 2019/04/07
category = "wat" category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/osmw_ynh" url = "https://github.com/YunoHost-Apps/osmw_ynh"
[peachpub] [peachpub]
added_date = 1655358480 # 2022/06/16
category = "communication" category = "communication"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/peachpub_ynh" url = "https://github.com/YunoHost-Apps/peachpub_ynh"
[piratebox] [piratebox]
added_date = 1554588215 # 2019/04/07
category = "system_tools" category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "network" ] subtags = [ "network" ]
url = "https://github.com/labriqueinternet/piratebox_ynh" url = "https://github.com/labriqueinternet/piratebox_ynh"
[plonecms] [plonecms]
added_date = 1554588215 # 2019/04/07
category = "publishing" category = "publishing"
killed_date = 1703600553 # 2023/12/26
subtags = [ "website" ] subtags = [ "website" ]
url = "https://github.com/YunoHost-Apps/plonecms_ynh" url = "https://github.com/YunoHost-Apps/plonecms_ynh"
[portainer] [portainer]
added_date = 1554588215 # 2019/04/07
category = "system_tools" category = "system_tools"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/portainer_ynh" 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] [reel2bits]
added_date = 1554588215 # 2019/04/07
category = "social_media" category = "social_media"
killed_date = 1703600553 # 2023/12/26
potential_alternative_to = [ "Soundcloud" ] potential_alternative_to = [ "Soundcloud" ]
subtags = [ "music" ] subtags = [ "music" ]
url = "https://github.com/YunoHost-Apps/reel2bits_ynh" url = "https://github.com/YunoHost-Apps/reel2bits_ynh"
[remotestorage] [remotestorage]
added_date = 1554588215 # 2019/04/07
category = "small_utilities" category = "small_utilities"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/remotestorage_ynh" url = "https://github.com/YunoHost-Apps/remotestorage_ynh"
[roadiz] [roadiz]
added_date = 1554588215 # 2019/04/07
category = "publishing" category = "publishing"
killed_date = 1703600553 # 2023/12/26
subtags = [ "website" ] subtags = [ "website" ]
url = "https://github.com/YunoHost-Apps/roadiz_ynh" url = "https://github.com/YunoHost-Apps/roadiz_ynh"
[shsd] [shsd]
added_date = 1554588215 # 2019/04/07
category = "system_tools" category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "monitoring" ] subtags = [ "monitoring" ]
url = "https://github.com/YunoHost-Apps/shsd_ynh" url = "https://github.com/YunoHost-Apps/shsd_ynh"
[sickbeard] [sickbeard]
added_date = 1554588215 # 2019/04/07
category = "multimedia" category = "multimedia"
killed_date = 1703600553 # 2023/12/26
subtags = [ "download" ] subtags = [ "download" ]
url = "https://github.com/YunoHost-Apps/sickbeard_ynh" url = "https://github.com/YunoHost-Apps/sickbeard_ynh"
[sickrage] [sickrage]
added_date = 1554588215 # 2019/04/07
category = "multimedia" category = "multimedia"
killed_date = 1703600553 # 2023/12/26
subtags = [ "download" ] subtags = [ "download" ]
url = "https://github.com/YunoHost-Apps/sickrage_ynh" url = "https://github.com/YunoHost-Apps/sickrage_ynh"
[sonerezh] [sonerezh]
added_date = 1554588215 # 2019/04/07
category = "multimedia" category = "multimedia"
killed_date = 1703600553 # 2023/12/26
subtags = [ "music" ] subtags = [ "music" ]
url = "https://github.com/YunoHost-Apps/sonerezh_ynh" url = "https://github.com/YunoHost-Apps/sonerezh_ynh"
[staticwebapp] [staticwebapp]
added_date = 1554588215 # 2019/04/07
category = "publishing" category = "publishing"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/staticwebapp_ynh" url = "https://github.com/YunoHost-Apps/staticwebapp_ynh"
[subscribe] [subscribe]
added_date = 1590399842 # 2020/05/25
category = "wat" category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/subscribe_ynh" url = "https://github.com/YunoHost-Apps/subscribe_ynh"
[tagspaces] [tagspaces]
added_date = 1554588215 # 2019/04/07
category = "synchronization" category = "synchronization"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/tagspaces_ynh" url = "https://github.com/YunoHost-Apps/tagspaces_ynh"
[telegram_chatbot] [telegram_chatbot]
added_date = 1554588215 # 2019/04/07
category = "dev" category = "dev"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/telegram_chatbot_ynh" url = "https://github.com/YunoHost-Apps/telegram_chatbot_ynh"
[tes3mp] [tes3mp]
added_date = 1554588215 # 2019/04/07
category = "games" category = "games"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/tes3mp_ynh" url = "https://github.com/YunoHost-Apps/tes3mp_ynh"
[transpay] [transpay]
added_date = 1571446958 # 2019/10/19
category = "productivity_and_management" category = "productivity_and_management"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/transpay_ynh" url = "https://github.com/YunoHost-Apps/transpay_ynh"
[unbound] [unbound]
added_date = 1590399842 # 2020/05/25
category = "system_tools" category = "system_tools"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/unbound_ynh" url = "https://github.com/YunoHost-Apps/unbound_ynh"
[vpnserver] [vpnserver]
added_date = 1564314757 # 2019/07/28
category = "system_tools" category = "system_tools"
killed_date = 1703600553 # 2023/12/26
subtags = [ "network" ] subtags = [ "network" ]
url = "https://github.com/YunoHost-Apps/vpnserver_ynh" url = "https://github.com/YunoHost-Apps/vpnserver_ynh"
[wildfly] [wildfly]
added_date = 1554588215 # 2019/04/07
category = "dev" category = "dev"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/wildfly_ynh" url = "https://github.com/YunoHost-Apps/wildfly_ynh"
[youtube-dl-webui] [youtube-dl-webui]
added_date = 1554588215 # 2019/04/07
category = "multimedia" category = "multimedia"
killed_date = 1703600553 # 2023/12/26
subtags = [ "download" ] subtags = [ "download" ]
url = "https://github.com/YunoHost-Apps/youtube-dl-webui_ynh" url = "https://github.com/YunoHost-Apps/youtube-dl-webui_ynh"
[yunofav] [yunofav]
added_date = 1554588215 # 2019/04/07
category = "wat" category = "wat"
killed_date = 1703600553 # 2023/12/26
url = "https://github.com/YunoHost-Apps/yunofav_ynh" 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": { "branch": {
"type": "string" "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", "$id": "https://raw.githubusercontent.com/YunoHost/apps/master/schemas/manifest.v2.schema.json",
"title": "Yunohost app manifest.toml schema", "title": "Yunohost app manifest.toml schema",
"version": "0", "version": "0",
"type": "object", "type": "object",
"$defs": { "$defs": {
"translated_string": { "translated_string": {
"anyOf": [ "anyOf": [
{ {
"type": "object", "type": "object",
"required": ["en"], "required": [
"en"
],
"additionalProperties": false, "additionalProperties": false,
"patternProperties": { "patternProperties": {
"^[a-z]{2}$": { "^[a-z]{2}$": {
@ -68,7 +69,6 @@
] ]
} }
}, },
"properties": { "properties": {
"packaging_format": { "packaging_format": {
"description": "Packaging format / version", "description": "Packaging format / version",
@ -87,7 +87,9 @@
"type": "string", "type": "string",
"pattern": "^[0-9a-z]*([\\.+-][0-9a-z]*)*~ynh[0-9]*$" "pattern": "^[0-9a-z]*([\\.+-][0-9a-z]*)*~ynh[0-9]*$"
}, },
"description": {"$ref": "#/$defs/translated_string"}, "description": {
"$ref": "#/$defs/translated_string"
},
"maintainers": { "maintainers": {
"description": "List of maintainers", "description": "List of maintainers",
"type": "array", "type": "array",
@ -97,22 +99,52 @@
}, },
"upstream": { "upstream": {
"type": "object", "type": "object",
"required": ["license"], "required": [
"license"
],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"license": {"type": "string"}, "license": {
"website": {"type": "string", "format": "uri-reference"}, "type": "string"
"demo": {"type": "string", "format": "uri-reference"}, },
"admindoc": {"type": "string", "format": "uri-reference"}, "website": {
"userdoc": {"type": "string", "format": "uri-reference"}, "type": "string",
"code": {"type": "string", "format": "uri-reference"}, "format": "uri-reference"
"fund": {"type": "string", "format": "uri-reference"}, },
"cpe": {"$ref": "#/$defs/cpe_id"} "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": { "integration": {
"type": "object", "type": "object",
"required": ["yunohost", "architectures", "multi_instance", "ldap", "sso"], "required": [
"yunohost",
"architectures",
"multi_instance",
"ldap",
"sso"
],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"yunohost": { "yunohost": {
@ -129,22 +161,39 @@
"type": "array", "type": "array",
"items": { "items": {
"type": "string", "type": "string",
"enum": ["amd64", "i386", "armhf", "arm64"] "enum": [
"amd64",
"i386",
"armhf",
"arm64"
]
} }
} }
] ]
}, },
"multi_instance": {"$ref": "#/$defs/boolean_or_not_relevant"}, "multi_instance": {
"ldap": {"$ref": "#/$defs/boolean_or_not_relevant"}, "$ref": "#/$defs/boolean_or_not_relevant"
"sso": {"$ref": "#/$defs/boolean_or_not_relevant"}, },
"disk": {"$ref": "#/$defs/byte_size"}, "ldap": {
"$ref": "#/$defs/boolean_or_not_relevant"
},
"sso": {
"$ref": "#/$defs/boolean_or_not_relevant"
},
"disk": {
"$ref": "#/$defs/byte_size"
},
"ram": { "ram": {
"type": "object", "type": "object",
"required": [], "required": [],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"build": {"$ref": "#/$defs/byte_size"}, "build": {
"runtime": {"$ref": "#/$defs/byte_size"} "$ref": "#/$defs/byte_size"
},
"runtime": {
"$ref": "#/$defs/byte_size"
}
} }
} }
} }
@ -154,7 +203,9 @@
"required": [], "required": [],
"additionalProperties": false, "additionalProperties": false,
"patternProperties": { "patternProperties": {
"^[a-zA-Z0-9_-]*$": {"$ref": "#/$defs/translated_string"} "^[a-zA-Z0-9_-]*$": {
"$ref": "#/$defs/translated_string"
}
} }
}, },
"install": { "install": {
@ -164,22 +215,60 @@
"patternProperties": { "patternProperties": {
"^[a-z][a-z0-9_]*$": { "^[a-z][a-z0-9_]*$": {
"type": "object", "type": "object",
"required": ["type"], "required": [
"type"
],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"type": { "type": {
"type": "string", "type": "string",
"enum": [ "enum": [
"string", "text", "select", "tags", "email", "url", "date", "time", "string",
"color", "password", "path", "boolean", "domain", "user", "group", "text",
"number", "range", "alert", "markdown", "file", "app" "select",
"tags",
"email",
"url",
"date",
"time",
"color",
"password",
"path",
"boolean",
"domain",
"user",
"group",
"number",
"range",
"alert",
"markdown",
"file",
"app"
] ]
}, },
"default": {"type": ["string", "number", "boolean"]}, "default": {
"example": {"type": ["string", "number", "boolean"]}, "type": [
"optional": {"type": "boolean"}, "string",
"ask": {"$ref": "#/$defs/translated_string"}, "number",
"help": {"$ref": "#/$defs/translated_string"}, "boolean"
]
},
"example": {
"type": [
"string",
"number",
"boolean"
]
},
"optional": {
"type": "boolean"
},
"ask": {
"$ref": "#/$defs/translated_string"
},
"help": {
"$ref": "#/$defs/translated_string"
},
"choices": { "choices": {
"anyOf": [ "anyOf": [
{ {
@ -228,7 +317,9 @@
"required": [], "required": [],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"packages": {"$ref": "#/$defs/string_or_array_of"}, "packages": {
"$ref": "#/$defs/string_or_array_of"
},
"packages_from_raw_bash": { "packages_from_raw_bash": {
"type": "string" "type": "string"
}, },
@ -237,7 +328,10 @@
"patternProperties": { "patternProperties": {
"^.[a-z][a-z0-9_]*$": { "^.[a-z][a-z0-9_]*$": {
"type": "object", "type": "object",
"required": ["repo", "packages"], "required": [
"repo",
"packages"
],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"repo": { "repo": {
@ -246,7 +340,9 @@
"key": { "key": {
"type": "string" "type": "string"
}, },
"packages": {"$ref": "#/$defs/string_or_array_of"} "packages": {
"$ref": "#/$defs/string_or_array_of"
}
} }
} }
} }
@ -258,25 +354,36 @@
"required": [], "required": [],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"dir": {"$ref": "#/$defs/path_absolute"}, "dir": {
"$ref": "#/$defs/path_absolute"
},
"subdirs": { "subdirs": {
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"owner": {"$ref": "#/$defs/name_and_permission"}, "owner": {
"group": {"$ref": "#/$defs/name_and_permission"} "$ref": "#/$defs/name_and_permission"
},
"group": {
"$ref": "#/$defs/name_and_permission"
}
} }
}, },
"database": { "database": {
"type": "object", "type": "object",
"required": ["type"], "required": [
"type"
],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"type": { "type": {
"type": "string", "type": "string",
"enum": ["mysql", "postgresql"] "enum": [
"mysql",
"postgresql"
]
} }
} }
}, },
@ -285,9 +392,15 @@
"required": [], "required": [],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"dir": {"$ref": "#/$defs/path_absolute"}, "dir": {
"owner": {"$ref": "#/$defs/name_and_permission"}, "$ref": "#/$defs/path_absolute"
"group": {"$ref": "#/$defs/name_and_permission"} },
"owner": {
"$ref": "#/$defs/name_and_permission"
},
"group": {
"$ref": "#/$defs/name_and_permission"
}
} }
}, },
"permissions": { "permissions": {
@ -300,7 +413,10 @@
"required": [], "required": [],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"url": {"$ref": "#/$defs/path_absolute"}, "url": {
"type": "string",
"pattern": "^((re:.*)?|(__[A-Z_]*__)?\/.*)$"
},
"show_tile": { "show_tile": {
"type": "boolean" "type": "boolean"
}, },
@ -315,7 +431,9 @@
}, },
"additional_urls": { "additional_urls": {
"type": "array", "type": "array",
"items": {"$ref": "#/$defs/path_absolute"} "items": {
"$ref": "#/$defs/path_absolute"
}
}, },
"label": { "label": {
"type": "string" "type": "string"
@ -344,7 +462,11 @@
}, },
{ {
"type": "string", "type": "string",
"enum": ["TCP", "UDP", "Both"] "enum": [
"TCP",
"UDP",
"Both"
]
} }
] ]
}, },
@ -369,7 +491,9 @@
"type": "string", "type": "string",
"format": "uri" "format": "uri"
}, },
"sha256": {"$ref": "#/$defs/sha256sum"}, "sha256": {
"$ref": "#/$defs/sha256sum"
},
"in_subdir": { "in_subdir": {
"anyOf": [ "anyOf": [
{ {
@ -451,6 +575,14 @@
}, },
"force_version": { "force_version": {
"type": "string" "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", "type": "string",
"format": "uri" "format": "uri"
}, },
"sha256": {"$ref": "#/$defs/sha256sum"} "sha256": {
"$ref": "#/$defs/sha256sum"
}
} }
} }
} }
@ -486,12 +620,13 @@
"allow_email": { "allow_email": {
"type": "boolean" "type": "boolean"
}, },
"home": {"$ref": "#/$defs/path_absolute"} "home": {
"$ref": "#/$defs/path_absolute"
}
} }
} }
} }
} }
}, },
"required": [ "required": [
"packaging_format", "packaging_format",

View file

@ -3,14 +3,16 @@
"$id": "https://github.com/YunoHost/apps/blob/master/schemas/wishlist.toml.schema.json", "$id": "https://github.com/YunoHost/apps/blob/master/schemas/wishlist.toml.schema.json",
"title": "Yunohost's wishlist.toml schema", "title": "Yunohost's wishlist.toml schema",
"version": "0", "version": "0",
"type": "object", "type": "object",
"required": [], "required": [],
"additionalProperties": false, "additionalProperties": false,
"patternProperties": { "patternProperties": {
"^[a-z0-9_-]*$": { "^[a-z0-9_-]*$": {
"type": "object", "type": "object",
"required": ["name", "upstream"], "required": [
"name",
"upstream"
],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"name": { "name": {
@ -26,9 +28,15 @@
"website": { "website": {
"type": "string", "type": "string",
"format": "url" "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 config.toml
.stars .stars
.wishlist_ratelimit
assets/fork-awesome.* .cache
assets/forkawesome-webfont.* .tmp
assets/tailwind.css assets/*
assets/tailwindcss-linux-x64
assets/ynh_logo_*

View file

@ -31,18 +31,21 @@ And then start the dev server:
```bash ```bash
source venv/bin/activate 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 ## 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 ```bash
source venv/bin/activate source venv/bin/activate
# Extract the english sentences from the code, needed if you modified it # 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) # If working on a new locale: initialize it (in this example: fr)
pybabel init -i messages.pot -d translations -l 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 re
import time
import json
import toml import toml
import tomlkit
import base64 import base64
import hashlib import hashlib
import hmac import hmac
import os
import string import string
import random import random
import urllib import urllib
import json from datetime import datetime
import sys
from slugify import slugify from slugify import slugify
from flask import ( from flask import (
Flask, Flask,
@ -18,6 +20,7 @@ from flask import (
session, session,
redirect, redirect,
request, request,
make_response,
) )
from flask_babel import Babel from flask_babel import Babel
from flask_babel import gettext as _ from flask_babel import gettext as _
@ -30,6 +33,7 @@ from utils import (
get_catalog, get_catalog,
get_wishlist, get_wishlist,
get_stars, get_stars,
get_dashboard_data,
get_app_md_and_screenshots, get_app_md_and_screenshots,
save_wishlist_submit_for_ratelimit, save_wishlist_submit_for_ratelimit,
check_wishlist_submit_ratelimit, check_wishlist_submit_ratelimit,
@ -61,9 +65,7 @@ for key in mandatory_config_keys:
print(f"Missing key in config.toml: {key}") print(f"Missing key in config.toml: {key}")
sys.exit(1) sys.exit(1)
if config.get("DEBUG"): if app.config.get("DEBUG"):
app.debug = True
app.config["DEBUG"] = True
app.config["TEMPLATES_AUTO_RELOAD"] = True app.config["TEMPLATES_AUTO_RELOAD"] = True
# This is the secret key used for session signing # This is the secret key used for session signing
@ -84,6 +86,39 @@ def localize(d):
return d["en"] 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(): def index():
return render_template( return render_template(
"index.html", "index.html",
locale=get_locale(),
user=session.get("user", {}),
catalog=get_catalog(), catalog=get_catalog(),
) )
@ -106,12 +139,10 @@ def index():
def browse_catalog(): def browse_catalog():
return render_template( return render_template(
"catalog.html", "catalog.html",
locale=get_locale(),
init_sort=request.args.get("sort"), init_sort=request.args.get("sort"),
init_search=request.args.get("search"), init_search=request.args.get("search"),
init_category=request.args.get("category"), init_category=request.args.get("category"),
init_starsonly=request.args.get("starsonly"), init_starsonly=request.args.get("starsonly"),
user=session.get("user", {}),
catalog=get_catalog(), catalog=get_catalog(),
timestamp_now=int(time.time()), timestamp_now=int(time.time()),
stars=get_stars(), stars=get_stars(),
@ -134,8 +165,6 @@ def app_info(app_id):
return render_template( return render_template(
"app.html", "app.html",
locale=get_locale(),
user=session.get("user", {}),
app_id=app_id, app_id=app_id,
infos=infos, infos=infos,
catalog=get_catalog(), catalog=get_catalog(),
@ -147,9 +176,16 @@ def app_info(app_id):
def star_app(app_id, action): def star_app(app_id, action):
assert action in ["star", "unstar"] assert action in ["star", "unstar"]
if app_id not in get_catalog()["apps"] and app_id not in get_wishlist(): 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", {}): 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_folder = os.path.join(".stars", app_id)
app_star_for_this_user = os.path.join( app_star_for_this_user = os.path.join(
@ -177,11 +213,6 @@ def star_app(app_id, action):
def browse_wishlist(): def browse_wishlist():
return render_template( return render_template(
"wishlist.html", "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(), wishlist=get_wishlist(),
stars=get_stars(), stars=get_stars(),
) )
@ -192,11 +223,15 @@ def add_to_wishlist():
if request.method == "POST": if request.method == "POST":
user = session.get("user", {}) user = session.get("user", {})
if not 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( return render_template(
"wishlist_add.html", "wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=None, csrf_token=None,
successmsg=None, successmsg=None,
errormsg=errormsg, errormsg=errormsg,
@ -207,8 +242,6 @@ def add_to_wishlist():
errormsg = _("Invalid CSRF token, please refresh the page and try again") errormsg = _("Invalid CSRF token, please refresh the page and try again")
return render_template( return render_template(
"wishlist_add.html", "wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=csrf_token, csrf_token=csrf_token,
successmsg=None, successmsg=None,
errormsg=errormsg, errormsg=errormsg,
@ -220,12 +253,33 @@ def add_to_wishlist():
website = request.form["website"].strip().replace("\n", "") website = request.form["website"].strip().replace("\n", "")
license = request.form["license"].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 = [ checks = [
( (
check_wishlist_submit_ratelimit(session['user']['username']) is True and session['user']['bypass_ratelimit'] is False, check_wishlist_submit_ratelimit(session["user"]["username"]) is True
_("Proposing wishlist additions is limited to once every 15 days per user. Please try again in a few days.") 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) >= 3, _("App name should be at least 3 characters")),
(len(name) <= 30, _("App name should be less than 30 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"), _("App name contains special characters"),
), ),
( (
all(keyword not in description.lower() for keyword in boring_keywords_to_check_for_people_not_reading_the_instructions), all(
_("Please focus on what the app does, without using marketing, fuzzy terms, or repeating that the app is 'free' and 'self-hostable'.") 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"]), description.lower().split()[0] != name
_("No need to repeat the name of the app. Focus on what the app does.") 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: for check, errormsg in checks:
if not check: if not check:
return render_template( return render_template(
"wishlist_add.html", "wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=csrf_token, csrf_token=csrf_token,
successmsg=None, successmsg=None,
errormsg=errormsg, errormsg=errormsg,
@ -288,19 +349,33 @@ def add_to_wishlist():
) )
current_wishlist_sha = current_wishlist_rawtoml.sha current_wishlist_sha = current_wishlist_rawtoml.sha
current_wishlist_rawtoml = current_wishlist_rawtoml.decoded_content.decode() 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: if slug in new_wishlist:
url = f"https://apps.yunohost.org/wishlist?search={slug}" url = f"https://apps.yunohost.org/wishlist?search={slug}"
return render_template( return render_template(
"wishlist_add.html", "wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=csrf_token, csrf_token=csrf_token,
successmsg=None, successmsg=None,
errormsg=_( 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>.", "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 = 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}" new_branch = f"add-to-wishlist-{slug}"
try: try:
# Get the commit base for the new branch, and create it # Get the commit base for the new branch, and create it
commit_sha = repo.get_branch(repo.default_branch).commit.sha commit_sha = repo.get_branch(repo.default_branch).commit.sha
repo.create_git_ref(ref=f"refs/heads/{new_branch}", sha=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("… Failed to create branch ?")
print(e) 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 = _( 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.", "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( return render_template(
"wishlist_add.html", "wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=csrf_token, csrf_token=csrf_token,
successmsg=None, successmsg=None,
errormsg=errormsg, errormsg=errormsg,
@ -370,6 +443,7 @@ Description: {description}
head=new_branch, head=new_branch,
base=repo.default_branch, base=repo.default_branch,
) )
pr.add_to_labels("Wishlist")
url = f"https://github.com/YunoHost/apps/pull/{pr.number}" url = f"https://github.com/YunoHost/apps/pull/{pr.number}"
@ -378,12 +452,10 @@ Description: {description}
url=url, url=url,
) )
save_wishlist_submit_for_ratelimit(session['user']['username']) save_wishlist_submit_for_ratelimit(session["user"]["username"])
return render_template( return render_template(
"wishlist_add.html", "wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
successmsg=successmsg, successmsg=successmsg,
) )
else: else:
@ -392,14 +464,125 @@ Description: {description}
session["csrf_token"] = csrf_token session["csrf_token"] = csrf_token
return render_template( return render_template(
"wishlist_add.html", "wishlist_add.html",
locale=get_locale(),
user=session.get("user", {}),
csrf_token=csrf_token, csrf_token=csrf_token,
successmsg=None, successmsg=None,
errormsg=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 # # Session / SSO using Discourse #
############################################################################### ###############################################################################
@ -427,7 +610,6 @@ def login_using_discourse():
@app.route("/sso_login_callback") @app.route("/sso_login_callback")
def sso_login_callback(): def sso_login_callback():
computed_sig = hmac.new( computed_sig = hmac.new(
config["DISCOURSE_SSO_SECRET"].encode(), config["DISCOURSE_SSO_SECRET"].encode(),
msg=request.args["sso"].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") 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(','): 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 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 bypass_ratelimit = True
else: else:
bypass_ratelimit = False bypass_ratelimit = False
@ -467,6 +656,22 @@ def sso_login_callback():
return redirect("/") 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") @app.route("/logout")
def logout(): def logout():
session.clear() 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 chmod +x tailwindcss-linux-x64
./tailwindcss-linux-x64 --input tailwind-local.css --output tailwind.css --minify ./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 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 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.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.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 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/logo_roundcorner.png > ynh_logo_roundcorner.png
curl https://raw.githubusercontent.com/YunoHost/doc/master/images/ynh_logo_black.svg > ynh_logo_black.svg 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; @tailwind utilities;
@layer utilities { @layer utilities {
input, textarea, select {
@apply !rounded-md shadow-sm !border-gray-200 !bg-neutral-50;
}
.btn { .btn {
@apply text-sm font-medium rounded-md px-4 py-2 transition; @apply text-sm font-medium rounded-md px-4 py-2 transition;
} }

View file

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

View file

@ -1,5 +1,7 @@
COOKIE_SECRET = "abcdefghijklmnopqrstuvwxyz1234567890" 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_SECRET = "abcdefghijklmnopqrstuvwxyz1234567890"
DISCOURSE_SSO_ENDPOINT = "https://forum.yunohost.org/session/sso_provider" DISCOURSE_SSO_ENDPOINT = "https://forum.yunohost.org/session/sso_provider"
CALLBACK_URL_AFTER_LOGIN_ON_DISCOURSE = "http://localhost:5000/sso_login_callback" 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 import os
install_dir = os.path.dirname(__file__) install_dir = os.path.dirname(__file__)
command = f'{install_dir}/venv/bin/gunicorn' command = f"{install_dir}/venv/bin/gunicorn"
pythonpath = install_dir pythonpath = install_dir
workers = 4 workers = 4
user = 'appstore' user = "appstore"
bind = f'unix:{install_dir}/sock' bind = f"unix:{install_dir}/sock"
pid = '/run/gunicorn/appstore-pid' pid = "/run/gunicorn/appstore-pid"
errorlog = '/var/log/appstore/error.log' errorlog = "/var/log/appstore/error.log"
accesslog = '/var/log/appstore/access.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"' 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 capture_output = True

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,15 +17,16 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:150 #: app.py:162
msgid "App %(app_id) not found" #, python-format
msgid "App %(app_id)s not found"
msgstr "" msgstr ""
#: app.py:152 #: app.py:165
msgid "You must be logged in to be able to star an app" msgid "You must be logged in to be able to star an app"
msgstr "" 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 "" msgid ""
"Note that, due to various abuses, we restricted login on the app store to" "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 " " 'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -34,71 +35,71 @@ msgid ""
"minutes reading posts." "minutes reading posts."
msgstr "" msgstr ""
#: app.py:195 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" msgid "You must be logged in to submit an app to the wishlist"
msgstr "" msgstr ""
#: app.py:207 #: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr ""
#: app.py:228 #: app.py:263
msgid "" msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. " "Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days." "Please try again in a few days."
msgstr "" msgstr ""
#: app.py:230 #: app.py:267
msgid "App name should be at least 3 characters" msgid "App name should be at least 3 characters"
msgstr "" msgstr ""
#: app.py:231 #: app.py:268
msgid "App name should be less than 30 characters" msgid "App name should be less than 30 characters"
msgstr "" msgstr ""
#: app.py:234 #: app.py:271
msgid "App description should be at least 5 characters" msgid "App description should be at least 5 characters"
msgstr "" msgstr ""
#: app.py:238 #: app.py:275
msgid "App description should be less than 100 characters" msgid "App description should be less than 100 characters"
msgstr "" msgstr ""
#: app.py:242 #: app.py:279
msgid "Upstream code repo URL should be at least 10 characters" msgid "Upstream code repo URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:246 #: app.py:283
msgid "Upstream code repo URL should be less than 150 characters" msgid "Upstream code repo URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:250 #: app.py:287
msgid "License URL should be at least 10 characters" msgid "License URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:254 #: app.py:291
msgid "License URL should be less than 250 characters" msgid "License URL should be less than 250 characters"
msgstr "" msgstr ""
#: app.py:256 #: app.py:293
msgid "Website URL should be less than 150 characters" msgid "Website URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:259 #: app.py:296
msgid "App name contains special characters" msgid "App name contains special characters"
msgstr "" msgstr ""
#: app.py:263 #: app.py:303
msgid "" msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, " "Please focus on what the app does, without using marketing, fuzzy terms, "
"or repeating that the app is 'free' and 'self-hostable'." "or repeating that the app is 'free' and 'self-hostable'."
msgstr "" msgstr ""
#: app.py:267 #: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does." msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr "" msgstr ""
#: app.py:301 #: app.py:343
#, python-format #, python-format
msgid "" msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, " "An entry with the name %(slug)s already exists in the wishlist, instead, "
@ -106,7 +107,14 @@ msgid ""
"interest</a>." "interest</a>."
msgstr "" 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 #, python-format
msgid "" msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe " "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." "please report the issue to the YunoHost team."
msgstr "" msgstr ""
#: app.py:376 #: app.py:433
#, python-format #, python-format
msgid "" msgid ""
"Your proposed app has succesfully been submitted. It must now be " "Your proposed app has succesfully been submitted. It must now be "
@ -122,7 +130,7 @@ msgid ""
"href='%(url)s'>%(url)s</a>" "href='%(url)s'>%(url)s</a>"
msgstr "" msgstr ""
#: app.py:449 #: app.py:528
msgid "Unfortunately, login was denied." msgid "Unfortunately, login was denied."
msgstr "" msgstr ""
@ -194,7 +202,7 @@ msgid "Important infos before installing"
msgstr "" msgstr ""
#: templates/app.html:124 #: templates/app.html:124
msgid "Anti-features" msgid "Antifeatures"
msgstr "" msgstr ""
#: templates/app.html:125 #: templates/app.html:125
@ -234,47 +242,65 @@ msgstr ""
msgid "YunoHost package license" msgid "YunoHost package license"
msgstr "" msgstr ""
#: templates/base.html:5 #: templates/base.html:11
msgid "YunoHost app store" msgid "YunoHost app store"
msgstr "" 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" msgid "Home"
msgstr "" msgstr ""
#: templates/base.html:27 templates/base.html:122 #: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog" msgid "Catalog"
msgstr "" msgstr ""
#: templates/base.html:33 templates/base.html:131 #: templates/base.html:46 templates/base.html:172
msgid "Wishlist" msgid "Wishlist"
msgstr "" 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" msgid "YunoHost documentation"
msgstr "" msgstr ""
#: templates/base.html:54 templates/base.html:151 #: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum" msgid "Login using YunoHost's forum"
msgstr "" 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" msgid "Logout"
msgstr "" msgstr ""
#: templates/base.html:99 #: templates/base.html:140
msgid "Toggle menu" msgid "Toggle menu"
msgstr "" msgstr ""
#: templates/base.html:197 #: templates/base.html:255
msgid "" msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> " "Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> "
"using <a class='text-blue-800' " "using <a class='text-blue-800' "
"href='https://flask.palletsprojects.com'>Flask</a> and <a class='text-" "href='https://flask.palletsprojects.com'>Flask</a> and <a class='text-"
"blue-800' href='https://tailwindcss.com/'>TailwindCSS</a> - <a class" "blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>"
"='text-blue-800' " msgstr ""
"href='https://github.com/YunoHost/apps/tree/master/store'><i class='fa "
"fa-code fa-fw' aria-hidden='true'></i> Source</a>" #: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr "" msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80 #: templates/catalog.html:75 templates/catalog.html:80
@ -293,7 +319,7 @@ msgstr ""
msgid "All apps" msgid "All apps"
msgstr "" msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39 #: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by" msgid "Sort by"
msgstr "" msgstr ""
@ -306,16 +332,16 @@ msgstr ""
msgid "Newest" msgid "Newest"
msgstr "" msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46 #: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical" msgid "Alphabetical"
msgstr "" 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" msgid "Requires to be logged-in"
msgstr "" msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139 #: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/wishlist.html:51 templates/wishlist.html:60 #: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred" msgid "Show only apps you starred"
msgstr "" msgstr ""
@ -353,6 +379,204 @@ msgid ""
"advise against their installation and advise users to find alternatives." "advise against their installation and advise users to find alternatives."
msgstr "" 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 #: templates/index.html:10
msgid "Application Store" msgid "Application Store"
msgstr "" msgstr ""
@ -361,44 +585,10 @@ msgstr ""
msgid "Browse all applications" msgid "Browse all applications"
msgstr "" 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 #: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app" msgid "Suggest an app"
msgstr "" 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 #: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog" msgid "Suggest an application to be added to YunoHost's catalog"
msgstr "" msgstr ""
@ -417,6 +607,10 @@ msgid ""
"send every random nerdy stuff you find on the Internet." "send every random nerdy stuff you find on the Internet."
msgstr "" msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64 #: templates/wishlist_add.html:64
msgid "App's description" msgid "App's description"
msgstr "" msgstr ""
@ -461,3 +655,33 @@ msgstr ""
msgid "Submit" msgid "Submit"
msgstr "" 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 Babel==2.14.0
python-slugify blinker==1.8.1
PyGithub certifi==2024.2.2
toml cffi==1.16.0
pycmarkgfm charset-normalizer==3.3.2
gunicorn click==8.1.7
emoji cryptography==42.0.5
Babel Deprecated==1.2.14
Flask-Babel 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" 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-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'] %} {% 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 "> <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> <span class="inline sm:hidden">{{ _("Demo") }}</span>
</a> </a>
{% endif %} {% 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 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> <span class="inline-block pr-2 pt-1"><img alt="YunoHost" src="{{ url_for('static', filename='horizontal-yunohost.svg') }}"></span>
</a> </a>
@ -121,7 +121,7 @@
{% endif %} {% endif %}
{% if infos["antifeatures"] %} {% 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> <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"> <div class="my-3 rounded-md bg-red-100 text-red-800 px-5 py-2">
<ul> <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> <!DOCTYPE html>
<html lang="{{ locale }}"> <html lang="{{ locale }}">
@ -7,9 +13,16 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <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='fork-awesome.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='tailwind.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> </head>
<body> <body class="bg-neutral-50 text-gray-800">
<header class="pb-2 shadow-sm"> <header class="pb-2 shadow-sm">
<div <div
class="flex h-12 items-center gap-8 pt-2 px-4 sm:px-6 lg:px-8" 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"> <nav class="hidden md:block">
<ul class="flex items-center gap-6 text-sm"> <ul class="flex items-center gap-6 text-sm">
<li> <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") }} {{ _("Catalog") }}
</a> </a>
</li> </li>
<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") }} {{ _("Wishlist") }}
</a> </a>
</li> </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> </ul>
</nav> </nav>
@ -45,6 +70,15 @@
<i class="fa fa-external-link fa-fw" aria-hidden="true"></i> <i class="fa fa-external-link fa-fw" aria-hidden="true"></i>
{{ _("YunoHost documentation") }} {{ _("YunoHost documentation") }}
</a> </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 %} {% if not user %}
<a <a
class="btn btn-primary inline-block" class="btn btn-primary inline-block"
@ -78,9 +112,25 @@
role="menu" role="menu"
> >
<div class="p-2"> <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 <a
href="/logout" 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" role="menuitem"
> >
{{ _("Logout") }} {{ _("Logout") }}
@ -101,7 +151,7 @@
</button> </button>
<div <div
id="menu" 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" role="menu"
> >
<div class="px-2 py-0.5"> <div class="px-2 py-0.5">
@ -171,6 +221,23 @@
</span> </span>
</div> </div>
<div class="px-2 py-0.5"> <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 <a
href="/logout" href="/logout"
class="block rounded-md px-4 py-3 text-sm hover:bg-gray-100" class="block rounded-md px-4 py-3 text-sm hover:bg-gray-100"
@ -187,19 +254,32 @@
</div> </div>
</header> </header>
<main> <main class="mx-auto max-w-screen-lg">
{% block main %} {% block main %}
{% endblock %} {% endblock %}
</main> </main>
<footer class="h-5 my-5 text-center"> <footer class="h-5 my-5 text-center">
<p> <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>") }} {{ _("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> </p>
</footer> </footer>
</body> </body>
<script type="text/javascript"> <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 %} {% if user %}
document.getElementById('toggleUserMenu').addEventListener('click', () => { document.getElementById('toggleUserMenu').addEventListener('click', () => {
document.getElementById('userMenu').classList.toggle("hidden"); document.getElementById('userMenu').classList.toggle("hidden");
@ -209,5 +289,4 @@
document.getElementById('menu').classList.toggle("hidden"); document.getElementById('menu').classList.toggle("hidden");
}); });
</script> </script>
</html> </html>

View file

@ -16,7 +16,7 @@
> >
<a <a
href="{{ url_for('app_info', app_id=app) }}" 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="flex justify-between gap-4">
<div class="shrink-0"> <div class="shrink-0">
@ -27,12 +27,12 @@
src="{{ url_for('static', filename='app_logo_placeholder.png') }}" src="{{ url_for('static', filename='app_logo_placeholder.png') }}"
{% endif %} {% endif %}
loading="lazy" 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>
<div class="w-full"> <div class="w-full">
<span class="flex"> <span class="flex">
<h3 class="grow text-md font-bold text-gray-900"> <h3 class="grow text-md font-bold">
{{ infos['manifest']['name'] }} {{ infos['manifest']['name'] }}
</h3> </h3>
<span class="text-xs"> <span class="text-xs">
@ -53,14 +53,16 @@
</span> </span>
</span> </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 }} {{ infos['manifest']['description']|localize }}
</p> </p>
<div class="hidden"> <div class="hidden">
{{ infos["potential_alternative_to"]|join(', ') }} {{ infos["potential_alternative_to"]|join(', ') }}
</div> </div>
{% if infos['category'] %} {% 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 }} {{ catalog['categories'][infos['category']]['title']|localize|lower }}
</span> </span>
{% endif %} {% endif %}
@ -76,7 +78,7 @@
{% endblock %} {% endblock %}
{% block main %} {% block main %}
<div class="mt-5 text-center"> <div class="mt-5 text-center">
<h1 class="text-2xl font-bold text-gray-900"> <h1 class="text-2xl font-bold">
{{ _("Application Catalog") }} {{ _("Application Catalog") }}
</h1> </h1>
</div> </div>
@ -89,8 +91,8 @@
type="text" type="text"
id="search" id="search"
placeholder="{{ _('Search for…') }}" placeholder="{{ _('Search for…') }}"
{% if init_search %}value="{{ init_search }}"{% endif %} {% if request.args.get("search") %}value="{{ request.args.get("search") }}"{% endif %}
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">
@ -102,11 +104,11 @@
<select <select
name="selectcategory" name="selectcategory"
id="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> <option value="">{{ _("All apps") }}</option>
{% for id, category in catalog['categories'].items() %} {% 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 %} {% endfor %}
</select> </select>
</div> </div>
@ -118,17 +120,17 @@
<select <select
name="selectsort" name="selectsort"
id="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 request.args.get("sort") in [None, "popularity"] %}selected{% endif %} value="popularity">{{ _("Popularity") }}</option>
<option {% if init_sort == "newest" %}selected{% endif %} value="newest">{{ _("Newest") }}</option> <option {% if request.args.get("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") == "alpha" %}selected{% endif %} value="alpha">{{ _("Alphabetical") }}</option>
</select> </select>
</div> </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"> <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> <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 class="absolute inset-0 rounded-full bg-gray-300 transition peer-checked:bg-green-500">
</span> </span>
@ -151,10 +153,10 @@
<div id="noResultFound" class="text-center pt-5 hidden"> <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.") }} {{ _("No results found.") }}
</p> </p>
<p class="text-md text-gray-900"> <p class="text-md">
{{ _("Not finding what you are looking for?") }}<br/> {{ _("Not finding what you are looking for?") }}<br/>
{{ _("Checkout the wishlist!") }} {{ _("Checkout the wishlist!") }}
</p> </p>
@ -162,7 +164,7 @@
<div id="lowQualityAppTitle" class="text-center pt-10 mx-4 md:mx-0"> <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") }} {{ _("Applications currently flagged as broken") }}
</h2> </h2>
<p class="text-sm"> <p class="text-sm">
@ -180,7 +182,7 @@
</div> </div>
<div id="deprecatedAppTitle" class="text-center pt-10 mx-4 md:mx-0"> <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") }} {{ _("Deprecated applications") }}
</h2> </h2>
<p class="text-sm"> <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 %} {% block main %}
<div class="mx-auto w-full text-center p-8"> <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"> <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 text-gray-900"> <h1 class="text-2xl font-bold">
{{ _("Application Store") }} {{ _("Application Store") }}
</h1> </h1>
</div> </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="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 <a
href="{{ url_for('browse_catalog') }}" href="{{ url_for('browse_catalog') }}"
class="h-full relative block overflow-hidden hover:bg-gray-200 pt-12" 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") }} {{ _("Browse all applications") }}
</h2> </h2>
</a> </a>
</div> </div>
{% for id, category in catalog['categories'].items() %} {% 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 <a
href="{{ url_for('browse_catalog', category=id) }}" href="{{ url_for('browse_catalog', category=id) }}"
class="h-full relative block overflow-hidden hover:bg-gray-200 pt-10" 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> <i class="fa fa-{{ category['icon'] }}" aria-hidden="true"></i>
{{ category['title']|localize }} {{ category['title']|localize }}
</h2> </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 }} {{ category['description']|localize }}
</p> </p>
</a> </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 %} {% endblock %}
{% block main %} {% block main %}
<div class="text-center max-w-screen-md mx-auto mt-5 mx-2"> <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") }} {{ _("Application Wishlist") }}
</h1> </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>
<div class="max-w-screen-md mx-auto mt-3 mb-3"> <div class="max-w-screen-md mx-auto mt-3 mb-3">
<div class="flex flex-col md:flex-row items-center"> <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> <label for="search" class="sr-only"> {{ _("Search") }} </label>
<input <input
type="text" type="text"
id="search" id="search"
placeholder="{{ _('Search for…') }}" 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> <i class="fa fa-search" aria-hidden="true"></i>
</span> </span>
</div> </div>
@ -40,16 +40,16 @@
<select <select
name="selectsort" name="selectsort"
id="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 request.args.get("sort") in [None, "popularity"] %}selected{% endif %} value="popularity">{{ _("Popularity") }}</option>
<option {% if init_sort == "alpha" %}selected{% endif %} value="alpha">{{ _("Alphabetical") }}</option> <option {% if request.args.get("sort") == "alpha" %}selected{% endif %} value="alpha">{{ _("Alphabetical") }}</option>
</select> </select>
</div> </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"> <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> <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 class="absolute inset-0 rounded-full bg-gray-300 transition peer-checked:bg-green-500">
</span> </span>
@ -64,22 +64,22 @@
</div> </div>
<div class="overflow-x-auto max-w-screen-lg mx-auto pt-5"> <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> <thead>
<tr> <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") }} {{ _("Name") }}
</th> </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") }} {{ _("Description") }}
</th> </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 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> </tr>
</thead> </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() %} {% for app, infos in wishlist.items() %}
{% set this_app_stars = stars.get(app, {})|length %} {% set this_app_stars = stars.get(app, {})|length %}
{% if user %} {% if user %}
@ -92,10 +92,10 @@
data-stars="{{ this_app_stars }}" data-stars="{{ this_app_stars }}"
data-starred="{{ user_starred_this_app }}" 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'] }} {{ infos['name'] }}
</td> </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"> <td class="float-right sm:float-none sm:table-cell py-2 px-1 sm:px-0">
{% if infos['website'] %} {% if infos['website'] %}
<a <a
@ -105,7 +105,7 @@
class="inline-block" class="inline-block"
target="_blank" 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> </a>
{% endif %} {% endif %}
</td> </td>
@ -118,7 +118,7 @@
class="inline-block" class="inline-block"
target="_blank" 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> </a>
{% endif %} {% endif %}
</td> </td>
@ -150,7 +150,7 @@
</table> </table>
<div id="noResultFound" class="text-center pt-5 hidden"> <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.") }} {{ _("No results found.") }}
</p> </p>
</div> </div>

View file

@ -4,7 +4,7 @@
{% endblock %} {% endblock %}
{% block main %} {% block main %}
<div class="mt-5 text-center px-3 sm:px-0"> <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") }} {{ _("Suggest an application to be added to YunoHost's catalog") }}
</h1> </h1>
</div> </div>
@ -59,21 +59,21 @@
<input name="csrf_token" type="text" class="hidden" value="{{ csrf_token }}" > <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> <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> <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> <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> <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> <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> <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> <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> <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> <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 <button

View file

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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" "PO-Revision-Date: 2024-02-21 06:04+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: ar <LL@li.org>\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" "&& n%100<=10 ? 3 : n%100>=0 && n%100<=2 ? 4 : 5);\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:150 #: app.py:162
msgid "App %(app_id) not found" #, python-format
msgid "App %(app_id)s not found"
msgstr "" msgstr ""
#: app.py:152 #: app.py:165
msgid "You must be logged in to be able to star an app" msgid "You must be logged in to be able to star an app"
msgstr "" 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 "" msgid ""
"Note that, due to various abuses, we restricted login on the app store to " "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 " "'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -36,78 +37,85 @@ msgid ""
"reading posts." "reading posts."
msgstr "" msgstr ""
#: app.py:195 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" msgid "You must be logged in to submit an app to the wishlist"
msgstr "" msgstr ""
#: app.py:207 #: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr ""
#: app.py:228 #: app.py:263
msgid "" msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. " "Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days." "Please try again in a few days."
msgstr "" msgstr ""
#: app.py:230 #: app.py:267
msgid "App name should be at least 3 characters" msgid "App name should be at least 3 characters"
msgstr "" msgstr ""
#: app.py:231 #: app.py:268
msgid "App name should be less than 30 characters" msgid "App name should be less than 30 characters"
msgstr "" msgstr ""
#: app.py:234 #: app.py:271
msgid "App description should be at least 5 characters" msgid "App description should be at least 5 characters"
msgstr "" msgstr ""
#: app.py:238 #: app.py:275
msgid "App description should be less than 100 characters" msgid "App description should be less than 100 characters"
msgstr "" msgstr ""
#: app.py:242 #: app.py:279
msgid "Upstream code repo URL should be at least 10 characters" msgid "Upstream code repo URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:246 #: app.py:283
msgid "Upstream code repo URL should be less than 150 characters" msgid "Upstream code repo URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:250 #: app.py:287
msgid "License URL should be at least 10 characters" msgid "License URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:254 #: app.py:291
msgid "License URL should be less than 250 characters" msgid "License URL should be less than 250 characters"
msgstr "" msgstr ""
#: app.py:256 #: app.py:293
msgid "Website URL should be less than 150 characters" msgid "Website URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:259 #: app.py:296
msgid "App name contains special characters" msgid "App name contains special characters"
msgstr "" msgstr ""
#: app.py:263 #: app.py:303
msgid "" msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or " "Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'." "repeating that the app is 'free' and 'self-hostable'."
msgstr "" msgstr ""
#: app.py:267 #: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does." msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr "" msgstr ""
#: app.py:301 #: app.py:343
#, python-format #, python-format
msgid "" msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you " "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>." "can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr "" 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 #, python-format
msgid "" msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe " "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." "please report the issue to the YunoHost team."
msgstr "" msgstr ""
#: app.py:376 #: app.py:433
#, python-format #, python-format
msgid "" msgid ""
"Your proposed app has succesfully been submitted. It must now be validated " "Your proposed app has succesfully been submitted. It must now be validated "
@ -123,7 +131,7 @@ msgid ""
"%(url)s</a>" "%(url)s</a>"
msgstr "" msgstr ""
#: app.py:449 #: app.py:528
msgid "Unfortunately, login was denied." msgid "Unfortunately, login was denied."
msgstr "" msgstr ""
@ -196,7 +204,7 @@ msgid "Important infos before installing"
msgstr "" msgstr ""
#: templates/app.html:124 #: templates/app.html:124
msgid "Anti-features" msgid "Antifeatures"
msgstr "" msgstr ""
#: templates/app.html:125 #: templates/app.html:125
@ -236,45 +244,64 @@ msgstr ""
msgid "YunoHost package license" msgid "YunoHost package license"
msgstr "" msgstr ""
#: templates/base.html:5 #: templates/base.html:11
msgid "YunoHost app store" msgid "YunoHost app store"
msgstr "" 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" msgid "Home"
msgstr "" msgstr ""
#: templates/base.html:27 templates/base.html:122 #: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog" msgid "Catalog"
msgstr "" msgstr ""
#: templates/base.html:33 templates/base.html:131 #: templates/base.html:46 templates/base.html:172
msgid "Wishlist" msgid "Wishlist"
msgstr "" 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" msgid "YunoHost documentation"
msgstr "" msgstr ""
#: templates/base.html:54 templates/base.html:151 #: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum" msgid "Login using YunoHost's forum"
msgstr "" 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" msgid "Logout"
msgstr "" msgstr ""
#: templates/base.html:99 #: templates/base.html:140
msgid "Toggle menu" msgid "Toggle menu"
msgstr "" msgstr ""
#: templates/base.html:197 #: templates/base.html:255
msgid "" msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using " "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> " "<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</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/" msgstr ""
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr "" msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80 #: templates/catalog.html:75 templates/catalog.html:80
@ -293,7 +320,7 @@ msgstr ""
msgid "All apps" msgid "All apps"
msgstr "" msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39 #: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by" msgid "Sort by"
msgstr "" msgstr ""
@ -306,16 +333,16 @@ msgstr ""
msgid "Newest" msgid "Newest"
msgstr "" msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46 #: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical" msgid "Alphabetical"
msgstr "" 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" msgid "Requires to be logged-in"
msgstr "" msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139 #: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/wishlist.html:51 templates/wishlist.html:60 #: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred" msgid "Show only apps you starred"
msgstr "" msgstr ""
@ -349,8 +376,206 @@ msgstr ""
#: templates/catalog.html:188 #: templates/catalog.html:188
msgid "" 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 "
"advise against their installation and advise users to find alternatives." "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 "" msgstr ""
#: templates/index.html:10 #: templates/index.html:10
@ -361,44 +586,10 @@ msgstr ""
msgid "Browse all applications" msgid "Browse all applications"
msgstr "" 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 #: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app" msgid "Suggest an app"
msgstr "" 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 #: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog" msgid "Suggest an application to be added to YunoHost's catalog"
msgstr "" msgstr ""
@ -417,6 +608,10 @@ msgid ""
"every random nerdy stuff you find on the Internet." "every random nerdy stuff you find on the Internet."
msgstr "" msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64 #: templates/wishlist_add.html:64
msgid "App's description" msgid "App's description"
msgstr "" msgstr ""
@ -460,3 +655,33 @@ msgstr ""
#: templates/wishlist_add.html:84 #: templates/wishlist_add.html:84
msgid "Submit" msgid "Submit"
msgstr "" 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 "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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" "PO-Revision-Date: 2024-02-21 06:05+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: bn_BD <LL@li.org>\n" "Language-Team: bn_BD <LL@li.org>\n"
@ -18,15 +18,16 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:150 #: app.py:162
msgid "App %(app_id) not found" #, python-format
msgid "App %(app_id)s not found"
msgstr "" msgstr ""
#: app.py:152 #: app.py:165
msgid "You must be logged in to be able to star an app" msgid "You must be logged in to be able to star an app"
msgstr "" 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 "" msgid ""
"Note that, due to various abuses, we restricted login on the app store to " "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 " "'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts." "reading posts."
msgstr "" msgstr ""
#: app.py:195 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" msgid "You must be logged in to submit an app to the wishlist"
msgstr "" msgstr ""
#: app.py:207 #: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr ""
#: app.py:228 #: app.py:263
msgid "" msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. " "Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days." "Please try again in a few days."
msgstr "" msgstr ""
#: app.py:230 #: app.py:267
msgid "App name should be at least 3 characters" msgid "App name should be at least 3 characters"
msgstr "" msgstr ""
#: app.py:231 #: app.py:268
msgid "App name should be less than 30 characters" msgid "App name should be less than 30 characters"
msgstr "" msgstr ""
#: app.py:234 #: app.py:271
msgid "App description should be at least 5 characters" msgid "App description should be at least 5 characters"
msgstr "" msgstr ""
#: app.py:238 #: app.py:275
msgid "App description should be less than 100 characters" msgid "App description should be less than 100 characters"
msgstr "" msgstr ""
#: app.py:242 #: app.py:279
msgid "Upstream code repo URL should be at least 10 characters" msgid "Upstream code repo URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:246 #: app.py:283
msgid "Upstream code repo URL should be less than 150 characters" msgid "Upstream code repo URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:250 #: app.py:287
msgid "License URL should be at least 10 characters" msgid "License URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:254 #: app.py:291
msgid "License URL should be less than 250 characters" msgid "License URL should be less than 250 characters"
msgstr "" msgstr ""
#: app.py:256 #: app.py:293
msgid "Website URL should be less than 150 characters" msgid "Website URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:259 #: app.py:296
msgid "App name contains special characters" msgid "App name contains special characters"
msgstr "" msgstr ""
#: app.py:263 #: app.py:303
msgid "" msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or " "Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'." "repeating that the app is 'free' and 'self-hostable'."
msgstr "" msgstr ""
#: app.py:267 #: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does." msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr "" msgstr ""
#: app.py:301 #: app.py:343
#, python-format #, python-format
msgid "" msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you " "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>." "can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr "" 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 #, python-format
msgid "" msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe " "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." "please report the issue to the YunoHost team."
msgstr "" msgstr ""
#: app.py:376 #: app.py:433
#, python-format #, python-format
msgid "" msgid ""
"Your proposed app has succesfully been submitted. It must now be validated " "Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>" "%(url)s</a>"
msgstr "" msgstr ""
#: app.py:449 #: app.py:528
msgid "Unfortunately, login was denied." msgid "Unfortunately, login was denied."
msgstr "" msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr "" msgstr ""
#: templates/app.html:124 #: templates/app.html:124
msgid "Anti-features" msgid "Antifeatures"
msgstr "" msgstr ""
#: templates/app.html:125 #: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license" msgid "YunoHost package license"
msgstr "" msgstr ""
#: templates/base.html:5 #: templates/base.html:11
msgid "YunoHost app store" msgid "YunoHost app store"
msgstr "" 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" msgid "Home"
msgstr "" msgstr ""
#: templates/base.html:27 templates/base.html:122 #: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog" msgid "Catalog"
msgstr "" msgstr ""
#: templates/base.html:33 templates/base.html:131 #: templates/base.html:46 templates/base.html:172
msgid "Wishlist" msgid "Wishlist"
msgstr "" 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" msgid "YunoHost documentation"
msgstr "" msgstr ""
#: templates/base.html:54 templates/base.html:151 #: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum" msgid "Login using YunoHost's forum"
msgstr "" 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" msgid "Logout"
msgstr "" msgstr ""
#: templates/base.html:99 #: templates/base.html:140
msgid "Toggle menu" msgid "Toggle menu"
msgstr "" msgstr ""
#: templates/base.html:197 #: templates/base.html:255
msgid "" msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using " "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> " "<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</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/" msgstr ""
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr "" msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80 #: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps" msgid "All apps"
msgstr "" msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39 #: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by" msgid "Sort by"
msgstr "" msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest" msgid "Newest"
msgstr "" msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46 #: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical" msgid "Alphabetical"
msgstr "" 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" msgid "Requires to be logged-in"
msgstr "" msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139 #: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/wishlist.html:51 templates/wishlist.html:60 #: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred" msgid "Show only apps you starred"
msgstr "" msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188 #: templates/catalog.html:188
msgid "" 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 "
"advise against their installation and advise users to find alternatives." "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 "" msgstr ""
#: templates/index.html:10 #: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications" msgid "Browse all applications"
msgstr "" 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 #: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app" msgid "Suggest an app"
msgstr "" 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 #: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog" msgid "Suggest an application to be added to YunoHost's catalog"
msgstr "" msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet." "every random nerdy stuff you find on the Internet."
msgstr "" msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64 #: templates/wishlist_add.html:64
msgid "App's description" msgid "App's description"
msgstr "" msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84 #: templates/wishlist_add.html:84
msgid "Submit" msgid "Submit"
msgstr "" 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 "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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" "PO-Revision-Date: 2024-02-21 06:05+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: br <LL@li.org>\n" "Language-Team: br <LL@li.org>\n"
@ -22,15 +22,16 @@ msgstr ""
"3 : n%1000000==0 ? 4 : 5);\n" "3 : n%1000000==0 ? 4 : 5);\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:150 #: app.py:162
msgid "App %(app_id) not found" #, python-format
msgid "App %(app_id)s not found"
msgstr "" msgstr ""
#: app.py:152 #: app.py:165
msgid "You must be logged in to be able to star an app" msgid "You must be logged in to be able to star an app"
msgstr "" 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 "" msgid ""
"Note that, due to various abuses, we restricted login on the app store to " "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 " "'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -39,78 +40,85 @@ msgid ""
"reading posts." "reading posts."
msgstr "" msgstr ""
#: app.py:195 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" msgid "You must be logged in to submit an app to the wishlist"
msgstr "" msgstr ""
#: app.py:207 #: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr ""
#: app.py:228 #: app.py:263
msgid "" msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. " "Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days." "Please try again in a few days."
msgstr "" msgstr ""
#: app.py:230 #: app.py:267
msgid "App name should be at least 3 characters" msgid "App name should be at least 3 characters"
msgstr "" msgstr ""
#: app.py:231 #: app.py:268
msgid "App name should be less than 30 characters" msgid "App name should be less than 30 characters"
msgstr "" msgstr ""
#: app.py:234 #: app.py:271
msgid "App description should be at least 5 characters" msgid "App description should be at least 5 characters"
msgstr "" msgstr ""
#: app.py:238 #: app.py:275
msgid "App description should be less than 100 characters" msgid "App description should be less than 100 characters"
msgstr "" msgstr ""
#: app.py:242 #: app.py:279
msgid "Upstream code repo URL should be at least 10 characters" msgid "Upstream code repo URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:246 #: app.py:283
msgid "Upstream code repo URL should be less than 150 characters" msgid "Upstream code repo URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:250 #: app.py:287
msgid "License URL should be at least 10 characters" msgid "License URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:254 #: app.py:291
msgid "License URL should be less than 250 characters" msgid "License URL should be less than 250 characters"
msgstr "" msgstr ""
#: app.py:256 #: app.py:293
msgid "Website URL should be less than 150 characters" msgid "Website URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:259 #: app.py:296
msgid "App name contains special characters" msgid "App name contains special characters"
msgstr "" msgstr ""
#: app.py:263 #: app.py:303
msgid "" msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or " "Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'." "repeating that the app is 'free' and 'self-hostable'."
msgstr "" msgstr ""
#: app.py:267 #: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does." msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr "" msgstr ""
#: app.py:301 #: app.py:343
#, python-format #, python-format
msgid "" msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you " "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>." "can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr "" 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 #, python-format
msgid "" msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe " "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." "please report the issue to the YunoHost team."
msgstr "" msgstr ""
#: app.py:376 #: app.py:433
#, python-format #, python-format
msgid "" msgid ""
"Your proposed app has succesfully been submitted. It must now be validated " "Your proposed app has succesfully been submitted. It must now be validated "
@ -126,7 +134,7 @@ msgid ""
"%(url)s</a>" "%(url)s</a>"
msgstr "" msgstr ""
#: app.py:449 #: app.py:528
msgid "Unfortunately, login was denied." msgid "Unfortunately, login was denied."
msgstr "" msgstr ""
@ -199,7 +207,7 @@ msgid "Important infos before installing"
msgstr "" msgstr ""
#: templates/app.html:124 #: templates/app.html:124
msgid "Anti-features" msgid "Antifeatures"
msgstr "" msgstr ""
#: templates/app.html:125 #: templates/app.html:125
@ -239,45 +247,64 @@ msgstr ""
msgid "YunoHost package license" msgid "YunoHost package license"
msgstr "" msgstr ""
#: templates/base.html:5 #: templates/base.html:11
msgid "YunoHost app store" msgid "YunoHost app store"
msgstr "" 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" msgid "Home"
msgstr "" msgstr ""
#: templates/base.html:27 templates/base.html:122 #: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog" msgid "Catalog"
msgstr "" msgstr ""
#: templates/base.html:33 templates/base.html:131 #: templates/base.html:46 templates/base.html:172
msgid "Wishlist" msgid "Wishlist"
msgstr "" 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" msgid "YunoHost documentation"
msgstr "" msgstr ""
#: templates/base.html:54 templates/base.html:151 #: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum" msgid "Login using YunoHost's forum"
msgstr "" 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" msgid "Logout"
msgstr "" msgstr ""
#: templates/base.html:99 #: templates/base.html:140
msgid "Toggle menu" msgid "Toggle menu"
msgstr "" msgstr ""
#: templates/base.html:197 #: templates/base.html:255
msgid "" msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using " "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> " "<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</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/" msgstr ""
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr "" msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80 #: templates/catalog.html:75 templates/catalog.html:80
@ -296,7 +323,7 @@ msgstr ""
msgid "All apps" msgid "All apps"
msgstr "" msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39 #: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by" msgid "Sort by"
msgstr "" msgstr ""
@ -309,16 +336,16 @@ msgstr ""
msgid "Newest" msgid "Newest"
msgstr "" msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46 #: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical" msgid "Alphabetical"
msgstr "" 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" msgid "Requires to be logged-in"
msgstr "" msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139 #: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/wishlist.html:51 templates/wishlist.html:60 #: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred" msgid "Show only apps you starred"
msgstr "" msgstr ""
@ -352,8 +379,206 @@ msgstr ""
#: templates/catalog.html:188 #: templates/catalog.html:188
msgid "" 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 "
"advise against their installation and advise users to find alternatives." "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 "" msgstr ""
#: templates/index.html:10 #: templates/index.html:10
@ -364,44 +589,10 @@ msgstr ""
msgid "Browse all applications" msgid "Browse all applications"
msgstr "" 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 #: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app" msgid "Suggest an app"
msgstr "" 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 #: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog" msgid "Suggest an application to be added to YunoHost's catalog"
msgstr "" msgstr ""
@ -420,6 +611,10 @@ msgid ""
"every random nerdy stuff you find on the Internet." "every random nerdy stuff you find on the Internet."
msgstr "" msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64 #: templates/wishlist_add.html:64
msgid "App's description" msgid "App's description"
msgstr "" msgstr ""
@ -463,3 +658,33 @@ msgstr ""
#: templates/wishlist_add.html:84 #: templates/wishlist_add.html:84
msgid "Submit" msgid "Submit"
msgstr "" 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 "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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" "PO-Revision-Date: 2024-03-23 19:04+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: OniriCorpe <oniricorpe@disroot.org>\n"
"Language-Team: ca <LL@li.org>\n" "Language-Team: Catalan <https://translate.yunohost.org/projects/yunohost/"
"apps/ca/>\n"
"Language: ca\n" "Language: ca\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\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" "Generated-By: Babel 2.14.0\n"
#: app.py:150 #: app.py:162
msgid "App %(app_id) not found" #, python-format
msgstr "" 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" 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 "" msgid ""
"Note that, due to various abuses, we restricted login on the app store to " "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 " "'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 " "least 5 topics, reading at least 30 posts, and spending at least 10 minutes "
"reading posts." "reading posts."
msgstr "" 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" 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" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr ""
"El testimoni CSRF no és vàlid; actualitzeu la pàgina i torneu-ho a provar"
#: app.py:228 #: app.py:263
msgid "" msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. " "Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days." "Please try again in a few days."
msgstr "" 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" 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" 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" 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" 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" 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" 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" 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" 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" 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" msgid "App name contains special characters"
msgstr "" msgstr "El nom de l'aplicació conté caràcters especials"
#: app.py:263 #: app.py:303
msgid "" msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or " "Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'." "repeating that the app is 'free' and 'self-hostable'."
msgstr "" 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." msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr "" 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 #, python-format
msgid "" msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you " "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>." "can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr "" 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 #, python-format
msgid "" msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe " "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, " "there's already <a href='%(url)s'>a waiting PR for this app</a>? Else, "
"please report the issue to the YunoHost team." "please report the issue to the YunoHost team."
msgstr "" 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 #, python-format
msgid "" msgid ""
"Your proposed app has succesfully been submitted. It must now be validated " "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'>" "by the YunoHost team. You can track progress here: <a href='%(url)s'>"
"%(url)s</a>" "%(url)s</a>"
msgstr "" 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." msgid "Unfortunately, login was denied."
msgstr "" msgstr "Malauradament s'ha denegat l'inici de sessió."
#: templates/app.html:10 templates/catalog.html:23 #: templates/app.html:10 templates/catalog.html:23
#, python-format #, python-format
msgid "Logo for %(app)s" msgid "Logo for %(app)s"
msgstr "" msgstr "Logotip de %(app)s"
#: templates/app.html:30 templates/app.html:31 templates/catalog.html:41 #: templates/app.html:30 templates/app.html:31 templates/catalog.html:41
#: templates/catalog.html:42 #: templates/catalog.html:42
@ -137,6 +170,8 @@ msgid ""
"This app is currently flagged as broken because it failed our automatic " "This app is currently flagged as broken because it failed our automatic "
"tests." "tests."
msgstr "" 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/app.html:30 templates/app.html:31 templates/catalog.html:41
#: templates/catalog.html:42 templates/catalog.html:170 #: templates/catalog.html:42 templates/catalog.html:170
@ -144,6 +179,8 @@ msgid ""
"This is usually a temporary situation which requires packagers to fix " "This is usually a temporary situation which requires packagers to fix "
"something in the app." "something in the app."
msgstr "" 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/app.html:37 templates/app.html:38 templates/catalog.html:46
#: templates/catalog.html:47 #: templates/catalog.html:47
@ -151,218 +188,537 @@ msgid ""
"This app has been good quality according to our automatic tests over at " "This app has been good quality according to our automatic tests over at "
"least one year." "least one year."
msgstr "" msgstr ""
"Aquesta aplicació ha estat de bona qualitat segons les nostres proves "
"automàtiques durant almenys un any."
#: templates/app.html:81 #: templates/app.html:81
msgid "Try the demo" msgid "Try the demo"
msgstr "" msgstr "Prova la demostració"
#: templates/app.html:82 #: templates/app.html:82
msgid "Demo" msgid "Demo"
msgstr "" msgstr "Demostració"
#: templates/app.html:85 #: templates/app.html:85
msgid "Install with YunoHost" msgid "Install with YunoHost"
msgstr "" msgstr "Instal·leu amb YunoHost"
#: templates/app.html:93 #: templates/app.html:93
#, python-format #, python-format
msgid "Current version: %(version)s" msgid "Current version: %(version)s"
msgstr "" msgstr "Versió actual: %(version)s"
#: templates/app.html:95 #: templates/app.html:95
#, python-format #, python-format
msgid "Potential alternative to: %(alternatives)s" msgid "Potential alternative to: %(alternatives)s"
msgstr "" msgstr "Alternativa potencial a: %(alternatives)s"
#: templates/app.html:101 #: templates/app.html:101
#, python-format #, python-format
msgid "Screenshot for %(app)s" msgid "Screenshot for %(app)s"
msgstr "" msgstr "Captura de pantalla de %(app)s"
#: templates/app.html:106 #: templates/app.html:106
#, python-format #, python-format
msgid "" msgid ""
"This app is only compatible with these specific architectures: %(archs)s" "This app is only compatible with these specific architectures: %(archs)s"
msgstr "" msgstr ""
"Aquesta aplicació només és compatible amb aquestes arquitectures "
"específiques: %(archs)s"
#: templates/app.html:112 #: templates/app.html:112
#, python-format #, python-format
msgid "This app requires an unusual amount of RAM to install: %(ram)s" msgid "This app requires an unusual amount of RAM to install: %(ram)s"
msgstr "" msgstr ""
"Aquesta aplicació requereix una quantitat inusual de RAM per instal·lar-se: "
"%(ram)s"
#: templates/app.html:118 #: templates/app.html:118
msgid "Important infos before installing" msgid "Important infos before installing"
msgstr "" msgstr "Informació important abans d'instal·lar"
# | msgid "Anti-features"
#: templates/app.html:124 #: templates/app.html:124
msgid "Anti-features" #, fuzzy
msgstr "" msgid "Antifeatures"
msgstr "Anticaracterístiques"
#: templates/app.html:125 #: templates/app.html:125
msgid "(This app has features you may not like)" msgid "(This app has features you may not like)"
msgstr "" msgstr "(Aquesta aplicació té funcions que potser no us agraden)"
#: templates/app.html:136 #: templates/app.html:136
msgid "Useful links" msgid "Useful links"
msgstr "" msgstr "Vincles útils"
#: templates/app.html:139 #: templates/app.html:139
#, python-format #, python-format
msgid "App license: %(license)s" msgid "App license: %(license)s"
msgstr "" msgstr "Llicència de l'aplicació: %(license)s"
#: templates/app.html:140 #: templates/app.html:140
msgid " Official website" msgid " Official website"
msgstr "" msgstr " Pàgina web oficial"
#: templates/app.html:141 #: templates/app.html:141
msgid "Official admin documentation" msgid "Official admin documentation"
msgstr "" msgstr "Documentació oficial d'administració"
#: templates/app.html:142 #: templates/app.html:142
msgid "Official user documentation" msgid "Official user documentation"
msgstr "" msgstr "Documentació oficial d'usuari"
#: templates/app.html:143 #: templates/app.html:143
msgid "Official code repository" msgid "Official code repository"
msgstr "" msgstr "Repositori de codi oficial"
#: templates/app.html:144 #: templates/app.html:144
msgid "YunoHost package repository" msgid "YunoHost package repository"
msgstr "" msgstr "Repositori de paquets YunoHost"
#: templates/app.html:145 #: templates/app.html:145
msgid "YunoHost package license" msgid "YunoHost package license"
msgstr "" msgstr "Llicència del paquet YunoHost"
#: templates/base.html:5 #: templates/base.html:11
msgid "YunoHost app store" 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" 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" msgid "Catalog"
msgstr "" msgstr "Catàleg"
#: templates/base.html:33 templates/base.html:131 #: templates/base.html:46 templates/base.html:172
msgid "Wishlist" msgid "Wishlist"
msgstr "Llista de desitjos"
#: templates/base.html:52
msgid "Packaging dashboard"
msgstr "" 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" 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" 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 "" msgstr ""
#: templates/base.html:86 templates/base.html:179 #: templates/base.html:127 templates/base.html:237
msgid "Logout" msgid "Logout"
msgstr "" msgstr "Tancar sessió"
#: templates/base.html:99 #: templates/base.html:140
msgid "Toggle menu" msgid "Toggle menu"
msgstr "" msgstr "Canvia el menú"
#: templates/base.html:197 #: templates/base.html:255
msgid "" msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using " "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> " "<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</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>"
msgstr "" 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 #: templates/catalog.html:75 templates/catalog.html:80
msgid "Application Catalog" msgid "Application Catalog"
msgstr "" msgstr "Catàleg d'aplicacions"
#: templates/catalog.html:86 templates/wishlist.html:16 #: templates/catalog.html:86 templates/wishlist.html:16
msgid "Search" msgid "Search"
msgstr "" msgstr "Cercar"
#: templates/catalog.html:91 templates/wishlist.html:21 #: templates/catalog.html:91 templates/wishlist.html:21
msgid "Search for…" msgid "Search for…"
msgstr "" msgstr "Buscar…"
#: templates/catalog.html:107 #: templates/catalog.html:107
msgid "All apps" 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" msgid "Sort by"
msgstr "" msgstr "Ordenar per"
#: templates/catalog.html:123 templates/wishlist.html:45 #: templates/catalog.html:123 templates/wishlist.html:45
#: templates/wishlist.html:78 #: templates/wishlist.html:78
msgid "Popularity" msgid "Popularity"
msgstr "" msgstr "Popularitat"
#: templates/catalog.html:124 #: templates/catalog.html:124
msgid "Newest" 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" 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" msgid "Requires to be logged-in"
msgstr "" msgstr "Requereix estar connectat"
#: templates/catalog.html:130 templates/catalog.html:139 #: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/wishlist.html:51 templates/wishlist.html:60 #: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred" msgid "Show only apps you starred"
msgstr "" msgstr "Mostra només les aplicacions que has destacat"
#: templates/catalog.html:155 templates/wishlist.html:154 #: templates/catalog.html:155 templates/wishlist.html:154
msgid "No results found." msgid "No results found."
msgstr "" msgstr "Sense resultats."
#: templates/catalog.html:158 #: templates/catalog.html:158
msgid "Not finding what you are looking for?" msgid "Not finding what you are looking for?"
msgstr "" msgstr "No trobes el que estàs buscant?"
#: templates/catalog.html:159 #: templates/catalog.html:159
msgid "Checkout the wishlist!" msgid "Checkout the wishlist!"
msgstr "" msgstr "Fes una ullada a la llista de desitjos!"
#: templates/catalog.html:166 #: templates/catalog.html:166
msgid "Applications currently flagged as broken" msgid "Applications currently flagged as broken"
msgstr "" msgstr "Aplicacions marcades actualment com a trencades"
#: templates/catalog.html:169 #: templates/catalog.html:169
msgid "These are apps which failed our automatic tests." msgid "These are apps which failed our automatic tests."
msgstr "" msgstr ""
"Aquestes són aplicacions que no han passat les nostres proves automàtiques."
#: templates/catalog.html:184 #: templates/catalog.html:184
msgid "Deprecated applications" msgid "Deprecated applications"
msgstr "" msgstr "Aplicacions obsoletes"
#: templates/catalog.html:187 #: templates/catalog.html:187
msgid "These are apps who are not maintained anymore." msgid "These are apps who are not maintained anymore."
msgstr "" msgstr "Aquestes són aplicacions que ja no es mantenen."
#: templates/catalog.html:188 #: templates/catalog.html:188
msgid "" 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 "
"advise against their installation and advise users to find alternatives." "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 "" msgstr ""
#: templates/index.html:10 #: templates/index.html:10
msgid "Application Store" msgid "Application Store"
msgstr "" msgstr "Botiga d'aplicacions"
#: templates/index.html:21 #: templates/index.html:21
msgid "Browse all applications" 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 "" 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 #: templates/wishlist.html:3 templates/wishlist.html:8
msgid "Application Wishlist" msgid "Application Wishlist"
msgstr "" msgstr "Llista de desitjos d'aplicacions"
#: templates/wishlist.html:10 #: templates/wishlist.html:10
msgid "" msgid ""
@ -373,89 +729,25 @@ msgid ""
"to integrate it, and is merely a source of inspiration for packaging " "to integrate it, and is merely a source of inspiration for packaging "
"volunteers." "volunteers."
msgstr "" msgstr ""
"La llista de desitjos és el lloc on les persones poden suggerir i votar "
#: templates/wishlist.html:33 templates/wishlist_add.html:3 "col·lectivament les aplicacions que els agradaria veure empaquetades i "
msgid "Suggest an app" "disponibles al catàleg oficial d'aplicacions de YunoHost. No obstant això, "
msgstr "" "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 "
#: templates/wishlist.html:71 templates/wishlist_add.html:61 "només una font d'inspiració per als voluntaris d'embalatge."
msgid "Name"
msgstr ""
#: templates/wishlist.html:74 #: templates/wishlist.html:74
msgid "Description" msgid "Description"
msgstr "" msgstr "Descripció"
#: templates/wishlist.html:102 templates/wishlist.html:103 #: templates/wishlist.html:102 templates/wishlist.html:103
msgid "Official website" msgid "Official website"
msgstr "" msgstr "Pàgina web oficial"
#: templates/wishlist.html:115 templates/wishlist.html:116 #: templates/wishlist.html:115 templates/wishlist.html:116
msgid "Code repository" msgid "Code repository"
msgstr "" msgstr "Repositori de codi"
#: templates/wishlist.html:129 templates/wishlist.html:130 #: templates/wishlist.html:129 templates/wishlist.html:130
msgid "Star this app" msgid "Star this app"
msgstr "" msgstr "Destaca aquesta aplicació"
#: 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 ""

View file

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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" "PO-Revision-Date: 2024-02-21 06:08+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: ckb <LL@li.org>\n" "Language-Team: ckb <LL@li.org>\n"
@ -18,15 +18,16 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:150 #: app.py:162
msgid "App %(app_id) not found" #, python-format
msgid "App %(app_id)s not found"
msgstr "" msgstr ""
#: app.py:152 #: app.py:165
msgid "You must be logged in to be able to star an app" msgid "You must be logged in to be able to star an app"
msgstr "" 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 "" msgid ""
"Note that, due to various abuses, we restricted login on the app store to " "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 " "'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts." "reading posts."
msgstr "" msgstr ""
#: app.py:195 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" msgid "You must be logged in to submit an app to the wishlist"
msgstr "" msgstr ""
#: app.py:207 #: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr ""
#: app.py:228 #: app.py:263
msgid "" msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. " "Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days." "Please try again in a few days."
msgstr "" msgstr ""
#: app.py:230 #: app.py:267
msgid "App name should be at least 3 characters" msgid "App name should be at least 3 characters"
msgstr "" msgstr ""
#: app.py:231 #: app.py:268
msgid "App name should be less than 30 characters" msgid "App name should be less than 30 characters"
msgstr "" msgstr ""
#: app.py:234 #: app.py:271
msgid "App description should be at least 5 characters" msgid "App description should be at least 5 characters"
msgstr "" msgstr ""
#: app.py:238 #: app.py:275
msgid "App description should be less than 100 characters" msgid "App description should be less than 100 characters"
msgstr "" msgstr ""
#: app.py:242 #: app.py:279
msgid "Upstream code repo URL should be at least 10 characters" msgid "Upstream code repo URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:246 #: app.py:283
msgid "Upstream code repo URL should be less than 150 characters" msgid "Upstream code repo URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:250 #: app.py:287
msgid "License URL should be at least 10 characters" msgid "License URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:254 #: app.py:291
msgid "License URL should be less than 250 characters" msgid "License URL should be less than 250 characters"
msgstr "" msgstr ""
#: app.py:256 #: app.py:293
msgid "Website URL should be less than 150 characters" msgid "Website URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:259 #: app.py:296
msgid "App name contains special characters" msgid "App name contains special characters"
msgstr "" msgstr ""
#: app.py:263 #: app.py:303
msgid "" msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or " "Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'." "repeating that the app is 'free' and 'self-hostable'."
msgstr "" msgstr ""
#: app.py:267 #: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does." msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr "" msgstr ""
#: app.py:301 #: app.py:343
#, python-format #, python-format
msgid "" msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you " "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>." "can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr "" 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 #, python-format
msgid "" msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe " "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." "please report the issue to the YunoHost team."
msgstr "" msgstr ""
#: app.py:376 #: app.py:433
#, python-format #, python-format
msgid "" msgid ""
"Your proposed app has succesfully been submitted. It must now be validated " "Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>" "%(url)s</a>"
msgstr "" msgstr ""
#: app.py:449 #: app.py:528
msgid "Unfortunately, login was denied." msgid "Unfortunately, login was denied."
msgstr "" msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr "" msgstr ""
#: templates/app.html:124 #: templates/app.html:124
msgid "Anti-features" msgid "Antifeatures"
msgstr "" msgstr ""
#: templates/app.html:125 #: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license" msgid "YunoHost package license"
msgstr "" msgstr ""
#: templates/base.html:5 #: templates/base.html:11
msgid "YunoHost app store" msgid "YunoHost app store"
msgstr "" 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" msgid "Home"
msgstr "" msgstr ""
#: templates/base.html:27 templates/base.html:122 #: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog" msgid "Catalog"
msgstr "" msgstr ""
#: templates/base.html:33 templates/base.html:131 #: templates/base.html:46 templates/base.html:172
msgid "Wishlist" msgid "Wishlist"
msgstr "" 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" msgid "YunoHost documentation"
msgstr "" msgstr ""
#: templates/base.html:54 templates/base.html:151 #: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum" msgid "Login using YunoHost's forum"
msgstr "" 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" msgid "Logout"
msgstr "" msgstr ""
#: templates/base.html:99 #: templates/base.html:140
msgid "Toggle menu" msgid "Toggle menu"
msgstr "" msgstr ""
#: templates/base.html:197 #: templates/base.html:255
msgid "" msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using " "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> " "<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</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/" msgstr ""
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr "" msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80 #: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps" msgid "All apps"
msgstr "" msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39 #: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by" msgid "Sort by"
msgstr "" msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest" msgid "Newest"
msgstr "" msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46 #: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical" msgid "Alphabetical"
msgstr "" 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" msgid "Requires to be logged-in"
msgstr "" msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139 #: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/wishlist.html:51 templates/wishlist.html:60 #: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred" msgid "Show only apps you starred"
msgstr "" msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188 #: templates/catalog.html:188
msgid "" 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 "
"advise against their installation and advise users to find alternatives." "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 "" msgstr ""
#: templates/index.html:10 #: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications" msgid "Browse all applications"
msgstr "" 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 #: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app" msgid "Suggest an app"
msgstr "" 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 #: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog" msgid "Suggest an application to be added to YunoHost's catalog"
msgstr "" msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet." "every random nerdy stuff you find on the Internet."
msgstr "" msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64 #: templates/wishlist_add.html:64
msgid "App's description" msgid "App's description"
msgstr "" msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84 #: templates/wishlist_add.html:84
msgid "Submit" msgid "Submit"
msgstr "" 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 "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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" "PO-Revision-Date: 2024-02-21 06:09+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: cs <LL@li.org>\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" "Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:150 #: app.py:162
msgid "App %(app_id) not found" #, python-format
msgid "App %(app_id)s not found"
msgstr "" msgstr ""
#: app.py:152 #: app.py:165
msgid "You must be logged in to be able to star an app" msgid "You must be logged in to be able to star an app"
msgstr "" 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 "" msgid ""
"Note that, due to various abuses, we restricted login on the app store to " "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 " "'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts." "reading posts."
msgstr "" msgstr ""
#: app.py:195 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" msgid "You must be logged in to submit an app to the wishlist"
msgstr "" msgstr ""
#: app.py:207 #: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr ""
#: app.py:228 #: app.py:263
msgid "" msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. " "Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days." "Please try again in a few days."
msgstr "" msgstr ""
#: app.py:230 #: app.py:267
msgid "App name should be at least 3 characters" msgid "App name should be at least 3 characters"
msgstr "" msgstr ""
#: app.py:231 #: app.py:268
msgid "App name should be less than 30 characters" msgid "App name should be less than 30 characters"
msgstr "" msgstr ""
#: app.py:234 #: app.py:271
msgid "App description should be at least 5 characters" msgid "App description should be at least 5 characters"
msgstr "" msgstr ""
#: app.py:238 #: app.py:275
msgid "App description should be less than 100 characters" msgid "App description should be less than 100 characters"
msgstr "" msgstr ""
#: app.py:242 #: app.py:279
msgid "Upstream code repo URL should be at least 10 characters" msgid "Upstream code repo URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:246 #: app.py:283
msgid "Upstream code repo URL should be less than 150 characters" msgid "Upstream code repo URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:250 #: app.py:287
msgid "License URL should be at least 10 characters" msgid "License URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:254 #: app.py:291
msgid "License URL should be less than 250 characters" msgid "License URL should be less than 250 characters"
msgstr "" msgstr ""
#: app.py:256 #: app.py:293
msgid "Website URL should be less than 150 characters" msgid "Website URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:259 #: app.py:296
msgid "App name contains special characters" msgid "App name contains special characters"
msgstr "" msgstr ""
#: app.py:263 #: app.py:303
msgid "" msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or " "Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'." "repeating that the app is 'free' and 'self-hostable'."
msgstr "" msgstr ""
#: app.py:267 #: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does." msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr "" msgstr ""
#: app.py:301 #: app.py:343
#, python-format #, python-format
msgid "" msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you " "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>." "can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr "" 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 #, python-format
msgid "" msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe " "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." "please report the issue to the YunoHost team."
msgstr "" msgstr ""
#: app.py:376 #: app.py:433
#, python-format #, python-format
msgid "" msgid ""
"Your proposed app has succesfully been submitted. It must now be validated " "Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>" "%(url)s</a>"
msgstr "" msgstr ""
#: app.py:449 #: app.py:528
msgid "Unfortunately, login was denied." msgid "Unfortunately, login was denied."
msgstr "" msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr "" msgstr ""
#: templates/app.html:124 #: templates/app.html:124
msgid "Anti-features" msgid "Antifeatures"
msgstr "" msgstr ""
#: templates/app.html:125 #: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license" msgid "YunoHost package license"
msgstr "" msgstr ""
#: templates/base.html:5 #: templates/base.html:11
msgid "YunoHost app store" msgid "YunoHost app store"
msgstr "" 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" msgid "Home"
msgstr "" msgstr ""
#: templates/base.html:27 templates/base.html:122 #: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog" msgid "Catalog"
msgstr "" msgstr ""
#: templates/base.html:33 templates/base.html:131 #: templates/base.html:46 templates/base.html:172
msgid "Wishlist" msgid "Wishlist"
msgstr "" 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" msgid "YunoHost documentation"
msgstr "" msgstr ""
#: templates/base.html:54 templates/base.html:151 #: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum" msgid "Login using YunoHost's forum"
msgstr "" 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" msgid "Logout"
msgstr "" msgstr ""
#: templates/base.html:99 #: templates/base.html:140
msgid "Toggle menu" msgid "Toggle menu"
msgstr "" msgstr ""
#: templates/base.html:197 #: templates/base.html:255
msgid "" msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using " "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> " "<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</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/" msgstr ""
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr "" msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80 #: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps" msgid "All apps"
msgstr "" msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39 #: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by" msgid "Sort by"
msgstr "" msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest" msgid "Newest"
msgstr "" msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46 #: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical" msgid "Alphabetical"
msgstr "" 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" msgid "Requires to be logged-in"
msgstr "" msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139 #: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/wishlist.html:51 templates/wishlist.html:60 #: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred" msgid "Show only apps you starred"
msgstr "" msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188 #: templates/catalog.html:188
msgid "" 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 "
"advise against their installation and advise users to find alternatives." "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 "" msgstr ""
#: templates/index.html:10 #: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications" msgid "Browse all applications"
msgstr "" 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 #: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app" msgid "Suggest an app"
msgstr "" 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 #: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog" msgid "Suggest an application to be added to YunoHost's catalog"
msgstr "" msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet." "every random nerdy stuff you find on the Internet."
msgstr "" msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64 #: templates/wishlist_add.html:64
msgid "App's description" msgid "App's description"
msgstr "" msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84 #: templates/wishlist_add.html:84
msgid "Submit" msgid "Submit"
msgstr "" 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 "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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" "PO-Revision-Date: 2024-02-21 06:05+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: da <LL@li.org>\n" "Language-Team: da <LL@li.org>\n"
@ -18,15 +18,16 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:150 #: app.py:162
msgid "App %(app_id) not found" #, python-format
msgid "App %(app_id)s not found"
msgstr "" msgstr ""
#: app.py:152 #: app.py:165
msgid "You must be logged in to be able to star an app" msgid "You must be logged in to be able to star an app"
msgstr "" 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 "" msgid ""
"Note that, due to various abuses, we restricted login on the app store to " "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 " "'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts." "reading posts."
msgstr "" msgstr ""
#: app.py:195 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" msgid "You must be logged in to submit an app to the wishlist"
msgstr "" msgstr ""
#: app.py:207 #: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr ""
#: app.py:228 #: app.py:263
msgid "" msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. " "Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days." "Please try again in a few days."
msgstr "" msgstr ""
#: app.py:230 #: app.py:267
msgid "App name should be at least 3 characters" msgid "App name should be at least 3 characters"
msgstr "" msgstr ""
#: app.py:231 #: app.py:268
msgid "App name should be less than 30 characters" msgid "App name should be less than 30 characters"
msgstr "" msgstr ""
#: app.py:234 #: app.py:271
msgid "App description should be at least 5 characters" msgid "App description should be at least 5 characters"
msgstr "" msgstr ""
#: app.py:238 #: app.py:275
msgid "App description should be less than 100 characters" msgid "App description should be less than 100 characters"
msgstr "" msgstr ""
#: app.py:242 #: app.py:279
msgid "Upstream code repo URL should be at least 10 characters" msgid "Upstream code repo URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:246 #: app.py:283
msgid "Upstream code repo URL should be less than 150 characters" msgid "Upstream code repo URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:250 #: app.py:287
msgid "License URL should be at least 10 characters" msgid "License URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:254 #: app.py:291
msgid "License URL should be less than 250 characters" msgid "License URL should be less than 250 characters"
msgstr "" msgstr ""
#: app.py:256 #: app.py:293
msgid "Website URL should be less than 150 characters" msgid "Website URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:259 #: app.py:296
msgid "App name contains special characters" msgid "App name contains special characters"
msgstr "" msgstr ""
#: app.py:263 #: app.py:303
msgid "" msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or " "Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'." "repeating that the app is 'free' and 'self-hostable'."
msgstr "" msgstr ""
#: app.py:267 #: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does." msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr "" msgstr ""
#: app.py:301 #: app.py:343
#, python-format #, python-format
msgid "" msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you " "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>." "can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr "" 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 #, python-format
msgid "" msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe " "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." "please report the issue to the YunoHost team."
msgstr "" msgstr ""
#: app.py:376 #: app.py:433
#, python-format #, python-format
msgid "" msgid ""
"Your proposed app has succesfully been submitted. It must now be validated " "Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>" "%(url)s</a>"
msgstr "" msgstr ""
#: app.py:449 #: app.py:528
msgid "Unfortunately, login was denied." msgid "Unfortunately, login was denied."
msgstr "" msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr "" msgstr ""
#: templates/app.html:124 #: templates/app.html:124
msgid "Anti-features" msgid "Antifeatures"
msgstr "" msgstr ""
#: templates/app.html:125 #: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license" msgid "YunoHost package license"
msgstr "" msgstr ""
#: templates/base.html:5 #: templates/base.html:11
msgid "YunoHost app store" msgid "YunoHost app store"
msgstr "" 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" msgid "Home"
msgstr "" msgstr ""
#: templates/base.html:27 templates/base.html:122 #: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog" msgid "Catalog"
msgstr "" msgstr ""
#: templates/base.html:33 templates/base.html:131 #: templates/base.html:46 templates/base.html:172
msgid "Wishlist" msgid "Wishlist"
msgstr "" 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" msgid "YunoHost documentation"
msgstr "" msgstr ""
#: templates/base.html:54 templates/base.html:151 #: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum" msgid "Login using YunoHost's forum"
msgstr "" 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" msgid "Logout"
msgstr "" msgstr ""
#: templates/base.html:99 #: templates/base.html:140
msgid "Toggle menu" msgid "Toggle menu"
msgstr "" msgstr ""
#: templates/base.html:197 #: templates/base.html:255
msgid "" msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using " "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> " "<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</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/" msgstr ""
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr "" msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80 #: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps" msgid "All apps"
msgstr "" msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39 #: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by" msgid "Sort by"
msgstr "" msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest" msgid "Newest"
msgstr "" msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46 #: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical" msgid "Alphabetical"
msgstr "" 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" msgid "Requires to be logged-in"
msgstr "" msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139 #: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/wishlist.html:51 templates/wishlist.html:60 #: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred" msgid "Show only apps you starred"
msgstr "" msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188 #: templates/catalog.html:188
msgid "" 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 "
"advise against their installation and advise users to find alternatives." "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 "" msgstr ""
#: templates/index.html:10 #: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications" msgid "Browse all applications"
msgstr "" 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 #: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app" msgid "Suggest an app"
msgstr "" 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 #: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog" msgid "Suggest an application to be added to YunoHost's catalog"
msgstr "" msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet." "every random nerdy stuff you find on the Internet."
msgstr "" msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64 #: templates/wishlist_add.html:64
msgid "App's description" msgid "App's description"
msgstr "" msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84 #: templates/wishlist_add.html:84
msgid "Submit" msgid "Submit"
msgstr "" 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 "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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-03-06 17:37+0000\n" "PO-Revision-Date: 2024-03-23 19:04+0000\n"
"Last-Translator: Christian Wehrli <christian@chw.onl>\n" "Last-Translator: OniriCorpe <oniricorpe@disroot.org>\n"
"Language-Team: German <https://translate.yunohost.org/projects/yunohost/apps/" "Language-Team: German <https://translate.yunohost.org/projects/yunohost/apps/"
"de/>\n" "de/>\n"
"Language: de\n" "Language: de\n"
@ -17,18 +17,18 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.3.1\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:150 #: app.py:162
msgid "App %(app_id) not found" #, python-format
msgstr "App %(app_id) nicht gefunden" 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" 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" 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 "" msgid ""
"Note that, due to various abuses, we restricted login on the app store to " "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 " "'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 " "Beiträge gelesen und mindestens 10 Minuten damit verbracht haben, Beiträge "
"zu lesen." "zu lesen."
#: app.py:195 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" 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" 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" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr ""
"Ungültiges CSRF-Token. Bitte aktualisieren Sie die Seite und versuchen Sie " "Ungültiges CSRF-Token. Bitte aktualisieren Sie die Seite und versuchen Sie "
"es erneut" "es erneut"
#: app.py:228 #: app.py:263
msgid "" msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. " "Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days." "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 " "pro Benutzer beschränkt. Bitte versuchen Sie es in ein paar Tagen noch "
"einmal." "einmal."
#: app.py:230 #: app.py:267
msgid "App name should be at least 3 characters" msgid "App name should be at least 3 characters"
msgstr "Der App-Name sollte mindestens 3 Zeichen lang sein" 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" msgid "App name should be less than 30 characters"
msgstr "Der App-Name sollte weniger als 30 Zeichen lang sein" 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" msgid "App description should be at least 5 characters"
msgstr "Die App-Beschreibung sollte mindestens 5 Zeichen lang sein" 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" msgid "App description should be less than 100 characters"
msgstr "Die App-Beschreibung sollte weniger als 100 Zeichen umfassen" 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" msgid "Upstream code repo URL should be at least 10 characters"
msgstr "" msgstr ""
"Die Upstream-Code-Repository-URL sollte mindestens 10 Zeichen lang sein" "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" msgid "Upstream code repo URL should be less than 150 characters"
msgstr "" msgstr ""
"Die Upstream-Code-Repository-URL sollte weniger als 150 Zeichen lang sein" "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" msgid "License URL should be at least 10 characters"
msgstr "Die Lizenz-URL sollte mindestens 10 Zeichen lang sein" 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" msgid "License URL should be less than 250 characters"
msgstr "Die Lizenz-URL sollte weniger als 250 Zeichen lang sein" 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" msgid "Website URL should be less than 150 characters"
msgstr "Die Website-URL sollte weniger als 150 Zeichen lang sein" msgstr "Die Website-URL sollte weniger als 150 Zeichen lang sein"
#: app.py:259 #: app.py:296
msgid "App name contains special characters" msgid "App name contains special characters"
msgstr "Der App-Name enthält Sonderzeichen" msgstr "Der App-Name enthält Sonderzeichen"
#: app.py:263 #: app.py:303
msgid "" msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or " "Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'." "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 " "unpräzise Begriffe zu verwenden oder zu wiederholen, dass die App 'frei' und "
"'selbsthostbar' ist." "'selbsthostbar' ist."
#: app.py:267 #: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does." msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr "" msgstr ""
"Bitte wiederholen Sie den Namen der Anwendung nicht. Es geht darum, was die " "Bitte wiederholen Sie den Namen der Anwendung nicht. Es geht darum, was die "
"App tut." "App tut."
#: app.py:301 #: app.py:343
#, python-format #, python-format
msgid "" msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you " "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>, " "Sie können stattdessen der App <a href='%(url)s'>einen Stern hinzufügen</a>, "
"um Ihr Interesse zu zeigen." "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 #, python-format
msgid "" msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe " "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." "please report the issue to the YunoHost team."
msgstr "" msgstr ""
"Pull-Request zum Hinzufügen der App zur Wunschliste konnte nicht erstellt " "Pull-Request zum Hinzufügen der App zur Wunschliste konnte nicht erstellt "
"werden... Vielleicht gibt es bereits <a href='%(url)s'>einen wartenden PR " "werden… Vielleicht gibt es bereits <a href='%(url)s'>einen wartenden PR für "
"für diese App</a>? Andernfalls melden Sie das Problem bitte dem YunoHost-" "diese App</a>? Andernfalls melden Sie das Problem bitte dem YunoHost-Team."
"Team."
#: app.py:376 #: app.py:433
#, python-format #, python-format
msgid "" msgid ""
"Your proposed app has succesfully been submitted. It must now be validated " "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: " "YunoHost-Team validiert werden. Sie können den Fortschritt hier verfolgen: "
"<a href='%(url)s'>%(url)s</a>" "<a href='%(url)s'>%(url)s</a>"
#: app.py:449 #: app.py:528
msgid "Unfortunately, login was denied." msgid "Unfortunately, login was denied."
msgstr "Leider wurde die Anmeldung verweigert." msgstr "Leider wurde die Anmeldung verweigert."
@ -234,8 +248,10 @@ msgstr ""
msgid "Important infos before installing" msgid "Important infos before installing"
msgstr "Wichtige Informationen vor der Installation" msgstr "Wichtige Informationen vor der Installation"
# | msgid "Anti-features"
#: templates/app.html:124 #: templates/app.html:124
msgid "Anti-features" #, fuzzy
msgid "Antifeatures"
msgstr "Anti-Funktionen" msgstr "Anti-Funktionen"
#: templates/app.html:125 #: templates/app.html:125
@ -276,52 +292,69 @@ msgstr "YunoHost Paket-Repository"
msgid "YunoHost package license" msgid "YunoHost package license"
msgstr "YunoHost Paket-Lizenz" msgstr "YunoHost Paket-Lizenz"
#: templates/base.html:5 #: templates/base.html:11
msgid "YunoHost app store" msgid "YunoHost app store"
msgstr "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" msgid "Home"
msgstr "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" msgid "Catalog"
msgstr "Katalog" msgstr "Katalog"
#: templates/base.html:33 templates/base.html:131 #: templates/base.html:46 templates/base.html:172
msgid "Wishlist" msgid "Wishlist"
msgstr "Wunschliste" 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" msgid "YunoHost documentation"
msgstr "YunoHost-Dokumentation" 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" msgid "Login using YunoHost's forum"
msgstr "Login über YunoHost-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" msgid "Logout"
msgstr "Ausloggen" msgstr "Ausloggen"
#: templates/base.html:99 #: templates/base.html:140
msgid "Toggle menu" msgid "Toggle menu"
msgstr "Menu umschalten" msgstr "Menu umschalten"
#: templates/base.html:197 #: templates/base.html:255
msgid "" msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using " "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> " "<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</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>"
msgstr "" msgstr ""
"Hergestellt mit <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> " "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." "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'>Flask</a> und <a class='text-blue-800' href='https://tailwindcss."
"com/'>TailwindCSS</a> - <a class='text-blue-800' href='https://github.com/" "com/'>TailwindCSS</a>"
"YunoHost/apps/tree/master/store'><i class='fa fa-code fa-fw' aria-"
"hidden='true'></i> Source</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 #: templates/catalog.html:75 templates/catalog.html:80
msgid "Application Catalog" msgid "Application Catalog"
@ -339,7 +372,7 @@ msgstr "Suchen nach…"
msgid "All apps" msgid "All apps"
msgstr "Alle 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" msgid "Sort by"
msgstr "Sortieren nach" msgstr "Sortieren nach"
@ -352,16 +385,16 @@ msgstr "Popularität"
msgid "Newest" msgid "Newest"
msgstr "Neueste" msgstr "Neueste"
#: templates/catalog.html:125 templates/wishlist.html:46 #: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical" msgid "Alphabetical"
msgstr "Alphabetisch" 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" msgid "Requires to be logged-in"
msgstr "Erfordert eingeloggt zu sein" msgstr "Erfordert eingeloggt zu sein"
#: templates/catalog.html:130 templates/catalog.html:139 #: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/wishlist.html:51 templates/wishlist.html:60 #: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred" msgid "Show only apps you starred"
msgstr "Zeige nur meine Favoriten" 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." msgstr "Das sind Apps, welche die automatischen Tests nicht bestanden haben."
#: templates/catalog.html:184 #: templates/catalog.html:184
#, fuzzy
#| msgid "Browse all applications"
msgid "Deprecated applications" msgid "Deprecated applications"
msgstr "Alle Applikationen" msgstr "Veraltete Applikationen"
#: templates/catalog.html:187 #: templates/catalog.html:187
#, fuzzy
#| msgid "These are apps which failed our automatic tests."
msgid "These are apps who are not maintained anymore." 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 #: templates/catalog.html:188
msgid "" 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 "
"advise against their installation and advise users to find alternatives." "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 "" 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 #: templates/index.html:10
msgid "Application Store" msgid "Application Store"
@ -414,50 +643,10 @@ msgstr "Applikations-Store"
msgid "Browse all applications" msgid "Browse all applications"
msgstr "Alle Applikationen" 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 #: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app" msgid "Suggest an app"
msgstr "Eine App vorschlagen" 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 #: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog" msgid "Suggest an application to be added to YunoHost's catalog"
msgstr "" msgstr ""
@ -485,6 +674,10 @@ msgstr ""
"verschicken Sie nicht jedes beliebige nerdige Zeug, das Sie im Internet " "verschicken Sie nicht jedes beliebige nerdige Zeug, das Sie im Internet "
"finden." "finden."
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr "Name"
#: templates/wishlist_add.html:64 #: templates/wishlist_add.html:64
msgid "App's description" msgid "App's description"
msgstr "App Beschreibung" msgstr "App Beschreibung"
@ -537,3 +730,39 @@ msgstr ""
#: templates/wishlist_add.html:84 #: templates/wishlist_add.html:84
msgid "Submit" msgid "Submit"
msgstr "Einreichen" 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 "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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" "PO-Revision-Date: 2024-02-21 06:06+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: el <LL@li.org>\n" "Language-Team: el <LL@li.org>\n"
@ -18,15 +18,16 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:150 #: app.py:162
msgid "App %(app_id) not found" #, python-format
msgid "App %(app_id)s not found"
msgstr "" msgstr ""
#: app.py:152 #: app.py:165
msgid "You must be logged in to be able to star an app" msgid "You must be logged in to be able to star an app"
msgstr "" 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 "" msgid ""
"Note that, due to various abuses, we restricted login on the app store to " "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 " "'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts." "reading posts."
msgstr "" msgstr ""
#: app.py:195 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" msgid "You must be logged in to submit an app to the wishlist"
msgstr "" msgstr ""
#: app.py:207 #: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr ""
#: app.py:228 #: app.py:263
msgid "" msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. " "Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days." "Please try again in a few days."
msgstr "" msgstr ""
#: app.py:230 #: app.py:267
msgid "App name should be at least 3 characters" msgid "App name should be at least 3 characters"
msgstr "" msgstr ""
#: app.py:231 #: app.py:268
msgid "App name should be less than 30 characters" msgid "App name should be less than 30 characters"
msgstr "" msgstr ""
#: app.py:234 #: app.py:271
msgid "App description should be at least 5 characters" msgid "App description should be at least 5 characters"
msgstr "" msgstr ""
#: app.py:238 #: app.py:275
msgid "App description should be less than 100 characters" msgid "App description should be less than 100 characters"
msgstr "" msgstr ""
#: app.py:242 #: app.py:279
msgid "Upstream code repo URL should be at least 10 characters" msgid "Upstream code repo URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:246 #: app.py:283
msgid "Upstream code repo URL should be less than 150 characters" msgid "Upstream code repo URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:250 #: app.py:287
msgid "License URL should be at least 10 characters" msgid "License URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:254 #: app.py:291
msgid "License URL should be less than 250 characters" msgid "License URL should be less than 250 characters"
msgstr "" msgstr ""
#: app.py:256 #: app.py:293
msgid "Website URL should be less than 150 characters" msgid "Website URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:259 #: app.py:296
msgid "App name contains special characters" msgid "App name contains special characters"
msgstr "" msgstr ""
#: app.py:263 #: app.py:303
msgid "" msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or " "Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'." "repeating that the app is 'free' and 'self-hostable'."
msgstr "" msgstr ""
#: app.py:267 #: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does." msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr "" msgstr ""
#: app.py:301 #: app.py:343
#, python-format #, python-format
msgid "" msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you " "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>." "can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr "" 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 #, python-format
msgid "" msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe " "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." "please report the issue to the YunoHost team."
msgstr "" msgstr ""
#: app.py:376 #: app.py:433
#, python-format #, python-format
msgid "" msgid ""
"Your proposed app has succesfully been submitted. It must now be validated " "Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>" "%(url)s</a>"
msgstr "" msgstr ""
#: app.py:449 #: app.py:528
msgid "Unfortunately, login was denied." msgid "Unfortunately, login was denied."
msgstr "" msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr "" msgstr ""
#: templates/app.html:124 #: templates/app.html:124
msgid "Anti-features" msgid "Antifeatures"
msgstr "" msgstr ""
#: templates/app.html:125 #: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license" msgid "YunoHost package license"
msgstr "" msgstr ""
#: templates/base.html:5 #: templates/base.html:11
msgid "YunoHost app store" msgid "YunoHost app store"
msgstr "" 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" msgid "Home"
msgstr "" msgstr ""
#: templates/base.html:27 templates/base.html:122 #: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog" msgid "Catalog"
msgstr "" msgstr ""
#: templates/base.html:33 templates/base.html:131 #: templates/base.html:46 templates/base.html:172
msgid "Wishlist" msgid "Wishlist"
msgstr "" 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" msgid "YunoHost documentation"
msgstr "" msgstr ""
#: templates/base.html:54 templates/base.html:151 #: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum" msgid "Login using YunoHost's forum"
msgstr "" 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" msgid "Logout"
msgstr "" msgstr ""
#: templates/base.html:99 #: templates/base.html:140
msgid "Toggle menu" msgid "Toggle menu"
msgstr "" msgstr ""
#: templates/base.html:197 #: templates/base.html:255
msgid "" msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using " "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> " "<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</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/" msgstr ""
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr "" msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80 #: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps" msgid "All apps"
msgstr "" msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39 #: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by" msgid "Sort by"
msgstr "" msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest" msgid "Newest"
msgstr "" msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46 #: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical" msgid "Alphabetical"
msgstr "" 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" msgid "Requires to be logged-in"
msgstr "" msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139 #: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/wishlist.html:51 templates/wishlist.html:60 #: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred" msgid "Show only apps you starred"
msgstr "" msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188 #: templates/catalog.html:188
msgid "" 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 "
"advise against their installation and advise users to find alternatives." "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 "" msgstr ""
#: templates/index.html:10 #: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications" msgid "Browse all applications"
msgstr "" 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 #: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app" msgid "Suggest an app"
msgstr "" 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 #: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog" msgid "Suggest an application to be added to YunoHost's catalog"
msgstr "" msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet." "every random nerdy stuff you find on the Internet."
msgstr "" msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64 #: templates/wishlist_add.html:64
msgid "App's description" msgid "App's description"
msgstr "" msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84 #: templates/wishlist_add.html:84
msgid "Submit" msgid "Submit"
msgstr "" 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 "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\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" "PO-Revision-Date: 2024-02-21 06:06+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: eo <LL@li.org>\n" "Language-Team: eo <LL@li.org>\n"
@ -18,15 +18,16 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:150 #: app.py:162
msgid "App %(app_id) not found" #, python-format
msgid "App %(app_id)s not found"
msgstr "" msgstr ""
#: app.py:152 #: app.py:165
msgid "You must be logged in to be able to star an app" msgid "You must be logged in to be able to star an app"
msgstr "" 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 "" msgid ""
"Note that, due to various abuses, we restricted login on the app store to " "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 " "'trust level 1' users.<br/><br/>'Trust level 1' is obtained after "
@ -35,78 +36,85 @@ msgid ""
"reading posts." "reading posts."
msgstr "" msgstr ""
#: app.py:195 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" msgid "You must be logged in to submit an app to the wishlist"
msgstr "" msgstr ""
#: app.py:207 #: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr ""
#: app.py:228 #: app.py:263
msgid "" msgid ""
"Proposing wishlist additions is limited to once every 15 days per user. " "Proposing wishlist additions is limited to once every 15 days per user. "
"Please try again in a few days." "Please try again in a few days."
msgstr "" msgstr ""
#: app.py:230 #: app.py:267
msgid "App name should be at least 3 characters" msgid "App name should be at least 3 characters"
msgstr "" msgstr ""
#: app.py:231 #: app.py:268
msgid "App name should be less than 30 characters" msgid "App name should be less than 30 characters"
msgstr "" msgstr ""
#: app.py:234 #: app.py:271
msgid "App description should be at least 5 characters" msgid "App description should be at least 5 characters"
msgstr "" msgstr ""
#: app.py:238 #: app.py:275
msgid "App description should be less than 100 characters" msgid "App description should be less than 100 characters"
msgstr "" msgstr ""
#: app.py:242 #: app.py:279
msgid "Upstream code repo URL should be at least 10 characters" msgid "Upstream code repo URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:246 #: app.py:283
msgid "Upstream code repo URL should be less than 150 characters" msgid "Upstream code repo URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:250 #: app.py:287
msgid "License URL should be at least 10 characters" msgid "License URL should be at least 10 characters"
msgstr "" msgstr ""
#: app.py:254 #: app.py:291
msgid "License URL should be less than 250 characters" msgid "License URL should be less than 250 characters"
msgstr "" msgstr ""
#: app.py:256 #: app.py:293
msgid "Website URL should be less than 150 characters" msgid "Website URL should be less than 150 characters"
msgstr "" msgstr ""
#: app.py:259 #: app.py:296
msgid "App name contains special characters" msgid "App name contains special characters"
msgstr "" msgstr ""
#: app.py:263 #: app.py:303
msgid "" msgid ""
"Please focus on what the app does, without using marketing, fuzzy terms, or " "Please focus on what the app does, without using marketing, fuzzy terms, or "
"repeating that the app is 'free' and 'self-hostable'." "repeating that the app is 'free' and 'self-hostable'."
msgstr "" msgstr ""
#: app.py:267 #: app.py:313
msgid "No need to repeat the name of the app. Focus on what the app does." msgid "No need to repeat the name of the app. Focus on what the app does."
msgstr "" msgstr ""
#: app.py:301 #: app.py:343
#, python-format #, python-format
msgid "" msgid ""
"An entry with the name %(slug)s already exists in the wishlist, instead, you " "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>." "can <a href='%(url)s'>add a star to the app to show your interest</a>."
msgstr "" 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 #, python-format
msgid "" msgid ""
"Failed to create the pull request to add the app to the wishlist… Maybe " "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." "please report the issue to the YunoHost team."
msgstr "" msgstr ""
#: app.py:376 #: app.py:433
#, python-format #, python-format
msgid "" msgid ""
"Your proposed app has succesfully been submitted. It must now be validated " "Your proposed app has succesfully been submitted. It must now be validated "
@ -122,7 +130,7 @@ msgid ""
"%(url)s</a>" "%(url)s</a>"
msgstr "" msgstr ""
#: app.py:449 #: app.py:528
msgid "Unfortunately, login was denied." msgid "Unfortunately, login was denied."
msgstr "" msgstr ""
@ -195,7 +203,7 @@ msgid "Important infos before installing"
msgstr "" msgstr ""
#: templates/app.html:124 #: templates/app.html:124
msgid "Anti-features" msgid "Antifeatures"
msgstr "" msgstr ""
#: templates/app.html:125 #: templates/app.html:125
@ -235,45 +243,64 @@ msgstr ""
msgid "YunoHost package license" msgid "YunoHost package license"
msgstr "" msgstr ""
#: templates/base.html:5 #: templates/base.html:11
msgid "YunoHost app store" msgid "YunoHost app store"
msgstr "" 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" msgid "Home"
msgstr "" msgstr ""
#: templates/base.html:27 templates/base.html:122 #: templates/base.html:40 templates/base.html:163 templates/dash.html:66
msgid "Catalog" msgid "Catalog"
msgstr "" msgstr ""
#: templates/base.html:33 templates/base.html:131 #: templates/base.html:46 templates/base.html:172
msgid "Wishlist" msgid "Wishlist"
msgstr "" 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" msgid "YunoHost documentation"
msgstr "" msgstr ""
#: templates/base.html:54 templates/base.html:151 #: templates/base.html:79 templates/base.html:192
msgid "Login using YunoHost's forum" msgid "Login using YunoHost's forum"
msgstr "" 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" msgid "Logout"
msgstr "" msgstr ""
#: templates/base.html:99 #: templates/base.html:140
msgid "Toggle menu" msgid "Toggle menu"
msgstr "" msgstr ""
#: templates/base.html:197 #: templates/base.html:255
msgid "" msgid ""
"Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using " "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> " "<a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> "
"and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</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/" msgstr ""
"master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> Source</a>"
#: templates/base.html:256
msgid "Source"
msgstr ""
#: templates/base.html:257
msgid "Terms of Services"
msgstr "" msgstr ""
#: templates/catalog.html:75 templates/catalog.html:80 #: templates/catalog.html:75 templates/catalog.html:80
@ -292,7 +319,7 @@ msgstr ""
msgid "All apps" msgid "All apps"
msgstr "" msgstr ""
#: templates/catalog.html:117 templates/wishlist.html:39 #: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39
msgid "Sort by" msgid "Sort by"
msgstr "" msgstr ""
@ -305,16 +332,16 @@ msgstr ""
msgid "Newest" msgid "Newest"
msgstr "" msgstr ""
#: templates/catalog.html:125 templates/wishlist.html:46 #: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46
msgid "Alphabetical" msgid "Alphabetical"
msgstr "" 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" msgid "Requires to be logged-in"
msgstr "" msgstr ""
#: templates/catalog.html:130 templates/catalog.html:139 #: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49
#: templates/wishlist.html:51 templates/wishlist.html:60 #: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60
msgid "Show only apps you starred" msgid "Show only apps you starred"
msgstr "" msgstr ""
@ -348,8 +375,206 @@ msgstr ""
#: templates/catalog.html:188 #: templates/catalog.html:188
msgid "" 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 "
"advise against their installation and advise users to find alternatives." "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 "" msgstr ""
#: templates/index.html:10 #: templates/index.html:10
@ -360,44 +585,10 @@ msgstr ""
msgid "Browse all applications" msgid "Browse all applications"
msgstr "" 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 #: templates/wishlist.html:33 templates/wishlist_add.html:3
msgid "Suggest an app" msgid "Suggest an app"
msgstr "" 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 #: templates/wishlist_add.html:8
msgid "Suggest an application to be added to YunoHost's catalog" msgid "Suggest an application to be added to YunoHost's catalog"
msgstr "" msgstr ""
@ -416,6 +607,10 @@ msgid ""
"every random nerdy stuff you find on the Internet." "every random nerdy stuff you find on the Internet."
msgstr "" msgstr ""
#: templates/wishlist.html:71 templates/wishlist_add.html:61
msgid "Name"
msgstr ""
#: templates/wishlist_add.html:64 #: templates/wishlist_add.html:64
msgid "App's description" msgid "App's description"
msgstr "" msgstr ""
@ -459,3 +654,33 @@ msgstr ""
#: templates/wishlist_add.html:84 #: templates/wishlist_add.html:84
msgid "Submit" msgid "Submit"
msgstr "" 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