Merge remote-tracking branch 'origin/main' into main with visibility permissions fix

This commit is contained in:
Karl Determe 2026-08-20 12:08:29 +02:00
commit 56281b4821
134 changed files with 40973 additions and 37417 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,22 @@
# Generated by Django 6.0.7 on 2026-08-19 09:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0021_sync_asset_parent_data'),
]
operations = [
migrations.AlterModelOptions(
name='trafficlightprogramming',
options={'ordering': ['-commissioning_date'], 'verbose_name': 'Programmation', 'verbose_name_plural': 'Programmations'},
),
migrations.AlterField(
model_name='trafficlightprogramming',
name='index',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Index'),
),
]

View file

@ -0,0 +1,52 @@
from django.db import migrations
def create_programming_category(apps, schema_editor):
Thematic = apps.get_model('common', 'Thematic')
AssetCategory = apps.get_model('assets', 'AssetCategory')
ContentType = apps.get_model('contenttypes', 'ContentType')
try:
thematic = Thematic.objects.get(code='trafficlights')
except Thematic.DoesNotExist:
thematic, _ = Thematic.objects.get_or_create(
code='trafficlights',
defaults={
'name_fr': 'Feux de signalisation',
'name_nl': 'Verkeerslichten',
'description': 'Gestion des carrefours à feux et équipements associés',
'icon': 'bi-stoplights',
'color': '#ffc107',
}
)
category, _cat_created = AssetCategory.objects.get_or_create(
code='TL_PROGRAMMING',
defaults={
'thematic': thematic,
'name_fr': 'Programmation',
'name_nl': 'Programmatie',
}
)
# Link ContentType for TrafficLightProgramming
try:
prog_ct = ContentType.objects.get(app_label='assets', model='trafficlightprogramming')
category.allowed_models.add(prog_ct)
except Exception:
pass
def remove_programming_category(apps, schema_editor):
AssetCategory = apps.get_model('assets', 'AssetCategory')
AssetCategory.objects.filter(code='TL_PROGRAMMING').delete()
class Migration(migrations.Migration):
dependencies = [
('assets', '0022_alter_trafficlightprogramming_options_and_more'),
]
operations = [
migrations.RunPython(create_programming_category, remove_programming_category),
]

View file

@ -97,6 +97,9 @@ class TrafficLightIntersection(AbstractLocation):
# Retrieve associated radars
radars = self.radars.filter(status='active').order_by('code')
# Retrieve associated programmations
programmations = self.programmations.filter(status='active').order_by('code')
return {
"poles": all_poles,
"cables": cables,
@ -105,6 +108,7 @@ class TrafficLightIntersection(AbstractLocation):
"detectors": detectors,
"electrical_cabinets": electrical_cabinets,
"radars": radars,
"programmations": programmations,
}
def get_all_assets(self):
@ -132,6 +136,9 @@ class TrafficLightIntersection(AbstractLocation):
# Retrieve associated radars
radars = self.radars.all().order_by('code')
# Retrieve associated programmations
programmations = self.programmations.all().order_by('code')
return {
"poles": all_poles,
"cables": cables,
@ -140,6 +147,7 @@ class TrafficLightIntersection(AbstractLocation):
"detectors": detectors,
"electrical_cabinets": electrical_cabinets,
"radars": radars,
"programmations": programmations,
}
def get_direct_child_assets(self):
@ -167,6 +175,9 @@ class TrafficLightIntersection(AbstractLocation):
# Retrieve associated radars
radars = self.radars.all().order_by('code')
# Retrieve associated programmations
programmations = self.programmations.all().order_by('code')
return {
"poles": all_poles,
"cables": cables,
@ -175,6 +186,7 @@ class TrafficLightIntersection(AbstractLocation):
"detectors": detectors,
"electrical_cabinets": electrical_cabinets,
"radars": radars,
"programmations": programmations,
}
def get_controller_contract(self):
@ -192,6 +204,18 @@ class TrafficLightIntersection(AbstractLocation):
latest_controller = self.controllers.filter(status='active').order_by('-installation_date').first()
return latest_controller.connected_to_control_center if latest_controller else None
@property
def controller_model_name(self):
"""
Get the model name of the active controller (or most recently installed controller).
"""
latest_controller = self.controllers.filter(status='active').order_by('-installation_date').first()
if not latest_controller:
latest_controller = self.controllers.order_by('-installation_date').first()
if latest_controller and latest_controller.model:
return latest_controller.model.get_name() or latest_controller.model.code
return None
def get_absolute_url(self):
return reverse("assets:trafficlights_intersections_detail", kwargs={"intersection_id": self.id})
@ -697,19 +721,21 @@ class TrafficLightAccessory(TrafficLightAbstractGeoAsset):
# Treffic Light Programmation
# Traffic Light Programmation
class TrafficLightProgramming(TrafficLightAbstractAsset):
intersection = models.ForeignKey(TrafficLightIntersection, on_delete=models.CASCADE, related_name="programmations")
commissioning_date = models.DateTimeField(null=True, blank=True, verbose_name=_("Date de mise en service"))
uncommissioning_date = models.DateTimeField(null=True, blank=True, verbose_name=_("Date de mise hors service"))
plan = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("Plan"))
index = models.CharField(max_length=100, verbose_name=_("Index"))
index = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Index"))
info = models.TextField(null=True, blank=True, verbose_name=_("Informations"))
def __str__(self):
return f"{self.index} - {self.intersection.code}"
return f"{self.index or self.code} - {self.intersection.code}"
class Meta:
verbose_name = _("Programmation")
verbose_name_plural = _("Programmations")
ordering = ['-commissioning_date']

View file

@ -462,6 +462,8 @@
<input type="number" step="any" class="form-control form-control-sm" value="{{ field.input_value }}">
{% elif field.field_type == 'date' %}
<input type="date" class="form-control form-control-sm" value="{{ field.input_value }}">
{% elif field.field_type == 'textarea' %}
<textarea class="form-control form-control-sm" rows="3">{{ field.input_value }}</textarea>
{% else %}
<input type="text" class="form-control form-control-sm" value="{{ field.input_value }}">
{% endif %}

View file

@ -48,6 +48,8 @@
{% endif %}
<br>
<label class="mx-2">{% translate "Index" %}:</label>{{ intersection.current_index|default:""}}
<br>
<label class="mx-2">{% translate "Modèle du contrôleur" %}:</label>{{ intersection.controller_model_name|default:""}}
{% if intersection.master %}
<br>
<label class="mx-2">{% translate "Carrefour principal" %}:</label><a href="{% url 'assets:trafficlights_intersections_detail' intersection.master.id %}">{{ intersection.master.code|default:"/" }}</a>
@ -848,7 +850,12 @@
<div class="card-header bg-light d-flex align-items-center gap-2 py-2">
<i class="bi bi-kanban text-secondary"></i>
<span class="fw-semibold">{% translate "Programmations" %}</span>
<span class="badge bg-secondary ms-auto">{{ prog_list|length }}</span>
<span class="badge bg-secondary">{{ prog_list|length }}</span>
{% if 'create' in allowed_location_actions %}
<button type="button" class="btn btn-sm btn-outline-primary ms-auto" data-bs-toggle="modal" data-bs-target="#addProgrammingModal" title="{% translate 'Ajouter une programmation' %}">
<i class="bi bi-plus-circle me-1"></i>{% translate "Ajouter" %}
</button>
{% endif %}
</div>
<ul class="list-group list-group-flush">
{% for prog in prog_list %}
@ -874,7 +881,12 @@
{% else %}
<div class="text-center text-muted py-4">
<i class="bi bi-kanban fs-3 opacity-50 d-block mb-2"></i>
{% translate "Aucune programmation" %}
<p class="mb-2">{% translate "Aucune programmation" %}</p>
{% if 'create' in allowed_location_actions %}
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#addProgrammingModal">
<i class="bi bi-plus-circle me-1"></i>{% translate "Ajouter une programmation" %}
</button>
{% endif %}
</div>
{% endif %}
{% endwith %}
@ -1023,6 +1035,76 @@
</div>
</div>
</div>
<!-- Add Programming Modal -->
<div class="modal fade" id="addProgrammingModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="bi bi-kanban me-2 text-primary"></i>{% translate "Ajouter une programmation" %}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form id="addProgrammingForm" enctype="multipart/form-data" method="POST" action="{% url 'assets:trafficlights_add_programming' intersection.id %}">
{% csrf_token %}
<div class="modal-body">
<div id="addProgrammingAlert" class="alert d-none" role="alert"></div>
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">{% translate "Code" %}</label>
<input type="text" name="code" class="form-control" placeholder="{% translate 'Laisser vide pour auto-génération' %}">
<small class="text-muted">{% translate "Ex: " %}{{ intersection.code }}-PRG-001</small>
</div>
<div class="col-md-6">
<label class="form-label">{% translate "Index" %}</label>
<input type="text" name="index" class="form-control" value="{{ intersection.current_index|default:'' }}" placeholder="Ex: 01">
</div>
<div class="col-md-6">
<label class="form-label">{% translate "Plan" %}</label>
<input type="text" name="plan" class="form-control" placeholder="Ex: Plan 1A">
</div>
<div class="col-md-6">
<label class="form-label">{% translate "Statut" %}</label>
<select name="status" class="form-select">
<option value="active" selected>{% translate "Actif" %}</option>
<option value="in_preparation">{% translate "En préparation" %}</option>
<option value="inactive">{% translate "Inactif" %}</option>
<option value="removed">{% translate "Retiré" %}</option>
</select>
</div>
<div class="col-md-6">
<label class="form-label">{% translate "Date de mise en service" %}</label>
<input type="date" name="commissioning_date" class="form-control">
</div>
<div class="col-md-6">
<label class="form-label">{% translate "Date de mise hors service" %}</label>
<input type="date" name="uncommissioning_date" class="form-control">
</div>
<div class="col-12">
<label class="form-label">{% translate "Fichier de programmation" %}</label>
<input type="file" name="file" class="form-control">
<small class="text-muted">{% translate "Optionnel. Fichier joint à la programmation." %}</small>
</div>
<div class="col-12">
<label class="form-label">{% translate "Informations" %}</label>
<textarea name="info" rows="3" class="form-control" placeholder="{% translate 'Notes ou informations complémentaires...' %}"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% translate "Annuler" %}</button>
<button type="submit" class="btn btn-primary" id="addProgrammingSubmitBtn">
<i class="bi bi-plus-circle me-1"></i>{% translate "Créer la programmation" %}
</button>
</div>
</form>
</div>
</div>
</div>
{% endif %}
<!-- Georeferenced Plans Selection Modal -->
@ -1383,5 +1465,55 @@
: 'bi bi-chevron-expand small';
});
})();
// Handle Add Programming form submission
(function () {
const form = document.getElementById('addProgrammingForm');
if (!form) return;
form.addEventListener('submit', function (e) {
e.preventDefault();
const alertEl = document.getElementById('addProgrammingAlert');
const submitBtn = document.getElementById('addProgrammingSubmitBtn');
alertEl.className = 'alert d-none';
if (submitBtn) submitBtn.disabled = true;
const formData = new FormData(form);
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]')?.value || '{{ csrf_token }}';
fetch(form.action, {
method: 'POST',
headers: {
'X-CSRFToken': csrfToken,
'X-Requested-With': 'XMLHttpRequest'
},
body: formData
})
.then(r => r.json().then(data => ({ status: r.status, ok: r.ok, data })))
.then(({ ok, data }) => {
if (ok && data.success) {
alertEl.textContent = data.message || "{% translate 'Programmation ajoutée avec succès.' %}";
alertEl.className = 'alert alert-success';
setTimeout(() => {
if (data.redirect_url) {
window.location.href = data.redirect_url;
} else {
window.location.reload();
}
}, 1000);
} else {
alertEl.textContent = data.error || "{% translate 'Erreur lors de la création de la programmation.' %}";
alertEl.className = 'alert alert-danger';
if (submitBtn) submitBtn.disabled = false;
}
})
.catch(err => {
console.error('Error creating programming:', err);
alertEl.textContent = "{% translate 'Une erreur inattendue est survenue.' %}";
alertEl.className = 'alert alert-danger';
if (submitBtn) submitBtn.disabled = false;
});
});
})();
</script>
{% endblock script %}

View file

@ -100,7 +100,7 @@ def get_asset_specific_fields(asset):
from django.contrib.gis.db.models import GeometryField
from django.db.models import (ForeignKey, OneToOneField, ManyToManyField, AutoField,
BooleanField, FloatField, DecimalField, IntegerField,
DateField, DateTimeField)
DateField, DateTimeField, TextField)
from django.utils.translation import gettext_lazy as _
from assets.models import AbstractAsset, AbstractGeoAsset
@ -136,6 +136,10 @@ def get_asset_specific_fields(asset):
field_type = 'date'
display_value = value.strftime('%d/%m/%Y') if value else '-'
input_value = value.strftime('%Y-%m-%d') if value else ''
elif isinstance(field, TextField):
field_type = 'textarea'
display_value = str(value) if value is not None else '-'
input_value = str(value) if value is not None else ''
elif field.choices:
field_type = 'select'
choices_dict = dict(field.choices)

View file

@ -2,6 +2,7 @@ from django.test import TestCase, tag
from django.contrib.auth.models import User
from django.contrib.gis.geos import MultiPolygon, Polygon
from django.urls import reverse
from django.contrib.contenttypes.models import ContentType
import json
import os
from unittest import skipUnless
@ -3235,3 +3236,374 @@ class CreateInterventionForAssetWorkflowTest(TestCase):
self.assertEqual(first_event.event_user, self.user)
class TrafficLightIntersectionControllerModelTest(TestCase):
def setUp(self):
self.thematic, _ = Thematic.objects.get_or_create(
code="trafficlights",
defaults={
"name_fr": "Feux de signalisation",
"name_nl": "Verkeerslichten"
}
)
self.user, _ = User.objects.get_or_create(username="tl_ctrl_testuser")
self.user.set_password("password123")
self.user.save()
self.config, _ = UserConfig.objects.get_or_create(user=self.user, defaults={"limit_assets_to_contracts": False})
self.config.limit_assets_to_contracts = False
self.config.save()
UserThematics.objects.get_or_create(
user_config=self.config,
thematic=self.thematic,
defaults={"can_view_assets": True}
)
from django.contrib.gis.geos import Point
geom_intersection = Point(648000, 670000, srid=3812)
self.intersection = TrafficLightIntersection.objects.create(
code="TL_INT_001",
name_fr="Carrefour Test",
geom=geom_intersection,
lon=4.3508,
lat=50.8465,
current_index="IDX-12345"
)
self.category, _ = AssetCategory.objects.get_or_create(
code="TL_CONTROLLER_CAT",
defaults={
"name_fr": "Contrôleur de trafic",
"name_nl": "Verkeersregelaar",
"thematic": self.thematic
}
)
from assets.models import TrafficLightControllerModel, TrafficLightController
self.controller_model = TrafficLightControllerModel.objects.create(
code="CTRL_MOD_01",
name_fr="Siemens Sitraffic C1000",
name_nl="Siemens Sitraffic C1000 NL",
category=self.category
)
self.controller = TrafficLightController.objects.create(
code="CTRL_001",
intersection=self.intersection,
model=self.controller_model,
geom=geom_intersection,
lon=4.3508,
lat=50.8465,
status="active"
)
def test_controller_model_name_property(self):
self.assertEqual(self.intersection.controller_model_name, "Siemens Sitraffic C1000")
def test_controller_model_name_none_when_no_controller(self):
from django.contrib.gis.geos import Point
empty_intersection = TrafficLightIntersection.objects.create(
code="TL_INT_EMPTY",
name_fr="Carrefour Sans Contrôleur",
geom=Point(648000, 670000, srid=3812)
)
self.assertIsNone(empty_intersection.controller_model_name)
def test_detail_view_renders_controller_model_name(self):
self.client.force_login(self.user)
# Test French
response_fr = self.client.get(
reverse("assets:trafficlights_intersections_detail", args=[self.intersection.id]),
HTTP_HOST="localhost",
HTTP_ACCEPT_LANGUAGE="fr"
)
self.assertEqual(response_fr.status_code, 200)
content_fr = response_fr.content.decode("utf-8")
self.assertIn("Modèle du contrôleur", content_fr)
self.assertIn("Siemens Sitraffic C1000", content_fr)
self.assertIn("IDX-12345", content_fr)
# Test Dutch
response_nl = self.client.get(
reverse("assets:trafficlights_intersections_detail", args=[self.intersection.id]),
HTTP_HOST="localhost",
HTTP_ACCEPT_LANGUAGE="nl"
)
self.assertEqual(response_nl.status_code, 200)
content_nl = response_nl.content.decode("utf-8")
self.assertIn("Controllermodel", content_nl)
self.assertIn("Siemens Sitraffic C1000 NL", content_nl)
class TrafficLightProgrammingTest(TestCase):
def setUp(self):
from django.contrib.gis.geos import Point
from django.contrib.contenttypes.models import ContentType
from assets.models.trafficlights import TrafficLightProgramming
self.thematic, _ = Thematic.objects.get_or_create(
code="trafficlights",
defaults={
"name_fr": "Feux de signalisation",
"name_nl": "Verkeerslichten"
}
)
from common.models import Role
self.user = User.objects.create_user(username="proguser", password="password123")
self.config = UserConfig.objects.create(user=self.user, limit_assets_to_contracts=False)
admin_role, _ = Role.objects.get_or_create(name="admin")
self.config.roles.add(admin_role)
UserThematics.objects.create(
user_config=self.config,
thematic=self.thematic,
can_view_assets=True,
can_edit_assets=True
)
self.category, _ = AssetCategory.objects.get_or_create(
code="TL_PROGRAMMING",
defaults={
"name_fr": "Programmation",
"name_nl": "Programmatie",
"thematic": self.thematic
}
)
prog_ct = ContentType.objects.get_for_model(TrafficLightProgramming)
self.category.allowed_models.add(prog_ct)
self.intersection = TrafficLightIntersection.objects.create(
code="K999",
name_fr="Carrefour Test Prog",
geom=Point(648000, 670000, srid=3812),
lon=4.3508,
lat=50.8465,
current_index="01"
)
def test_programming_category_exists_and_linked(self):
from assets.models.trafficlights import TrafficLightProgramming
prog_ct = ContentType.objects.get_for_model(TrafficLightProgramming)
self.assertTrue(self.category.allowed_models.filter(id=prog_ct.id).exists())
def test_intersection_get_assets_includes_programmations(self):
from assets.models.trafficlights import TrafficLightProgramming
prog_active = TrafficLightProgramming.objects.create(
code="K999-PRG-001",
intersection=self.intersection,
status="active",
index="01",
plan="Plan A"
)
prog_inactive = TrafficLightProgramming.objects.create(
code="K999-PRG-002",
intersection=self.intersection,
status="removed",
index="00",
plan="Plan Old"
)
active_assets = self.intersection.get_active_assets()
all_assets = self.intersection.get_all_assets()
self.assertIn("programmations", active_assets)
self.assertIn("programmations", all_assets)
self.assertEqual(len(active_assets["programmations"]), 1)
self.assertEqual(active_assets["programmations"][0].id, prog_active.id)
self.assertEqual(len(all_assets["programmations"]), 2)
def test_create_programming_via_dedicated_endpoint(self):
from assets.models.trafficlights import TrafficLightProgramming
from django.core.files.uploadedfile import SimpleUploadedFile
self.client.force_login(self.user)
test_file = SimpleUploadedFile("prog_test.txt", b"programming binary data", content_type="text/plain")
response = self.client.post(
reverse("assets:trafficlights_add_programming", kwargs={"intersection_id": self.intersection.id}),
{
"code": "K999-PRG-NEW",
"index": "02",
"plan": "Plan 2B",
"commissioning_date": "2026-05-01",
"uncommissioning_date": "2026-12-31",
"status": "active",
"info": "Notes sur la programmation",
"file": test_file
},
HTTP_X_REQUESTED_WITH="XMLHttpRequest"
)
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertTrue(data["success"])
self.assertEqual(data["asset_code"], "K999-PRG-NEW")
prog = TrafficLightProgramming.objects.get(code="K999-PRG-NEW")
self.assertEqual(prog.intersection, self.intersection)
self.assertEqual(prog.index, "02")
self.assertEqual(prog.plan, "Plan 2B")
self.assertEqual(prog.info, "Notes sur la programmation")
from django.utils import timezone
self.assertEqual(timezone.localtime(prog.commissioning_date).strftime("%Y-%m-%d"), "2026-05-01")
self.assertEqual(timezone.localtime(prog.uncommissioning_date).strftime("%Y-%m-%d"), "2026-12-31")
# Check document attached
doc = prog.documents.first()
self.assertIsNotNone(doc)
self.assertEqual(doc.document_type, "programming_file")
def test_create_programming_via_create_asset(self):
from assets.models.trafficlights import TrafficLightProgramming
self.client.force_login(self.user)
response = self.client.post(
f"/assets/trafficlights/trafficlightintersection/{self.intersection.id}/create-asset/",
data=json.dumps({
"category_id": self.category.id,
"asset_type": "trafficlightprogramming",
"data": {}
}),
content_type="application/json",
HTTP_X_REQUESTED_WITH="XMLHttpRequest"
)
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertTrue(data["success"])
self.assertEqual(data["asset_type"], "trafficlightprogramming")
self.assertTrue(data["asset_code"].startswith("K999-PRG-"))
created_prog = TrafficLightProgramming.objects.get(id=data["asset_id"])
self.assertEqual(created_prog.intersection, self.intersection)
self.assertEqual(created_prog.category, self.category)
def test_create_programming_via_create_asset_api(self):
from assets.models.trafficlights import TrafficLightProgramming
self.client.force_login(self.user)
response = self.client.post(
reverse("assets:create_asset_api"),
data=json.dumps({
"thematic_code": "trafficlights",
"category_id": self.category.id,
"location_type": "trafficlightintersection",
"location_id": self.intersection.id,
"asset_type": "trafficlightprogramming",
"code": "K999-PRG-API",
"data": {
"index": "05",
"plan": "Plan API",
"info": "Created from API"
}
}),
content_type="application/json",
HTTP_X_REQUESTED_WITH="XMLHttpRequest"
)
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertTrue(data["success"])
self.assertEqual(data["asset_type"], "trafficlightprogramming")
prog = TrafficLightProgramming.objects.get(code="K999-PRG-API")
self.assertEqual(prog.intersection, self.intersection)
self.assertEqual(prog.index, "05")
self.assertEqual(prog.plan, "Plan API")
self.assertEqual(prog.info, "Created from API")
def test_update_programming_fields_via_api(self):
from assets.models.trafficlights import TrafficLightProgramming
from django.utils import timezone
prog = TrafficLightProgramming.objects.create(
code="K999-PRG-UPD",
intersection=self.intersection,
status="in_preparation",
index="01",
plan="Plan Init",
info="Initial Info"
)
self.client.force_login(self.user)
# Update index, plan, info, status, and dates
updates = {
"index": "02",
"plan": "Plan Updated",
"info": "Updated Info Notes",
"status": "active",
"commissioning_date": "2026-06-15",
"uncommissioning_date": "2027-01-01"
}
response = self.client.post(
reverse("assets:update_asset", kwargs={
"asset_model": "trafficlightprogramming",
"asset_id": prog.id
}),
data=json.dumps(updates),
content_type="application/json",
HTTP_X_REQUESTED_WITH="XMLHttpRequest"
)
self.assertEqual(response.status_code, 200, f"Failed updating programming: {response.content}")
data = response.json()
self.assertTrue(data["success"])
prog.refresh_from_db()
self.assertEqual(prog.index, "02")
self.assertEqual(prog.plan, "Plan Updated")
self.assertEqual(prog.info, "Updated Info Notes")
self.assertEqual(prog.status, "active")
self.assertEqual(timezone.localtime(prog.commissioning_date).strftime("%Y-%m-%d"), "2026-06-15")
self.assertEqual(timezone.localtime(prog.uncommissioning_date).strftime("%Y-%m-%d"), "2027-01-01")
def test_programming_detail_view_renders_cms_fields(self):
from assets.models.trafficlights import TrafficLightProgramming
prog = TrafficLightProgramming.objects.create(
code="K999-PRG-VIEW",
intersection=self.intersection,
status="active",
index="03",
plan="Plan Detail",
info="Detailed Programming Info"
)
self.client.force_login(self.user)
response = self.client.get(
reverse("assets:trafficlights_assets_detail", kwargs={
"asset_model": "trafficlightprogramming",
"asset_id": prog.id
})
)
self.assertEqual(response.status_code, 200)
content = response.content.decode("utf-8")
self.assertIn("K999-PRG-VIEW", content)
self.assertIn("Plan Detail", content)
self.assertIn("Detailed Programming Info", content)
self.assertIn("K999", content)
def test_intersection_detail_view_renders_programmations_tab(self):
from assets.models.trafficlights import TrafficLightProgramming
prog = TrafficLightProgramming.objects.create(
code="K999-PRG-TAB",
intersection=self.intersection,
status="active",
index="01",
plan="Plan Tab"
)
self.client.force_login(self.user)
response = self.client.get(
reverse("assets:trafficlights_intersections_detail", kwargs={
"intersection_id": self.intersection.id
})
)
self.assertEqual(response.status_code, 200)
content = response.content.decode("utf-8")
self.assertIn("K999-PRG-TAB", content)
self.assertIn("assets-programmation", content)
self.assertIn("addProgrammingModal", content)

View file

@ -86,6 +86,7 @@ urlpatterns = [
path('trafficlights/intersections/<int:intersection_id>/document-config/', trafficlights.get_document_config, name='trafficlights_intersections_document_config'),
path('trafficlights/intersections/<str:intersection_code>/', trafficlights.trafficlights_intersections_get_by_code, name='trafficlights_interstrafficlights_intersections_get_by_codeections_detail'),
path('trafficlights/intersections/<int:intersection_id>/add-document/', trafficlights.trafficlights_intersections_add_document, name='trafficlights_intersections_add_document'),
path('trafficlights/intersections/<int:intersection_id>/add-programming/', trafficlights.trafficlights_add_programming, name='trafficlights_add_programming'),
path('trafficlights/intersections/<int:document_id>/delete-document/', trafficlights.trafficlights_intersections_delete_document, name='trafficlights_intersections_delete_document'),
path('trafficlights/assets/', trafficlights.trafficlights_assets, name='trafficlights_assets'),
path('trafficlights/assets/geojson/', trafficlights.trafficlights_assets_geojson, name='trafficlights_assets_geojson'),

View file

@ -457,6 +457,13 @@ def _update_asset_field(asset, field_name, new_value, model_class):
parsed = datetime.strptime(str(new_value), "%Y-%m-%d")
except ValueError:
return False, _("Format de date invalide pour %(field)s") % {"field": field_name}
if isinstance(field_obj, DateTimeField):
from datetime import datetime, time
from django.utils.timezone import make_aware, get_current_timezone, is_aware
if not isinstance(parsed, datetime):
parsed = datetime.combine(parsed, time.min)
if not is_aware(parsed):
parsed = make_aware(parsed, get_current_timezone())
setattr(asset, field_name, parsed)
else:
setattr(asset, field_name, None)
@ -858,12 +865,13 @@ def create_asset(request, thematic_code, location_type, location_id):
'success': False,
'error': _("Le modèle d'asset est requis pour ce type d'asset")
}, status=400)
except model_class._meta.get_field('model').related_model.DoesNotExist:
return JsonResponse({
'success': False,
'error': _("Modèle d'asset non trouvé")
}, status=400)
except Exception:
except Exception as e:
# Check if it was a DoesNotExist on model_id
if model_id and 'DoesNotExist' in e.__class__.__name__:
return JsonResponse({
'success': False,
'error': _("Modèle d'asset non trouvé")
}, status=400)
# No 'model' field on this asset type, that's OK
pass
@ -896,6 +904,7 @@ def create_asset(request, thematic_code, location_type, location_id):
'success': True,
'message': _("Asset créé avec succès"),
'asset_id': new_asset.id,
'asset_type': model_class._meta.model_name,
'asset_code': new_asset.code
})
@ -905,7 +914,10 @@ def _generate_asset_code(model_class, location):
location_code = getattr(location, 'code', 'AST')
# Get count of existing assets at this location
model_name = model_class._meta.model_name.upper()[:3]
if model_class._meta.model_name.lower() == 'trafficlightprogramming':
model_name = 'PRG'
else:
model_name = model_class._meta.model_name.upper()[:3]
base_code = f"{location_code}-{model_name}"
# Find next available number
@ -1369,6 +1381,14 @@ CATEGORY_ASSET_MAPPING = {
'TL_DETEC_OTHER': ('TrafficLightDetector', 'TrafficLightDetectorModel'),
'TL_BORNIER': ('TrafficLightAccessory', 'TrafficLightAccessoryModel'),
'TL_DIVERS': ('TrafficLightAccessory', 'TrafficLightAccessoryModel'),
'trafficlights_programming': ('TrafficLightProgramming', None),
'trafficlights_programmation': ('TrafficLightProgramming', None),
'trafficlights_tl_programming': ('TrafficLightProgramming', None),
'trafficlights_tl_programmation': ('TrafficLightProgramming', None),
'tl_programming': ('TrafficLightProgramming', None),
'tl_programmation': ('TrafficLightProgramming', None),
'programming': ('TrafficLightProgramming', None),
'programmation': ('TrafficLightProgramming', None),
# Public Lighting categories
'publiclighting_pole': ('PublicLightingPole', 'PublicLightingPoleModel'),
'LI_poles': ('PublicLightingPole', 'PublicLightingPoleModel'),
@ -1441,7 +1461,7 @@ def _import_asset_classes(thematic_code, class_names):
import importlib
module = importlib.import_module(module_name)
asset_class = getattr(module, asset_class_name, None)
model_class = getattr(module, model_class_name, None)
model_class = getattr(module, model_class_name, None) if model_class_name else None
return asset_class, model_class
except (ImportError, AttributeError):
return None, None
@ -1652,7 +1672,8 @@ def create_asset_api(request):
if hasattr(new_asset, 'category'):
new_asset.category = category
new_asset.model = asset_model_instance
if hasattr(new_asset, 'model'):
new_asset.model = asset_model_instance
new_asset.status = 'active'
new_asset.validation_status = 'to_be_validated'
new_asset.installation_date = timezone.now()
@ -1709,6 +1730,13 @@ def create_asset_api(request):
except TrafficLightPole.DoesNotExist:
pass
# Set additional data
extra_data = data.get('data', {})
if isinstance(extra_data, dict):
for field_name, value in extra_data.items():
if hasattr(new_asset, field_name) and field_name not in ('id', 'code'):
setattr(new_asset, field_name, value)
# Assign position from location / hierarchy
location = getattr(new_asset, 'location', None) or getattr(new_asset, 'intersection', None)
_assign_default_position(new_asset, location, thematic_code)
@ -1749,6 +1777,7 @@ def create_asset_api(request):
'success': True,
'message': success_message,
'asset_id': new_asset.id,
'asset_type': asset_class._meta.model_name,
'asset_code': new_asset.code,
'intervention_linked': intervention_linked,
'operations_created': operations_created,
@ -1797,11 +1826,13 @@ def get_available_locations_for_asset(request, thematic_code, asset_id):
elif thematic_code == 'trafficlights':
from assets.models.trafficlights import (
TrafficLightPole, TrafficLightCable, TrafficLightLantern,
TrafficLightController, TrafficLightDetector, TrafficLightElectricalCabinet
TrafficLightController, TrafficLightDetector, TrafficLightElectricalCabinet,
TrafficLightProgramming, TrafficLightRadar, TrafficLightRadarPole, TrafficLightAccessory
)
# Try each possible class
for cls in [TrafficLightPole, TrafficLightCable, TrafficLightLantern,
TrafficLightController, TrafficLightDetector, TrafficLightElectricalCabinet]:
TrafficLightController, TrafficLightDetector, TrafficLightElectricalCabinet,
TrafficLightProgramming, TrafficLightRadar, TrafficLightRadarPole, TrafficLightAccessory]:
try:
asset = cls.objects.get(pk=asset_id)
break

View file

@ -34,7 +34,7 @@ from common.models import Thematic, UserConfig, UserContractAccess, UserThematic
from common.utils import check_thematic_access
from interventions.models import InterventionLocation
from interventions.views.drafts import InterventionDraftManager
from assets.models import TrafficLightIntersection, TrafficLightIntersectionDocument, TrafficLightController, TrafficLightPole, TrafficLightCable, TrafficLightLantern, TrafficLightDetector, TrafficLightElectricalCabinet, TrafficLightRadar, TrafficLightRadarPole
from assets.models import TrafficLightIntersection, TrafficLightIntersectionDocument, TrafficLightController, TrafficLightPole, TrafficLightCable, TrafficLightLantern, TrafficLightDetector, TrafficLightElectricalCabinet, TrafficLightRadar, TrafficLightRadarPole, TrafficLightProgramming
from assets.models import AssetCategory, TrafficLightCableModel, TrafficLightControllerModel, TrafficLightDetectorModel, TrafficLightLanternModel, TrafficLightPoleModel, TrafficLightElectricalCabinetModel, TrafficLightContract, TrafficLightRadarModel
from assets.forms import IntersectionDocumentForm
from assets.permissions import get_allowed_actions_for_thematic, can_edit_location_for_thematic
@ -758,6 +758,97 @@ def trafficlights_intersections_delete_document(request, document_id):
return redirect('assets:trafficlights_intersections_detail', intersection_id=intersection_id)
@require_POST
@check_thematic_access('trafficlights')
def trafficlights_add_programming(request, intersection_id):
intersection = get_object_or_404(TrafficLightIntersection, pk=intersection_id)
# Check create permission
thematic = Thematic.objects.get(code='trafficlights')
allowed_actions = get_allowed_actions_for_thematic(request.user, thematic)
if 'create' not in allowed_actions:
return JsonResponse({'success': False, 'error': _("Permission refusée")}, status=403)
from assets.views.asset_editing import _generate_asset_code
from django.db import transaction
from django.utils import timezone
code = request.POST.get('code', '').strip()
name_fr = request.POST.get('name_fr', '').strip()
name_nl = request.POST.get('name_nl', '').strip()
index = request.POST.get('index', '').strip()
plan = request.POST.get('plan', '').strip()
commissioning_date_str = request.POST.get('commissioning_date', '').strip()
uncommissioning_date_str = request.POST.get('uncommissioning_date', '').strip()
status = request.POST.get('status', 'active').strip() or 'active'
info = request.POST.get('info', '').strip()
with transaction.atomic():
category = AssetCategory.objects.filter(thematic=thematic, code__in=['TL_PROGRAMMING', 'trafficlights_programming']).first()
prog = TrafficLightProgramming(
intersection=intersection,
category=category,
status=status,
validation_status='to_be_validated',
name_fr=name_fr if name_fr else None,
name_nl=name_nl if name_nl else None,
index=index if index else None,
plan=plan if plan else None,
info=info if info else None,
)
if not code:
prog.code = _generate_asset_code(TrafficLightProgramming, intersection)
else:
if TrafficLightProgramming.objects.filter(code=code).exists():
return JsonResponse({'success': False, 'error': _("Un équipement avec ce code existe déjà")}, status=400)
prog.code = code
if commissioning_date_str:
from django.utils.dateparse import parse_datetime, parse_date
parsed = parse_datetime(commissioning_date_str) or parse_date(commissioning_date_str)
if parsed:
if not getattr(parsed, 'tzinfo', None) and hasattr(parsed, 'hour'):
parsed = make_aware(parsed, get_current_timezone())
prog.commissioning_date = parsed
prog.installation_date = parsed
else:
prog.installation_date = timezone.now()
if uncommissioning_date_str:
from django.utils.dateparse import parse_datetime, parse_date
parsed = parse_datetime(uncommissioning_date_str) or parse_date(uncommissioning_date_str)
if parsed:
if not getattr(parsed, 'tzinfo', None) and hasattr(parsed, 'hour'):
parsed = make_aware(parsed, get_current_timezone())
prog.uncommissioning_date = parsed
prog.save()
# Handle optional programming file upload
uploaded_file = request.FILES.get('file')
if uploaded_file:
doc = TrafficLightIntersectionDocument(
intersection=intersection,
programming=prog,
document_type='programming_file',
uploaded_by=request.user,
)
doc.file.save(uploaded_file.name, uploaded_file, save=True)
if request.headers.get('x-requested-with') != 'XMLHttpRequest' and request.content_type and 'multipart/form-data' in request.content_type:
return redirect(f"{reverse('assets:trafficlights_intersections_detail', kwargs={'intersection_id': intersection.id})}#assets-programmation")
return JsonResponse({
'success': True,
'message': _("Programmation ajoutée avec succès"),
'asset_id': prog.id,
'asset_code': prog.code,
'redirect_url': prog.get_absolute_url()
})
@check_thematic_access('trafficlights')
def fetch_document_history(request):
intersection_id = request.GET.get('intersection_id')

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,393 +17,393 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: loko/authorizations/admin.py:28
#: loko/authorizations/templates/authorizations/authorization_detail.html:73
#: loko/authorizations/templates/authorizations/authorization_list.html:73
#: loko/authorizations/templates/authorizations/authorization_list.html:139
#: authorizations/admin.py:28
#: authorizations/templates/authorizations/authorization_detail.html:73
#: authorizations/templates/authorizations/authorization_list.html:73
#: authorizations/templates/authorizations/authorization_list.html:139
msgid "Type"
msgstr "Type"
#: loko/authorizations/admin.py:46
#: authorizations/admin.py:46
msgid "Expiré"
msgstr "Expired"
#: loko/authorizations/forms.py:62
#: authorizations/forms.py:62
msgid "Veuillez dessiner la zone concernée sur la carte."
msgstr "Please draw the relevant area on the map."
#: loko/authorizations/forms.py:66
#: authorizations/forms.py:66
msgid "Géométrie invalide."
msgstr "Invalid geometry."
#: loko/authorizations/forms.py:68
#: authorizations/forms.py:68
msgid "Veuillez dessiner un polygone."
msgstr "Please draw a polygon."
#: loko/authorizations/forms.py:77
#: loko/authorizations/templates/authorizations/authorization_detail.html:175
#: authorizations/forms.py:77
#: authorizations/templates/authorizations/authorization_detail.html:175
msgid "Description du document"
msgstr "Document description"
#: loko/authorizations/forms.py:127
#: authorizations/forms.py:127
msgid "Inclure les archives (> 2 ans)"
msgstr "Include archives (> 2 years)"
#: loko/authorizations/forms.py:132
#: authorizations/forms.py:132
msgid "Type d'autorisation"
msgstr "Authorisation type"
#: loko/authorizations/forms.py:140
#: authorizations/forms.py:140
msgid "Recherche…"
msgstr "Search…"
#: loko/authorizations/models.py:17
#: authorizations/models.py:17
msgid "Affichage (panneau, ...)"
msgstr "Display (panel, ...)"
#: loko/authorizations/models.py:18
#: authorizations/models.py:18
msgid "Terrasse"
msgstr "Terrace"
#: loko/authorizations/models.py:19
#: authorizations/models.py:19
msgid "Mobilier urbain"
msgstr "Street furniture"
#: loko/authorizations/models.py:20
#: authorizations/models.py:20
msgid "Œuvre d'art"
msgstr "Artwork"
#: loko/authorizations/models.py:21
#: authorizations/models.py:21
msgid "Nouvel Emplacement PMR"
msgstr "New PRM parking space"
#: loko/authorizations/models.py:22
#: authorizations/models.py:22
msgid "Nouvelle Zone de livraison"
msgstr "New delivery zone"
#: loko/authorizations/models.py:23
#: authorizations/models.py:23
msgid "Tournage audiovisuel"
msgstr "Audiovisual filming"
#: loko/authorizations/models.py:24
#: authorizations/models.py:24
msgid "Evénement"
msgstr "Event"
#: loko/authorizations/models.py:25
#: authorizations/models.py:25
msgid "Plante grimpante"
msgstr "Climbing plant"
#: loko/authorizations/models.py:26
#: authorizations/models.py:26
msgid "Pied d'arbre"
msgstr "Tree base"
#: loko/authorizations/models.py:30
#: authorizations/models.py:30
msgid "À traiter"
msgstr "To be processed"
#: loko/authorizations/models.py:31
#: authorizations/models.py:31
msgid "En cours"
msgstr "In progress"
#: loko/authorizations/models.py:32
#: authorizations/models.py:32
msgid "Autorisé"
msgstr "Authorised"
#: loko/authorizations/models.py:33
#: authorizations/models.py:33
msgid "Refusé"
msgstr "Refused"
#: loko/authorizations/models.py:34
#: authorizations/models.py:34
msgid "Clôturé"
msgstr "Closed"
#: loko/authorizations/models.py:45
#: authorizations/models.py:45
msgid "Langue"
msgstr "Language"
#: loko/authorizations/models.py:49 loko/authorizations/models.py:201
#: authorizations/models.py:49 authorizations/models.py:201
msgid "Email vérifié"
msgstr "Email verified"
#: loko/authorizations/models.py:50
#: authorizations/models.py:50
msgid "Indique si l'adresse email du demandeur a été vérifiée."
msgstr "Indicates whether the applicant's email address has been verified."
#: loko/authorizations/models.py:52
#: authorizations/models.py:52
msgid "Type d'occupation"
msgstr "Occupation type"
#: loko/authorizations/models.py:53
#: loko/authorizations/templates/authorizations/authorization_detail.html:92
#: authorizations/models.py:53
#: authorizations/templates/authorizations/authorization_detail.html:92
msgid "Description de la demande"
msgstr "Request description"
#: loko/authorizations/models.py:54
#: loko/authorizations/templates/authorizations/authorization_detail.html:105
#: authorizations/models.py:54
#: authorizations/templates/authorizations/authorization_detail.html:105
msgid "Nom"
msgstr "Name"
#: loko/authorizations/models.py:55 loko/authorizations/models.py:197
#: loko/authorizations/templates/authorizations/authorization_detail.html:108
#: authorizations/models.py:55 authorizations/models.py:197
#: authorizations/templates/authorizations/authorization_detail.html:108
msgid "Email"
msgstr "Email"
#: loko/authorizations/models.py:56
#: loko/authorizations/templates/authorizations/authorization_detail.html:113
#: authorizations/models.py:56
#: authorizations/templates/authorizations/authorization_detail.html:113
msgid "Adresse"
msgstr "Address"
#: loko/authorizations/models.py:57
#: loko/authorizations/templates/authorizations/authorization_detail.html:117
#: authorizations/models.py:57
#: authorizations/templates/authorizations/authorization_detail.html:117
msgid "Entreprise"
msgstr "Company"
#: loko/authorizations/models.py:64
#: authorizations/models.py:64
msgid "Agent traitant"
msgstr "Handling agent"
#: loko/authorizations/models.py:66
#: authorizations/models.py:66
msgid "Commentaire"
msgstr "Comment"
#: loko/authorizations/models.py:67
#: authorizations/models.py:67
msgid "Localisation – Adresse"
msgstr "Location – Address"
#: loko/authorizations/models.py:68
#: loko/authorizations/templates/authorizations/authorization_detail.html:95
#: loko/authorizations/templates/authorizations/authorization_detail.html:228
#: loko/authorizations/templates/authorizations/authorization_list.html:142
#: authorizations/models.py:68
#: authorizations/templates/authorizations/authorization_detail.html:95
#: authorizations/templates/authorizations/authorization_detail.html:228
#: authorizations/templates/authorizations/authorization_list.html:142
msgid "Localisation"
msgstr "Location"
#: loko/authorizations/models.py:107
#: authorizations/models.py:107
msgid "Autorisation d'occupation de l'espace public"
msgstr ""
#: loko/authorizations/models.py:108
#: authorizations/models.py:108
msgid "Autorisations d'occupation de l'espace public"
msgstr ""
#: loko/authorizations/models.py:146
#: authorizations/models.py:146
#, python-format
msgid "La taille maximale du fichier est de %(limit)s Mo."
msgstr "The maximum file size is %(limit)s MB."
#: loko/authorizations/models.py:151
#: loko/authorizations/templates/authorizations/authorization_detail.html:179
#: authorizations/models.py:151
#: authorizations/templates/authorizations/authorization_detail.html:179
msgid "Fichier"
msgstr "File"
#: loko/authorizations/models.py:155
#: authorizations/models.py:155
msgid "Description"
msgstr "Description"
#: loko/authorizations/models.py:163
#: authorizations/models.py:163
msgid "Document"
msgstr "Document"
#: loko/authorizations/models.py:164
#: authorizations/models.py:164
msgid "Documents"
msgstr "Documents"
#: loko/authorizations/models.py:176
#: authorizations/models.py:176
msgid "Début de l'occupation"
msgstr "Start of occupation"
#: loko/authorizations/models.py:177
#: authorizations/models.py:177
msgid "Fin de l'occupation"
msgstr "End of occupation"
#: loko/authorizations/models.py:180
#: authorizations/models.py:180
msgid "Date d'occupation"
msgstr "Occupation date"
#: loko/authorizations/models.py:181
#: loko/authorizations/templates/authorizations/authorization_detail.html:127
#: authorizations/models.py:181
#: authorizations/templates/authorizations/authorization_detail.html:127
msgid "Dates d'occupation"
msgstr "Occupation dates"
#: loko/authorizations/models.py:202
#: authorizations/models.py:202
msgid "Emails vérifiés"
msgstr "Verified emails"
#: loko/authorizations/models.py:247
#: authorizations/models.py:247
msgid "Code de vérification"
msgstr "Verification code"
#: loko/authorizations/models.py:248
#: authorizations/models.py:248
msgid "Codes de vérification"
msgstr "Verification codes"
#: loko/authorizations/templates/authorizations/authorization_detail.html:12
#: authorizations/templates/authorizations/authorization_detail.html:12
msgid "Retour à la liste"
msgstr "Back to list"
#: loko/authorizations/templates/authorizations/authorization_detail.html:13
#: loko/authorizations/templates/authorizations/authorization_detail.html:27
#: authorizations/templates/authorizations/authorization_detail.html:13
#: authorizations/templates/authorizations/authorization_detail.html:27
msgid "Retour"
msgstr "Back"
#: loko/authorizations/templates/authorizations/authorization_detail.html:23
#: authorizations/templates/authorizations/authorization_detail.html:23
msgid "Demande"
msgstr "Request"
#: loko/authorizations/templates/authorizations/authorization_detail.html:52
#: authorizations/templates/authorizations/authorization_detail.html:52
msgid "Informations générales"
msgstr "General information"
#: loko/authorizations/templates/authorizations/authorization_detail.html:55
#: loko/authorizations/templates/authorizations/authorization_list.html:138
#: authorizations/templates/authorizations/authorization_detail.html:55
#: authorizations/templates/authorizations/authorization_list.html:138
msgid "Code"
msgstr "Code"
#: loko/authorizations/templates/authorizations/authorization_detail.html:58
#: loko/authorizations/templates/authorizations/authorization_list.html:140
#: authorizations/templates/authorizations/authorization_detail.html:58
#: authorizations/templates/authorizations/authorization_list.html:140
msgid "Statut"
msgstr "Status"
#: loko/authorizations/templates/authorizations/authorization_detail.html:76
#: authorizations/templates/authorizations/authorization_detail.html:76
msgid "Créé le"
msgstr "Created on"
#: loko/authorizations/templates/authorizations/authorization_detail.html:79
#: authorizations/templates/authorizations/authorization_detail.html:79
msgid "Mis à jour"
msgstr "Updated"
#: loko/authorizations/templates/authorizations/authorization_detail.html:83
#: authorizations/templates/authorizations/authorization_detail.html:83
msgid "Agent"
msgstr "Agent"
#: loko/authorizations/templates/authorizations/authorization_detail.html:102
#: loko/authorizations/templates/authorizations/authorization_list.html:141
#: authorizations/templates/authorizations/authorization_detail.html:102
#: authorizations/templates/authorizations/authorization_list.html:141
msgid "Demandeur"
msgstr "Applicant"
#: loko/authorizations/templates/authorizations/authorization_detail.html:132
#: authorizations/templates/authorizations/authorization_detail.html:132
msgid "Début"
msgstr "Start"
#: loko/authorizations/templates/authorizations/authorization_detail.html:133
#: authorizations/templates/authorizations/authorization_detail.html:133
msgid "Fin"
msgstr "End"
#: loko/authorizations/templates/authorizations/authorization_detail.html:151
#: authorizations/templates/authorizations/authorization_detail.html:151
msgid "Documents joints"
msgstr "Attached documents"
#: loko/authorizations/templates/authorizations/authorization_detail.html:167
#: authorizations/templates/authorizations/authorization_detail.html:167
msgid "Aucun document joint."
msgstr "Attached documents"
#: loko/authorizations/templates/authorizations/authorization_detail.html:176
#: authorizations/templates/authorizations/authorization_detail.html:176
msgid "Ex: Arrêté de police"
msgstr ""
#: loko/authorizations/templates/authorizations/authorization_detail.html:183
#: authorizations/templates/authorizations/authorization_detail.html:183
msgid "Ajouter"
msgstr "Add a date"
#: loko/authorizations/templates/authorizations/authorization_detail.html:194
#: authorizations/templates/authorizations/authorization_detail.html:194
msgid "Traitement de la demande"
msgstr "Request description"
#: loko/authorizations/templates/authorizations/authorization_detail.html:201
#: authorizations/templates/authorizations/authorization_detail.html:201
msgid "Modifier le statut"
msgstr "Modifier le statut"
#: loko/authorizations/templates/authorizations/authorization_detail.html:211
#: authorizations/templates/authorizations/authorization_detail.html:211
msgid "Commentaire agent"
msgstr "Agent comment"
#: loko/authorizations/templates/authorizations/authorization_detail.html:212
#: authorizations/templates/authorizations/authorization_detail.html:212
msgid "Saisir un commentaire ou des notes..."
msgstr "Saisir un commentaire ou des notes..."
#: loko/authorizations/templates/authorizations/authorization_detail.html:216
#: authorizations/templates/authorizations/authorization_detail.html:216
msgid "Enregistrer le traitement"
msgstr "Enregistrer le traitement"
#: loko/authorizations/templates/authorizations/authorization_list.html:41
#: loko/authorizations/templates/authorizations/authorization_list.html:42
#: loko/authorizations/templates/authorizations/authorization_list.html:58
#: authorizations/templates/authorizations/authorization_list.html:41
#: authorizations/templates/authorizations/authorization_list.html:42
#: authorizations/templates/authorizations/authorization_list.html:58
msgid "Formulaire public"
msgstr "Public form"
#: loko/authorizations/templates/authorizations/authorization_list.html:45
#: authorizations/templates/authorizations/authorization_list.html:45
msgid "Liste"
msgstr "List"
#: loko/authorizations/templates/authorizations/authorization_list.html:46
#: authorizations/templates/authorizations/authorization_list.html:46
msgid "Liste des demandes"
msgstr "List of requests"
#: loko/authorizations/templates/authorizations/authorization_list.html:55
#: authorizations/templates/authorizations/authorization_list.html:55
msgid "Demandes d'autorisation d'occupation de l'espace public"
msgstr "Public space occupation authorization requests"
#: loko/authorizations/templates/authorizations/authorization_list.html:68
#: authorizations/templates/authorizations/authorization_list.html:68
msgid "Recherche"
msgstr "Search"
#: loko/authorizations/templates/authorizations/authorization_list.html:82
#: loko/authorizations/templates/authorizations/authorization_list.html:207
#: authorizations/templates/authorizations/authorization_list.html:82
#: authorizations/templates/authorizations/authorization_list.html:207
msgid "Tous les types"
msgstr "All types"
#: loko/authorizations/templates/authorizations/authorization_list.html:89
#: authorizations/templates/authorizations/authorization_list.html:89
msgid "Rechercher un type..."
msgstr "Search"
#: loko/authorizations/templates/authorizations/authorization_list.html:92
#: loko/authorizations/templates/authorizations/new_authorization_default.html:226
#: authorizations/templates/authorizations/authorization_list.html:92
#: authorizations/templates/authorizations/new_authorization_default.html:226
msgid "Effacer"
msgstr "Clear"
#: loko/authorizations/templates/authorizations/authorization_list.html:106
#: authorizations/templates/authorizations/authorization_list.html:106
msgid "Aucun type correspondant"
msgstr "Aucun type correspondant"
#: loko/authorizations/templates/authorizations/authorization_list.html:121
#: authorizations/templates/authorizations/authorization_list.html:121
msgid "Filtrer"
msgstr "Filter"
#: loko/authorizations/templates/authorizations/authorization_list.html:143
#: authorizations/templates/authorizations/authorization_list.html:143
msgid "Date de création"
msgstr "Creation date"
#: loko/authorizations/templates/authorizations/authorization_list.html:177
#: authorizations/templates/authorizations/authorization_list.html:177
msgid "Aucune demande trouvée."
msgstr "No request found."
#: loko/authorizations/templates/authorizations/authorization_list.html:215
#: authorizations/templates/authorizations/authorization_list.html:215
msgid "types sélectionnés"
msgstr ""
#: loko/authorizations/templates/authorizations/authorization_success.html:9
#: loko/authorizations/templates/authorizations/authorization_success.html:37
#: authorizations/templates/authorizations/authorization_success.html:9
#: authorizations/templates/authorizations/authorization_success.html:37
msgid "Demande enregistrée"
msgstr "Request saved"
#: loko/authorizations/templates/authorizations/authorization_success.html:28
#: loko/authorizations/templates/authorizations/email_verification_failed.html:28
#: loko/authorizations/templates/authorizations/email_verification_pending.html:28
#: loko/authorizations/templates/authorizations/email_verify_code.html:35
#: loko/authorizations/templates/authorizations/new_authorization_default.html:9
#: loko/authorizations/templates/authorizations/new_authorization_default.html:99
#: loko/authorizations/templates/authorizations/new_authorization_default.html:376
#: authorizations/templates/authorizations/authorization_success.html:28
#: authorizations/templates/authorizations/email_verification_failed.html:28
#: authorizations/templates/authorizations/email_verification_pending.html:28
#: authorizations/templates/authorizations/email_verify_code.html:35
#: authorizations/templates/authorizations/new_authorization_default.html:9
#: authorizations/templates/authorizations/new_authorization_default.html:99
#: authorizations/templates/authorizations/new_authorization_default.html:376
msgid "Demande d'occupation de l'espace public"
msgstr "Public space occupation request"
#: loko/authorizations/templates/authorizations/authorization_success.html:41
#: authorizations/templates/authorizations/authorization_success.html:41
msgid "Numéro de référence"
msgstr "Reference number"
#: loko/authorizations/templates/authorizations/authorization_success.html:43
#: authorizations/templates/authorizations/authorization_success.html:43
msgid "Conservez ce numéro pour le suivi de votre dossier."
msgstr "Keep this number to track your application."
#: loko/authorizations/templates/authorizations/authorization_success.html:49
#: authorizations/templates/authorizations/authorization_success.html:49
msgid ""
"Votre adresse email a été confirmée et votre demande d'autorisation "
"d'occupation de l'espace public a bien été enregistrée. Un accusé de "
@ -414,7 +414,7 @@ msgstr ""
"request has been registered. An acknowledgement of receipt has been sent to "
"you by email. Our services will contact you as soon as possible."
#: loko/authorizations/templates/authorizations/authorization_success.html:55
#: authorizations/templates/authorizations/authorization_success.html:55
msgid ""
"Votre demande d'autorisation d'occupation de l'espace public a bien été "
"enregistrée. Un accusé de réception vous a été envoyé par email. Nos "
@ -424,20 +424,20 @@ msgstr ""
"of receipt has been sent to you by email. Our services will contact you as "
"soon as possible.contact you as soon as possible."
#: loko/authorizations/templates/authorizations/authorization_success.html:64
#: authorizations/templates/authorizations/authorization_success.html:64
msgid "Faire une nouvelle demande"
msgstr "Submit a new request"
#: loko/authorizations/templates/authorizations/email_verification_failed.html:9
#: loko/authorizations/templates/authorizations/email_verification_failed.html:47
#: authorizations/templates/authorizations/email_verification_failed.html:9
#: authorizations/templates/authorizations/email_verification_failed.html:47
msgid "Lien invalide"
msgstr "Invalid link"
#: loko/authorizations/templates/authorizations/email_verification_failed.html:39
#: authorizations/templates/authorizations/email_verification_failed.html:39
msgid "Lien expiré"
msgstr "Expired link"
#: loko/authorizations/templates/authorizations/email_verification_failed.html:41
#: authorizations/templates/authorizations/email_verification_failed.html:41
msgid ""
"Le lien de confirmation que vous avez utilisé n'est plus valide (délai de 48 "
"heures dépassé). Veuillez soumettre une nouvelle demande."
@ -445,7 +445,7 @@ msgstr ""
"The confirmation link you used is no longer valid (48-hour deadline "
"exceeded). Please submit a new request."
#: loko/authorizations/templates/authorizations/email_verification_failed.html:49
#: authorizations/templates/authorizations/email_verification_failed.html:49
msgid ""
"Le lien de confirmation que vous avez utilisé est invalide ou a déjà été "
"utilisé. Si votre demande a déjà été validée, vous pouvez en soumettre une "
@ -454,21 +454,21 @@ msgstr ""
"The confirmation link you used is invalid or has already been used. If your "
"request has already been validated, you can submit a new one."
#: loko/authorizations/templates/authorizations/email_verification_failed.html:58
#: loko/authorizations/templates/authorizations/email_verify_code.html:55
#: loko/authorizations/templates/authorizations/email_verify_code.html:72
#: authorizations/templates/authorizations/email_verification_failed.html:58
#: authorizations/templates/authorizations/email_verify_code.html:55
#: authorizations/templates/authorizations/email_verify_code.html:72
msgid "Nouvelle demande"
msgstr "New request"
#: loko/authorizations/templates/authorizations/email_verification_pending.html:9
#: authorizations/templates/authorizations/email_verification_pending.html:9
msgid "Confirmation de votre email"
msgstr "Email confirmation"
#: loko/authorizations/templates/authorizations/email_verification_pending.html:37
#: authorizations/templates/authorizations/email_verification_pending.html:37
msgid "Vérifiez votre boîte email"
msgstr "Check your inbox"
#: loko/authorizations/templates/authorizations/email_verification_pending.html:39
#: authorizations/templates/authorizations/email_verification_pending.html:39
msgid ""
"Votre demande a bien été reçue. Pour la finaliser, veuillez confirmer votre "
"adresse email en cliquant sur le lien que nous venons de vous envoyer."
@ -476,7 +476,7 @@ msgstr ""
"Your request has been received. To finalise it, please confirm your email "
"address by clicking the link we have just sent you."
#: loko/authorizations/templates/authorizations/email_verification_pending.html:47
#: authorizations/templates/authorizations/email_verification_pending.html:47
msgid ""
"Le lien de confirmation est valable 48 heures. Si vous ne trouvez pas "
"l'email, vérifiez votre dossier de courrier indésirable (spam)."
@ -484,19 +484,19 @@ msgstr ""
"The confirmation link is valid for 48 hours. If you cannot find the email, "
"please check your junk/spam folder."
#: loko/authorizations/templates/authorizations/email_verification_pending.html:55
#: authorizations/templates/authorizations/email_verification_pending.html:55
msgid "Retour au formulaire"
msgstr "Back to the form"
#: loko/authorizations/templates/authorizations/email_verify_code.html:9
#: authorizations/templates/authorizations/email_verify_code.html:9
msgid "Vérification de votre email"
msgstr "Email verification"
#: loko/authorizations/templates/authorizations/email_verify_code.html:46
#: authorizations/templates/authorizations/email_verify_code.html:46
msgid "Code expiré"
msgstr "Code expired"
#: loko/authorizations/templates/authorizations/email_verify_code.html:48
#: authorizations/templates/authorizations/email_verify_code.html:48
msgid ""
"Le code de vérification est arrivé à expiration (validité&nbsp;: "
"10&nbsp;minutes). Veuillez soumettre une nouvelle demande pour recevoir un "
@ -505,11 +505,11 @@ msgstr ""
"The verification code has expired (validity:&nbsp;10&nbsp;minutes). Please "
"submit a new request to receive a new code."
#: loko/authorizations/templates/authorizations/email_verify_code.html:63
#: authorizations/templates/authorizations/email_verify_code.html:63
msgid "Trop de tentatives"
msgstr "Too many attempts"
#: loko/authorizations/templates/authorizations/email_verify_code.html:65
#: authorizations/templates/authorizations/email_verify_code.html:65
msgid ""
"Le nombre maximum de tentatives a été atteint. Votre code est bloqué. "
"Veuillez soumettre une nouvelle demande."
@ -517,11 +517,11 @@ msgstr ""
"The maximum number of attempts has been reached. Your code is blocked. "
"Please submit a new request."
#: loko/authorizations/templates/authorizations/email_verify_code.html:80
#: authorizations/templates/authorizations/email_verify_code.html:80
msgid "Entrez votre code de vérification"
msgstr "Enter your verification code"
#: loko/authorizations/templates/authorizations/email_verify_code.html:82
#: authorizations/templates/authorizations/email_verify_code.html:82
#, python-format
msgid ""
"Un code à 6 chiffres a été envoyé à <strong>%(email)s</strong>. Saisissez-le "
@ -530,60 +530,60 @@ msgstr ""
"A 6-digit code has been sent to <strong>%(email)s</strong>. Enter it below. "
"It is valid for 10&nbsp;minutes."
#: loko/authorizations/templates/authorizations/email_verify_code.html:92
#: authorizations/templates/authorizations/email_verify_code.html:92
msgid "Code incorrect. Vérifiez l'email reçu et réessayez."
msgstr "Incorrect code. Check the email you received and try again."
#: loko/authorizations/templates/authorizations/email_verify_code.html:115
#: authorizations/templates/authorizations/email_verify_code.html:115
msgid "Code de vérification à 6 chiffres"
msgstr "6-digit verification code"
#: loko/authorizations/templates/authorizations/email_verify_code.html:118
#: authorizations/templates/authorizations/email_verify_code.html:118
msgid "Vérifier"
msgstr "Verify"
#: loko/authorizations/templates/authorizations/email_verify_code.html:124
#: authorizations/templates/authorizations/email_verify_code.html:124
msgid ""
"Vous n'avez pas reçu l'email ? Vérifiez votre dossier de courrier "
"indésirable (spam)."
msgstr "Didn't receive the email? Check your junk/spam folder."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:116
#: authorizations/templates/authorizations/new_authorization_default.html:116
msgid ""
"Toute occupation de l'espace public (terrasse, affichage, événement, "
"mobilier, etc.) doit faire l'objet d'une autorisation préalable de la part "
"de l'administration."
msgstr ""
#: loko/authorizations/templates/authorizations/new_authorization_default.html:121
#: authorizations/templates/authorizations/new_authorization_default.html:121
msgid ""
"Veuillez compléter ce formulaire et délimiter la zone concernée sur la carte "
"ci-dessous ainsi que la période souhaitée."
msgstr ""
#: loko/authorizations/templates/authorizations/new_authorization_default.html:126
#: authorizations/templates/authorizations/new_authorization_default.html:126
msgid ""
"Si vous éprouvez des difficultés ou avez des questions, vous pouvez "
"contacter nos services."
msgstr ""
#: loko/authorizations/templates/authorizations/new_authorization_default.html:144
#: authorizations/templates/authorizations/new_authorization_default.html:144
msgid "Votre demande"
msgstr "Your request"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:216
#: authorizations/templates/authorizations/new_authorization_default.html:216
msgid "Localisation (dessiner un polygone pour indiquer la zone concernée)"
msgstr "Location (draw a polygon to indicate the area concerned)"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:220
#: authorizations/templates/authorizations/new_authorization_default.html:220
msgid "Dessiner un polygone"
msgstr "Draw a polygon"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:223
#: authorizations/templates/authorizations/new_authorization_default.html:223
msgid "Terminer"
msgstr "Finish"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:231
#: authorizations/templates/authorizations/new_authorization_default.html:231
msgid ""
"Cliquez sur « Dessiner un polygone » puis cliquez sur la carte pour ajouter "
"des sommets. Cliquez sur le premier sommet pour fermer le polygone."
@ -591,84 +591,84 @@ msgstr ""
"Click « Draw a polygon » then click on the map to add vertices. Click on the "
"first vertex to close the polygon."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:245
#: authorizations/templates/authorizations/new_authorization_default.html:245
msgid "Vos coordonnées"
msgstr "Your contact details"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:278
#: loko/authorizations/templates/authorizations/new_authorization_default.html:317
#: loko/authorizations/templates/authorizations/new_authorization_default.html:337
#: authorizations/templates/authorizations/new_authorization_default.html:278
#: authorizations/templates/authorizations/new_authorization_default.html:317
#: authorizations/templates/authorizations/new_authorization_default.html:337
msgid "optionnel"
msgstr "optional"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:292
#: authorizations/templates/authorizations/new_authorization_default.html:292
msgid "Date(s) d'occupation"
msgstr "Occupation date(s)"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:298
#: authorizations/templates/authorizations/new_authorization_default.html:298
msgid "Veuillez indiquer au moins une date de début d'occupation."
msgstr "Please provide at least one occupation start date."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:328
#: authorizations/templates/authorizations/new_authorization_default.html:328
msgid "Ajouter une date"
msgstr "Add a date"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:336
#: authorizations/templates/authorizations/new_authorization_default.html:336
msgid "Document(s) à joindre"
msgstr "Document(s) to attach"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:360
#: authorizations/templates/authorizations/new_authorization_default.html:360
msgid "Ajouter un document"
msgstr "Add a document"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:367
#: authorizations/templates/authorizations/new_authorization_default.html:367
msgid "Envoyer la demande"
msgstr "Submit the request"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:385
#: authorizations/templates/authorizations/new_authorization_default.html:385
msgid ""
"Veillez à joindre en annexe l'attestation d'assurance couvrant tous les "
"risques."
msgstr "Please attach the insurance certificate covering all risks."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:386
#: authorizations/templates/authorizations/new_authorization_default.html:386
msgid "Veillez à joindre en annexe l'autorisation de la commune."
msgstr "Please attach the municipal authorisation."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:472
#: loko/authorizations/templates/authorizations/new_authorization_default.html:521
#: authorizations/templates/authorizations/new_authorization_default.html:472
#: authorizations/templates/authorizations/new_authorization_default.html:521
msgid "Polygone enregistré. Cliquez sur « Dessiner » pour le redessiner."
msgstr "Polygon saved. Click « Draw » to redraw it."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:492
#: authorizations/templates/authorizations/new_authorization_default.html:492
msgid "Cliquer pour fermer le polygone"
msgstr "Click to close the polygon"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:536
#: authorizations/templates/authorizations/new_authorization_default.html:536
msgid ""
"Cliquez sur « Dessiner un polygone » puis cliquez sur la carte pour ajouter "
"des sommets."
msgstr "Click « Draw a polygon » then click on the map to add vertices."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:559
#: authorizations/templates/authorizations/new_authorization_default.html:559
msgid ""
"Cliquez sur la carte pour ajouter des sommets. Cliquez sur le premier sommet "
"pour fermer le polygone."
msgstr ""
#: loko/authorizations/views.py:326 loko/authorizations/views.py:375
#: authorizations/views.py:326 authorizations/views.py:375
msgid "Vous n'avez pas accès à cette vue."
msgstr ""
#: loko/authorizations/views.py:392
#: authorizations/views.py:392
msgid "La demande a été mise à jour avec succès."
msgstr ""
#: loko/authorizations/views.py:409
#: authorizations/views.py:409
msgid "Le document a été ajouté avec succès."
msgstr ""
#: loko/authorizations/views.py:413
#: authorizations/views.py:413
msgid "Veuillez fournir une description et un fichier."
msgstr "Veuillez fournir une description et un fichier."

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,393 +17,393 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: loko/authorizations/admin.py:28
#: loko/authorizations/templates/authorizations/authorization_detail.html:73
#: loko/authorizations/templates/authorizations/authorization_list.html:73
#: loko/authorizations/templates/authorizations/authorization_list.html:139
#: authorizations/admin.py:28
#: authorizations/templates/authorizations/authorization_detail.html:73
#: authorizations/templates/authorizations/authorization_list.html:73
#: authorizations/templates/authorizations/authorization_list.html:139
msgid "Type"
msgstr "Type"
#: loko/authorizations/admin.py:46
#: authorizations/admin.py:46
msgid "Expiré"
msgstr "Expiré"
#: loko/authorizations/forms.py:62
#: authorizations/forms.py:62
msgid "Veuillez dessiner la zone concernée sur la carte."
msgstr "Veuillez dessiner la zone concernée sur la carte."
#: loko/authorizations/forms.py:66
#: authorizations/forms.py:66
msgid "Géométrie invalide."
msgstr "Géométrie invalide."
#: loko/authorizations/forms.py:68
#: authorizations/forms.py:68
msgid "Veuillez dessiner un polygone."
msgstr "Veuillez dessiner un polygone."
#: loko/authorizations/forms.py:77
#: loko/authorizations/templates/authorizations/authorization_detail.html:175
#: authorizations/forms.py:77
#: authorizations/templates/authorizations/authorization_detail.html:175
msgid "Description du document"
msgstr "Description du document"
#: loko/authorizations/forms.py:127
#: authorizations/forms.py:127
msgid "Inclure les archives (> 2 ans)"
msgstr "Inclure les archives (> 2 ans)"
#: loko/authorizations/forms.py:132
#: authorizations/forms.py:132
msgid "Type d'autorisation"
msgstr "Type d'autorisation"
#: loko/authorizations/forms.py:140
#: authorizations/forms.py:140
msgid "Recherche…"
msgstr "Recherche…"
#: loko/authorizations/models.py:17
#: authorizations/models.py:17
msgid "Affichage (panneau, ...)"
msgstr "Affichage (panneau, ...)"
#: loko/authorizations/models.py:18
#: authorizations/models.py:18
msgid "Terrasse"
msgstr "Terrasse"
#: loko/authorizations/models.py:19
#: authorizations/models.py:19
msgid "Mobilier urbain"
msgstr "Mobilier urbain"
#: loko/authorizations/models.py:20
#: authorizations/models.py:20
msgid "Œuvre d'art"
msgstr "Œuvre d'art"
#: loko/authorizations/models.py:21
#: authorizations/models.py:21
msgid "Nouvel Emplacement PMR"
msgstr "Nouvel Emplacement PMR"
#: loko/authorizations/models.py:22
#: authorizations/models.py:22
msgid "Nouvelle Zone de livraison"
msgstr "Nouvelle Zone de livraison"
#: loko/authorizations/models.py:23
#: authorizations/models.py:23
msgid "Tournage audiovisuel"
msgstr "Tournage audiovisuel"
#: loko/authorizations/models.py:24
#: authorizations/models.py:24
msgid "Evénement"
msgstr "Evénement"
#: loko/authorizations/models.py:25
#: authorizations/models.py:25
msgid "Plante grimpante"
msgstr "Plante grimpante"
#: loko/authorizations/models.py:26
#: authorizations/models.py:26
msgid "Pied d'arbre"
msgstr "Pied d'arbre"
#: loko/authorizations/models.py:30
#: authorizations/models.py:30
msgid "À traiter"
msgstr "À traiter"
#: loko/authorizations/models.py:31
#: authorizations/models.py:31
msgid "En cours"
msgstr "En cours"
#: loko/authorizations/models.py:32
#: authorizations/models.py:32
msgid "Autorisé"
msgstr "Autorisé"
#: loko/authorizations/models.py:33
#: authorizations/models.py:33
msgid "Refusé"
msgstr "Refusé"
#: loko/authorizations/models.py:34
#: authorizations/models.py:34
msgid "Clôturé"
msgstr "Clôturé"
#: loko/authorizations/models.py:45
#: authorizations/models.py:45
msgid "Langue"
msgstr "Langue"
#: loko/authorizations/models.py:49 loko/authorizations/models.py:201
#: authorizations/models.py:49 authorizations/models.py:201
msgid "Email vérifié"
msgstr "Email vérifié"
#: loko/authorizations/models.py:50
#: authorizations/models.py:50
msgid "Indique si l'adresse email du demandeur a été vérifiée."
msgstr "Indique si l'adresse email du demandeur a été vérifiée."
#: loko/authorizations/models.py:52
#: authorizations/models.py:52
msgid "Type d'occupation"
msgstr "Type d'occupation"
#: loko/authorizations/models.py:53
#: loko/authorizations/templates/authorizations/authorization_detail.html:92
#: authorizations/models.py:53
#: authorizations/templates/authorizations/authorization_detail.html:92
msgid "Description de la demande"
msgstr "Description de la demande"
#: loko/authorizations/models.py:54
#: loko/authorizations/templates/authorizations/authorization_detail.html:105
#: authorizations/models.py:54
#: authorizations/templates/authorizations/authorization_detail.html:105
msgid "Nom"
msgstr "Nom"
#: loko/authorizations/models.py:55 loko/authorizations/models.py:197
#: loko/authorizations/templates/authorizations/authorization_detail.html:108
#: authorizations/models.py:55 authorizations/models.py:197
#: authorizations/templates/authorizations/authorization_detail.html:108
msgid "Email"
msgstr "Email"
#: loko/authorizations/models.py:56
#: loko/authorizations/templates/authorizations/authorization_detail.html:113
#: authorizations/models.py:56
#: authorizations/templates/authorizations/authorization_detail.html:113
msgid "Adresse"
msgstr "Adresse"
#: loko/authorizations/models.py:57
#: loko/authorizations/templates/authorizations/authorization_detail.html:117
#: authorizations/models.py:57
#: authorizations/templates/authorizations/authorization_detail.html:117
msgid "Entreprise"
msgstr "Entreprise"
#: loko/authorizations/models.py:64
#: authorizations/models.py:64
msgid "Agent traitant"
msgstr "Agent traitant"
#: loko/authorizations/models.py:66
#: authorizations/models.py:66
msgid "Commentaire"
msgstr "Commentaire"
#: loko/authorizations/models.py:67
#: authorizations/models.py:67
msgid "Localisation – Adresse"
msgstr "Localisation – Adresse"
#: loko/authorizations/models.py:68
#: loko/authorizations/templates/authorizations/authorization_detail.html:95
#: loko/authorizations/templates/authorizations/authorization_detail.html:228
#: loko/authorizations/templates/authorizations/authorization_list.html:142
#: authorizations/models.py:68
#: authorizations/templates/authorizations/authorization_detail.html:95
#: authorizations/templates/authorizations/authorization_detail.html:228
#: authorizations/templates/authorizations/authorization_list.html:142
msgid "Localisation"
msgstr "Localisation"
#: loko/authorizations/models.py:107
#: authorizations/models.py:107
msgid "Autorisation d'occupation de l'espace public"
msgstr "Autorisation d'occupation de l'espace public"
#: loko/authorizations/models.py:108
#: authorizations/models.py:108
msgid "Autorisations d'occupation de l'espace public"
msgstr "Autorisations d'occupation de l'espace public"
#: loko/authorizations/models.py:146
#: authorizations/models.py:146
#, python-format
msgid "La taille maximale du fichier est de %(limit)s Mo."
msgstr "La taille maximale du fichier est de %(limit)s Mo."
#: loko/authorizations/models.py:151
#: loko/authorizations/templates/authorizations/authorization_detail.html:179
#: authorizations/models.py:151
#: authorizations/templates/authorizations/authorization_detail.html:179
msgid "Fichier"
msgstr "Fichier"
#: loko/authorizations/models.py:155
#: authorizations/models.py:155
msgid "Description"
msgstr "Description"
#: loko/authorizations/models.py:163
#: authorizations/models.py:163
msgid "Document"
msgstr "Document"
#: loko/authorizations/models.py:164
#: authorizations/models.py:164
msgid "Documents"
msgstr "Documents"
#: loko/authorizations/models.py:176
#: authorizations/models.py:176
msgid "Début de l'occupation"
msgstr "Début de l'occupation"
#: loko/authorizations/models.py:177
#: authorizations/models.py:177
msgid "Fin de l'occupation"
msgstr "Fin de l'occupation"
#: loko/authorizations/models.py:180
#: authorizations/models.py:180
msgid "Date d'occupation"
msgstr "Date d'occupation"
#: loko/authorizations/models.py:181
#: loko/authorizations/templates/authorizations/authorization_detail.html:127
#: authorizations/models.py:181
#: authorizations/templates/authorizations/authorization_detail.html:127
msgid "Dates d'occupation"
msgstr "Dates d'occupation"
#: loko/authorizations/models.py:202
#: authorizations/models.py:202
msgid "Emails vérifiés"
msgstr "Emails vérifiés"
#: loko/authorizations/models.py:247
#: authorizations/models.py:247
msgid "Code de vérification"
msgstr "Code de vérification"
#: loko/authorizations/models.py:248
#: authorizations/models.py:248
msgid "Codes de vérification"
msgstr "Codes de vérification"
#: loko/authorizations/templates/authorizations/authorization_detail.html:12
#: authorizations/templates/authorizations/authorization_detail.html:12
msgid "Retour à la liste"
msgstr "Retour à la liste"
#: loko/authorizations/templates/authorizations/authorization_detail.html:13
#: loko/authorizations/templates/authorizations/authorization_detail.html:27
#: authorizations/templates/authorizations/authorization_detail.html:13
#: authorizations/templates/authorizations/authorization_detail.html:27
msgid "Retour"
msgstr "Retour"
#: loko/authorizations/templates/authorizations/authorization_detail.html:23
#: authorizations/templates/authorizations/authorization_detail.html:23
msgid "Demande"
msgstr "Demande"
#: loko/authorizations/templates/authorizations/authorization_detail.html:52
#: authorizations/templates/authorizations/authorization_detail.html:52
msgid "Informations générales"
msgstr "Informations générales"
#: loko/authorizations/templates/authorizations/authorization_detail.html:55
#: loko/authorizations/templates/authorizations/authorization_list.html:138
#: authorizations/templates/authorizations/authorization_detail.html:55
#: authorizations/templates/authorizations/authorization_list.html:138
msgid "Code"
msgstr "Code"
#: loko/authorizations/templates/authorizations/authorization_detail.html:58
#: loko/authorizations/templates/authorizations/authorization_list.html:140
#: authorizations/templates/authorizations/authorization_detail.html:58
#: authorizations/templates/authorizations/authorization_list.html:140
msgid "Statut"
msgstr "Statut"
#: loko/authorizations/templates/authorizations/authorization_detail.html:76
#: authorizations/templates/authorizations/authorization_detail.html:76
msgid "Créé le"
msgstr "Créé le"
#: loko/authorizations/templates/authorizations/authorization_detail.html:79
#: authorizations/templates/authorizations/authorization_detail.html:79
msgid "Mis à jour"
msgstr "Mis à jour"
#: loko/authorizations/templates/authorizations/authorization_detail.html:83
#: authorizations/templates/authorizations/authorization_detail.html:83
msgid "Agent"
msgstr "Agent"
#: loko/authorizations/templates/authorizations/authorization_detail.html:102
#: loko/authorizations/templates/authorizations/authorization_list.html:141
#: authorizations/templates/authorizations/authorization_detail.html:102
#: authorizations/templates/authorizations/authorization_list.html:141
msgid "Demandeur"
msgstr "Demandeur"
#: loko/authorizations/templates/authorizations/authorization_detail.html:132
#: authorizations/templates/authorizations/authorization_detail.html:132
msgid "Début"
msgstr "Début"
#: loko/authorizations/templates/authorizations/authorization_detail.html:133
#: authorizations/templates/authorizations/authorization_detail.html:133
msgid "Fin"
msgstr "Fin"
#: loko/authorizations/templates/authorizations/authorization_detail.html:151
#: authorizations/templates/authorizations/authorization_detail.html:151
msgid "Documents joints"
msgstr "Documents joints"
#: loko/authorizations/templates/authorizations/authorization_detail.html:167
#: authorizations/templates/authorizations/authorization_detail.html:167
msgid "Aucun document joint."
msgstr "Aucun document joint."
#: loko/authorizations/templates/authorizations/authorization_detail.html:176
#: authorizations/templates/authorizations/authorization_detail.html:176
msgid "Ex: Arrêté de police"
msgstr "Ex: Arrêté de police"
#: loko/authorizations/templates/authorizations/authorization_detail.html:183
#: authorizations/templates/authorizations/authorization_detail.html:183
msgid "Ajouter"
msgstr "Ajouter"
#: loko/authorizations/templates/authorizations/authorization_detail.html:194
#: authorizations/templates/authorizations/authorization_detail.html:194
msgid "Traitement de la demande"
msgstr "Traitement de la demande"
#: loko/authorizations/templates/authorizations/authorization_detail.html:201
#: authorizations/templates/authorizations/authorization_detail.html:201
msgid "Modifier le statut"
msgstr "Modifier le statut"
#: loko/authorizations/templates/authorizations/authorization_detail.html:211
#: authorizations/templates/authorizations/authorization_detail.html:211
msgid "Commentaire agent"
msgstr "Commentaire agent"
#: loko/authorizations/templates/authorizations/authorization_detail.html:212
#: authorizations/templates/authorizations/authorization_detail.html:212
msgid "Saisir un commentaire ou des notes..."
msgstr "Saisir un commentaire ou des notes..."
#: loko/authorizations/templates/authorizations/authorization_detail.html:216
#: authorizations/templates/authorizations/authorization_detail.html:216
msgid "Enregistrer le traitement"
msgstr "Enregistrer le traitement"
#: loko/authorizations/templates/authorizations/authorization_list.html:41
#: loko/authorizations/templates/authorizations/authorization_list.html:42
#: loko/authorizations/templates/authorizations/authorization_list.html:58
#: authorizations/templates/authorizations/authorization_list.html:41
#: authorizations/templates/authorizations/authorization_list.html:42
#: authorizations/templates/authorizations/authorization_list.html:58
msgid "Formulaire public"
msgstr "Formulaire public"
#: loko/authorizations/templates/authorizations/authorization_list.html:45
#: authorizations/templates/authorizations/authorization_list.html:45
msgid "Liste"
msgstr "Liste"
#: loko/authorizations/templates/authorizations/authorization_list.html:46
#: authorizations/templates/authorizations/authorization_list.html:46
msgid "Liste des demandes"
msgstr "Liste des demandes"
#: loko/authorizations/templates/authorizations/authorization_list.html:55
#: authorizations/templates/authorizations/authorization_list.html:55
msgid "Demandes d'autorisation d'occupation de l'espace public"
msgstr "Demandes d'autorisation d'occupation de l'espace public"
#: loko/authorizations/templates/authorizations/authorization_list.html:68
#: authorizations/templates/authorizations/authorization_list.html:68
msgid "Recherche"
msgstr "Recherche"
#: loko/authorizations/templates/authorizations/authorization_list.html:82
#: loko/authorizations/templates/authorizations/authorization_list.html:207
#: authorizations/templates/authorizations/authorization_list.html:82
#: authorizations/templates/authorizations/authorization_list.html:207
msgid "Tous les types"
msgstr "Tous les types"
#: loko/authorizations/templates/authorizations/authorization_list.html:89
#: authorizations/templates/authorizations/authorization_list.html:89
msgid "Rechercher un type..."
msgstr "Rechercher un type..."
#: loko/authorizations/templates/authorizations/authorization_list.html:92
#: loko/authorizations/templates/authorizations/new_authorization_default.html:226
#: authorizations/templates/authorizations/authorization_list.html:92
#: authorizations/templates/authorizations/new_authorization_default.html:226
msgid "Effacer"
msgstr "Effacer"
#: loko/authorizations/templates/authorizations/authorization_list.html:106
#: authorizations/templates/authorizations/authorization_list.html:106
msgid "Aucun type correspondant"
msgstr "Aucun type correspondant"
#: loko/authorizations/templates/authorizations/authorization_list.html:121
#: authorizations/templates/authorizations/authorization_list.html:121
msgid "Filtrer"
msgstr "Filtrer"
#: loko/authorizations/templates/authorizations/authorization_list.html:143
#: authorizations/templates/authorizations/authorization_list.html:143
msgid "Date de création"
msgstr "Date de création"
#: loko/authorizations/templates/authorizations/authorization_list.html:177
#: authorizations/templates/authorizations/authorization_list.html:177
msgid "Aucune demande trouvée."
msgstr "Aucune demande trouvée."
#: loko/authorizations/templates/authorizations/authorization_list.html:215
#: authorizations/templates/authorizations/authorization_list.html:215
msgid "types sélectionnés"
msgstr "types sélectionnés"
#: loko/authorizations/templates/authorizations/authorization_success.html:9
#: loko/authorizations/templates/authorizations/authorization_success.html:37
#: authorizations/templates/authorizations/authorization_success.html:9
#: authorizations/templates/authorizations/authorization_success.html:37
msgid "Demande enregistrée"
msgstr "Demande enregistrée"
#: loko/authorizations/templates/authorizations/authorization_success.html:28
#: loko/authorizations/templates/authorizations/email_verification_failed.html:28
#: loko/authorizations/templates/authorizations/email_verification_pending.html:28
#: loko/authorizations/templates/authorizations/email_verify_code.html:35
#: loko/authorizations/templates/authorizations/new_authorization_default.html:9
#: loko/authorizations/templates/authorizations/new_authorization_default.html:99
#: loko/authorizations/templates/authorizations/new_authorization_default.html:376
#: authorizations/templates/authorizations/authorization_success.html:28
#: authorizations/templates/authorizations/email_verification_failed.html:28
#: authorizations/templates/authorizations/email_verification_pending.html:28
#: authorizations/templates/authorizations/email_verify_code.html:35
#: authorizations/templates/authorizations/new_authorization_default.html:9
#: authorizations/templates/authorizations/new_authorization_default.html:99
#: authorizations/templates/authorizations/new_authorization_default.html:376
msgid "Demande d'occupation de l'espace public"
msgstr "Demande d'occupation de l'espace public"
#: loko/authorizations/templates/authorizations/authorization_success.html:41
#: authorizations/templates/authorizations/authorization_success.html:41
msgid "Numéro de référence"
msgstr "Numéro de référence"
#: loko/authorizations/templates/authorizations/authorization_success.html:43
#: authorizations/templates/authorizations/authorization_success.html:43
msgid "Conservez ce numéro pour le suivi de votre dossier."
msgstr "Conservez ce numéro pour le suivi de votre dossier."
#: loko/authorizations/templates/authorizations/authorization_success.html:49
#: authorizations/templates/authorizations/authorization_success.html:49
msgid ""
"Votre adresse email a été confirmée et votre demande d'autorisation "
"d'occupation de l'espace public a bien été enregistrée. Un accusé de "
@ -415,7 +415,7 @@ msgstr ""
"réception vous a été envoyé par email. Nos services prendront contact avec "
"vous dans les meilleurs délais."
#: loko/authorizations/templates/authorizations/authorization_success.html:55
#: authorizations/templates/authorizations/authorization_success.html:55
msgid ""
"Votre demande d'autorisation d'occupation de l'espace public a bien été "
"enregistrée. Un accusé de réception vous a été envoyé par email. Nos "
@ -425,20 +425,20 @@ msgstr ""
"enregistrée. Un accusé de réception vous a été envoyé par email. Nos "
"services prendront contact avec vous dans les meilleurs délais."
#: loko/authorizations/templates/authorizations/authorization_success.html:64
#: authorizations/templates/authorizations/authorization_success.html:64
msgid "Faire une nouvelle demande"
msgstr "Faire une nouvelle demande"
#: loko/authorizations/templates/authorizations/email_verification_failed.html:9
#: loko/authorizations/templates/authorizations/email_verification_failed.html:47
#: authorizations/templates/authorizations/email_verification_failed.html:9
#: authorizations/templates/authorizations/email_verification_failed.html:47
msgid "Lien invalide"
msgstr "Lien invalide"
#: loko/authorizations/templates/authorizations/email_verification_failed.html:39
#: authorizations/templates/authorizations/email_verification_failed.html:39
msgid "Lien expiré"
msgstr "Lien expiré"
#: loko/authorizations/templates/authorizations/email_verification_failed.html:41
#: authorizations/templates/authorizations/email_verification_failed.html:41
msgid ""
"Le lien de confirmation que vous avez utilisé n'est plus valide (délai de 48 "
"heures dépassé). Veuillez soumettre une nouvelle demande."
@ -446,7 +446,7 @@ msgstr ""
"Le lien de confirmation que vous avez utilisé n'est plus valide (délai de 48 "
"heures dépassé). Veuillez soumettre une nouvelle demande."
#: loko/authorizations/templates/authorizations/email_verification_failed.html:49
#: authorizations/templates/authorizations/email_verification_failed.html:49
msgid ""
"Le lien de confirmation que vous avez utilisé est invalide ou a déjà été "
"utilisé. Si votre demande a déjà été validée, vous pouvez en soumettre une "
@ -456,21 +456,21 @@ msgstr ""
"utilisé. Si votre demande a déjà été validée, vous pouvez en soumettre une "
"nouvelle."
#: loko/authorizations/templates/authorizations/email_verification_failed.html:58
#: loko/authorizations/templates/authorizations/email_verify_code.html:55
#: loko/authorizations/templates/authorizations/email_verify_code.html:72
#: authorizations/templates/authorizations/email_verification_failed.html:58
#: authorizations/templates/authorizations/email_verify_code.html:55
#: authorizations/templates/authorizations/email_verify_code.html:72
msgid "Nouvelle demande"
msgstr "Nouvelle demande"
#: loko/authorizations/templates/authorizations/email_verification_pending.html:9
#: authorizations/templates/authorizations/email_verification_pending.html:9
msgid "Confirmation de votre email"
msgstr "Confirmation de votre email"
#: loko/authorizations/templates/authorizations/email_verification_pending.html:37
#: authorizations/templates/authorizations/email_verification_pending.html:37
msgid "Vérifiez votre boîte email"
msgstr "Vérifiez votre boîte email"
#: loko/authorizations/templates/authorizations/email_verification_pending.html:39
#: authorizations/templates/authorizations/email_verification_pending.html:39
msgid ""
"Votre demande a bien été reçue. Pour la finaliser, veuillez confirmer votre "
"adresse email en cliquant sur le lien que nous venons de vous envoyer."
@ -478,7 +478,7 @@ msgstr ""
"Votre demande a bien été reçue. Pour la finaliser, veuillez confirmer votre "
"adresse email en cliquant sur le lien que nous venons de vous envoyer."
#: loko/authorizations/templates/authorizations/email_verification_pending.html:47
#: authorizations/templates/authorizations/email_verification_pending.html:47
msgid ""
"Le lien de confirmation est valable 48 heures. Si vous ne trouvez pas "
"l'email, vérifiez votre dossier de courrier indésirable (spam)."
@ -486,19 +486,19 @@ msgstr ""
"Le lien de confirmation est valable 48 heures. Si vous ne trouvez pas "
"l'email, vérifiez votre dossier de courrier indésirable (spam)."
#: loko/authorizations/templates/authorizations/email_verification_pending.html:55
#: authorizations/templates/authorizations/email_verification_pending.html:55
msgid "Retour au formulaire"
msgstr "Retour au formulaire"
#: loko/authorizations/templates/authorizations/email_verify_code.html:9
#: authorizations/templates/authorizations/email_verify_code.html:9
msgid "Vérification de votre email"
msgstr "Vérification de votre email"
#: loko/authorizations/templates/authorizations/email_verify_code.html:46
#: authorizations/templates/authorizations/email_verify_code.html:46
msgid "Code expiré"
msgstr "Code expiré"
#: loko/authorizations/templates/authorizations/email_verify_code.html:48
#: authorizations/templates/authorizations/email_verify_code.html:48
msgid ""
"Le code de vérification est arrivé à expiration (validité&nbsp;: "
"10&nbsp;minutes). Veuillez soumettre une nouvelle demande pour recevoir un "
@ -508,11 +508,11 @@ msgstr ""
"10&nbsp;minutes). Veuillez soumettre une nouvelle demande pour recevoir un "
"nouveau code."
#: loko/authorizations/templates/authorizations/email_verify_code.html:63
#: authorizations/templates/authorizations/email_verify_code.html:63
msgid "Trop de tentatives"
msgstr "Trop de tentatives"
#: loko/authorizations/templates/authorizations/email_verify_code.html:65
#: authorizations/templates/authorizations/email_verify_code.html:65
msgid ""
"Le nombre maximum de tentatives a été atteint. Votre code est bloqué. "
"Veuillez soumettre une nouvelle demande."
@ -520,11 +520,11 @@ msgstr ""
"Le nombre maximum de tentatives a été atteint. Votre code est bloqué. "
"Veuillez soumettre une nouvelle demande."
#: loko/authorizations/templates/authorizations/email_verify_code.html:80
#: authorizations/templates/authorizations/email_verify_code.html:80
msgid "Entrez votre code de vérification"
msgstr "Entrez votre code de vérification"
#: loko/authorizations/templates/authorizations/email_verify_code.html:82
#: authorizations/templates/authorizations/email_verify_code.html:82
#, python-format
msgid ""
"Un code à 6 chiffres a été envoyé à <strong>%(email)s</strong>. Saisissez-le "
@ -533,19 +533,19 @@ msgstr ""
"Un code à 6 chiffres a été envoyé à <strong>%(email)s</strong>. Saisissez-le "
"ci-dessous. Il est valable 10&nbsp;minutes."
#: loko/authorizations/templates/authorizations/email_verify_code.html:92
#: authorizations/templates/authorizations/email_verify_code.html:92
msgid "Code incorrect. Vérifiez l'email reçu et réessayez."
msgstr "Code incorrect. Vérifiez l'email reçu et réessayez."
#: loko/authorizations/templates/authorizations/email_verify_code.html:115
#: authorizations/templates/authorizations/email_verify_code.html:115
msgid "Code de vérification à 6 chiffres"
msgstr "Code de vérification à 6 chiffres"
#: loko/authorizations/templates/authorizations/email_verify_code.html:118
#: authorizations/templates/authorizations/email_verify_code.html:118
msgid "Vérifier"
msgstr "Vérifier"
#: loko/authorizations/templates/authorizations/email_verify_code.html:124
#: authorizations/templates/authorizations/email_verify_code.html:124
msgid ""
"Vous n'avez pas reçu l'email ? Vérifiez votre dossier de courrier "
"indésirable (spam)."
@ -553,7 +553,7 @@ msgstr ""
"Vous n'avez pas reçu l'email ? Vérifiez votre dossier de courrier "
"indésirable (spam)."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:116
#: authorizations/templates/authorizations/new_authorization_default.html:116
msgid ""
"Toute occupation de l'espace public (terrasse, affichage, événement, "
"mobilier, etc.) doit faire l'objet d'une autorisation préalable de la part "
@ -563,7 +563,7 @@ msgstr ""
"mobilier, etc.) doit faire l'objet d'une autorisation préalable de la part "
"de l'administration."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:121
#: authorizations/templates/authorizations/new_authorization_default.html:121
msgid ""
"Veuillez compléter ce formulaire et délimiter la zone concernée sur la carte "
"ci-dessous ainsi que la période souhaitée."
@ -571,7 +571,7 @@ msgstr ""
"Veuillez compléter ce formulaire et délimiter la zone concernée sur la carte "
"ci-dessous ainsi que la période souhaitée."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:126
#: authorizations/templates/authorizations/new_authorization_default.html:126
msgid ""
"Si vous éprouvez des difficultés ou avez des questions, vous pouvez "
"contacter nos services."
@ -579,23 +579,23 @@ msgstr ""
"Si vous éprouvez des difficultés ou avez des questions, vous pouvez "
"contacter nos services."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:144
#: authorizations/templates/authorizations/new_authorization_default.html:144
msgid "Votre demande"
msgstr "Votre demande"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:216
#: authorizations/templates/authorizations/new_authorization_default.html:216
msgid "Localisation (dessiner un polygone pour indiquer la zone concernée)"
msgstr "Localisation (dessiner un polygone pour indiquer la zone concernée)"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:220
#: authorizations/templates/authorizations/new_authorization_default.html:220
msgid "Dessiner un polygone"
msgstr "Dessiner un polygone"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:223
#: authorizations/templates/authorizations/new_authorization_default.html:223
msgid "Terminer"
msgstr "Terminer"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:231
#: authorizations/templates/authorizations/new_authorization_default.html:231
msgid ""
"Cliquez sur « Dessiner un polygone » puis cliquez sur la carte pour ajouter "
"des sommets. Cliquez sur le premier sommet pour fermer le polygone."
@ -603,41 +603,41 @@ msgstr ""
"Cliquez sur « Dessiner un polygone » puis cliquez sur la carte pour ajouter "
"des sommets. Cliquez sur le premier sommet pour fermer le polygone."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:245
#: authorizations/templates/authorizations/new_authorization_default.html:245
msgid "Vos coordonnées"
msgstr "Vos coordonnées"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:278
#: loko/authorizations/templates/authorizations/new_authorization_default.html:317
#: loko/authorizations/templates/authorizations/new_authorization_default.html:337
#: authorizations/templates/authorizations/new_authorization_default.html:278
#: authorizations/templates/authorizations/new_authorization_default.html:317
#: authorizations/templates/authorizations/new_authorization_default.html:337
msgid "optionnel"
msgstr "optionnel"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:292
#: authorizations/templates/authorizations/new_authorization_default.html:292
msgid "Date(s) d'occupation"
msgstr "Date(s) d'occupation"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:298
#: authorizations/templates/authorizations/new_authorization_default.html:298
msgid "Veuillez indiquer au moins une date de début d'occupation."
msgstr "Veuillez indiquer au moins une date de début d'occupation."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:328
#: authorizations/templates/authorizations/new_authorization_default.html:328
msgid "Ajouter une date"
msgstr "Ajouter une date"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:336
#: authorizations/templates/authorizations/new_authorization_default.html:336
msgid "Document(s) à joindre"
msgstr "Document(s) à joindre"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:360
#: authorizations/templates/authorizations/new_authorization_default.html:360
msgid "Ajouter un document"
msgstr "Ajouter un document"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:367
#: authorizations/templates/authorizations/new_authorization_default.html:367
msgid "Envoyer la demande"
msgstr "Envoyer la demande"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:385
#: authorizations/templates/authorizations/new_authorization_default.html:385
msgid ""
"Veillez à joindre en annexe l'attestation d'assurance couvrant tous les "
"risques."
@ -645,20 +645,20 @@ msgstr ""
"Veillez à joindre en annexe l'attestation d'assurance couvrant tous les "
"risques."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:386
#: authorizations/templates/authorizations/new_authorization_default.html:386
msgid "Veillez à joindre en annexe l'autorisation de la commune."
msgstr "Veillez à joindre en annexe l'autorisation de la commune."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:472
#: loko/authorizations/templates/authorizations/new_authorization_default.html:521
#: authorizations/templates/authorizations/new_authorization_default.html:472
#: authorizations/templates/authorizations/new_authorization_default.html:521
msgid "Polygone enregistré. Cliquez sur « Dessiner » pour le redessiner."
msgstr "Polygone enregistré. Cliquez sur « Dessiner » pour le redessiner."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:492
#: authorizations/templates/authorizations/new_authorization_default.html:492
msgid "Cliquer pour fermer le polygone"
msgstr "Cliquer pour fermer le polygone"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:536
#: authorizations/templates/authorizations/new_authorization_default.html:536
msgid ""
"Cliquez sur « Dessiner un polygone » puis cliquez sur la carte pour ajouter "
"des sommets."
@ -666,7 +666,7 @@ msgstr ""
"Cliquez sur « Dessiner un polygone » puis cliquez sur la carte pour ajouter "
"des sommets."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:559
#: authorizations/templates/authorizations/new_authorization_default.html:559
msgid ""
"Cliquez sur la carte pour ajouter des sommets. Cliquez sur le premier sommet "
"pour fermer le polygone."
@ -674,19 +674,19 @@ msgstr ""
"Cliquez sur la carte pour ajouter des sommets. Cliquez sur le premier sommet "
"pour fermer le polygone."
#: loko/authorizations/views.py:326 loko/authorizations/views.py:375
#: authorizations/views.py:326 authorizations/views.py:375
msgid "Vous n'avez pas accès à cette vue."
msgstr "Vous n'avez pas accès à cette vue."
#: loko/authorizations/views.py:392
#: authorizations/views.py:392
msgid "La demande a été mise à jour avec succès."
msgstr "La demande a été mise à jour avec succès."
#: loko/authorizations/views.py:409
#: authorizations/views.py:409
msgid "Le document a été ajouté avec succès."
msgstr "Le document a été ajouté avec succès."
#: loko/authorizations/views.py:413
#: authorizations/views.py:413
msgid "Veuillez fournir une description et un fichier."
msgstr "Veuillez fournir une description et un fichier."

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,394 +17,394 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: loko/authorizations/admin.py:28
#: loko/authorizations/templates/authorizations/authorization_detail.html:73
#: loko/authorizations/templates/authorizations/authorization_list.html:73
#: loko/authorizations/templates/authorizations/authorization_list.html:139
#: authorizations/admin.py:28
#: authorizations/templates/authorizations/authorization_detail.html:73
#: authorizations/templates/authorizations/authorization_list.html:73
#: authorizations/templates/authorizations/authorization_list.html:139
msgid "Type"
msgstr "Type"
#: loko/authorizations/admin.py:46
#: authorizations/admin.py:46
msgid "Expiré"
msgstr "Verlopen"
#: loko/authorizations/forms.py:62
#: authorizations/forms.py:62
msgid "Veuillez dessiner la zone concernée sur la carte."
msgstr "Teken de betrokken zone op de kaart."
#: loko/authorizations/forms.py:66
#: authorizations/forms.py:66
msgid "Géométrie invalide."
msgstr "Ongeldige geometrie."
#: loko/authorizations/forms.py:68
#: authorizations/forms.py:68
msgid "Veuillez dessiner un polygone."
msgstr "Teken een veelhoek."
#: loko/authorizations/forms.py:77
#: loko/authorizations/templates/authorizations/authorization_detail.html:175
#: authorizations/forms.py:77
#: authorizations/templates/authorizations/authorization_detail.html:175
msgid "Description du document"
msgstr "Documentomschrijving"
#: loko/authorizations/forms.py:127
#: authorizations/forms.py:127
msgid "Inclure les archives (> 2 ans)"
msgstr "Archieven weergeven (> 2 jaar)"
#: loko/authorizations/forms.py:132
#: authorizations/forms.py:132
msgid "Type d'autorisation"
msgstr "Type vergunning"
#: loko/authorizations/forms.py:140
#: authorizations/forms.py:140
msgid "Recherche…"
msgstr "Zoeken…"
#: loko/authorizations/models.py:17
#: authorizations/models.py:17
msgid "Affichage (panneau, ...)"
msgstr "Affichage (bord…)"
#: loko/authorizations/models.py:18
#: authorizations/models.py:18
msgid "Terrasse"
msgstr "Terras"
#: loko/authorizations/models.py:19
#: authorizations/models.py:19
msgid "Mobilier urbain"
msgstr "Straatmeubilair"
#: loko/authorizations/models.py:20
#: authorizations/models.py:20
msgid "Œuvre d'art"
msgstr "Kunstwerk"
#: loko/authorizations/models.py:21
#: authorizations/models.py:21
msgid "Nouvel Emplacement PMR"
msgstr "Nieuwe gehandicaptenparkeerplaats"
#: loko/authorizations/models.py:22
#: authorizations/models.py:22
msgid "Nouvelle Zone de livraison"
msgstr "Nieuwe laad- en loszone"
#: loko/authorizations/models.py:23
#: authorizations/models.py:23
msgid "Tournage audiovisuel"
msgstr "Filmopname"
#: loko/authorizations/models.py:24
#: authorizations/models.py:24
msgid "Evénement"
msgstr "Evenement"
#: loko/authorizations/models.py:25
#: authorizations/models.py:25
msgid "Plante grimpante"
msgstr "Klimplant"
#: loko/authorizations/models.py:26
#: authorizations/models.py:26
msgid "Pied d'arbre"
msgstr "Boomspiegel"
#: loko/authorizations/models.py:30
#: authorizations/models.py:30
msgid "À traiter"
msgstr "Te behandelen"
#: loko/authorizations/models.py:31
#: authorizations/models.py:31
msgid "En cours"
msgstr "In behandeling"
#: loko/authorizations/models.py:32
#: authorizations/models.py:32
msgid "Autorisé"
msgstr "Vergund"
#: loko/authorizations/models.py:33
#: authorizations/models.py:33
msgid "Refusé"
msgstr "Geweigerd"
#: loko/authorizations/models.py:34
#: authorizations/models.py:34
msgid "Clôturé"
msgstr "Afgesloten"
#: loko/authorizations/models.py:45
#: authorizations/models.py:45
msgid "Langue"
msgstr "Taal"
#: loko/authorizations/models.py:49 loko/authorizations/models.py:201
#: authorizations/models.py:49 authorizations/models.py:201
msgid "Email vérifié"
msgstr "E-mail geverifieerd"
#: loko/authorizations/models.py:50
#: authorizations/models.py:50
msgid "Indique si l'adresse email du demandeur a été vérifiée."
msgstr "Geeft aan of het e-mailadres van de aanvrager is geverifieerd."
#: loko/authorizations/models.py:52
#: authorizations/models.py:52
msgid "Type d'occupation"
msgstr "Type bezetting"
#: loko/authorizations/models.py:53
#: loko/authorizations/templates/authorizations/authorization_detail.html:92
#: authorizations/models.py:53
#: authorizations/templates/authorizations/authorization_detail.html:92
msgid "Description de la demande"
msgstr "Beschrijving van de aanvraag"
#: loko/authorizations/models.py:54
#: loko/authorizations/templates/authorizations/authorization_detail.html:105
#: authorizations/models.py:54
#: authorizations/templates/authorizations/authorization_detail.html:105
msgid "Nom"
msgstr "Naam"
#: loko/authorizations/models.py:55 loko/authorizations/models.py:197
#: loko/authorizations/templates/authorizations/authorization_detail.html:108
#: authorizations/models.py:55 authorizations/models.py:197
#: authorizations/templates/authorizations/authorization_detail.html:108
msgid "Email"
msgstr "E-mail"
#: loko/authorizations/models.py:56
#: loko/authorizations/templates/authorizations/authorization_detail.html:113
#: authorizations/models.py:56
#: authorizations/templates/authorizations/authorization_detail.html:113
msgid "Adresse"
msgstr "Adres"
#: loko/authorizations/models.py:57
#: loko/authorizations/templates/authorizations/authorization_detail.html:117
#: authorizations/models.py:57
#: authorizations/templates/authorizations/authorization_detail.html:117
msgid "Entreprise"
msgstr "Onderneming"
#: loko/authorizations/models.py:64
#: authorizations/models.py:64
msgid "Agent traitant"
msgstr "Behandelende ambtenaar"
#: loko/authorizations/models.py:66
#: authorizations/models.py:66
msgid "Commentaire"
msgstr "Opmerking"
#: loko/authorizations/models.py:67
#: authorizations/models.py:67
msgid "Localisation – Adresse"
msgstr "Locatie – Adres"
#: loko/authorizations/models.py:68
#: loko/authorizations/templates/authorizations/authorization_detail.html:95
#: loko/authorizations/templates/authorizations/authorization_detail.html:228
#: loko/authorizations/templates/authorizations/authorization_list.html:142
#: authorizations/models.py:68
#: authorizations/templates/authorizations/authorization_detail.html:95
#: authorizations/templates/authorizations/authorization_detail.html:228
#: authorizations/templates/authorizations/authorization_list.html:142
msgid "Localisation"
msgstr "Locatie"
#: loko/authorizations/models.py:107
#: authorizations/models.py:107
msgid "Autorisation d'occupation de l'espace public"
msgstr ""
#: loko/authorizations/models.py:108
#: authorizations/models.py:108
msgid "Autorisations d'occupation de l'espace public"
msgstr ""
#: loko/authorizations/models.py:146
#: authorizations/models.py:146
#, python-format
msgid "La taille maximale du fichier est de %(limit)s Mo."
msgstr "De maximale bestandsgrootte is %(limit)s MB."
#: loko/authorizations/models.py:151
#: loko/authorizations/templates/authorizations/authorization_detail.html:179
#: authorizations/models.py:151
#: authorizations/templates/authorizations/authorization_detail.html:179
msgid "Fichier"
msgstr "Bestand"
#: loko/authorizations/models.py:155
#: authorizations/models.py:155
msgid "Description"
msgstr "Beschrijving"
#: loko/authorizations/models.py:163
#: authorizations/models.py:163
msgid "Document"
msgstr "Document"
#: loko/authorizations/models.py:164
#: authorizations/models.py:164
msgid "Documents"
msgstr "Documenten"
#: loko/authorizations/models.py:176
#: authorizations/models.py:176
msgid "Début de l'occupation"
msgstr "Begin van de bezetting"
#: loko/authorizations/models.py:177
#: authorizations/models.py:177
msgid "Fin de l'occupation"
msgstr "Einde van de bezetting"
#: loko/authorizations/models.py:180
#: authorizations/models.py:180
msgid "Date d'occupation"
msgstr "Bezettingsdatum"
#: loko/authorizations/models.py:181
#: loko/authorizations/templates/authorizations/authorization_detail.html:127
#: authorizations/models.py:181
#: authorizations/templates/authorizations/authorization_detail.html:127
msgid "Dates d'occupation"
msgstr "Bezettingsdata"
#: loko/authorizations/models.py:202
#: authorizations/models.py:202
msgid "Emails vérifiés"
msgstr "Geverifieerde e-mails"
#: loko/authorizations/models.py:247
#: authorizations/models.py:247
msgid "Code de vérification"
msgstr "Verificatiecode"
#: loko/authorizations/models.py:248
#: authorizations/models.py:248
msgid "Codes de vérification"
msgstr "Verificatiecodes"
#: loko/authorizations/templates/authorizations/authorization_detail.html:12
#: authorizations/templates/authorizations/authorization_detail.html:12
msgid "Retour à la liste"
msgstr "Terug naar de lijst"
#: loko/authorizations/templates/authorizations/authorization_detail.html:13
#: loko/authorizations/templates/authorizations/authorization_detail.html:27
#: authorizations/templates/authorizations/authorization_detail.html:13
#: authorizations/templates/authorizations/authorization_detail.html:27
msgid "Retour"
msgstr "Terug"
#: loko/authorizations/templates/authorizations/authorization_detail.html:23
#: authorizations/templates/authorizations/authorization_detail.html:23
msgid "Demande"
msgstr "Aanvraag"
#: loko/authorizations/templates/authorizations/authorization_detail.html:52
#: authorizations/templates/authorizations/authorization_detail.html:52
msgid "Informations générales"
msgstr "Algemene informatie"
#: loko/authorizations/templates/authorizations/authorization_detail.html:55
#: loko/authorizations/templates/authorizations/authorization_list.html:138
#: authorizations/templates/authorizations/authorization_detail.html:55
#: authorizations/templates/authorizations/authorization_list.html:138
msgid "Code"
msgstr "Code"
#: loko/authorizations/templates/authorizations/authorization_detail.html:58
#: loko/authorizations/templates/authorizations/authorization_list.html:140
#: authorizations/templates/authorizations/authorization_detail.html:58
#: authorizations/templates/authorizations/authorization_list.html:140
msgid "Statut"
msgstr "Status"
#: loko/authorizations/templates/authorizations/authorization_detail.html:76
#: authorizations/templates/authorizations/authorization_detail.html:76
msgid "Créé le"
msgstr "Aangemaakt op"
#: loko/authorizations/templates/authorizations/authorization_detail.html:79
#: authorizations/templates/authorizations/authorization_detail.html:79
msgid "Mis à jour"
msgstr "Bijgewerkt"
#: loko/authorizations/templates/authorizations/authorization_detail.html:83
#: authorizations/templates/authorizations/authorization_detail.html:83
msgid "Agent"
msgstr "Ambtenaar"
#: loko/authorizations/templates/authorizations/authorization_detail.html:102
#: loko/authorizations/templates/authorizations/authorization_list.html:141
#: authorizations/templates/authorizations/authorization_detail.html:102
#: authorizations/templates/authorizations/authorization_list.html:141
msgid "Demandeur"
msgstr "Aanvrager"
#: loko/authorizations/templates/authorizations/authorization_detail.html:132
#: authorizations/templates/authorizations/authorization_detail.html:132
msgid "Début"
msgstr "Begin"
#: loko/authorizations/templates/authorizations/authorization_detail.html:133
#: authorizations/templates/authorizations/authorization_detail.html:133
msgid "Fin"
msgstr "Einde"
#: loko/authorizations/templates/authorizations/authorization_detail.html:151
#: authorizations/templates/authorizations/authorization_detail.html:151
msgid "Documents joints"
msgstr "Bijgevoegde documenten"
#: loko/authorizations/templates/authorizations/authorization_detail.html:167
#: authorizations/templates/authorizations/authorization_detail.html:167
msgid "Aucun document joint."
msgstr "Bijgevoegde documenten"
#: loko/authorizations/templates/authorizations/authorization_detail.html:176
#: authorizations/templates/authorizations/authorization_detail.html:176
msgid "Ex: Arrêté de police"
msgstr ""
#: loko/authorizations/templates/authorizations/authorization_detail.html:183
#: authorizations/templates/authorizations/authorization_detail.html:183
msgid "Ajouter"
msgstr "Een datum toevoegen"
#: loko/authorizations/templates/authorizations/authorization_detail.html:194
#: authorizations/templates/authorizations/authorization_detail.html:194
msgid "Traitement de la demande"
msgstr "Beschrijving van de aanvraag"
#: loko/authorizations/templates/authorizations/authorization_detail.html:201
#: authorizations/templates/authorizations/authorization_detail.html:201
msgid "Modifier le statut"
msgstr ""
#: loko/authorizations/templates/authorizations/authorization_detail.html:211
#: authorizations/templates/authorizations/authorization_detail.html:211
msgid "Commentaire agent"
msgstr "Opmerking ambtenaar"
#: loko/authorizations/templates/authorizations/authorization_detail.html:212
#: authorizations/templates/authorizations/authorization_detail.html:212
msgid "Saisir un commentaire ou des notes..."
msgstr ""
#: loko/authorizations/templates/authorizations/authorization_detail.html:216
#: authorizations/templates/authorizations/authorization_detail.html:216
msgid "Enregistrer le traitement"
msgstr ""
#: loko/authorizations/templates/authorizations/authorization_list.html:41
#: loko/authorizations/templates/authorizations/authorization_list.html:42
#: loko/authorizations/templates/authorizations/authorization_list.html:58
#: authorizations/templates/authorizations/authorization_list.html:41
#: authorizations/templates/authorizations/authorization_list.html:42
#: authorizations/templates/authorizations/authorization_list.html:58
msgid "Formulaire public"
msgstr "Openbaar formulier"
#: loko/authorizations/templates/authorizations/authorization_list.html:45
#: authorizations/templates/authorizations/authorization_list.html:45
msgid "Liste"
msgstr "Lijst"
#: loko/authorizations/templates/authorizations/authorization_list.html:46
#: authorizations/templates/authorizations/authorization_list.html:46
msgid "Liste des demandes"
msgstr "Lijst van aanvragen"
#: loko/authorizations/templates/authorizations/authorization_list.html:55
#: authorizations/templates/authorizations/authorization_list.html:55
msgid "Demandes d'autorisation d'occupation de l'espace public"
msgstr ""
"Aanvragen voor vergunning voor de ingebruikneming van de openbare ruimte"
#: loko/authorizations/templates/authorizations/authorization_list.html:68
#: authorizations/templates/authorizations/authorization_list.html:68
msgid "Recherche"
msgstr "Zoeken"
#: loko/authorizations/templates/authorizations/authorization_list.html:82
#: loko/authorizations/templates/authorizations/authorization_list.html:207
#: authorizations/templates/authorizations/authorization_list.html:82
#: authorizations/templates/authorizations/authorization_list.html:207
msgid "Tous les types"
msgstr "Alle types"
#: loko/authorizations/templates/authorizations/authorization_list.html:89
#: authorizations/templates/authorizations/authorization_list.html:89
msgid "Rechercher un type..."
msgstr "Zoeken"
#: loko/authorizations/templates/authorizations/authorization_list.html:92
#: loko/authorizations/templates/authorizations/new_authorization_default.html:226
#: authorizations/templates/authorizations/authorization_list.html:92
#: authorizations/templates/authorizations/new_authorization_default.html:226
msgid "Effacer"
msgstr "Wissen"
#: loko/authorizations/templates/authorizations/authorization_list.html:106
#: authorizations/templates/authorizations/authorization_list.html:106
msgid "Aucun type correspondant"
msgstr ""
#: loko/authorizations/templates/authorizations/authorization_list.html:121
#: authorizations/templates/authorizations/authorization_list.html:121
msgid "Filtrer"
msgstr "Filteren"
#: loko/authorizations/templates/authorizations/authorization_list.html:143
#: authorizations/templates/authorizations/authorization_list.html:143
msgid "Date de création"
msgstr "Aanmaakdatum"
#: loko/authorizations/templates/authorizations/authorization_list.html:177
#: authorizations/templates/authorizations/authorization_list.html:177
msgid "Aucune demande trouvée."
msgstr "Geen aanvraag gevonden."
#: loko/authorizations/templates/authorizations/authorization_list.html:215
#: authorizations/templates/authorizations/authorization_list.html:215
msgid "types sélectionnés"
msgstr ""
#: loko/authorizations/templates/authorizations/authorization_success.html:9
#: loko/authorizations/templates/authorizations/authorization_success.html:37
#: authorizations/templates/authorizations/authorization_success.html:9
#: authorizations/templates/authorizations/authorization_success.html:37
msgid "Demande enregistrée"
msgstr "Aanvraag opgeslagen"
#: loko/authorizations/templates/authorizations/authorization_success.html:28
#: loko/authorizations/templates/authorizations/email_verification_failed.html:28
#: loko/authorizations/templates/authorizations/email_verification_pending.html:28
#: loko/authorizations/templates/authorizations/email_verify_code.html:35
#: loko/authorizations/templates/authorizations/new_authorization_default.html:9
#: loko/authorizations/templates/authorizations/new_authorization_default.html:99
#: loko/authorizations/templates/authorizations/new_authorization_default.html:376
#: authorizations/templates/authorizations/authorization_success.html:28
#: authorizations/templates/authorizations/email_verification_failed.html:28
#: authorizations/templates/authorizations/email_verification_pending.html:28
#: authorizations/templates/authorizations/email_verify_code.html:35
#: authorizations/templates/authorizations/new_authorization_default.html:9
#: authorizations/templates/authorizations/new_authorization_default.html:99
#: authorizations/templates/authorizations/new_authorization_default.html:376
msgid "Demande d'occupation de l'espace public"
msgstr "Aanvraag ingebruikneming openbare ruimte"
#: loko/authorizations/templates/authorizations/authorization_success.html:41
#: authorizations/templates/authorizations/authorization_success.html:41
msgid "Numéro de référence"
msgstr "Referentienummer"
#: loko/authorizations/templates/authorizations/authorization_success.html:43
#: authorizations/templates/authorizations/authorization_success.html:43
msgid "Conservez ce numéro pour le suivi de votre dossier."
msgstr "Bewaar dit nummer voor de opvolging van uw dossier."
#: loko/authorizations/templates/authorizations/authorization_success.html:49
#: authorizations/templates/authorizations/authorization_success.html:49
msgid ""
"Votre adresse email a été confirmée et votre demande d'autorisation "
"d'occupation de l'espace public a bien été enregistrée. Un accusé de "
@ -416,7 +416,7 @@ msgstr ""
"ontvangstbevestiging werd u per e-mail verzonden. Onze diensten nemen zo "
"spoedig mogelijk contact met u op."
#: loko/authorizations/templates/authorizations/authorization_success.html:55
#: authorizations/templates/authorizations/authorization_success.html:55
msgid ""
"Votre demande d'autorisation d'occupation de l'espace public a bien été "
"enregistrée. Un accusé de réception vous a été envoyé par email. Nos "
@ -426,20 +426,20 @@ msgstr ""
"is geregistreerd. Een ontvangstbevestiging werd u per e-mail verzonden. Onze "
"diensten nemen zo spoedig mogelijk contact met u op."
#: loko/authorizations/templates/authorizations/authorization_success.html:64
#: authorizations/templates/authorizations/authorization_success.html:64
msgid "Faire une nouvelle demande"
msgstr "Een nieuwe aanvraag indienen"
#: loko/authorizations/templates/authorizations/email_verification_failed.html:9
#: loko/authorizations/templates/authorizations/email_verification_failed.html:47
#: authorizations/templates/authorizations/email_verification_failed.html:9
#: authorizations/templates/authorizations/email_verification_failed.html:47
msgid "Lien invalide"
msgstr "Ongeldige link"
#: loko/authorizations/templates/authorizations/email_verification_failed.html:39
#: authorizations/templates/authorizations/email_verification_failed.html:39
msgid "Lien expiré"
msgstr "Link verlopen"
#: loko/authorizations/templates/authorizations/email_verification_failed.html:41
#: authorizations/templates/authorizations/email_verification_failed.html:41
msgid ""
"Le lien de confirmation que vous avez utilisé n'est plus valide (délai de 48 "
"heures dépassé). Veuillez soumettre une nouvelle demande."
@ -447,7 +447,7 @@ msgstr ""
"De bevestigingslink die u heeft gebruikt, is niet meer geldig (termijn van "
"48 uur overschreden). Dien een nieuwe aanvraag in."
#: loko/authorizations/templates/authorizations/email_verification_failed.html:49
#: authorizations/templates/authorizations/email_verification_failed.html:49
msgid ""
"Le lien de confirmation que vous avez utilisé est invalide ou a déjà été "
"utilisé. Si votre demande a déjà été validée, vous pouvez en soumettre une "
@ -456,21 +456,21 @@ msgstr ""
"De bevestigingslink die u heeft gebruikt, is ongeldig of reeds gebruikt. Als "
"uw aanvraag al is gevalideerd, kunt u een nieuwe indienen."
#: loko/authorizations/templates/authorizations/email_verification_failed.html:58
#: loko/authorizations/templates/authorizations/email_verify_code.html:55
#: loko/authorizations/templates/authorizations/email_verify_code.html:72
#: authorizations/templates/authorizations/email_verification_failed.html:58
#: authorizations/templates/authorizations/email_verify_code.html:55
#: authorizations/templates/authorizations/email_verify_code.html:72
msgid "Nouvelle demande"
msgstr "Nieuwe aanvraag"
#: loko/authorizations/templates/authorizations/email_verification_pending.html:9
#: authorizations/templates/authorizations/email_verification_pending.html:9
msgid "Confirmation de votre email"
msgstr "Bevestiging van uw e-mail"
#: loko/authorizations/templates/authorizations/email_verification_pending.html:37
#: authorizations/templates/authorizations/email_verification_pending.html:37
msgid "Vérifiez votre boîte email"
msgstr "Controleer uw e-mailbox"
#: loko/authorizations/templates/authorizations/email_verification_pending.html:39
#: authorizations/templates/authorizations/email_verification_pending.html:39
msgid ""
"Votre demande a bien été reçue. Pour la finaliser, veuillez confirmer votre "
"adresse email en cliquant sur le lien que nous venons de vous envoyer."
@ -478,7 +478,7 @@ msgstr ""
"Uw aanvraag is ontvangen. Om deze te voltooien, bevestigt u uw e-mailadres "
"door op de link te klikken die wij u zojuist hebben gestuurd."
#: loko/authorizations/templates/authorizations/email_verification_pending.html:47
#: authorizations/templates/authorizations/email_verification_pending.html:47
msgid ""
"Le lien de confirmation est valable 48 heures. Si vous ne trouvez pas "
"l'email, vérifiez votre dossier de courrier indésirable (spam)."
@ -486,19 +486,19 @@ msgstr ""
"De bevestigingslink is 48 uur geldig. Als u de e-mail niet vindt, controleer "
"dan uw map met ongewenste e-mail (spam)."
#: loko/authorizations/templates/authorizations/email_verification_pending.html:55
#: authorizations/templates/authorizations/email_verification_pending.html:55
msgid "Retour au formulaire"
msgstr "Terug naar het formulier"
#: loko/authorizations/templates/authorizations/email_verify_code.html:9
#: authorizations/templates/authorizations/email_verify_code.html:9
msgid "Vérification de votre email"
msgstr "Verificatie van uw e-mail"
#: loko/authorizations/templates/authorizations/email_verify_code.html:46
#: authorizations/templates/authorizations/email_verify_code.html:46
msgid "Code expiré"
msgstr "Code verlopen"
#: loko/authorizations/templates/authorizations/email_verify_code.html:48
#: authorizations/templates/authorizations/email_verify_code.html:48
msgid ""
"Le code de vérification est arrivé à expiration (validité&nbsp;: "
"10&nbsp;minutes). Veuillez soumettre une nouvelle demande pour recevoir un "
@ -507,11 +507,11 @@ msgstr ""
"De verificatiecode is verlopen (geldigheid:&nbsp;10&nbsp;minuten). Dien een "
"nieuwe aanvraag in om een nieuwe code te ontvangen."
#: loko/authorizations/templates/authorizations/email_verify_code.html:63
#: authorizations/templates/authorizations/email_verify_code.html:63
msgid "Trop de tentatives"
msgstr "Te veel pogingen"
#: loko/authorizations/templates/authorizations/email_verify_code.html:65
#: authorizations/templates/authorizations/email_verify_code.html:65
msgid ""
"Le nombre maximum de tentatives a été atteint. Votre code est bloqué. "
"Veuillez soumettre une nouvelle demande."
@ -519,11 +519,11 @@ msgstr ""
"Het maximale aantal pogingen is bereikt. Uw code is geblokkeerd. Dien een "
"nieuwe aanvraag in."
#: loko/authorizations/templates/authorizations/email_verify_code.html:80
#: authorizations/templates/authorizations/email_verify_code.html:80
msgid "Entrez votre code de vérification"
msgstr "Voer uw verificatiecode in"
#: loko/authorizations/templates/authorizations/email_verify_code.html:82
#: authorizations/templates/authorizations/email_verify_code.html:82
#, python-format
msgid ""
"Un code à 6 chiffres a été envoyé à <strong>%(email)s</strong>. Saisissez-le "
@ -532,19 +532,19 @@ msgstr ""
"Een 6-cijferige code werd verzonden naar <strong>%(email)s</strong>. Voer "
"hem hieronder in. Hij is 10&nbsp;minuten geldig."
#: loko/authorizations/templates/authorizations/email_verify_code.html:92
#: authorizations/templates/authorizations/email_verify_code.html:92
msgid "Code incorrect. Vérifiez l'email reçu et réessayez."
msgstr "Onjuiste code. Controleer de ontvangen e-mail en probeer opnieuw."
#: loko/authorizations/templates/authorizations/email_verify_code.html:115
#: authorizations/templates/authorizations/email_verify_code.html:115
msgid "Code de vérification à 6 chiffres"
msgstr "6-cijferige verificatiecode"
#: loko/authorizations/templates/authorizations/email_verify_code.html:118
#: authorizations/templates/authorizations/email_verify_code.html:118
msgid "Vérifier"
msgstr "Verifiëren"
#: loko/authorizations/templates/authorizations/email_verify_code.html:124
#: authorizations/templates/authorizations/email_verify_code.html:124
msgid ""
"Vous n'avez pas reçu l'email ? Vérifiez votre dossier de courrier "
"indésirable (spam)."
@ -552,42 +552,42 @@ msgstr ""
"Heeft u de e-mail niet ontvangen? Controleer uw map met ongewenste e-mail "
"(spam)."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:116
#: authorizations/templates/authorizations/new_authorization_default.html:116
msgid ""
"Toute occupation de l'espace public (terrasse, affichage, événement, "
"mobilier, etc.) doit faire l'objet d'une autorisation préalable de la part "
"de l'administration."
msgstr ""
#: loko/authorizations/templates/authorizations/new_authorization_default.html:121
#: authorizations/templates/authorizations/new_authorization_default.html:121
msgid ""
"Veuillez compléter ce formulaire et délimiter la zone concernée sur la carte "
"ci-dessous ainsi que la période souhaitée."
msgstr ""
#: loko/authorizations/templates/authorizations/new_authorization_default.html:126
#: authorizations/templates/authorizations/new_authorization_default.html:126
msgid ""
"Si vous éprouvez des difficultés ou avez des questions, vous pouvez "
"contacter nos services."
msgstr ""
#: loko/authorizations/templates/authorizations/new_authorization_default.html:144
#: authorizations/templates/authorizations/new_authorization_default.html:144
msgid "Votre demande"
msgstr "Uw aanvraag"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:216
#: authorizations/templates/authorizations/new_authorization_default.html:216
msgid "Localisation (dessiner un polygone pour indiquer la zone concernée)"
msgstr "Locatie (teken een veelhoek om de betrokken zone aan te geven)"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:220
#: authorizations/templates/authorizations/new_authorization_default.html:220
msgid "Dessiner un polygone"
msgstr "Veelhoek tekenen"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:223
#: authorizations/templates/authorizations/new_authorization_default.html:223
msgid "Terminer"
msgstr "Voltooien"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:231
#: authorizations/templates/authorizations/new_authorization_default.html:231
msgid ""
"Cliquez sur « Dessiner un polygone » puis cliquez sur la carte pour ajouter "
"des sommets. Cliquez sur le premier sommet pour fermer le polygone."
@ -595,60 +595,60 @@ msgstr ""
"Klik op « Veelhoek tekenen » en klik vervolgens op de kaart om hoekpunten "
"toe te voegen. Klik op het eerste hoekpunt om de veelhoek te sluiten."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:245
#: authorizations/templates/authorizations/new_authorization_default.html:245
msgid "Vos coordonnées"
msgstr "Uw contactgegevens"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:278
#: loko/authorizations/templates/authorizations/new_authorization_default.html:317
#: loko/authorizations/templates/authorizations/new_authorization_default.html:337
#: authorizations/templates/authorizations/new_authorization_default.html:278
#: authorizations/templates/authorizations/new_authorization_default.html:317
#: authorizations/templates/authorizations/new_authorization_default.html:337
msgid "optionnel"
msgstr "optioneel"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:292
#: authorizations/templates/authorizations/new_authorization_default.html:292
msgid "Date(s) d'occupation"
msgstr "Bezettingsdatum(-data)"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:298
#: authorizations/templates/authorizations/new_authorization_default.html:298
msgid "Veuillez indiquer au moins une date de début d'occupation."
msgstr "Geef ten minste één begindatum van de bezetting op."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:328
#: authorizations/templates/authorizations/new_authorization_default.html:328
msgid "Ajouter une date"
msgstr "Een datum toevoegen"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:336
#: authorizations/templates/authorizations/new_authorization_default.html:336
msgid "Document(s) à joindre"
msgstr "Bij te voegen document(en)"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:360
#: authorizations/templates/authorizations/new_authorization_default.html:360
msgid "Ajouter un document"
msgstr "Een document toevoegen"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:367
#: authorizations/templates/authorizations/new_authorization_default.html:367
msgid "Envoyer la demande"
msgstr "De aanvraag verzenden"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:385
#: authorizations/templates/authorizations/new_authorization_default.html:385
msgid ""
"Veillez à joindre en annexe l'attestation d'assurance couvrant tous les "
"risques."
msgstr "Voeg als bijlage het verzekeringsbewijs bij dat alle risico's dekt."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:386
#: authorizations/templates/authorizations/new_authorization_default.html:386
msgid "Veillez à joindre en annexe l'autorisation de la commune."
msgstr "Voeg als bijlage de gemeentelijke toestemming bij."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:472
#: loko/authorizations/templates/authorizations/new_authorization_default.html:521
#: authorizations/templates/authorizations/new_authorization_default.html:472
#: authorizations/templates/authorizations/new_authorization_default.html:521
msgid "Polygone enregistré. Cliquez sur « Dessiner » pour le redessiner."
msgstr "Veelhoek opgeslagen. Klik op « Tekenen » om hem opnieuw te tekenen."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:492
#: authorizations/templates/authorizations/new_authorization_default.html:492
msgid "Cliquer pour fermer le polygone"
msgstr "Klik om de veelhoek te sluiten"
#: loko/authorizations/templates/authorizations/new_authorization_default.html:536
#: authorizations/templates/authorizations/new_authorization_default.html:536
msgid ""
"Cliquez sur « Dessiner un polygone » puis cliquez sur la carte pour ajouter "
"des sommets."
@ -656,25 +656,25 @@ msgstr ""
"Klik op « Veelhoek tekenen » en klik vervolgens op de kaart om hoekpunten "
"toe te voegen."
#: loko/authorizations/templates/authorizations/new_authorization_default.html:559
#: authorizations/templates/authorizations/new_authorization_default.html:559
msgid ""
"Cliquez sur la carte pour ajouter des sommets. Cliquez sur le premier sommet "
"pour fermer le polygone."
msgstr ""
#: loko/authorizations/views.py:326 loko/authorizations/views.py:375
#: authorizations/views.py:326 authorizations/views.py:375
msgid "Vous n'avez pas accès à cette vue."
msgstr ""
#: loko/authorizations/views.py:392
#: authorizations/views.py:392
msgid "La demande a été mise à jour avec succès."
msgstr ""
#: loko/authorizations/views.py:409
#: authorizations/views.py:409
msgid "Le document a été ajouté avec succès."
msgstr ""
#: loko/authorizations/views.py:413
#: authorizations/views.py:413
msgid "Veuillez fournir une description et un fichier."
msgstr ""

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,526 +17,526 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: loko/common/middleware.py:154
#: common/middleware.py:154
msgid ""
"Votre session a expiré après le délai configuré. Veuillez vous reconnecter."
msgstr ""
"Your session has expired after the configured timeout. Please log in again."
#: loko/common/models.py:162
#: common/models.py:162
msgid "Français"
msgstr ""
#: loko/common/models.py:163
#: common/models.py:163
msgid "Nederlands"
msgstr ""
#: loko/common/models.py:164
#: common/models.py:164
msgid "English"
msgstr ""
#: loko/common/models.py:170
#: common/models.py:170
msgid "Langue préférée"
msgstr ""
#: loko/common/models.py:171
#: common/models.py:171
msgid "Langue utilisée pour l'interface, les e-mails et les notifications."
msgstr ""
#: loko/common/models.py:175
#: common/models.py:175
msgid "Activer les rappels par e-mail"
msgstr "Enable email reminders"
#: loko/common/models.py:176
#: common/models.py:176
msgid ""
"Recevoir un e-mail de rappel pour les notifications non lues après un "
"certain délai."
msgstr ""
#: loko/common/models.py:181
#: common/models.py:181
msgid "E-mail(s) de réception des rappels"
msgstr "Reminder email recipient(s)"
#: loko/common/models.py:182
#: common/models.py:182
msgid ""
"Adresses e-mail séparées par des virgules. Si vide, l'adresse de votre "
"compte sera utilisée."
msgstr ""
#: loko/common/models.py:186
#: common/models.py:186
msgid "Délai avant rappel (en heures)"
msgstr "Reminder delay (in hours)"
#: loko/common/models.py:187
#: common/models.py:187
msgid ""
"Nombre d'heures écoulées après la réception d'une notification avant l'envoi "
"d'un rappel par e-mail."
msgstr ""
#: loko/common/private_files/views.py:37
#: common/private_files/views.py:37
msgid "Lien expiré ou invalide"
msgstr "Expired or invalid link"
#: loko/common/private_files/views.py:43
#: common/private_files/views.py:43
msgid "Modèle inconnu"
msgstr "Unknown model"
#: loko/common/private_files/views.py:47
#: common/private_files/views.py:47
msgid "Objet introuvable"
msgstr "Object not found"
#: loko/common/private_files/views.py:53
#: common/private_files/views.py:53
msgid "Fichier non exposé"
msgstr "File not exposed"
#: loko/common/private_files/views.py:58
#: common/private_files/views.py:58
msgid "Accès refusé"
msgstr "Access denied"
#: loko/common/private_files/views.py:63
#: common/private_files/views.py:63
msgid "Fichier introuvable"
msgstr "File not found"
#: loko/common/templates/admin/common/status_permission_matrix.html:19
#: common/templates/admin/common/status_permission_matrix.html:19
msgid "Permission"
msgstr "Permission"
#: loko/common/templates/admin/common/status_permission_matrix.html:36
#: common/templates/admin/common/status_permission_matrix.html:36
msgid "Voir"
msgstr "View"
#: loko/common/templates/admin/common/status_permission_matrix.html:53
#: common/templates/admin/common/status_permission_matrix.html:53
msgid "Modifier"
msgstr "Edit"
#: loko/common/templates/admin/common/status_permission_matrix.html:70
#: common/templates/admin/common/status_permission_matrix.html:70
msgid "Changer → vers"
msgstr "Change → to"
#: loko/common/templates/admin/common/status_permission_matrix.html:102
#: common/templates/admin/common/status_permission_matrix.html:102
msgid "Enregistrez d'abord pour configurer les permissions par statut."
msgstr "Save first to configure permissions by status."
#: loko/common/templates/common/account_info.html:8
#: common/templates/common/account_info.html:8
msgid "Déconnexion"
msgstr "Logout"
#: loko/common/templates/common/account_info.html:26
#: common/templates/common/account_info.html:26
msgid "Vous êtes connecté en tant que :"
msgstr "You are logged in as:"
#: loko/common/templates/common/account_info.html:32
#: common/templates/common/account_info.html:32
msgid "Changer de langue"
msgstr "Change language"
#: loko/common/templates/common/account_info.html:40
#: common/templates/common/account_info.html:40
msgid "Choisir la langue"
msgstr "Choose language"
#: loko/common/templates/common/account_info.html:42
#: loko/common/templates/common/account_info.html:88
#: loko/common/templates/common/components/document_viewer.html:201
#: common/templates/common/account_info.html:42
#: common/templates/common/account_info.html:88
#: common/templates/common/components/document_viewer.html:201
msgid "Fermer"
msgstr "Close"
#: loko/common/templates/common/account_info.html:73
#: loko/common/templates/common/account_info.html:86
#: common/templates/common/account_info.html:73
#: common/templates/common/account_info.html:86
msgid "Modifier mon mot de passe"
msgstr "Change my password"
#: loko/common/templates/common/account_info.html:158
#: common/templates/common/account_info.html:158
msgid "Annuler"
msgstr "Cancel"
#: loko/common/templates/common/account_info.html:161
#: common/templates/common/account_info.html:161
msgid "Enregistrer"
msgstr "Save"
#: loko/common/templates/common/account_info.html:174
#: common/templates/common/account_info.html:174
msgid "Se déconnecter"
msgstr "Sign out"
#: loko/common/templates/common/account_info.html:181
#: loko/common/templates/common/components/help_panel.html:125
#: common/templates/common/account_info.html:181
#: common/templates/common/components/help_panel.html:125
msgid "Retour"
msgstr "Back"
#: loko/common/templates/common/components/document_viewer.html:40
#: loko/common/templates/common/components/document_viewer.html:50
#: loko/common/templates/common/components/document_viewer.html:61
#: common/templates/common/components/document_viewer.html:40
#: common/templates/common/components/document_viewer.html:50
#: common/templates/common/components/document_viewer.html:61
msgid "Supprimer"
msgstr "Delete"
#: loko/common/templates/common/components/document_viewer.html:75
#: common/templates/common/components/document_viewer.html:75
msgid "Copier vers une localisation ou un asset"
msgstr "Copy to a location or an asset"
#: loko/common/templates/common/components/document_viewer.html:99
#: loko/common/templates/common/components/document_viewer.html:154
#: common/templates/common/components/document_viewer.html:99
#: common/templates/common/components/document_viewer.html:154
msgid "Historique des versions"
msgstr "Version history"
#: loko/common/templates/common/components/document_viewer.html:156
#: common/templates/common/components/document_viewer.html:156
msgid "Historique"
msgstr "History"
#: loko/common/templates/common/components/document_viewer.html:180
#: common/templates/common/components/document_viewer.html:180
msgid "Visionneuse de documents"
msgstr "Document viewer"
#: loko/common/templates/common/components/document_viewer.html:188
#: common/templates/common/components/document_viewer.html:188
msgid "Ouvrir en pleine page"
msgstr "Open in full screen"
#: loko/common/templates/common/components/document_viewer.html:195
#: loko/common/templates/common/components/document_viewer.html:196
#: loko/common/templates/common/components/document_viewer.html:261
#: common/templates/common/components/document_viewer.html:195
#: common/templates/common/components/document_viewer.html:196
#: common/templates/common/components/document_viewer.html:261
msgid "Télécharger"
msgstr "Download"
#: loko/common/templates/common/components/document_viewer.html:229
#: common/templates/common/components/document_viewer.html:229
msgid "File truncated to the first 50 000 characters."
msgstr "File truncated to the first 50,000 characters."
#: loko/common/templates/common/components/document_viewer.html:245
#: common/templates/common/components/document_viewer.html:245
msgid "Only the first 200 rows are shown."
msgstr "Only the first 200 rows are shown."
#: loko/common/templates/common/components/document_viewer.html:301
#: common/templates/common/components/document_viewer.html:301
msgid "Précédent"
msgstr "Previous"
#: loko/common/templates/common/components/document_viewer.html:309
#: common/templates/common/components/document_viewer.html:309
msgid "Suivant"
msgstr "Next"
#: loko/common/templates/common/components/document_viewer.html:432
#: common/templates/common/components/document_viewer.html:432
msgid "Aucun document associé"
msgstr "No associated document"
#: loko/common/templates/common/components/help_panel.html:9
#: common/templates/common/components/help_panel.html:9
msgid "Chargement..."
msgstr "Loading..."
#: loko/common/templates/common/components/help_panel.html:10
#: common/templates/common/components/help_panel.html:10
msgid "Erreur lors du chargement."
msgstr "Erreur lors du chargement."
#: loko/common/templates/common/components/help_panel.html:16
#: loko/common/templates/common/components/help_panel.html:144
#: common/templates/common/components/help_panel.html:16
#: common/templates/common/components/help_panel.html:144
msgid "Centre d'aide"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:19
#: common/templates/common/components/help_panel.html:19
msgid "Agrandir en grand format"
msgstr "Agrandir en grand format"
#: loko/common/templates/common/components/help_panel.html:21
#: common/templates/common/components/help_panel.html:21
msgid "Agrandir"
msgstr "Agrandir"
#: loko/common/templates/common/components/help_panel.html:37
#: common/templates/common/components/help_panel.html:37
msgid "Rechercher un guide..."
msgstr "Rechercher un guide..."
#: loko/common/templates/common/components/help_panel.html:46
#: common/templates/common/components/help_panel.html:46
msgid "Prise en main de StreetUp"
msgstr "Prise en main de StreetUp"
#: loko/common/templates/common/components/help_panel.html:47
#: common/templates/common/components/help_panel.html:47
msgid "Découvrez les bases de l'application, la navigation et le menu."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:55
#: common/templates/common/components/help_panel.html:55
msgid "Concepts et notions clés de StreetUp"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:56
#: common/templates/common/components/help_panel.html:56
msgid ""
"Comprendre la différence entre Assets, Observations, Inspections, "
"Interventions et Contrôles."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:64
#: common/templates/common/components/help_panel.html:64
msgid "Rechercher et filtrer des assets"
msgstr "Rechercher et filtrer des assets"
#: loko/common/templates/common/components/help_panel.html:65
#: common/templates/common/components/help_panel.html:65
msgid "Apprenez à rechercher, filtrer et personnaliser l'inventaire."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:73
#: common/templates/common/components/help_panel.html:73
msgid "Statuts des interventions"
msgstr "Statuts des interventions"
#: loko/common/templates/common/components/help_panel.html:74
#: common/templates/common/components/help_panel.html:74
msgid ""
"Comprendre le cycle de vie d'une intervention à travers ses différents "
"statuts."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:83
#: common/templates/common/components/help_panel.html:83
msgid "Approuver des interventions"
msgstr "Approuver des interventions"
#: loko/common/templates/common/components/help_panel.html:84
#: common/templates/common/components/help_panel.html:84
msgid ""
"Guide destiné aux gestionnaires pour valider et approuver les chantiers."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:94
#: common/templates/common/components/help_panel.html:94
msgid "Gérer les projets"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:95
#: common/templates/common/components/help_panel.html:95
msgid ""
"Comment regrouper les interventions et suivre la progression des chantiers."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:105
#: common/templates/common/components/help_panel.html:105
msgid "Ajouter un contrôle"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:106
#: common/templates/common/components/help_panel.html:106
msgid "Comment planifier, réaliser et synchroniser un contrôle de conformité."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:115
#: common/templates/common/components/help_panel.html:115
msgid "Aucun guide ne correspond à votre recherche."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:147
#: loko/common/templates/common/components/help_panel.html:149
#: common/templates/common/components/help_panel.html:147
#: common/templates/common/components/help_panel.html:149
msgid "Réduire en panneau latéral"
msgstr ""
#: loko/common/tests.py:48 loko/common/tests.py:80 loko/common/views.py:265
#: loko/common/views.py:269 loko/common/views.py:280
#: common/tests.py:48 common/tests.py:80 common/views.py:265
#: common/views.py:269 common/views.py:280
msgid "Vous ne pouvez pas accéder à ce compte."
msgstr "You cannot access this account."
#: loko/common/utils.py:133
#: common/utils.py:133
msgid "Belgique (PEB / Maison Communale / Sécurité PMR)"
msgstr "Belgium (PEB / Town Hall / PRM Safety)"
#: loko/common/utils.py:134
#: common/utils.py:134
msgid "Hôtel de Ville / Maison Communale"
msgstr "Town Hall / Municipal Building"
#: loko/common/utils.py:135
#: common/utils.py:135
msgid "PEB"
msgstr "PEB"
#: loko/common/utils.py:136
#: common/utils.py:136
msgid "Performance Énergétique des Bâtiments (PEB)"
msgstr "Building Energy Performance (PEB)"
#: loko/common/utils.py:137
#: common/utils.py:137
msgid "Bilan Carbone"
msgstr "Carbon Footprint"
#: loko/common/utils.py:138
#: common/utils.py:138
msgid "Émissions de Carbone / Bilan Énergétique"
msgstr "Carbon Emissions / Energy Audit"
#: loko/common/utils.py:139
#: common/utils.py:139
msgid "Accès public & PMR"
msgstr "Public & PRM Access"
#: loko/common/utils.py:140
#: common/utils.py:140
msgid "Accueil & Sécurité du Public (Normes PMR)"
msgstr "Public Reception & Safety (PRM Standards)"
#: loko/common/utils.py:141
#: common/utils.py:141
msgid "Catégorie d'accueil"
msgstr "Reception Category"
#: loko/common/utils.py:142
#: common/utils.py:142
msgid "Type d'affectation"
msgstr "Assignment Type"
#: loko/common/utils.py:145
#: common/utils.py:145
msgid "France (DPE / GES / Mairie / ERP)"
msgstr "France (DPE / GHG / Town Hall / ERP)"
#: loko/common/utils.py:146
#: common/utils.py:146
msgid "Mairie / Hôtel de Ville"
msgstr "Town Hall / City Hall"
#: loko/common/utils.py:147
#: common/utils.py:147
msgid "DPE"
msgstr "DPE"
#: loko/common/utils.py:148
#: common/utils.py:148
msgid "Diagnostic de Performance Énergétique (DPE)"
msgstr "Energy Performance Certificate (DPE)"
#: loko/common/utils.py:149
#: common/utils.py:149
msgid "GES"
msgstr "GHG"
#: loko/common/utils.py:150
#: common/utils.py:150
msgid "Émissions de Gaz à Effet de Serre (GES)"
msgstr "Greenhouse Gas Emissions (GHG)"
#: loko/common/utils.py:151
#: common/utils.py:151
msgid "ERP"
msgstr "ERP"
#: loko/common/utils.py:152
#: common/utils.py:152
msgid "Établissement Recevant du Public (ERP)"
msgstr "Public Reception Facility (ERP)"
#: loko/common/utils.py:153
#: common/utils.py:153
msgid "Catégorie ERP"
msgstr "ERP Category"
#: loko/common/utils.py:154
#: common/utils.py:154
msgid "Type ERP"
msgstr "ERP Type"
#: loko/common/utils.py:157
#: common/utils.py:157
msgid "International / Générique"
msgstr "International / Generic"
#: loko/common/utils.py:158
#: common/utils.py:158
msgid "Bâtiment Administratif / Hôtel de Ville"
msgstr "Administrative Building / Town Hall"
#: loko/common/utils.py:159
#: common/utils.py:159
msgid "PEB / DPE"
msgstr "EPC / Energy Diag"
#: loko/common/utils.py:160
#: common/utils.py:160
msgid "Performance Énergétique (PEB / DPE / EPC)"
msgstr "Energy Performance (PEB / DPE / EPC)"
#: loko/common/utils.py:161
#: common/utils.py:161
msgid "Émissions Carbone"
msgstr "Carbon Emissions"
#: loko/common/utils.py:162
#: common/utils.py:162
msgid "Bilan Carbone & Émissions"
msgstr "Carbon Footprint & Emissions"
#: loko/common/utils.py:163
#: common/utils.py:163
msgid "Accès Public"
msgstr "Public Access"
#: loko/common/utils.py:164
#: common/utils.py:164
msgid "Bâtiment d'Accueil du Public (ERP / PMR)"
msgstr "Public Reception Building (ERP / PRM)"
#: loko/common/utils.py:165
#: common/utils.py:165
msgid "Capacité d'accueil"
msgstr "Reception Capacity"
#: loko/common/utils.py:166
#: common/utils.py:166
msgid "Type d'établissement"
msgstr "Establishment Type"
#: loko/common/views.py:104
#: common/views.py:104
msgid "Coordonnées invalides"
msgstr "Invalid coordinates"
#: loko/common/views.py:120
#: common/views.py:120
msgid "Aucune rue trouvée"
msgstr "No street found"
#: loko/common/views.py:205
#: common/views.py:205
msgid "Mot de passe mis à jour avec succès."
msgstr "Password updated successfully."
#: loko/common/views.py:235
#: common/views.py:235
msgid "Aucun compte lié n'est disponible."
msgstr "No linked account is available."
#: loko/common/views.py:239
#: common/views.py:239
msgid "Aucun compte cible n'a été sélectionné."
msgstr "No target account was selected."
#: loko/common/views.py:243
#: common/views.py:243
msgid "Ce compte est déjà actif."
msgstr "This account is already active."
#: loko/common/views.py:286
#: common/views.py:286
msgid "Changement de compte effectué."
msgstr "Account switch completed."
#: loko/common/views.py:304 loko/common/views.py:329 loko/common/views.py:356
#: loko/common/views.py:397 loko/common/views.py:428 loko/common/views.py:457
#: loko/common/views.py:524 loko/common/views.py:551
#: common/views.py:304 common/views.py:329 common/views.py:356
#: common/views.py:397 common/views.py:428 common/views.py:457
#: common/views.py:524 common/views.py:551
msgid "Données invalides"
msgstr "Invalid data"
#: loko/common/views.py:308 loko/common/views.py:333
#: common/views.py:308 common/views.py:333
msgid "Layout invalide"
msgstr "Invalid layout"
#: loko/common/views.py:316 loko/common/views.py:341 loko/common/views.py:383
#: loko/common/views.py:414 loko/common/views.py:445 loko/common/views.py:511
#: loko/common/views.py:537 loko/common/views.py:568 loko/common/views.py:586
#: common/views.py:316 common/views.py:341 common/views.py:383
#: common/views.py:414 common/views.py:445 common/views.py:511
#: common/views.py:537 common/views.py:568 common/views.py:586
msgid "Configuration utilisateur non trouvée"
msgstr "User configuration not found"
#: loko/common/views.py:363 loko/common/views.py:403 loko/common/views.py:434
#: loko/common/views.py:557
#: common/views.py:363 common/views.py:403 common/views.py:434
#: common/views.py:557
msgid "Format de filtres invalide"
msgstr "Invalid filter format"
#: loko/common/views.py:367 loko/common/views.py:406 loko/common/views.py:437
#: loko/common/views.py:560
#: common/views.py:367 common/views.py:406 common/views.py:437
#: common/views.py:560
msgid "Format de tri invalide"
msgstr "Invalid sort format"
#: loko/common/views.py:375
#: common/views.py:375
msgid "Format de colonnes invalide"
msgstr "Invalid column format"
#: loko/common/views.py:472
#: common/views.py:472
msgid "Format de thématiques invalide"
msgstr "Invalid thematic format"
#: loko/common/views.py:474
#: common/views.py:474
msgid "Format de catégories invalide"
msgstr "Invalid category format"
#: loko/common/views.py:476
#: common/views.py:476
msgid "Format de modèles invalide"
msgstr "Invalid model format"
#: loko/common/views.py:478
#: common/views.py:478
msgid "Format de filtres thématiques invalide"
msgstr "Invalid thematic filter format"
#: loko/common/views.py:480
#: common/views.py:480
msgid "Format de colonnes visibles invalide"
msgstr "Invalid visible columns format"
#: loko/common/views.py:482
#: common/views.py:482
msgid "Format de filtre type invalide"
msgstr "Invalid type filter format"
#: loko/common/views.py:484
#: common/views.py:484
msgid "Format de filtres statut invalide"
msgstr "Invalid status filter format"
#: loko/common/views.py:486
#: common/views.py:486
msgid "Format de filtres statut de validation invalide"
msgstr "Invalid validation status filter format"
#: loko/common/views.py:530
#: common/views.py:530
msgid "Format de préférences invalide"
msgstr "Invalid filter format"
#: loko/common/views.py:581 loko/common/views.py:607
#: common/views.py:581 common/views.py:607
msgid "Document non trouvé"
msgstr "No street found"
#: loko/common/views.py:591 loko/common/views.py:595
#: common/views.py:591 common/views.py:595
msgid "Accès interdit"
msgstr ""
#: loko/common/views.py:613
#: common/views.py:613
msgid "Erreur lors de la lecture du document"
msgstr "Erreur lors de la lecture du document"

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,259 +17,259 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: loko/common/middleware.py:154
#: common/middleware.py:154
msgid ""
"Votre session a expiré après le délai configuré. Veuillez vous reconnecter."
msgstr ""
"Votre session a expiré après le délai configuré. Veuillez vous reconnecter."
#: loko/common/models.py:162
#: common/models.py:162
msgid "Français"
msgstr ""
#: loko/common/models.py:163
#: common/models.py:163
msgid "Nederlands"
msgstr ""
#: loko/common/models.py:164
#: common/models.py:164
msgid "English"
msgstr ""
#: loko/common/models.py:170
#: common/models.py:170
msgid "Langue préférée"
msgstr ""
#: loko/common/models.py:171
#: common/models.py:171
msgid "Langue utilisée pour l'interface, les e-mails et les notifications."
msgstr ""
#: loko/common/models.py:175
#: common/models.py:175
msgid "Activer les rappels par e-mail"
msgstr "Activer les rappels par e-mail"
#: loko/common/models.py:176
#: common/models.py:176
msgid ""
"Recevoir un e-mail de rappel pour les notifications non lues après un "
"certain délai."
msgstr ""
#: loko/common/models.py:181
#: common/models.py:181
msgid "E-mail(s) de réception des rappels"
msgstr "E-mail(s) de réception des rappels"
#: loko/common/models.py:182
#: common/models.py:182
msgid ""
"Adresses e-mail séparées par des virgules. Si vide, l'adresse de votre "
"compte sera utilisée."
msgstr ""
#: loko/common/models.py:186
#: common/models.py:186
msgid "Délai avant rappel (en heures)"
msgstr "Délai avant rappel (en heures)"
#: loko/common/models.py:187
#: common/models.py:187
msgid ""
"Nombre d'heures écoulées après la réception d'une notification avant l'envoi "
"d'un rappel par e-mail."
msgstr ""
#: loko/common/private_files/views.py:37
#: common/private_files/views.py:37
msgid "Lien expiré ou invalide"
msgstr "Lien expiré ou invalide"
#: loko/common/private_files/views.py:43
#: common/private_files/views.py:43
msgid "Modèle inconnu"
msgstr "Modèle inconnu"
#: loko/common/private_files/views.py:47
#: common/private_files/views.py:47
msgid "Objet introuvable"
msgstr "Objet introuvable"
#: loko/common/private_files/views.py:53
#: common/private_files/views.py:53
msgid "Fichier non exposé"
msgstr "Fichier non exposé"
#: loko/common/private_files/views.py:58
#: common/private_files/views.py:58
msgid "Accès refusé"
msgstr "Accès refusé"
#: loko/common/private_files/views.py:63
#: common/private_files/views.py:63
msgid "Fichier introuvable"
msgstr "Fichier introuvable"
#: loko/common/templates/admin/common/status_permission_matrix.html:19
#: common/templates/admin/common/status_permission_matrix.html:19
msgid "Permission"
msgstr "Permission"
#: loko/common/templates/admin/common/status_permission_matrix.html:36
#: common/templates/admin/common/status_permission_matrix.html:36
msgid "Voir"
msgstr "Voir"
#: loko/common/templates/admin/common/status_permission_matrix.html:53
#: common/templates/admin/common/status_permission_matrix.html:53
msgid "Modifier"
msgstr "Modifier"
#: loko/common/templates/admin/common/status_permission_matrix.html:70
#: common/templates/admin/common/status_permission_matrix.html:70
msgid "Changer → vers"
msgstr "Changer → vers"
#: loko/common/templates/admin/common/status_permission_matrix.html:102
#: common/templates/admin/common/status_permission_matrix.html:102
msgid "Enregistrez d'abord pour configurer les permissions par statut."
msgstr "Enregistrez d'abord pour configurer les permissions par statut."
#: loko/common/templates/common/account_info.html:8
#: common/templates/common/account_info.html:8
msgid "Déconnexion"
msgstr "Déconnexion"
#: loko/common/templates/common/account_info.html:26
#: common/templates/common/account_info.html:26
msgid "Vous êtes connecté en tant que :"
msgstr "Vous êtes connecté en tant que :"
#: loko/common/templates/common/account_info.html:32
#: common/templates/common/account_info.html:32
msgid "Changer de langue"
msgstr "Changer de langue"
#: loko/common/templates/common/account_info.html:40
#: common/templates/common/account_info.html:40
msgid "Choisir la langue"
msgstr "Choisir la langue"
#: loko/common/templates/common/account_info.html:42
#: loko/common/templates/common/account_info.html:88
#: loko/common/templates/common/components/document_viewer.html:201
#: common/templates/common/account_info.html:42
#: common/templates/common/account_info.html:88
#: common/templates/common/components/document_viewer.html:201
msgid "Fermer"
msgstr "Fermer"
#: loko/common/templates/common/account_info.html:73
#: loko/common/templates/common/account_info.html:86
#: common/templates/common/account_info.html:73
#: common/templates/common/account_info.html:86
msgid "Modifier mon mot de passe"
msgstr "Modifier mon mot de passe"
#: loko/common/templates/common/account_info.html:158
#: common/templates/common/account_info.html:158
msgid "Annuler"
msgstr "Annuler"
#: loko/common/templates/common/account_info.html:161
#: common/templates/common/account_info.html:161
msgid "Enregistrer"
msgstr "Enregistrer"
#: loko/common/templates/common/account_info.html:174
#: common/templates/common/account_info.html:174
msgid "Se déconnecter"
msgstr "Se déconnecter"
#: loko/common/templates/common/account_info.html:181
#: loko/common/templates/common/components/help_panel.html:125
#: common/templates/common/account_info.html:181
#: common/templates/common/components/help_panel.html:125
msgid "Retour"
msgstr "Retour"
#: loko/common/templates/common/components/document_viewer.html:40
#: loko/common/templates/common/components/document_viewer.html:50
#: loko/common/templates/common/components/document_viewer.html:61
#: common/templates/common/components/document_viewer.html:40
#: common/templates/common/components/document_viewer.html:50
#: common/templates/common/components/document_viewer.html:61
msgid "Supprimer"
msgstr "Supprimer"
#: loko/common/templates/common/components/document_viewer.html:75
#: common/templates/common/components/document_viewer.html:75
msgid "Copier vers une localisation ou un asset"
msgstr "Copier vers une localisation ou un asset"
#: loko/common/templates/common/components/document_viewer.html:99
#: loko/common/templates/common/components/document_viewer.html:154
#: common/templates/common/components/document_viewer.html:99
#: common/templates/common/components/document_viewer.html:154
msgid "Historique des versions"
msgstr "Historique des versions"
#: loko/common/templates/common/components/document_viewer.html:156
#: common/templates/common/components/document_viewer.html:156
msgid "Historique"
msgstr "Historique"
#: loko/common/templates/common/components/document_viewer.html:180
#: common/templates/common/components/document_viewer.html:180
msgid "Visionneuse de documents"
msgstr "Visionneuse de documents"
#: loko/common/templates/common/components/document_viewer.html:188
#: common/templates/common/components/document_viewer.html:188
msgid "Ouvrir en pleine page"
msgstr "Ouvrir en pleine page"
#: loko/common/templates/common/components/document_viewer.html:195
#: loko/common/templates/common/components/document_viewer.html:196
#: loko/common/templates/common/components/document_viewer.html:261
#: common/templates/common/components/document_viewer.html:195
#: common/templates/common/components/document_viewer.html:196
#: common/templates/common/components/document_viewer.html:261
msgid "Télécharger"
msgstr "Télécharger"
#: loko/common/templates/common/components/document_viewer.html:229
#: common/templates/common/components/document_viewer.html:229
msgid "File truncated to the first 50 000 characters."
msgstr "File truncated to the first 50 000 characters."
#: loko/common/templates/common/components/document_viewer.html:245
#: common/templates/common/components/document_viewer.html:245
msgid "Only the first 200 rows are shown."
msgstr "Only the first 200 rows are shown."
#: loko/common/templates/common/components/document_viewer.html:301
#: common/templates/common/components/document_viewer.html:301
msgid "Précédent"
msgstr "Précédent"
#: loko/common/templates/common/components/document_viewer.html:309
#: common/templates/common/components/document_viewer.html:309
msgid "Suivant"
msgstr "Suivant"
#: loko/common/templates/common/components/document_viewer.html:432
#: common/templates/common/components/document_viewer.html:432
msgid "Aucun document associé"
msgstr "Aucun document associé"
#: loko/common/templates/common/components/help_panel.html:9
#: common/templates/common/components/help_panel.html:9
msgid "Chargement..."
msgstr "Chargement..."
#: loko/common/templates/common/components/help_panel.html:10
#: common/templates/common/components/help_panel.html:10
msgid "Erreur lors du chargement."
msgstr "Erreur lors du chargement."
#: loko/common/templates/common/components/help_panel.html:16
#: loko/common/templates/common/components/help_panel.html:144
#: common/templates/common/components/help_panel.html:16
#: common/templates/common/components/help_panel.html:144
msgid "Centre d'aide"
msgstr "Centre d'aide"
#: loko/common/templates/common/components/help_panel.html:19
#: common/templates/common/components/help_panel.html:19
msgid "Agrandir en grand format"
msgstr "Agrandir en grand format"
#: loko/common/templates/common/components/help_panel.html:21
#: common/templates/common/components/help_panel.html:21
msgid "Agrandir"
msgstr "Agrandir"
#: loko/common/templates/common/components/help_panel.html:37
#: common/templates/common/components/help_panel.html:37
msgid "Rechercher un guide..."
msgstr "Rechercher un guide..."
#: loko/common/templates/common/components/help_panel.html:46
#: common/templates/common/components/help_panel.html:46
msgid "Prise en main de StreetUp"
msgstr "Prise en main de StreetUp"
#: loko/common/templates/common/components/help_panel.html:47
#: common/templates/common/components/help_panel.html:47
msgid "Découvrez les bases de l'application, la navigation et le menu."
msgstr "Découvrez les bases de l'application, la navigation et le menu."
#: loko/common/templates/common/components/help_panel.html:55
#: common/templates/common/components/help_panel.html:55
msgid "Concepts et notions clés de StreetUp"
msgstr "Concepts et notions clés de StreetUp"
#: loko/common/templates/common/components/help_panel.html:56
#: common/templates/common/components/help_panel.html:56
msgid ""
"Comprendre la différence entre Assets, Observations, Inspections, "
"Interventions et Contrôles."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:64
#: common/templates/common/components/help_panel.html:64
msgid "Rechercher et filtrer des assets"
msgstr "Rechercher et filtrer des assets"
#: loko/common/templates/common/components/help_panel.html:65
#: common/templates/common/components/help_panel.html:65
msgid "Apprenez à rechercher, filtrer et personnaliser l'inventaire."
msgstr "Apprenez à rechercher, filtrer et personnaliser l'inventaire."
#: loko/common/templates/common/components/help_panel.html:73
#: common/templates/common/components/help_panel.html:73
msgid "Statuts des interventions"
msgstr "Statuts des interventions"
#: loko/common/templates/common/components/help_panel.html:74
#: common/templates/common/components/help_panel.html:74
msgid ""
"Comprendre le cycle de vie d'une intervention à travers ses différents "
"statuts."
@ -277,270 +277,270 @@ msgstr ""
"Comprendre le cycle de vie d'une intervention à travers ses différents "
"statuts."
#: loko/common/templates/common/components/help_panel.html:83
#: common/templates/common/components/help_panel.html:83
msgid "Approuver des interventions"
msgstr "Approuver des interventions"
#: loko/common/templates/common/components/help_panel.html:84
#: common/templates/common/components/help_panel.html:84
msgid ""
"Guide destiné aux gestionnaires pour valider et approuver les chantiers."
msgstr ""
"Guide destiné aux gestionnaires pour valider et approuver les chantiers."
#: loko/common/templates/common/components/help_panel.html:94
#: common/templates/common/components/help_panel.html:94
msgid "Gérer les projets"
msgstr "Gérer les projets"
#: loko/common/templates/common/components/help_panel.html:95
#: common/templates/common/components/help_panel.html:95
msgid ""
"Comment regrouper les interventions et suivre la progression des chantiers."
msgstr ""
"Comment regrouper les interventions et suivre la progression des chantiers."
#: loko/common/templates/common/components/help_panel.html:105
#: common/templates/common/components/help_panel.html:105
msgid "Ajouter un contrôle"
msgstr "Ajouter un contrôle"
#: loko/common/templates/common/components/help_panel.html:106
#: common/templates/common/components/help_panel.html:106
msgid "Comment planifier, réaliser et synchroniser un contrôle de conformité."
msgstr "Comment planifier, réaliser et synchroniser un contrôle de conformité."
#: loko/common/templates/common/components/help_panel.html:115
#: common/templates/common/components/help_panel.html:115
msgid "Aucun guide ne correspond à votre recherche."
msgstr "Aucun guide ne correspond à votre recherche."
#: loko/common/templates/common/components/help_panel.html:147
#: loko/common/templates/common/components/help_panel.html:149
#: common/templates/common/components/help_panel.html:147
#: common/templates/common/components/help_panel.html:149
msgid "Réduire en panneau latéral"
msgstr "Réduire en panneau latéral"
#: loko/common/tests.py:48 loko/common/tests.py:80 loko/common/views.py:265
#: loko/common/views.py:269 loko/common/views.py:280
#: common/tests.py:48 common/tests.py:80 common/views.py:265
#: common/views.py:269 common/views.py:280
msgid "Vous ne pouvez pas accéder à ce compte."
msgstr "Vous ne pouvez pas accéder à ce compte."
#: loko/common/utils.py:133
#: common/utils.py:133
msgid "Belgique (PEB / Maison Communale / Sécurité PMR)"
msgstr "Belgique (PEB / Maison Communale / Sécurité PMR)"
#: loko/common/utils.py:134
#: common/utils.py:134
msgid "Hôtel de Ville / Maison Communale"
msgstr "Hôtel de Ville / Maison Communale"
#: loko/common/utils.py:135
#: common/utils.py:135
msgid "PEB"
msgstr "PEB"
#: loko/common/utils.py:136
#: common/utils.py:136
msgid "Performance Énergétique des Bâtiments (PEB)"
msgstr "Performance Énergétique des Bâtiments (PEB)"
#: loko/common/utils.py:137
#: common/utils.py:137
msgid "Bilan Carbone"
msgstr "Bilan Carbone"
#: loko/common/utils.py:138
#: common/utils.py:138
msgid "Émissions de Carbone / Bilan Énergétique"
msgstr "Émissions de Carbone / Bilan Énergétique"
#: loko/common/utils.py:139
#: common/utils.py:139
msgid "Accès public & PMR"
msgstr "Accès public & PMR"
#: loko/common/utils.py:140
#: common/utils.py:140
msgid "Accueil & Sécurité du Public (Normes PMR)"
msgstr "Accueil & Sécurité du Public (Normes PMR)"
#: loko/common/utils.py:141
#: common/utils.py:141
msgid "Catégorie d'accueil"
msgstr "Catégorie d'accueil"
#: loko/common/utils.py:142
#: common/utils.py:142
msgid "Type d'affectation"
msgstr "Type d'affectation"
#: loko/common/utils.py:145
#: common/utils.py:145
msgid "France (DPE / GES / Mairie / ERP)"
msgstr "France (DPE / GES / Mairie / ERP)"
#: loko/common/utils.py:146
#: common/utils.py:146
msgid "Mairie / Hôtel de Ville"
msgstr "Mairie / Hôtel de Ville"
#: loko/common/utils.py:147
#: common/utils.py:147
msgid "DPE"
msgstr "DPE"
#: loko/common/utils.py:148
#: common/utils.py:148
msgid "Diagnostic de Performance Énergétique (DPE)"
msgstr "Diagnostic de Performance Énergétique (DPE)"
#: loko/common/utils.py:149
#: common/utils.py:149
msgid "GES"
msgstr "GES"
#: loko/common/utils.py:150
#: common/utils.py:150
msgid "Émissions de Gaz à Effet de Serre (GES)"
msgstr "Émissions de Gaz à Effet de Serre (GES)"
#: loko/common/utils.py:151
#: common/utils.py:151
msgid "ERP"
msgstr "ERP"
#: loko/common/utils.py:152
#: common/utils.py:152
msgid "Établissement Recevant du Public (ERP)"
msgstr "Établissement Recevant du Public (ERP)"
#: loko/common/utils.py:153
#: common/utils.py:153
msgid "Catégorie ERP"
msgstr "Catégorie ERP"
#: loko/common/utils.py:154
#: common/utils.py:154
msgid "Type ERP"
msgstr "Type ERP"
#: loko/common/utils.py:157
#: common/utils.py:157
msgid "International / Générique"
msgstr "International / Générique"
#: loko/common/utils.py:158
#: common/utils.py:158
msgid "Bâtiment Administratif / Hôtel de Ville"
msgstr "Bâtiment Administratif / Hôtel de Ville"
#: loko/common/utils.py:159
#: common/utils.py:159
msgid "PEB / DPE"
msgstr "PEB / DPE"
#: loko/common/utils.py:160
#: common/utils.py:160
msgid "Performance Énergétique (PEB / DPE / EPC)"
msgstr "Performance Énergétique (PEB / DPE / EPC)"
#: loko/common/utils.py:161
#: common/utils.py:161
msgid "Émissions Carbone"
msgstr "Émissions Carbone"
#: loko/common/utils.py:162
#: common/utils.py:162
msgid "Bilan Carbone & Émissions"
msgstr "Bilan Carbone & Émissions"
#: loko/common/utils.py:163
#: common/utils.py:163
msgid "Accès Public"
msgstr "Accès Public"
#: loko/common/utils.py:164
#: common/utils.py:164
msgid "Bâtiment d'Accueil du Public (ERP / PMR)"
msgstr "Bâtiment d'Accueil du Public (ERP / PMR)"
#: loko/common/utils.py:165
#: common/utils.py:165
msgid "Capacité d'accueil"
msgstr "Capacité d'accueil"
#: loko/common/utils.py:166
#: common/utils.py:166
msgid "Type d'établissement"
msgstr "Type d'établissement"
#: loko/common/views.py:104
#: common/views.py:104
msgid "Coordonnées invalides"
msgstr "Coordonnées invalides"
#: loko/common/views.py:120
#: common/views.py:120
msgid "Aucune rue trouvée"
msgstr "Aucune rue trouvée"
#: loko/common/views.py:205
#: common/views.py:205
msgid "Mot de passe mis à jour avec succès."
msgstr "Mot de passe mis à jour avec succès."
#: loko/common/views.py:235
#: common/views.py:235
msgid "Aucun compte lié n'est disponible."
msgstr "Aucun compte lié n'est disponible."
#: loko/common/views.py:239
#: common/views.py:239
msgid "Aucun compte cible n'a été sélectionné."
msgstr "Aucun compte cible n'a été sélectionné."
#: loko/common/views.py:243
#: common/views.py:243
msgid "Ce compte est déjà actif."
msgstr "Ce compte est déjà actif."
#: loko/common/views.py:286
#: common/views.py:286
msgid "Changement de compte effectué."
msgstr "Changement de compte effectué."
#: loko/common/views.py:304 loko/common/views.py:329 loko/common/views.py:356
#: loko/common/views.py:397 loko/common/views.py:428 loko/common/views.py:457
#: loko/common/views.py:524 loko/common/views.py:551
#: common/views.py:304 common/views.py:329 common/views.py:356
#: common/views.py:397 common/views.py:428 common/views.py:457
#: common/views.py:524 common/views.py:551
msgid "Données invalides"
msgstr "Données invalides"
#: loko/common/views.py:308 loko/common/views.py:333
#: common/views.py:308 common/views.py:333
msgid "Layout invalide"
msgstr "Layout invalide"
#: loko/common/views.py:316 loko/common/views.py:341 loko/common/views.py:383
#: loko/common/views.py:414 loko/common/views.py:445 loko/common/views.py:511
#: loko/common/views.py:537 loko/common/views.py:568 loko/common/views.py:586
#: common/views.py:316 common/views.py:341 common/views.py:383
#: common/views.py:414 common/views.py:445 common/views.py:511
#: common/views.py:537 common/views.py:568 common/views.py:586
msgid "Configuration utilisateur non trouvée"
msgstr "Configuration utilisateur non trouvée"
#: loko/common/views.py:363 loko/common/views.py:403 loko/common/views.py:434
#: loko/common/views.py:557
#: common/views.py:363 common/views.py:403 common/views.py:434
#: common/views.py:557
msgid "Format de filtres invalide"
msgstr "Format de filtres invalide"
#: loko/common/views.py:367 loko/common/views.py:406 loko/common/views.py:437
#: loko/common/views.py:560
#: common/views.py:367 common/views.py:406 common/views.py:437
#: common/views.py:560
msgid "Format de tri invalide"
msgstr "Format de tri invalide"
#: loko/common/views.py:375
#: common/views.py:375
msgid "Format de colonnes invalide"
msgstr "Format de colonnes invalide"
#: loko/common/views.py:472
#: common/views.py:472
msgid "Format de thématiques invalide"
msgstr "Format de thématiques invalide"
#: loko/common/views.py:474
#: common/views.py:474
msgid "Format de catégories invalide"
msgstr "Format de catégories invalide"
#: loko/common/views.py:476
#: common/views.py:476
msgid "Format de modèles invalide"
msgstr "Format de modèles invalide"
#: loko/common/views.py:478
#: common/views.py:478
msgid "Format de filtres thématiques invalide"
msgstr "Format de filtres thématiques invalide"
#: loko/common/views.py:480
#: common/views.py:480
msgid "Format de colonnes visibles invalide"
msgstr "Format de colonnes visibles invalide"
#: loko/common/views.py:482
#: common/views.py:482
msgid "Format de filtre type invalide"
msgstr "Format de filtre type invalide"
#: loko/common/views.py:484
#: common/views.py:484
msgid "Format de filtres statut invalide"
msgstr "Format de filtres statut invalide"
#: loko/common/views.py:486
#: common/views.py:486
msgid "Format de filtres statut de validation invalide"
msgstr "Format de filtres statut de validation invalide"
#: loko/common/views.py:530
#: common/views.py:530
msgid "Format de préférences invalide"
msgstr "Format de préférences invalide"
#: loko/common/views.py:581 loko/common/views.py:607
#: common/views.py:581 common/views.py:607
msgid "Document non trouvé"
msgstr "Document non trouvé"
#: loko/common/views.py:591 loko/common/views.py:595
#: common/views.py:591 common/views.py:595
msgid "Accès interdit"
msgstr "Accès interdit"
#: loko/common/views.py:613
#: common/views.py:613
msgid "Erreur lors de la lecture du document"
msgstr "Erreur lors de la lecture du document"

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,527 +17,527 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: loko/common/middleware.py:154
#: common/middleware.py:154
msgid ""
"Votre session a expiré après le délai configuré. Veuillez vous reconnecter."
msgstr ""
"Uw sessie is verlopen na de ingestelde time-out. Gelieve opnieuw in te "
"loggen."
#: loko/common/models.py:162
#: common/models.py:162
msgid "Français"
msgstr ""
#: loko/common/models.py:163
#: common/models.py:163
msgid "Nederlands"
msgstr ""
#: loko/common/models.py:164
#: common/models.py:164
msgid "English"
msgstr ""
#: loko/common/models.py:170
#: common/models.py:170
msgid "Langue préférée"
msgstr ""
#: loko/common/models.py:171
#: common/models.py:171
msgid "Langue utilisée pour l'interface, les e-mails et les notifications."
msgstr ""
#: loko/common/models.py:175
#: common/models.py:175
msgid "Activer les rappels par e-mail"
msgstr "E-mailherinneringen inschakelen"
#: loko/common/models.py:176
#: common/models.py:176
msgid ""
"Recevoir un e-mail de rappel pour les notifications non lues après un "
"certain délai."
msgstr ""
#: loko/common/models.py:181
#: common/models.py:181
msgid "E-mail(s) de réception des rappels"
msgstr "E-mailadres(sen) voor herinneringen"
#: loko/common/models.py:182
#: common/models.py:182
msgid ""
"Adresses e-mail séparées par des virgules. Si vide, l'adresse de votre "
"compte sera utilisée."
msgstr ""
#: loko/common/models.py:186
#: common/models.py:186
msgid "Délai avant rappel (en heures)"
msgstr "Wachttijd vóór herinnering (in uren)"
#: loko/common/models.py:187
#: common/models.py:187
msgid ""
"Nombre d'heures écoulées après la réception d'une notification avant l'envoi "
"d'un rappel par e-mail."
msgstr ""
#: loko/common/private_files/views.py:37
#: common/private_files/views.py:37
msgid "Lien expiré ou invalide"
msgstr "Verlopen of ongeldige link"
#: loko/common/private_files/views.py:43
#: common/private_files/views.py:43
msgid "Modèle inconnu"
msgstr "Onbekend model"
#: loko/common/private_files/views.py:47
#: common/private_files/views.py:47
msgid "Objet introuvable"
msgstr "Object niet gevonden"
#: loko/common/private_files/views.py:53
#: common/private_files/views.py:53
msgid "Fichier non exposé"
msgstr "Bestand niet toegankelijk"
#: loko/common/private_files/views.py:58
#: common/private_files/views.py:58
msgid "Accès refusé"
msgstr "Toegang geweigerd"
#: loko/common/private_files/views.py:63
#: common/private_files/views.py:63
msgid "Fichier introuvable"
msgstr "Bestand niet gevonden"
#: loko/common/templates/admin/common/status_permission_matrix.html:19
#: common/templates/admin/common/status_permission_matrix.html:19
msgid "Permission"
msgstr "Machtiging"
#: loko/common/templates/admin/common/status_permission_matrix.html:36
#: common/templates/admin/common/status_permission_matrix.html:36
msgid "Voir"
msgstr "Bekijken"
#: loko/common/templates/admin/common/status_permission_matrix.html:53
#: common/templates/admin/common/status_permission_matrix.html:53
msgid "Modifier"
msgstr "Bewerken"
#: loko/common/templates/admin/common/status_permission_matrix.html:70
#: common/templates/admin/common/status_permission_matrix.html:70
msgid "Changer → vers"
msgstr "Wijzigen → naar"
#: loko/common/templates/admin/common/status_permission_matrix.html:102
#: common/templates/admin/common/status_permission_matrix.html:102
msgid "Enregistrez d'abord pour configurer les permissions par statut."
msgstr "Sla eerst op om machtigingen per status te configureren."
#: loko/common/templates/common/account_info.html:8
#: common/templates/common/account_info.html:8
msgid "Déconnexion"
msgstr "Afmelden"
#: loko/common/templates/common/account_info.html:26
#: common/templates/common/account_info.html:26
msgid "Vous êtes connecté en tant que :"
msgstr "U bent ingelogd als:"
#: loko/common/templates/common/account_info.html:32
#: common/templates/common/account_info.html:32
msgid "Changer de langue"
msgstr "Taal wijzigen"
#: loko/common/templates/common/account_info.html:40
#: common/templates/common/account_info.html:40
msgid "Choisir la langue"
msgstr "Kies de taal"
#: loko/common/templates/common/account_info.html:42
#: loko/common/templates/common/account_info.html:88
#: loko/common/templates/common/components/document_viewer.html:201
#: common/templates/common/account_info.html:42
#: common/templates/common/account_info.html:88
#: common/templates/common/components/document_viewer.html:201
msgid "Fermer"
msgstr "Sluiten"
#: loko/common/templates/common/account_info.html:73
#: loko/common/templates/common/account_info.html:86
#: common/templates/common/account_info.html:73
#: common/templates/common/account_info.html:86
msgid "Modifier mon mot de passe"
msgstr "Mijn wachtwoord wijzigen"
#: loko/common/templates/common/account_info.html:158
#: common/templates/common/account_info.html:158
msgid "Annuler"
msgstr "Annuleren"
#: loko/common/templates/common/account_info.html:161
#: common/templates/common/account_info.html:161
msgid "Enregistrer"
msgstr "Opslaan"
#: loko/common/templates/common/account_info.html:174
#: common/templates/common/account_info.html:174
msgid "Se déconnecter"
msgstr "Afmelden"
#: loko/common/templates/common/account_info.html:181
#: loko/common/templates/common/components/help_panel.html:125
#: common/templates/common/account_info.html:181
#: common/templates/common/components/help_panel.html:125
msgid "Retour"
msgstr "Terug"
#: loko/common/templates/common/components/document_viewer.html:40
#: loko/common/templates/common/components/document_viewer.html:50
#: loko/common/templates/common/components/document_viewer.html:61
#: common/templates/common/components/document_viewer.html:40
#: common/templates/common/components/document_viewer.html:50
#: common/templates/common/components/document_viewer.html:61
msgid "Supprimer"
msgstr "Verwijderen"
#: loko/common/templates/common/components/document_viewer.html:75
#: common/templates/common/components/document_viewer.html:75
msgid "Copier vers une localisation ou un asset"
msgstr "Kopiëren naar een locatie of asset"
#: loko/common/templates/common/components/document_viewer.html:99
#: loko/common/templates/common/components/document_viewer.html:154
#: common/templates/common/components/document_viewer.html:99
#: common/templates/common/components/document_viewer.html:154
msgid "Historique des versions"
msgstr "Versiegeschiedenis"
#: loko/common/templates/common/components/document_viewer.html:156
#: common/templates/common/components/document_viewer.html:156
msgid "Historique"
msgstr "Geschiedenis"
#: loko/common/templates/common/components/document_viewer.html:180
#: common/templates/common/components/document_viewer.html:180
msgid "Visionneuse de documents"
msgstr "Documentviewer"
#: loko/common/templates/common/components/document_viewer.html:188
#: common/templates/common/components/document_viewer.html:188
msgid "Ouvrir en pleine page"
msgstr "Volledig scherm openen"
#: loko/common/templates/common/components/document_viewer.html:195
#: loko/common/templates/common/components/document_viewer.html:196
#: loko/common/templates/common/components/document_viewer.html:261
#: common/templates/common/components/document_viewer.html:195
#: common/templates/common/components/document_viewer.html:196
#: common/templates/common/components/document_viewer.html:261
msgid "Télécharger"
msgstr "Downloaden"
#: loko/common/templates/common/components/document_viewer.html:229
#: common/templates/common/components/document_viewer.html:229
msgid "File truncated to the first 50 000 characters."
msgstr "Bestand ingekort tot de eerste 50.000 tekens."
#: loko/common/templates/common/components/document_viewer.html:245
#: common/templates/common/components/document_viewer.html:245
msgid "Only the first 200 rows are shown."
msgstr "Alleen de eerste 200 rijen worden weergegeven."
#: loko/common/templates/common/components/document_viewer.html:301
#: common/templates/common/components/document_viewer.html:301
msgid "Précédent"
msgstr "Vorige"
#: loko/common/templates/common/components/document_viewer.html:309
#: common/templates/common/components/document_viewer.html:309
msgid "Suivant"
msgstr "Volgende"
#: loko/common/templates/common/components/document_viewer.html:432
#: common/templates/common/components/document_viewer.html:432
msgid "Aucun document associé"
msgstr "Geen gekoppeld document"
#: loko/common/templates/common/components/help_panel.html:9
#: common/templates/common/components/help_panel.html:9
msgid "Chargement..."
msgstr "Laden..."
#: loko/common/templates/common/components/help_panel.html:10
#: common/templates/common/components/help_panel.html:10
msgid "Erreur lors du chargement."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:16
#: loko/common/templates/common/components/help_panel.html:144
#: common/templates/common/components/help_panel.html:16
#: common/templates/common/components/help_panel.html:144
msgid "Centre d'aide"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:19
#: common/templates/common/components/help_panel.html:19
msgid "Agrandir en grand format"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:21
#: common/templates/common/components/help_panel.html:21
msgid "Agrandir"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:37
#: common/templates/common/components/help_panel.html:37
msgid "Rechercher un guide..."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:46
#: common/templates/common/components/help_panel.html:46
msgid "Prise en main de StreetUp"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:47
#: common/templates/common/components/help_panel.html:47
msgid "Découvrez les bases de l'application, la navigation et le menu."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:55
#: common/templates/common/components/help_panel.html:55
msgid "Concepts et notions clés de StreetUp"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:56
#: common/templates/common/components/help_panel.html:56
msgid ""
"Comprendre la différence entre Assets, Observations, Inspections, "
"Interventions et Contrôles."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:64
#: common/templates/common/components/help_panel.html:64
msgid "Rechercher et filtrer des assets"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:65
#: common/templates/common/components/help_panel.html:65
msgid "Apprenez à rechercher, filtrer et personnaliser l'inventaire."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:73
#: common/templates/common/components/help_panel.html:73
msgid "Statuts des interventions"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:74
#: common/templates/common/components/help_panel.html:74
msgid ""
"Comprendre le cycle de vie d'une intervention à travers ses différents "
"statuts."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:83
#: common/templates/common/components/help_panel.html:83
msgid "Approuver des interventions"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:84
#: common/templates/common/components/help_panel.html:84
msgid ""
"Guide destiné aux gestionnaires pour valider et approuver les chantiers."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:94
#: common/templates/common/components/help_panel.html:94
msgid "Gérer les projets"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:95
#: common/templates/common/components/help_panel.html:95
msgid ""
"Comment regrouper les interventions et suivre la progression des chantiers."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:105
#: common/templates/common/components/help_panel.html:105
msgid "Ajouter un contrôle"
msgstr ""
#: loko/common/templates/common/components/help_panel.html:106
#: common/templates/common/components/help_panel.html:106
msgid "Comment planifier, réaliser et synchroniser un contrôle de conformité."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:115
#: common/templates/common/components/help_panel.html:115
msgid "Aucun guide ne correspond à votre recherche."
msgstr ""
#: loko/common/templates/common/components/help_panel.html:147
#: loko/common/templates/common/components/help_panel.html:149
#: common/templates/common/components/help_panel.html:147
#: common/templates/common/components/help_panel.html:149
msgid "Réduire en panneau latéral"
msgstr ""
#: loko/common/tests.py:48 loko/common/tests.py:80 loko/common/views.py:265
#: loko/common/views.py:269 loko/common/views.py:280
#: common/tests.py:48 common/tests.py:80 common/views.py:265
#: common/views.py:269 common/views.py:280
msgid "Vous ne pouvez pas accéder à ce compte."
msgstr "U hebt geen toegang tot dit account."
#: loko/common/utils.py:133
#: common/utils.py:133
msgid "Belgique (PEB / Maison Communale / Sécurité PMR)"
msgstr "België (EPB / Gemeentehuis / PMR-veiligheid)"
#: loko/common/utils.py:134
#: common/utils.py:134
msgid "Hôtel de Ville / Maison Communale"
msgstr "Stadhuis / Gemeentehuis"
#: loko/common/utils.py:135
#: common/utils.py:135
msgid "PEB"
msgstr "EPB"
#: loko/common/utils.py:136
#: common/utils.py:136
msgid "Performance Énergétique des Bâtiments (PEB)"
msgstr "Energieprestatie van Gebouwen (EPB)"
#: loko/common/utils.py:137
#: common/utils.py:137
msgid "Bilan Carbone"
msgstr "Koolstofbalans"
#: loko/common/utils.py:138
#: common/utils.py:138
msgid "Émissions de Carbone / Bilan Énergétique"
msgstr "Koolstofemissies / Energiebalans"
#: loko/common/utils.py:139
#: common/utils.py:139
msgid "Accès public & PMR"
msgstr "Publiekstoegang & PMR"
#: loko/common/utils.py:140
#: common/utils.py:140
msgid "Accueil & Sécurité du Public (Normes PMR)"
msgstr "Publieksontvangst & Veiligheid (PMR-normen)"
#: loko/common/utils.py:141
#: common/utils.py:141
msgid "Catégorie d'accueil"
msgstr "Ontvangstcategorie"
#: loko/common/utils.py:142
#: common/utils.py:142
msgid "Type d'affectation"
msgstr "Bestemmingstype"
#: loko/common/utils.py:145
#: common/utils.py:145
msgid "France (DPE / GES / Mairie / ERP)"
msgstr "Frankrijk (DPE / BKG / Stadhuis / ERP)"
#: loko/common/utils.py:146
#: common/utils.py:146
msgid "Mairie / Hôtel de Ville"
msgstr "Gemeentehuis / Stadhuis"
#: loko/common/utils.py:147
#: common/utils.py:147
msgid "DPE"
msgstr "DPE"
#: loko/common/utils.py:148
#: common/utils.py:148
msgid "Diagnostic de Performance Énergétique (DPE)"
msgstr "Energieprestatiediagnose (DPE)"
#: loko/common/utils.py:149
#: common/utils.py:149
msgid "GES"
msgstr "BKG"
#: loko/common/utils.py:150
#: common/utils.py:150
msgid "Émissions de Gaz à Effet de Serre (GES)"
msgstr "Broeikasgasemissies (BKG)"
#: loko/common/utils.py:151
#: common/utils.py:151
msgid "ERP"
msgstr "ERP"
#: loko/common/utils.py:152
#: common/utils.py:152
msgid "Établissement Recevant du Public (ERP)"
msgstr "Publiek Toegankelijke Inrichting (ERP)"
#: loko/common/utils.py:153
#: common/utils.py:153
msgid "Catégorie ERP"
msgstr "ERP-categorie"
#: loko/common/utils.py:154
#: common/utils.py:154
msgid "Type ERP"
msgstr "ERP-type"
#: loko/common/utils.py:157
#: common/utils.py:157
msgid "International / Générique"
msgstr "Internationaal / Generiek"
#: loko/common/utils.py:158
#: common/utils.py:158
msgid "Bâtiment Administratif / Hôtel de Ville"
msgstr "Administratief Gebouw / Stadhuis"
#: loko/common/utils.py:159
#: common/utils.py:159
msgid "PEB / DPE"
msgstr "EPB / DPE"
#: loko/common/utils.py:160
#: common/utils.py:160
msgid "Performance Énergétique (PEB / DPE / EPC)"
msgstr "Energieprestatie (EPB / DPE / EPC)"
#: loko/common/utils.py:161
#: common/utils.py:161
msgid "Émissions Carbone"
msgstr "Koolstofemissies"
#: loko/common/utils.py:162
#: common/utils.py:162
msgid "Bilan Carbone & Émissions"
msgstr "Koolstofbalans & Emissies"
#: loko/common/utils.py:163
#: common/utils.py:163
msgid "Accès Public"
msgstr "Publiekstoegang"
#: loko/common/utils.py:164
#: common/utils.py:164
msgid "Bâtiment d'Accueil du Public (ERP / PMR)"
msgstr "Publieksontvangstgebouw (ERP / PMR)"
#: loko/common/utils.py:165
#: common/utils.py:165
msgid "Capacité d'accueil"
msgstr "Ontvangstcapaciteit"
#: loko/common/utils.py:166
#: common/utils.py:166
msgid "Type d'établissement"
msgstr "Type inrichting"
#: loko/common/views.py:104
#: common/views.py:104
msgid "Coordonnées invalides"
msgstr "Ongeldige coördinaten"
#: loko/common/views.py:120
#: common/views.py:120
msgid "Aucune rue trouvée"
msgstr "Geen straat gevonden"
#: loko/common/views.py:205
#: common/views.py:205
msgid "Mot de passe mis à jour avec succès."
msgstr "Wachtwoord succesvol bijgewerkt."
#: loko/common/views.py:235
#: common/views.py:235
msgid "Aucun compte lié n'est disponible."
msgstr "Geen gekoppeld account beschikbaar."
#: loko/common/views.py:239
#: common/views.py:239
msgid "Aucun compte cible n'a été sélectionné."
msgstr "Geen doelaccount geselecteerd."
#: loko/common/views.py:243
#: common/views.py:243
msgid "Ce compte est déjà actif."
msgstr "Dit account is al actief."
#: loko/common/views.py:286
#: common/views.py:286
msgid "Changement de compte effectué."
msgstr "Accountwissel uitgevoerd."
#: loko/common/views.py:304 loko/common/views.py:329 loko/common/views.py:356
#: loko/common/views.py:397 loko/common/views.py:428 loko/common/views.py:457
#: loko/common/views.py:524 loko/common/views.py:551
#: common/views.py:304 common/views.py:329 common/views.py:356
#: common/views.py:397 common/views.py:428 common/views.py:457
#: common/views.py:524 common/views.py:551
msgid "Données invalides"
msgstr "Ongeldige gegevens"
#: loko/common/views.py:308 loko/common/views.py:333
#: common/views.py:308 common/views.py:333
msgid "Layout invalide"
msgstr "Ongeldige lay-out"
#: loko/common/views.py:316 loko/common/views.py:341 loko/common/views.py:383
#: loko/common/views.py:414 loko/common/views.py:445 loko/common/views.py:511
#: loko/common/views.py:537 loko/common/views.py:568 loko/common/views.py:586
#: common/views.py:316 common/views.py:341 common/views.py:383
#: common/views.py:414 common/views.py:445 common/views.py:511
#: common/views.py:537 common/views.py:568 common/views.py:586
msgid "Configuration utilisateur non trouvée"
msgstr "Gebruikersconfiguratie niet gevonden"
#: loko/common/views.py:363 loko/common/views.py:403 loko/common/views.py:434
#: loko/common/views.py:557
#: common/views.py:363 common/views.py:403 common/views.py:434
#: common/views.py:557
msgid "Format de filtres invalide"
msgstr "Ongeldig filterformaat"
#: loko/common/views.py:367 loko/common/views.py:406 loko/common/views.py:437
#: loko/common/views.py:560
#: common/views.py:367 common/views.py:406 common/views.py:437
#: common/views.py:560
msgid "Format de tri invalide"
msgstr "Ongeldig sorteervoorbeeld"
#: loko/common/views.py:375
#: common/views.py:375
msgid "Format de colonnes invalide"
msgstr "Ongeldig kolomformaat"
#: loko/common/views.py:472
#: common/views.py:472
msgid "Format de thématiques invalide"
msgstr "Ongeldig thematiekformaat"
#: loko/common/views.py:474
#: common/views.py:474
msgid "Format de catégories invalide"
msgstr "Ongeldig categorieformaat"
#: loko/common/views.py:476
#: common/views.py:476
msgid "Format de modèles invalide"
msgstr "Ongeldig modelformaat"
#: loko/common/views.py:478
#: common/views.py:478
msgid "Format de filtres thématiques invalide"
msgstr "Ongeldig thematiekfilterformaat"
#: loko/common/views.py:480
#: common/views.py:480
msgid "Format de colonnes visibles invalide"
msgstr "Ongeldig zichtbare kolommenformaat"
#: loko/common/views.py:482
#: common/views.py:482
msgid "Format de filtre type invalide"
msgstr "Ongeldig type-filterformaat"
#: loko/common/views.py:484
#: common/views.py:484
msgid "Format de filtres statut invalide"
msgstr "Ongeldig statusfilterformaat"
#: loko/common/views.py:486
#: common/views.py:486
msgid "Format de filtres statut de validation invalide"
msgstr "Ongeldig validatiestatusfilterformaat"
#: loko/common/views.py:530
#: common/views.py:530
msgid "Format de préférences invalide"
msgstr "Ongeldig filterformaat"
#: loko/common/views.py:581 loko/common/views.py:607
#: common/views.py:581 common/views.py:607
msgid "Document non trouvé"
msgstr "Geen straat gevonden"
#: loko/common/views.py:591 loko/common/views.py:595
#: common/views.py:591 common/views.py:595
msgid "Accès interdit"
msgstr ""
#: loko/common/views.py:613
#: common/views.py:613
msgid "Erreur lors de la lecture du document"
msgstr ""

View file

@ -90,19 +90,48 @@ def _get_symptom_autoclose_inline():
return SymptomAutoCloseInline
def _get_operation_template_posts_inline():
from interventions.models import ContractOperationTemplatePost, OperationTemplate
from django.db.models import Q
class ContractOperationTemplatePostInline(admin.TabularInline):
model = ContractOperationTemplatePost
extra = 0
fields = ('operation_template', 'contract_post', 'default_quantity', 'comment')
verbose_name = "Poste par défaut (Template d'opérations)"
verbose_name_plural = "Postes par défaut (Templates d'opérations)"
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "contract_post":
contract_id = request.resolver_match.kwargs.get('object_id') if request.resolver_match else None
if contract_id:
kwargs["queryset"] = ContractPost.objects.filter(contract_id=contract_id).order_by('order_number')
elif db_field.name == "operation_template":
contract_id = request.resolver_match.kwargs.get('object_id') if request.resolver_match else None
if contract_id:
contract = Contract.objects.filter(pk=contract_id).first()
if contract and contract.thematics.exists():
kwargs["queryset"] = OperationTemplate.objects.filter(
Q(thematic__in=contract.thematics.all()) | Q(thematic__isnull=True)
).distinct().order_by('name')
return super().formfield_for_foreignkey(db_field, request, **kwargs)
return ContractOperationTemplatePostInline
@admin.register(Company)
class CompanyAdmin(admin.ModelAdmin):
list_display = ('name', 'contact_email', 'phone_number')
@admin.register(Contract)
class ContractAdmin(admin.ModelAdmin):
list_display = ('contract_number', 'description', 'company', 'start_date', 'end_date', 'is_active', 'contact_phone', 'send_email_notifications', 'send_daily_summary', 'uses_occupations', 'occupations_required', 'uses_intervention_manager', 'thematics_list')
list_display = ('contract_number', 'description', 'company', 'start_date', 'end_date', 'is_active', 'contact_phone', 'send_email_notifications', 'send_daily_summary', 'uses_occupations', 'occupations_required', 'uses_intervention_manager', 'allow_team_members_edit', 'thematics_list')
search_fields = ('contract_number', 'company__name', 'description', 'contact_phone')
list_filter = ('is_active', 'thematics', 'uses_occupations', 'occupations_required', 'uses_intervention_manager', 'send_daily_summary')
list_filter = ('is_active', 'thematics', 'uses_occupations', 'occupations_required', 'uses_intervention_manager', 'allow_team_members_edit', 'send_daily_summary')
filter_horizontal = ('thematics',)
def get_inlines(self, request, obj=None):
return [_get_pause_reason_inline(), _get_symptom_autoclose_inline()] + list(super().get_inlines(request, obj))
return [_get_pause_reason_inline(), _get_symptom_autoclose_inline(), _get_operation_template_posts_inline()] + list(super().get_inlines(request, obj))
fieldsets = (
(None, {
@ -117,7 +146,7 @@ class ContractAdmin(admin.ModelAdmin):
),
}),
('Options de workflow', {
'fields': ('needs_approval', 'needs_checking', 'uses_occupations', 'occupations_required', 'uses_intervention_manager', 'warn_if_no_prestation_on_processed'),
'fields': ('needs_approval', 'needs_checking', 'uses_occupations', 'occupations_required', 'uses_intervention_manager', 'warn_if_no_prestation_on_processed', 'allow_team_members_edit'),
}),
)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,18 @@
# Generated by Django 6.0.7 on 2026-08-19 09:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contracts', '0002_initial'),
]
operations = [
migrations.AddField(
model_name='contract',
name='allow_team_members_edit',
field=models.BooleanField(default=False, help_text="Si activé, les membres d'une même équipe peuvent modifier les interventions assignées à d'autres membres de leur équipe, y compris à partir du statut 'Pris en charge' ou au-delà.", verbose_name="Modification inter-membres d'équipe autorisée"),
),
]

View file

@ -341,6 +341,11 @@ class Contract(models.Model):
verbose_name=_("Emails uniquement si priorité urgente"),
help_text=_("Si activé, les notifications email ne sont envoyées que pour les interventions de priorité 'Urgent'."),
)
allow_team_members_edit = models.BooleanField(
default=False,
verbose_name=_("Modification inter-membres d'équipe autorisée"),
help_text=_("Si activé, les membres d'une même équipe peuvent modifier les interventions assignées à d'autres membres de leur équipe, y compris à partir du statut 'Pris en charge' ou au-delà."),
)
def __str__(self):
return f"Contrat {self.contract_number} - {self.company.name}"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,18 @@
# Generated by Django 6.0.7 on 2026-08-19 07:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('home', '0003_alter_homewidget_widget_code'),
]
operations = [
migrations.AlterField(
model_name='homewidget',
name='widget_code',
field=models.CharField(choices=[('intervention_stats', 'Statistiques interventions'), ('contracts_summary', 'Résumé contrats'), ('map_today', 'Carte du jour'), ('operator_shortcuts', 'Raccourcis opérateur'), ('assets_links', 'Liens assets'), ('stock_summary', 'Résumé stock'), ('observer_shortcuts', 'Raccourcis observateur'), ('incident_counter', 'Compteur incidents à traiter'), ('intervention_to_verify', 'Compteur interventions à vérifier'), ('intervention_to_plan', 'Compteur interventions à planifier'), ('intervention_to_approve', 'Compteur interventions à approuver'), ('intervention_checked_to_approve', 'Compteur interventions vérifiées à approuver'), ('intervention_finished', 'Compteur interventions terminées'), ('intervention_on_pause', 'Compteur interventions en pause'), ('external_interventions', 'Interventions externes'), ('stock_actions', 'Actions stock')], max_length=50, unique=True, verbose_name='Code du widget'),
),
]

View file

@ -18,6 +18,7 @@ WIDGET_CODE_CHOICES = [
('intervention_checked_to_approve', _('Compteur interventions vérifiées à approuver')),
('intervention_finished', _('Compteur interventions terminées')),
('intervention_on_pause', _('Compteur interventions en pause')),
('external_interventions', _('Interventions externes')),
('stock_actions', _('Actions stock')),
]

View file

@ -0,0 +1,148 @@
{% load i18n %}
{# ========== Widget Interventions Externes ========== #}
<div class="card shadow-sm h-100" style="border-color: #0284c7 !important;">
{# --- En-tête de carte --- #}
<div class="card-header d-flex align-items-center justify-content-between text-white" style="background-color: #0284c7 !important;">
<a href="{% url 'interventions:interventions_index' %}?{% if thematic_filter_param %}{{ thematic_filter_param }}&{% endif %}external=1"
class="text-white text-decoration-none fw-bold text-uppercase d-flex align-items-center" style="letter-spacing: .05em;">
<i class="bi bi-buildings-fill me-2"></i>{% translate "Interventions externes" %}
</a>
<span class="badge bg-white text-dark rounded-pill px-2 py-1 small fw-semibold" title="{% translate 'Total des interventions externes' %}">
{{ external_interventions_total_count }}
</span>
</div>
{# --- Compteur principal des interventions non terminées --- #}
<div class="text-center py-2 border-bottom bg-light bg-opacity-25">
<a href="{% url 'interventions:interventions_index' %}?{% if thematic_filter_param %}{{ thematic_filter_param }}&{% endif %}external=1&status=in_preparation,to_be_approved,to_be_planned,to_be_processed,assigned,in_progress,on_pause,to_be_corrected"
class="text-decoration-none d-block">
<span class="display-5 fw-bold" style="color: #0284c7 !important;">{{ external_interventions_unfinished_count }}</span>
<div class="text-muted small fw-semibold">
{% blocktranslate count count=external_interventions_unfinished_count %}
intervention non terminée
{% plural %}
interventions non terminées
{% endblocktranslate %}
</div>
</a>
{# --- Compteurs détaillés par statut non terminé --- #}
{% if external_interventions_unfinished_count > 0 %}
<div class="d-flex flex-wrap justify-content-center gap-1 mt-2 px-2">
{% if external_status_counts.count_to_be_approved > 0 %}
<a href="{% url 'interventions:interventions_index' %}?{% if thematic_filter_param %}{{ thematic_filter_param }}&{% endif %}external=1&status=to_be_approved"
class="badge text-decoration-none bg-warning text-dark border border-warning-subtle py-1 px-2"
title="{% translate 'À approuver' %}">
<i class="bi bi-patch-check me-1"></i>{% translate "À approuver" %} : <strong>{{ external_status_counts.count_to_be_approved }}</strong>
</a>
{% endif %}
{% if external_status_counts.count_to_be_planned > 0 %}
<a href="{% url 'interventions:interventions_index' %}?{% if thematic_filter_param %}{{ thematic_filter_param }}&{% endif %}external=1&status=to_be_planned"
class="badge text-decoration-none bg-secondary text-white py-1 px-2"
title="{% translate 'À planifier' %}">
<i class="bi bi-calendar2-week me-1"></i>{% translate "À planifier" %} : <strong>{{ external_status_counts.count_to_be_planned }}</strong>
</a>
{% endif %}
{% if external_status_counts.count_to_be_processed > 0 %}
<a href="{% url 'interventions:interventions_index' %}?{% if thematic_filter_param %}{{ thematic_filter_param }}&{% endif %}external=1&status=to_be_processed"
class="badge text-decoration-none bg-danger text-white py-1 px-2"
title="{% translate 'À traiter' %}">
<i class="bi bi-exclamation-square me-1"></i>{% translate "À traiter" %} : <strong>{{ external_status_counts.count_to_be_processed }}</strong>
</a>
{% endif %}
{% if external_status_counts.count_assigned > 0 %}
<a href="{% url 'interventions:interventions_index' %}?{% if thematic_filter_param %}{{ thematic_filter_param }}&{% endif %}external=1&status=assigned"
class="badge text-decoration-none bg-info text-dark py-1 px-2"
title="{% translate 'Prises en charge' %}">
<i class="bi bi-hand-thumbs-up me-1"></i>{% translate "Prises en charge" %} : <strong>{{ external_status_counts.count_assigned }}</strong>
</a>
{% endif %}
{% if external_status_counts.count_in_progress > 0 %}
<a href="{% url 'interventions:interventions_index' %}?{% if thematic_filter_param %}{{ thematic_filter_param }}&{% endif %}external=1&status=in_progress"
class="badge text-decoration-none bg-primary text-white py-1 px-2"
title="{% translate 'Démarrées' %}">
<i class="bi bi-play-circle me-1"></i>{% translate "Démarrées" %} : <strong>{{ external_status_counts.count_in_progress }}</strong>
</a>
{% endif %}
{% if external_status_counts.count_on_pause > 0 %}
<a href="{% url 'interventions:interventions_index' %}?{% if thematic_filter_param %}{{ thematic_filter_param }}&{% endif %}external=1&status=on_pause"
class="badge text-decoration-none bg-dark text-white py-1 px-2"
title="{% translate 'En pause' %}">
<i class="bi bi-pause-circle me-1"></i>{% translate "En pause" %} : <strong>{{ external_status_counts.count_on_pause }}</strong>
</a>
{% endif %}
{% if external_status_counts.count_to_be_corrected > 0 %}
<a href="{% url 'interventions:interventions_index' %}?{% if thematic_filter_param %}{{ thematic_filter_param }}&{% endif %}external=1&status=to_be_corrected"
class="badge text-decoration-none bg-danger text-white py-1 px-2"
title="{% translate 'À corriger' %}">
<i class="bi bi-arrow-counterclockwise me-1"></i>{% translate "À corriger" %} : <strong>{{ external_status_counts.count_to_be_corrected }}</strong>
</a>
{% endif %}
</div>
{% endif %}
</div>
{# --- Titre section 10 dernières interventions --- #}
<div class="px-3 py-1 bg-light border-bottom small fw-semibold text-muted text-uppercase d-flex justify-content-between align-items-center" style="font-size: .75rem; letter-spacing: .05em;">
<span><i class="bi bi-clock-history me-1"></i>{% translate "10 dernières interventions" %}</span>
<span class="text-muted">{{ external_interventions_list|length }} / {{ external_interventions_total_count }}</span>
</div>
{# --- Liste des 10 dernières interventions --- #}
<ul class="list-group list-group-flush flex-grow-1">
{% for itv in external_interventions_list %}
<li class="list-group-item px-3 py-2 small">
<a href="{% url 'interventions:intervention_detail' itv.id %}" class="text-decoration-none d-block">
{# Ligne 1 : Code + Organisme + Statut #}
<div class="d-flex justify-content-between align-items-center mb-1">
<span class="fw-bold text-truncate me-1" style="color: #0284c7 !important;">{{ itv.code }}</span>
{% if itv.provider_or_company_name %}
<span class="badge bg-secondary-subtle text-secondary-emphasis border border-secondary-subtle text-truncate me-auto ms-1" style="max-width: 140px;" title="{{ itv.provider_or_company_name }}">
<i class="bi bi-building me-1"></i>{{ itv.provider_or_company_name }}
</span>
{% endif %}
<span class="badge ms-auto" style="background-color: {{ itv.status_color_hex }}; color: {{ itv.status_text_color_hex }}; font-size: .72rem;">
{{ itv.get_status_display }}
</span>
</div>
{# Ligne 2 : Titre/Description + Thématique/Catégorie + Date #}
<div class="d-flex justify-content-between align-items-center text-muted" style="font-size: .75rem;">
<span class="text-truncate me-2" style="max-width: 70%;">
{% if itv.title %}
{{ itv.title }}
{% else %}
<em class="text-muted">{% translate "Sans titre" %}</em>
{% endif %}
{% if itv.asset_category %}
&middot; {{ itv.asset_category.get_name }}
{% elif itv.thematic %}
&middot; {{ itv.thematic.code }}
{% endif %}
</span>
<span class="text-nowrap">{{ itv.creation_time|date:"d/m/Y" }}</span>
</div>
</a>
</li>
{% empty %}
<li class="list-group-item text-center text-muted py-3 small">
<i class="bi bi-check-circle text-success me-1"></i>{% translate "Aucune intervention externe" %}
</li>
{% endfor %}
</ul>
{# --- Pied de carte (Raccourci vers toutes les interventions externes) --- #}
<div class="card-footer text-center text-muted small bg-transparent">
<a href="{% url 'interventions:interventions_index' %}?{% if thematic_filter_param %}{{ thematic_filter_param }}&{% endif %}external=1"
class="text-muted text-decoration-none fw-semibold">
<i class="bi bi-arrow-right-circle me-1"></i>{% translate "Voir toutes les interventions externes" %} ({{ external_interventions_total_count }})
</a>
</div>
</div>

View file

@ -250,6 +250,102 @@ class HomeIndexViewTests(TestCase):
self.assertContains(response, 'Interventions en pause')
self.assertContains(response, 'status=on_pause')
def test_home_index_external_interventions_widget(self):
from django.urls import reverse
from django.contrib.auth import get_user_model
from common.models import UserConfig, Role, Thematic, UserThematics
from contracts.models import Company, Contract
from interventions.models import Intervention
from home.models import HomeWidget
User = get_user_model()
user = User.objects.create_user('ext_user', password='pass')
thematic = Thematic.objects.create(code='THEM_EXT', name_fr='Thema Ext', name_nl='Thema Ext')
company_internal = Company.objects.create(name='Organisme Interne')
company_external_1 = Company.objects.create(name='Société Ext 1')
company_external_2 = Company.objects.create(name='Société Ext 2')
user_config = UserConfig.objects.create(
user=user,
is_intern=True,
company=company_internal,
default_thematic=thematic,
limit_interventions_to_contracts=False
)
role_admin, _ = Role.objects.get_or_create(name='admin')
user_config.roles.add(role_admin)
UserThematics.objects.create(
user_config=user_config,
thematic=thematic,
can_edit_interventions=True,
can_view_interventions=True
)
self.client.force_login(user)
# 1. Internal intervention (linked to user's company)
Intervention.objects.create(
code='ITV-INT-001',
title='Interne A',
status='to_be_processed',
thematic=thematic,
assigned_provider=company_internal
)
# 2. External intervention 1 (unfinished)
itv_ext1 = Intervention.objects.create(
code='ITV-EXT-001',
title='Externe A',
status='to_be_processed',
thematic=thematic,
assigned_provider=company_external_1
)
# 3. External intervention 2 (finished)
itv_ext2 = Intervention.objects.create(
code='ITV-EXT-002',
title='Externe B',
status='finished',
thematic=thematic,
assigned_provider=company_external_1
)
# 4. External intervention 3 via contract (unfinished)
contract_ext = Contract.objects.create(
company=company_external_2,
contract_number='C-EXT-99',
start_date=date(2026, 1, 1),
end_date=date(2026, 12, 31)
)
itv_ext3 = Intervention.objects.create(
code='ITV-EXT-003',
title='Externe C',
status='assigned',
thematic=thematic,
contract=contract_ext
)
# Create widget
HomeWidget.objects.create(widget_code='external_interventions')
response = self.client.get(reverse('home:index'), HTTP_ACCEPT_LANGUAGE='fr')
self.assertEqual(response.status_code, 200)
# Verify widget content
self.assertContains(response, 'Interventions externes')
self.assertContains(response, 'ITV-EXT-001')
self.assertContains(response, 'ITV-EXT-002')
self.assertContains(response, 'ITV-EXT-003')
self.assertNotContains(response, 'ITV-INT-001')
# Total external is 3, unfinished is 2
self.assertEqual(response.context['external_interventions_total_count'], 3)
self.assertEqual(response.context['external_interventions_unfinished_count'], 2)
self.assertEqual(len(response.context['external_interventions_list']), 3)
# Verify property on Intervention
self.assertEqual(itv_ext1.provider_or_company_name, 'Société Ext 1')
self.assertEqual(itv_ext3.provider_or_company_name, 'Société Ext 2')
class HomeWidgetAdminTests(TestCase):
def setUp(self):

View file

@ -654,6 +654,58 @@ def index(request):
total_finished_count = interventions.filter(status='finished').count()
total_on_pause_count = interventions.filter(status='on_pause').count()
# ========== Données widget external_interventions ==========
user_company_ids = set()
if user_config.company_id:
user_company_ids.add(user_config.company_id)
if user_teams:
user_company_ids.update(user_teams.values_list('company_id', flat=True))
if user_company_ids:
external_q = (
(Q(assigned_provider__isnull=False) & ~Q(assigned_provider_id__in=user_company_ids)) |
(Q(contract__company__isnull=False) & ~Q(contract__company_id__in=user_company_ids)) |
(Q(assigned_team__company__isnull=False) & ~Q(assigned_team__company_id__in=user_company_ids))
)
else:
external_q = (
Q(assigned_provider__isnull=False) |
Q(contract__company__isnull=False) |
Q(assigned_team__company__isnull=False)
)
external_interventions_qs = interventions.filter(external_q).distinct()
external_interventions_total_count = external_interventions_qs.count()
_UNFINISHED_STATUSES = [
'in_preparation', 'to_be_approved', 'to_be_planned',
'to_be_processed', 'assigned', 'in_progress',
'on_pause', 'to_be_corrected'
]
external_unfinished_qs = external_interventions_qs.filter(status__in=_UNFINISHED_STATUSES)
external_interventions_unfinished_count = external_unfinished_qs.count()
external_status_counts = external_unfinished_qs.aggregate(
count_in_preparation=Count('id', filter=Q(status='in_preparation')),
count_to_be_approved=Count('id', filter=Q(status='to_be_approved')),
count_to_be_planned=Count('id', filter=Q(status='to_be_planned')),
count_to_be_processed=Count('id', filter=Q(status='to_be_processed')),
count_assigned=Count('id', filter=Q(status='assigned')),
count_in_progress=Count('id', filter=Q(status='in_progress')),
count_on_pause=Count('id', filter=Q(status='on_pause')),
count_to_be_corrected=Count('id', filter=Q(status='to_be_corrected')),
)
external_interventions_list = list(
external_interventions_qs
.select_related(
'thematic', 'asset_category', 'contract', 'contract__company',
'assigned_provider', 'assigned_team', 'assigned_team__company'
)
.order_by('-creation_time', '-id')[:10]
)
t = _t('external_interventions', t, _perf_splits)
is_inspector = 'inspector' in user_roles
inspection_configs = []
if is_inspector:
@ -745,6 +797,10 @@ def index(request):
'loan_items_list': loan_items_list,
'pending_purchase_orders_count': pending_purchase_orders_count,
'pending_purchase_orders_list': pending_purchase_orders_list,
'external_interventions_total_count': external_interventions_total_count,
'external_interventions_unfinished_count': external_interventions_unfinished_count,
'external_status_counts': external_status_counts,
'external_interventions_list': external_interventions_list,
}
# ── Logging de performance (désactivé) ────────────────────────────────

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -31,6 +31,7 @@ from .models import (
InspectionConfiguration, InspectionConfigurationContract,
OperationTemplate, OperationTemplateItem, OperationType,
OperationTemplateAssetModelFilter,
ContractOperationTemplatePost,
Operation, OperationPhoto
)
from .services import generate_interventions_excel
@ -712,25 +713,21 @@ class OperationTemplateAdminForm(forms.ModelForm):
ct = ContentType.objects.get_for_model(model)
# Filter instances by categories first (most specific), then by thematic
qs = model.objects.select_related('category')
if category_ids:
instances = model.objects.filter(
category_id__in=category_ids
).order_by('code')
instances = qs.filter(category_id__in=category_ids).order_by('code')
elif thematic_id:
instances = model.objects.filter(
category__thematic_id=thematic_id
).order_by('code')
instances = qs.filter(category__thematic_id=thematic_id).order_by('code')
else:
instances = model.objects.all().order_by('code')
instances = qs.all().order_by('code')
if instances.exists():
for instance in instances:
# Value format: "content_type_id:object_id"
value = f"{ct.id}:{instance.pk}"
# Display with category info
category_name = instance.category.get_name() if instance.category else ''
display = f"{instance} ({category_name})" if category_name else str(instance)
choices.append((value, display))
for instance in instances:
# Value format: "content_type_id:object_id"
value = f"{ct.id}:{instance.pk}"
# Display with category info
category_name = instance.category.get_name() if instance.category else ''
display = f"{instance} ({category_name})" if category_name else str(instance)
choices.append((value, display))
except (TypeError, Exception):
continue
@ -777,13 +774,62 @@ class OperationTemplateAdminForm(forms.ModelForm):
js = ('interventions/admin_operation_template_dynamic.js',)
class ContractOperationTemplatePostInlineForm(forms.ModelForm):
class Meta:
model = ContractOperationTemplatePost
fields = '__all__'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
from contracts.models import ContractPost
contract_id = None
if self.instance and self.instance.pk and self.instance.contract_id:
contract_id = self.instance.contract_id
elif self.data:
prefix = self.prefix
contract_key = f"{prefix}-contract" if prefix else "contract"
contract_id = self.data.get(contract_key)
if contract_id:
self.fields['contract_post'].queryset = ContractPost.objects.filter(
contract_id=contract_id
).order_by('order_number')
else:
self.fields['contract_post'].queryset = ContractPost.objects.none()
class OperationTemplateContractPostInline(admin.TabularInline):
model = ContractOperationTemplatePost
form = ContractOperationTemplatePostInlineForm
extra = 0
fields = ('contract', 'contract_post', 'default_quantity', 'comment')
verbose_name = "Poste de contrat par défaut"
verbose_name_plural = "Postes de contrats par défaut"
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "contract":
template_id = request.resolver_match.kwargs.get('object_id') if request.resolver_match else None
if template_id:
template = OperationTemplate.objects.filter(pk=template_id).first()
if template and template.thematic_id:
kwargs["queryset"] = Contract.objects.filter(
thematics=template.thematic
).distinct().select_related('company').order_by('contract_number')
else:
kwargs["queryset"] = Contract.objects.all().select_related('company').order_by('contract_number')
else:
kwargs["queryset"] = Contract.objects.all().select_related('company').order_by('contract_number')
return super().formfield_for_foreignkey(db_field, request, **kwargs)
@admin.register(OperationTemplate)
class OperationTemplateAdmin(admin.ModelAdmin):
form = OperationTemplateAdminForm
list_display = ('code', 'name', 'description', 'thematic', 'team', 'categories_list', 'models_list')
search_fields = ('name', 'code', 'description')
list_filter = ('thematic', 'team', 'categories')
filter_horizontal = ('categories',)
inlines = [OperationTemplateItemInline]
inlines = [OperationTemplateItemInline, OperationTemplateContractPostInline]
fieldsets = (
(None, {
'fields': ('code', 'name', 'description', 'thematic', 'team', 'guided_template')
@ -798,6 +844,13 @@ class OperationTemplateAdmin(admin.ModelAdmin):
}),
)
def get_queryset(self, request):
return super().get_queryset(request).select_related(
'thematic', 'team', 'team__company'
).prefetch_related(
'categories', 'asset_model_filters'
)
@admin.display(description='Catégories')
def categories_list(self, obj):
cats = obj.categories.all()
@ -813,6 +866,60 @@ class OperationTemplateAdmin(admin.ModelAdmin):
return ', '.join(str(f) for f in filters) + ('...' if obj.asset_model_filters.count() > 3 else '')
class ContractOperationTemplatePostAdminForm(forms.ModelForm):
class Meta:
model = ContractOperationTemplatePost
fields = '__all__'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
from contracts.models import ContractPost
contract_id = None
if self.instance and self.instance.pk and self.instance.contract_id:
contract_id = self.instance.contract_id
elif self.data and 'contract' in self.data:
contract_id = self.data.get('contract')
if contract_id:
self.fields['contract_post'].queryset = ContractPost.objects.filter(
contract_id=contract_id
).order_by('order_number')
else:
self.fields['contract_post'].queryset = ContractPost.objects.none()
@admin.register(ContractOperationTemplatePost)
class ContractOperationTemplatePostAdmin(admin.ModelAdmin):
form = ContractOperationTemplatePostAdminForm
list_display = ('contract', 'operation_template', 'contract_post', 'default_quantity', 'comment')
list_filter = ('contract', 'operation_template', 'contract__thematics')
search_fields = (
'contract__contract_number',
'operation_template__name',
'contract_post__code',
'contract_post__description_fr',
'contract_post__description_nl',
)
autocomplete_fields = ('operation_template',)
class Media:
js = ('interventions/admin_operation_template_dynamic.js',)
def get_queryset(self, request):
return super().get_queryset(request).select_related(
'contract', 'contract__company', 'operation_template', 'contract_post'
)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "contract_post":
obj_id = request.resolver_match.kwargs.get('object_id') if request.resolver_match else None
if obj_id:
obj = ContractOperationTemplatePost.objects.filter(pk=obj_id).first()
if obj and obj.contract_id:
kwargs["queryset"] = ContractPost.objects.filter(contract_id=obj.contract_id).order_by('order_number')
return super().formfield_for_foreignkey(db_field, request, **kwargs)
@admin.register(OperationTemplateItem)
class OperationTemplateItemAdmin(admin.ModelAdmin):
list_display = ('code', 'get_name', 'template', 'status_set', 'measurement_definition', 'is_generic', 'order')

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,18 @@
# Generated by Django 6.0.7 on 2026-08-19 08:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('interventions', '0003_operationtemplate_team'),
]
operations = [
migrations.AlterField(
model_name='intervention',
name='type',
field=models.CharField(blank=True, choices=[('fixing', 'Dépannage'), ('repair', 'Réparation'), ('repair_post_preventive', 'Réparation post préventif'), ('replace', 'Remplacement'), ('care', 'Entretien'), ('control', 'Contrôle'), ('inspection', 'Inspection'), ('build', 'Construction'), ('collection', 'Ramassage'), ('reprogramming', 'Reprogrammation')], null=True),
),
]

View file

@ -0,0 +1,32 @@
# Generated by Django 6.0.7 on 2026-08-19 13:11
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contracts', '0003_contract_allow_team_members_edit'),
('interventions', '0004_alter_intervention_type'),
]
operations = [
migrations.CreateModel(
name='ContractOperationTemplatePost',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('default_quantity', models.DecimalField(decimal_places=2, default=1, max_digits=10, verbose_name='Quantité par défaut')),
('comment', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Commentaire par défaut')),
('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='operation_template_posts', to='contracts.contract', verbose_name='Contrat')),
('contract_post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='operation_template_posts', to='contracts.contractpost', verbose_name='Poste de contrat')),
('operation_template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contract_posts', to='interventions.operationtemplate', verbose_name="Template d'opérations")),
],
options={
'verbose_name': "Poste par défaut (Contrat × Template d'opérations)",
'verbose_name_plural': "Postes par défaut (Contrats × Templates d'opérations)",
'ordering': ['contract', 'operation_template', 'contract_post__order_number'],
'unique_together': {('contract', 'operation_template', 'contract_post')},
},
),
]

View file

@ -2,6 +2,7 @@ from django.contrib.gis.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.conf import settings
from django.core.exceptions import ValidationError
from django.utils.translation import get_language, gettext_lazy as _
from django.utils import timezone
from django.db.models import Sum, F, Q
@ -102,8 +103,26 @@ TYPE_CHOICES = [
('inspection', _('Inspection')),
('build', _('Construction')),
('collection', _('Ramassage')),
('reprogramming', _('Reprogrammation')),
]
def get_type_choices(thematic=None):
"""
Renvoie la liste des choix de type d'intervention selon la thématique.
Le type 'reprogramming' (Reprogrammation) n'est disponible que pour la thématique 'trafficlights'.
"""
thematic_code = None
if thematic:
if isinstance(thematic, str):
thematic_code = thematic
elif hasattr(thematic, 'code'):
thematic_code = thematic.code
if thematic_code == 'trafficlights':
return list(TYPE_CHOICES)
return [c for c in TYPE_CHOICES if c[0] != 'reprogramming']
ORIGIN_TYPE_CHOICES = [
('damage', _('Avarie')),
('defect', _('Défaut/Panne')),
@ -688,6 +707,17 @@ class Intervention(models.Model):
def status_text_color_hex(self):
return '#000000' if self.status in STATUS_COLORS_DARK_TEXT else '#ffffff'
@property
def provider_or_company_name(self):
"""Retourne le nom de l'organisme / prestataire associé à cette intervention."""
if self.assigned_provider:
return self.assigned_provider.name
if self.contract and self.contract.company:
return self.contract.company.name
if self.assigned_team and self.assigned_team.company:
return self.assigned_team.company.name
return ""
def get_status_color(self):
return {
"in_preparation": "secondary",
@ -742,6 +772,61 @@ class Intervention(models.Model):
status__in=['to_process', 'pending']
).exists()
def get_associated_observations(self):
"""
Retourne le QuerySet de toutes les observations associées à cette intervention :
- Celles dont le champ intervention pointe directement vers cette intervention
- Celles correspondant au source_ref de cette intervention
- Celles associées aux interventions liées via InterventionLink (origine, duplication, réparation)
"""
if not self.pk:
from observations.models import Observation
return Observation.objects.none()
from observations.models import Observation
possible_obs_ids = set()
for obs_id in self.observations.values_list('id', flat=True):
possible_obs_ids.add(obs_id)
if self.source_category and self.source_ref:
sc_names = [getattr(self.source_category, a, '') or '' for a in ('name_fr', 'name_nl')]
if any(n.strip().lower() == 'observation' for n in sc_names):
try:
possible_obs_ids.add(int(self.source_ref))
except (ValueError, TypeError):
pass
if self.source_ref.startswith('OBS') and self.source_ref[3:].isdigit():
try:
possible_obs_ids.add(int(self.source_ref[3:]))
except (ValueError, TypeError):
pass
# Interventions liées (duplication, réparation, lien manuel)
linked_itv_ids = set()
for f, s in InterventionLink.objects.filter(
Q(first=self) | Q(second=self)
).values_list('first_id', 'second_id'):
linked_itv_ids.add(f if f != self.id else s)
if linked_itv_ids:
for obs_id in Observation.objects.filter(intervention_id__in=linked_itv_ids).values_list('id', flat=True):
possible_obs_ids.add(obs_id)
for itv_other in Intervention.objects.filter(id__in=linked_itv_ids, source_category__isnull=False).exclude(source_ref__isnull=True).exclude(source_ref=''):
sc_names = [getattr(itv_other.source_category, a, '') or '' for a in ('name_fr', 'name_nl')]
if any(n.strip().lower() == 'observation' for n in sc_names):
try:
possible_obs_ids.add(int(itv_other.source_ref))
except (ValueError, TypeError):
pass
if itv_other.source_ref.startswith('OBS') and itv_other.source_ref[3:].isdigit():
try:
possible_obs_ids.add(int(itv_other.source_ref[3:]))
except (ValueError, TypeError):
pass
return Observation.objects.filter(id__in=possible_obs_ids).order_by('-created_at')
class InterventionLink(models.Model):
class LinkType(models.TextChoices):
@ -1594,6 +1679,65 @@ class OperationTemplateItem(models.Model):
return f"{self.template.name} - {self.name_fr}"
class ContractOperationTemplatePost(models.Model):
"""
Associe un poste de contrat à un template d'opérations avec une quantité par défaut.
Utilisé lors de la création d'interventions préventives pour pré-remplir les postes de contrat.
"""
contract = models.ForeignKey(
Contract,
on_delete=models.CASCADE,
related_name='operation_template_posts',
verbose_name=_("Contrat"),
)
operation_template = models.ForeignKey(
OperationTemplate,
on_delete=models.CASCADE,
related_name='contract_posts',
verbose_name=_("Template d'opérations"),
)
contract_post = models.ForeignKey(
ContractPost,
on_delete=models.CASCADE,
related_name='operation_template_posts',
verbose_name=_("Poste de contrat"),
)
default_quantity = models.DecimalField(
max_digits=10,
decimal_places=2,
default=1,
verbose_name=_("Quantité par défaut"),
)
comment = models.CharField(
max_length=1024,
blank=True,
null=True,
verbose_name=_("Commentaire par défaut"),
)
class Meta:
unique_together = [('contract', 'operation_template', 'contract_post')]
ordering = ['contract', 'operation_template', 'contract_post__order_number']
verbose_name = _("Poste par défaut (Contrat × Template d'opérations)")
verbose_name_plural = _("Postes par défaut (Contrats × Templates d'opérations)")
def __str__(self):
return f"{self.contract.contract_number} × {self.operation_template.name} → {self.contract_post.code} ({self.default_quantity})"
def clean(self):
super().clean()
if self.contract_post_id and self.contract_id:
if self.contract_post.contract_id != self.contract_id:
raise ValidationError({
'contract_post': _("Ce poste n'appartient pas au contrat sélectionné.")
})
def save(self, *args, **kwargs):
if self.contract_post_id and not self.contract_id:
self.contract = self.contract_post.contract
super().save(*args, **kwargs)
EMAIL_LOG_TYPE_CHOICES = {
'transmission': _('Envoi de la fiche'),
'reminder': _('Rappel'),

View file

@ -259,8 +259,14 @@ def can_view_intervention(user, intervention):
is_assigned_to_user = (intervention.assigned_member == company_member)
is_assigned_to_user_team = (intervention.assigned_team in company_member.teams.all())
is_unrestricted_company = (intervention.assigned_provider_id in unrestricted_companies)
is_team_member_edit_allowed = bool(
intervention.contract
and getattr(intervention.contract, 'allow_team_members_edit', False)
and intervention.assigned_member
and intervention.assigned_member.teams.filter(id__in=company_member.teams.all()).exists()
)
if not (is_assigned_to_user or is_assigned_to_user_team or is_unrestricted_company):
if not (is_assigned_to_user or is_assigned_to_user_team or is_unrestricted_company or is_team_member_edit_allowed):
return False
contract = intervention.contract
@ -680,7 +686,11 @@ def filter_viewable_interventions_for_user(user, limit_to_default_thematic=False
unrestricted_teams = company_member.teams.filter(restrict_to_assigned_interventions=False)
unrestricted_companies = list(unrestricted_teams.values_list('company_id', flat=True).distinct())
company_q = Q(assigned_member=company_member) | Q(assigned_team__in=list(company_member.teams.all()))
company_q = (
Q(assigned_member=company_member) |
Q(assigned_team__in=list(company_member.teams.all())) |
Q(contract__allow_team_members_edit=True, assigned_member__teams__in=list(company_member.teams.all()))
)
if unrestricted_companies:
company_q |= Q(assigned_member__isnull=True, assigned_team__isnull=True, assigned_provider_id__in=unrestricted_companies)
else:
@ -721,7 +731,11 @@ def filter_viewable_interventions_for_user(user, limit_to_default_thematic=False
unrestricted_teams = company_member.teams.filter(restrict_to_assigned_interventions=False)
unrestricted_companies = list(unrestricted_teams.values_list('company_id', flat=True).distinct())
assign_filter = Q(assigned_member=company_member) | Q(assigned_team__in=list(company_member.teams.all()))
assign_filter = (
Q(assigned_member=company_member) |
Q(assigned_team__in=list(company_member.teams.all())) |
Q(contract__allow_team_members_edit=True, assigned_member__teams__in=list(company_member.teams.all()))
)
if unrestricted_companies:
assign_filter |= Q(assigned_provider_id__in=unrestricted_companies)
qs = qs.filter(assign_filter)
@ -949,7 +963,23 @@ def can_edit_intervention(user, intervention, user_config=None):
assigned_member = getattr(intervention, 'assigned_member', None)
assigned_user_id = getattr(assigned_member, 'user_id', None) if assigned_member else None
if assigned_user_id is not None and assigned_user_id != user.id:
return False
# Vérifier si le contrat autorise la modification par les membres de la même équipe
contract = intervention.contract
allow_team_edit = bool(contract and getattr(contract, 'allow_team_members_edit', False))
is_same_team_member = False
if allow_team_edit:
company_member = CompanyMember.objects.filter(user=user).prefetch_related('teams').first()
if company_member:
user_team_ids = set(company_member.teams.values_list('id', flat=True))
if intervention.assigned_team_id and intervention.assigned_team_id in user_team_ids:
is_same_team_member = True
elif assigned_member:
assigned_member_team_ids = set(assigned_member.teams.values_list('id', flat=True))
if user_team_ids & assigned_member_team_ids:
is_same_team_member = True
if not is_same_team_member:
return False
contract = intervention.contract
thematic = intervention.thematic
@ -989,11 +1019,36 @@ def can_edit_intervention(user, intervention, user_config=None):
thematic=thematic,
).first()
if ut:
return UserThematicStatusPermission.objects.filter(
if UserThematicStatusPermission.objects.filter(
user_thematic=ut,
status=status,
can_edit=True,
).exists()
).exists():
return True
# Si pas de contrat et pas de permission de statut thématique explicite :
if contract is None:
# 1. Le créateur de l'intervention peut toujours la modifier s'il n'y a pas de contrat
if intervention.created_by_id == user.id:
return True
# 2. Utilisateur ayant des droits d'édition sur au moins un contrat de la thématique
if UserContractStatusPermission.objects.filter(
user_contract__user_config=user_config,
user_contract__contract__thematics=thematic,
status=status,
can_edit=True,
).exists():
return True
# 3. Utilisateur ayant des droits d'édition sur au moins un contrat du prestataire assigné
if intervention.assigned_provider_id and UserContractStatusPermission.objects.filter(
user_contract__user_config=user_config,
user_contract__contract__company_id=intervention.assigned_provider_id,
status=status,
can_edit=True,
).exists():
return True
# 4. Si l'utilisateur a can_edit_interventions sur la thématique pour les statuts initiaux
if ut.can_edit_interventions and status in ('in_preparation', 'to_be_approved', 'to_be_planned'):
return True
return False
@ -1050,6 +1105,15 @@ def can_manage_occupations(user, intervention, user_config=None):
and intervention.assigned_team_id in member_team_ids):
return True
# Si le contrat autorise la modification par les membres d'équipe, autoriser si partage d'équipe
contract = intervention.contract
if contract and getattr(contract, 'allow_team_members_edit', False):
assigned_member = getattr(intervention, 'assigned_member', None)
if assigned_member:
assigned_member_team_ids = set(assigned_member.teams.values_list('id', flat=True))
if set(member_team_ids) & assigned_member_team_ids:
return True
# Autoriser tous les techniciens qui ont démarré cette intervention, même si elle est ensuite réassignée à une autre équipe ou un autre membre
if InterventionTimeLine.objects.filter(
intervention=intervention,
@ -1548,3 +1612,23 @@ def can_user_create_inspection_for_contract(user, contract):
status__in=target_statuses,
can_change_status_to=True,
).exists()
def can_duplicate_intervention(user, intervention):
"""
Vérifie si l'utilisateur peut dupliquer l'intervention donnée.
L'utilisateur doit pouvoir voir l'intervention source et pouvoir créer une nouvelle intervention
pour la thématique concernée.
"""
try:
user_config = UserConfig.objects.get(user=user)
except UserConfig.DoesNotExist:
return False
if user_config.roles.filter(name__in=['admin', 'top_manager']).exists():
return True
if not can_view_intervention(user, intervention):
return False
return can_add_intervention(user, intervention.thematic)

View file

@ -1,7 +1,10 @@
/**
* Dynamic filtering for OperationTemplate admin form
* Updates categories based on thematic selection
* Updates asset models based on categories selection
* Dynamic filtering for OperationTemplate and ContractOperationTemplatePost admin forms:
* - Updates categories based on thematic selection
* - Updates asset models based on categories selection
* - Updates teams based on thematic selection
* - Updates inline contracts based on thematic selection
* - Updates contract posts dynamically based on selected contract (inlines and standalone form)
*/
(function() {
'use strict';
@ -16,172 +19,295 @@
var $ = django.jQuery;
$(document).ready(function() {
var $thematic = $('#id_thematic');
var $team = $('#id_team');
var $categoriesFrom = $('#id_categories_from');
var $categoriesTo = $('#id_categories_to');
var $assetModelsFrom = $('#id_asset_models_from');
var $assetModelsTo = $('#id_asset_models_to');
var $thematic = $('#id_thematic');
var $team = $('#id_team');
var $categoriesFrom = $('#id_categories_from');
var $categoriesTo = $('#id_categories_to');
var $assetModelsFrom = $('#id_asset_models_from');
var $assetModelsTo = $('#id_asset_models_to');
if (!$thematic.length) return;
/**
* Update teams based on selected thematic
*/
function updateTeams() {
if (!$team.length || !$thematic.length) return;
var thematicId = $thematic.val();
var currentTeamVal = $team.val();
/**
* Update teams based on selected thematic
*/
function updateTeams() {
if (!$team.length) return;
var thematicId = $thematic.val();
var currentTeamVal = $team.val();
$.ajax({
url: '/interventions/ajax/get-teams-by-thematic/',
data: { thematic_id: thematicId || '' },
success: function(data) {
$team.empty();
$team.append($('<option></option>').val('').text('---------'));
var hasCurrentVal = false;
data.teams.forEach(function(team) {
var option = $('<option></option>')
.val(team.id)
.text(team.name);
if (String(team.id) === String(currentTeamVal)) {
option.prop('selected', true);
hasCurrentVal = true;
$.ajax({
url: '/interventions/ajax/get-teams-by-thematic/',
data: { thematic_id: thematicId || '' },
success: function(data) {
$team.empty();
$team.append($('<option></option>').val('').text('---------'));
var hasCurrentVal = false;
data.teams.forEach(function(team) {
var option = $('<option></option>')
.val(team.id)
.text(team.name);
if (String(team.id) === String(currentTeamVal)) {
option.prop('selected', true);
hasCurrentVal = true;
}
$team.append(option);
});
if (!hasCurrentVal && currentTeamVal) {
$team.val('');
}
$team.append(option);
});
if (!hasCurrentVal && currentTeamVal) {
$team.val('');
},
error: function() {
console.error('Error fetching teams');
}
},
error: function() {
console.error('Error fetching teams');
}
});
}
/**
* Update categories based on selected thematic
*/
function updateCategories() {
var thematicId = $thematic.val();
if (!thematicId) {
// Clear categories if no thematic selected
$categoriesFrom.empty();
$categoriesTo.empty();
updateAssetModels();
return;
});
}
// Get current selections
var selectedCategories = $categoriesTo.find('option').map(function() {
return $(this).val();
}).get();
/**
* Update categories based on selected thematic
*/
function updateCategories() {
if (!$thematic.length || !$categoriesFrom.length) return;
var thematicId = $thematic.val();
// Fetch filtered categories
$.ajax({
url: '/interventions/ajax/get-categories-by-thematic/',
data: { thematic_id: thematicId },
success: function(data) {
// Clear both lists
if (!thematicId) {
// Clear categories if no thematic selected
$categoriesFrom.empty();
$categoriesTo.empty();
// Populate categories
data.categories.forEach(function(cat) {
var option = $('<option></option>')
.val(cat.id)
.text(cat.name);
// If previously selected, add to "chosen" list
if (selectedCategories.indexOf(String(cat.id)) !== -1) {
$categoriesTo.append(option);
} else {
$categoriesFrom.append(option);
}
});
// Update asset models after categories change
updateAssetModels();
},
error: function() {
console.error('Error fetching categories');
return;
}
});
}
/**
* Update asset models based on selected categories (or thematic if no categories)
*/
function updateAssetModels() {
var thematicId = $thematic.val();
var categoryIds = $categoriesTo.find('option').map(function() {
return $(this).val();
}).get();
// Get current selections
var selectedCategories = $categoriesTo.find('option').map(function() {
return $(this).val();
}).get();
if (!thematicId) {
// Clear asset models if no thematic selected
$assetModelsFrom.empty();
$assetModelsTo.empty();
return;
// Fetch filtered categories
$.ajax({
url: '/interventions/ajax/get-categories-by-thematic/',
data: { thematic_id: thematicId },
success: function(data) {
// Clear both lists
$categoriesFrom.empty();
$categoriesTo.empty();
// Populate categories
data.categories.forEach(function(cat) {
var option = $('<option></option>')
.val(cat.id)
.text(cat.name);
// If previously selected, add to "chosen" list
if (selectedCategories.indexOf(String(cat.id)) !== -1) {
$categoriesTo.append(option);
} else {
$categoriesFrom.append(option);
}
});
// Update asset models after categories change
updateAssetModels();
},
error: function() {
console.error('Error fetching categories');
}
});
}
// Get current selections
var selectedModels = $assetModelsTo.find('option').map(function() {
return $(this).val();
}).get();
/**
* Update asset models based on selected categories (or thematic if no categories)
*/
function updateAssetModels() {
if (!$thematic.length || !$assetModelsFrom.length) return;
var thematicId = $thematic.val();
var categoryIds = $categoriesTo.find('option').map(function() {
return $(this).val();
}).get();
// Fetch filtered asset models
$.ajax({
url: '/interventions/ajax/get-asset-models/',
data: {
thematic_id: thematicId,
category_ids: categoryIds.join(',')
},
success: function(data) {
// Clear both lists
if (!thematicId) {
// Clear asset models if no thematic selected
$assetModelsFrom.empty();
$assetModelsTo.empty();
// Populate asset models
data.models.forEach(function(model) {
var option = $('<option></option>')
.val(model.value)
.text(model.display);
// If previously selected, add to "chosen" list
if (selectedModels.indexOf(model.value) !== -1) {
$assetModelsTo.append(option);
} else {
$assetModelsFrom.append(option);
}
});
},
error: function() {
console.error('Error fetching asset models');
return;
}
});
}
// Listen to thematic changes
$thematic.on('change', function() {
updateCategories();
updateTeams();
});
// Get current selections
var selectedModels = $assetModelsTo.find('option').map(function() {
return $(this).val();
}).get();
// Listen to categories changes using MutationObserver
// (filter_horizontal uses JavaScript to move options, not change events)
if ($categoriesTo.length) {
var observer = new MutationObserver(function(mutations) {
updateAssetModels();
// Fetch filtered asset models
$.ajax({
url: '/interventions/ajax/get-asset-models/',
data: {
thematic_id: thematicId,
category_ids: categoryIds.join(',')
},
success: function(data) {
// Clear both lists
$assetModelsFrom.empty();
$assetModelsTo.empty();
// Populate asset models
data.models.forEach(function(model) {
var option = $('<option></option>')
.val(model.value)
.text(model.display);
// If previously selected, add to "chosen" list
if (selectedModels.indexOf(model.value) !== -1) {
$assetModelsTo.append(option);
} else {
$assetModelsFrom.append(option);
}
});
},
error: function() {
console.error('Error fetching asset models');
}
});
}
/**
* Update contract options in inlines based on selected thematic
*/
function updateContractsInlines() {
if (!$thematic.length) return;
var thematicId = $thematic.val();
$.ajax({
url: '/interventions/ajax/get-contracts-by-thematic/',
data: { thematic_id: thematicId || '' },
success: function(data) {
$('select[name$="-contract"]').each(function() {
var $cSelect = $(this);
var currentVal = $cSelect.val();
$cSelect.empty();
$cSelect.append($('<option></option>').val('').text('---------'));
var hasCurrent = false;
data.contracts.forEach(function(c) {
var opt = $('<option></option>').val(c.id).text(c.label);
if (String(c.id) === String(currentVal)) {
opt.prop('selected', true);
hasCurrent = true;
}
$cSelect.append(opt);
});
if (!hasCurrent && currentVal) {
$cSelect.val('');
$cSelect.trigger('change.dynamicPosts');
}
});
}
});
}
/**
* Update posts dropdown based on selected contract
*/
function updatePostsForContract($contractSelect, $postSelect, keepSelectedVal) {
var contractId = $contractSelect.val();
var currentPostVal = keepSelectedVal !== undefined ? keepSelectedVal : $postSelect.val();
if (!contractId) {
$postSelect.empty();
$postSelect.append($('<option></option>').val('').text('---------'));
$postSelect.val('');
return;
}
$.ajax({
url: '/interventions/ajax/get-posts-by-contract/',
data: { contract_id: contractId },
success: function(data) {
$postSelect.empty();
$postSelect.append($('<option></option>').val('').text('---------'));
var matched = false;
if (data.posts && data.posts.length > 0) {
data.posts.forEach(function(post) {
var option = $('<option></option>')
.val(post.id)
.text(post.label);
if (String(post.id) === String(currentPostVal)) {
option.prop('selected', true);
matched = true;
}
$postSelect.append(option);
});
}
if (matched) {
$postSelect.val(currentPostVal);
} else if (currentPostVal) {
$postSelect.val('');
}
},
error: function() {
console.error('Error fetching contract posts');
}
});
}
function bindContractPostRow($row) {
var $contract = $row.find('select[name$="-contract"]');
var $post = $row.find('select[name$="-contract_post"]');
if (!$contract.length || !$post.length) return;
$contract.off('change.dynamicPosts').on('change.dynamicPosts', function() {
updatePostsForContract($contract, $post);
});
// Initial load for existing row: if contract is selected, populate options
if ($contract.val()) {
var initialPostVal = $post.val();
updatePostsForContract($contract, $post, initialPostVal);
} else {
$post.empty().append($('<option></option>').val('').text('---------'));
}
}
// Bind all inline rows
$('tr.form-row, tr[id^="contract_posts-"], .dynamic-contract_posts, tbody tr').each(function() {
bindContractPostRow($(this));
});
observer.observe($categoriesTo[0], {
childList: true,
subtree: true
// Listen for new inline rows added dynamically in Django Admin
$(document).on('formset:added', function(event, $row, formsetName) {
bindContractPostRow($row);
});
}
// Standalone form (ContractOperationTemplatePostAdmin)
var $standaloneContract = $('#id_contract');
var $standalonePost = $('#id_contract_post');
if ($standaloneContract.length && $standalonePost.length) {
$standaloneContract.on('change', function() {
updatePostsForContract($standaloneContract, $standalonePost);
});
if ($standaloneContract.val()) {
var initialPostVal = $standalonePost.val();
updatePostsForContract($standaloneContract, $standalonePost, initialPostVal);
} else {
$standalonePost.empty().append($('<option></option>').val('').text('---------'));
}
}
// Listen to thematic changes
if ($thematic.length) {
$thematic.on('change', function() {
updateCategories();
updateTeams();
updateContractsInlines();
});
// Listen to categories changes using MutationObserver
if ($categoriesTo.length) {
var observer = new MutationObserver(function(mutations) {
updateAssetModels();
});
observer.observe($categoriesTo[0], {
childList: true,
subtree: true
});
}
}
});
}

View file

@ -1382,14 +1382,66 @@
}
// ==================== Affichage de tous les postes ====================
async function showAllContractPosts() {
function updateShowAllButtonUI() {
const showAllBtn = document.querySelector(CONFIG.selectors.showAllBtn);
if (!showAllBtn) return;
if (appState.isShowingAllPosts) {
// Revenir aux postes de l'intervention
appState.currentData = appState.originalData.map(item => ({...item}));
appState.isShowingAllPosts = false;
document.querySelector(CONFIG.selectors.showAllBtn).innerHTML = `
showAllBtn.innerHTML = `
<i class="bi bi-list-check"></i> ${gettext('Afficher uniquement les postes de l\'intervention')}
`;
} else {
showAllBtn.innerHTML = `
<i class="bi bi-list-ul"></i> ${gettext('Afficher tous les postes du contrat')}
`;
}
}
function populateWithAllContractPosts() {
const currentPostIds = new Set((appState.currentData || []).map(item => String(item.contract_post_id)));
const allPosts = [...(appState.currentData || [])];
(appState.contractPosts || []).forEach(post => {
if (!currentPostIds.has(String(post.id))) {
allPosts.push({
contract_post_id: post.id,
order_number: post.order_number,
code: post.code,
description: post.description_fr || post.description_nl,
quantity: '',
comment: '',
unit: post.unit || '',
unit_price: post.unit_price,
total: '',
control_status: '',
control_comment: '',
remaining_quantity: '',
post_type: post.post_type || '',
is_coefficient_multipliable: post.is_coefficient_multipliable || false,
is_amount_to_be_justified: post.is_amount_to_be_justified || false,
coeff_amount_to_be_justified: post.coeff_amount_to_be_justified || 1,
deleted: false,
});
}
});
appState.currentData = allPosts;
appState.isShowingAllPosts = true;
updateShowAllButtonUI();
}
async function showAllContractPosts() {
if (appState.isShowingAllPosts) {
// Revenir aux postes de l'intervention (postes originaux + postes ayant une quantité > 0 ou un commentaire)
const originalPostIds = new Set((appState.originalData || []).map(item => String(item.contract_post_id)));
appState.currentData = (appState.currentData || []).filter(item => {
const isOriginal = originalPostIds.has(String(item.contract_post_id));
const qty = parseFloat(String(item.quantity || '').replace(',', '.'));
const hasQty = !Number.isNaN(qty) && qty !== 0;
const hasComment = Boolean(item.comment && item.comment.trim());
return isOriginal || hasQty || hasComment;
});
appState.isShowingAllPosts = false;
updateShowAllButtonUI();
} else {
// Vérifier qu'un contrat est disponible
const currentContractId = window.contractId || contractId;
@ -1399,48 +1451,17 @@
}
// Charger tous les postes
if (appState.contractPosts.length === 0) {
if (!appState.contractPosts || appState.contractPosts.length === 0) {
appState.contractPosts = await loadContractPosts();
}
// Vérifier que des postes ont été chargés
if (appState.contractPosts.length === 0) {
if (!appState.contractPosts || appState.contractPosts.length === 0) {
showAlert(gettext('Aucun poste trouvé dans le contrat.'), 'info');
return;
}
// Merger avec les données actuelles
const currentPostIds = new Set(appState.originalData.map(item => item.contract_post_id));
const allPosts = [...appState.originalData];
appState.contractPosts.forEach(post => {
if (!currentPostIds.has(post.id.toString())) {
allPosts.push({
contract_post_id: post.id,
order_number: post.order_number,
code: post.code,
description: post.description_fr || post.description_nl,
quantity: '',
comment: '',
unit_price: post.unit_price,
total: '',
control_status: '',
control_comment: '',
remaining_quantity: '',
post_type: post.post_type || '',
is_coefficient_multipliable: post.is_coefficient_multipliable || false,
is_amount_to_be_justified: post.is_amount_to_be_justified || false,
coeff_amount_to_be_justified: post.coeff_amount_to_be_justified || 1,
deleted: false,
});
}
});
appState.currentData = allPosts;
appState.isShowingAllPosts = true;
document.querySelector(CONFIG.selectors.showAllBtn).innerHTML = `
<i class="bi bi-list-check"></i> ${gettext('Afficher uniquement les postes de l\'intervention')}
`;
populateWithAllContractPosts();
}
renderTable();
@ -1482,12 +1503,7 @@
if (appState.isShowingAllPosts) {
appState.isShowingAllPosts = false;
const showAllBtn = document.querySelector(CONFIG.selectors.showAllBtn);
if (showAllBtn) {
showAllBtn.innerHTML = `
<i class="bi bi-list-ul"></i> ${gettext('Afficher tous les postes du contrat')}
`;
}
updateShowAllButtonUI();
}
};
@ -2638,6 +2654,8 @@
if (!orderSelect) return;
const initialVal = orderSelect.getAttribute('data-initial-order-id') || $(orderSelect).val() || orderSelect.value || '';
// Initialiser Select2 avec recherche
$(orderSelect).select2({
placeholder: gettext('-- Sélectionnez une commande --'),
@ -2654,6 +2672,10 @@
dropdownParent: $(CONFIG.selectors.modal)
});
if (initialVal) {
$(orderSelect).val(initialVal).trigger('change.select2');
}
// Gérer le changement de commande
$(orderSelect).on('change', async function() {
const orderId = $(this).val();
@ -2679,11 +2701,38 @@
appState.quoteItems = Array.isArray(data.quote_items) ? data.quote_items : [];
// Mettre à jour le contractId global si fourni par le serveur
const previousContractId = window.contractId;
if (data.contract_id) {
window.contractId = data.contract_id;
window.contractPostsCount = data.contract_posts_count !== undefined ? data.contract_posts_count : 0;
if (previousContractId !== data.contract_id) {
appState.contractPosts = [];
}
} else if (!orderId) {
// Si on désélectionne la commande, réinitialiser contractId
window.contractId = null;
window.contractPostsCount = 0;
appState.contractPosts = [];
}
if (appState.originalData.length === 0) {
if (window.contractId && window.contractPostsCount > 0 && window.contractPostsCount < 1000) {
if (!appState.contractPosts || appState.contractPosts.length === 0) {
appState.contractPosts = await loadContractPosts();
}
if (appState.contractPosts && appState.contractPosts.length > 0) {
appState.currentData = [];
populateWithAllContractPosts();
} else {
appState.currentData = [];
appState.isShowingAllPosts = false;
updateShowAllButtonUI();
}
} else {
appState.currentData = [];
appState.isShowingAllPosts = false;
updateShowAllButtonUI();
}
}
// Mettre à jour l'affichage dans la vue consultation
@ -2831,6 +2880,11 @@
appState.modal = new bootstrap.Modal(modalEl, { backdrop: 'static', keyboard: false });
// Initialiser contractPostsCount depuis le contexte serveur
if (typeof contractPostsCount !== 'undefined') {
window.contractPostsCount = contractPostsCount;
}
// Initialiser hasCoefficientPosts depuis le contexte serveur
if (typeof hasCoefficientPostsInitial !== 'undefined') {
appState.hasCoefficientPosts = hasCoefficientPostsInitial;
@ -2848,10 +2902,27 @@
appState.originalData = extractDataFromSourceTable();
appState.currentData = appState.originalData.map(item => ({...item}));
normalizeStatusForPeriodValidation();
appState.isShowingAllPosts = false;
appState.hasUnsavedChanges = false;
appState.statusChanges = {};
const currentContractId = window.contractId || contractId;
const currentPostsCount = window.contractPostsCount !== undefined ? window.contractPostsCount : (typeof contractPostsCount !== 'undefined' ? contractPostsCount : 0);
if (appState.originalData.length === 0 && currentContractId && currentPostsCount > 0 && currentPostsCount < 1000) {
if (!appState.contractPosts || appState.contractPosts.length === 0) {
appState.contractPosts = await loadContractPosts();
}
if (appState.contractPosts && appState.contractPosts.length > 0) {
populateWithAllContractPosts();
} else {
appState.isShowingAllPosts = false;
updateShowAllButtonUI();
}
} else {
appState.isShowingAllPosts = false;
updateShowAllButtonUI();
}
await fetchPeriodQuantities();
if (autoShowPeriods) {
appState.showPeriods = true;
@ -2868,6 +2939,7 @@
fixTableColumnWidths(CONFIG.selectors.table);
const orderSelect = document.getElementById('orderSelect');
if (orderSelect && $.fn.select2) {
const currentVal = $(orderSelect).val() || orderSelect.getAttribute('data-initial-order-id') || orderSelect.value || '';
$(orderSelect).select2('destroy');
$(orderSelect).select2({
placeholder: gettext('-- Sélectionnez une commande --'),
@ -2885,7 +2957,11 @@
});
// S'assurer que la valeur sélectionnée est correcte
$(orderSelect).trigger('change.select2');
if (currentVal) {
$(orderSelect).val(currentVal).trigger('change.select2');
} else {
$(orderSelect).trigger('change.select2');
}
}
// Initialiser la visibilité du bouton d'ajout du devis

View file

@ -144,19 +144,20 @@
}
}
async function updateField(interventionId, field, value) {
async function updateFieldsBatch(interventionId, payload) {
const response = await fetch(`/interventions/${interventionId}/update/`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Type': 'application/json',
'X-CSRFToken': getCookie('csrftoken')
},
body: new URLSearchParams({ field, value })
body: JSON.stringify(payload)
});
const data = await response.json();
if (!response.ok || !data.success) {
throw new Error(data.error || gettext('Une erreur est survenue.'));
const errMsg = data.error || (data.errors && data.errors.join(', ')) || gettext('Une erreur est survenue.');
throw new Error(errMsg);
}
return data;
}
@ -227,11 +228,16 @@
if (spinnerEl) spinnerEl.classList.remove('d-none');
try {
const payload = {};
if (providerChanged) {
await updateField(interventionId, 'assigned_provider', providerValue);
payload.assigned_provider = providerValue;
}
if (contractChanged) {
await updateField(interventionId, 'contract', contractValue);
payload.contract = contractValue;
}
if (Object.keys(payload).length > 0) {
await updateFieldsBatch(interventionId, payload);
}
if (providerDisplay && providerSelect) {

View file

@ -1,11 +1,20 @@
{% load i18n interventions_tags %}
{% if linked_groups or can_manage_links %}
{% if linked_groups or can_manage_links or can_duplicate_intervention %}
<div id="section-liens" class="card mt-3 mb-4">
<div class="card-header bg-light d-flex align-items-center justify-content-between">
<h4>
<h4 class="mb-0">
<i class="bi bi-link-45deg"></i>
{% translate "Interventions liées" %}
</h4>
{% if can_duplicate_intervention %}
<form method="post" action="{% url 'interventions:duplicate_intervention' intervention.id %}" class="d-inline" onsubmit="return confirm('{% translate "Êtes-vous sûr de vouloir dupliquer cette intervention ?" %}');">
{% csrf_token %}
<button type="submit" class="btn btn-outline-primary btn-sm">
<i class="bi bi-copy"></i>
{% translate "Dupliquer" %}
</button>
</form>
{% endif %}
</div>
<div class="card-body">
{% if linked_groups %}

View file

@ -355,14 +355,15 @@
</label>
</div>
<div class="col-md-9">
<select class="form-select" id="orderSelect" style="width: 100%;">
<select class="form-select" id="orderSelect" style="width: 100%;" data-initial-order-id="{% if intervention.order_id %}{{ intervention.order_id }}{% endif %}">
<option value="">-- {% translate "Sélectionnez une commande" %} --</option>
{% for order in orders %}
<option value="{{ order.id }}"
data-contract="{{ order.contract.contract_number }}"
data-order-code="{{ order.order_code }}"
data-has-quote="{% if order.quote %}true{% else %}false{% endif %}"
{% if intervention.order and order.id == intervention.order.id %}selected{% endif %}>
data-contract-posts-count="{{ order.contract.posts.count }}"
{% if intervention.order_id and order.id == intervention.order_id %}selected{% endif %}>
{{ order.contract.contract_number }} - {{ order.order_code }}
</option>
{% endfor %}

View file

@ -48,6 +48,7 @@
const photosRequiredSince = "{{ photos_required_since }}";
const contractWarnNoPrestationOnProcessed = {{ contract_warn_no_prestation_on_processed|yesno:"true,false" }};
const hasPrestationsEncoded = {{ has_prestations_encoded|yesno:"true,false" }};
var contractPostsCount = {{ contract_posts_count|default:0 }};
</script>
<script>

View file

@ -1762,12 +1762,23 @@
</div>
{% endif %}
{% if linked_groups %}
{% if linked_groups or can_duplicate_intervention %}
<div class="card mb-3">
<div class="card-body">
<h6 class="text-uppercase text-muted small mb-3">
<i class="bi bi-link-45deg"></i> {% translate "Interventions liées" %}
</h6>
<div class="d-flex justify-content-between align-items-center mb-3">
<h6 class="text-uppercase text-muted small mb-0">
<i class="bi bi-link-45deg"></i> {% translate "Interventions liées" %}
</h6>
{% if can_duplicate_intervention %}
<form method="post" action="{% url 'interventions:duplicate_intervention' intervention.id %}" class="d-inline" onsubmit="return confirm('{% translate "Êtes-vous sûr de vouloir dupliquer cette intervention ?" %}');">
{% csrf_token %}
<input type="hidden" name="variant" value="mobile">
<button type="submit" class="btn btn-outline-primary btn-sm">
<i class="bi bi-copy"></i> {% translate "Dupliquer" %}
</button>
</form>
{% endif %}
</div>
{% for group in linked_groups %}
<p class="text-muted mb-1 fw-semibold">{{ group.label }}</p>
<ul class="list-unstyled {% if not forloop.last %}mb-3{% else %}mb-0{% endif %}">
@ -1782,6 +1793,8 @@
{% endwith %}
{% endfor %}
</ul>
{% empty %}
<p class="text-muted mb-0 small">{% translate "Aucune intervention liée pour l'instant." %}</p>
{% endfor %}
</div>
</div>

View file

@ -776,7 +776,8 @@ class ExternalManagerScheduleUpdateTests(TestCase):
}
res = self.client.post(self.update_url, data=json.dumps(payload), content_type='application/json')
self.assertEqual(res.status_code, 403)
self.assertIn("entreprise", res.json().get('error', '').lower())
err_msg = res.json().get('error', '').lower()
self.assertTrue('entreprise' in err_msg or 'company' in err_msg)
def test_external_manager_can_unassign_assigned_status_intervention_to_backlog(self):
itv_assigned = Intervention.objects.create(

View file

@ -16,6 +16,10 @@ from interventions.models import (
InterventionContractPost,
InterventionPlanificationTimeLine,
InterventionRealizationTimeLine,
InterventionTimeLine,
InterventionLink,
InterventionNote,
Symptom,
Operation,
InterventionAsset,
OperationTemplate,
@ -24,7 +28,9 @@ from interventions.models import (
OperationStatus,
STATUS_ORDERS,
InterventionDocument,
get_type_choices,
)
from django.db.models import Q
from django.contrib.contenttypes.models import ContentType
from interventions.views import _group_operations_by_asset_and_template, _create_equipment_operations_for_assets
from interventions.permissions import can_manage_occupations, can_delete_document
@ -1367,5 +1373,409 @@ class InterventionSubscriptionTests(TestCase):
self.assertNotIn(itv2, filtered_qs)
class InterventionDuplicationTests(TestCase):
def setUp(self):
User = get_user_model()
self.admin_user = User.objects.create_superuser(username='dup-admin', password='pwd', email='admin@example.com')
self.admin_role = Role.objects.create(name='admin')
self.admin_config = UserConfig.objects.create(user=self.admin_user, is_intern=True)
self.admin_config.roles.add(self.admin_role)
self.thematic = Thematic.objects.create(code='roads_dup', name_fr='Routes Dup', name_nl='Wegen Dup')
self.symptom = Symptom.objects.create(thematic=self.thematic, name_fr='Nid de poule', name_nl='Kuil', is_active=True)
self.company = Company.objects.create(name='Provider Co')
self.team = CompanyTeam.objects.create(name='Team A', company=self.company)
self.member = CompanyMember.objects.create(user=self.admin_user, name='Member A')
self.member.teams.add(self.team)
from datetime import date, timedelta
self.contract = Contract.objects.create(
company=self.company,
contract_number='C-DUP-01',
start_date=date.today() - timedelta(days=10),
end_date=date.today() + timedelta(days=100),
)
from django.utils import timezone
now = timezone.now()
self.itv = Intervention.objects.create(
title='Intervention originale',
description='Description détaillée',
init_description='Origine signalement',
maintain_type='corrective',
type='repair',
origin_type='damage',
priority='1',
thematic=self.thematic,
symptom=self.symptom,
contract=self.contract,
assigned_provider=self.company,
assigned_team=self.team,
assigned_member=self.member,
status='in_progress',
status_order=21,
begin_time=now - timedelta(hours=2),
end_time=now + timedelta(hours=1),
planned_begin_time=now - timedelta(hours=3),
planned_end_time=now + timedelta(hours=2),
expected_begin_time=now - timedelta(hours=4),
expected_end_time=now + timedelta(hours=3),
transmission_time=now - timedelta(days=1),
address='Rue Royale 10, 1000 Bruxelles',
location_code='LOC-001',
lon=4.35,
lat=50.85,
created_by=self.admin_user,
)
# Notes
self.origin_note = InterventionNote.objects.create(
intervention=self.itv,
content='Note origine importante',
note_time=now,
note_type=InterventionNote.NoteType.ORIGIN,
note_author=self.admin_user,
)
self.work_note = InterventionNote.objects.create(
intervention=self.itv,
content='Note travaux réalisés à ne pas copier',
note_time=now,
note_type=InterventionNote.NoteType.WORK_DONE,
note_author=self.admin_user,
)
# Document
self.doc = InterventionDocument.objects.create(
intervention=self.itv,
file=SimpleUploadedFile('test_dup_doc.txt', b'hello world duplicated file'),
uploaded_by=self.admin_user,
description='Doc description',
)
# Operation template & Operation
self.template = OperationTemplate.objects.create(name='Template Dup', thematic=self.thematic)
self.itv.equipment_operation_templates.add(self.template)
self.op = Operation.objects.create(
intervention=self.itv,
name_fr='Vérifier enrobé',
name_nl='Asfalt controleren',
template_group='Template Dup',
order=1,
is_custom=False,
)
def test_duplication_success(self):
self.client.force_login(self.admin_user)
url = reverse('interventions:duplicate_intervention', kwargs={'intervention_id': self.itv.id})
response = self.client.post(url)
# Should redirect to the new intervention detail
new_itv = Intervention.objects.exclude(id=self.itv.id).first()
self.assertIsNotNone(new_itv)
self.assertRedirects(response, reverse('interventions:intervention_detail', kwargs={'intervention_id': new_itv.id}))
# General properties copied
self.assertEqual(new_itv.title, self.itv.title)
self.assertEqual(new_itv.description, self.itv.description)
self.assertEqual(new_itv.init_description, self.itv.init_description)
self.assertEqual(new_itv.thematic, self.itv.thematic)
self.assertEqual(new_itv.symptom, self.itv.symptom)
self.assertEqual(new_itv.priority, self.itv.priority)
self.assertEqual(new_itv.maintain_type, self.itv.maintain_type)
self.assertEqual(new_itv.type, self.itv.type)
self.assertEqual(new_itv.origin_type, self.itv.origin_type)
self.assertEqual(new_itv.address, self.itv.address)
self.assertEqual(new_itv.location_code, self.itv.location_code)
self.assertEqual(new_itv.lon, self.itv.lon)
self.assertEqual(new_itv.lat, self.itv.lat)
# Status reset to in_preparation
self.assertEqual(new_itv.status, 'in_preparation')
self.assertEqual(new_itv.status_order, 1)
# Contract, provider, team, members and dates NOT copied
self.assertIsNone(new_itv.contract)
self.assertIsNone(new_itv.order)
self.assertIsNone(new_itv.assigned_provider)
self.assertIsNone(new_itv.assigned_team)
self.assertIsNone(new_itv.assigned_member)
self.assertIsNone(new_itv.intervention_manager)
self.assertIsNone(new_itv.begin_time)
self.assertIsNone(new_itv.end_time)
self.assertIsNone(new_itv.planned_begin_time)
self.assertIsNone(new_itv.planned_end_time)
self.assertIsNone(new_itv.expected_begin_time)
self.assertIsNone(new_itv.expected_end_time)
self.assertIsNone(new_itv.transmission_time)
# Template & operations copied
self.assertEqual(list(new_itv.equipment_operation_templates.all()), [self.template])
self.assertEqual(new_itv.operations.count(), 1)
new_op = new_itv.operations.first()
self.assertEqual(new_op.name_fr, self.op.name_fr)
self.assertIsNone(new_op.status)
# Notes: only origin note copied
self.assertEqual(new_itv.notes.count(), 1)
copied_note = new_itv.notes.first()
self.assertEqual(copied_note.note_type, InterventionNote.NoteType.ORIGIN)
self.assertEqual(copied_note.content, self.origin_note.content)
# Documents copied
self.assertEqual(new_itv.documents.count(), 1)
copied_doc = new_itv.documents.first()
self.assertIn('test_dup_doc', copied_doc.file.name)
self.assertEqual(copied_doc.description, self.doc.description)
# Link exists between original and new
link_exists = InterventionLink.objects.filter(
Q(first=self.itv, second=new_itv) | Q(first=new_itv, second=self.itv)
).exists()
self.assertTrue(link_exists)
# Timeline creation event exists
timeline_exists = InterventionTimeLine.objects.filter(
intervention=new_itv,
event_type='creation',
).exists()
self.assertTrue(timeline_exists)
def test_duplication_mobile_redirect(self):
self.client.force_login(self.admin_user)
url = reverse('interventions:duplicate_intervention', kwargs={'intervention_id': self.itv.id})
response = self.client.post(url, {'variant': 'mobile'})
new_itv = Intervention.objects.exclude(id=self.itv.id).first()
self.assertIsNotNone(new_itv)
self.assertRedirects(response, reverse('mobile:intervention_detail_mobile', kwargs={'intervention_id': new_itv.id}))
def test_duplication_with_associated_observation(self):
from observations.models import Observation
from interventions.models import SourceCategory
source_cat, _ = SourceCategory.objects.get_or_create(name_fr='Observation', defaults={'name_nl': 'Observatie'})
# Create an observation linked to original intervention
obs = Observation.objects.create(
thematic=self.thematic,
status='in_progress',
created_by=self.admin_user,
description="Test Observation with Intervention",
intervention=self.itv,
latitude=50.85,
longitude=4.35,
)
self.itv.source_category = source_cat
self.itv.source_ref = str(obs.id)
self.itv.save()
# Check initial associations
self.assertIn(self.itv, obs.get_associated_interventions())
self.assertIn(obs, self.itv.get_associated_observations())
# Duplicate intervention
self.client.force_login(self.admin_user)
url = reverse('interventions:duplicate_intervention', kwargs={'intervention_id': self.itv.id})
response = self.client.post(url)
self.assertEqual(response.status_code, 302)
new_itv = Intervention.objects.exclude(id=self.itv.id).first()
self.assertIsNotNone(new_itv)
# Both interventions should be associated with the observation
obs_interventions = list(obs.get_associated_interventions())
self.assertIn(self.itv, obs_interventions)
self.assertIn(new_itv, obs_interventions)
# Both interventions should retrieve the observation
self.assertIn(obs, self.itv.get_associated_observations())
self.assertIn(obs, new_itv.get_associated_observations())
# Check observation detail view displays visible_interventions
obs_url = reverse('observations:observation_detail', kwargs={'observation_id': obs.id})
obs_response = self.client.get(obs_url)
self.assertEqual(obs_response.status_code, 200)
self.assertIn('visible_interventions', obs_response.context)
visible_itv_ids = [item['intervention'].id for item in obs_response.context['visible_interventions']]
self.assertIn(self.itv.id, visible_itv_ids)
self.assertIn(new_itv.id, visible_itv_ids)
class InterventionGeojsonExternalFilterTests(TestCase):
def setUp(self):
User = get_user_model()
self.user = User.objects.create_user(username='ext_filter_user', password='pwd')
role_admin = Role.objects.create(name='admin')
self.company_user = Company.objects.create(name='Ma Société')
self.company_other = Company.objects.create(name='Autre Société')
self.thematic = Thematic.objects.create(code='THEM_GEO_EXT', name_fr='Geo Ext', name_nl='Geo Ext')
self.user_config = UserConfig.objects.create(
user=self.user,
is_intern=True,
company=self.company_user,
default_thematic=self.thematic,
limit_interventions_to_contracts=False
)
self.user_config.roles.add(role_admin)
UserThematics.objects.create(
user_config=self.user_config,
thematic=self.thematic,
can_edit_interventions=True,
can_view_interventions=True
)
# Internal intervention
self.itv_internal = Intervention.objects.create(
code='ITV-INT-001',
title='Interne',
status='to_be_processed',
thematic=self.thematic,
assigned_provider=self.company_user
)
# External intervention
self.itv_external = Intervention.objects.create(
code='ITV-EXT-001',
title='Externe',
status='to_be_processed',
thematic=self.thematic,
assigned_provider=self.company_other
)
self.url = reverse('interventions:interventions_geojson')
def test_filter_external_interventions_geojson(self):
self.client.force_login(self.user)
# 1. Without filter: both returned
resp_all = self.client.get(self.url)
self.assertEqual(resp_all.status_code, 200)
data_all = json.loads(resp_all.content)
ids_all = [f['properties']['id'] for f in data_all['features']]
self.assertIn(self.itv_internal.id, ids_all)
self.assertIn(self.itv_external.id, ids_all)
# 2. With external=1 filter: only external returned
resp_ext = self.client.get(self.url + '?external=1')
self.assertEqual(resp_ext.status_code, 200)
data_ext = json.loads(resp_ext.content)
ids_ext = [f['properties']['id'] for f in data_ext['features']]
self.assertNotIn(self.itv_internal.id, ids_ext)
self.assertIn(self.itv_external.id, ids_ext)
class TrafficlightsReprogrammingTypeTests(TestCase):
def setUp(self):
User = get_user_model()
self.user = User.objects.create_user(username='admin_tl', password='pwd')
self.role_admin, _ = Role.objects.get_or_create(name='admin')
self.user_config = UserConfig.objects.create(user=self.user, is_intern=True)
self.user_config.roles.add(self.role_admin)
self.tl_thematic, _ = Thematic.objects.get_or_create(code='trafficlights', defaults={'name_fr': 'Feux tricolores', 'name_nl': 'Verkeerslichten'})
self.struct_thematic, _ = Thematic.objects.get_or_create(code='structures', defaults={'name_fr': "Ouvrages d'art", 'name_nl': 'Kunstwerken'})
UserThematics.objects.create(user_config=self.user_config, thematic=self.tl_thematic, can_edit_interventions=True)
UserThematics.objects.create(user_config=self.user_config, thematic=self.struct_thematic, can_edit_interventions=True)
self.itv_tl = Intervention.objects.create(
code='ITV-TL-001',
title='Intervention Feux',
status='in_preparation',
thematic=self.tl_thematic,
type='fixing',
created_by=self.user
)
self.itv_struct = Intervention.objects.create(
code='ITV-ST-001',
title='Intervention Ouvrage',
status='in_preparation',
thematic=self.struct_thematic,
type='fixing',
created_by=self.user
)
def test_get_type_choices(self):
tl_choices = [c[0] for c in get_type_choices(self.tl_thematic)]
self.assertIn('reprogramming', tl_choices)
self.assertIn('fixing', tl_choices)
tl_str_choices = [c[0] for c in get_type_choices('trafficlights')]
self.assertIn('reprogramming', tl_str_choices)
struct_choices = [c[0] for c in get_type_choices(self.struct_thematic)]
self.assertNotIn('reprogramming', struct_choices)
self.assertIn('fixing', struct_choices)
struct_str_choices = [c[0] for c in get_type_choices('structures')]
self.assertNotIn('reprogramming', struct_str_choices)
none_choices = [c[0] for c in get_type_choices(None)]
self.assertNotIn('reprogramming', none_choices)
def test_intervention_form_choices(self):
from interventions.views.forms import InterventionForm
form_tl = InterventionForm(thematic=self.tl_thematic, user=self.user)
tl_choices = [c[0] for c in form_tl.fields['type'].choices]
self.assertIn('reprogramming', tl_choices)
form_struct = InterventionForm(thematic=self.struct_thematic, user=self.user)
struct_choices = [c[0] for c in form_struct.fields['type'].choices]
self.assertNotIn('reprogramming', struct_choices)
def test_preventive_intervention_form_choices(self):
from interventions.views.forms import PreventiveInterventionForm
form_tl = PreventiveInterventionForm(thematic=self.tl_thematic, user=self.user)
tl_choices = [c[0] for c in form_tl.fields['type'].choices]
self.assertIn('reprogramming', tl_choices)
form_struct = PreventiveInterventionForm(thematic=self.struct_thematic, user=self.user)
struct_choices = [c[0] for c in form_struct.fields['type'].choices]
self.assertNotIn('reprogramming', struct_choices)
def test_intervention_detail_context(self):
self.client.force_login(self.user)
resp_tl = self.client.get(reverse('interventions:intervention_detail', kwargs={'intervention_id': self.itv_tl.id}))
self.assertEqual(resp_tl.status_code, 200)
tl_type_choices = [c[0] for c in resp_tl.context['type_choices']]
self.assertIn('reprogramming', tl_type_choices)
resp_struct = self.client.get(reverse('interventions:intervention_detail', kwargs={'intervention_id': self.itv_struct.id}))
self.assertEqual(resp_struct.status_code, 200)
struct_type_choices = [c[0] for c in resp_struct.context['type_choices']]
self.assertNotIn('reprogramming', struct_type_choices)
def test_update_intervention_type_reprogramming(self):
self.client.force_login(self.user)
# Updating trafficlights intervention to reprogramming -> SUCCESS
update_url_tl = reverse('interventions:update_intervention', kwargs={'intervention_id': self.itv_tl.id})
resp = self.client.post(
update_url_tl,
data=json.dumps({'type': 'reprogramming'}),
content_type='application/json'
)
self.assertEqual(resp.status_code, 200)
self.itv_tl.refresh_from_db()
self.assertEqual(self.itv_tl.type, 'reprogramming')
# Updating structures intervention to reprogramming -> REJECTED
update_url_struct = reverse('interventions:update_intervention', kwargs={'intervention_id': self.itv_struct.id})
resp = self.client.post(
update_url_struct,
data=json.dumps({'type': 'reprogramming'}),
content_type='application/json'
)
self.itv_struct.refresh_from_db()
self.assertEqual(self.itv_struct.type, 'fixing')

View file

@ -15,6 +15,7 @@ from assets.models import AssetCategory
from interventions.models import (
Intervention,
InterventionContractPost,
ContractOperationTemplatePost,
InterventionPlanificationTimeLine,
InterventionRealizationTimeLine,
Operation,
@ -609,7 +610,7 @@ class PreventiveTemplateTeamAssignmentTests(TestCase):
def setUp(self):
User = get_user_model()
self.thematic = Thematic.objects.create(code='trafficlights', name_fr='Signalisation', name_nl='Signalisatie')
self.thematic, _ = Thematic.objects.get_or_create(code='trafficlights', defaults={'name_fr': 'Signalisation', 'name_nl': 'Signalisatie'})
self.company = Company.objects.create(name='Provider Corp')
self.team_a = CompanyTeam.objects.create(name='Equipe Alpha', company=self.company)
self.team_a.thematics.add(self.thematic)
@ -882,6 +883,364 @@ class PreventiveTemplateTeamAssignmentTests(TestCase):
self.assertGreaterEqual(len(data['teams']), 2)
class ContractOperationTemplatePostTests(TestCase):
"""Test associating ContractPosts with default quantities to OperationTemplates and preventive interventions."""
def setUp(self):
User = get_user_model()
self.user = User.objects.create_user(username='test_user_posts', password='password123')
self.thematic, _ = Thematic.objects.get_or_create(
code='trafficlights',
defaults={'name_fr': 'Feux', 'name_nl': 'Verkeerslichten'}
)
self.role, _ = Role.objects.get_or_create(name='manager')
self.user_config = UserConfig.objects.create(user=self.user, is_intern=True)
self.user_config.roles.add(self.role)
self.company = Company.objects.create(name='Provider Co')
self.contract = Contract.objects.create(
contract_number='CTR-TEST-001',
company=self.company,
start_date=timezone.now().date(),
end_date=timezone.now().date() + timedelta(days=365),
is_active=True,
)
self.contract.thematics.add(self.thematic)
self.user_config.contracts.add(self.contract)
uca = UserContractAccess.objects.get(user_config=self.user_config, contract=self.contract)
uca.can_edit_interventions = True
uca.can_view_posts = True
uca.can_view_interventions = True
uca.save()
UserThematics.objects.create(user_config=self.user_config, thematic=self.thematic, can_edit_interventions=True)
self.contract_other = Contract.objects.create(
contract_number='CTR-OTHER-002',
company=self.company,
start_date=timezone.now().date(),
end_date=timezone.now().date() + timedelta(days=365),
is_active=True,
)
self.post_1 = ContractPost.objects.create(
contract=self.contract,
code='P01',
description_fr='Poste 1 FR',
description_nl='Post 1 NL',
order_number=1,
unit='pc',
unit_price=Decimal('10.00'),
)
self.post_2 = ContractPost.objects.create(
contract=self.contract,
code='P02',
description_fr='Poste 2 FR',
description_nl='Post 2 NL',
order_number=2,
unit='m',
unit_price=Decimal('25.50'),
)
self.post_3 = ContractPost.objects.create(
contract=self.contract,
code='P03',
description_fr='Poste 3 FR',
description_nl='Post 3 NL',
order_number=3,
unit='h',
unit_price=Decimal('50.00'),
)
self.post_other = ContractPost.objects.create(
contract=self.contract_other,
code='P_OTHER',
description_fr='Poste Autre Contrat',
description_nl='Post Andere',
order_number=1,
unit='pc',
unit_price=Decimal('100.00'),
)
self.template_a = OperationTemplate.objects.create(
name='Template A',
thematic=self.thematic
)
self.template_b = OperationTemplate.objects.create(
name='Template B',
thematic=self.thematic
)
def test_model_str_and_save_clean(self):
"""Test model validation, clean method, auto-contract and string representation."""
from django.core.exceptions import ValidationError
# Auto-populates contract if only contract_post is set
mapping = ContractOperationTemplatePost(
operation_template=self.template_a,
contract_post=self.post_1,
default_quantity=Decimal('2.00'),
comment='Commentaire test'
)
mapping.save()
self.assertEqual(mapping.contract, self.contract)
self.assertIn('CTR-TEST-001', str(mapping))
self.assertIn('Template A', str(mapping))
self.assertIn('P01', str(mapping))
# Invalid: contract_post belongs to another contract
invalid_mapping = ContractOperationTemplatePost(
contract=self.contract,
operation_template=self.template_a,
contract_post=self.post_other,
default_quantity=Decimal('1.00')
)
with self.assertRaises(ValidationError):
invalid_mapping.clean()
def test_assign_contract_posts_from_templates_single(self):
"""Test assigning default posts to an intervention from a single template."""
from interventions.views.helpers import _assign_contract_posts_from_templates
ContractOperationTemplatePost.objects.create(
contract=self.contract,
operation_template=self.template_a,
contract_post=self.post_1,
default_quantity=Decimal('3.00'),
comment='Nettoyage standard'
)
ContractOperationTemplatePost.objects.create(
contract=self.contract,
operation_template=self.template_a,
contract_post=self.post_2,
default_quantity=Decimal('1.50'),
)
intervention = Intervention.objects.create(
title='Intervention Test',
contract=self.contract,
thematic=self.thematic,
maintain_type='preventive',
created_by=self.user
)
_assign_contract_posts_from_templates(intervention, [self.template_a])
posts = list(intervention.interv_contract_posts.all().order_by('contract_post__order_number'))
self.assertEqual(len(posts), 2)
self.assertEqual(posts[0].contract_post, self.post_1)
self.assertEqual(posts[0].quantity, Decimal('3.00'))
self.assertEqual(posts[0].comment, 'Nettoyage standard')
self.assertEqual(posts[1].contract_post, self.post_2)
self.assertEqual(posts[1].quantity, Decimal('1.50'))
def test_assign_contract_posts_deduplication_first_found(self):
"""
When multiple templates are chosen and share a post,
the first one encountered must be kept, and subsequent duplicates ignored.
"""
from interventions.views.helpers import _assign_contract_posts_from_templates
# Template A defines Post 1 (qty 2) and Post 2 (qty 5)
ContractOperationTemplatePost.objects.create(
contract=self.contract,
operation_template=self.template_a,
contract_post=self.post_1,
default_quantity=Decimal('2.00'),
comment='From Template A'
)
ContractOperationTemplatePost.objects.create(
contract=self.contract,
operation_template=self.template_a,
contract_post=self.post_2,
default_quantity=Decimal('5.00'),
)
# Template B defines Post 1 (qty 10 with other comment) and Post 3 (qty 1)
ContractOperationTemplatePost.objects.create(
contract=self.contract,
operation_template=self.template_b,
contract_post=self.post_1,
default_quantity=Decimal('10.00'),
comment='From Template B'
)
ContractOperationTemplatePost.objects.create(
contract=self.contract,
operation_template=self.template_b,
contract_post=self.post_3,
default_quantity=Decimal('1.00'),
)
intervention = Intervention.objects.create(
title='Intervention Multi-Templates',
contract=self.contract,
thematic=self.thematic,
maintain_type='preventive',
created_by=self.user
)
# Pass templates in order [A, B]
_assign_contract_posts_from_templates(intervention, [self.template_a, self.template_b])
posts = list(intervention.interv_contract_posts.all().order_by('contract_post__order_number'))
self.assertEqual(len(posts), 3)
# Post 1 must come from Template A (qty 2, first found)
self.assertEqual(posts[0].contract_post, self.post_1)
self.assertEqual(posts[0].quantity, Decimal('2.00'))
self.assertEqual(posts[0].comment, 'From Template A')
# Post 2 from Template A
self.assertEqual(posts[1].contract_post, self.post_2)
self.assertEqual(posts[1].quantity, Decimal('5.00'))
# Post 3 from Template B
self.assertEqual(posts[2].contract_post, self.post_3)
self.assertEqual(posts[2].quantity, Decimal('1.00'))
def test_assign_contract_posts_empty_or_no_contract(self):
"""Test that helper handles empty templates or no contract gracefully."""
from interventions.views.helpers import _assign_contract_posts_from_templates
intervention_no_contract = Intervention.objects.create(
title='No Contract',
thematic=self.thematic,
created_by=self.user
)
_assign_contract_posts_from_templates(intervention_no_contract, [self.template_a])
self.assertEqual(intervention_no_contract.interv_contract_posts.count(), 0)
intervention = Intervention.objects.create(
title='With Contract',
contract=self.contract,
thematic=self.thematic,
created_by=self.user
)
_assign_contract_posts_from_templates(intervention, [])
self.assertEqual(intervention.interv_contract_posts.count(), 0)
def test_preventive_creation_flow_auto_creates_posts(self):
"""Test full preventive intervention creation flow automatically populates posts."""
from assets.models import TrafficLightIntersection
loc = TrafficLightIntersection.objects.create(code='TL-POST-01', name_fr='Carrefour Test')
ContractOperationTemplatePost.objects.create(
contract=self.contract,
operation_template=self.template_a,
contract_post=self.post_1,
default_quantity=Decimal('4.00'),
comment='Auto Post'
)
self.client.login(username='test_user_posts', password='password123')
url = reverse('interventions:intervention_add_preventive', kwargs={'thematic_code': 'trafficlights'})
session = self.client.session
session['intervention_drafts'] = {
'draft-posts': {
'locations': [loc.id],
'assets': [],
'form_data': {},
'timestamp': time.time(),
}
}
session.save()
post_data = {
'title': 'Preventive With Posts',
'status': 'in_preparation',
'type': 'care',
'contract': self.contract.id,
'operation_templates': [str(self.template_a.id)],
'expected_begin_time': '2026-08-20T08:00',
'expected_end_time': '2026-08-20T17:00',
'recurrence_count': 0,
'type_of_selected_elements': 'locations',
'intervention_creation_mode': 'one_per_element',
'draft_id': 'draft-posts',
}
response = self.client.post(url, post_data)
self.assertEqual(response.status_code, 302)
intervention = Intervention.objects.filter(location_code='TL-POST-01').first()
self.assertIsNotNone(intervention)
posts = list(intervention.interv_contract_posts.all())
self.assertEqual(len(posts), 1)
self.assertEqual(posts[0].contract_post, self.post_1)
self.assertEqual(posts[0].quantity, Decimal('4.00'))
self.assertEqual(posts[0].comment, 'Auto Post')
def test_detail_view_includes_associated_order_and_posts_modal(self):
"""Test that the detail view context includes orders and correctly preselects the associated order."""
admin_role, _ = Role.objects.get_or_create(name='admin')
self.user_config.roles.add(admin_role)
from contracts.models import ContractOrder
order = ContractOrder.objects.create(
contract=self.contract,
order_code='CMD-2026-001',
order_date=timezone.now().date(),
delivery_date=timezone.now().date() + timedelta(days=30),
order_status='pending',
total_amount=Decimal('500.00'),
)
intervention = Intervention.objects.create(
title='Intervention With Order',
contract=self.contract,
order=order,
thematic=self.thematic,
status='in_preparation',
created_by=self.user,
)
self.client.login(username='test_user_posts', password='password123')
detail_url = reverse('interventions:intervention_detail', kwargs={'intervention_id': intervention.id})
response = self.client.get(detail_url)
self.assertEqual(response.status_code, 200)
# Check context
self.assertIn('orders', response.context)
orders = response.context['orders']
self.assertIsNotNone(orders)
self.assertIn(order, orders)
self.assertEqual(response.context['contract_id'], self.contract.id)
# Check rendered HTML for modal selector
content = response.content.decode('utf-8')
self.assertIn(f'data-initial-order-id="{order.id}"', content)
self.assertIn(f'value="{order.id}"', content)
self.assertIn('selected', content)
def test_ajax_get_posts_by_contract(self):
"""Test the AJAX endpoint filtering contract posts by contract."""
self.client.login(username='test_user_posts', password='password123')
url = reverse('interventions:ajax_get_posts_by_contract')
# Call with no contract_id
res = self.client.get(url)
self.assertEqual(res.status_code, 200)
self.assertEqual(res.json().get('posts'), [])
# Call with self.contract
res = self.client.get(url, {'contract_id': self.contract.id})
self.assertEqual(res.status_code, 200)
posts_data = res.json().get('posts', [])
post_ids = [p['id'] for p in posts_data]
self.assertIn(self.post_1.id, post_ids)
self.assertIn(self.post_2.id, post_ids)
self.assertNotIn(self.post_other.id, post_ids)
def test_ajax_get_contracts_by_thematic(self):
"""Test the AJAX endpoint filtering contracts by thematic."""
self.client.login(username='test_user_posts', password='password123')
url = reverse('interventions:ajax_get_contracts_by_thematic')
res = self.client.get(url, {'thematic_id': self.thematic.id})
self.assertEqual(res.status_code, 200)
contracts_data = res.json().get('contracts', [])
contract_ids = [c['id'] for c in contracts_data]
self.assertIn(self.contract.id, contract_ids)
self.assertNotIn(self.contract_other.id, contract_ids)

View file

@ -0,0 +1,211 @@
from datetime import timedelta
from django.test import TestCase, RequestFactory
from django.contrib.auth import get_user_model
from django.utils import timezone
from common.models import Role, UserConfig, Thematic, UserThematics, UserContractAccess, UserContractStatusPermission
from contracts.models import Company, CompanyTeam, CompanyMember, Contract
from interventions.models import Intervention, STATUS_CHOICES
from interventions.permissions import can_edit_intervention, can_manage_occupations, can_view_intervention, filter_viewable_interventions_for_user
from interventions.views.workflow import attempt_status_update
class TeamMembersEditTests(TestCase):
def setUp(self):
self.User = get_user_model()
self.role_tech, _ = Role.objects.get_or_create(name='technician')
self.company = Company.objects.create(name='Prestataire Test')
self.team1 = CompanyTeam.objects.create(name='Équipe Alpha', company=self.company)
self.team2 = CompanyTeam.objects.create(name='Équipe Bêta', company=self.company)
self.thematic = Thematic.objects.create(code='roads', name_fr='Voirie', name_nl='Wegen')
# Utilisateur Tech A (Membre de l'Équipe Alpha)
self.user_a = self.User.objects.create_user(username='tech_a', password='pwd')
self.config_a = UserConfig.objects.create(user=self.user_a, is_intern=False)
self.config_a.roles.add(self.role_tech)
self.member_a = CompanyMember.objects.create(user=self.user_a, name='Technicien A')
self.member_a.teams.add(self.team1)
# Utilisateur Tech B (Collègue dans l'Équipe Alpha)
self.user_b = self.User.objects.create_user(username='tech_b', password='pwd')
self.config_b = UserConfig.objects.create(user=self.user_b, is_intern=False)
self.config_b.roles.add(self.role_tech)
self.member_b = CompanyMember.objects.create(user=self.user_b, name='Technicien B')
self.member_b.teams.add(self.team1)
# Utilisateur Tech C (Technicien dans une autre équipe: Bêta)
self.user_c = self.User.objects.create_user(username='tech_c', password='pwd')
self.config_c = UserConfig.objects.create(user=self.user_c, is_intern=False)
self.config_c.roles.add(self.role_tech)
self.member_c = CompanyMember.objects.create(user=self.user_c, name='Technicien C')
self.member_c.teams.add(self.team2)
# Contrat avec allow_team_members_edit=False
self.contract_no_team_edit = Contract.objects.create(
company=self.company,
contract_number='C-NO-TEAM-EDIT',
start_date=timezone.now().date() - timedelta(days=10),
end_date=timezone.now().date() + timedelta(days=10),
is_active=True,
allow_team_members_edit=False,
)
self.contract_no_team_edit.thematics.add(self.thematic)
# Contrat avec allow_team_members_edit=True
self.contract_with_team_edit = Contract.objects.create(
company=self.company,
contract_number='C-WITH-TEAM-EDIT',
start_date=timezone.now().date() - timedelta(days=10),
end_date=timezone.now().date() + timedelta(days=10),
is_active=True,
allow_team_members_edit=True,
)
self.contract_with_team_edit.thematics.add(self.thematic)
# Permissions thématiques et contrats pour les 3 techniciens
for cfg in [self.config_a, self.config_b, self.config_c]:
UserThematics.objects.create(
user_config=cfg,
thematic=self.thematic,
can_view_interventions=True,
can_edit_interventions=True,
)
for contract in [self.contract_no_team_edit, self.contract_with_team_edit]:
uca = UserContractAccess.objects.create(
user_config=cfg,
contract=contract,
can_view_interventions=True,
)
for status in ['assigned', 'in_progress', 'on_pause', 'finished', 'to_be_processed']:
UserContractStatusPermission.objects.create(
user_contract=uca,
status=status,
can_view=True,
can_edit=True,
can_change_status_to=True,
)
def test_default_behavior_team_member_cannot_edit_assigned_intervention(self):
"""Si allow_team_members_edit=False, Tech B ne peut pas modifier l'intervention assignée à Tech A."""
intervention = Intervention.objects.create(
title='Intervention Test 1',
thematic=self.thematic,
contract=self.contract_no_team_edit,
assigned_provider=self.company,
assigned_member=self.member_a,
status='assigned',
)
# Tech A peut modifier
self.assertTrue(can_edit_intervention(self.user_a, intervention))
# Tech B (même équipe) ne peut PAS modifier
self.assertFalse(can_edit_intervention(self.user_b, intervention))
# Tentative de passage à 'in_progress' par Tech B
factory = RequestFactory()
request = factory.post(f'/interventions/{intervention.id}/update_status/', {'new_status': 'in_progress'})
request.user = self.user_b
success, msg, _ = attempt_status_update(request, intervention, self.user_b, 'in_progress')
self.assertFalse(success)
self.assertEqual(intervention.status, 'assigned')
def test_allow_team_members_edit_true_allows_colleague_to_edit_and_transition(self):
"""Si allow_team_members_edit=True, Tech B (même équipe) peut modifier et faire avancer l'intervention."""
intervention = Intervention.objects.create(
title='Intervention Test 2',
thematic=self.thematic,
contract=self.contract_with_team_edit,
assigned_provider=self.company,
assigned_member=self.member_a,
status='assigned',
)
# Tech A peut modifier
self.assertTrue(can_edit_intervention(self.user_a, intervention))
# Tech B (même équipe) PEUT modifier
self.assertTrue(can_edit_intervention(self.user_b, intervention))
# Tech B peut passer au statut 'in_progress'
factory = RequestFactory()
request = factory.post(f'/interventions/{intervention.id}/update_status/', {'new_status': 'in_progress'})
request.user = self.user_b
success, msg, _ = attempt_status_update(request, intervention, self.user_b, 'in_progress')
self.assertTrue(success)
intervention.refresh_from_db()
self.assertEqual(intervention.status, 'in_progress')
# Tech B peut toujours éditer lorsque le statut est 'in_progress', 'on_pause', 'finished'
self.assertTrue(can_edit_intervention(self.user_b, intervention))
# Tech B peut mettre en pause
success, msg, _ = attempt_status_update(request, intervention, self.user_b, 'on_pause', pause_reason='order_material')
self.assertTrue(success)
intervention.refresh_from_db()
self.assertEqual(intervention.status, 'on_pause')
self.assertTrue(can_edit_intervention(self.user_b, intervention))
def test_allow_team_members_edit_true_rejects_unrelated_technician(self):
"""Même si allow_team_members_edit=True, un technicien d'une autre équipe (Tech C) ne peut pas modifier."""
intervention = Intervention.objects.create(
title='Intervention Test 3',
thematic=self.thematic,
contract=self.contract_with_team_edit,
assigned_provider=self.company,
assigned_member=self.member_a,
status='assigned',
)
# Tech C (Équipe Bêta, membre_a est dans Équipe Alpha) ne peut PAS modifier
self.assertFalse(can_edit_intervention(self.user_c, intervention))
def test_can_manage_occupations_for_team_colleague(self):
"""Vérifie la gestion des occupations entre collègues d'une même équipe selon le paramètre du contrat."""
# Cas 1 : allow_team_members_edit=False et pas de assigned_team
itv1 = Intervention.objects.create(
title='Intervention Occupations 1',
thematic=self.thematic,
contract=self.contract_no_team_edit,
assigned_provider=self.company,
assigned_member=self.member_a,
status='in_progress',
)
self.assertTrue(can_manage_occupations(self.user_a, itv1))
self.assertFalse(can_manage_occupations(self.user_b, itv1))
# Cas 2 : allow_team_members_edit=True
itv2 = Intervention.objects.create(
title='Intervention Occupations 2',
thematic=self.thematic,
contract=self.contract_with_team_edit,
assigned_provider=self.company,
assigned_member=self.member_a,
status='in_progress',
)
self.assertTrue(can_manage_occupations(self.user_a, itv2))
self.assertTrue(can_manage_occupations(self.user_b, itv2))
self.assertFalse(can_manage_occupations(self.user_c, itv2))
def test_visibility_with_restrict_to_assigned_interventions(self):
"""Vérifie que la restriction aux interventions assignées permet la visibilité aux collègues si allow_team_members_edit=True."""
self.team1.restrict_to_assigned_interventions = True
self.team1.save()
# Intervention sur contrat avec allow_team_members_edit=True
itv = Intervention.objects.create(
title='Intervention Visibilité',
thematic=self.thematic,
contract=self.contract_with_team_edit,
assigned_provider=self.company,
assigned_member=self.member_a,
status='assigned',
)
self.assertTrue(can_view_intervention(self.user_a, itv))
self.assertTrue(can_view_intervention(self.user_b, itv))
self.assertIn(itv, filter_viewable_interventions_for_user(self.user_b))

View file

@ -657,6 +657,94 @@ class GetContractsByProviderTests(TestCase):
self.assertIn("C-002", contract_numbers)
class QuickProviderContractUpdateTests(TestCase):
def setUp(self):
from common.models import UserContractAccess, UserContractStatusPermission
self.User = get_user_model()
self.manager_role, _ = Role.objects.get_or_create(name='manager')
self.thematic = Thematic.objects.create(name_fr='Voirie Test', allow_planning_without_contract=True)
self.company1 = Company.objects.create(name='Company 1')
self.company2 = Company.objects.create(name='Company 2')
self.contract1 = Contract.objects.create(
contract_number="C-001",
company=self.company1,
start_date=timezone.now().date(),
end_date=timezone.now().date() + timedelta(days=365)
)
self.contract1.thematics.add(self.thematic)
self.contract2 = Contract.objects.create(
contract_number="C-002",
company=self.company2,
start_date=timezone.now().date(),
end_date=timezone.now().date() + timedelta(days=365)
)
self.contract2.thematics.add(self.thematic)
# User with limited contract access
self.user = self.User.objects.create_user(username='contract-manager', password='pwd')
self.user_config = UserConfig.objects.create(
user=self.user,
is_intern=True,
limit_interventions_to_contracts=True,
)
self.user_config.roles.add(self.manager_role)
# User thematic without explicit UserThematicStatusPermission
UserThematics.objects.create(
user_config=self.user_config,
thematic=self.thematic,
can_view_interventions=True,
can_edit_interventions=True,
)
# Access and edit permissions on both contracts for to_be_planned status
uca1 = UserContractAccess.objects.create(user_config=self.user_config, contract=self.contract1, can_view_interventions=True)
UserContractStatusPermission.objects.create(user_contract=uca1, status='to_be_planned', can_edit=True, can_view=True)
uca2 = UserContractAccess.objects.create(user_config=self.user_config, contract=self.contract2, can_view_interventions=True)
UserContractStatusPermission.objects.create(user_contract=uca2, status='to_be_planned', can_edit=True, can_view=True)
self.intervention = Intervention.objects.create(
title='Test Quick Edit Intervention',
thematic=self.thematic,
status='to_be_planned',
assigned_provider=self.company1,
contract=self.contract1,
)
def test_batch_update_provider_and_contract(self):
from interventions.permissions import can_edit_intervention
self.assertTrue(can_edit_intervention(self.user, self.intervention))
self.client.login(username='contract-manager', password='pwd')
url = reverse('interventions:update_intervention', args=[self.intervention.id])
payload = {
'assigned_provider': str(self.company2.id),
'contract': str(self.contract2.id),
}
response = self.client.post(url, data=json.dumps(payload), content_type='application/json')
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertTrue(data['success'])
self.intervention.refresh_from_db()
self.assertEqual(self.intervention.assigned_provider, self.company2)
self.assertEqual(self.intervention.contract, self.contract2)
def test_can_edit_intervention_when_contract_is_none(self):
from interventions.permissions import can_edit_intervention
self.intervention.contract = None
self.intervention.assigned_provider = self.company2
self.intervention.save()
# User should still be allowed to edit because they have edit rights on contracts of this thematic/provider
self.assertTrue(can_edit_intervention(self.user, self.intervention))

View file

@ -29,6 +29,7 @@ urlpatterns = [
path('<int:intervention_id>/notes/<int:note_id>/update/', views.intervention_update_note, name='intervention_update_note'),
path('<int:intervention_id>/notes/<int:note_id>/delete/', views.intervention_delete_note, name='intervention_delete_note'),
path('<int:intervention_id>/create-repair/', views.create_repair_intervention, name='create_repair_intervention'),
path('<int:intervention_id>/duplicate/', views.duplicate_intervention, name='duplicate_intervention'),
path('<int:intervention_id>/link-existing/', views.link_existing_interventions, name='link_existing_interventions'),
path('<int:intervention_id>/occupations/add/', views.intervention_add_occupation, name='intervention_add_occupation'),
path('<int:intervention_id>/occupations/<int:occupation_id>/update/', views.intervention_update_occupation, name='intervention_update_occupation'),
@ -106,6 +107,8 @@ urlpatterns = [
path('ajax/get-subcategories/', views.ajax_get_subcategories, name='ajax_get_subcategories'),
path('ajax/get-asset-models/', views.ajax_get_asset_models, name='ajax_get_asset_models'),
path('ajax/get-replacement-models-by-category/', views.ajax_get_replacement_models_by_category, name='ajax_get_replacement_models_by_category'),
path('ajax/get-posts-by-contract/', views.ajax_get_posts_by_contract, name='ajax_get_posts_by_contract'),
path('ajax/get-contracts-by-thematic/', views.ajax_get_contracts_by_thematic, name='ajax_get_contracts_by_thematic'),
# Template check for assets without matching templates
path('<int:intervention_id>/check-asset-templates/', views.check_asset_templates_for_intervention, name='check_asset_templates'),
path('<int:intervention_id>/create-operations-from-template/', views.create_operations_from_selected_template, name='create_operations_from_template'),

View file

@ -61,7 +61,7 @@ from interventions.models import (InterventionSubscription, Intervention, Interv
Operation, OperationTemplate, OperationTemplateItem, OperationStatus, OperationStatusSet, MeasurementDefinition,
GuidedOperationTemplate, GuidedOperationData, GuidedOperationMedia,
InterventionPostPeriodQuantity, InterventionEmailLog, InterventionAssignment)
from interventions.models import STATUS_CHOICES, STATUS_ORDERS, MAINTAIN_CHOICES, TYPE_CHOICES, ORIGIN_TYPE_CHOICES, PAUSE_REASON_CHOICES
from interventions.models import STATUS_CHOICES, STATUS_ORDERS, MAINTAIN_CHOICES, TYPE_CHOICES, ORIGIN_TYPE_CHOICES, PAUSE_REASON_CHOICES, get_type_choices
from interventions.views.forms import (InterventionForm, InterventionNoteForm, InterventionDocumentForm,
InterventionOccupationForm, PreventiveInterventionForm, AssetsLinkForm,
LinkExistingInterventionsForm)
@ -72,7 +72,7 @@ from interventions.permissions import (intervention_permission_required, interve
can_view_intervention_summary,
get_accessible_interventions_for_technician, filter_viewable_interventions_for_user,
can_edit_note, can_delete_document, can_manage_occupations,
can_add_intervention, can_add_repair_intervention,
can_add_intervention, can_add_repair_intervention, can_duplicate_intervention,
intervention_manage_occupations_required,
get_contracts_for_intervention_creation, is_external_manager_with_contract_creation_rights,
should_show_created_by_provider_badge, can_view_correction_messages)
@ -149,7 +149,7 @@ def intervention_detail(request, intervention_id):
lang = get_language()
contract = intervention.contract
contract = intervention.contract or (intervention.order.contract if intervention.order else None)
thematic = intervention.thematic
allowed_update_fields = get_allowed_update_fields(request.user, intervention)
@ -223,11 +223,21 @@ def intervention_detail(request, intervention_id):
else:
has_coefficient_posts = False
orders = ContractOrder.objects.filter(contract=contract).exclude(order_status__in=['cancelled', 'paid'])
orders_qs = ContractOrder.objects.filter(contract=contract)
if intervention.order_id:
orders = orders_qs.filter(
Q(id=intervention.order_id) | ~Q(order_status__in=['cancelled', 'paid'])
).distinct().select_related('contract').order_by('order_code')
else:
orders = orders_qs.exclude(order_status__in=['cancelled', 'paid']).select_related('contract').order_by('order_code')
elif intervention.order_id:
has_coefficient_posts = False
orders = ContractOrder.objects.filter(id=intervention.order_id).select_related('contract')
else:
has_coefficient_posts = False
orders = ContractOrder.objects.none()
contract_id = intervention.order.contract.id if intervention.order else None
contract_id = contract.id if contract else None
# Limiter les providers et contracts selon les permissions de l'utilisateur
if user_config.is_intern and not user_config.limit_interventions_to_contracts:
@ -545,7 +555,7 @@ def intervention_detail(request, intervention_id):
linked_observations = []
obs_access_context = get_observation_access_context(request.user, user_config=user_config)
if obs_access_context:
all_observations = intervention.observations.select_related('thematic', 'category').order_by('-created_at')
all_observations = intervention.get_associated_observations().select_related('thematic', 'category')
linked_observations = [obs for obs in all_observations if obs_access_context.allows(obs)]
# Observation source (si la source est une observation)
@ -632,12 +642,13 @@ def intervention_detail(request, intervention_id):
'operations_asset_groups': asset_operations_groups,
'orders': orders,
'contract_id': contract_id,
'contract_posts_count': contract.posts.count() if contract else 0,
'can_control': can_control,
'is_draft': is_draft,
'providers': providers,
'contracts': contracts,
'maintain_choices': MAINTAIN_CHOICES,
'type_choices': TYPE_CHOICES,
'type_choices': get_type_choices(intervention.thematic),
'origin_type_choices': ORIGIN_TYPE_CHOICES,
'priority_choices': Intervention._meta.get_field('priority').choices,
'symptoms': Symptom.objects.filter(is_active=True, thematic=intervention.thematic).order_by('name_fr'),
@ -672,6 +683,7 @@ def intervention_detail(request, intervention_id):
'can_manage_links': can_manage_links,
'link_existing_form': LinkExistingInterventionsForm(),
'can_create_repair': can_create_repair,
'can_duplicate_intervention': can_duplicate_intervention(request.user, intervention),
'can_send_reminder': can_send_reminder,
# Historique des interventions aux mêmes localisations
'location_history_interventions': location_history_interventions,
@ -966,6 +978,194 @@ def create_repair_intervention(request, intervention_id):
return redirect('interventions:intervention_detail', intervention_id=intervention.id)
def duplicate_intervention(request, intervention_id):
"""
Duplique une intervention existante:
- Recopie la plupart des éléments (titre, description, localisation, équipement, thématique, etc.).
- Recopie les opérations (statut réinitialisé).
- Recopie les notes de type 'origine' (note_type='origin').
- Recopie les documents.
- Ne recopie pas : prestataire, contrat, équipe/membre assigné, dates.
- Statut par défaut : in_preparation (En préparation).
- Relie automatiquement la nouvelle intervention à la précédente (InterventionLink).
"""
intervention = get_object_or_404(Intervention, pk=intervention_id)
if not can_duplicate_intervention(request.user, intervention):
return HttpResponseForbidden(_("Vous n'avez pas la permission de dupliquer cette intervention."))
variant = request.POST.get('variant')
if "/mobile/" in request.path:
variant = 'mobile'
with transaction.atomic():
new_intervention = Intervention(
title=intervention.title,
description=intervention.description,
init_description=intervention.init_description,
maintain_type=intervention.maintain_type,
type=intervention.type,
origin_type=intervention.origin_type,
priority=intervention.priority,
thematic=intervention.thematic,
asset_category=intervention.asset_category,
symptom=intervention.symptom,
source_category=intervention.source_category,
source_detail=intervention.source_detail,
source_ref=intervention.source_ref,
pmo_number=intervention.pmo_number,
osiris=intervention.osiris,
lon=intervention.lon,
lat=intervention.lat,
address=intervention.address,
location_code=intervention.location_code,
geom=intervention.geom,
guided_operation_template=intervention.guided_operation_template,
status='in_preparation',
status_order=STATUS_ORDERS.get('in_preparation', 1),
created_by=request.user,
last_modified_by=request.user,
contract=None,
order=None,
intervention_manager=None,
assigned_provider=None,
assigned_team=None,
assigned_member=None,
begin_time=None,
end_time=None,
planned_begin_time=None,
planned_end_time=None,
expected_begin_time=None,
expected_end_time=None,
transmission_time=None,
init_call_confirmed_time=None,
init_call_received=False,
pause_reason=None,
pause_reason_other=None,
cancellation_type=None,
period_validation_enabled=False,
period_number=1,
period_is_final=False,
processed_via_other_intervention=False,
reason_for_correction=None,
correction_details=None,
follow_up_performed=None,
is_checked=False,
)
new_intervention.save()
auto_check_if_eligible(request.user, new_intervention)
# Copier les templates d'opérations équipements (M2M)
templates = list(intervention.equipment_operation_templates.all())
if templates:
new_intervention.equipment_operation_templates.set(templates)
# Copier les localisations liées
for location in intervention.locations.all():
InterventionLocation.objects.get_or_create(
intervention=new_intervention,
content_type=location.content_type,
object_id=location.object_id,
)
# Copier les équipements liés
for asset in intervention.interventionasset_set.all():
InterventionAsset.objects.get_or_create(
intervention=new_intervention,
content_type=asset.content_type,
object_id=asset.object_id,
)
# Copier les liaisons aux projets
for project_link in ProjectIntervention.objects.filter(intervention=intervention):
ProjectIntervention.objects.create(
intervention=new_intervention,
project=project_link.project,
phase=project_link.phase,
row_number=project_link.row_number,
)
# Copier les opérations (avec statut réinitialisé)
for op in intervention.operations.all():
Operation.objects.create(
intervention=new_intervention,
name_fr=op.name_fr,
name_nl=op.name_nl,
comment='',
status_set=op.status_set,
status=None,
measurement_definition=op.measurement_definition,
measured_value=None,
measured_duration=None,
measured_datetime=None,
is_not_applicable=False,
order=op.order,
template_group=op.template_group,
asset_content_type=op.asset_content_type,
asset_object_id=op.asset_object_id,
is_custom=op.is_custom,
is_generic=op.is_generic,
requires_photo=op.requires_photo,
)
# Copier uniquement les notes de type 'origine'
origin_notes = intervention.notes.filter(note_type=InterventionNote.NoteType.ORIGIN)
for note in origin_notes:
InterventionNote.objects.create(
intervention=new_intervention,
content=note.content,
note_time=note.note_time,
note_type=note.note_type,
note_author=note.note_author or request.user,
)
# Copier les documents
for doc in intervention.documents.all():
if doc.file:
try:
doc.file.open('rb')
InterventionDocument.objects.create(
intervention=new_intervention,
file=ContentFile(doc.file.read(), name=os.path.basename(doc.file.name)),
uploaded_by=doc.uploaded_by or request.user,
description=doc.description,
)
except Exception:
pass
finally:
try:
doc.file.close()
except Exception:
pass
# Relier automatiquement à l'intervention précédente
InterventionLink.link(intervention, new_intervention, InterventionLink.LinkType.RELATED)
# Timeline de création
InterventionTimeLine.objects.create(
intervention=new_intervention,
event_user=request.user,
event_time=now(),
event_type='creation',
from_status=None,
to_status=new_intervention.status,
)
messages.success(
request,
_("L'intervention %(code)s a été dupliquée avec succès à partir de %(origin)s.") % {
'code': new_intervention.code,
'origin': intervention.code,
}
)
if variant == 'mobile':
return redirect('mobile:intervention_detail_mobile', intervention_id=new_intervention.id)
return redirect('interventions:intervention_detail', intervention_id=new_intervention.id)
def add_repair_intervention_modal(request):
"""
Vue AJAX pour créer une intervention de réparation via modale desktop.
@ -1678,6 +1878,7 @@ def interventions_add(request, thematic_code):
intervention.equipment_operation_templates.add(*templates)
_assign_guided_template(intervention, templates)
_assign_team_from_templates(intervention, templates)
_assign_contract_posts_from_templates(intervention, templates)
_add_operations_from_templates(intervention, templates, only_generic=True)
if asset_pairs:
resolved_assets = _resolve_assets_from_pairs(asset_pairs)
@ -1694,6 +1895,8 @@ def interventions_add(request, thematic_code):
)
if resolved_contract:
intervention.contract = resolved_contract
if inspection_config and templates:
_assign_contract_posts_from_templates(intervention, templates)
if resolved_provider and not intervention.assigned_provider:
intervention.assigned_provider = resolved_provider
if resolved_contract or resolved_provider:
@ -1995,10 +2198,12 @@ def intervention_link_order(request, intervention_id):
intervention = Intervention.objects.get(pk=intervention_id)
allowed_update_fields = get_allowed_update_fields(request.user, intervention)
if data['order_id'] == '':
if not data.get('order_id'):
intervention.order = None
else:
intervention.order = ContractOrder.objects.get(pk=data['order_id'])
if intervention.order and not intervention.contract:
intervention.contract = intervention.order.contract
intervention.save()
quote_items = []
@ -2034,12 +2239,15 @@ def intervention_link_order(request, intervention_id):
quote_total = format_decimal(intervention.order.get_quote_total_amount())
active_contract = intervention.contract or (intervention.order.contract if intervention.order else None)
return JsonResponse({
'success': True,
'contract_id': intervention.order.contract.id if intervention.order else None,
'contract_id': active_contract.id if active_contract else None,
'contract_posts_count': active_contract.posts.count() if active_contract else 0,
'quote_items': quote_items,
'quote_total': quote_total,
'can_manage_posts': 'posts' in allowed_update_fields,
'order_display': f"{intervention.order.contract.contract_number} - {intervention.order.order_code}" if intervention.order else None,
})
except (Intervention.DoesNotExist, ContractOrder.DoesNotExist) as e:
return JsonResponse({'success': False, 'message': str(e)})

View file

@ -8,7 +8,7 @@ import bleach
import json
import re
from interventions.models import Intervention, InterventionNote, InterventionDocument, Symptom, OperationTemplate, InterventionOccupation, SourceCategory, OperationStatusSet, MeasurementDefinition, TYPE_CHOICES
from interventions.models import Intervention, InterventionNote, InterventionDocument, Symptom, OperationTemplate, InterventionOccupation, SourceCategory, OperationStatusSet, MeasurementDefinition, TYPE_CHOICES, get_type_choices
from assets.models import AssetCategory
from common.models import UserConfig, UserThematics
from contracts.models import Contract, ContractOrder, CompanyMember
@ -93,6 +93,11 @@ class InterventionForm(forms.ModelForm):
(val, lbl) for val, lbl in self.fields['status'].choices if val in allowed_statuses
]
# Filtrer les types selon la thématique (ex: reprogrammation uniquement pour trafficlights)
thematic_obj = thematic or (self.instance.thematic if self.instance and getattr(self.instance, 'pk', None) else None)
if 'type' in self.fields:
self.fields['type'].choices = get_type_choices(thematic_obj)
type_value = self.initial.get('type') or self.data.get('type')
maintain_type_value = self.initial.get('maintain_type') or self.data.get('maintain_type')
if type_value == 'inspection':
@ -515,6 +520,9 @@ class PreventiveInterventionForm(forms.Form):
def __init__(self, *args, user=None, thematic=None, **kwargs):
super().__init__(*args, **kwargs)
if 'type' in self.fields:
self.fields['type'].choices = get_type_choices(thematic)
type_value = self.initial.get('type') or (self.data.get('type') if self.data else None) or 'care'
if type_value == 'inspection':
self.fields['status'].choices = [

View file

@ -549,6 +549,27 @@ def interventions_geojson(request):
if followed_only == '1' and request.user.is_authenticated:
qs = qs.filter(subscriptions__user=request.user)
is_external = request.GET.get('is_external') or request.GET.get('external')
if is_external in ('1', 'true', 'True'):
user_company_ids = set()
user_config_obj = UserConfig.objects.filter(user=request.user).first()
if user_config_obj and user_config_obj.company_id:
user_company_ids.add(user_config_obj.company_id)
user_company_ids.update(Company.objects.filter(teams__members__user=request.user).values_list('id', flat=True))
if user_company_ids:
external_q = (
(Q(assigned_provider__isnull=False) & ~Q(assigned_provider_id__in=user_company_ids)) |
(Q(contract__company__isnull=False) & ~Q(contract__company_id__in=user_company_ids)) |
(Q(assigned_team__company__isnull=False) & ~Q(assigned_team__company_id__in=user_company_ids))
)
else:
external_q = (
Q(assigned_provider__isnull=False) |
Q(contract__company__isnull=False) |
Q(assigned_team__company__isnull=False)
)
qs = qs.filter(external_q).distinct()
# --- annotate preparation status
qs = annotate_preparation_status(qs)
if preparation_states:
@ -1279,3 +1300,66 @@ def ajax_get_replacement_models_by_category(request):
except Exception as e:
return JsonResponse({'error': str(e)}, status=400)
def ajax_get_posts_by_contract(request):
"""AJAX endpoint to get contract posts for a given contract.
Used by Django Admin to dynamically filter contract posts based on selected contract.
"""
contract_id = request.GET.get('contract_id')
if not contract_id:
return JsonResponse({'posts': []})
try:
from contracts.models import ContractPost
posts = ContractPost.objects.filter(contract_id=contract_id).order_by('order_number')
lang = get_language()
posts_data = []
for post in posts:
desc = post.description_fr
if lang and lang.startswith('nl') and post.description_nl:
desc = post.description_nl
label_parts = []
if post.order_number:
label_parts.append(str(post.order_number))
if post.code:
label_parts.append(str(post.code))
if desc:
label_parts.append(desc)
label = " - ".join(label_parts) if label_parts else f"Poste #{post.id}"
posts_data.append({
'id': post.id,
'code': post.code,
'order_number': post.order_number,
'description': desc,
'label': label,
})
return JsonResponse({'posts': posts_data})
except Exception as e:
return JsonResponse({'error': str(e)}, status=400)
def ajax_get_contracts_by_thematic(request):
"""AJAX endpoint to get contracts for a given thematic.
Used by Django Admin to dynamically filter contracts based on selected thematic.
"""
thematic_id = request.GET.get('thematic_id')
try:
from contracts.models import Contract
if thematic_id:
contracts = Contract.objects.filter(thematics__id=thematic_id).distinct().select_related('company').order_by('contract_number')
else:
contracts = Contract.objects.all().select_related('company').order_by('contract_number')
contracts_data = [
{
'id': c.id,
'contract_number': c.contract_number,
'description': c.description or '',
'label': f"{c.contract_number} ({c.company.name})" if c.company else c.contract_number,
}
for c in contracts
]
return JsonResponse({'contracts': contracts_data})
except Exception as e:
return JsonResponse({'error': str(e)}, status=400)

View file

@ -60,9 +60,10 @@ from interventions.models import (InterventionSubscription, Intervention, Interv
InterventionOccupation,
Operation, OperationTemplate, OperationTemplateItem, OperationStatus, OperationStatusSet, MeasurementDefinition,
GuidedOperationTemplate, GuidedOperationData, GuidedOperationMedia,
ContractOperationTemplatePost,
InterventionPostPeriodQuantity, InterventionEmailLog, InterventionAssignment,
DirectContractRouting)
from interventions.models import STATUS_CHOICES, STATUS_ORDERS, MAINTAIN_CHOICES, TYPE_CHOICES, ORIGIN_TYPE_CHOICES, PAUSE_REASON_CHOICES
from interventions.models import STATUS_CHOICES, STATUS_ORDERS, MAINTAIN_CHOICES, TYPE_CHOICES, ORIGIN_TYPE_CHOICES, PAUSE_REASON_CHOICES, get_type_choices
from interventions.views.forms import (InterventionForm, InterventionNoteForm, InterventionDocumentForm,
InterventionOccupationForm, PreventiveInterventionForm, AssetsLinkForm,
LinkExistingInterventionsForm)
@ -145,6 +146,7 @@ __all__ = [
'_apply_realization_side_effects',
'_asset_matches_filters',
'_asset_matches_template_filters',
'_assign_contract_posts_from_templates',
'_assign_guided_template',
'_assign_team_from_templates',
'_attach_equipment_templates',
@ -1123,6 +1125,49 @@ def _assign_team_from_templates(intervention, templates):
def _assign_contract_posts_from_templates(intervention, templates):
"""
Associe les postes de contrat par défaut configurés pour les OperationTemplates donnés
sur le contrat de l'intervention.
Si plusieurs templates ont des postes en doublon, le premier trouvé est conservé.
"""
if not templates:
return
contract = intervention.contract or (intervention.order.contract if intervention.order else None)
if not contract:
return
existing_post_ids = set(
intervention.interv_contract_posts.values_list('contract_post_id', flat=True)
)
posts_to_create = []
for template in templates:
template_posts = (
ContractOperationTemplatePost.objects
.filter(contract=contract, operation_template=template)
.select_related('contract_post')
.order_by('contract_post__order_number', 'id')
)
for tp in template_posts:
if tp.contract_post_id not in existing_post_ids:
posts_to_create.append(
InterventionContractPost(
intervention=intervention,
contract_post=tp.contract_post,
quantity=tp.default_quantity,
comment=tp.comment or '',
)
)
existing_post_ids.add(tp.contract_post_id)
if posts_to_create:
InterventionContractPost.objects.bulk_create(posts_to_create)
def _get_equipment_templates_for_intervention(intervention):
templates = list(intervention.equipment_operation_templates.all())
if templates:
@ -2495,6 +2540,8 @@ def _update_intervention_field(intervention, field, new_value, user_config=None)
if not has_access:
return False, _('You do not have access to this contract')
intervention.contract = contract
if contract.company and intervention.assigned_provider != contract.company:
intervention.assigned_provider = contract.company
return True, None
return False, _('Contract not found')
@ -2505,7 +2552,8 @@ def _update_intervention_field(intervention, field, new_value, user_config=None)
return False, _('Maintain Type not found')
elif field == "type":
if new_value in dict(TYPE_CHOICES).keys():
allowed_types = dict(get_type_choices(intervention.thematic)).keys()
if new_value in allowed_types:
intervention.type = new_value
return True, None
return False, _('Type not found')

View file

@ -74,7 +74,7 @@ from interventions.permissions import (intervention_permission_required, interve
can_view_intervention_summary,
get_accessible_interventions_for_technician, filter_viewable_interventions_for_user,
can_edit_note, can_delete_document, can_manage_occupations,
can_add_intervention, can_add_repair_intervention,
can_add_intervention, can_add_repair_intervention, can_duplicate_intervention,
intervention_manage_occupations_required,
get_contracts_for_intervention_creation, is_external_manager_with_contract_creation_rights,
should_show_created_by_provider_badge, can_view_correction_messages)
@ -1043,7 +1043,7 @@ def intervention_detail_mobile(request, intervention_id):
linked_observations = []
obs_access_context = get_observation_access_context(request.user, user_config=user_config)
if obs_access_context:
all_observations = intervention.observations.select_related('thematic', 'category').order_by('-created_at')
all_observations = intervention.get_associated_observations().select_related('thematic', 'category')
linked_observations = [obs for obs in all_observations if obs_access_context.allows(obs)]
# Discussion liée à cette intervention (mobile)
@ -1091,6 +1091,7 @@ def intervention_detail_mobile(request, intervention_id):
'pause_reason_choices': PAUSE_REASON_CHOICES,
'linked_groups': linked_groups,
'can_create_repair': can_create_repair,
'can_duplicate_intervention': can_duplicate_intervention(request.user, intervention),
'mobile_assets_enabled': can_edit_mobile,
'mobile_assets_config': mobile_assets_config,
'mobile_asset_location_labels': mobile_asset_location_labels,

View file

@ -449,6 +449,7 @@ def intervention_add_preventive(request, thematic_code):
_attach_equipment_templates(intervention, operation_templates)
_assign_guided_template(intervention, operation_templates)
_assign_team_from_templates(intervention, operation_templates)
_assign_contract_posts_from_templates(intervention, operation_templates)
# 1) Lien générique intervention ↔ localisation
ct = ContentType.objects.get_for_model(loc.__class__)
@ -576,6 +577,7 @@ def intervention_add_preventive(request, thematic_code):
_attach_equipment_templates(intervention, operation_templates)
_assign_guided_template(intervention, operation_templates)
_assign_team_from_templates(intervention, operation_templates)
_assign_contract_posts_from_templates(intervention, operation_templates)
# 1) Lien générique Asset ↔ Intervention
InterventionAsset.objects.get_or_create(
@ -647,6 +649,7 @@ def intervention_add_preventive(request, thematic_code):
_attach_equipment_templates(intervention, operation_templates)
_assign_guided_template(intervention, operation_templates)
_assign_team_from_templates(intervention, operation_templates)
_assign_contract_posts_from_templates(intervention, operation_templates)
# Utiliser le titre de base
intervention.title = title

View file

@ -486,8 +486,9 @@ def process_worksheet(
# Lien template d'opérations
intervention.equipment_operation_templates.add(template)
from interventions.views.helpers import _assign_team_from_templates
from interventions.views.helpers import _assign_team_from_templates, _assign_contract_posts_from_templates
_assign_team_from_templates(intervention, [template])
_assign_contract_posts_from_templates(intervention, [template])
# Timelines
InterventionTimeLine.objects.create(

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -5,7 +5,7 @@ msgid ""
msgstr ""
"Project-Id-Version: streetup\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: 2025-01-01 00:00+0000\n"
"Last-Translator: \n"
"Language-Team: English\n"
@ -15,11 +15,11 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: loko/maps/admin.py:18 loko/maps/templates/maps/index.html:224
#: maps/admin.py:18 maps/templates/maps/index.html:224
msgid "Accès restreint"
msgstr "Restricted access"
#: loko/maps/admin.py:21
#: maps/admin.py:21
msgid ""
"Ces champs ne s'appliquent que pour le niveau d'accès « Accès restreint ». "
"L'accès est accordé si l'utilisateur satisfait au moins une des conditions "
@ -30,45 +30,44 @@ msgstr ""
"granted if the user satisfies at least one condition (theme OR team OR "
"specific user). Administrators always have access."
#: loko/maps/models.py:24
#: maps/models.py:24
msgid "Tout public (sans connexion)"
msgstr "Public (no login)"
#: loko/maps/models.py:25
#: maps/models.py:25
msgid "Toute personne connectée"
msgstr "Any logged in person"
#: loko/maps/models.py:26
#: maps/models.py:26
msgid "Accès restreint (thématiques / équipes / utilisateurs)"
msgstr "Restricted access (themes / teams / users)"
#: loko/maps/models.py:32
#: loko/maps/templates/maps/concrete_blocks/index.html:477
#: loko/maps/views.py:701
#: maps/models.py:32 maps/templates/maps/concrete_blocks/index.html:477
#: maps/views.py:701
msgid "Code"
msgstr "Code"
#: loko/maps/models.py:33
#: maps/models.py:33
msgid "Identifiant technique de la carte (ex: concrete_blocks)."
msgstr "Technical map identifier (e.g. concrete_blocks)."
#: loko/maps/models.py:35
#: maps/models.py:35
msgid "Nom (FR)"
msgstr "Name (FR)"
#: loko/maps/models.py:36
#: maps/models.py:36
msgid "Naam (NL)"
msgstr "Name (NL)"
#: loko/maps/models.py:42
#: maps/models.py:42
msgid "Niveau d'accès"
msgstr "Access level"
#: loko/maps/models.py:51
#: maps/models.py:51
msgid "Thématiques autorisées"
msgstr "Authorized themes"
#: loko/maps/models.py:53
#: maps/models.py:53
msgid ""
"Les utilisateurs ayant accès à l'une de ces thématiques peuvent visualiser "
"la carte (niveau 'restreint' uniquement)."
@ -76,440 +75,438 @@ msgstr ""
"Users with access to one of these themes can view the map (restricted level "
"only)."
#: loko/maps/models.py:62
#: maps/models.py:62
msgid "Équipes autorisées"
msgstr "Authorized teams"
#: loko/maps/models.py:64
#: maps/models.py:64
msgid ""
"Les membres de ces équipes peuvent visualiser la carte (niveau 'restreint' "
"uniquement)."
msgstr "Members of these teams can view the map (restricted level only)."
#: loko/maps/models.py:73
#: maps/models.py:73
msgid "Utilisateurs autorisés"
msgstr "Authorized users"
#: loko/maps/models.py:75
#: maps/models.py:75
msgid ""
"Ces utilisateurs spécifiques peuvent visualiser la carte (niveau 'restreint' "
"uniquement)."
msgstr "These specific users can view the map (restricted level only)."
#: loko/maps/models.py:83
#: maps/models.py:83
msgid "Configuration d'accès à une carte"
msgstr "Map access configuration"
#: loko/maps/models.py:84
#: maps/models.py:84
msgid "Configurations d'accès aux cartes"
msgstr "Map access configurations"
#: loko/maps/templates/maps/base.html:6 loko/maps/templates/maps/base.html:7
#: loko/maps/templates/maps/index.html:185
#: maps/templates/maps/base.html:6 maps/templates/maps/base.html:7
#: maps/templates/maps/index.html:185
msgid "Cartes"
msgstr "Cards"
# template – tabs
#: loko/maps/templates/maps/concrete_blocks/index.html:23
#: maps/templates/maps/concrete_blocks/index.html:23
msgid "Légende"
msgstr "Legend"
#: loko/maps/templates/maps/concrete_blocks/index.html:30
#: loko/maps/templates/maps/concrete_blocks/index.html:127
#: maps/templates/maps/concrete_blocks/index.html:30
#: maps/templates/maps/concrete_blocks/index.html:127
msgid "Filtres"
msgstr "Filters"
#: loko/maps/templates/maps/concrete_blocks/index.html:37
#: maps/templates/maps/concrete_blocks/index.html:37
msgid "Détail"
msgstr "Detail"
#: loko/maps/templates/maps/concrete_blocks/index.html:44
#: maps/templates/maps/concrete_blocks/index.html:44
msgid "Projets"
msgstr "Projects"
#: loko/maps/templates/maps/concrete_blocks/index.html:52
#: maps/templates/maps/concrete_blocks/index.html:52
msgid "Édition"
msgstr "Edit"
# template – legend panel
#: loko/maps/templates/maps/concrete_blocks/index.html:64
#: maps/templates/maps/concrete_blocks/index.html:64
msgid "Représentation des couleurs"
msgstr "Colour representation"
#: loko/maps/templates/maps/concrete_blocks/index.html:66
#: maps/templates/maps/concrete_blocks/index.html:66
msgid "Par fonction"
msgstr "By function"
#: loko/maps/templates/maps/concrete_blocks/index.html:72
#: loko/maps/templates/maps/concrete_blocks/index.html:156
#: maps/templates/maps/concrete_blocks/index.html:72
#: maps/templates/maps/concrete_blocks/index.html:156
msgid "Nombre de blocs"
msgstr "Number of blocks"
#: loko/maps/templates/maps/concrete_blocks/index.html:78
#: maps/templates/maps/concrete_blocks/index.html:78
msgid "< 3 blocs"
msgstr "≤ 3 blocks"
#: loko/maps/templates/maps/concrete_blocks/index.html:85
#: maps/templates/maps/concrete_blocks/index.html:85
msgid "3 – 10 blocs"
msgstr "4 – 10 blocks"
#: loko/maps/templates/maps/concrete_blocks/index.html:93
#: maps/templates/maps/concrete_blocks/index.html:93
msgid "> 10 blocs"
msgstr "> 10 blocks"
#: loko/maps/templates/maps/concrete_blocks/index.html:108
#: loko/maps/views.py:662
#: maps/templates/maps/concrete_blocks/index.html:108 maps/views.py:662
msgid "Projets New-Jersey"
msgstr "New-Jersey Projects"
#: loko/maps/templates/maps/concrete_blocks/index.html:118
#: maps/templates/maps/concrete_blocks/index.html:118
msgid "Exporter en CSV"
msgstr "Export to CSV"
# template – filters panel
#: loko/maps/templates/maps/concrete_blocks/index.html:130
#: maps/templates/maps/concrete_blocks/index.html:130
msgid "Fonction"
msgstr "Function"
#: loko/maps/templates/maps/concrete_blocks/index.html:145
#: loko/maps/templates/maps/concrete_blocks/index.html:225
#: loko/maps/templates/maps/concrete_blocks/index.html:313
#: loko/maps/templates/maps/concrete_blocks/index.html:422
#: loko/maps/views.py:704
#: maps/templates/maps/concrete_blocks/index.html:145
#: maps/templates/maps/concrete_blocks/index.html:225
#: maps/templates/maps/concrete_blocks/index.html:313
#: maps/templates/maps/concrete_blocks/index.html:422 maps/views.py:704
msgid "Statut"
msgstr "Status"
#: loko/maps/templates/maps/concrete_blocks/index.html:159
#: loko/maps/templates/maps/concrete_blocks/index.html:170
#: maps/templates/maps/concrete_blocks/index.html:159
#: maps/templates/maps/concrete_blocks/index.html:170
msgid "Min"
msgstr "Min"
#: loko/maps/templates/maps/concrete_blocks/index.html:162
#: loko/maps/templates/maps/concrete_blocks/index.html:173
#: maps/templates/maps/concrete_blocks/index.html:162
#: maps/templates/maps/concrete_blocks/index.html:173
msgid "Max"
msgstr "Max"
#: loko/maps/templates/maps/concrete_blocks/index.html:167
#: loko/maps/templates/maps/concrete_blocks/index.html:362
#: loko/maps/templates/maps/concrete_blocks/index.html:450
#: loko/maps/templates/maps/concrete_blocks/index.html:528
#: maps/templates/maps/concrete_blocks/index.html:167
#: maps/templates/maps/concrete_blocks/index.html:362
#: maps/templates/maps/concrete_blocks/index.html:450
#: maps/templates/maps/concrete_blocks/index.html:528
msgid "Priorité"
msgstr "Priority"
#: loko/maps/templates/maps/concrete_blocks/index.html:178
#: loko/maps/templates/maps/concrete_blocks/index.html:352
#: loko/maps/templates/maps/concrete_blocks/index.html:440
#: loko/maps/templates/maps/concrete_blocks/index.html:518
#: maps/templates/maps/concrete_blocks/index.html:178
#: maps/templates/maps/concrete_blocks/index.html:352
#: maps/templates/maps/concrete_blocks/index.html:440
#: maps/templates/maps/concrete_blocks/index.html:518
msgid "Action recommandée"
msgstr "Recommended action"
#: loko/maps/templates/maps/concrete_blocks/index.html:190
#: maps/templates/maps/concrete_blocks/index.html:190
msgid "Appliquer"
msgstr "Apply"
#: loko/maps/templates/maps/concrete_blocks/index.html:193
#: maps/templates/maps/concrete_blocks/index.html:193
msgid "Réinitialiser"
msgstr "Reset"
#: loko/maps/templates/maps/concrete_blocks/index.html:202
#: maps/templates/maps/concrete_blocks/index.html:202
msgid "Détail du set de blocs"
msgstr "Block set detail"
#: loko/maps/templates/maps/concrete_blocks/index.html:206
#: maps/templates/maps/concrete_blocks/index.html:206
msgid "Cliquez sur un point de la carte pour voir les détails."
msgstr "Click on a map point to view the details."
#: loko/maps/templates/maps/concrete_blocks/index.html:221
#: maps/templates/maps/concrete_blocks/index.html:221
msgid "N° projet, PMO, Osiris, description…"
msgstr "Project No., PMO, Osiris, description…"
#: loko/maps/templates/maps/concrete_blocks/index.html:230
#: maps/templates/maps/concrete_blocks/index.html:230
msgid "Période"
msgstr "Period"
#: loko/maps/templates/maps/concrete_blocks/index.html:233
#: maps/templates/maps/concrete_blocks/index.html:233
msgid "Début à partir du"
msgstr "Start from"
#: loko/maps/templates/maps/concrete_blocks/index.html:236
#: maps/templates/maps/concrete_blocks/index.html:236
msgid "Fin avant le"
msgstr "End before"
#: loko/maps/templates/maps/concrete_blocks/index.html:245
#: maps/templates/maps/concrete_blocks/index.html:245
msgid "Cliquez sur l'onglet pour charger les projets."
msgstr "Click on a map point to view the details."
#: loko/maps/templates/maps/concrete_blocks/index.html:253
#: maps/templates/maps/concrete_blocks/index.html:253
msgid "Exporter en Excel"
msgstr "Export to Excel"
#: loko/maps/templates/maps/concrete_blocks/index.html:269
#: maps/templates/maps/concrete_blocks/index.html:269
msgid "Ajouter"
msgstr "Add"
#: loko/maps/templates/maps/concrete_blocks/index.html:274
#: maps/templates/maps/concrete_blocks/index.html:274
msgid "Activer la sélection multiple"
msgstr "Enable multi-select"
#: loko/maps/templates/maps/concrete_blocks/index.html:275
#: maps/templates/maps/concrete_blocks/index.html:275
msgid "Multi-sélection"
msgstr "Multi-select"
#: loko/maps/templates/maps/concrete_blocks/index.html:281
#: maps/templates/maps/concrete_blocks/index.html:281
msgid "asset(s) sélectionné(s)"
msgstr "selected asset(s)"
#: loko/maps/templates/maps/concrete_blocks/index.html:284
#: maps/templates/maps/concrete_blocks/index.html:284
msgid "Tout désélectionner"
msgstr "Deselect all"
#: loko/maps/templates/maps/concrete_blocks/index.html:292
#: maps/templates/maps/concrete_blocks/index.html:292
msgid ""
"Cliquez sur un asset de la carte pour l'éditer, ou activez la multi-"
"sélection."
msgstr "Click on a map asset to edit it, or enable multi-select."
#: loko/maps/templates/maps/concrete_blocks/index.html:298
#: maps/templates/maps/concrete_blocks/index.html:298
msgid "Modifier l'asset"
msgstr "Edit asset"
#: loko/maps/templates/maps/concrete_blocks/index.html:301
#: maps/templates/maps/concrete_blocks/index.html:301
msgid "Archiver cet asset"
msgstr "Archive this asset"
#: loko/maps/templates/maps/concrete_blocks/index.html:309
#: loko/maps/templates/maps/concrete_blocks/index.html:483
#: maps/templates/maps/concrete_blocks/index.html:309
#: maps/templates/maps/concrete_blocks/index.html:483
msgid "Adresse"
msgstr "Address"
#: loko/maps/templates/maps/concrete_blocks/index.html:321
#: loko/maps/templates/maps/concrete_blocks/index.html:431
#: loko/maps/templates/maps/concrete_blocks/index.html:487
#: maps/templates/maps/concrete_blocks/index.html:321
#: maps/templates/maps/concrete_blocks/index.html:431
#: maps/templates/maps/concrete_blocks/index.html:487
msgid "Fonction principale"
msgstr "Main function"
#: loko/maps/templates/maps/concrete_blocks/index.html:330
#: loko/maps/templates/maps/concrete_blocks/index.html:496
#: maps/templates/maps/concrete_blocks/index.html:330
#: maps/templates/maps/concrete_blocks/index.html:496
msgid "Fonctions secondaires"
msgstr "Secondary functions"
#: loko/maps/templates/maps/concrete_blocks/index.html:343
#: loko/maps/templates/maps/concrete_blocks/index.html:509
#: maps/templates/maps/concrete_blocks/index.html:343
#: maps/templates/maps/concrete_blocks/index.html:509
msgid "Nb. blocs"
msgstr "Number of blocks"
#: loko/maps/templates/maps/concrete_blocks/index.html:347
#: loko/maps/templates/maps/concrete_blocks/index.html:513
#: maps/templates/maps/concrete_blocks/index.html:347
#: maps/templates/maps/concrete_blocks/index.html:513
msgid "Longueur (m)"
msgstr "Length (m)"
#: loko/maps/templates/maps/concrete_blocks/index.html:366
#: loko/maps/templates/maps/concrete_blocks/index.html:455
#: loko/maps/templates/maps/concrete_blocks/index.html:532
#: maps/templates/maps/concrete_blocks/index.html:366
#: maps/templates/maps/concrete_blocks/index.html:455
#: maps/templates/maps/concrete_blocks/index.html:532
msgid "Date cible"
msgstr "Target date"
#: loko/maps/templates/maps/concrete_blocks/index.html:371
#: maps/templates/maps/concrete_blocks/index.html:371
msgid "Date d'enlèvement"
msgstr "Removal date"
#: loko/maps/templates/maps/concrete_blocks/index.html:376
#: maps/templates/maps/concrete_blocks/index.html:376
msgid "Observation source"
msgstr "Source observation"
#: loko/maps/templates/maps/concrete_blocks/index.html:383
#: maps/templates/maps/concrete_blocks/index.html:383
msgid "Position (glisser le marqueur)"
msgstr "Position (drag marker)"
#: loko/maps/templates/maps/concrete_blocks/index.html:388
#: loko/maps/templates/maps/concrete_blocks/index.html:544
#: maps/templates/maps/concrete_blocks/index.html:388
#: maps/templates/maps/concrete_blocks/index.html:544
msgid "Lon."
msgstr "Lon."
#: loko/maps/templates/maps/concrete_blocks/index.html:392
#: loko/maps/templates/maps/concrete_blocks/index.html:548
#: maps/templates/maps/concrete_blocks/index.html:392
#: maps/templates/maps/concrete_blocks/index.html:548
msgid "Lat."
msgstr "Lat."
#: loko/maps/templates/maps/concrete_blocks/index.html:398
#: loko/maps/templates/maps/concrete_blocks/index.html:554
#: maps/templates/maps/concrete_blocks/index.html:398
#: maps/templates/maps/concrete_blocks/index.html:554
msgid "Cliquer sur la carte pour positionner"
msgstr "Click on a map point to view the details."
#: loko/maps/templates/maps/concrete_blocks/index.html:404
#: maps/templates/maps/concrete_blocks/index.html:404
msgid "Enregistrer"
msgstr "Save"
#: loko/maps/templates/maps/concrete_blocks/index.html:407
#: loko/maps/templates/maps/concrete_blocks/index.html:464
#: loko/maps/templates/maps/concrete_blocks/index.html:563
#: maps/templates/maps/concrete_blocks/index.html:407
#: maps/templates/maps/concrete_blocks/index.html:464
#: maps/templates/maps/concrete_blocks/index.html:563
msgid "Annuler"
msgstr "Cancel"
#: loko/maps/templates/maps/concrete_blocks/index.html:416
#: maps/templates/maps/concrete_blocks/index.html:416
msgid "Modifier en lot"
msgstr "Bulk edit"
#: loko/maps/templates/maps/concrete_blocks/index.html:418
#: maps/templates/maps/concrete_blocks/index.html:418
msgid ""
"Seuls les champs renseignés seront mis à jour. Les champs vides sont ignorés."
msgstr "Only filled fields will be updated. Empty fields are ignored."
#: loko/maps/templates/maps/concrete_blocks/index.html:424
#: loko/maps/templates/maps/concrete_blocks/index.html:433
#: loko/maps/templates/maps/concrete_blocks/index.html:442
#: maps/templates/maps/concrete_blocks/index.html:424
#: maps/templates/maps/concrete_blocks/index.html:433
#: maps/templates/maps/concrete_blocks/index.html:442
msgid "Ne pas modifier"
msgstr "Do not modify"
#: loko/maps/templates/maps/concrete_blocks/index.html:452
#: maps/templates/maps/concrete_blocks/index.html:452
msgid "Laisser vide"
msgstr "Leave empty"
#: loko/maps/templates/maps/concrete_blocks/index.html:461
#: maps/templates/maps/concrete_blocks/index.html:461
msgid "Appliquer au lot"
msgstr "Apply"
#: loko/maps/templates/maps/concrete_blocks/index.html:473
#: maps/templates/maps/concrete_blocks/index.html:473
msgid "Nouvel asset"
msgstr "New asset"
#: loko/maps/templates/maps/concrete_blocks/index.html:477
#: maps/templates/maps/concrete_blocks/index.html:477
msgid "auto si vide"
msgstr "auto if empty"
#: loko/maps/templates/maps/concrete_blocks/index.html:539
#: maps/templates/maps/concrete_blocks/index.html:539
msgid "Position"
msgstr "Protection"
#: loko/maps/templates/maps/concrete_blocks/index.html:560
#: maps/templates/maps/concrete_blocks/index.html:560
msgid "Créer"
msgstr "Create"
#: loko/maps/templates/maps/concrete_blocks/index.html:580
#: maps/templates/maps/concrete_blocks/index.html:580
msgid "Opération New Jersey"
msgstr "New Jersey Operation"
#: loko/maps/templates/maps/concrete_blocks/index.html:595
#: maps/templates/maps/concrete_blocks/index.html:595
msgid "Fermer"
msgstr "Close"
#: loko/maps/templates/maps/index.html:186
#: maps/templates/maps/index.html:186
msgid "Consultez et gérez les cartes auxquelles vous avez accès."
msgstr "View and manage the maps you have access to."
#: loko/maps/templates/maps/index.html:214
#: maps/templates/maps/index.html:214
msgid "Tout public"
msgstr "All audiences"
#: loko/maps/templates/maps/index.html:219
#: maps/templates/maps/index.html:219
msgid "Accès connecté"
msgstr "Connected access"
#: loko/maps/templates/maps/index.html:231
#: maps/templates/maps/index.html:231
msgid "Ouvrir la carte"
msgstr "Open map"
#: loko/maps/templates/maps/index.html:250
#: maps/templates/maps/index.html:250
msgid "Aucune carte accessible pour votre compte."
msgstr "No card accessible for your account."
#: loko/maps/views.py:44
#: maps/views.py:44
msgid "Vous n'avez pas accès à cette vue."
msgstr "You do not have access to this view."
#: loko/maps/views.py:69
#: maps/views.py:69
msgid "Protection"
msgstr "Protection"
#: loko/maps/views.py:70
#: maps/views.py:70
msgid "Antiterroriste"
msgstr "Antiterrorism"
#: loko/maps/views.py:71
#: maps/views.py:71
msgid "Neutralisation stationnement"
msgstr "Parking restriction"
#: loko/maps/views.py:72
#: maps/views.py:72
msgid "Sécurité routière"
msgstr "Security"
#: loko/maps/views.py:73
#: maps/views.py:73
msgid "Espace public"
msgstr "Public space"
# views.py – function labels
#: loko/maps/views.py:74
#: maps/views.py:74
msgid "Chantier"
msgstr "Works"
#: loko/maps/views.py:75
#: maps/views.py:75
msgid "Non identifié"
msgstr "Unidentified"
#: loko/maps/views.py:76
#: maps/views.py:76
msgid "Autre / Non renseigné"
msgstr "Other / Not specified"
#: loko/maps/views.py:91
#: maps/views.py:91
msgid "Maintenir"
msgstr "Maintain"
#: loko/maps/views.py:92
#: maps/views.py:92
msgid "Enlever"
msgstr "Remove"
#: loko/maps/views.py:93
#: maps/views.py:93
msgid "Remplacer"
msgstr "Replace"
#: loko/maps/views.py:482 loko/maps/views.py:501 loko/maps/views.py:538
#: maps/views.py:482 maps/views.py:501 maps/views.py:538
msgid "Permission refusée"
msgstr "Permission denied"
#: loko/maps/views.py:487 loko/maps/views.py:506 loko/maps/views.py:559
#: maps/views.py:487 maps/views.py:506 maps/views.py:559
msgid "JSON invalide"
msgstr "Invalid JSON"
#: loko/maps/views.py:565
#: maps/views.py:565
msgid "Aucun asset sélectionné"
msgstr "No asset selected"
#: loko/maps/views.py:567
#: maps/views.py:567
msgid "Aucune modification spécifiée"
msgstr "No modification specified"
#: loko/maps/views.py:702
#: maps/views.py:702
msgid "Nom"
msgstr "Name"
#: loko/maps/views.py:703
#: maps/views.py:703
msgid "Description"
msgstr "Description"
#: loko/maps/views.py:705
#: maps/views.py:705
msgid "Numéro PMO"
msgstr "PMO number"
#: loko/maps/views.py:706
#: maps/views.py:706
msgid "Numéro OSIRIS"
msgstr "OSIRIS number"
#: loko/maps/views.py:707
#: maps/views.py:707
msgid "Date de début"
msgstr "Start date"
#: loko/maps/views.py:708
#: maps/views.py:708
msgid "Date de fin"
msgstr "End date"
#: loko/maps/views.py:709
#: maps/views.py:709
msgid "Créé par"
msgstr "Created by"
#: loko/maps/views.py:710
#: maps/views.py:710
msgid "Thématiques"
msgstr "Thematics"
#: loko/maps/views.py:711
#: maps/views.py:711
msgid "Tags"
msgstr "Tags"

View file

@ -5,7 +5,7 @@ msgid ""
msgstr ""
"Project-Id-Version: streetup\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: 2025-01-01 00:00+0000\n"
"Last-Translator: \n"
"Language-Team: French\n"
@ -14,11 +14,11 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: loko/maps/admin.py:18 loko/maps/templates/maps/index.html:224
#: maps/admin.py:18 maps/templates/maps/index.html:224
msgid "Accès restreint"
msgstr "Accès restreint"
#: loko/maps/admin.py:21
#: maps/admin.py:21
msgid ""
"Ces champs ne s'appliquent que pour le niveau d'accès « Accès restreint ». "
"L'accès est accordé si l'utilisateur satisfait au moins une des conditions "
@ -30,45 +30,44 @@ msgstr ""
"(thématique OU équipe OU utilisateur spécifique). Les administrateurs ont "
"toujours accès."
#: loko/maps/models.py:24
#: maps/models.py:24
msgid "Tout public (sans connexion)"
msgstr "Tout public (sans connexion)"
#: loko/maps/models.py:25
#: maps/models.py:25
msgid "Toute personne connectée"
msgstr "Toute personne connectée"
#: loko/maps/models.py:26
#: maps/models.py:26
msgid "Accès restreint (thématiques / équipes / utilisateurs)"
msgstr "Accès restreint (thématiques / équipes / utilisateurs)"
#: loko/maps/models.py:32
#: loko/maps/templates/maps/concrete_blocks/index.html:477
#: loko/maps/views.py:701
#: maps/models.py:32 maps/templates/maps/concrete_blocks/index.html:477
#: maps/views.py:701
msgid "Code"
msgstr "Code"
#: loko/maps/models.py:33
#: maps/models.py:33
msgid "Identifiant technique de la carte (ex: concrete_blocks)."
msgstr "Identifiant technique de la carte (ex: concrete_blocks)."
#: loko/maps/models.py:35
#: maps/models.py:35
msgid "Nom (FR)"
msgstr "Nom (FR)"
#: loko/maps/models.py:36
#: maps/models.py:36
msgid "Naam (NL)"
msgstr "Naam (NL)"
#: loko/maps/models.py:42
#: maps/models.py:42
msgid "Niveau d'accès"
msgstr "Niveau d'accès"
#: loko/maps/models.py:51
#: maps/models.py:51
msgid "Thématiques autorisées"
msgstr "Thématiques autorisées"
#: loko/maps/models.py:53
#: maps/models.py:53
msgid ""
"Les utilisateurs ayant accès à l'une de ces thématiques peuvent visualiser "
"la carte (niveau 'restreint' uniquement)."
@ -76,11 +75,11 @@ msgstr ""
"Les utilisateurs ayant accès à l'une de ces thématiques peuvent visualiser "
"la carte (niveau 'restreint' uniquement)."
#: loko/maps/models.py:62
#: maps/models.py:62
msgid "Équipes autorisées"
msgstr "Équipes autorisées"
#: loko/maps/models.py:64
#: maps/models.py:64
msgid ""
"Les membres de ces équipes peuvent visualiser la carte (niveau 'restreint' "
"uniquement)."
@ -88,11 +87,11 @@ msgstr ""
"Les membres de ces équipes peuvent visualiser la carte (niveau 'restreint' "
"uniquement)."
#: loko/maps/models.py:73
#: maps/models.py:73
msgid "Utilisateurs autorisés"
msgstr "Utilisateurs autorisés"
#: loko/maps/models.py:75
#: maps/models.py:75
msgid ""
"Ces utilisateurs spécifiques peuvent visualiser la carte (niveau 'restreint' "
"uniquement)."
@ -100,174 +99,172 @@ msgstr ""
"Ces utilisateurs spécifiques peuvent visualiser la carte (niveau 'restreint' "
"uniquement)."
#: loko/maps/models.py:83
#: maps/models.py:83
msgid "Configuration d'accès à une carte"
msgstr "Configuration d'accès à une carte"
#: loko/maps/models.py:84
#: maps/models.py:84
msgid "Configurations d'accès aux cartes"
msgstr "Configurations d'accès aux cartes"
#: loko/maps/templates/maps/base.html:6 loko/maps/templates/maps/base.html:7
#: loko/maps/templates/maps/index.html:185
#: maps/templates/maps/base.html:6 maps/templates/maps/base.html:7
#: maps/templates/maps/index.html:185
msgid "Cartes"
msgstr "Cartes"
# template – tabs
#: loko/maps/templates/maps/concrete_blocks/index.html:23
#: maps/templates/maps/concrete_blocks/index.html:23
msgid "Légende"
msgstr "Légende"
#: loko/maps/templates/maps/concrete_blocks/index.html:30
#: loko/maps/templates/maps/concrete_blocks/index.html:127
#: maps/templates/maps/concrete_blocks/index.html:30
#: maps/templates/maps/concrete_blocks/index.html:127
msgid "Filtres"
msgstr "Filtres"
#: loko/maps/templates/maps/concrete_blocks/index.html:37
#: maps/templates/maps/concrete_blocks/index.html:37
msgid "Détail"
msgstr "Détail"
#: loko/maps/templates/maps/concrete_blocks/index.html:44
#: maps/templates/maps/concrete_blocks/index.html:44
msgid "Projets"
msgstr "Projets"
#: loko/maps/templates/maps/concrete_blocks/index.html:52
#: maps/templates/maps/concrete_blocks/index.html:52
msgid "Édition"
msgstr "Édition"
# template – legend panel
#: loko/maps/templates/maps/concrete_blocks/index.html:64
#: maps/templates/maps/concrete_blocks/index.html:64
msgid "Représentation des couleurs"
msgstr "Représentation des couleurs"
#: loko/maps/templates/maps/concrete_blocks/index.html:66
#: maps/templates/maps/concrete_blocks/index.html:66
msgid "Par fonction"
msgstr "Par fonction"
#: loko/maps/templates/maps/concrete_blocks/index.html:72
#: loko/maps/templates/maps/concrete_blocks/index.html:156
#: maps/templates/maps/concrete_blocks/index.html:72
#: maps/templates/maps/concrete_blocks/index.html:156
msgid "Nombre de blocs"
msgstr "Nombre de blocs"
#: loko/maps/templates/maps/concrete_blocks/index.html:78
#: maps/templates/maps/concrete_blocks/index.html:78
msgid "< 3 blocs"
msgstr "< 3 blocs"
#: loko/maps/templates/maps/concrete_blocks/index.html:85
#: maps/templates/maps/concrete_blocks/index.html:85
msgid "3 – 10 blocs"
msgstr "3 – 10 blocs"
#: loko/maps/templates/maps/concrete_blocks/index.html:93
#: maps/templates/maps/concrete_blocks/index.html:93
msgid "> 10 blocs"
msgstr "> 10 blocs"
#: loko/maps/templates/maps/concrete_blocks/index.html:108
#: loko/maps/views.py:662
#: maps/templates/maps/concrete_blocks/index.html:108 maps/views.py:662
msgid "Projets New-Jersey"
msgstr "Projets New-Jersey"
#: loko/maps/templates/maps/concrete_blocks/index.html:118
#: maps/templates/maps/concrete_blocks/index.html:118
msgid "Exporter en CSV"
msgstr "Exporter en CSV"
# template – filters panel
#: loko/maps/templates/maps/concrete_blocks/index.html:130
#: maps/templates/maps/concrete_blocks/index.html:130
msgid "Fonction"
msgstr "Fonction"
#: loko/maps/templates/maps/concrete_blocks/index.html:145
#: loko/maps/templates/maps/concrete_blocks/index.html:225
#: loko/maps/templates/maps/concrete_blocks/index.html:313
#: loko/maps/templates/maps/concrete_blocks/index.html:422
#: loko/maps/views.py:704
#: maps/templates/maps/concrete_blocks/index.html:145
#: maps/templates/maps/concrete_blocks/index.html:225
#: maps/templates/maps/concrete_blocks/index.html:313
#: maps/templates/maps/concrete_blocks/index.html:422 maps/views.py:704
msgid "Statut"
msgstr "Statut"
#: loko/maps/templates/maps/concrete_blocks/index.html:159
#: loko/maps/templates/maps/concrete_blocks/index.html:170
#: maps/templates/maps/concrete_blocks/index.html:159
#: maps/templates/maps/concrete_blocks/index.html:170
msgid "Min"
msgstr "Min"
#: loko/maps/templates/maps/concrete_blocks/index.html:162
#: loko/maps/templates/maps/concrete_blocks/index.html:173
#: maps/templates/maps/concrete_blocks/index.html:162
#: maps/templates/maps/concrete_blocks/index.html:173
msgid "Max"
msgstr "Max"
#: loko/maps/templates/maps/concrete_blocks/index.html:167
#: loko/maps/templates/maps/concrete_blocks/index.html:362
#: loko/maps/templates/maps/concrete_blocks/index.html:450
#: loko/maps/templates/maps/concrete_blocks/index.html:528
#: maps/templates/maps/concrete_blocks/index.html:167
#: maps/templates/maps/concrete_blocks/index.html:362
#: maps/templates/maps/concrete_blocks/index.html:450
#: maps/templates/maps/concrete_blocks/index.html:528
msgid "Priorité"
msgstr "Priorité"
#: loko/maps/templates/maps/concrete_blocks/index.html:178
#: loko/maps/templates/maps/concrete_blocks/index.html:352
#: loko/maps/templates/maps/concrete_blocks/index.html:440
#: loko/maps/templates/maps/concrete_blocks/index.html:518
#: maps/templates/maps/concrete_blocks/index.html:178
#: maps/templates/maps/concrete_blocks/index.html:352
#: maps/templates/maps/concrete_blocks/index.html:440
#: maps/templates/maps/concrete_blocks/index.html:518
msgid "Action recommandée"
msgstr "Action recommandée"
#: loko/maps/templates/maps/concrete_blocks/index.html:190
#: maps/templates/maps/concrete_blocks/index.html:190
msgid "Appliquer"
msgstr "Appliquer"
#: loko/maps/templates/maps/concrete_blocks/index.html:193
#: maps/templates/maps/concrete_blocks/index.html:193
msgid "Réinitialiser"
msgstr "Réinitialiser"
#: loko/maps/templates/maps/concrete_blocks/index.html:202
#: maps/templates/maps/concrete_blocks/index.html:202
msgid "Détail du set de blocs"
msgstr "Détail du set de blocs"
#: loko/maps/templates/maps/concrete_blocks/index.html:206
#: maps/templates/maps/concrete_blocks/index.html:206
msgid "Cliquez sur un point de la carte pour voir les détails."
msgstr "Cliquez sur un point de la carte pour voir les détails."
#: loko/maps/templates/maps/concrete_blocks/index.html:221
#: maps/templates/maps/concrete_blocks/index.html:221
msgid "N° projet, PMO, Osiris, description…"
msgstr "N° projet, PMO, Osiris, description…"
#: loko/maps/templates/maps/concrete_blocks/index.html:230
#: maps/templates/maps/concrete_blocks/index.html:230
msgid "Période"
msgstr "Période"
#: loko/maps/templates/maps/concrete_blocks/index.html:233
#: maps/templates/maps/concrete_blocks/index.html:233
msgid "Début à partir du"
msgstr "Début à partir du"
#: loko/maps/templates/maps/concrete_blocks/index.html:236
#: maps/templates/maps/concrete_blocks/index.html:236
msgid "Fin avant le"
msgstr "Fin avant le"
#: loko/maps/templates/maps/concrete_blocks/index.html:245
#: maps/templates/maps/concrete_blocks/index.html:245
msgid "Cliquez sur l'onglet pour charger les projets."
msgstr "Cliquez sur l'onglet pour charger les projets."
#: loko/maps/templates/maps/concrete_blocks/index.html:253
#: maps/templates/maps/concrete_blocks/index.html:253
msgid "Exporter en Excel"
msgstr "Exporter en Excel"
#: loko/maps/templates/maps/concrete_blocks/index.html:269
#: maps/templates/maps/concrete_blocks/index.html:269
msgid "Ajouter"
msgstr "Ajouter"
#: loko/maps/templates/maps/concrete_blocks/index.html:274
#: maps/templates/maps/concrete_blocks/index.html:274
msgid "Activer la sélection multiple"
msgstr "Activer la sélection multiple"
#: loko/maps/templates/maps/concrete_blocks/index.html:275
#: maps/templates/maps/concrete_blocks/index.html:275
msgid "Multi-sélection"
msgstr "Multi-sélection"
#: loko/maps/templates/maps/concrete_blocks/index.html:281
#: maps/templates/maps/concrete_blocks/index.html:281
msgid "asset(s) sélectionné(s)"
msgstr "asset(s) sélectionné(s)"
#: loko/maps/templates/maps/concrete_blocks/index.html:284
#: maps/templates/maps/concrete_blocks/index.html:284
msgid "Tout désélectionner"
msgstr "Tout désélectionner"
#: loko/maps/templates/maps/concrete_blocks/index.html:292
#: maps/templates/maps/concrete_blocks/index.html:292
msgid ""
"Cliquez sur un asset de la carte pour l'éditer, ou activez la multi-"
"sélection."
@ -275,248 +272,248 @@ msgstr ""
"Cliquez sur un asset de la carte pour l'éditer, ou activez la multi-"
"sélection."
#: loko/maps/templates/maps/concrete_blocks/index.html:298
#: maps/templates/maps/concrete_blocks/index.html:298
msgid "Modifier l'asset"
msgstr "Modifier l'asset"
#: loko/maps/templates/maps/concrete_blocks/index.html:301
#: maps/templates/maps/concrete_blocks/index.html:301
msgid "Archiver cet asset"
msgstr "Archiver cet asset"
#: loko/maps/templates/maps/concrete_blocks/index.html:309
#: loko/maps/templates/maps/concrete_blocks/index.html:483
#: maps/templates/maps/concrete_blocks/index.html:309
#: maps/templates/maps/concrete_blocks/index.html:483
msgid "Adresse"
msgstr "Adresse"
#: loko/maps/templates/maps/concrete_blocks/index.html:321
#: loko/maps/templates/maps/concrete_blocks/index.html:431
#: loko/maps/templates/maps/concrete_blocks/index.html:487
#: maps/templates/maps/concrete_blocks/index.html:321
#: maps/templates/maps/concrete_blocks/index.html:431
#: maps/templates/maps/concrete_blocks/index.html:487
msgid "Fonction principale"
msgstr "Fonction principale"
#: loko/maps/templates/maps/concrete_blocks/index.html:330
#: loko/maps/templates/maps/concrete_blocks/index.html:496
#: maps/templates/maps/concrete_blocks/index.html:330
#: maps/templates/maps/concrete_blocks/index.html:496
msgid "Fonctions secondaires"
msgstr "Fonctions secondaires"
#: loko/maps/templates/maps/concrete_blocks/index.html:343
#: loko/maps/templates/maps/concrete_blocks/index.html:509
#: maps/templates/maps/concrete_blocks/index.html:343
#: maps/templates/maps/concrete_blocks/index.html:509
msgid "Nb. blocs"
msgstr "Nb. blocs"
#: loko/maps/templates/maps/concrete_blocks/index.html:347
#: loko/maps/templates/maps/concrete_blocks/index.html:513
#: maps/templates/maps/concrete_blocks/index.html:347
#: maps/templates/maps/concrete_blocks/index.html:513
msgid "Longueur (m)"
msgstr "Longueur (m)"
#: loko/maps/templates/maps/concrete_blocks/index.html:366
#: loko/maps/templates/maps/concrete_blocks/index.html:455
#: loko/maps/templates/maps/concrete_blocks/index.html:532
#: maps/templates/maps/concrete_blocks/index.html:366
#: maps/templates/maps/concrete_blocks/index.html:455
#: maps/templates/maps/concrete_blocks/index.html:532
msgid "Date cible"
msgstr "Date cible"
#: loko/maps/templates/maps/concrete_blocks/index.html:371
#: maps/templates/maps/concrete_blocks/index.html:371
msgid "Date d'enlèvement"
msgstr "Date d'enlèvement"
#: loko/maps/templates/maps/concrete_blocks/index.html:376
#: maps/templates/maps/concrete_blocks/index.html:376
msgid "Observation source"
msgstr "Observation source"
#: loko/maps/templates/maps/concrete_blocks/index.html:383
#: maps/templates/maps/concrete_blocks/index.html:383
msgid "Position (glisser le marqueur)"
msgstr "Position (glisser le marqueur)"
#: loko/maps/templates/maps/concrete_blocks/index.html:388
#: loko/maps/templates/maps/concrete_blocks/index.html:544
#: maps/templates/maps/concrete_blocks/index.html:388
#: maps/templates/maps/concrete_blocks/index.html:544
msgid "Lon."
msgstr "Lon."
#: loko/maps/templates/maps/concrete_blocks/index.html:392
#: loko/maps/templates/maps/concrete_blocks/index.html:548
#: maps/templates/maps/concrete_blocks/index.html:392
#: maps/templates/maps/concrete_blocks/index.html:548
msgid "Lat."
msgstr "Lat."
#: loko/maps/templates/maps/concrete_blocks/index.html:398
#: loko/maps/templates/maps/concrete_blocks/index.html:554
#: maps/templates/maps/concrete_blocks/index.html:398
#: maps/templates/maps/concrete_blocks/index.html:554
msgid "Cliquer sur la carte pour positionner"
msgstr "Cliquer sur la carte pour positionner"
#: loko/maps/templates/maps/concrete_blocks/index.html:404
#: maps/templates/maps/concrete_blocks/index.html:404
msgid "Enregistrer"
msgstr "Enregistrer"
#: loko/maps/templates/maps/concrete_blocks/index.html:407
#: loko/maps/templates/maps/concrete_blocks/index.html:464
#: loko/maps/templates/maps/concrete_blocks/index.html:563
#: maps/templates/maps/concrete_blocks/index.html:407
#: maps/templates/maps/concrete_blocks/index.html:464
#: maps/templates/maps/concrete_blocks/index.html:563
msgid "Annuler"
msgstr "Annuler"
#: loko/maps/templates/maps/concrete_blocks/index.html:416
#: maps/templates/maps/concrete_blocks/index.html:416
msgid "Modifier en lot"
msgstr "Modifier en lot"
#: loko/maps/templates/maps/concrete_blocks/index.html:418
#: maps/templates/maps/concrete_blocks/index.html:418
msgid ""
"Seuls les champs renseignés seront mis à jour. Les champs vides sont ignorés."
msgstr ""
"Seuls les champs renseignés seront mis à jour. Les champs vides sont ignorés."
#: loko/maps/templates/maps/concrete_blocks/index.html:424
#: loko/maps/templates/maps/concrete_blocks/index.html:433
#: loko/maps/templates/maps/concrete_blocks/index.html:442
#: maps/templates/maps/concrete_blocks/index.html:424
#: maps/templates/maps/concrete_blocks/index.html:433
#: maps/templates/maps/concrete_blocks/index.html:442
msgid "Ne pas modifier"
msgstr "Ne pas modifier"
#: loko/maps/templates/maps/concrete_blocks/index.html:452
#: maps/templates/maps/concrete_blocks/index.html:452
msgid "Laisser vide"
msgstr "Laisser vide"
#: loko/maps/templates/maps/concrete_blocks/index.html:461
#: maps/templates/maps/concrete_blocks/index.html:461
msgid "Appliquer au lot"
msgstr "Appliquer au lot"
#: loko/maps/templates/maps/concrete_blocks/index.html:473
#: maps/templates/maps/concrete_blocks/index.html:473
msgid "Nouvel asset"
msgstr "Nouvel asset"
#: loko/maps/templates/maps/concrete_blocks/index.html:477
#: maps/templates/maps/concrete_blocks/index.html:477
msgid "auto si vide"
msgstr "auto si vide"
#: loko/maps/templates/maps/concrete_blocks/index.html:539
#: maps/templates/maps/concrete_blocks/index.html:539
msgid "Position"
msgstr "Position"
#: loko/maps/templates/maps/concrete_blocks/index.html:560
#: maps/templates/maps/concrete_blocks/index.html:560
msgid "Créer"
msgstr "Créer"
#: loko/maps/templates/maps/concrete_blocks/index.html:580
#: maps/templates/maps/concrete_blocks/index.html:580
msgid "Opération New Jersey"
msgstr "Opération New Jersey"
#: loko/maps/templates/maps/concrete_blocks/index.html:595
#: maps/templates/maps/concrete_blocks/index.html:595
msgid "Fermer"
msgstr "Fermer"
#: loko/maps/templates/maps/index.html:186
#: maps/templates/maps/index.html:186
msgid "Consultez et gérez les cartes auxquelles vous avez accès."
msgstr "Consultez et gérez les cartes auxquelles vous avez accès."
#: loko/maps/templates/maps/index.html:214
#: maps/templates/maps/index.html:214
msgid "Tout public"
msgstr "Tout public"
#: loko/maps/templates/maps/index.html:219
#: maps/templates/maps/index.html:219
msgid "Accès connecté"
msgstr "Accès connecté"
#: loko/maps/templates/maps/index.html:231
#: maps/templates/maps/index.html:231
msgid "Ouvrir la carte"
msgstr "Ouvrir la carte"
#: loko/maps/templates/maps/index.html:250
#: maps/templates/maps/index.html:250
msgid "Aucune carte accessible pour votre compte."
msgstr "Aucune carte accessible pour votre compte."
#: loko/maps/views.py:44
#: maps/views.py:44
msgid "Vous n'avez pas accès à cette vue."
msgstr "Vous n'avez pas accès à cette vue."
#: loko/maps/views.py:69
#: maps/views.py:69
msgid "Protection"
msgstr "Protection"
#: loko/maps/views.py:70
#: maps/views.py:70
msgid "Antiterroriste"
msgstr "Antiterroriste"
#: loko/maps/views.py:71
#: maps/views.py:71
msgid "Neutralisation stationnement"
msgstr "Neutralisation stationnement"
#: loko/maps/views.py:72
#: maps/views.py:72
msgid "Sécurité routière"
msgstr "Sécurité routière"
#: loko/maps/views.py:73
#: maps/views.py:73
msgid "Espace public"
msgstr "Espace public"
# views.py – function labels
#: loko/maps/views.py:74
#: maps/views.py:74
msgid "Chantier"
msgstr "Chantier"
#: loko/maps/views.py:75
#: maps/views.py:75
msgid "Non identifié"
msgstr "Non identifié"
#: loko/maps/views.py:76
#: maps/views.py:76
msgid "Autre / Non renseigné"
msgstr "Autre / Non renseigné"
#: loko/maps/views.py:91
#: maps/views.py:91
msgid "Maintenir"
msgstr "Maintenir"
#: loko/maps/views.py:92
#: maps/views.py:92
msgid "Enlever"
msgstr "Enlever"
#: loko/maps/views.py:93
#: maps/views.py:93
msgid "Remplacer"
msgstr "Remplacer"
#: loko/maps/views.py:482 loko/maps/views.py:501 loko/maps/views.py:538
#: maps/views.py:482 maps/views.py:501 maps/views.py:538
msgid "Permission refusée"
msgstr "Permission refusée"
#: loko/maps/views.py:487 loko/maps/views.py:506 loko/maps/views.py:559
#: maps/views.py:487 maps/views.py:506 maps/views.py:559
msgid "JSON invalide"
msgstr "JSON invalide"
#: loko/maps/views.py:565
#: maps/views.py:565
msgid "Aucun asset sélectionné"
msgstr "Aucun asset sélectionné"
#: loko/maps/views.py:567
#: maps/views.py:567
msgid "Aucune modification spécifiée"
msgstr "Aucune modification spécifiée"
#: loko/maps/views.py:702
#: maps/views.py:702
msgid "Nom"
msgstr "Nom"
#: loko/maps/views.py:703
#: maps/views.py:703
msgid "Description"
msgstr "Description"
#: loko/maps/views.py:705
#: maps/views.py:705
msgid "Numéro PMO"
msgstr "Numéro PMO"
#: loko/maps/views.py:706
#: maps/views.py:706
msgid "Numéro OSIRIS"
msgstr "Numéro OSIRIS"
#: loko/maps/views.py:707
#: maps/views.py:707
msgid "Date de début"
msgstr "Date de début"
#: loko/maps/views.py:708
#: maps/views.py:708
msgid "Date de fin"
msgstr "Date de fin"
#: loko/maps/views.py:709
#: maps/views.py:709
msgid "Créé par"
msgstr "Créé par"
#: loko/maps/views.py:710
#: maps/views.py:710
msgid "Thématiques"
msgstr "Thématiques"
#: loko/maps/views.py:711
#: maps/views.py:711
msgid "Tags"
msgstr "Tags"

View file

@ -5,7 +5,7 @@ msgid ""
msgstr ""
"Project-Id-Version: streetup\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: 2025-01-01 00:00+0000\n"
"Last-Translator: \n"
"Language-Team: Dutch\n"
@ -15,11 +15,11 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: loko/maps/admin.py:18 loko/maps/templates/maps/index.html:224
#: maps/admin.py:18 maps/templates/maps/index.html:224
msgid "Accès restreint"
msgstr "Beperkte toegang"
#: loko/maps/admin.py:21
#: maps/admin.py:21
msgid ""
"Ces champs ne s'appliquent que pour le niveau d'accès « Accès restreint ». "
"L'accès est accordé si l'utilisateur satisfait au moins une des conditions "
@ -31,45 +31,44 @@ msgstr ""
"voorwaarden voldoet (thema OF team OF specifieke gebruiker). Beheerders "
"hebben altijd toegang."
#: loko/maps/models.py:24
#: maps/models.py:24
msgid "Tout public (sans connexion)"
msgstr "Openbaar (geen inloggen)"
#: loko/maps/models.py:25
#: maps/models.py:25
msgid "Toute personne connectée"
msgstr "Iedere ingelogde persoon"
#: loko/maps/models.py:26
#: maps/models.py:26
msgid "Accès restreint (thématiques / équipes / utilisateurs)"
msgstr "Beperkte toegang (thema's / teams / gebruikers)"
#: loko/maps/models.py:32
#: loko/maps/templates/maps/concrete_blocks/index.html:477
#: loko/maps/views.py:701
#: maps/models.py:32 maps/templates/maps/concrete_blocks/index.html:477
#: maps/views.py:701
msgid "Code"
msgstr "Code"
#: loko/maps/models.py:33
#: maps/models.py:33
msgid "Identifiant technique de la carte (ex: concrete_blocks)."
msgstr "Technische kaart-identificatie (bijv. concrete_blocks)."
#: loko/maps/models.py:35
#: maps/models.py:35
msgid "Nom (FR)"
msgstr "Naam (FR)"
#: loko/maps/models.py:36
#: maps/models.py:36
msgid "Naam (NL)"
msgstr "Naam (NL)"
#: loko/maps/models.py:42
#: maps/models.py:42
msgid "Niveau d'accès"
msgstr "Toegangsniveau"
#: loko/maps/models.py:51
#: maps/models.py:51
msgid "Thématiques autorisées"
msgstr "Toegestane thema's"
#: loko/maps/models.py:53
#: maps/models.py:53
msgid ""
"Les utilisateurs ayant accès à l'une de ces thématiques peuvent visualiser "
"la carte (niveau 'restreint' uniquement)."
@ -77,195 +76,193 @@ msgstr ""
"Gebruikers met toegang tot een van deze thema's kunnen de kaart bekijken "
"(alleen beperkt niveau)."
#: loko/maps/models.py:62
#: maps/models.py:62
msgid "Équipes autorisées"
msgstr "Toegestane teams"
#: loko/maps/models.py:64
#: maps/models.py:64
msgid ""
"Les membres de ces équipes peuvent visualiser la carte (niveau 'restreint' "
"uniquement)."
msgstr "Leden van deze teams kunnen de kaart bekijken (alleen beperkt niveau)."
#: loko/maps/models.py:73
#: maps/models.py:73
msgid "Utilisateurs autorisés"
msgstr "Toegestane gebruikers"
#: loko/maps/models.py:75
#: maps/models.py:75
msgid ""
"Ces utilisateurs spécifiques peuvent visualiser la carte (niveau 'restreint' "
"uniquement)."
msgstr ""
"Deze specifieke gebruikers kunnen de kaart bekijken (alleen beperkt niveau)."
#: loko/maps/models.py:83
#: maps/models.py:83
msgid "Configuration d'accès à une carte"
msgstr "Toegangsconfiguratie voor een kaart"
#: loko/maps/models.py:84
#: maps/models.py:84
msgid "Configurations d'accès aux cartes"
msgstr "Toegangsconfiguraties voor kaarten"
#: loko/maps/templates/maps/base.html:6 loko/maps/templates/maps/base.html:7
#: loko/maps/templates/maps/index.html:185
#: maps/templates/maps/base.html:6 maps/templates/maps/base.html:7
#: maps/templates/maps/index.html:185
msgid "Cartes"
msgstr "Kaarten"
# template – tabs
#: loko/maps/templates/maps/concrete_blocks/index.html:23
#: maps/templates/maps/concrete_blocks/index.html:23
msgid "Légende"
msgstr "Legende"
#: loko/maps/templates/maps/concrete_blocks/index.html:30
#: loko/maps/templates/maps/concrete_blocks/index.html:127
#: maps/templates/maps/concrete_blocks/index.html:30
#: maps/templates/maps/concrete_blocks/index.html:127
msgid "Filtres"
msgstr "Filters"
#: loko/maps/templates/maps/concrete_blocks/index.html:37
#: maps/templates/maps/concrete_blocks/index.html:37
msgid "Détail"
msgstr "Detail"
#: loko/maps/templates/maps/concrete_blocks/index.html:44
#: maps/templates/maps/concrete_blocks/index.html:44
msgid "Projets"
msgstr "Projecten"
#: loko/maps/templates/maps/concrete_blocks/index.html:52
#: maps/templates/maps/concrete_blocks/index.html:52
msgid "Édition"
msgstr "Bewerken"
# template – legend panel
#: loko/maps/templates/maps/concrete_blocks/index.html:64
#: maps/templates/maps/concrete_blocks/index.html:64
msgid "Représentation des couleurs"
msgstr "Kleurrepresentatie"
#: loko/maps/templates/maps/concrete_blocks/index.html:66
#: maps/templates/maps/concrete_blocks/index.html:66
msgid "Par fonction"
msgstr "Per functie"
#: loko/maps/templates/maps/concrete_blocks/index.html:72
#: loko/maps/templates/maps/concrete_blocks/index.html:156
#: maps/templates/maps/concrete_blocks/index.html:72
#: maps/templates/maps/concrete_blocks/index.html:156
msgid "Nombre de blocs"
msgstr "Aantal blokken"
#: loko/maps/templates/maps/concrete_blocks/index.html:78
#: maps/templates/maps/concrete_blocks/index.html:78
msgid "< 3 blocs"
msgstr "≤ 3 blokken"
#: loko/maps/templates/maps/concrete_blocks/index.html:85
#: maps/templates/maps/concrete_blocks/index.html:85
msgid "3 – 10 blocs"
msgstr "4 – 10 blokken"
#: loko/maps/templates/maps/concrete_blocks/index.html:93
#: maps/templates/maps/concrete_blocks/index.html:93
msgid "> 10 blocs"
msgstr "> 10 blokken"
#: loko/maps/templates/maps/concrete_blocks/index.html:108
#: loko/maps/views.py:662
#: maps/templates/maps/concrete_blocks/index.html:108 maps/views.py:662
msgid "Projets New-Jersey"
msgstr "New-Jersey projecten"
#: loko/maps/templates/maps/concrete_blocks/index.html:118
#: maps/templates/maps/concrete_blocks/index.html:118
msgid "Exporter en CSV"
msgstr "Exporteren naar CSV"
# template – filters panel
#: loko/maps/templates/maps/concrete_blocks/index.html:130
#: maps/templates/maps/concrete_blocks/index.html:130
msgid "Fonction"
msgstr "Functie"
#: loko/maps/templates/maps/concrete_blocks/index.html:145
#: loko/maps/templates/maps/concrete_blocks/index.html:225
#: loko/maps/templates/maps/concrete_blocks/index.html:313
#: loko/maps/templates/maps/concrete_blocks/index.html:422
#: loko/maps/views.py:704
#: maps/templates/maps/concrete_blocks/index.html:145
#: maps/templates/maps/concrete_blocks/index.html:225
#: maps/templates/maps/concrete_blocks/index.html:313
#: maps/templates/maps/concrete_blocks/index.html:422 maps/views.py:704
msgid "Statut"
msgstr "Status"
#: loko/maps/templates/maps/concrete_blocks/index.html:159
#: loko/maps/templates/maps/concrete_blocks/index.html:170
#: maps/templates/maps/concrete_blocks/index.html:159
#: maps/templates/maps/concrete_blocks/index.html:170
msgid "Min"
msgstr "Min"
#: loko/maps/templates/maps/concrete_blocks/index.html:162
#: loko/maps/templates/maps/concrete_blocks/index.html:173
#: maps/templates/maps/concrete_blocks/index.html:162
#: maps/templates/maps/concrete_blocks/index.html:173
msgid "Max"
msgstr "Max"
#: loko/maps/templates/maps/concrete_blocks/index.html:167
#: loko/maps/templates/maps/concrete_blocks/index.html:362
#: loko/maps/templates/maps/concrete_blocks/index.html:450
#: loko/maps/templates/maps/concrete_blocks/index.html:528
#: maps/templates/maps/concrete_blocks/index.html:167
#: maps/templates/maps/concrete_blocks/index.html:362
#: maps/templates/maps/concrete_blocks/index.html:450
#: maps/templates/maps/concrete_blocks/index.html:528
msgid "Priorité"
msgstr "Prioriteit"
#: loko/maps/templates/maps/concrete_blocks/index.html:178
#: loko/maps/templates/maps/concrete_blocks/index.html:352
#: loko/maps/templates/maps/concrete_blocks/index.html:440
#: loko/maps/templates/maps/concrete_blocks/index.html:518
#: maps/templates/maps/concrete_blocks/index.html:178
#: maps/templates/maps/concrete_blocks/index.html:352
#: maps/templates/maps/concrete_blocks/index.html:440
#: maps/templates/maps/concrete_blocks/index.html:518
msgid "Action recommandée"
msgstr "Aanbevolen actie"
#: loko/maps/templates/maps/concrete_blocks/index.html:190
#: maps/templates/maps/concrete_blocks/index.html:190
msgid "Appliquer"
msgstr "Toepassen"
#: loko/maps/templates/maps/concrete_blocks/index.html:193
#: maps/templates/maps/concrete_blocks/index.html:193
msgid "Réinitialiser"
msgstr "Opnieuw instellen"
#: loko/maps/templates/maps/concrete_blocks/index.html:202
#: maps/templates/maps/concrete_blocks/index.html:202
msgid "Détail du set de blocs"
msgstr "Detail van de blokkenset"
#: loko/maps/templates/maps/concrete_blocks/index.html:206
#: maps/templates/maps/concrete_blocks/index.html:206
msgid "Cliquez sur un point de la carte pour voir les détails."
msgstr "Klik op een punt op de kaart om de details te bekijken."
#: loko/maps/templates/maps/concrete_blocks/index.html:221
#: maps/templates/maps/concrete_blocks/index.html:221
msgid "N° projet, PMO, Osiris, description…"
msgstr "Projectnr., PMO, Osiris, beschrijving…"
#: loko/maps/templates/maps/concrete_blocks/index.html:230
#: maps/templates/maps/concrete_blocks/index.html:230
msgid "Période"
msgstr "Periode"
#: loko/maps/templates/maps/concrete_blocks/index.html:233
#: maps/templates/maps/concrete_blocks/index.html:233
msgid "Début à partir du"
msgstr "Start vanaf"
#: loko/maps/templates/maps/concrete_blocks/index.html:236
#: maps/templates/maps/concrete_blocks/index.html:236
msgid "Fin avant le"
msgstr "Einde voor"
#: loko/maps/templates/maps/concrete_blocks/index.html:245
#: maps/templates/maps/concrete_blocks/index.html:245
msgid "Cliquez sur l'onglet pour charger les projets."
msgstr "Klik op een punt op de kaart om de details te bekijken."
#: loko/maps/templates/maps/concrete_blocks/index.html:253
#: maps/templates/maps/concrete_blocks/index.html:253
msgid "Exporter en Excel"
msgstr "Exporteren naar Excel"
#: loko/maps/templates/maps/concrete_blocks/index.html:269
#: maps/templates/maps/concrete_blocks/index.html:269
msgid "Ajouter"
msgstr "Toevoegen"
#: loko/maps/templates/maps/concrete_blocks/index.html:274
#: maps/templates/maps/concrete_blocks/index.html:274
msgid "Activer la sélection multiple"
msgstr "Activeer meervoudige selectie"
#: loko/maps/templates/maps/concrete_blocks/index.html:275
#: maps/templates/maps/concrete_blocks/index.html:275
msgid "Multi-sélection"
msgstr "Meervoudige selectie"
#: loko/maps/templates/maps/concrete_blocks/index.html:281
#: maps/templates/maps/concrete_blocks/index.html:281
msgid "asset(s) sélectionné(s)"
msgstr "geselecteerd(e) asset(s)"
#: loko/maps/templates/maps/concrete_blocks/index.html:284
#: maps/templates/maps/concrete_blocks/index.html:284
msgid "Tout désélectionner"
msgstr "Alles deselecteren"
#: loko/maps/templates/maps/concrete_blocks/index.html:292
#: maps/templates/maps/concrete_blocks/index.html:292
msgid ""
"Cliquez sur un asset de la carte pour l'éditer, ou activez la multi-"
"sélection."
@ -273,248 +270,248 @@ msgstr ""
"Klik op een asset op de kaart om deze te bewerken, of activeer meervoudige "
"selectie."
#: loko/maps/templates/maps/concrete_blocks/index.html:298
#: maps/templates/maps/concrete_blocks/index.html:298
msgid "Modifier l'asset"
msgstr "Asset bewerken"
#: loko/maps/templates/maps/concrete_blocks/index.html:301
#: maps/templates/maps/concrete_blocks/index.html:301
msgid "Archiver cet asset"
msgstr "Dit asset archiveren"
#: loko/maps/templates/maps/concrete_blocks/index.html:309
#: loko/maps/templates/maps/concrete_blocks/index.html:483
#: maps/templates/maps/concrete_blocks/index.html:309
#: maps/templates/maps/concrete_blocks/index.html:483
msgid "Adresse"
msgstr "Adres"
#: loko/maps/templates/maps/concrete_blocks/index.html:321
#: loko/maps/templates/maps/concrete_blocks/index.html:431
#: loko/maps/templates/maps/concrete_blocks/index.html:487
#: maps/templates/maps/concrete_blocks/index.html:321
#: maps/templates/maps/concrete_blocks/index.html:431
#: maps/templates/maps/concrete_blocks/index.html:487
msgid "Fonction principale"
msgstr "Hoofdfunctie"
#: loko/maps/templates/maps/concrete_blocks/index.html:330
#: loko/maps/templates/maps/concrete_blocks/index.html:496
#: maps/templates/maps/concrete_blocks/index.html:330
#: maps/templates/maps/concrete_blocks/index.html:496
msgid "Fonctions secondaires"
msgstr "Secundaire functies"
#: loko/maps/templates/maps/concrete_blocks/index.html:343
#: loko/maps/templates/maps/concrete_blocks/index.html:509
#: maps/templates/maps/concrete_blocks/index.html:343
#: maps/templates/maps/concrete_blocks/index.html:509
msgid "Nb. blocs"
msgstr "Aantal blokken"
#: loko/maps/templates/maps/concrete_blocks/index.html:347
#: loko/maps/templates/maps/concrete_blocks/index.html:513
#: maps/templates/maps/concrete_blocks/index.html:347
#: maps/templates/maps/concrete_blocks/index.html:513
msgid "Longueur (m)"
msgstr "Lengte (m)"
#: loko/maps/templates/maps/concrete_blocks/index.html:366
#: loko/maps/templates/maps/concrete_blocks/index.html:455
#: loko/maps/templates/maps/concrete_blocks/index.html:532
#: maps/templates/maps/concrete_blocks/index.html:366
#: maps/templates/maps/concrete_blocks/index.html:455
#: maps/templates/maps/concrete_blocks/index.html:532
msgid "Date cible"
msgstr "Targetdatum"
#: loko/maps/templates/maps/concrete_blocks/index.html:371
#: maps/templates/maps/concrete_blocks/index.html:371
msgid "Date d'enlèvement"
msgstr "Verwijderingsdatum"
#: loko/maps/templates/maps/concrete_blocks/index.html:376
#: maps/templates/maps/concrete_blocks/index.html:376
msgid "Observation source"
msgstr "Bronobservatie"
#: loko/maps/templates/maps/concrete_blocks/index.html:383
#: maps/templates/maps/concrete_blocks/index.html:383
msgid "Position (glisser le marqueur)"
msgstr "Positie (sleep de markering)"
#: loko/maps/templates/maps/concrete_blocks/index.html:388
#: loko/maps/templates/maps/concrete_blocks/index.html:544
#: maps/templates/maps/concrete_blocks/index.html:388
#: maps/templates/maps/concrete_blocks/index.html:544
msgid "Lon."
msgstr "Lon."
#: loko/maps/templates/maps/concrete_blocks/index.html:392
#: loko/maps/templates/maps/concrete_blocks/index.html:548
#: maps/templates/maps/concrete_blocks/index.html:392
#: maps/templates/maps/concrete_blocks/index.html:548
msgid "Lat."
msgstr "Lat."
#: loko/maps/templates/maps/concrete_blocks/index.html:398
#: loko/maps/templates/maps/concrete_blocks/index.html:554
#: maps/templates/maps/concrete_blocks/index.html:398
#: maps/templates/maps/concrete_blocks/index.html:554
msgid "Cliquer sur la carte pour positionner"
msgstr "Klik op een punt op de kaart om de details te bekijken."
#: loko/maps/templates/maps/concrete_blocks/index.html:404
#: maps/templates/maps/concrete_blocks/index.html:404
msgid "Enregistrer"
msgstr "Opslaan"
#: loko/maps/templates/maps/concrete_blocks/index.html:407
#: loko/maps/templates/maps/concrete_blocks/index.html:464
#: loko/maps/templates/maps/concrete_blocks/index.html:563
#: maps/templates/maps/concrete_blocks/index.html:407
#: maps/templates/maps/concrete_blocks/index.html:464
#: maps/templates/maps/concrete_blocks/index.html:563
msgid "Annuler"
msgstr "Annuleren"
#: loko/maps/templates/maps/concrete_blocks/index.html:416
#: maps/templates/maps/concrete_blocks/index.html:416
msgid "Modifier en lot"
msgstr "In bulk bewerken"
#: loko/maps/templates/maps/concrete_blocks/index.html:418
#: maps/templates/maps/concrete_blocks/index.html:418
msgid ""
"Seuls les champs renseignés seront mis à jour. Les champs vides sont ignorés."
msgstr ""
"Alleen ingevulde velden worden bijgewerkt. Lege velden worden genegeerd."
#: loko/maps/templates/maps/concrete_blocks/index.html:424
#: loko/maps/templates/maps/concrete_blocks/index.html:433
#: loko/maps/templates/maps/concrete_blocks/index.html:442
#: maps/templates/maps/concrete_blocks/index.html:424
#: maps/templates/maps/concrete_blocks/index.html:433
#: maps/templates/maps/concrete_blocks/index.html:442
msgid "Ne pas modifier"
msgstr "Niet wijzigen"
#: loko/maps/templates/maps/concrete_blocks/index.html:452
#: maps/templates/maps/concrete_blocks/index.html:452
msgid "Laisser vide"
msgstr "Leeg laten"
#: loko/maps/templates/maps/concrete_blocks/index.html:461
#: maps/templates/maps/concrete_blocks/index.html:461
msgid "Appliquer au lot"
msgstr "Toepassen"
#: loko/maps/templates/maps/concrete_blocks/index.html:473
#: maps/templates/maps/concrete_blocks/index.html:473
msgid "Nouvel asset"
msgstr "Nieuw asset"
#: loko/maps/templates/maps/concrete_blocks/index.html:477
#: maps/templates/maps/concrete_blocks/index.html:477
msgid "auto si vide"
msgstr "automatisch indien leeg"
#: loko/maps/templates/maps/concrete_blocks/index.html:539
#: maps/templates/maps/concrete_blocks/index.html:539
msgid "Position"
msgstr "Bescherming"
#: loko/maps/templates/maps/concrete_blocks/index.html:560
#: maps/templates/maps/concrete_blocks/index.html:560
msgid "Créer"
msgstr "Aanmaken"
#: loko/maps/templates/maps/concrete_blocks/index.html:580
#: maps/templates/maps/concrete_blocks/index.html:580
msgid "Opération New Jersey"
msgstr "Operatie New Jersey"
#: loko/maps/templates/maps/concrete_blocks/index.html:595
#: maps/templates/maps/concrete_blocks/index.html:595
msgid "Fermer"
msgstr "Sluiten"
#: loko/maps/templates/maps/index.html:186
#: maps/templates/maps/index.html:186
msgid "Consultez et gérez les cartes auxquelles vous avez accès."
msgstr "Bekijk en beheer de kaarten waartoe u toegang heeft."
#: loko/maps/templates/maps/index.html:214
#: maps/templates/maps/index.html:214
msgid "Tout public"
msgstr "Alle doelgroepen"
#: loko/maps/templates/maps/index.html:219
#: maps/templates/maps/index.html:219
msgid "Accès connecté"
msgstr "Verbonden toegang"
#: loko/maps/templates/maps/index.html:231
#: maps/templates/maps/index.html:231
msgid "Ouvrir la carte"
msgstr "Kaart openen"
#: loko/maps/templates/maps/index.html:250
#: maps/templates/maps/index.html:250
msgid "Aucune carte accessible pour votre compte."
msgstr "Geen kaart toegankelijk voor uw account."
#: loko/maps/views.py:44
#: maps/views.py:44
msgid "Vous n'avez pas accès à cette vue."
msgstr "U heeft geen toegang tot deze weergave."
#: loko/maps/views.py:69
#: maps/views.py:69
msgid "Protection"
msgstr "Bescherming"
#: loko/maps/views.py:70
#: maps/views.py:70
msgid "Antiterroriste"
msgstr "Antiterreur"
#: loko/maps/views.py:71
#: maps/views.py:71
msgid "Neutralisation stationnement"
msgstr "Parkeerverbod"
#: loko/maps/views.py:72
#: maps/views.py:72
msgid "Sécurité routière"
msgstr "Beveiliging"
#: loko/maps/views.py:73
#: maps/views.py:73
msgid "Espace public"
msgstr "Openbare ruimte"
# views.py – function labels
#: loko/maps/views.py:74
#: maps/views.py:74
msgid "Chantier"
msgstr "Werf"
#: loko/maps/views.py:75
#: maps/views.py:75
msgid "Non identifié"
msgstr "Niet geïdentificeerd"
#: loko/maps/views.py:76
#: maps/views.py:76
msgid "Autre / Non renseigné"
msgstr "Andere / Niet ingevuld"
#: loko/maps/views.py:91
#: maps/views.py:91
msgid "Maintenir"
msgstr "Behouden"
#: loko/maps/views.py:92
#: maps/views.py:92
msgid "Enlever"
msgstr "Verwijderen"
#: loko/maps/views.py:93
#: maps/views.py:93
msgid "Remplacer"
msgstr "Vervangen"
#: loko/maps/views.py:482 loko/maps/views.py:501 loko/maps/views.py:538
#: maps/views.py:482 maps/views.py:501 maps/views.py:538
msgid "Permission refusée"
msgstr "Toegang geweigerd"
#: loko/maps/views.py:487 loko/maps/views.py:506 loko/maps/views.py:559
#: maps/views.py:487 maps/views.py:506 maps/views.py:559
msgid "JSON invalide"
msgstr "Ongeldige JSON"
#: loko/maps/views.py:565
#: maps/views.py:565
msgid "Aucun asset sélectionné"
msgstr "Geen asset geselecteerd"
#: loko/maps/views.py:567
#: maps/views.py:567
msgid "Aucune modification spécifiée"
msgstr "Geen wijziging gespecificeerd"
#: loko/maps/views.py:702
#: maps/views.py:702
msgid "Nom"
msgstr "Naam"
#: loko/maps/views.py:703
#: maps/views.py:703
msgid "Description"
msgstr "Beschrijving"
#: loko/maps/views.py:705
#: maps/views.py:705
msgid "Numéro PMO"
msgstr "PMO-nummer"
#: loko/maps/views.py:706
#: maps/views.py:706
msgid "Numéro OSIRIS"
msgstr "OSIRIS-nummer"
#: loko/maps/views.py:707
#: maps/views.py:707
msgid "Date de début"
msgstr "Startdatum"
#: loko/maps/views.py:708
#: maps/views.py:708
msgid "Date de fin"
msgstr "Einddatum"
#: loko/maps/views.py:709
#: maps/views.py:709
msgid "Créé par"
msgstr "Gemaakt door"
#: loko/maps/views.py:710
#: maps/views.py:710
msgid "Thématiques"
msgstr "Thema's"
#: loko/maps/views.py:711
#: maps/views.py:711
msgid "Tags"
msgstr "Labels"

View file

@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: 2025-12-04 12:00+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: English <LL@li.org>\n"
@ -16,233 +16,233 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:240
#: mobile/templates/mobile/green_surfaces_edit_v2.html:240
msgid "Espaces verts - V2"
msgstr "Green spaces - V2"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:254
#: mobile/templates/mobile/green_surfaces_edit_v2.html:254
msgid "Édition des espaces verts"
msgstr "Green spaces editing"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:269
#: mobile/templates/mobile/green_surfaces_edit_v2.html:269
msgid "géométrie(s) modifiée(s)"
msgstr "geometry(ies) modified"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:274
#: mobile/templates/mobile/green_surfaces_edit_v2.html:274
msgid "élément(s) sélectionné(s)"
msgstr "selected item(s)"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:275
#: mobile/templates/mobile/green_surfaces_edit_v2.html:275
msgid ""
"Sélectionnez un modèle ci-dessous pour l'appliquer aux éléments sélectionnés."
msgstr "Select a template below to apply it to the selected elements."
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:280
#: mobile/templates/mobile/green_surfaces_edit_v2.html:280
msgid "Édition des attributs"
msgstr "Attribute editing"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:288
#: mobile/templates/mobile/green_surfaces_edit_v2.html:288
msgid "Modèle"
msgstr "Model"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:303
#: mobile/templates/mobile/green_surfaces_edit_v2.html:303
msgid "Types de bulbes"
msgstr "Types of bulbs"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:325
#: mobile/templates/mobile/green_surfaces_edit_v2.html:325
msgid "Enregistrer"
msgstr "Save"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:328
#: mobile/templates/mobile/green_surfaces_edit_v2.html:328
msgid "Désélectionner"
msgstr "Deselect"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:338
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:986
#: mobile/templates/mobile/green_surfaces_edit_v2.html:338
#: mobile/templates/mobile/green_surfaces_edit_v2.html:986
msgid "Mode dessin"
msgstr "Drawing mode"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:339
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1519
#: mobile/templates/mobile/green_surfaces_edit_v2.html:339
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1519
msgid "Inactif"
msgstr "Inactive"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:342
#: mobile/templates/mobile/green_surfaces_edit_v2.html:342
msgid "Modifications"
msgstr "Changes"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:348
#: mobile/templates/mobile/green_surfaces_edit_v2.html:348
msgid "Assets chargés"
msgstr "Assets loaded"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:352
#: mobile/templates/mobile/green_surfaces_edit_v2.html:352
msgid "En édition"
msgstr "Editing"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:723
#: mobile/templates/mobile/green_surfaces_edit_v2.html:723
msgid "Sélection multiple"
msgstr "Multiple selection"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:738
#: mobile/templates/mobile/green_surfaces_edit_v2.html:738
msgid "Aucune modification à enregistrer"
msgstr "No changes to save"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:792
#: mobile/templates/mobile/green_surfaces_edit_v2.html:792
msgid "Géométries enregistrées avec succès"
msgstr "Geometries saved successfully"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:794
#: mobile/templates/mobile/green_surfaces_edit_v2.html:794
msgid "modifié(s)"
msgstr "modified"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:797
#: mobile/templates/mobile/green_surfaces_edit_v2.html:797
msgid "supprimé(s)"
msgstr "deleted"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:830
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:908
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:913
#: mobile/templates/mobile/green_surfaces_edit_v2.html:830
#: mobile/templates/mobile/green_surfaces_edit_v2.html:908
#: mobile/templates/mobile/green_surfaces_edit_v2.html:913
msgid "Erreur lors de la sauvegarde"
msgstr "Error saving changes"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:835
#: mobile/templates/mobile/green_surfaces_edit_v2.html:835
msgid "Erreur lors de la sauvegarde des géométries"
msgstr "Error saving geometries"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:868
#: mobile/templates/mobile/green_surfaces_edit_v2.html:868
msgid "Aucun élément sélectionné"
msgstr "No element selected"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:873
#: mobile/templates/mobile/green_surfaces_edit_v2.html:873
msgid "Veuillez sélectionner un modèle ou des types de bulbes"
msgstr "Please select a template"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:898
#: mobile/templates/mobile/green_surfaces_edit_v2.html:898
msgid "Modifications enregistrées avec succès"
msgstr "Changes saved successfully"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:987
#: mobile/templates/mobile/green_surfaces_edit_v2.html:987
msgid "Ajouter un polygone"
msgstr "Add a polygon"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:988
#: mobile/templates/mobile/green_surfaces_edit_v2.html:988
msgid "Supprimer les géométries sélectionnées"
msgstr "Delete selected geometries"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:989
#: mobile/templates/mobile/green_surfaces_edit_v2.html:989
msgid "Aimantage (Snap)"
msgstr "Snap"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:990
#: mobile/templates/mobile/green_surfaces_edit_v2.html:990
msgid "Aimantage activé"
msgstr "Snapping enabled"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:991
#: mobile/templates/mobile/green_surfaces_edit_v2.html:991
msgid "Aimantage désactivé"
msgstr "Snapping disabled"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:992
#: mobile/templates/mobile/green_surfaces_edit_v2.html:992
msgid "Découper un polygone"
msgstr "Cut a polygon"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:993
#: mobile/templates/mobile/green_surfaces_edit_v2.html:993
msgid "Découpage annulé"
msgstr "Cutting cancelled"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:994
#: mobile/templates/mobile/green_surfaces_edit_v2.html:994
msgid "Polygone découpé avec succès"
msgstr "Polygon cut successfully"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:995
#: mobile/templates/mobile/green_surfaces_edit_v2.html:995
msgid "Fusionner les polygones sélectionnés"
msgstr "Merge selected polygons"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:996
#: mobile/templates/mobile/green_surfaces_edit_v2.html:996
msgid "Polygones fusionnés avec succès"
msgstr "Polygons merged successfully"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:997
#: mobile/templates/mobile/green_surfaces_edit_v2.html:997
msgid "Enregistrer les modifications"
msgstr "Save changes"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:998
#: mobile/templates/mobile/green_surfaces_edit_v2.html:998
msgid "Annuler"
msgstr "Cancel"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:999
#: mobile/templates/mobile/green_surfaces_edit_v2.html:999
msgid "Aucune géométrie à supprimer"
msgstr "No geometry to delete"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1000
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1000
msgid "Géométrie(s) supprimée(s)"
msgstr "Geometry(ies) deleted"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1001
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1001
msgid "Mode dessin activé - Cliquez sur une géométrie pour l'éditer"
msgstr "Drawing mode activated - Click on a geometry to edit it"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1002
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1002
msgid "Mode dessin désactivé"
msgstr "Drawing mode disabled"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1003
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1003
msgid ""
"Cliquez pour ajouter des points. Double-cliquez ou cliquez sur le premier "
"point pour terminer."
msgstr "Click to add points. Double-click or click the first point to finish."
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1004
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1004
msgid ""
"Tracez une ligne pour découper le polygone. Double-cliquez pour terminer."
msgstr "Draw a line to cut the polygon. Double-click to finish."
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1107
#: loko/mobile/templates/mobile/mobile_index.html:146
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1107
#: mobile/templates/mobile/mobile_index.html:146
msgid "Espaces verts"
msgstr "Green spaces"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1116
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1116
msgid "Arbres"
msgstr "Trees"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1436
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1436
msgid "Erreur lors du rechargement des données"
msgstr "Error reloading data"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1511
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1511
msgid "Erreur lors du chargement des données"
msgstr "Error loading data"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1519
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1519
msgid "Actif"
msgstr "Active"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1722
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1723
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1722
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1723
msgid "Quitter"
msgstr "Exit"
#: loko/mobile/templates/mobile/mobile_base.html:220
#: mobile/templates/mobile/mobile_base.html:220
msgid "Chargement..."
msgstr "Loading..."
#: loko/mobile/templates/mobile/mobile_base.html:244
#: mobile/templates/mobile/mobile_base.html:244
msgid "Notifications"
msgstr "Notifications"
#: loko/mobile/templates/mobile/mobile_base.html:250
#: mobile/templates/mobile/mobile_base.html:250
msgid "notifications non lues"
msgstr "unread notifications"
#: loko/mobile/templates/mobile/mobile_base.html:256
#: mobile/templates/mobile/mobile_base.html:256
msgid "Scanner un QR Code"
msgstr "Scan a QR Code"
#: loko/mobile/templates/mobile/mobile_index.html:17
#: mobile/templates/mobile/mobile_index.html:17
msgid "Notifications non lues"
msgstr "Unread notifications"
#: loko/mobile/templates/mobile/mobile_index.html:20
#: mobile/templates/mobile/mobile_index.html:20
#, python-format
msgid ""
"\n"
@ -257,186 +257,187 @@ msgid_plural ""
msgstr[0] ""
msgstr[1] ""
#: loko/mobile/templates/mobile/mobile_index.html:29
#: mobile/templates/mobile/mobile_index.html:29
msgid "Consulter"
msgstr "View"
#: loko/mobile/templates/mobile/mobile_index.html:40
#: mobile/templates/mobile/mobile_index.html:40
msgid "Nouveaux éléments"
msgstr "New items"
#: loko/mobile/templates/mobile/mobile_index.html:45
#: mobile/templates/mobile/mobile_index.html:45
msgid "Nouvelle observation"
msgstr "New observation"
#: loko/mobile/templates/mobile/mobile_index.html:52
#: mobile/templates/mobile/mobile_index.html:52
msgid "Nouvelle inspection"
msgstr "New inspection"
#: loko/mobile/templates/mobile/mobile_index.html:59
#: mobile/templates/mobile/mobile_index.html:59
msgid "Intervention Réparation"
msgstr "Repair intervention"
#: loko/mobile/templates/mobile/mobile_index.html:66
#: mobile/templates/mobile/mobile_index.html:66
msgid "Nouvelle intervention"
msgstr "New intervention"
#: loko/mobile/templates/mobile/mobile_index.html:72
#: mobile/templates/mobile/mobile_index.html:72
msgid "Nouvelle discussion"
msgstr "New discussion"
#: loko/mobile/templates/mobile/mobile_index.html:86
#: mobile/templates/mobile/mobile_index.html:86
msgid "Interventions"
msgstr "Interventions"
#: loko/mobile/templates/mobile/mobile_index.html:87
#: mobile/templates/mobile/mobile_index.html:87
msgid "Consulter et suivre les interventions en cours"
msgstr "View and track ongoing interventions"
#: loko/mobile/templates/mobile/mobile_index.html:97
#: mobile/templates/mobile/mobile_index.html:97
msgid "Contrôles"
msgstr "Controls"
#: loko/mobile/templates/mobile/mobile_index.html:98
#: mobile/templates/mobile/mobile_index.html:98
msgid "Accéder aux contrôles terrain"
msgstr "Access field controls"
#: loko/mobile/templates/mobile/mobile_index.html:109
#: mobile/templates/mobile/mobile_index.html:109
msgid "Projets"
msgstr "Projects"
#: loko/mobile/templates/mobile/mobile_index.html:110
#: mobile/templates/mobile/mobile_index.html:110
msgid "Suivre l'état des projets"
msgstr "Track project status"
#: loko/mobile/templates/mobile/mobile_index.html:121
#: mobile/templates/mobile/mobile_index.html:121
msgid "Observations"
msgstr "Observations"
#: loko/mobile/templates/mobile/mobile_index.html:122
#: mobile/templates/mobile/mobile_index.html:122
msgid "Consulter et ajouter des observations terrain"
msgstr "View and add field observations"
#: loko/mobile/templates/mobile/mobile_index.html:133
#: mobile/templates/mobile/mobile_index.html:133
msgid "Inspections d'assets"
msgstr "Asset inspections"
#: loko/mobile/templates/mobile/mobile_index.html:134
#: mobile/templates/mobile/mobile_index.html:134
msgid "Consulter la liste et l'historique des vérifications d'assets"
msgstr "View the list and history of asset verifications"
#: loko/mobile/templates/mobile/mobile_index.html:147
#: mobile/templates/mobile/mobile_index.html:147
msgid "Éditer les espaces verts"
msgstr "Edit green spaces"
#: loko/mobile/templates/mobile/mobile_index.html:158
#: mobile/templates/mobile/mobile_index.html:158
msgid "Stock"
msgstr "Stock"
#: loko/mobile/templates/mobile/mobile_index.html:159
#: mobile/templates/mobile/mobile_index.html:159
msgid "Gérer les produits, commandes et mouvements de stock"
msgstr "Manage products, orders and stock movements"
#: loko/mobile/templates/mobile/mobile_install.html:8
#: mobile/templates/mobile/mobile_install.html:8
msgid "Installer"
msgstr "Install"
#: loko/mobile/templates/mobile/mobile_install.html:64
#: mobile/templates/mobile/mobile_install.html:64
msgid "Installez l'application en 3 options"
msgstr "Install the app with 3 options"
#: loko/mobile/templates/mobile/mobile_install.html:65
#: mobile/templates/mobile/mobile_install.html:65
msgid ""
"Choisissez la méthode la plus adaptée à votre appareil ou à votre usage."
msgstr "Choose the method best suited to your device or usage."
#: loko/mobile/templates/mobile/mobile_install.html:76
#: mobile/templates/mobile/mobile_install.html:76
msgid "Télécharger l'APK Android"
msgstr "Download Android APK"
#: loko/mobile/templates/mobile/mobile_install.html:77
#: mobile/templates/mobile/mobile_install.html:77
msgid "Installez la version native (recommandé pour les appareils de terrain)."
msgstr "Install the native version (recommended for field devices)."
#: loko/mobile/templates/mobile/mobile_install.html:79
#: mobile/templates/mobile/mobile_install.html:79
msgid "Appuyez sur le bouton ci-dessous pour lancer le téléchargement."
msgstr "Press the button below to start the download."
#: loko/mobile/templates/mobile/mobile_install.html:80
#: mobile/templates/mobile/mobile_install.html:80
msgid ""
"Autorisez l'installation depuis des sources inconnues si Android le demande."
msgstr "Allow installation from unknown sources if Android requests it."
#: loko/mobile/templates/mobile/mobile_install.html:81
#: mobile/templates/mobile/mobile_install.html:81
msgid "Ouvrez le fichier loko-app.apk et confirmez l'installation."
msgstr "Open the loko-app.apk file and confirm the installation."
#: loko/mobile/templates/mobile/mobile_install.html:84
#: mobile/templates/mobile/mobile_install.html:84
msgid "Télécharger l'APK"
msgstr "Download APK"
#: loko/mobile/templates/mobile/mobile_install.html:94
#: mobile/templates/mobile/mobile_install.html:94
msgid "Installer la PWA"
msgstr "Install the PWA"
#: loko/mobile/templates/mobile/mobile_install.html:95
#: mobile/templates/mobile/mobile_install.html:95
msgid "Ajoutez l'application sur l'écran d'accueil sans passer par un store."
msgstr "Add the application to your home screen without going through an app store."
msgstr ""
"Add the application to your home screen without going through an app store."
#: loko/mobile/templates/mobile/mobile_install.html:97
#: mobile/templates/mobile/mobile_install.html:97
msgid ""
"Ouvrez l'application dans votre navigateur mobile (Chrome, Edge, Safari)."
msgstr "Open the application in your mobile browser (Chrome, Edge, Safari)."
#: loko/mobile/templates/mobile/mobile_install.html:98
#: mobile/templates/mobile/mobile_install.html:98
msgid "Dans la barre d'adresse, choisissez “Ajouter à l'écran d'accueil”."
msgstr "In the address bar, choose \"Add to Home Screen\"."
#: loko/mobile/templates/mobile/mobile_install.html:99
#: mobile/templates/mobile/mobile_install.html:99
msgid "Confirmez : l'icône apparaît comme une application."
msgstr "Confirm: the icon appears as an application."
#: loko/mobile/templates/mobile/mobile_install.html:103
#: mobile/templates/mobile/mobile_install.html:103
msgid "Assurez-vous d'accepter l'installation quand la bannière PWA s'affiche."
msgstr "Make sure to accept the installation when the PWA banner appears."
#: loko/mobile/templates/mobile/mobile_install.html:106
#: mobile/templates/mobile/mobile_install.html:106
msgid "Ouvrir l'application"
msgstr "Open application"
#: loko/mobile/templates/mobile/mobile_install.html:116
#: mobile/templates/mobile/mobile_install.html:116
msgid "Utiliser la version web"
msgstr "Use the web version"
#: loko/mobile/templates/mobile/mobile_install.html:117
#: mobile/templates/mobile/mobile_install.html:117
msgid "Accédez directement à l'application mobile depuis votre navigateur."
msgstr "Access the mobile app directly from your browser."
#: loko/mobile/templates/mobile/mobile_install.html:119
#: mobile/templates/mobile/mobile_install.html:119
msgid "Tapez l'adresse"
msgstr "Type the address"
#: loko/mobile/templates/mobile/mobile_install.html:119
#: mobile/templates/mobile/mobile_install.html:119
msgid "une fois connecté(e) à StreetUp."
msgstr "once logged in to StreetUp."
#: loko/mobile/templates/mobile/mobile_install.html:120
#: mobile/templates/mobile/mobile_install.html:120
msgid "Ajoutez un favori pour y revenir en un geste."
msgstr "Add a bookmark to return with one tap."
#: loko/mobile/templates/mobile/mobile_install.html:121
#: mobile/templates/mobile/mobile_install.html:121
msgid "Compatible bureau et tablette."
msgstr "Compatible with desktop and tablet."
#: loko/mobile/templates/mobile/mobile_install.html:124
#: mobile/templates/mobile/mobile_install.html:124
msgid "Aller vers /mobile/"
msgstr "Go to /mobile/"
#: loko/mobile/templates/mobile/mobile_install.html:136
#: mobile/templates/mobile/mobile_install.html:136
msgid "Scanner pour ouvrir cette page"
msgstr "Scan to open this page"
#: loko/mobile/templates/mobile/mobile_install.html:138
#: mobile/templates/mobile/mobile_install.html:138
msgid ""
"Pointez l'appareil photo de votre smartphone sur ce QR code pour accéder "
"instantanément aux instructions d'installation."
@ -444,138 +445,138 @@ msgstr ""
"Point your smartphone camera at this QR code to instantly access the "
"installation instructions."
#: loko/mobile/templates/mobile/mobile_install.html:141
#: mobile/templates/mobile/mobile_install.html:141
msgid "URL vérifiée"
msgstr "Verified URL"
#: loko/mobile/templates/mobile/mobile_install.html:154
#: mobile/templates/mobile/mobile_install.html:154
msgid ""
"Besoin d'aide ? Contactez le support StreetUp pour être accompagné dans le "
"déploiement."
msgstr "Need help? Contact StreetUp support for deployment assistance."
#: loko/mobile/templates/mobile/qr_scanner.html:5
#: mobile/templates/mobile/qr_scanner.html:5
msgid "Scanner QR"
msgstr "QR scanner"
#: loko/mobile/templates/mobile/qr_scanner.html:92
#: mobile/templates/mobile/qr_scanner.html:92
msgid "Pointez la caméra vers un QR code pour être redirigé automatiquement."
msgstr "Point the camera at a QR code to be automatically redirected."
#: loko/mobile/templates/mobile/qr_scanner.html:102
#: loko/mobile/templates/mobile/qr_scanner.html:147
#: mobile/templates/mobile/qr_scanner.html:102
#: mobile/templates/mobile/qr_scanner.html:147
msgid "Initialisation de la caméra…"
msgstr "Initializing the camera…"
#: loko/mobile/templates/mobile/qr_scanner.html:107
#: mobile/templates/mobile/qr_scanner.html:107
msgid "Ouvrir"
msgstr "Open"
#: loko/mobile/templates/mobile/qr_scanner.html:113
#: mobile/templates/mobile/qr_scanner.html:113
msgid "Réessayer"
msgstr "Try again"
#: loko/mobile/templates/mobile/qr_scanner.html:117
#: mobile/templates/mobile/qr_scanner.html:117
msgid "Démarrer la caméra"
msgstr "Start the camera"
#: loko/mobile/templates/mobile/qr_scanner.html:156
#: loko/mobile/templates/mobile/qr_scanner.html:225
#: loko/mobile/templates/mobile/qr_scanner.html:233
#: mobile/templates/mobile/qr_scanner.html:156
#: mobile/templates/mobile/qr_scanner.html:225
#: mobile/templates/mobile/qr_scanner.html:233
msgid "Pointez vers un QR code…"
msgstr "Point to a QR code…"
#: loko/mobile/templates/mobile/qr_scanner.html:195
#: mobile/templates/mobile/qr_scanner.html:195
msgid "QR Code détecté, résolution…"
msgstr "QR Code detected, resolution…"
#: loko/mobile/templates/mobile/qr_scanner.html:210 loko/mobile/views.py:264
#: mobile/templates/mobile/qr_scanner.html:210 mobile/views.py:264
msgid "QR Code non reconnu."
msgstr "QR Code not recognized."
#: loko/mobile/templates/mobile/qr_scanner.html:213
#: mobile/templates/mobile/qr_scanner.html:213
msgid "Erreur lors de la résolution."
msgstr "Error resolving QR code."
#: loko/mobile/views.py:268
#: mobile/views.py:268
msgid "Format de QR Code invalide."
msgstr "Invalid QR Code format."
#: loko/mobile/views.py:292
#: mobile/views.py:292
msgid "Commande introuvable."
msgstr "Order not found."
#: loko/mobile/views.py:448
#: mobile/views.py:448
msgid "A traiter"
msgstr "To process"
#: loko/mobile/views.py:449
#: mobile/views.py:449
msgid "En attente"
msgstr "On hold"
#: loko/mobile/views.py:450
#: mobile/views.py:450
msgid "Traité"
msgstr "Processed"
#: loko/mobile/views.py:451
#: mobile/views.py:451
msgid "Annulé"
msgstr "Cancelled"
#: loko/mobile/views.py:454
#: mobile/views.py:454
msgid "Urgent"
msgstr "Urgent"
#: loko/mobile/views.py:455
#: mobile/views.py:455
msgid "Elevé"
msgstr "High"
#: loko/mobile/views.py:456
#: mobile/views.py:456
msgid "Normal"
msgstr "Normal"
#: loko/mobile/views.py:457
#: mobile/views.py:457
msgid "Bas"
msgstr "Low"
#: loko/mobile/views.py:607
#: mobile/views.py:607
msgid "Vous n'avez pas la permission d'accéder à cette page."
msgstr "You do not have permission to access this page."
#: loko/mobile/views.py:637
#: mobile/views.py:637
#, python-brace-format
msgid "Issu de l'article {product} du bon de préparation #{order_number}"
msgstr "From the article {product} of the preparation order #{order_number}"
#: loko/mobile/views.py:656
#: mobile/views.py:656
#, python-brace-format
msgid "Issu de l'item #{id} du bon de préparation #{order_number}: {desc}"
msgstr "From item #{id} of preparation order #{order_number}: {desc}"
#: loko/mobile/views.py:685
#: mobile/views.py:685
msgid "Bon de confection créé avec succès."
msgstr "Crafting voucher successfully created."
#: loko/mobile/views.py:745
#: mobile/views.py:745
msgid "Vous n'avez pas la permission d'ajouter une signature à ce lot."
msgstr "You do not have permission to add a signature to this batch."
#: loko/mobile/views.py:761
#: mobile/views.py:761
msgid "Signature enregistrée avec succès."
msgstr "Signature registered successfully."
#: loko/mobile/views.py:847
#: mobile/views.py:847
msgid "Veuillez sélectionner un emplacement."
msgstr "Please select a location."
#: loko/mobile/views.py:854
#: mobile/views.py:854
msgid "Emplacement invalide ou non accessible."
msgstr "Invalid or inaccessible location."
#: loko/mobile/views.py:875
#: mobile/views.py:875
msgid "Inventaire créé avec succès."
msgstr "Inventory created successfully."
#: loko/mobile/views.py:976
#: mobile/views.py:976
msgid "Document(s) ajouté(s) avec succès."
msgstr "Document(s) added successfully."

View file

@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: 2025-12-04 12:00+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: French <LL@li.org>\n"
@ -16,177 +16,177 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:240
#: mobile/templates/mobile/green_surfaces_edit_v2.html:240
msgid "Espaces verts - V2"
msgstr "Espaces verts - V2"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:254
#: mobile/templates/mobile/green_surfaces_edit_v2.html:254
msgid "Édition des espaces verts"
msgstr "Édition des espaces verts"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:269
#: mobile/templates/mobile/green_surfaces_edit_v2.html:269
msgid "géométrie(s) modifiée(s)"
msgstr "géométrie(s) modifiée(s)"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:274
#: mobile/templates/mobile/green_surfaces_edit_v2.html:274
msgid "élément(s) sélectionné(s)"
msgstr "élément(s) sélectionné(s)"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:275
#: mobile/templates/mobile/green_surfaces_edit_v2.html:275
msgid ""
"Sélectionnez un modèle ci-dessous pour l'appliquer aux éléments sélectionnés."
msgstr ""
"Sélectionnez un modèle ci-dessous pour l'appliquer aux éléments sélectionnés."
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:280
#: mobile/templates/mobile/green_surfaces_edit_v2.html:280
msgid "Édition des attributs"
msgstr "Édition des attributs"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:288
#: mobile/templates/mobile/green_surfaces_edit_v2.html:288
msgid "Modèle"
msgstr "Modèle"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:303
#: mobile/templates/mobile/green_surfaces_edit_v2.html:303
msgid "Types de bulbes"
msgstr "Types de bulbes"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:325
#: mobile/templates/mobile/green_surfaces_edit_v2.html:325
msgid "Enregistrer"
msgstr "Enregistrer"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:328
#: mobile/templates/mobile/green_surfaces_edit_v2.html:328
msgid "Désélectionner"
msgstr "Désélectionner"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:338
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:986
#: mobile/templates/mobile/green_surfaces_edit_v2.html:338
#: mobile/templates/mobile/green_surfaces_edit_v2.html:986
msgid "Mode dessin"
msgstr "Mode dessin"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:339
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1519
#: mobile/templates/mobile/green_surfaces_edit_v2.html:339
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1519
msgid "Inactif"
msgstr "Inactif"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:342
#: mobile/templates/mobile/green_surfaces_edit_v2.html:342
msgid "Modifications"
msgstr "Modifications"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:348
#: mobile/templates/mobile/green_surfaces_edit_v2.html:348
msgid "Assets chargés"
msgstr "Assets chargés"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:352
#: mobile/templates/mobile/green_surfaces_edit_v2.html:352
msgid "En édition"
msgstr "En édition"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:723
#: mobile/templates/mobile/green_surfaces_edit_v2.html:723
msgid "Sélection multiple"
msgstr "Sélection multiple"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:738
#: mobile/templates/mobile/green_surfaces_edit_v2.html:738
msgid "Aucune modification à enregistrer"
msgstr "Aucune modification à enregistrer"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:792
#: mobile/templates/mobile/green_surfaces_edit_v2.html:792
msgid "Géométries enregistrées avec succès"
msgstr "Géométries enregistrées avec succès"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:794
#: mobile/templates/mobile/green_surfaces_edit_v2.html:794
msgid "modifié(s)"
msgstr "modifié(s)"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:797
#: mobile/templates/mobile/green_surfaces_edit_v2.html:797
msgid "supprimé(s)"
msgstr "supprimé(s)"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:830
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:908
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:913
#: mobile/templates/mobile/green_surfaces_edit_v2.html:830
#: mobile/templates/mobile/green_surfaces_edit_v2.html:908
#: mobile/templates/mobile/green_surfaces_edit_v2.html:913
msgid "Erreur lors de la sauvegarde"
msgstr "Erreur lors de la sauvegarde"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:835
#: mobile/templates/mobile/green_surfaces_edit_v2.html:835
msgid "Erreur lors de la sauvegarde des géométries"
msgstr "Erreur lors de la sauvegarde des géométries"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:868
#: mobile/templates/mobile/green_surfaces_edit_v2.html:868
msgid "Aucun élément sélectionné"
msgstr "Aucun élément sélectionné"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:873
#: mobile/templates/mobile/green_surfaces_edit_v2.html:873
msgid "Veuillez sélectionner un modèle ou des types de bulbes"
msgstr "Veuillez sélectionner un modèle ou des types de bulbes"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:898
#: mobile/templates/mobile/green_surfaces_edit_v2.html:898
msgid "Modifications enregistrées avec succès"
msgstr "Modifications enregistrées avec succès"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:987
#: mobile/templates/mobile/green_surfaces_edit_v2.html:987
msgid "Ajouter un polygone"
msgstr "Ajouter un polygone"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:988
#: mobile/templates/mobile/green_surfaces_edit_v2.html:988
msgid "Supprimer les géométries sélectionnées"
msgstr "Supprimer les géométries sélectionnées"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:989
#: mobile/templates/mobile/green_surfaces_edit_v2.html:989
msgid "Aimantage (Snap)"
msgstr "Aimantage (Snap)"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:990
#: mobile/templates/mobile/green_surfaces_edit_v2.html:990
msgid "Aimantage activé"
msgstr "Aimantage activé"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:991
#: mobile/templates/mobile/green_surfaces_edit_v2.html:991
msgid "Aimantage désactivé"
msgstr "Aimantage désactivé"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:992
#: mobile/templates/mobile/green_surfaces_edit_v2.html:992
msgid "Découper un polygone"
msgstr "Découper un polygone"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:993
#: mobile/templates/mobile/green_surfaces_edit_v2.html:993
msgid "Découpage annulé"
msgstr "Découpage annulé"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:994
#: mobile/templates/mobile/green_surfaces_edit_v2.html:994
msgid "Polygone découpé avec succès"
msgstr "Polygone découpé avec succès"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:995
#: mobile/templates/mobile/green_surfaces_edit_v2.html:995
msgid "Fusionner les polygones sélectionnés"
msgstr "Fusionner les polygones sélectionnés"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:996
#: mobile/templates/mobile/green_surfaces_edit_v2.html:996
msgid "Polygones fusionnés avec succès"
msgstr "Polygones fusionnés avec succès"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:997
#: mobile/templates/mobile/green_surfaces_edit_v2.html:997
msgid "Enregistrer les modifications"
msgstr "Enregistrer les modifications"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:998
#: mobile/templates/mobile/green_surfaces_edit_v2.html:998
msgid "Annuler"
msgstr "Annuler"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:999
#: mobile/templates/mobile/green_surfaces_edit_v2.html:999
msgid "Aucune géométrie à supprimer"
msgstr "Aucune géométrie à supprimer"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1000
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1000
msgid "Géométrie(s) supprimée(s)"
msgstr "Géométrie(s) supprimée(s)"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1001
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1001
msgid "Mode dessin activé - Cliquez sur une géométrie pour l'éditer"
msgstr "Mode dessin activé - Cliquez sur une géométrie pour l'éditer"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1002
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1002
msgid "Mode dessin désactivé"
msgstr "Mode dessin désactivé"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1003
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1003
msgid ""
"Cliquez pour ajouter des points. Double-cliquez ou cliquez sur le premier "
"point pour terminer."
@ -194,59 +194,59 @@ msgstr ""
"Cliquez pour ajouter des points. Double-cliquez ou cliquez sur le premier "
"point pour terminer."
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1004
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1004
msgid ""
"Tracez une ligne pour découper le polygone. Double-cliquez pour terminer."
msgstr ""
"Tracez une ligne pour découper le polygone. Double-cliquez pour terminer."
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1107
#: loko/mobile/templates/mobile/mobile_index.html:146
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1107
#: mobile/templates/mobile/mobile_index.html:146
msgid "Espaces verts"
msgstr "Espaces verts"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1116
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1116
msgid "Arbres"
msgstr "Arbres"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1436
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1436
msgid "Erreur lors du rechargement des données"
msgstr "Erreur lors du rechargement des données"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1511
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1511
msgid "Erreur lors du chargement des données"
msgstr "Erreur lors du chargement des données"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1519
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1519
msgid "Actif"
msgstr "Actif"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1722
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1723
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1722
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1723
msgid "Quitter"
msgstr "Quitter"
#: loko/mobile/templates/mobile/mobile_base.html:220
#: mobile/templates/mobile/mobile_base.html:220
msgid "Chargement..."
msgstr "Chargement..."
#: loko/mobile/templates/mobile/mobile_base.html:244
#: mobile/templates/mobile/mobile_base.html:244
msgid "Notifications"
msgstr "Notifications"
#: loko/mobile/templates/mobile/mobile_base.html:250
#: mobile/templates/mobile/mobile_base.html:250
msgid "notifications non lues"
msgstr "notifications non lues"
#: loko/mobile/templates/mobile/mobile_base.html:256
#: mobile/templates/mobile/mobile_base.html:256
msgid "Scanner un QR Code"
msgstr "Scanner un QR Code"
#: loko/mobile/templates/mobile/mobile_index.html:17
#: mobile/templates/mobile/mobile_index.html:17
msgid "Notifications non lues"
msgstr "Notifications non lues"
#: loko/mobile/templates/mobile/mobile_index.html:20
#: mobile/templates/mobile/mobile_index.html:20
#, python-format
msgid ""
"\n"
@ -261,194 +261,195 @@ msgid_plural ""
msgstr[0] ""
msgstr[1] ""
#: loko/mobile/templates/mobile/mobile_index.html:29
#: mobile/templates/mobile/mobile_index.html:29
msgid "Consulter"
msgstr "Consulter"
#: loko/mobile/templates/mobile/mobile_index.html:40
#: mobile/templates/mobile/mobile_index.html:40
msgid "Nouveaux éléments"
msgstr "Nouveaux éléments"
#: loko/mobile/templates/mobile/mobile_index.html:45
#: mobile/templates/mobile/mobile_index.html:45
msgid "Nouvelle observation"
msgstr "Nouvelle observation"
#: loko/mobile/templates/mobile/mobile_index.html:52
#: mobile/templates/mobile/mobile_index.html:52
msgid "Nouvelle inspection"
msgstr "Nouvelle inspection"
#: loko/mobile/templates/mobile/mobile_index.html:59
#: mobile/templates/mobile/mobile_index.html:59
msgid "Intervention Réparation"
msgstr "Intervention Réparation"
#: loko/mobile/templates/mobile/mobile_index.html:66
#: mobile/templates/mobile/mobile_index.html:66
msgid "Nouvelle intervention"
msgstr "Nouvelle intervention"
#: loko/mobile/templates/mobile/mobile_index.html:72
#: mobile/templates/mobile/mobile_index.html:72
msgid "Nouvelle discussion"
msgstr "Nouvelle discussion"
#: loko/mobile/templates/mobile/mobile_index.html:86
#: mobile/templates/mobile/mobile_index.html:86
msgid "Interventions"
msgstr "Interventions"
#: loko/mobile/templates/mobile/mobile_index.html:87
#: mobile/templates/mobile/mobile_index.html:87
msgid "Consulter et suivre les interventions en cours"
msgstr "Consulter et suivre les interventions en cours"
#: loko/mobile/templates/mobile/mobile_index.html:97
#: mobile/templates/mobile/mobile_index.html:97
msgid "Contrôles"
msgstr "Contrôles"
#: loko/mobile/templates/mobile/mobile_index.html:98
#: mobile/templates/mobile/mobile_index.html:98
msgid "Accéder aux contrôles terrain"
msgstr "Accéder aux contrôles terrain"
#: loko/mobile/templates/mobile/mobile_index.html:109
#: mobile/templates/mobile/mobile_index.html:109
msgid "Projets"
msgstr "Projets"
#: loko/mobile/templates/mobile/mobile_index.html:110
#: mobile/templates/mobile/mobile_index.html:110
msgid "Suivre l'état des projets"
msgstr "Suivre l'état des projets"
#: loko/mobile/templates/mobile/mobile_index.html:121
#: mobile/templates/mobile/mobile_index.html:121
msgid "Observations"
msgstr "Observations"
#: loko/mobile/templates/mobile/mobile_index.html:122
#: mobile/templates/mobile/mobile_index.html:122
msgid "Consulter et ajouter des observations terrain"
msgstr "Consulter et ajouter des observations terrain"
#: loko/mobile/templates/mobile/mobile_index.html:133
#: mobile/templates/mobile/mobile_index.html:133
msgid "Inspections d'assets"
msgstr "Inspections d'assets"
#: loko/mobile/templates/mobile/mobile_index.html:134
#: mobile/templates/mobile/mobile_index.html:134
msgid "Consulter la liste et l'historique des vérifications d'assets"
msgstr "Consulter la liste et l'historique des vérifications d'assets"
#: loko/mobile/templates/mobile/mobile_index.html:147
#: mobile/templates/mobile/mobile_index.html:147
msgid "Éditer les espaces verts"
msgstr "Éditer les espaces verts"
#: loko/mobile/templates/mobile/mobile_index.html:158
#: mobile/templates/mobile/mobile_index.html:158
msgid "Stock"
msgstr "Stock"
#: loko/mobile/templates/mobile/mobile_index.html:159
#: mobile/templates/mobile/mobile_index.html:159
msgid "Gérer les produits, commandes et mouvements de stock"
msgstr "Gérer les produits, commandes et mouvements de stock"
#: loko/mobile/templates/mobile/mobile_install.html:8
#: mobile/templates/mobile/mobile_install.html:8
msgid "Installer"
msgstr "Installer"
#: loko/mobile/templates/mobile/mobile_install.html:64
#: mobile/templates/mobile/mobile_install.html:64
msgid "Installez l'application en 3 options"
msgstr "Installez l'application en 3 options"
#: loko/mobile/templates/mobile/mobile_install.html:65
#: mobile/templates/mobile/mobile_install.html:65
msgid ""
"Choisissez la méthode la plus adaptée à votre appareil ou à votre usage."
msgstr ""
"Choisissez la méthode la plus adaptée à votre appareil ou à votre usage."
#: loko/mobile/templates/mobile/mobile_install.html:76
#: mobile/templates/mobile/mobile_install.html:76
msgid "Télécharger l'APK Android"
msgstr "Télécharger l'APK Android"
#: loko/mobile/templates/mobile/mobile_install.html:77
#: mobile/templates/mobile/mobile_install.html:77
msgid "Installez la version native (recommandé pour les appareils de terrain)."
msgstr ""
"Installez la version native (recommandé pour les appareils de "
"terrain).Installez la version native (recommandé pour les appareils de "
"terrain)."
#: loko/mobile/templates/mobile/mobile_install.html:79
#: mobile/templates/mobile/mobile_install.html:79
msgid "Appuyez sur le bouton ci-dessous pour lancer le téléchargement."
msgstr "Appuyez sur le bouton ci-dessous pour lancer le téléchargement."
#: loko/mobile/templates/mobile/mobile_install.html:80
#: mobile/templates/mobile/mobile_install.html:80
msgid ""
"Autorisez l'installation depuis des sources inconnues si Android le demande."
msgstr ""
"Autorisez l'installation depuis des sources inconnues si Android le demande."
#: loko/mobile/templates/mobile/mobile_install.html:81
#: mobile/templates/mobile/mobile_install.html:81
msgid "Ouvrez le fichier loko-app.apk et confirmez l'installation."
msgstr "Ouvrez le fichier loko-app.apk et confirmez l'installation."
#: loko/mobile/templates/mobile/mobile_install.html:84
#: mobile/templates/mobile/mobile_install.html:84
msgid "Télécharger l'APK"
msgstr "Télécharger l'APK"
#: loko/mobile/templates/mobile/mobile_install.html:94
#: mobile/templates/mobile/mobile_install.html:94
msgid "Installer la PWA"
msgstr "Installer la PWA"
#: loko/mobile/templates/mobile/mobile_install.html:95
#: mobile/templates/mobile/mobile_install.html:95
msgid "Ajoutez l'application sur l'écran d'accueil sans passer par un store."
msgstr "Ajoutez l'application sur l'écran d'accueil sans passer par un store."
#: loko/mobile/templates/mobile/mobile_install.html:97
#: mobile/templates/mobile/mobile_install.html:97
msgid ""
"Ouvrez l'application dans votre navigateur mobile (Chrome, Edge, Safari)."
msgstr "Ouvrez l'application dans votre navigateur mobile (Chrome, Edge, Safari)."
msgstr ""
"Ouvrez l'application dans votre navigateur mobile (Chrome, Edge, Safari)."
#: loko/mobile/templates/mobile/mobile_install.html:98
#: mobile/templates/mobile/mobile_install.html:98
msgid "Dans la barre d'adresse, choisissez “Ajouter à l'écran d'accueil”."
msgstr "Dans la barre d'adresse, choisissez “Ajouter à l'écran d'accueil”."
#: loko/mobile/templates/mobile/mobile_install.html:99
#: mobile/templates/mobile/mobile_install.html:99
msgid "Confirmez : l'icône apparaît comme une application."
msgstr "Confirmez : l'icône apparaît comme une application."
#: loko/mobile/templates/mobile/mobile_install.html:103
#: mobile/templates/mobile/mobile_install.html:103
msgid "Assurez-vous d'accepter l'installation quand la bannière PWA s'affiche."
msgstr ""
"Assurez-vous d'accepter l'installation quand la bannière PWA "
"s'affiche.Assurez-vous d'accepter l'installation quand la bannière PWA "
"s'affiche."
#: loko/mobile/templates/mobile/mobile_install.html:106
#: mobile/templates/mobile/mobile_install.html:106
msgid "Ouvrir l'application"
msgstr "Ouvrir l'application"
#: loko/mobile/templates/mobile/mobile_install.html:116
#: mobile/templates/mobile/mobile_install.html:116
msgid "Utiliser la version web"
msgstr "Utiliser la version web"
#: loko/mobile/templates/mobile/mobile_install.html:117
#: mobile/templates/mobile/mobile_install.html:117
msgid "Accédez directement à l'application mobile depuis votre navigateur."
msgstr "Accédez directement à l'application mobile depuis votre navigateur."
#: loko/mobile/templates/mobile/mobile_install.html:119
#: mobile/templates/mobile/mobile_install.html:119
msgid "Tapez l'adresse"
msgstr "Tapez l'adresse"
#: loko/mobile/templates/mobile/mobile_install.html:119
#: mobile/templates/mobile/mobile_install.html:119
msgid "une fois connecté(e) à StreetUp."
msgstr "une fois connecté(e) à StreetUp."
#: loko/mobile/templates/mobile/mobile_install.html:120
#: mobile/templates/mobile/mobile_install.html:120
msgid "Ajoutez un favori pour y revenir en un geste."
msgstr "Ajoutez un favori pour y revenir en un geste."
#: loko/mobile/templates/mobile/mobile_install.html:121
#: mobile/templates/mobile/mobile_install.html:121
msgid "Compatible bureau et tablette."
msgstr "Compatible bureau et tablette."
#: loko/mobile/templates/mobile/mobile_install.html:124
#: mobile/templates/mobile/mobile_install.html:124
msgid "Aller vers /mobile/"
msgstr "Aller vers /mobile/"
#: loko/mobile/templates/mobile/mobile_install.html:136
#: mobile/templates/mobile/mobile_install.html:136
msgid "Scanner pour ouvrir cette page"
msgstr "Scanner pour ouvrir cette page"
#: loko/mobile/templates/mobile/mobile_install.html:138
#: mobile/templates/mobile/mobile_install.html:138
msgid ""
"Pointez l'appareil photo de votre smartphone sur ce QR code pour accéder "
"instantanément aux instructions d'installation."
@ -456,11 +457,11 @@ msgstr ""
"Pointez l'appareil photo de votre smartphone sur ce QR code pour accéder "
"instantanément aux instructions d'installation."
#: loko/mobile/templates/mobile/mobile_install.html:141
#: mobile/templates/mobile/mobile_install.html:141
msgid "URL vérifiée"
msgstr "URL vérifiée"
#: loko/mobile/templates/mobile/mobile_install.html:154
#: mobile/templates/mobile/mobile_install.html:154
msgid ""
"Besoin d'aide ? Contactez le support StreetUp pour être accompagné dans le "
"déploiement."
@ -468,128 +469,128 @@ msgstr ""
"Besoin d'aide ? Contactez le support StreetUp pour être accompagné dans le "
"déploiement."
#: loko/mobile/templates/mobile/qr_scanner.html:5
#: mobile/templates/mobile/qr_scanner.html:5
msgid "Scanner QR"
msgstr "Scanner QR"
#: loko/mobile/templates/mobile/qr_scanner.html:92
#: mobile/templates/mobile/qr_scanner.html:92
msgid "Pointez la caméra vers un QR code pour être redirigé automatiquement."
msgstr "Pointez la caméra vers un QR code pour être redirigé automatiquement."
#: loko/mobile/templates/mobile/qr_scanner.html:102
#: loko/mobile/templates/mobile/qr_scanner.html:147
#: mobile/templates/mobile/qr_scanner.html:102
#: mobile/templates/mobile/qr_scanner.html:147
msgid "Initialisation de la caméra…"
msgstr "Initialisation de la caméra…"
#: loko/mobile/templates/mobile/qr_scanner.html:107
#: mobile/templates/mobile/qr_scanner.html:107
msgid "Ouvrir"
msgstr "Ouvrir"
#: loko/mobile/templates/mobile/qr_scanner.html:113
#: mobile/templates/mobile/qr_scanner.html:113
msgid "Réessayer"
msgstr "Réessayer"
#: loko/mobile/templates/mobile/qr_scanner.html:117
#: mobile/templates/mobile/qr_scanner.html:117
msgid "Démarrer la caméra"
msgstr "Démarrer la caméra"
#: loko/mobile/templates/mobile/qr_scanner.html:156
#: loko/mobile/templates/mobile/qr_scanner.html:225
#: loko/mobile/templates/mobile/qr_scanner.html:233
#: mobile/templates/mobile/qr_scanner.html:156
#: mobile/templates/mobile/qr_scanner.html:225
#: mobile/templates/mobile/qr_scanner.html:233
msgid "Pointez vers un QR code…"
msgstr "Pointez vers un QR code…"
#: loko/mobile/templates/mobile/qr_scanner.html:195
#: mobile/templates/mobile/qr_scanner.html:195
msgid "QR Code détecté, résolution…"
msgstr "QR Code détecté, résolution…"
#: loko/mobile/templates/mobile/qr_scanner.html:210 loko/mobile/views.py:264
#: mobile/templates/mobile/qr_scanner.html:210 mobile/views.py:264
msgid "QR Code non reconnu."
msgstr "QR Code non reconnu."
#: loko/mobile/templates/mobile/qr_scanner.html:213
#: mobile/templates/mobile/qr_scanner.html:213
msgid "Erreur lors de la résolution."
msgstr "Erreur lors de la résolution."
#: loko/mobile/views.py:268
#: mobile/views.py:268
msgid "Format de QR Code invalide."
msgstr "Format de QR Code invalide."
#: loko/mobile/views.py:292
#: mobile/views.py:292
msgid "Commande introuvable."
msgstr "Commande introuvable."
#: loko/mobile/views.py:448
#: mobile/views.py:448
msgid "A traiter"
msgstr "A traiter"
#: loko/mobile/views.py:449
#: mobile/views.py:449
msgid "En attente"
msgstr "En attente"
#: loko/mobile/views.py:450
#: mobile/views.py:450
msgid "Traité"
msgstr "Traité"
#: loko/mobile/views.py:451
#: mobile/views.py:451
msgid "Annulé"
msgstr "Annulé"
#: loko/mobile/views.py:454
#: mobile/views.py:454
msgid "Urgent"
msgstr "Urgent"
#: loko/mobile/views.py:455
#: mobile/views.py:455
msgid "Elevé"
msgstr "Elevé"
#: loko/mobile/views.py:456
#: mobile/views.py:456
msgid "Normal"
msgstr "Normal"
#: loko/mobile/views.py:457
#: mobile/views.py:457
msgid "Bas"
msgstr "Bas"
#: loko/mobile/views.py:607
#: mobile/views.py:607
msgid "Vous n'avez pas la permission d'accéder à cette page."
msgstr "Vous n'avez pas la permission d'accéder à cette page."
#: loko/mobile/views.py:637
#: mobile/views.py:637
#, python-brace-format
msgid "Issu de l'article {product} du bon de préparation #{order_number}"
msgstr "Issu de l'article {product} du bon de préparation #{order_number}"
#: loko/mobile/views.py:656
#: mobile/views.py:656
#, python-brace-format
msgid "Issu de l'item #{id} du bon de préparation #{order_number}: {desc}"
msgstr "Issu de l'item #{id} du bon de préparation #{order_number}: {desc}"
#: loko/mobile/views.py:685
#: mobile/views.py:685
msgid "Bon de confection créé avec succès."
msgstr "Bon de confection créé avec succès."
#: loko/mobile/views.py:745
#: mobile/views.py:745
msgid "Vous n'avez pas la permission d'ajouter une signature à ce lot."
msgstr "Vous n'avez pas la permission d'ajouter une signature à ce lot."
#: loko/mobile/views.py:761
#: mobile/views.py:761
msgid "Signature enregistrée avec succès."
msgstr "Signature enregistrée avec succès."
#: loko/mobile/views.py:847
#: mobile/views.py:847
msgid "Veuillez sélectionner un emplacement."
msgstr "Veuillez sélectionner un emplacement."
#: loko/mobile/views.py:854
#: mobile/views.py:854
msgid "Emplacement invalide ou non accessible."
msgstr "Emplacement invalide ou non accessible."
#: loko/mobile/views.py:875
#: mobile/views.py:875
msgid "Inventaire créé avec succès."
msgstr "Inventaire créé avec succès."
#: loko/mobile/views.py:976
#: mobile/views.py:976
msgid "Document(s) ajouté(s) avec succès."
msgstr "Document(s) ajouté(s) avec succès."

View file

@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-08-17 11:56+0200\n"
"POT-Creation-Date: 2026-08-19 09:47+0200\n"
"PO-Revision-Date: 2025-12-04 12:00+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Dutch <LL@li.org>\n"
@ -16,177 +16,177 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:240
#: mobile/templates/mobile/green_surfaces_edit_v2.html:240
msgid "Espaces verts - V2"
msgstr "Groene ruimtes - V2"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:254
#: mobile/templates/mobile/green_surfaces_edit_v2.html:254
msgid "Édition des espaces verts"
msgstr "Bewerking van groene ruimtes"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:269
#: mobile/templates/mobile/green_surfaces_edit_v2.html:269
msgid "géométrie(s) modifiée(s)"
msgstr "gewijzigde geometrie(ën)"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:274
#: mobile/templates/mobile/green_surfaces_edit_v2.html:274
msgid "élément(s) sélectionné(s)"
msgstr "geselecteerde elementen"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:275
#: mobile/templates/mobile/green_surfaces_edit_v2.html:275
msgid ""
"Sélectionnez un modèle ci-dessous pour l'appliquer aux éléments sélectionnés."
msgstr ""
"Selecteer een model hieronder om toe te passen op de geselecteerde items."
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:280
#: mobile/templates/mobile/green_surfaces_edit_v2.html:280
msgid "Édition des attributs"
msgstr "Bewerking van attributen"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:288
#: mobile/templates/mobile/green_surfaces_edit_v2.html:288
msgid "Modèle"
msgstr "Model"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:303
#: mobile/templates/mobile/green_surfaces_edit_v2.html:303
msgid "Types de bulbes"
msgstr "Soorten lampen"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:325
#: mobile/templates/mobile/green_surfaces_edit_v2.html:325
msgid "Enregistrer"
msgstr "Opslaan"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:328
#: mobile/templates/mobile/green_surfaces_edit_v2.html:328
msgid "Désélectionner"
msgstr "Deselekteer"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:338
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:986
#: mobile/templates/mobile/green_surfaces_edit_v2.html:338
#: mobile/templates/mobile/green_surfaces_edit_v2.html:986
msgid "Mode dessin"
msgstr "Tekenmodus"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:339
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1519
#: mobile/templates/mobile/green_surfaces_edit_v2.html:339
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1519
msgid "Inactif"
msgstr "Inactief"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:342
#: mobile/templates/mobile/green_surfaces_edit_v2.html:342
msgid "Modifications"
msgstr "Wijzigingen"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:348
#: mobile/templates/mobile/green_surfaces_edit_v2.html:348
msgid "Assets chargés"
msgstr "Assets geladen"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:352
#: mobile/templates/mobile/green_surfaces_edit_v2.html:352
msgid "En édition"
msgstr "In bewerking"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:723
#: mobile/templates/mobile/green_surfaces_edit_v2.html:723
msgid "Sélection multiple"
msgstr "Meervoudige selectie"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:738
#: mobile/templates/mobile/green_surfaces_edit_v2.html:738
msgid "Aucune modification à enregistrer"
msgstr "Geen wijzigingen om op te slaan"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:792
#: mobile/templates/mobile/green_surfaces_edit_v2.html:792
msgid "Géométries enregistrées avec succès"
msgstr "Geometrieën succesvol opgeslagen"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:794
#: mobile/templates/mobile/green_surfaces_edit_v2.html:794
msgid "modifié(s)"
msgstr "gewijzigd"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:797
#: mobile/templates/mobile/green_surfaces_edit_v2.html:797
msgid "supprimé(s)"
msgstr "verwijderd"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:830
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:908
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:913
#: mobile/templates/mobile/green_surfaces_edit_v2.html:830
#: mobile/templates/mobile/green_surfaces_edit_v2.html:908
#: mobile/templates/mobile/green_surfaces_edit_v2.html:913
msgid "Erreur lors de la sauvegarde"
msgstr "Fout bij het opslaan"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:835
#: mobile/templates/mobile/green_surfaces_edit_v2.html:835
msgid "Erreur lors de la sauvegarde des géométries"
msgstr "Fout bij het opslaan van de geometrieën"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:868
#: mobile/templates/mobile/green_surfaces_edit_v2.html:868
msgid "Aucun élément sélectionné"
msgstr "Geen item geselecteerd"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:873
#: mobile/templates/mobile/green_surfaces_edit_v2.html:873
msgid "Veuillez sélectionner un modèle ou des types de bulbes"
msgstr "Selecteer een model"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:898
#: mobile/templates/mobile/green_surfaces_edit_v2.html:898
msgid "Modifications enregistrées avec succès"
msgstr "Wijzigingen succesvol opgeslagen"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:987
#: mobile/templates/mobile/green_surfaces_edit_v2.html:987
msgid "Ajouter un polygone"
msgstr "Voeg een polygoon toe"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:988
#: mobile/templates/mobile/green_surfaces_edit_v2.html:988
msgid "Supprimer les géométries sélectionnées"
msgstr "Verwijder de geselecteerde geometrieën"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:989
#: mobile/templates/mobile/green_surfaces_edit_v2.html:989
msgid "Aimantage (Snap)"
msgstr "Uitlijnen (Snap)"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:990
#: mobile/templates/mobile/green_surfaces_edit_v2.html:990
msgid "Aimantage activé"
msgstr "Uitlijnen ingeschakeld"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:991
#: mobile/templates/mobile/green_surfaces_edit_v2.html:991
msgid "Aimantage désactivé"
msgstr "Uitlijnen uitgeschakeld"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:992
#: mobile/templates/mobile/green_surfaces_edit_v2.html:992
msgid "Découper un polygone"
msgstr "Een polygoon knippen"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:993
#: mobile/templates/mobile/green_surfaces_edit_v2.html:993
msgid "Découpage annulé"
msgstr "Knippen geannuleerd"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:994
#: mobile/templates/mobile/green_surfaces_edit_v2.html:994
msgid "Polygone découpé avec succès"
msgstr "Polygoon succesvol geknipt"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:995
#: mobile/templates/mobile/green_surfaces_edit_v2.html:995
msgid "Fusionner les polygones sélectionnés"
msgstr "Geselecteerde polygonen samenvoegen"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:996
#: mobile/templates/mobile/green_surfaces_edit_v2.html:996
msgid "Polygones fusionnés avec succès"
msgstr "Polygonen succesvol samengevoegd"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:997
#: mobile/templates/mobile/green_surfaces_edit_v2.html:997
msgid "Enregistrer les modifications"
msgstr "Wijzigingen opslaan"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:998
#: mobile/templates/mobile/green_surfaces_edit_v2.html:998
msgid "Annuler"
msgstr "Annuleren"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:999
#: mobile/templates/mobile/green_surfaces_edit_v2.html:999
msgid "Aucune géométrie à supprimer"
msgstr "Geen geometrieën om te verwijderen"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1000
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1000
msgid "Géométrie(s) supprimée(s)"
msgstr "Geometrie(s) verwijderd"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1001
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1001
msgid "Mode dessin activé - Cliquez sur une géométrie pour l'éditer"
msgstr "Tekenmodus ingeschakeld - Klik op een geometrie om deze te bewerken"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1002
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1002
msgid "Mode dessin désactivé"
msgstr "Tekenmodus uitgeschakeld"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1003
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1003
msgid ""
"Cliquez pour ajouter des points. Double-cliquez ou cliquez sur le premier "
"point pour terminer."
@ -194,58 +194,58 @@ msgstr ""
"Klik om punten toe te voegen. Dubbelklik of klik op het eerste punt om te "
"voltooien."
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1004
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1004
msgid ""
"Tracez une ligne pour découper le polygone. Double-cliquez pour terminer."
msgstr "Teken een lijn om de polygoon te knippen. Dubbelklik om te voltooien."
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1107
#: loko/mobile/templates/mobile/mobile_index.html:146
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1107
#: mobile/templates/mobile/mobile_index.html:146
msgid "Espaces verts"
msgstr "Groene ruimtes"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1116
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1116
msgid "Arbres"
msgstr "Bomen"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1436
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1436
msgid "Erreur lors du rechargement des données"
msgstr "Fout bij het opnieuw laden van gegevens"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1511
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1511
msgid "Erreur lors du chargement des données"
msgstr "Fout bij het laden van gegevens"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1519
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1519
msgid "Actif"
msgstr "Actief"
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1722
#: loko/mobile/templates/mobile/green_surfaces_edit_v2.html:1723
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1722
#: mobile/templates/mobile/green_surfaces_edit_v2.html:1723
msgid "Quitter"
msgstr "Afsluiten"
#: loko/mobile/templates/mobile/mobile_base.html:220
#: mobile/templates/mobile/mobile_base.html:220
msgid "Chargement..."
msgstr "Laden..."
#: loko/mobile/templates/mobile/mobile_base.html:244
#: mobile/templates/mobile/mobile_base.html:244
msgid "Notifications"
msgstr "Meldingen"
#: loko/mobile/templates/mobile/mobile_base.html:250
#: mobile/templates/mobile/mobile_base.html:250
msgid "notifications non lues"
msgstr "ongelezen meldingen"
#: loko/mobile/templates/mobile/mobile_base.html:256
#: mobile/templates/mobile/mobile_base.html:256
msgid "Scanner un QR Code"
msgstr "Scan een QR-code"
#: loko/mobile/templates/mobile/mobile_index.html:17
#: mobile/templates/mobile/mobile_index.html:17
msgid "Notifications non lues"
msgstr "Ongelezen meldingen"
#: loko/mobile/templates/mobile/mobile_index.html:20
#: mobile/templates/mobile/mobile_index.html:20
#, python-format
msgid ""
"\n"
@ -260,187 +260,188 @@ msgid_plural ""
msgstr[0] ""
msgstr[1] ""
#: loko/mobile/templates/mobile/mobile_index.html:29
#: mobile/templates/mobile/mobile_index.html:29
msgid "Consulter"
msgstr "Bekijken"
#: loko/mobile/templates/mobile/mobile_index.html:40
#: mobile/templates/mobile/mobile_index.html:40
msgid "Nouveaux éléments"
msgstr "Nieuwe artikelen"
#: loko/mobile/templates/mobile/mobile_index.html:45
#: mobile/templates/mobile/mobile_index.html:45
msgid "Nouvelle observation"
msgstr "Nieuwe observatie"
#: loko/mobile/templates/mobile/mobile_index.html:52
#: mobile/templates/mobile/mobile_index.html:52
msgid "Nouvelle inspection"
msgstr "Nieuwe inspectie"
#: loko/mobile/templates/mobile/mobile_index.html:59
#: mobile/templates/mobile/mobile_index.html:59
msgid "Intervention Réparation"
msgstr "Reparatie-interventie"
#: loko/mobile/templates/mobile/mobile_index.html:66
#: mobile/templates/mobile/mobile_index.html:66
msgid "Nouvelle intervention"
msgstr "Nieuwe interventie"
#: loko/mobile/templates/mobile/mobile_index.html:72
#: mobile/templates/mobile/mobile_index.html:72
msgid "Nouvelle discussion"
msgstr "Nieuw gesprek"
#: loko/mobile/templates/mobile/mobile_index.html:86
#: mobile/templates/mobile/mobile_index.html:86
msgid "Interventions"
msgstr "Interventies"
#: loko/mobile/templates/mobile/mobile_index.html:87
#: mobile/templates/mobile/mobile_index.html:87
msgid "Consulter et suivre les interventions en cours"
msgstr "Lopende interventies bekijken en volgen"
#: loko/mobile/templates/mobile/mobile_index.html:97
#: mobile/templates/mobile/mobile_index.html:97
msgid "Contrôles"
msgstr "Controles"
#: loko/mobile/templates/mobile/mobile_index.html:98
#: mobile/templates/mobile/mobile_index.html:98
msgid "Accéder aux contrôles terrain"
msgstr "Toegang tot veldcontroles"
#: loko/mobile/templates/mobile/mobile_index.html:109
#: mobile/templates/mobile/mobile_index.html:109
msgid "Projets"
msgstr "Projecten"
#: loko/mobile/templates/mobile/mobile_index.html:110
#: mobile/templates/mobile/mobile_index.html:110
msgid "Suivre l'état des projets"
msgstr "Projectstatus volgen"
#: loko/mobile/templates/mobile/mobile_index.html:121
#: mobile/templates/mobile/mobile_index.html:121
msgid "Observations"
msgstr "Observaties"
#: loko/mobile/templates/mobile/mobile_index.html:122
#: mobile/templates/mobile/mobile_index.html:122
msgid "Consulter et ajouter des observations terrain"
msgstr "Veldobservaties bekijken en toevoegen"
#: loko/mobile/templates/mobile/mobile_index.html:133
#: mobile/templates/mobile/mobile_index.html:133
msgid "Inspections d'assets"
msgstr "Assetinspecties"
#: loko/mobile/templates/mobile/mobile_index.html:134
#: mobile/templates/mobile/mobile_index.html:134
msgid "Consulter la liste et l'historique des vérifications d'assets"
msgstr "Bekijk de lijst en geschiedenis van assetcontroles"
#: loko/mobile/templates/mobile/mobile_index.html:147
#: mobile/templates/mobile/mobile_index.html:147
msgid "Éditer les espaces verts"
msgstr "Groene ruimtes bewerken"
#: loko/mobile/templates/mobile/mobile_index.html:158
#: mobile/templates/mobile/mobile_index.html:158
msgid "Stock"
msgstr "Voorraad"
#: loko/mobile/templates/mobile/mobile_index.html:159
#: mobile/templates/mobile/mobile_index.html:159
msgid "Gérer les produits, commandes et mouvements de stock"
msgstr "Beheer producten, bestellingen en voorraadbewegingen"
#: loko/mobile/templates/mobile/mobile_install.html:8
#: mobile/templates/mobile/mobile_install.html:8
msgid "Installer"
msgstr "Installeren"
#: loko/mobile/templates/mobile/mobile_install.html:64
#: mobile/templates/mobile/mobile_install.html:64
msgid "Installez l'application en 3 options"
msgstr "Installeer de app met 3 opties"
#: loko/mobile/templates/mobile/mobile_install.html:65
#: mobile/templates/mobile/mobile_install.html:65
msgid ""
"Choisissez la méthode la plus adaptée à votre appareil ou à votre usage."
msgstr "Kies de methode die het beste past bij uw apparaat of gebruik."
#: loko/mobile/templates/mobile/mobile_install.html:76
#: mobile/templates/mobile/mobile_install.html:76
msgid "Télécharger l'APK Android"
msgstr "Download Android APK"
#: loko/mobile/templates/mobile/mobile_install.html:77
#: mobile/templates/mobile/mobile_install.html:77
msgid "Installez la version native (recommandé pour les appareils de terrain)."
msgstr "Installeer de native versie (aanbevolen voor veldapparaten)."
#: loko/mobile/templates/mobile/mobile_install.html:79
#: mobile/templates/mobile/mobile_install.html:79
msgid "Appuyez sur le bouton ci-dessous pour lancer le téléchargement."
msgstr "Druk op de onderstaande knop om de download te starten."
#: loko/mobile/templates/mobile/mobile_install.html:80
#: mobile/templates/mobile/mobile_install.html:80
msgid ""
"Autorisez l'installation depuis des sources inconnues si Android le demande."
msgstr "Sta installatie van onbekende bronnen toe als Android daarom vraagt."
#: loko/mobile/templates/mobile/mobile_install.html:81
#: mobile/templates/mobile/mobile_install.html:81
msgid "Ouvrez le fichier loko-app.apk et confirmez l'installation."
msgstr "Open het bestand loko-app.apk en bevestig de installatie."
#: loko/mobile/templates/mobile/mobile_install.html:84
#: mobile/templates/mobile/mobile_install.html:84
msgid "Télécharger l'APK"
msgstr "APK downloaden"
#: loko/mobile/templates/mobile/mobile_install.html:94
#: mobile/templates/mobile/mobile_install.html:94
msgid "Installer la PWA"
msgstr "PWA installeren"
#: loko/mobile/templates/mobile/mobile_install.html:95
#: mobile/templates/mobile/mobile_install.html:95
msgid "Ajoutez l'application sur l'écran d'accueil sans passer par un store."
msgstr "Voeg de applicatie toe aan het startscherm zonder via een app store te gaan."
msgstr ""
"Voeg de applicatie toe aan het startscherm zonder via een app store te gaan."
#: loko/mobile/templates/mobile/mobile_install.html:97
#: mobile/templates/mobile/mobile_install.html:97
msgid ""
"Ouvrez l'application dans votre navigateur mobile (Chrome, Edge, Safari)."
msgstr "Open de applicatie in uw mobiele browser (Chrome, Edge, Safari)."
#: loko/mobile/templates/mobile/mobile_install.html:98
#: mobile/templates/mobile/mobile_install.html:98
msgid "Dans la barre d'adresse, choisissez “Ajouter à l'écran d'accueil”."
msgstr "Kies in de adresbalk \"Toevoegen aan startscherm\"."
#: loko/mobile/templates/mobile/mobile_install.html:99
#: mobile/templates/mobile/mobile_install.html:99
msgid "Confirmez : l'icône apparaît comme une application."
msgstr "Bevestig: het pictogram verschijnt als een applicatie."
#: loko/mobile/templates/mobile/mobile_install.html:103
#: mobile/templates/mobile/mobile_install.html:103
msgid "Assurez-vous d'accepter l'installation quand la bannière PWA s'affiche."
msgstr ""
"Zorg ervoor dat u de installatie accepteert wanneer de PWA-banner verschijnt."
#: loko/mobile/templates/mobile/mobile_install.html:106
#: mobile/templates/mobile/mobile_install.html:106
msgid "Ouvrir l'application"
msgstr "Applicatie openen"
#: loko/mobile/templates/mobile/mobile_install.html:116
#: mobile/templates/mobile/mobile_install.html:116
msgid "Utiliser la version web"
msgstr "Webversie gebruiken"
#: loko/mobile/templates/mobile/mobile_install.html:117
#: mobile/templates/mobile/mobile_install.html:117
msgid "Accédez directement à l'application mobile depuis votre navigateur."
msgstr "Ga rechtstreeks naar de mobiele app vanuit uw browser."
#: loko/mobile/templates/mobile/mobile_install.html:119
#: mobile/templates/mobile/mobile_install.html:119
msgid "Tapez l'adresse"
msgstr "Typ het adres"
#: loko/mobile/templates/mobile/mobile_install.html:119
#: mobile/templates/mobile/mobile_install.html:119
msgid "une fois connecté(e) à StreetUp."
msgstr "zodra u bent ingelogd bij StreetUp."
#: loko/mobile/templates/mobile/mobile_install.html:120
#: mobile/templates/mobile/mobile_install.html:120
msgid "Ajoutez un favori pour y revenir en un geste."
msgstr "Voeg een bladwijzer toe om er met één klik naar terug te keren."
#: loko/mobile/templates/mobile/mobile_install.html:121
#: mobile/templates/mobile/mobile_install.html:121
msgid "Compatible bureau et tablette."
msgstr "Compatibel met desktop en tablet."
#: loko/mobile/templates/mobile/mobile_install.html:124
#: mobile/templates/mobile/mobile_install.html:124
msgid "Aller vers /mobile/"
msgstr "Ga naar /mobile/"
#: loko/mobile/templates/mobile/mobile_install.html:136
#: mobile/templates/mobile/mobile_install.html:136
msgid "Scanner pour ouvrir cette page"
msgstr "Scan om deze pagina te openen"
#: loko/mobile/templates/mobile/mobile_install.html:138
#: mobile/templates/mobile/mobile_install.html:138
msgid ""
"Pointez l'appareil photo de votre smartphone sur ce QR code pour accéder "
"instantanément aux instructions d'installation."
@ -448,11 +449,11 @@ msgstr ""
"Richt de camera van uw smartphone op deze QR-code om direct toegang te "
"krijgen tot de installatie-instructies."
#: loko/mobile/templates/mobile/mobile_install.html:141
#: mobile/templates/mobile/mobile_install.html:141
msgid "URL vérifiée"
msgstr "Geverifieerde URL"
#: loko/mobile/templates/mobile/mobile_install.html:154
#: mobile/templates/mobile/mobile_install.html:154
msgid ""
"Besoin d'aide ? Contactez le support StreetUp pour être accompagné dans le "
"déploiement."
@ -460,130 +461,130 @@ msgstr ""
"Hulp nodig? Neem contact op met de StreetUp-ondersteuning voor hulp bij de "
"implementatie."
#: loko/mobile/templates/mobile/qr_scanner.html:5
#: mobile/templates/mobile/qr_scanner.html:5
msgid "Scanner QR"
msgstr "QR-scanner"
#: loko/mobile/templates/mobile/qr_scanner.html:92
#: mobile/templates/mobile/qr_scanner.html:92
msgid "Pointez la caméra vers un QR code pour être redirigé automatiquement."
msgstr "Richt de camera op een QR-code om automatisch te worden omgeleid."
#: loko/mobile/templates/mobile/qr_scanner.html:102
#: loko/mobile/templates/mobile/qr_scanner.html:147
#: mobile/templates/mobile/qr_scanner.html:102
#: mobile/templates/mobile/qr_scanner.html:147
msgid "Initialisation de la caméra…"
msgstr "De camera initialiseren…"
#: loko/mobile/templates/mobile/qr_scanner.html:107
#: mobile/templates/mobile/qr_scanner.html:107
msgid "Ouvrir"
msgstr "Open"
#: loko/mobile/templates/mobile/qr_scanner.html:113
#: mobile/templates/mobile/qr_scanner.html:113
msgid "Réessayer"
msgstr "Probeer het opnieuw"
#: loko/mobile/templates/mobile/qr_scanner.html:117
#: mobile/templates/mobile/qr_scanner.html:117
msgid "Démarrer la caméra"
msgstr "Start de camera"
#: loko/mobile/templates/mobile/qr_scanner.html:156
#: loko/mobile/templates/mobile/qr_scanner.html:225
#: loko/mobile/templates/mobile/qr_scanner.html:233
#: mobile/templates/mobile/qr_scanner.html:156
#: mobile/templates/mobile/qr_scanner.html:225
#: mobile/templates/mobile/qr_scanner.html:233
msgid "Pointez vers un QR code…"
msgstr "Wijs een QR-code aan..."
#: loko/mobile/templates/mobile/qr_scanner.html:195
#: mobile/templates/mobile/qr_scanner.html:195
msgid "QR Code détecté, résolution…"
msgstr "QR-code gedetecteerd, resolutie..."
#: loko/mobile/templates/mobile/qr_scanner.html:210 loko/mobile/views.py:264
#: mobile/templates/mobile/qr_scanner.html:210 mobile/views.py:264
msgid "QR Code non reconnu."
msgstr "QR-code niet herkend."
#: loko/mobile/templates/mobile/qr_scanner.html:213
#: mobile/templates/mobile/qr_scanner.html:213
msgid "Erreur lors de la résolution."
msgstr "Fout bij het verwerken van de QR-code."
#: loko/mobile/views.py:268
#: mobile/views.py:268
msgid "Format de QR Code invalide."
msgstr "Ongeldig QR-codeformaat."
#: loko/mobile/views.py:292
#: mobile/views.py:292
msgid "Commande introuvable."
msgstr "Bestelling niet gevonden."
#: loko/mobile/views.py:448
#: mobile/views.py:448
msgid "A traiter"
msgstr "Te verwerken"
#: loko/mobile/views.py:449
#: mobile/views.py:449
msgid "En attente"
msgstr "In afwachting"
#: loko/mobile/views.py:450
#: mobile/views.py:450
msgid "Traité"
msgstr "Verwerkt"
#: loko/mobile/views.py:451
#: mobile/views.py:451
msgid "Annulé"
msgstr "Geannuleerd"
#: loko/mobile/views.py:454
#: mobile/views.py:454
msgid "Urgent"
msgstr "Dringend"
#: loko/mobile/views.py:455
#: mobile/views.py:455
msgid "Elevé"
msgstr "Hoog"
#: loko/mobile/views.py:456
#: mobile/views.py:456
msgid "Normal"
msgstr "Normaal"
#: loko/mobile/views.py:457
#: mobile/views.py:457
msgid "Bas"
msgstr "Laag"
#: loko/mobile/views.py:607
#: mobile/views.py:607
msgid "Vous n'avez pas la permission d'accéder à cette page."
msgstr "U heeft geen toestemming om deze pagina te bezoeken."
#: loko/mobile/views.py:637
#: mobile/views.py:637
#, python-brace-format
msgid "Issu de l'article {product} du bon de préparation #{order_number}"
msgstr ""
"Uit het artikel {product} van de voorbereidingsbestelling #{order_number}"
#: loko/mobile/views.py:656
#: mobile/views.py:656
#, python-brace-format
msgid "Issu de l'item #{id} du bon de préparation #{order_number}: {desc}"
msgstr "Van item #{id} van voorbereidingsorder #{order_number}: {desc}"
#: loko/mobile/views.py:685
#: mobile/views.py:685
msgid "Bon de confection créé avec succès."
msgstr "Craftingvoucher succesvol aangemaakt."
#: loko/mobile/views.py:745
#: mobile/views.py:745
msgid "Vous n'avez pas la permission d'ajouter une signature à ce lot."
msgstr ""
"U heeft geen toestemming om een ​​handtekening aan deze batch toe te voegen."
#: loko/mobile/views.py:761
#: mobile/views.py:761
msgid "Signature enregistrée avec succès."
msgstr "Handtekening succesvol geregistreerd."
#: loko/mobile/views.py:847
#: mobile/views.py:847
msgid "Veuillez sélectionner un emplacement."
msgstr "Selecteer een locatie."
#: loko/mobile/views.py:854
#: mobile/views.py:854
msgid "Emplacement invalide ou non accessible."
msgstr "Ongeldige of ontoegankelijke locatie."
#: loko/mobile/views.py:875
#: mobile/views.py:875
msgid "Inventaire créé avec succès."
msgstr "Inventaris succesvol aangemaakt."
#: loko/mobile/views.py:976
#: mobile/views.py:976
msgid "Document(s) ajouté(s) avec succès."
msgstr "Document(en) succesvol toegevoegd."

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