mirror of
https://github.com/YunoHost/apps.git
synced 2024-09-03 20:06:07 +02:00
v0.9.1 - add translations
This commit is contained in:
parent
3236111bfe
commit
7b22673200
1 changed files with 147 additions and 113 deletions
|
@ -35,6 +35,12 @@ from wtforms.validators import (
|
||||||
Length,
|
Length,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
from flask_babel import Babel
|
||||||
|
from flask_babel import gettext
|
||||||
|
|
||||||
|
from flask import redirect, request, make_response # Language swap by redirecting
|
||||||
|
|
||||||
# Markdown to HTML - for debugging purposes
|
# Markdown to HTML - for debugging purposes
|
||||||
from misaka import Markdown, HtmlRenderer
|
from misaka import Markdown, HtmlRenderer
|
||||||
|
|
||||||
|
@ -45,7 +51,7 @@ from urllib import parse
|
||||||
from secrets import token_urlsafe
|
from secrets import token_urlsafe
|
||||||
|
|
||||||
#### GLOBAL VARIABLES
|
#### GLOBAL VARIABLES
|
||||||
YOLOGEN_VERSION = "0.8.5"
|
YOLOGEN_VERSION = "0.9.1"
|
||||||
GENERATOR_DICT = {"GENERATOR_VERSION": YOLOGEN_VERSION}
|
GENERATOR_DICT = {"GENERATOR_VERSION": YOLOGEN_VERSION}
|
||||||
|
|
||||||
#### Create FLASK and Jinja Environments
|
#### Create FLASK and Jinja Environments
|
||||||
|
@ -56,6 +62,28 @@ cors = CORS(app)
|
||||||
|
|
||||||
environment = j2.Environment(loader=j2.FileSystemLoader("templates/"))
|
environment = j2.Environment(loader=j2.FileSystemLoader("templates/"))
|
||||||
|
|
||||||
|
# Handle translations
|
||||||
|
BABEL_TRANSLATION_DIRECTORIES='translations'
|
||||||
|
|
||||||
|
babel = Babel()
|
||||||
|
|
||||||
|
LANGUAGES = {
|
||||||
|
'en': 'English',
|
||||||
|
'fr': 'French'
|
||||||
|
}
|
||||||
|
|
||||||
|
def configure(app):
|
||||||
|
babel.init_app(app, locale_selector=get_locale)
|
||||||
|
app.config['LANGUAGES'] = LANGUAGES
|
||||||
|
def get_locale():
|
||||||
|
print(request.accept_languages.best_match(app.config['LANGUAGES'].keys()))
|
||||||
|
print(request.cookies.get('lang', 'en'))
|
||||||
|
#return 'en' # to test
|
||||||
|
#return 'fr'
|
||||||
|
return request.cookies.get('lang', 'en')
|
||||||
|
#return request.accept_languages.best_match(app.config['LANGUAGES'].keys()) # The result is based on the Accept-Language header. For testing purposes, you can directly return a language code, for example: return ‘de’
|
||||||
|
|
||||||
|
configure(app)
|
||||||
|
|
||||||
#### Custom functions
|
#### Custom functions
|
||||||
|
|
||||||
|
@ -88,9 +116,9 @@ class GeneralInfos(FlaskForm):
|
||||||
|
|
||||||
app_id = StringField(
|
app_id = StringField(
|
||||||
Markup(
|
Markup(
|
||||||
"Identifiant (id) de l'application"
|
gettext("Application identifier (id)")
|
||||||
),
|
),
|
||||||
description="En minuscule et sans espace.",
|
description=gettext("Small caps and without spaces"),
|
||||||
validators=[DataRequired(), Regexp("[a-z_1-9]+.*(?<!_ynh)$")],
|
validators=[DataRequired(), Regexp("[a-z_1-9]+.*(?<!_ynh)$")],
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "my_super_app",
|
"placeholder": "my_super_app",
|
||||||
|
@ -98,8 +126,8 @@ class GeneralInfos(FlaskForm):
|
||||||
)
|
)
|
||||||
|
|
||||||
app_name = StringField(
|
app_name = StringField(
|
||||||
"Nom de l'application",
|
gettext("App name"),
|
||||||
description="Il s'agit du nom l'application, affiché dans les interfaces utilisateur·ice·s",
|
description=gettext("It's the application name, displayed in the user interface"),
|
||||||
validators=[DataRequired()],
|
validators=[DataRequired()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "My super App",
|
"placeholder": "My super App",
|
||||||
|
@ -107,13 +135,13 @@ class GeneralInfos(FlaskForm):
|
||||||
)
|
)
|
||||||
|
|
||||||
description_en = StringField(
|
description_en = StringField(
|
||||||
"Description courte (en)",
|
gettext("Short description (en)"),
|
||||||
description="Expliquez en *quelques* (10~15) mots l'utilité de l'app ou ce qu'elle fait (l'objectif est de donner une idée grossière pour des utilisateurs qui naviguent dans un catalogue de 100+ apps)",
|
description=gettext("Explain in a few words (10-15) why this app is useful or what it does (the goal is to give a broad idea for the user browsing an hundred apps long catalog"),
|
||||||
validators=[DataRequired()],
|
validators=[DataRequired()],
|
||||||
)
|
)
|
||||||
description_fr = StringField(
|
description_fr = StringField(
|
||||||
"Description courte (fr)",
|
gettext("Description courte (fr)"),
|
||||||
description="Expliquez en *quelques* (10~15) mots l'utilité de l'app ou ce qu'elle fait (l'objectif est de donner une idée grossière pour des utilisateurs qui naviguent dans un catalogue de 100+ apps)",
|
description="Explain in a few words (10-15) why this app is useful or what it does (the goal is to give a broad idea for the user browsing an hundred apps long catalog",
|
||||||
validators=[DataRequired()],
|
validators=[DataRequired()],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -128,22 +156,22 @@ class IntegrationInfos(FlaskForm):
|
||||||
)
|
)
|
||||||
|
|
||||||
maintainers = StringField(
|
maintainers = StringField(
|
||||||
"Mainteneur·euse de l'app YunoHost créée",
|
gettext("Maintener of the generated app"),
|
||||||
description="Généralement vous mettez votre nom ici… Si vous êtes d'accord ;)"
|
description=gettext("Commonly you put your name here... If you agree with it ;)")
|
||||||
)
|
)
|
||||||
|
|
||||||
yunohost_required_version = StringField(
|
yunohost_required_version = StringField(
|
||||||
"Minimum YunoHost version",
|
gettext("Minimal YunoHost version"),
|
||||||
description="Version minimale de Yunohost pour que l'application fonctionne.",
|
description=gettext("Minimal YunoHost version for the application to work"),
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "11.1.21",
|
"placeholder": "11.1.21",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
architectures = SelectMultipleField(
|
architectures = SelectMultipleField(
|
||||||
"Architectures supportées",
|
gettext("Supported architectures"),
|
||||||
choices=[
|
choices=[
|
||||||
("all", "Toutes les architectures"),
|
("all", gettext("All architectures")),
|
||||||
("amd64", "amd64"),
|
("amd64", "amd64"),
|
||||||
("i386", "i386"),
|
("i386", "i386"),
|
||||||
("armhf", "armhf"),
|
("armhf", "armhf"),
|
||||||
|
@ -154,28 +182,28 @@ class IntegrationInfos(FlaskForm):
|
||||||
)
|
)
|
||||||
|
|
||||||
multi_instance = BooleanField(
|
multi_instance = BooleanField(
|
||||||
"L'app pourra être installée simultannément plusieurs fois sur la même machine",
|
gettext("The app can be installed multiple times at the same time on the same server"),
|
||||||
default=True,
|
default=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
ldap = SelectField(
|
ldap = SelectField(
|
||||||
"L'app s'intègrera avec le LDAP",
|
gettext("The app will be integrating LDAP"),
|
||||||
description="c-à-d pouvoir se connecter en utilisant ses identifiants YunoHost. 'LDAP' corresponds à la technologie utilisée par YunoHost comme base de compte utilisateurs centralisée. L'interface entre l'app et le LDAP de YunoHost nécessite le plus souvent de remplir des paramètres dans la configuration de l'app (voir plus tard)",
|
description=gettext("Which means it's possible to use Yunohost credential to connect. 'LDAP' corresponds to the technology used by Yunohost to handle a centralised user base. Bridging the APP and Yunohost LDAP often requires to fill some parameters in the app configuration"),
|
||||||
choices=[
|
choices=[
|
||||||
("false", "No"),
|
("false", gettext("No")),
|
||||||
("true", "Yes"),
|
("true", gettext("Yes")),
|
||||||
("not_relevant", "Not relevant"),
|
("not_relevant", gettext("Not relevant")),
|
||||||
],
|
],
|
||||||
default="not_relevant",
|
default="not_relevant",
|
||||||
validators=[DataRequired()],
|
validators=[DataRequired()],
|
||||||
)
|
)
|
||||||
sso = SelectField(
|
sso = SelectField(
|
||||||
"L'app s'intègrera avec le SSO (Single Sign On) de YunoHost",
|
gettext("The app will be integrated in Yunohost SSO (Single Sign On)"),
|
||||||
description="c-à-d être connecté automatiquement à l'app si connecté au portail YunoHost. Le SSO de YunoHost se base sur le principe du 'Basic HTTP auth header', c'est à vous de vérifier si l'application supporte ce mécanisme de SSO.",
|
description=gettext("Which means that one connexion to Yunohost unlock the connexion to the software, without having to sign on specificaly into it. One only has to connect once (Single Sign On)"),
|
||||||
choices=[
|
choices=[
|
||||||
("false", "Yes"),
|
("false", gettext("Yes")),
|
||||||
("true", "No"),
|
("true", gettext("No")),
|
||||||
("not_relevant", "Not relevant"),
|
("not_relevant", gettext("Not relevant")),
|
||||||
],
|
],
|
||||||
default="not_relevant",
|
default="not_relevant",
|
||||||
validators=[DataRequired()],
|
validators=[DataRequired()],
|
||||||
|
@ -185,45 +213,45 @@ class IntegrationInfos(FlaskForm):
|
||||||
class UpstreamInfos(FlaskForm):
|
class UpstreamInfos(FlaskForm):
|
||||||
|
|
||||||
license = StringField(
|
license = StringField(
|
||||||
"Licence",
|
gettext("Licence"),
|
||||||
description="You should check this on the upstream repository. The expected format is a SPDX id listed in https://spdx.org/licenses/",
|
description=gettext("You should check this on the upstream repository. The expected format is a SPDX id listed in https://spdx.org/licenses/"),
|
||||||
validators=[DataRequired()],
|
validators=[DataRequired()],
|
||||||
)
|
)
|
||||||
|
|
||||||
website = StringField(
|
website = StringField(
|
||||||
"Site web officiel",
|
gettext("Official website"),
|
||||||
description="Leave empty if there is no official website",
|
description=gettext("Leave empty if there is no official website"),
|
||||||
validators=[URL(), Optional()],
|
validators=[URL(), Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "https://awesome-app-website.com",
|
"placeholder": "https://awesome-app-website.com",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
demo = StringField(
|
demo = StringField(
|
||||||
"Démo officielle de l'app",
|
gettext("Official app demo"),
|
||||||
description="Leave empty if there is no official demo",
|
description=gettext("Leave empty if there is no official demo"),
|
||||||
validators=[URL(), Optional()],
|
validators=[URL(), Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "https://awesome-app-website.com/demo",
|
"placeholder": "https://awesome-app-website.com/demo",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
admindoc = StringField(
|
admindoc = StringField(
|
||||||
"Documentation d'aministration",
|
gettext("Admin documentation"),
|
||||||
description="Leave empty if there is no official admin doc",
|
description=gettext("Leave empty if there is no official admin doc"),
|
||||||
validators=[URL(), Optional()],
|
validators=[URL(), Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "https://awesome-app-website.com/doc/admin",
|
"placeholder": "https://awesome-app-website.com/doc/admin",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
userdoc = StringField(
|
userdoc = StringField(
|
||||||
"Documentation d'utilisation",
|
gettext("Usage documentation"),
|
||||||
description="Leave empty if there is no official user doc",
|
description=gettext("Leave empty if there is no official user doc"),
|
||||||
validators=[URL(), Optional()],
|
validators=[URL(), Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "https://awesome-app-website.com/doc/user",
|
"placeholder": "https://awesome-app-website.com/doc/user",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
code = StringField(
|
code = StringField(
|
||||||
"Dépôt de code",
|
gettext("Code repository"),
|
||||||
validators=[URL(), DataRequired()],
|
validators=[URL(), DataRequired()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "https://some.git.forge/org/app",
|
"placeholder": "https://some.git.forge/org/app",
|
||||||
|
@ -233,42 +261,42 @@ class UpstreamInfos(FlaskForm):
|
||||||
class InstallQuestions(FlaskForm):
|
class InstallQuestions(FlaskForm):
|
||||||
|
|
||||||
domain_and_path = SelectField(
|
domain_and_path = SelectField(
|
||||||
"Demander l'URL sur laquelle sera installée l'app (variables 'domain' et 'path')",
|
gettext("Ask the URL where the app will be installed ('domain' and 'path' variables)"),
|
||||||
default="true",
|
default="true",
|
||||||
choices=[
|
choices=[
|
||||||
("true", "Demander le domaine+path"),
|
("true", gettext("Ask domain+path")),
|
||||||
("full_domain", "Demander le domaine uniquement (l'app nécessite d'être installée à la racine d'un domaine dédié à cette app)"),
|
("full_domain", gettext("Ask only the domain (the app requires to be installed at the root of a dedicated domain)")),
|
||||||
("false", "Ne pas demander (l'app n'est pas une webapp)")
|
("false", gettext("Do not ask (it isn't a webapp)"))
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
init_main_permission = BooleanField(
|
init_main_permission = BooleanField(
|
||||||
"Demander qui pourra accéder à l'app",
|
gettext("Ask who can access to the app"),
|
||||||
description="Parmis les groupes d'utilisateurs : par défaut au moins 'visitors', 'all_users' et 'admins' existent. (Corresponds anciennement à la notion d'app privée/publique)",
|
description=gettext("In the users groups : by default at least 'visitors', 'all_users' et 'admins' exists. (It was previously the private/public app concept)"),
|
||||||
default=True,
|
default=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
init_admin_permission = BooleanField(
|
init_admin_permission = BooleanField(
|
||||||
"Demander qui pourra accéder à l'interface d'admin",
|
gettext("Ask who can access to the admin interface"),
|
||||||
description="Ceci est suppose apriori que l'app dispose d'une interface d'admin",
|
description=gettext("In the case where the app has an admin interface"),
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
language = SelectMultipleField(
|
language = SelectMultipleField(
|
||||||
"Langues supportées",
|
gettext("Supported languages"),
|
||||||
choices=[
|
choices=[
|
||||||
("_", "None / not relevant"),
|
("_", gettext("None / not relevant")),
|
||||||
("en", "English"),
|
("en", gettext("English")),
|
||||||
("fr", "Français"),
|
("fr", gettext("Français")),
|
||||||
("en", "Spanish"),
|
("en", gettext("Spanish")),
|
||||||
("it", "Italian"),
|
("it", gettext("Italian")),
|
||||||
("de", "German"),
|
("de", gettext("German")),
|
||||||
("zh", "Chinese"),
|
("zh", gettext("Chinese")),
|
||||||
("jp", "Japanese"),
|
("jp", gettext("Japanese")),
|
||||||
("da", "Danish"),
|
("da", gettext("Danish")),
|
||||||
("pt", "Portugese"),
|
("pt", gettext("Portugese")),
|
||||||
("nl", "Dutch"),
|
("nl", gettext("Dutch")),
|
||||||
("ru", "Russian"),
|
("ru", gettext("Russian")),
|
||||||
],
|
],
|
||||||
default=["_"],
|
default=["_"],
|
||||||
validators=[DataRequired()],
|
validators=[DataRequired()],
|
||||||
|
@ -282,14 +310,14 @@ class Resources(FlaskForm):
|
||||||
|
|
||||||
# Sources
|
# Sources
|
||||||
source_url = StringField(
|
source_url = StringField(
|
||||||
"Code source ou exécutable de l'application",
|
gettext("Application source code or executable"),
|
||||||
validators=[DataRequired(), URL()],
|
validators=[DataRequired(), URL()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "https://github.com/foo/bar/archive/refs/tags/v1.2.3.tar.gz",
|
"placeholder": "https://github.com/foo/bar/archive/refs/tags/v1.2.3.tar.gz",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
sha256sum = StringField(
|
sha256sum = StringField(
|
||||||
"Checksum sha256 des sources",
|
gettext("Sources sha256 checksum"),
|
||||||
validators=[DataRequired(), Length(min=64, max=64)],
|
validators=[DataRequired(), Length(min=64, max=64)],
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
"placeholder": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||||
|
@ -297,8 +325,8 @@ class Resources(FlaskForm):
|
||||||
)
|
)
|
||||||
|
|
||||||
auto_update = SelectField(
|
auto_update = SelectField(
|
||||||
"Activer le robot de mise à jour automatique des sources",
|
gettext("Activate the automated source update bot"),
|
||||||
description="Si le logiciel est disponible sur une des sources prises en charge et publie des releases ou des tags pour ses nouvelles versions, ou pour chaque nouveau commits, un robot proposera automatiquement des mises à jour de l'url et de la checksum.",
|
description=gettext("If the software is available in one of the handled sources and publish releases or tags for its new updates, or for each new commit, a bot will provide an update with updated URL and checksum"),
|
||||||
default="none",
|
default="none",
|
||||||
choices=[
|
choices=[
|
||||||
("none", "Non"),
|
("none", "Non"),
|
||||||
|
@ -318,14 +346,14 @@ class Resources(FlaskForm):
|
||||||
)
|
)
|
||||||
|
|
||||||
apt_dependencies = StringField(
|
apt_dependencies = StringField(
|
||||||
"Dépendances à installer via apt (séparées par des virgules et/ou espaces)",
|
gettext("Dependances to be installed via apt (separated by a quote and/or spaces)"),
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "foo, bar2.1-ext, libwat",
|
"placeholder": "foo, bar2.1-ext, libwat",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
database = SelectField(
|
database = SelectField(
|
||||||
"Initialiser une base de données SQL",
|
gettext("Initialise a SQL database"),
|
||||||
choices=[
|
choices=[
|
||||||
("false", "Non"),
|
("false", "Non"),
|
||||||
("mysql", "MySQL/MariaDB"),
|
("mysql", "MySQL/MariaDB"),
|
||||||
|
@ -335,19 +363,19 @@ class Resources(FlaskForm):
|
||||||
)
|
)
|
||||||
|
|
||||||
system_user = BooleanField(
|
system_user = BooleanField(
|
||||||
"Initialiser un utilisateur système pour cet app",
|
gettext("Initialise a system user for this app"),
|
||||||
default=True,
|
default=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
install_dir = BooleanField(
|
install_dir = BooleanField(
|
||||||
"Initialiser un dossier d'installation de l'app",
|
gettext("Initialise an installation folder for this app"),
|
||||||
description="Par défaut il s'agit de /var/www/$app",
|
description=gettext("By default it's /var/www/$app"),
|
||||||
default=True,
|
default=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
data_dir = BooleanField(
|
data_dir = BooleanField(
|
||||||
"Initialiser un dossier destiné à stocker les données de l'app",
|
gettext("Initialise a folder to store the app data"),
|
||||||
description="Par défaut il s'agit de /home/yunohost.app/$app",
|
description=gettext("By default it's /var/yunohost.app/$app"),
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -355,22 +383,22 @@ class Resources(FlaskForm):
|
||||||
class SpecificTechnology(FlaskForm):
|
class SpecificTechnology(FlaskForm):
|
||||||
|
|
||||||
main_technology = SelectField(
|
main_technology = SelectField(
|
||||||
"Technologie principale de l'app",
|
gettext("App main technology"),
|
||||||
choices=[
|
choices=[
|
||||||
("none", "None / Static"),
|
("none", gettext("None / Static application")),
|
||||||
("php", "PHP"),
|
("php", "PHP"),
|
||||||
("nodejs", "NodeJS"),
|
("nodejs", "NodeJS"),
|
||||||
("python", "Python"),
|
("python", "Python"),
|
||||||
("ruby", "Ruby"),
|
("ruby", "Ruby"),
|
||||||
("other", "Other"),
|
("other", gettext("Other")),
|
||||||
],
|
],
|
||||||
default="none",
|
default="none",
|
||||||
validators=[DataRequired()],
|
validators=[DataRequired()],
|
||||||
)
|
)
|
||||||
|
|
||||||
install_snippet = TextAreaField(
|
install_snippet = TextAreaField(
|
||||||
"Commandes spécifiques d'installation",
|
gettext("Installation specific commands"),
|
||||||
description="Ces commandes seront éxécutées depuis le répertoire d'installation de l'app (par défaut, /var/www/$app) après que les sources aient été déployées. Le champ est pré-rempli avec un exemple classique basé sur la technologie sélectionnée. Vous devriez sans-doute le comparer et l'adapter en fonction de la doc d'installation de l'app.",
|
description=gettext("These commands are executed from the app installation folder (by default, /var/www/$app) after the sources have been deployed. This field uses by default a classic example based on the selected technology. You should probably compare and adapt it according to the app installation documentation"),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"spellcheck": "false"
|
"spellcheck": "false"
|
||||||
|
@ -382,8 +410,8 @@ class SpecificTechnology(FlaskForm):
|
||||||
#
|
#
|
||||||
|
|
||||||
use_composer = BooleanField(
|
use_composer = BooleanField(
|
||||||
"Utiliser composer",
|
gettext("Use composer"),
|
||||||
description="Composer est un gestionnaire de dépendance PHP utilisé par certaines apps",
|
description=gettext("Composer is a PHP dependencies manager used by some apps"),
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -392,23 +420,23 @@ class SpecificTechnology(FlaskForm):
|
||||||
#
|
#
|
||||||
|
|
||||||
nodejs_version = StringField(
|
nodejs_version = StringField(
|
||||||
"Version de NodeJS",
|
gettext("NodeJS version"),
|
||||||
description="For example: 16.4, 18, 18.2, 20, 20.1, ...",
|
description=gettext("For example: 16.4, 18, 18.2, 20, 20.1, ..."),
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "20",
|
"placeholder": "20",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
use_yarn = BooleanField(
|
use_yarn = BooleanField(
|
||||||
"Installer et utiliser Yarn",
|
gettext("Install and use Yarn"),
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
# NodeJS / Python / Ruby / ...
|
# NodeJS / Python / Ruby / ...
|
||||||
|
|
||||||
systemd_execstart = StringField(
|
systemd_execstart = StringField(
|
||||||
"Commande pour lancer le daemon de l'app (depuis le service systemd)",
|
gettext("Command to start the app daemon (from systemd service)"),
|
||||||
description="Corresponds to 'ExecStart' statement in systemd. You can use '__INSTALL_DIR__' to refer to the install directory, or '__APP__' to refer to the app id",
|
description=gettext("Corresponds to 'ExecStart' statement in systemd. You can use '__INSTALL_DIR__' to refer to the install directory, or '__APP__' to refer to the app id"),
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "__INSTALL_DIR__/bin/app --some-option",
|
"placeholder": "__INSTALL_DIR__/bin/app --some-option",
|
||||||
},
|
},
|
||||||
|
@ -418,13 +446,13 @@ class SpecificTechnology(FlaskForm):
|
||||||
class AppConfig(FlaskForm):
|
class AppConfig(FlaskForm):
|
||||||
|
|
||||||
use_custom_config_file = BooleanField(
|
use_custom_config_file = BooleanField(
|
||||||
"L'app utilise un fichier de configuration spécifique",
|
gettext("The app uses a specific configuration file"),
|
||||||
description="Typiquement : .env, config.json, conf.ini, params.yml, ...",
|
description=gettext("Usually : .env, config.json, conf.ini, params.yml, ..."),
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
custom_config_file = StringField(
|
custom_config_file = StringField(
|
||||||
"Nom ou chemin du fichier à utiliser",
|
gettext("Name or file path to use"),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "config.json",
|
"placeholder": "config.json",
|
||||||
|
@ -432,8 +460,8 @@ class AppConfig(FlaskForm):
|
||||||
)
|
)
|
||||||
|
|
||||||
custom_config_file_content = TextAreaField(
|
custom_config_file_content = TextAreaField(
|
||||||
"Modèle de fichier de configuration de l'app",
|
gettext("App configuration file pattern"),
|
||||||
description="Dans ce modèle, vous pouvez utilisez la syntaxe __FOO_BAR__ qui sera automatiquement remplacé par la valeur de la variable $foo_bar",
|
description=gettext("In this pattern, you can use the syntax __FOO_BAR__ which will automatically replaced by the value of the variable $foo_bar"),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"spellcheck": "false"
|
"spellcheck": "false"
|
||||||
|
@ -443,8 +471,8 @@ class AppConfig(FlaskForm):
|
||||||
class Documentation(FlaskForm):
|
class Documentation(FlaskForm):
|
||||||
# TODO : # screenshot
|
# TODO : # screenshot
|
||||||
description = TextAreaField(
|
description = TextAreaField(
|
||||||
Markup('''Saisissez le contenu du fichier DESCRIPTION.md. <br> \
|
Markup(gettext('''Type the content of DESCRIPTION.md file. <br> \
|
||||||
N'indiquez pas de titre du logiciel au début, car ce sera intégré dans une sous-partie "Overview" '''),
|
Do not give the software name at the beginning, as it will be integrated an 'Overview' subpart''')),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"class": "form-control",
|
"class": "form-control",
|
||||||
|
@ -452,7 +480,7 @@ class Documentation(FlaskForm):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
disclaimer = TextAreaField(
|
disclaimer = TextAreaField(
|
||||||
"Saisissez le contenu du fichier DISCLAIMER.md, qui liste des avertissements et points d'attention.",
|
gettext("Type the DISCLAIMER.md file content, which list warnings and attention points."),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"class": "form-control",
|
"class": "form-control",
|
||||||
|
@ -460,7 +488,7 @@ class Documentation(FlaskForm):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
pre_install = TextAreaField(
|
pre_install = TextAreaField(
|
||||||
"Saisissez le contenu du fichier PRE_INSTALL.md",
|
gettext("Type the PRE_INSTALL.md file content"),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"class": "form-control",
|
"class": "form-control",
|
||||||
|
@ -468,7 +496,7 @@ class Documentation(FlaskForm):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
post_install = TextAreaField(
|
post_install = TextAreaField(
|
||||||
"Saisissez le contenu du fichier POST_INSTALL.md",
|
gettext("Type the POST_INSTALL.md file content"),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"class": "form-control",
|
"class": "form-control",
|
||||||
|
@ -476,7 +504,7 @@ class Documentation(FlaskForm):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
pre_upgrade = TextAreaField(
|
pre_upgrade = TextAreaField(
|
||||||
"Saisissez le contenu du fichier PRE_UPGRADE.md",
|
gettext("Type the PRE_UPGRADE.md file content"),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"class": "form-control",
|
"class": "form-control",
|
||||||
|
@ -484,7 +512,7 @@ class Documentation(FlaskForm):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
post_upgrade = TextAreaField(
|
post_upgrade = TextAreaField(
|
||||||
"Saisissez le contenu du fichier POST_UPGRADE.md",
|
gettext("Type the POST_UPGRADE.md file content"),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"class": "form-control",
|
"class": "form-control",
|
||||||
|
@ -492,7 +520,7 @@ class Documentation(FlaskForm):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
admin = TextAreaField(
|
admin = TextAreaField(
|
||||||
"Saisissez le contenu du fichier ADMIN.md",
|
gettext("Type the ADMIN.md file content"),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"class": "form-control",
|
"class": "form-control",
|
||||||
|
@ -503,36 +531,36 @@ class Documentation(FlaskForm):
|
||||||
class MoreAdvanced(FlaskForm):
|
class MoreAdvanced(FlaskForm):
|
||||||
|
|
||||||
enable_change_url = BooleanField(
|
enable_change_url = BooleanField(
|
||||||
"Gérer le changement d'URL d'installation (script change_url)",
|
gettext("Handle app install URL change (change_url script)"),
|
||||||
default=True,
|
default=True,
|
||||||
render_kw={
|
render_kw={
|
||||||
"title": "Faut-il permettre le changement d'URL pour l'application ? (fichier change_url)"
|
"title": gettext("Should changing the app URL be allowed ? (change_url change)")
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
use_logrotate = BooleanField(
|
use_logrotate = BooleanField(
|
||||||
"Utiliser logrotate pour les journaux de l'app",
|
gettext("Use logrotate for the app logs"),
|
||||||
default=True,
|
default=True,
|
||||||
render_kw={
|
render_kw={
|
||||||
"title": "Si l'application genère des journaux (log), cette option permet d'en gérer l'archivage. Recommandé."
|
"title": gettext("If the app generates logs, this option permit to handle their archival. Recommended.")
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
# TODO : specify custom log file
|
# TODO : specify custom log file
|
||||||
# custom_log_file = "/var/log/$app/$app.log" "/var/log/nginx/${domain}-error.log"
|
# custom_log_file = "/var/log/$app/$app.log" "/var/log/nginx/${domain}-error.log"
|
||||||
use_fail2ban = BooleanField(
|
use_fail2ban = BooleanField(
|
||||||
"Protéger l'application des attaques par force brute (via fail2ban)",
|
gettext("Protect the application against brute force attacks (via fail2ban)"),
|
||||||
default=False,
|
default=False,
|
||||||
render_kw={
|
render_kw={
|
||||||
"title": "Si l'application genère des journaux (log) d'erreurs de connexion, cette option permet de bannir automatiquement les IP au bout d'un certain nombre d'essais de mot de passe. Recommandé."
|
"title": gettext("If the app generates failed connexions logs, this option allows to automatically banish the related IP after a certain number of failed password tries. Recommended.")
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
use_cron = BooleanField(
|
use_cron = BooleanField(
|
||||||
"Ajouter une tâche CRON pour cette application",
|
gettext("Add a CRON task for this application"),
|
||||||
description="Corresponds à des opérations périodiques de l'application",
|
description=gettext("Corresponds to some app periodic operations"),
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
cron_config_file = TextAreaField(
|
cron_config_file = TextAreaField(
|
||||||
"Saisissez le contenu du fichier CRON",
|
gettext("Type the CRON file content"),
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"class": "form-control",
|
"class": "form-control",
|
||||||
|
@ -541,13 +569,13 @@ class MoreAdvanced(FlaskForm):
|
||||||
)
|
)
|
||||||
|
|
||||||
fail2ban_regex = StringField(
|
fail2ban_regex = StringField(
|
||||||
"Expression régulière pour fail2ban",
|
gettext("Regular expression for fail2ban"),
|
||||||
# Regex to match into the log for a failed login
|
# Regex to match into the log for a failed login
|
||||||
validators=[Optional()],
|
validators=[Optional()],
|
||||||
render_kw={
|
render_kw={
|
||||||
"placeholder": "A regular expression",
|
"placeholder": gettext("A regular expression"),
|
||||||
"class": "form-control",
|
"class": "form-control",
|
||||||
"title": "Expression régulière à vérifier dans le journal pour que fail2ban s'active (cherchez une ligne qui indique une erreur d'identifiants deconnexion).",
|
"title": gettext("Regular expression to check in the log file to activate failban (search for a line that indicates a credentials error)."),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -561,17 +589,17 @@ class GeneratorForm(
|
||||||
csrf = False
|
csrf = False
|
||||||
|
|
||||||
generator_mode = SelectField(
|
generator_mode = SelectField(
|
||||||
"Mode du générateur",
|
gettext("Generator mode"),
|
||||||
description="En mode tutoriel, l'application générée contiendra des commentaires additionnels pour faciliter la compréhension. En version épurée, l'application générée ne contiendra que le minimum nécessaire.",
|
description=gettext("In tutorial version, the generated app will contain additionnal comments to ease the understanding. In steamlined version, the generated app will only contain the necessary minimum."),
|
||||||
choices=[("simple", "Version épurée"), ("tutorial", "Version tutoriel")],
|
choices=[("simple", gettext("Streamlined version")), ("tutorial", gettext("Tutorial version"))],
|
||||||
default="true",
|
default="true",
|
||||||
validators=[DataRequired()],
|
validators=[DataRequired()],
|
||||||
)
|
)
|
||||||
|
|
||||||
submit_preview = SubmitField("Prévisualiser")
|
submit_preview = SubmitField(gettext("Previsualise"))
|
||||||
submit_download = SubmitField("Télécharger le .zip")
|
submit_download = SubmitField(gettext("Download the .zip"))
|
||||||
submit_demo = SubmitField('Remplir avec des valeurs de démonstration', render_kw={"onclick": "fillFormWithDefaultValues()",
|
submit_demo = SubmitField(gettext('Fill with demo values'), render_kw={"onclick": "fillFormWithDefaultValues()",
|
||||||
"title": "Générer une application minimaliste complète et fonctionnelle à partir de laquelle itérer"
|
"title": gettext("Generate a complete and functionnal minimalistic app that you can iterate from")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -679,6 +707,12 @@ def main_form_route():
|
||||||
"index.html", main_form=main_form, generator_info=GENERATOR_DICT, generated_files=app_files,
|
"index.html", main_form=main_form, generator_info=GENERATOR_DICT, generated_files=app_files,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Localisation
|
||||||
|
@app.route('/language/<language>')
|
||||||
|
def set_language(language=None):
|
||||||
|
response = make_response(redirect(request.referrer or '/'))
|
||||||
|
response.set_cookie('lang', language)
|
||||||
|
return response
|
||||||
|
|
||||||
#### Running the web server
|
#### Running the web server
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Add table
Reference in a new issue