Re named src folder
This commit is contained in:
parent
60d5c84042
commit
ee353d35e8
17
app/main.py
17
app/main.py
@ -1,17 +0,0 @@
|
||||
from flask import Flask, render_template
|
||||
|
||||
app = Flask(
|
||||
__name__,
|
||||
template_folder="templates",
|
||||
static_folder="resources",
|
||||
static_url_path="/resources",
|
||||
)
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
return render_template("index.html")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True)
|
||||
@ -6,4 +6,5 @@ readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"flask>=3.1.3",
|
||||
"uvicorn>=0.47.0",
|
||||
]
|
||||
|
||||
13
src/i18n.py
Normal file
13
src/i18n.py
Normal file
@ -0,0 +1,13 @@
|
||||
from translations import en_strings, it_strings
|
||||
|
||||
_LANGUAGES: dict[str, dict] = {
|
||||
"it": it_strings,
|
||||
"en": en_strings,
|
||||
}
|
||||
|
||||
DEFAULT_LANG = "it"
|
||||
SUPPORTED_LANGS = list(_LANGUAGES.keys())
|
||||
|
||||
|
||||
def get_translations(lang_code: str) -> dict:
|
||||
return _LANGUAGES.get(lang_code, _LANGUAGES[DEFAULT_LANG])
|
||||
22
src/main.py
Normal file
22
src/main.py
Normal file
@ -0,0 +1,22 @@
|
||||
from flask import Flask, render_template, request
|
||||
from src.i18n import get_translations, SUPPORTED_LANGS
|
||||
|
||||
app = Flask(
|
||||
__name__,
|
||||
template_folder="templates",
|
||||
static_folder="resources",
|
||||
static_url_path="/resources",
|
||||
)
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
lang = request.args.get("lang", "it")
|
||||
if lang not in SUPPORTED_LANGS:
|
||||
lang = "it"
|
||||
t = get_translations(lang)
|
||||
return render_template("index.html", t=t, lang=lang, supported_langs=SUPPORTED_LANGS)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=False)
|
||||
@ -4,6 +4,39 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.lang-switcher {
|
||||
position: fixed;
|
||||
top: 0.75rem;
|
||||
right: 1rem;
|
||||
display: flex;
|
||||
gap: 0.4rem;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.lang-btn {
|
||||
padding: 0.25rem 0.6rem;
|
||||
border-radius: 4px;
|
||||
font-family: inherit;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.05em;
|
||||
text-decoration: none;
|
||||
background: rgba(255, 248, 220, 0.75);
|
||||
color: #3b2a0e;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
.lang-btn:hover {
|
||||
background: rgba(255, 248, 220, 0.95);
|
||||
}
|
||||
|
||||
.lang-btn--active {
|
||||
background: rgba(107, 90, 42, 0.85);
|
||||
color: #fdf5e0;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
|
Before Width: | Height: | Size: 534 KiB After Width: | Height: | Size: 534 KiB |
0
src/resources/videos/.gitkeep
Normal file
0
src/resources/videos/.gitkeep
Normal file
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<html lang="{{ lang }}">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
@ -10,33 +10,43 @@
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}" />
|
||||
</head>
|
||||
<body>
|
||||
<nav class="lang-switcher">
|
||||
{% for code in supported_langs %}
|
||||
{% if code == lang %}
|
||||
<span class="lang-btn lang-btn--active">{{ code.upper() }}</span>
|
||||
{% else %}
|
||||
<a class="lang-btn" href="/?lang={{ code }}">{{ code.upper() }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</nav>
|
||||
|
||||
<header>
|
||||
<h1>3a sviluppi agro-tech</h1>
|
||||
<h2>Innovazione digitale per l'agricoltura</h2>
|
||||
<h2>{{ t.subtitle }}</h2>
|
||||
</header>
|
||||
|
||||
<div class="cards-row">
|
||||
<div class="action-card" data-action="video" data-src="/resources/videos/video1.mp4">
|
||||
<div class="card-icon"></div>
|
||||
<h3 class="card-title">Quaderno di campagna digitale</h3>
|
||||
<p class="card-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vehicula arcu vel ligula fermentum.</p>
|
||||
<h3 class="card-title">{{ t.card1_title }}</h3>
|
||||
<p class="card-text">{{ t.card1_text }}</p>
|
||||
</div>
|
||||
<div class="action-card" data-action="video" data-src="/resources/videos/video2.mp4">
|
||||
<div class="card-icon"></div>
|
||||
<h3 class="card-title">Assistente virtuale per la difesa fitopatologica</h3>
|
||||
<p class="card-text">Pellentesque habitant morbi tristique senectus et netus malesuada fames ac turpis egestas.</p>
|
||||
<h3 class="card-title">{{ t.card2_title }}</h3>
|
||||
<p class="card-text">{{ t.card2_text }}</p>
|
||||
</div>
|
||||
<div class="action-card" data-action="iframe" data-src="http://localhost/viewer?userId=1398&lang=it-IT">
|
||||
<div class="action-card" data-action="iframe" data-src="{{ t.card3_src }}">
|
||||
<div class="card-icon"></div>
|
||||
<h3 class="card-title">Riconoscimento fenologico</h3>
|
||||
<p class="card-text">Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae.</p>
|
||||
<h3 class="card-title">{{ t.card3_title }}</h3>
|
||||
<p class="card-text">{{ t.card3_text }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Shared modal overlay -->
|
||||
<div id="modal" class="modal hidden" role="dialog" aria-modal="true">
|
||||
<div class="modal-box">
|
||||
<button class="modal-close" id="modal-close" aria-label="Chiudi">×</button>
|
||||
<button class="modal-close" id="modal-close" aria-label="{{ t.close_label }}">×</button>
|
||||
<video id="modal-video" controls></video>
|
||||
<iframe id="modal-iframe" src="" allowfullscreen></iframe>
|
||||
</div>
|
||||
2
src/translations/__init__.py
Normal file
2
src/translations/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from .en import strings as en_strings
|
||||
from .it import strings as it_strings
|
||||
12
src/translations/en.py
Normal file
12
src/translations/en.py
Normal file
@ -0,0 +1,12 @@
|
||||
strings = {
|
||||
"lang_code": "en",
|
||||
"subtitle": "Digital innovation for agriculture",
|
||||
"card1_title": "Digital field notebook",
|
||||
"card1_text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vehicula arcu vel ligula fermentum.",
|
||||
"card2_title": "Virtual assistant for phytopathological defence",
|
||||
"card2_text": "Pellentesque habitant morbi tristique senectus et netus malesuada fames ac turpis egestas.",
|
||||
"card3_title": "Phenological recognition",
|
||||
"card3_text": "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae.",
|
||||
"card3_src": "http://localhost/viewer?userId=1398&lang=en-EN",
|
||||
"close_label": "Close",
|
||||
}
|
||||
12
src/translations/it.py
Normal file
12
src/translations/it.py
Normal file
@ -0,0 +1,12 @@
|
||||
strings = {
|
||||
"lang_code": "it",
|
||||
"subtitle": "Innovazione digitale per l'agricoltura",
|
||||
"card1_title": "Quaderno di campagna digitale",
|
||||
"card1_text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vehicula arcu vel ligula fermentum.",
|
||||
"card2_title": "Assistente virtuale per la difesa fitopatologica",
|
||||
"card2_text": "Pellentesque habitant morbi tristique senectus et netus malesuada fames ac turpis egestas.",
|
||||
"card3_title": "Riconoscimento fenologico",
|
||||
"card3_text": "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae.",
|
||||
"card3_src": "http://localhost/viewer?userId=1398&lang=it-IT",
|
||||
"close_label": "Chiudi",
|
||||
}
|
||||
28
uv.lock
generated
28
uv.lock
generated
@ -49,6 +49,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/9c/34f6962f9b9e9c71f6e5ed806e0d0ff03c9d1b0b2340088a0cf4bce09b18/flask-3.1.3-py3-none-any.whl", hash = "sha256:f4bcbefc124291925f1a26446da31a5178f9483862233b23c0c96a20701f670c", size = 103424, upload-time = "2026-02-19T05:00:56.027Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itsdangerous"
|
||||
version = "2.2.0"
|
||||
@ -128,10 +137,27 @@ version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "flask" },
|
||||
{ name = "uvicorn" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "flask", specifier = ">=3.1.3" }]
|
||||
requires-dist = [
|
||||
{ name = "flask", specifier = ">=3.1.3" },
|
||||
{ name = "uvicorn", specifier = ">=0.47.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uvicorn"
|
||||
version = "0.47.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f6/b1/8e7077a8641086aea449e1b5752a570f1b5906c64e0a33cd6d93b63a066b/uvicorn-0.47.0.tar.gz", hash = "sha256:7c9a0ea1a9414106bbab7324609c162d8fa0cdcdcb703060987269d77c7bb533", size = 90582, upload-time = "2026-05-14T18:16:54.455Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/15/41/ac2dfdbc1f60c7af4f994c7a335cfa7040c01642b605d65f611cecc2a1e4/uvicorn-0.47.0-py3-none-any.whl", hash = "sha256:2c5715bc12d1892d84752049f400cd1c3cb018514967fdfeb97640443a6a9432", size = 71301, upload-time = "2026-05-14T18:16:51.762Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "werkzeug"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user