diff --git a/www/TODO b/www/TODO
index cd6807f..48fddd4 100644
--- a/www/TODO
+++ b/www/TODO
@@ -1 +1,3 @@
-- i18n switch
+- i18n switch (to keep on same page)
+- /records pagination
+- /records ajax bird contacts retrieval
diff --git a/www/assets/styles/app.css b/www/assets/styles/app.css
index 9008bd3..7f2b885 100644
--- a/www/assets/styles/app.css
+++ b/www/assets/styles/app.css
@@ -65,7 +65,9 @@ a {
z-index: 1;
}
-.button, input[type=submit], input[type=button] {
+.button,
+input[type=submit],
+input[type=button] {
background-color: #f1f1f1;
color: black;
border-radius: 5px;
@@ -97,7 +99,8 @@ a {
word-wrap: break-word;
}
-.button:hover, input:hover {
+.button:hover,
+input:hover {
background-color: #F3F4F6;
text-decoration: none;
transition-duration: 0.1s;
@@ -111,30 +114,30 @@ a {
}
.button-main:focus:not(:focus-visible):not(.focus-visible) {
- box-shadow: none;
- outline: none;
+ box-shadow: none;
+ outline: none;
}
.button-main:hover {
- background-color: #2c974b;
- padding: 6px 16px;
+ background-color: #2c974b;
+ padding: 6px 16px;
}
.button-main:focus {
- box-shadow: rgba(46, 164, 79, .4) 0 0 0 3px;
- outline: none;
+ box-shadow: rgba(46, 164, 79, .4) 0 0 0 3px;
+ outline: none;
}
.button-main:disabled {
- background-color: #94d3a2;
- border-color: rgba(27, 31, 35, .1);
- color: rgba(255, 255, 255, .8);
- cursor: default;
+ background-color: #94d3a2;
+ border-color: rgba(27, 31, 35, .1);
+ color: rgba(255, 255, 255, .8);
+ cursor: default;
}
.button-main:active {
- background-color: #298e46;
- box-shadow: rgba(20, 70, 32, .2) 0 1px 0 inset;
+ background-color: #298e46;
+ box-shadow: rgba(20, 70, 32, .2) 0 1px 0 inset;
}
.button-main:active {
@@ -143,7 +146,8 @@ a {
transition: none 0s;
}
-.button:focus, input:focus {
+.button:focus,
+input:focus {
outline: 1px transparent;
border: solid blue 1px;
}
@@ -179,7 +183,7 @@ header img.logo {
}
main {
- min-height: calc(100vh - (var(--header-height, 4em) + var(--footer-height, 4em)) );
+ min-height: calc(100vh - (var(--header-height, 4em) + var(--footer-height, 4em)));
padding: 5em;
z-index: 0;
}
@@ -201,11 +205,16 @@ footer a:hover {
font-style: italic;
}
-li, td {
+li {
+ list-style: none;
+}
+
+li,
+td {
align-items: center;
}
-/* .dropdown-button:hover {
+.dropdown-toggle:hover {
background-color: #900;
color: white
}
@@ -213,22 +222,58 @@ li, td {
.dropdown:hover .dropdown-content {
display: block;
}
-*/
.dropdown-content {
display: none;
- position: absolute;
- min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
+ width: fit-content;
}
+
canvas {
display: block;
height: 100%;
width: 100%;
}
+.language-selector {
+ position: absolute;
+ top: 0;
+ right: 0;
+}
+
+.language-selector .toggle {
+ position: absolute;
+ top: 0;
+ right: 0;
+ opacity: 0;
+ width: 5em;
+ height: 1em;
+}
+
+.touch {
+ cursor: pointer;
+}
+
+.touch::after {
+ content: "+";
+}
+
+.slide {
+ clear: both;
+ width: 100%;
+ height: 0px;
+ overflow: hidden;
+ text-align: center;
+ transition: height .4s ease;
+ box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
+}
+
+.toggle:checked + .slide {
+ height: fit-content;
+}
+
.scientific-name {
font-style: italic;
}
@@ -294,4 +339,4 @@ canvas {
main {
padding: 1em;
}
-}
+}
\ No newline at end of file
diff --git a/www/composer.json b/www/composer.json
index 3088255..1037790 100644
--- a/www/composer.json
+++ b/www/composer.json
@@ -23,6 +23,7 @@
"symfony/yaml": "6.1.*",
"twig/extra-bundle": "^2.12|^3.0",
"twig/intl-extra": "^3.4",
+ "twig/string-extra": "^3.4",
"twig/twig": "^2.12|^3.0"
},
"config": {
diff --git a/www/composer.lock b/www/composer.lock
index 13c77da..3aded40 100644
--- a/www/composer.lock
+++ b/www/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "96fd1b588fa4ee292b8be380f2260cc1",
+ "content-hash": "5ee7614277dd908e6485a36c9b423ace",
"packages": [
{
"name": "doctrine/annotations",
@@ -4951,6 +4951,78 @@
],
"time": "2022-06-10T08:33:05+00:00"
},
+ {
+ "name": "twig/string-extra",
+ "version": "v3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/twigphp/string-extra.git",
+ "reference": "03608ae2e9c270a961e8cf1b75751e8635ad3e3c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/twigphp/string-extra/zipball/03608ae2e9c270a961e8cf1b75751e8635ad3e3c",
+ "reference": "03608ae2e9c270a961e8cf1b75751e8635ad3e3c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/string": "^5.0|^6.0",
+ "symfony/translation-contracts": "^1.1|^2|^3",
+ "twig/twig": "^2.7|^3.0"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Twig\\Extra\\String\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ }
+ ],
+ "description": "A Twig extension for Symfony String",
+ "homepage": "https://twig.symfony.com",
+ "keywords": [
+ "html",
+ "string",
+ "twig",
+ "unicode"
+ ],
+ "support": {
+ "source": "https://github.com/twigphp/string-extra/tree/v3.4.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/twig/twig",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-01-02T10:02:25+00:00"
+ },
{
"name": "twig/twig",
"version": "v3.4.2",
diff --git a/www/config/secrets/dev/dev.decrypt.private.php b/www/config/secrets/dev/dev.decrypt.private.php
new file mode 100644
index 0000000..61ce849
--- /dev/null
+++ b/www/config/secrets/dev/dev.decrypt.private.php
@@ -0,0 +1,4 @@
+}/auth", name="auth_i18n")
*/
public function index(Connection $connection)
{
@@ -21,6 +22,7 @@ class AuthController extends AbstractController
/**
* @Route("/auth/login", name="login")
+ * @Route("/{_locale<%app.supported_locales%>}/auth/login", name="login_i18n")
*/
public function login()
{
diff --git a/www/src/Controller/HomeController.php b/www/src/Controller/HomeController.php
index 7ececa9..ccf9c63 100644
--- a/www/src/Controller/HomeController.php
+++ b/www/src/Controller/HomeController.php
@@ -12,7 +12,8 @@ class HomeController extends AbstractController
private Connection $connection;
/**
- * @Route("/", name="home")
+ * @Route("", name="home")
+ * @Route("/{_locale<%app.supported_locales%>}/", name="home_i18n")
*/
public function index(Connection $connection)
{
@@ -25,6 +26,7 @@ class HomeController extends AbstractController
/**
* @Route("/about", name="about")
+ * @Route("/{_locale<%app.supported_locales%>}/about", name="about_i18n")
*/
public function about()
{
diff --git a/www/src/Controller/LogsController.php b/www/src/Controller/LogsController.php
index a17d7b1..4ce5e2f 100644
--- a/www/src/Controller/LogsController.php
+++ b/www/src/Controller/LogsController.php
@@ -12,6 +12,7 @@ class LogsController extends AbstractController
private $allowed_services = "recording analyzis miner plotter";
/**
* @Route("/logs/{service}", name="logs")
+ * @Route("/{_locale<%app.supported_locales%>}/logs/{service}", name="logs_i18n")
*/
public function logs($service = "all")
{
diff --git a/www/src/Controller/RecordsController.php b/www/src/Controller/RecordsController.php
index a827eaa..d6827c8 100644
--- a/www/src/Controller/RecordsController.php
+++ b/www/src/Controller/RecordsController.php
@@ -13,7 +13,8 @@ class RecordsController extends AbstractController
private Connection $connection;
/**
- * @Route("/records/{date}", name="records_index")
+ * @Route("/records", name="records")
+ * @Route("/{_locale<%app.supported_locales%>}/records/{date}", name="records_i18n")
*/
public function records_index($date = "now")
{
@@ -30,6 +31,7 @@ class RecordsController extends AbstractController
/**
* @Route("/records/delete/{basename}", name="record_delete")
+ * @Route("/{_locale<%app.supported_locales%>}/records/delete/{basename}", name="record_delete_i18n")
*/
public function delete_record(Connection $connection, $basename)
{
@@ -38,6 +40,16 @@ class RecordsController extends AbstractController
return $this->redirectToRoute('records_index');
}
+ /**
+ * @Route("/records/best", name="records_best")
+ * @Route("/{_locale<%app.supported_locales%>}/records/best", name="records_best_i18n")
+ */
+ public function best_records(Connection $connection)
+ {
+ $this->render('records/best.html.twig', [
+ ]);
+ }
+
private function list_records()
{
$records_path = $this->getParameter('app.records_dir') . "/out/*.wav";
diff --git a/www/src/Controller/ServicesController.php b/www/src/Controller/ServicesController.php
index bebddec..a1bc070 100644
--- a/www/src/Controller/ServicesController.php
+++ b/www/src/Controller/ServicesController.php
@@ -14,7 +14,8 @@ class ServicesController extends AbstractController
/**
- * @Route("/services/status", name="service_status")
+ * @Route("/services/status", name="services_status")
+ * @Route("/{_locale<%app.supported_locales%>}/services/status", name="service_status_i18n")
*/
public function service_status() {
$status = array_map(function($service) {
@@ -29,7 +30,8 @@ class ServicesController extends AbstractController
}
/**
- * @Route("/services/manage/{action}/{service}", name="service_manager")
+ * @Route("/services/manage/{action}/{service}", name="services_manager")
+ * @Route("/{_locale<%app.supported_locales%>}/services/manage/{action}/{service}", name="service_manager_i18n")
*/
public function service_manage($action, $service="all")
{
diff --git a/www/src/Controller/SpectroController.php b/www/src/Controller/SpectroController.php
index d407893..a95dfac 100644
--- a/www/src/Controller/SpectroController.php
+++ b/www/src/Controller/SpectroController.php
@@ -10,8 +10,9 @@ class SpectroController extends AbstractController
{
/**
* @Route("/spectro", name="spectro")
+ * @Route("/{_locale<%app.supported_locales%>}/spectro", name="spectro_i18n")
*/
- public function about()
+ public function spectro()
{
return $this->render('spectro/index.html.twig', [
diff --git a/www/src/Controller/StatsController.php b/www/src/Controller/StatsController.php
new file mode 100644
index 0000000..a3d84af
--- /dev/null
+++ b/www/src/Controller/StatsController.php
@@ -0,0 +1,22 @@
+}/stats", name="stats_i18n")
+ */
+ public function index(Connection $connection)
+ {
+ return $this->render("stats/index.html.twig");
+ }
+}
\ No newline at end of file
diff --git a/www/src/Controller/TodayController.php b/www/src/Controller/TodayController.php
index 2d1167f..452de59 100644
--- a/www/src/Controller/TodayController.php
+++ b/www/src/Controller/TodayController.php
@@ -14,6 +14,7 @@ class TodayController extends AbstractController
/**
* @Route("/today", name="today")
+ * @Route("/{_locale<%app.supported_locales%>}/today", name="today_i18n")
*/
public function today(Connection $connection)
{
@@ -22,6 +23,7 @@ class TodayController extends AbstractController
/**
* @Route("/today/species", name="today_species")
+ * @Route("/{_locale<%app.supported_locales%>}/today/species", name="today_species_i18n")
*/
public function today_species_page(Connection $connection)
{
@@ -35,6 +37,7 @@ class TodayController extends AbstractController
/**
* @Route("/today/species/{id}", name="today_species_id")
+ * @Route("/{_locale<%app.supported_locales%>}/today/species/{id}", name="today_species_id_i18n")
*/
public function today_species_by_id(Connection $connection, $id)
{
@@ -49,6 +52,7 @@ class TodayController extends AbstractController
/**
* @Route("/today/{date}", name="today_date")
+ * @Route("/{_locale<%app.supported_locales%>}/today/{date}", name="today_date_i18n")
*/
public function today_date(Connection $connection, $date)
{
@@ -57,6 +61,7 @@ class TodayController extends AbstractController
/**
* @Route("/today/{date}/species", name="today_species_date")
+ * @Route("/{_locale<%app.supported_locales%>}/today/{date}/species", name="today_species_date_i18n")
*/
public function today_species_by_date(Connection $connection, $date)
{
@@ -69,6 +74,7 @@ class TodayController extends AbstractController
/**
* @Route("/today/{date}/species/{id}", name="today_species_id_and_date")
+ * @Route("/{_locale<%app.supported_locales%>}/today/{date}/species/{id}", name="today_species_id_and_date_i18n")
*/
public function today_species_by_id_and_date(Connection $connection, $date, $id)
{
@@ -141,4 +147,4 @@ class TodayController extends AbstractController
$result = $stmt->executeQuery();
return $result->fetchAllAssociative();
}
-}
+}
\ No newline at end of file
diff --git a/www/templates/base.html.twig b/www/templates/base.html.twig
index ee10174..efb0f29 100644
--- a/www/templates/base.html.twig
+++ b/www/templates/base.html.twig
@@ -1,5 +1,5 @@
-
+
@@ -27,6 +27,7 @@
+ {% include "utils/locale-switcher.html.twig" %}
{% block content %}
Welcome to BirdNET-stream !
diff --git a/www/templates/menu.html.twig b/www/templates/menu.html.twig
index 39e2398..9b6c0f0 100644
--- a/www/templates/menu.html.twig
+++ b/www/templates/menu.html.twig
@@ -9,57 +9,51 @@
{% include 'utils/nav-item.html.twig' with {
route: 'home',
url: '/',
- name: 'Home'|trans
+ text: 'Home'|trans
} %}
{% include 'utils/nav-item.html.twig' with {
route: 'about',
url: '/about',
- name: 'About'|trans
+ text: 'About'|trans
} %}
{% include 'utils/nav-item.html.twig' with {
route: 'today',
url: '/today',
- name: "Today's Detections"|trans
+ text: "Today's Detections"|trans
} %}
{% include 'utils/nav-item.html.twig' with {
route: 'spectro',
url: '/spectro',
- name: 'Live Spectrogram'|trans
+ text: 'Live Spectrogram'|trans
} %}
{% include 'utils/nav-item.html.twig' with {
route: 'stats',
url: '/stats',
- name: 'Statistics'|trans
+ text: 'Statistics'|trans
} %}
{% include 'utils/nav-item.html.twig' with {
route: 'records',
url: '/records',
- name: 'Recordings'|trans
+ text: 'Recordings'|trans
} %}
{% include 'utils/nav-item.html.twig' with {
- route: 'bests',
+ route: 'records_best',
url: '/records/best',
- name: 'Best Recordings'|trans
+ text: 'Best Recordings'|trans
} %}
- {% include 'utils/nav-item.html.twig' with {
- route: 'bests',
- url: '/records/best',
- name: 'Best Recordings'|trans
- } %}
-
{% include 'utils/nav-item.html.twig' with {
route: 'logs',
url: '/logs',
- name: 'View Logs'|trans
+ text: 'View Logs'|trans
} %}
{% include 'utils/nav-item.html.twig' with {
- route: 'status',
+ route: 'services_status',
url: '/services/status',
- name: 'Status'|trans
+ text: 'Status'|trans
} %}
diff --git a/www/templates/records/best.html.twig b/www/templates/records/best.html.twig
new file mode 100644
index 0000000..4cda376
--- /dev/null
+++ b/www/templates/records/best.html.twig
@@ -0,0 +1 @@
+{{ "Not implemented yet"|trans
\ No newline at end of file
diff --git a/www/templates/stats/index.html.twig b/www/templates/stats/index.html.twig
new file mode 100644
index 0000000..8b8a65d
--- /dev/null
+++ b/www/templates/stats/index.html.twig
@@ -0,0 +1,3 @@
+{% block content %}
+ {{ "Not implemented yet"|trans }}
+{% endblock %}
\ No newline at end of file
diff --git a/www/templates/utils/locale-switcher.html.twig b/www/templates/utils/locale-switcher.html.twig
new file mode 100644
index 0000000..2c9acd3
--- /dev/null
+++ b/www/templates/utils/locale-switcher.html.twig
@@ -0,0 +1,28 @@
+{% set current = app.request.get('_route')|replace({"_i18n": ""})~"_i18n" %}
+{% macro lang_url(route, locale, name) %}
+ {{ name }}
+
+{% endmacro %}
+
+
+ {{ app.request.locale|locale_name(app.request.locale)|u.title }}
+
+
+
+
+ {{ _self.lang_url(current, "en", "English") }}
+
+
+ {{ _self.lang_url(current, "fr", "Français") }}
+
+
+
\ No newline at end of file
diff --git a/www/templates/utils/nav-item.html.twig b/www/templates/utils/nav-item.html.twig
index 1b0f8e7..6c3d539 100644
--- a/www/templates/utils/nav-item.html.twig
+++ b/www/templates/utils/nav-item.html.twig
@@ -1,6 +1,6 @@
- {{ name }}
+ href="{{ path(route) }}">
+ {{ text }}
diff --git a/www/translations/messages+intl-icu.fr.xlf b/www/translations/messages+intl-icu.fr.xlf
index 6491285..3536ef7 100644
--- a/www/translations/messages+intl-icu.fr.xlf
+++ b/www/translations/messages+intl-icu.fr.xlf
@@ -23,7 +23,7 @@
This project is made with ♥ by Samuel ORTION.
-
+ Ce projet est fait avec ♥ par Samuel ORTION.
License
@@ -37,6 +37,206 @@
BirdNET-Analyzer, on which this project relies, is licensed under
BirdNET-Analyzer, sur qui ce projet repose, est sous licence
+
+ Frequency charts
+ Graphe de fréquence
+
+
+ No charts available
+ Pas de graphe disponible
+
+
+ Home
+ Accueil
+
+
+ Today's Detections
+ Détection aujourd'hui
+
+
+ Live Spectrogram
+ Spectrogramme en temps réel
+
+
+ Statistics
+ Statistiques
+
+
+ Recordings
+ Enregistrements
+
+
+ Best Recordings
+ Meilleurs Enregistrements
+
+
+ View Logs
+ Voir les logs
+
+
+ Status
+ Status
+
+
+ Date
+ Date
+
+
+ Enter a date in this format YYYY-MM-DD
+ Entrez une date au format YYYY-MM-DD
+
+
+ Go
+ Go
+
+
+ Logs
+ Logs
+
+
+ No logs available
+ Pas de logs disponible
+
+
+ Spectrogram
+ Spectrogramme
+
+
+ Launch Live Spectrogram
+ Lancer le Spectrogramme en temps réel
+
+
+ No audio sources yet
+ Pas de source audio pour le moment
+
+
+ Quick Stats
+ Statistiques rapides
+
+
+ Most recorded species
+ Espèce la plus souvent enregistrée
+
+
+ with
+ avec
+
+
+ contacts
+ contacts
+
+
+ No species in database.
+ Aucune espèce dans la base de donnée.
+
+
+ Last detected species
+ Dernière espèce détectée
+
+
+ AI confidence
+ Niveau de confiance
+
+
+ today
+ aujourd'hui
+
+
+ on
+ le
+
+
+ No species in database
+ Aucune espèce dans la base de données
+
+
+ Today's contacts for
+ Contacts d'aujourd'hui pour
+
+
+ Contacts on
+ Contacts le
+
+
+ for
+ pour
+
+
+ Stats
+ Stats
+
+
+ Contact count:
+ Nombre de contact:
+
+
+ Max confidence
+ Niveau de confiance maximal
+
+
+ Contact records
+ Enregistrement du contact
+
+
+ Filename
+ Fichier
+
+
+ Time
+ Heure
+
+
+ Confidence
+ Confiance
+
+
+ Audio
+ Audio
+
+
+ Select this record
+ Sélectionner cet enregistrement
+
+
+ Download audio file
+ Télécharger le fichier audio
+
+
+ No records this day for this species
+ Pas d'entrement ce jour pour cette espèce
+
+
+ Select all
+ Séléctionner tout
+
+
+ Delete selected
+ Supprimer la sélection
+
+
+ Today's detected species
+ Espèces détectées aujourd'hui
+
+
+ Detected species on
+ Espèces détectées le
+
+
+ No species detected this day
+ Aucune espèce détectée ce jour
+
+
+ Services status
+ Status des services
+
+
+ No status available
+ Aucun status disponible
+
+
+ Welcome to BirdNET-stream !
+ Bienvenue sur BirdNET-stream !
+