mirror of
https://github.com/ae-utbm/sith.git
synced 2024-11-22 06:03:20 +00:00
Optimize barmen timeout and counter state fetch
Le timeout se fait en une seule requête et la récupération de l'état des comptoirs en une seule requête aussi. Grâce à ça, on peut en grande partie retirer le cache pour l'affichage de l'état des comptoirs, ce qui a des implications excellentes en termes d'UX (comme le fait que la redirection vers la page de comptoir ou d'activité aura plus une apparence de truc aléatoire)
This commit is contained in:
parent
4bc4d266c2
commit
c0a6f5eb30
@ -68,25 +68,34 @@
|
|||||||
</form>
|
</form>
|
||||||
<ul class="bars">
|
<ul class="bars">
|
||||||
{% cache 100 "counters_activity" %}
|
{% cache 100 "counters_activity" %}
|
||||||
{% for bar in Counter.objects.annotate_has_barman(user).filter(type="BAR") %}
|
{# The sith has no periodic tasks manager
|
||||||
<li>
|
and using cron jobs would be way too overkill here.
|
||||||
{# If the user is a barman, we redirect him directly to the barman page
|
Thus the barmen timeout is handled in the only place that
|
||||||
else we redirect him to the activity page #}
|
is loaded on every page : the header bar.
|
||||||
{% if bar.has_annotated_barman %}
|
However, let's be clear : this has nothing to do here.
|
||||||
<a href="{{ url('counter:details', counter_id=bar.id) }}">
|
It's' merely a contrived workaround in order not to setup
|
||||||
{% else %}
|
a proper periodic task manager that has lived way too much.
|
||||||
<a href="{{ url('counter:activity', counter_id=bar.id) }}">
|
As Hubert Bonisseur De La Batte said : "s'agirait de grandir"#}
|
||||||
{% endif %}
|
{% set _ = Counter.objects.filter(type="BAR").handle_timeout() %}
|
||||||
{% if bar.is_open %}
|
|
||||||
<i class="fa fa-check" style="color: #2ecc71"></i>
|
|
||||||
{% else %}
|
|
||||||
<i class="fa fa-times" style="color: #eb2f06"></i>
|
|
||||||
{% endif %}
|
|
||||||
<span>{{ bar }}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
{% endcache %}
|
{% endcache %}
|
||||||
|
{% for bar in Counter.objects.annotate_has_barman(user).annotate_is_open().filter(type="BAR") %}
|
||||||
|
<li>
|
||||||
|
{# If the user is a barman, we redirect him directly to the barman page
|
||||||
|
else we redirect him to the activity page #}
|
||||||
|
{% if bar.has_annotated_barman %}
|
||||||
|
<a href="{{ url('counter:details', counter_id=bar.id) }}">
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ url('counter:activity', counter_id=bar.id) }}">
|
||||||
|
{% endif %}
|
||||||
|
{% if bar.is_open %}
|
||||||
|
<i class="fa fa-check" style="color: #2ecc71"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="fa fa-times" style="color: #eb2f06"></i>
|
||||||
|
{% endif %}
|
||||||
|
<span>{{ bar }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
|
@ -23,15 +23,17 @@ from counter.schemas import CounterSchema
|
|||||||
class CounterController(ControllerBase):
|
class CounterController(ControllerBase):
|
||||||
@route.get("", response=list[CounterSchema], permissions=[IsRoot])
|
@route.get("", response=list[CounterSchema], permissions=[IsRoot])
|
||||||
def fetch_all(self):
|
def fetch_all(self):
|
||||||
return Counter.objects.all()
|
return Counter.objects.annotate_is_open()
|
||||||
|
|
||||||
@route.get("{counter_id}/", response=CounterSchema, permissions=[CanView])
|
@route.get("{counter_id}/", response=CounterSchema, permissions=[CanView])
|
||||||
def fetch_one(self, counter_id: int):
|
def fetch_one(self, counter_id: int):
|
||||||
return self.get_object_or_exception(Counter, pk=counter_id)
|
return self.get_object_or_exception(
|
||||||
|
Counter.objects.annotate_is_open(), pk=counter_id
|
||||||
|
)
|
||||||
|
|
||||||
@route.get("bar/", response=list[CounterSchema], permissions=[CanView])
|
@route.get("bar/", response=list[CounterSchema], permissions=[CanView])
|
||||||
def fetch_bars(self):
|
def fetch_bars(self):
|
||||||
counters = list(Counter.objects.filter(type="BAR"))
|
counters = list(Counter.objects.annotate_is_open().filter(type="BAR"))
|
||||||
for c in counters:
|
for c in counters:
|
||||||
self.check_object_permissions(c)
|
self.check_object_permissions(c)
|
||||||
return counters
|
return counters
|
||||||
|
@ -358,7 +358,7 @@ class Product(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
class CounterQuerySet(models.QuerySet):
|
class CounterQuerySet(models.QuerySet):
|
||||||
def annotate_has_barman(self, user: User) -> CounterQuerySet:
|
def annotate_has_barman(self, user: User) -> Self:
|
||||||
"""Annotate the queryset with the `user_is_barman` field.
|
"""Annotate the queryset with the `user_is_barman` field.
|
||||||
|
|
||||||
For each counter, this field has value True if the user
|
For each counter, this field has value True if the user
|
||||||
@ -383,6 +383,29 @@ class CounterQuerySet(models.QuerySet):
|
|||||||
subquery = user.counters.filter(pk=OuterRef("pk"))
|
subquery = user.counters.filter(pk=OuterRef("pk"))
|
||||||
return self.annotate(has_annotated_barman=Exists(subquery))
|
return self.annotate(has_annotated_barman=Exists(subquery))
|
||||||
|
|
||||||
|
def annotate_is_open(self) -> Self:
|
||||||
|
"""Annotate tue queryset with the `is_open` field.
|
||||||
|
|
||||||
|
For each counter, if `is_open=True`, then the counter is currently opened.
|
||||||
|
Else the counter is closed.
|
||||||
|
"""
|
||||||
|
return self.annotate(
|
||||||
|
is_open=Exists(
|
||||||
|
Permanency.objects.filter(counter_id=OuterRef("pk"), end=None)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle_timeout(self) -> int:
|
||||||
|
"""Disconnect the barmen who are inactive in the given counters.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The number of affected rows (ie, the number of timeouted permanences)
|
||||||
|
"""
|
||||||
|
timeout = timezone.now() - timedelta(minutes=settings.SITH_BARMAN_TIMEOUT)
|
||||||
|
return Permanency.objects.filter(
|
||||||
|
counter__in=self, end=None, activity__lt=timeout
|
||||||
|
).update(end=F("activity"))
|
||||||
|
|
||||||
|
|
||||||
class Counter(models.Model):
|
class Counter(models.Model):
|
||||||
name = models.CharField(_("name"), max_length=30)
|
name = models.CharField(_("name"), max_length=30)
|
||||||
@ -450,20 +473,10 @@ class Counter(models.Model):
|
|||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def barmen_list(self) -> list[User]:
|
def barmen_list(self) -> list[User]:
|
||||||
return self.get_barmen_list()
|
"""Returns the barman list as list of User."""
|
||||||
|
return [
|
||||||
def get_barmen_list(self) -> list[User]:
|
p.user for p in self.permanencies.filter(end=None).select_related("user")
|
||||||
"""Returns the barman list as list of User.
|
]
|
||||||
|
|
||||||
Also handle the timeout of the barmen
|
|
||||||
"""
|
|
||||||
perms = self.permanencies.filter(end=None)
|
|
||||||
|
|
||||||
# disconnect barmen who are inactive
|
|
||||||
timeout = timezone.now() - timedelta(minutes=settings.SITH_BARMAN_TIMEOUT)
|
|
||||||
perms.filter(activity__lte=timeout).update(end=F("activity"))
|
|
||||||
|
|
||||||
return [p.user for p in perms.select_related("user")]
|
|
||||||
|
|
||||||
def get_random_barman(self) -> User:
|
def get_random_barman(self) -> User:
|
||||||
"""Return a random user being currently a barman."""
|
"""Return a random user being currently a barman."""
|
||||||
|
@ -15,20 +15,29 @@
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import string
|
import string
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from django.conf import settings
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.timezone import timedelta
|
from django.utils.timezone import now
|
||||||
|
from freezegun import freeze_time
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
|
|
||||||
from club.models import Club, Membership
|
from club.models import Club, Membership
|
||||||
from core.baker_recipes import subscriber_user
|
from core.baker_recipes import subscriber_user
|
||||||
from core.models import User
|
from core.models import User
|
||||||
from counter.models import BillingInfo, Counter, Customer, Permanency, Product, Selling
|
from counter.models import (
|
||||||
from sith.settings import SITH_MAIN_CLUB
|
BillingInfo,
|
||||||
|
Counter,
|
||||||
|
Customer,
|
||||||
|
Permanency,
|
||||||
|
Product,
|
||||||
|
Selling,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestCounter(TestCase):
|
class TestCounter(TestCase):
|
||||||
@ -219,7 +228,7 @@ class TestCounterStats(TestCase):
|
|||||||
s = Selling(
|
s = Selling(
|
||||||
label=barbar.name,
|
label=barbar.name,
|
||||||
product=barbar,
|
product=barbar,
|
||||||
club=Club.objects.get(name=SITH_MAIN_CLUB["name"]),
|
club=Club.objects.get(name=settings.SITH_MAIN_CLUB["name"]),
|
||||||
counter=cls.counter,
|
counter=cls.counter,
|
||||||
unit_price=2,
|
unit_price=2,
|
||||||
seller=cls.skia,
|
seller=cls.skia,
|
||||||
@ -497,6 +506,29 @@ class TestBarmanConnection(TestCase):
|
|||||||
assert not '<li><a href="/user/1/">S' Kia</a></li>' in str(response.content)
|
assert not '<li><a href="/user/1/">S' Kia</a></li>' in str(response.content)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_barman_timeout():
|
||||||
|
"""Test that barmen timeout is well managed."""
|
||||||
|
bar = baker.make(Counter, type="BAR")
|
||||||
|
user = baker.make(User)
|
||||||
|
bar.sellers.add(user)
|
||||||
|
baker.make(Permanency, counter=bar, user=user, start=now())
|
||||||
|
|
||||||
|
qs = Counter.objects.annotate_is_open().filter(pk=bar.pk)
|
||||||
|
|
||||||
|
bar = qs[0]
|
||||||
|
assert bar.is_open
|
||||||
|
assert bar.barmen_list == [user]
|
||||||
|
qs.handle_timeout() # handling timeout before the actual timeout should be no-op
|
||||||
|
assert qs[0].is_open
|
||||||
|
with freeze_time() as frozen_time:
|
||||||
|
frozen_time.tick(timedelta(minutes=settings.SITH_BARMAN_TIMEOUT + 1))
|
||||||
|
qs.handle_timeout()
|
||||||
|
bar = qs[0]
|
||||||
|
assert not bar.is_open
|
||||||
|
assert bar.barmen_list == []
|
||||||
|
|
||||||
|
|
||||||
class TestStudentCard(TestCase):
|
class TestStudentCard(TestCase):
|
||||||
"""Tests for adding and deleting Stundent Cards
|
"""Tests for adding and deleting Stundent Cards
|
||||||
Test that an user can be found with it's student card.
|
Test that an user can be found with it's student card.
|
||||||
|
@ -239,6 +239,7 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
model = Counter
|
model = Counter
|
||||||
|
queryset = Counter.objects.annotate_is_open()
|
||||||
template_name = "counter/counter_click.jinja"
|
template_name = "counter/counter_click.jinja"
|
||||||
pk_url_kwarg = "counter_id"
|
pk_url_kwarg = "counter_id"
|
||||||
current_tab = "counter"
|
current_tab = "counter"
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-10-09 11:48+0200\n"
|
"POT-Creation-Date: 2024-10-10 19:37+0200\n"
|
||||||
"PO-Revision-Date: 2016-07-18\n"
|
"PO-Revision-Date: 2016-07-18\n"
|
||||||
"Last-Translator: Skia <skia@libskia.so>\n"
|
"Last-Translator: Skia <skia@libskia.so>\n"
|
||||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||||
@ -19,7 +19,7 @@ msgstr ""
|
|||||||
#: accounting/models.py:62 accounting/models.py:103 accounting/models.py:136
|
#: accounting/models.py:62 accounting/models.py:103 accounting/models.py:136
|
||||||
#: accounting/models.py:203 club/models.py:55 com/models.py:274
|
#: accounting/models.py:203 club/models.py:55 com/models.py:274
|
||||||
#: com/models.py:293 counter/models.py:220 counter/models.py:253
|
#: com/models.py:293 counter/models.py:220 counter/models.py:253
|
||||||
#: counter/models.py:388 forum/models.py:59 launderette/models.py:29
|
#: counter/models.py:411 forum/models.py:59 launderette/models.py:29
|
||||||
#: launderette/models.py:84 launderette/models.py:122
|
#: launderette/models.py:84 launderette/models.py:122
|
||||||
msgid "name"
|
msgid "name"
|
||||||
msgstr "nom"
|
msgstr "nom"
|
||||||
@ -66,7 +66,7 @@ msgstr "numéro de compte"
|
|||||||
|
|
||||||
#: accounting/models.py:109 accounting/models.py:140 club/models.py:345
|
#: accounting/models.py:109 accounting/models.py:140 club/models.py:345
|
||||||
#: com/models.py:74 com/models.py:259 com/models.py:299 counter/models.py:276
|
#: com/models.py:74 com/models.py:259 com/models.py:299 counter/models.py:276
|
||||||
#: counter/models.py:390 trombi/models.py:210
|
#: counter/models.py:413 trombi/models.py:210
|
||||||
msgid "club"
|
msgid "club"
|
||||||
msgstr "club"
|
msgstr "club"
|
||||||
|
|
||||||
@ -87,12 +87,12 @@ msgstr "Compte club"
|
|||||||
msgid "%(club_account)s on %(bank_account)s"
|
msgid "%(club_account)s on %(bank_account)s"
|
||||||
msgstr "%(club_account)s sur %(bank_account)s"
|
msgstr "%(club_account)s sur %(bank_account)s"
|
||||||
|
|
||||||
#: accounting/models.py:201 club/models.py:351 counter/models.py:901
|
#: accounting/models.py:201 club/models.py:351 counter/models.py:899
|
||||||
#: election/models.py:16 launderette/models.py:179
|
#: election/models.py:16 launderette/models.py:179
|
||||||
msgid "start date"
|
msgid "start date"
|
||||||
msgstr "date de début"
|
msgstr "date de début"
|
||||||
|
|
||||||
#: accounting/models.py:202 club/models.py:352 counter/models.py:902
|
#: accounting/models.py:202 club/models.py:352 counter/models.py:900
|
||||||
#: election/models.py:17
|
#: election/models.py:17
|
||||||
msgid "end date"
|
msgid "end date"
|
||||||
msgstr "date de fin"
|
msgstr "date de fin"
|
||||||
@ -106,7 +106,7 @@ msgid "club account"
|
|||||||
msgstr "compte club"
|
msgstr "compte club"
|
||||||
|
|
||||||
#: accounting/models.py:212 accounting/models.py:272 counter/models.py:57
|
#: accounting/models.py:212 accounting/models.py:272 counter/models.py:57
|
||||||
#: counter/models.py:611
|
#: counter/models.py:609
|
||||||
msgid "amount"
|
msgid "amount"
|
||||||
msgstr "montant"
|
msgstr "montant"
|
||||||
|
|
||||||
@ -128,18 +128,18 @@ msgstr "classeur"
|
|||||||
|
|
||||||
#: accounting/models.py:273 core/models.py:940 core/models.py:1460
|
#: accounting/models.py:273 core/models.py:940 core/models.py:1460
|
||||||
#: core/models.py:1505 core/models.py:1534 core/models.py:1558
|
#: core/models.py:1505 core/models.py:1534 core/models.py:1558
|
||||||
#: counter/models.py:621 counter/models.py:725 counter/models.py:937
|
#: counter/models.py:619 counter/models.py:723 counter/models.py:935
|
||||||
#: eboutic/models.py:57 eboutic/models.py:189 forum/models.py:311
|
#: eboutic/models.py:57 eboutic/models.py:189 forum/models.py:311
|
||||||
#: forum/models.py:412
|
#: forum/models.py:412
|
||||||
msgid "date"
|
msgid "date"
|
||||||
msgstr "date"
|
msgstr "date"
|
||||||
|
|
||||||
#: accounting/models.py:274 counter/models.py:222 counter/models.py:938
|
#: accounting/models.py:274 counter/models.py:222 counter/models.py:936
|
||||||
#: pedagogy/models.py:207
|
#: pedagogy/models.py:207
|
||||||
msgid "comment"
|
msgid "comment"
|
||||||
msgstr "commentaire"
|
msgstr "commentaire"
|
||||||
|
|
||||||
#: accounting/models.py:276 counter/models.py:623 counter/models.py:727
|
#: accounting/models.py:276 counter/models.py:621 counter/models.py:725
|
||||||
#: subscription/models.py:56
|
#: subscription/models.py:56
|
||||||
msgid "payment method"
|
msgid "payment method"
|
||||||
msgstr "méthode de paiement"
|
msgstr "méthode de paiement"
|
||||||
@ -166,7 +166,7 @@ msgstr "type comptable"
|
|||||||
|
|
||||||
#: accounting/models.py:311 accounting/models.py:450 accounting/models.py:483
|
#: accounting/models.py:311 accounting/models.py:450 accounting/models.py:483
|
||||||
#: accounting/models.py:515 core/models.py:1533 core/models.py:1559
|
#: accounting/models.py:515 core/models.py:1533 core/models.py:1559
|
||||||
#: counter/models.py:691
|
#: counter/models.py:689
|
||||||
msgid "label"
|
msgid "label"
|
||||||
msgstr "étiquette"
|
msgstr "étiquette"
|
||||||
|
|
||||||
@ -650,7 +650,7 @@ msgid "Done"
|
|||||||
msgstr "Effectuées"
|
msgstr "Effectuées"
|
||||||
|
|
||||||
#: accounting/templates/accounting/journal_details.jinja:41
|
#: accounting/templates/accounting/journal_details.jinja:41
|
||||||
#: counter/templates/counter/cash_summary_list.jinja:37 counter/views.py:940
|
#: counter/templates/counter/cash_summary_list.jinja:37 counter/views.py:941
|
||||||
#: pedagogy/templates/pedagogy/moderation.jinja:13
|
#: pedagogy/templates/pedagogy/moderation.jinja:13
|
||||||
#: pedagogy/templates/pedagogy/uv_detail.jinja:142
|
#: pedagogy/templates/pedagogy/uv_detail.jinja:142
|
||||||
#: trombi/templates/trombi/comment.jinja:4
|
#: trombi/templates/trombi/comment.jinja:4
|
||||||
@ -971,11 +971,11 @@ msgstr "Date de fin"
|
|||||||
msgid "Counter"
|
msgid "Counter"
|
||||||
msgstr "Comptoir"
|
msgstr "Comptoir"
|
||||||
|
|
||||||
#: club/forms.py:167 counter/views.py:684
|
#: club/forms.py:167 counter/views.py:685
|
||||||
msgid "Products"
|
msgid "Products"
|
||||||
msgstr "Produits"
|
msgstr "Produits"
|
||||||
|
|
||||||
#: club/forms.py:172 counter/views.py:689
|
#: club/forms.py:172 counter/views.py:690
|
||||||
msgid "Archived products"
|
msgid "Archived products"
|
||||||
msgstr "Produits archivés"
|
msgstr "Produits archivés"
|
||||||
|
|
||||||
@ -1045,7 +1045,7 @@ msgstr "Vous ne pouvez pas faire de boucles dans les clubs"
|
|||||||
msgid "A club with that unix_name already exists"
|
msgid "A club with that unix_name already exists"
|
||||||
msgstr "Un club avec ce nom UNIX existe déjà."
|
msgstr "Un club avec ce nom UNIX existe déjà."
|
||||||
|
|
||||||
#: club/models.py:337 counter/models.py:892 counter/models.py:928
|
#: club/models.py:337 counter/models.py:890 counter/models.py:926
|
||||||
#: eboutic/models.py:53 eboutic/models.py:185 election/models.py:183
|
#: eboutic/models.py:53 eboutic/models.py:185 election/models.py:183
|
||||||
#: launderette/models.py:136 launderette/models.py:198 sas/models.py:274
|
#: launderette/models.py:136 launderette/models.py:198 sas/models.py:274
|
||||||
#: trombi/models.py:206
|
#: trombi/models.py:206
|
||||||
@ -1373,7 +1373,7 @@ msgstr "Anciens membres"
|
|||||||
msgid "History"
|
msgid "History"
|
||||||
msgstr "Historique"
|
msgstr "Historique"
|
||||||
|
|
||||||
#: club/views.py:116 core/templates/core/base.jinja:101 core/views/user.py:223
|
#: club/views.py:116 core/templates/core/base.jinja:107 core/views/user.py:223
|
||||||
#: sas/templates/sas/picture.jinja:91 trombi/views.py:61
|
#: sas/templates/sas/picture.jinja:91 trombi/views.py:61
|
||||||
msgid "Tools"
|
msgid "Tools"
|
||||||
msgstr "Outils"
|
msgstr "Outils"
|
||||||
@ -1659,7 +1659,7 @@ msgid "Calls to moderate"
|
|||||||
msgstr "Appels à modérer"
|
msgstr "Appels à modérer"
|
||||||
|
|
||||||
#: com/templates/com/news_admin_list.jinja:242
|
#: com/templates/com/news_admin_list.jinja:242
|
||||||
#: core/templates/core/base.jinja:216
|
#: core/templates/core/base.jinja:222
|
||||||
msgid "Events"
|
msgid "Events"
|
||||||
msgstr "Événements"
|
msgstr "Événements"
|
||||||
|
|
||||||
@ -2416,52 +2416,52 @@ msgstr "Inscription"
|
|||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Recherche"
|
msgstr "Recherche"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:102
|
#: core/templates/core/base.jinja:108
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr "Déconnexion"
|
msgstr "Déconnexion"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:150
|
#: core/templates/core/base.jinja:156
|
||||||
msgid "You do not have any unread notification"
|
msgid "You do not have any unread notification"
|
||||||
msgstr "Vous n'avez aucune notification non lue"
|
msgstr "Vous n'avez aucune notification non lue"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:155
|
#: core/templates/core/base.jinja:161
|
||||||
msgid "View more"
|
msgid "View more"
|
||||||
msgstr "Voir plus"
|
msgstr "Voir plus"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:158
|
#: core/templates/core/base.jinja:164
|
||||||
#: forum/templates/forum/last_unread.jinja:21
|
#: forum/templates/forum/last_unread.jinja:21
|
||||||
msgid "Mark all as read"
|
msgid "Mark all as read"
|
||||||
msgstr "Marquer tout comme lu"
|
msgstr "Marquer tout comme lu"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:206
|
#: core/templates/core/base.jinja:212
|
||||||
msgid "Main"
|
msgid "Main"
|
||||||
msgstr "Accueil"
|
msgstr "Accueil"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:208
|
#: core/templates/core/base.jinja:214
|
||||||
msgid "Associations & Clubs"
|
msgid "Associations & Clubs"
|
||||||
msgstr "Associations & Clubs"
|
msgstr "Associations & Clubs"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:210
|
#: core/templates/core/base.jinja:216
|
||||||
msgid "AE"
|
msgid "AE"
|
||||||
msgstr "L'AE"
|
msgstr "L'AE"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:211
|
#: core/templates/core/base.jinja:217
|
||||||
msgid "AE's clubs"
|
msgid "AE's clubs"
|
||||||
msgstr "Les clubs de L'AE"
|
msgstr "Les clubs de L'AE"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:212
|
#: core/templates/core/base.jinja:218
|
||||||
msgid "Others UTBM's Associations"
|
msgid "Others UTBM's Associations"
|
||||||
msgstr "Les autres associations de l'UTBM"
|
msgstr "Les autres associations de l'UTBM"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:218 core/templates/core/user_tools.jinja:172
|
#: core/templates/core/base.jinja:224 core/templates/core/user_tools.jinja:172
|
||||||
msgid "Elections"
|
msgid "Elections"
|
||||||
msgstr "Élections"
|
msgstr "Élections"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:219
|
#: core/templates/core/base.jinja:225
|
||||||
msgid "Big event"
|
msgid "Big event"
|
||||||
msgstr "Grandes Activités"
|
msgstr "Grandes Activités"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:222
|
#: core/templates/core/base.jinja:228
|
||||||
#: forum/templates/forum/favorite_topics.jinja:18
|
#: forum/templates/forum/favorite_topics.jinja:18
|
||||||
#: forum/templates/forum/last_unread.jinja:18
|
#: forum/templates/forum/last_unread.jinja:18
|
||||||
#: forum/templates/forum/macros.jinja:90 forum/templates/forum/main.jinja:6
|
#: forum/templates/forum/macros.jinja:90 forum/templates/forum/main.jinja:6
|
||||||
@ -2470,11 +2470,11 @@ msgstr "Grandes Activités"
|
|||||||
msgid "Forum"
|
msgid "Forum"
|
||||||
msgstr "Forum"
|
msgstr "Forum"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:223
|
#: core/templates/core/base.jinja:229
|
||||||
msgid "Gallery"
|
msgid "Gallery"
|
||||||
msgstr "Photos"
|
msgstr "Photos"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:224 counter/models.py:398
|
#: core/templates/core/base.jinja:230 counter/models.py:421
|
||||||
#: counter/templates/counter/counter_list.jinja:11
|
#: counter/templates/counter/counter_list.jinja:11
|
||||||
#: eboutic/templates/eboutic/eboutic_main.jinja:4
|
#: eboutic/templates/eboutic/eboutic_main.jinja:4
|
||||||
#: eboutic/templates/eboutic/eboutic_main.jinja:22
|
#: eboutic/templates/eboutic/eboutic_main.jinja:22
|
||||||
@ -2484,75 +2484,75 @@ msgstr "Photos"
|
|||||||
msgid "Eboutic"
|
msgid "Eboutic"
|
||||||
msgstr "Eboutic"
|
msgstr "Eboutic"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:226
|
#: core/templates/core/base.jinja:232
|
||||||
msgid "Services"
|
msgid "Services"
|
||||||
msgstr "Services"
|
msgstr "Services"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:228
|
#: core/templates/core/base.jinja:234
|
||||||
msgid "Matmatronch"
|
msgid "Matmatronch"
|
||||||
msgstr "Matmatronch"
|
msgstr "Matmatronch"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:229 launderette/models.py:38
|
#: core/templates/core/base.jinja:235 launderette/models.py:38
|
||||||
#: launderette/templates/launderette/launderette_book.jinja:5
|
#: launderette/templates/launderette/launderette_book.jinja:5
|
||||||
#: launderette/templates/launderette/launderette_book_choose.jinja:4
|
#: launderette/templates/launderette/launderette_book_choose.jinja:4
|
||||||
#: launderette/templates/launderette/launderette_main.jinja:4
|
#: launderette/templates/launderette/launderette_main.jinja:4
|
||||||
msgid "Launderette"
|
msgid "Launderette"
|
||||||
msgstr "Laverie"
|
msgstr "Laverie"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:230 core/templates/core/file.jinja:20
|
#: core/templates/core/base.jinja:236 core/templates/core/file.jinja:20
|
||||||
#: core/views/files.py:116
|
#: core/views/files.py:116
|
||||||
msgid "Files"
|
msgid "Files"
|
||||||
msgstr "Fichiers"
|
msgstr "Fichiers"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:231 core/templates/core/user_tools.jinja:163
|
#: core/templates/core/base.jinja:237 core/templates/core/user_tools.jinja:163
|
||||||
msgid "Pedagogy"
|
msgid "Pedagogy"
|
||||||
msgstr "Pédagogie"
|
msgstr "Pédagogie"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:235
|
#: core/templates/core/base.jinja:241
|
||||||
msgid "My Benefits"
|
msgid "My Benefits"
|
||||||
msgstr "Mes Avantages"
|
msgstr "Mes Avantages"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:237
|
#: core/templates/core/base.jinja:243
|
||||||
msgid "Sponsors"
|
msgid "Sponsors"
|
||||||
msgstr "Partenaires"
|
msgstr "Partenaires"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:238
|
#: core/templates/core/base.jinja:244
|
||||||
msgid "Subscriber benefits"
|
msgid "Subscriber benefits"
|
||||||
msgstr "Les avantages cotisants"
|
msgstr "Les avantages cotisants"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:242
|
#: core/templates/core/base.jinja:248
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr "Aide"
|
msgstr "Aide"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:244
|
#: core/templates/core/base.jinja:250
|
||||||
msgid "FAQ"
|
msgid "FAQ"
|
||||||
msgstr "FAQ"
|
msgstr "FAQ"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:245 core/templates/core/base.jinja:285
|
#: core/templates/core/base.jinja:251 core/templates/core/base.jinja:291
|
||||||
msgid "Contacts"
|
msgid "Contacts"
|
||||||
msgstr "Contacts"
|
msgstr "Contacts"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:246
|
#: core/templates/core/base.jinja:252
|
||||||
msgid "Wiki"
|
msgid "Wiki"
|
||||||
msgstr "Wiki"
|
msgstr "Wiki"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:286
|
#: core/templates/core/base.jinja:292
|
||||||
msgid "Legal notices"
|
msgid "Legal notices"
|
||||||
msgstr "Mentions légales"
|
msgstr "Mentions légales"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:287
|
#: core/templates/core/base.jinja:293
|
||||||
msgid "Intellectual property"
|
msgid "Intellectual property"
|
||||||
msgstr "Propriété intellectuelle"
|
msgstr "Propriété intellectuelle"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:288
|
#: core/templates/core/base.jinja:294
|
||||||
msgid "Help & Documentation"
|
msgid "Help & Documentation"
|
||||||
msgstr "Aide & Documentation"
|
msgstr "Aide & Documentation"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:289
|
#: core/templates/core/base.jinja:295
|
||||||
msgid "R&D"
|
msgid "R&D"
|
||||||
msgstr "R&D"
|
msgstr "R&D"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:292
|
#: core/templates/core/base.jinja:298
|
||||||
msgid "Site created by the IT Department of the AE"
|
msgid "Site created by the IT Department of the AE"
|
||||||
msgstr "Site réalisé par le Pôle Informatique de l'AE"
|
msgstr "Site réalisé par le Pôle Informatique de l'AE"
|
||||||
|
|
||||||
@ -3039,7 +3039,7 @@ msgid "Eboutic invoices"
|
|||||||
msgstr "Facture eboutic"
|
msgstr "Facture eboutic"
|
||||||
|
|
||||||
#: core/templates/core/user_account.jinja:54
|
#: core/templates/core/user_account.jinja:54
|
||||||
#: core/templates/core/user_tools.jinja:58 counter/views.py:709
|
#: core/templates/core/user_tools.jinja:58 counter/views.py:710
|
||||||
msgid "Etickets"
|
msgid "Etickets"
|
||||||
msgstr "Etickets"
|
msgstr "Etickets"
|
||||||
|
|
||||||
@ -3375,7 +3375,7 @@ msgid "Subscription stats"
|
|||||||
msgstr "Statistiques de cotisation"
|
msgstr "Statistiques de cotisation"
|
||||||
|
|
||||||
#: core/templates/core/user_tools.jinja:48 counter/forms.py:164
|
#: core/templates/core/user_tools.jinja:48 counter/forms.py:164
|
||||||
#: counter/views.py:679
|
#: counter/views.py:680
|
||||||
msgid "Counters"
|
msgid "Counters"
|
||||||
msgstr "Comptoirs"
|
msgstr "Comptoirs"
|
||||||
|
|
||||||
@ -3392,12 +3392,12 @@ msgid "Product types management"
|
|||||||
msgstr "Gestion des types de produit"
|
msgstr "Gestion des types de produit"
|
||||||
|
|
||||||
#: core/templates/core/user_tools.jinja:56
|
#: core/templates/core/user_tools.jinja:56
|
||||||
#: counter/templates/counter/cash_summary_list.jinja:23 counter/views.py:699
|
#: counter/templates/counter/cash_summary_list.jinja:23 counter/views.py:700
|
||||||
msgid "Cash register summaries"
|
msgid "Cash register summaries"
|
||||||
msgstr "Relevés de caisse"
|
msgstr "Relevés de caisse"
|
||||||
|
|
||||||
#: core/templates/core/user_tools.jinja:57
|
#: core/templates/core/user_tools.jinja:57
|
||||||
#: counter/templates/counter/invoices_call.jinja:4 counter/views.py:704
|
#: counter/templates/counter/invoices_call.jinja:4 counter/views.py:705
|
||||||
msgid "Invoices call"
|
msgid "Invoices call"
|
||||||
msgstr "Appels à facture"
|
msgstr "Appels à facture"
|
||||||
|
|
||||||
@ -3608,8 +3608,8 @@ msgstr "Photos"
|
|||||||
msgid "Galaxy"
|
msgid "Galaxy"
|
||||||
msgstr "Galaxie"
|
msgstr "Galaxie"
|
||||||
|
|
||||||
#: counter/apps.py:30 counter/models.py:414 counter/models.py:898
|
#: counter/apps.py:30 counter/models.py:437 counter/models.py:896
|
||||||
#: counter/models.py:934 launderette/models.py:32
|
#: counter/models.py:932 launderette/models.py:32
|
||||||
msgid "counter"
|
msgid "counter"
|
||||||
msgstr "comptoir"
|
msgstr "comptoir"
|
||||||
|
|
||||||
@ -3649,7 +3649,7 @@ msgstr "client"
|
|||||||
msgid "customers"
|
msgid "customers"
|
||||||
msgstr "clients"
|
msgstr "clients"
|
||||||
|
|
||||||
#: counter/models.py:74 counter/views.py:261
|
#: counter/models.py:74 counter/views.py:262
|
||||||
msgid "Not enough money"
|
msgid "Not enough money"
|
||||||
msgstr "Solde insuffisant"
|
msgstr "Solde insuffisant"
|
||||||
|
|
||||||
@ -3725,77 +3725,77 @@ msgstr "groupe d'achat"
|
|||||||
msgid "archived"
|
msgid "archived"
|
||||||
msgstr "archivé"
|
msgstr "archivé"
|
||||||
|
|
||||||
#: counter/models.py:294 counter/models.py:1034
|
#: counter/models.py:294 counter/models.py:1032
|
||||||
msgid "product"
|
msgid "product"
|
||||||
msgstr "produit"
|
msgstr "produit"
|
||||||
|
|
||||||
#: counter/models.py:393
|
#: counter/models.py:416
|
||||||
msgid "products"
|
msgid "products"
|
||||||
msgstr "produits"
|
msgstr "produits"
|
||||||
|
|
||||||
#: counter/models.py:396
|
#: counter/models.py:419
|
||||||
msgid "counter type"
|
msgid "counter type"
|
||||||
msgstr "type de comptoir"
|
msgstr "type de comptoir"
|
||||||
|
|
||||||
#: counter/models.py:398
|
#: counter/models.py:421
|
||||||
msgid "Bar"
|
msgid "Bar"
|
||||||
msgstr "Bar"
|
msgstr "Bar"
|
||||||
|
|
||||||
#: counter/models.py:398
|
#: counter/models.py:421
|
||||||
msgid "Office"
|
msgid "Office"
|
||||||
msgstr "Bureau"
|
msgstr "Bureau"
|
||||||
|
|
||||||
#: counter/models.py:401
|
#: counter/models.py:424
|
||||||
msgid "sellers"
|
msgid "sellers"
|
||||||
msgstr "vendeurs"
|
msgstr "vendeurs"
|
||||||
|
|
||||||
#: counter/models.py:409 launderette/models.py:192
|
#: counter/models.py:432 launderette/models.py:192
|
||||||
msgid "token"
|
msgid "token"
|
||||||
msgstr "jeton"
|
msgstr "jeton"
|
||||||
|
|
||||||
#: counter/models.py:629
|
#: counter/models.py:627
|
||||||
msgid "bank"
|
msgid "bank"
|
||||||
msgstr "banque"
|
msgstr "banque"
|
||||||
|
|
||||||
#: counter/models.py:631 counter/models.py:732
|
#: counter/models.py:629 counter/models.py:730
|
||||||
msgid "is validated"
|
msgid "is validated"
|
||||||
msgstr "est validé"
|
msgstr "est validé"
|
||||||
|
|
||||||
#: counter/models.py:636
|
#: counter/models.py:634
|
||||||
msgid "refilling"
|
msgid "refilling"
|
||||||
msgstr "rechargement"
|
msgstr "rechargement"
|
||||||
|
|
||||||
#: counter/models.py:709 eboutic/models.py:245
|
#: counter/models.py:707 eboutic/models.py:245
|
||||||
msgid "unit price"
|
msgid "unit price"
|
||||||
msgstr "prix unitaire"
|
msgstr "prix unitaire"
|
||||||
|
|
||||||
#: counter/models.py:710 counter/models.py:1014 eboutic/models.py:246
|
#: counter/models.py:708 counter/models.py:1012 eboutic/models.py:246
|
||||||
msgid "quantity"
|
msgid "quantity"
|
||||||
msgstr "quantité"
|
msgstr "quantité"
|
||||||
|
|
||||||
#: counter/models.py:729
|
#: counter/models.py:727
|
||||||
msgid "Sith account"
|
msgid "Sith account"
|
||||||
msgstr "Compte utilisateur"
|
msgstr "Compte utilisateur"
|
||||||
|
|
||||||
#: counter/models.py:729 sith/settings.py:403 sith/settings.py:408
|
#: counter/models.py:727 sith/settings.py:403 sith/settings.py:408
|
||||||
#: sith/settings.py:428
|
#: sith/settings.py:428
|
||||||
msgid "Credit card"
|
msgid "Credit card"
|
||||||
msgstr "Carte bancaire"
|
msgstr "Carte bancaire"
|
||||||
|
|
||||||
#: counter/models.py:737
|
#: counter/models.py:735
|
||||||
msgid "selling"
|
msgid "selling"
|
||||||
msgstr "vente"
|
msgstr "vente"
|
||||||
|
|
||||||
#: counter/models.py:841
|
#: counter/models.py:839
|
||||||
msgid "Unknown event"
|
msgid "Unknown event"
|
||||||
msgstr "Événement inconnu"
|
msgstr "Événement inconnu"
|
||||||
|
|
||||||
#: counter/models.py:842
|
#: counter/models.py:840
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Eticket bought for the event %(event)s"
|
msgid "Eticket bought for the event %(event)s"
|
||||||
msgstr "Eticket acheté pour l'événement %(event)s"
|
msgstr "Eticket acheté pour l'événement %(event)s"
|
||||||
|
|
||||||
#: counter/models.py:844 counter/models.py:867
|
#: counter/models.py:842 counter/models.py:865
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"You bought an eticket for the event %(event)s.\n"
|
"You bought an eticket for the event %(event)s.\n"
|
||||||
@ -3807,63 +3807,63 @@ msgstr ""
|
|||||||
"Vous pouvez également retrouver tous vos e-tickets sur votre page de compte "
|
"Vous pouvez également retrouver tous vos e-tickets sur votre page de compte "
|
||||||
"%(url)s."
|
"%(url)s."
|
||||||
|
|
||||||
#: counter/models.py:903
|
#: counter/models.py:901
|
||||||
msgid "last activity date"
|
msgid "last activity date"
|
||||||
msgstr "dernière activité"
|
msgstr "dernière activité"
|
||||||
|
|
||||||
#: counter/models.py:906
|
#: counter/models.py:904
|
||||||
msgid "permanency"
|
msgid "permanency"
|
||||||
msgstr "permanence"
|
msgstr "permanence"
|
||||||
|
|
||||||
#: counter/models.py:939
|
#: counter/models.py:937
|
||||||
msgid "emptied"
|
msgid "emptied"
|
||||||
msgstr "coffre vidée"
|
msgstr "coffre vidée"
|
||||||
|
|
||||||
#: counter/models.py:942
|
#: counter/models.py:940
|
||||||
msgid "cash register summary"
|
msgid "cash register summary"
|
||||||
msgstr "relevé de caisse"
|
msgstr "relevé de caisse"
|
||||||
|
|
||||||
#: counter/models.py:1010
|
#: counter/models.py:1008
|
||||||
msgid "cash summary"
|
msgid "cash summary"
|
||||||
msgstr "relevé"
|
msgstr "relevé"
|
||||||
|
|
||||||
#: counter/models.py:1013
|
#: counter/models.py:1011
|
||||||
msgid "value"
|
msgid "value"
|
||||||
msgstr "valeur"
|
msgstr "valeur"
|
||||||
|
|
||||||
#: counter/models.py:1016
|
#: counter/models.py:1014
|
||||||
msgid "check"
|
msgid "check"
|
||||||
msgstr "chèque"
|
msgstr "chèque"
|
||||||
|
|
||||||
#: counter/models.py:1018
|
#: counter/models.py:1016
|
||||||
msgid "True if this is a bank check, else False"
|
msgid "True if this is a bank check, else False"
|
||||||
msgstr "Vrai si c'est un chèque, sinon Faux."
|
msgstr "Vrai si c'est un chèque, sinon Faux."
|
||||||
|
|
||||||
#: counter/models.py:1022
|
#: counter/models.py:1020
|
||||||
msgid "cash register summary item"
|
msgid "cash register summary item"
|
||||||
msgstr "élément de relevé de caisse"
|
msgstr "élément de relevé de caisse"
|
||||||
|
|
||||||
#: counter/models.py:1038
|
#: counter/models.py:1036
|
||||||
msgid "banner"
|
msgid "banner"
|
||||||
msgstr "bannière"
|
msgstr "bannière"
|
||||||
|
|
||||||
#: counter/models.py:1040
|
#: counter/models.py:1038
|
||||||
msgid "event date"
|
msgid "event date"
|
||||||
msgstr "date de l'événement"
|
msgstr "date de l'événement"
|
||||||
|
|
||||||
#: counter/models.py:1042
|
#: counter/models.py:1040
|
||||||
msgid "event title"
|
msgid "event title"
|
||||||
msgstr "titre de l'événement"
|
msgstr "titre de l'événement"
|
||||||
|
|
||||||
#: counter/models.py:1044
|
#: counter/models.py:1042
|
||||||
msgid "secret"
|
msgid "secret"
|
||||||
msgstr "secret"
|
msgstr "secret"
|
||||||
|
|
||||||
#: counter/models.py:1083
|
#: counter/models.py:1081
|
||||||
msgid "uid"
|
msgid "uid"
|
||||||
msgstr "uid"
|
msgstr "uid"
|
||||||
|
|
||||||
#: counter/models.py:1088
|
#: counter/models.py:1086
|
||||||
msgid "student cards"
|
msgid "student cards"
|
||||||
msgstr "cartes étudiante"
|
msgstr "cartes étudiante"
|
||||||
|
|
||||||
@ -3890,15 +3890,6 @@ msgid "counter is open, there's at least one barman connected"
|
|||||||
msgstr "Le comptoir est ouvert, et il y a au moins un barman connecté"
|
msgstr "Le comptoir est ouvert, et il y a au moins un barman connecté"
|
||||||
|
|
||||||
#: counter/templates/counter/activity.jinja:35
|
#: counter/templates/counter/activity.jinja:35
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"counter is open but not active, the last sale was done at least %(minutes)s "
|
|
||||||
"minutes ago "
|
|
||||||
msgstr ""
|
|
||||||
"Le comptoir est ouvert, mais inactif. La dernière vente a eu lieu il y a "
|
|
||||||
"%(minutes)s minutes."
|
|
||||||
|
|
||||||
#: counter/templates/counter/activity.jinja:39
|
|
||||||
msgid "counter is not open : no one is connected"
|
msgid "counter is not open : no one is connected"
|
||||||
msgstr "Le comptoir est fermé"
|
msgstr "Le comptoir est fermé"
|
||||||
|
|
||||||
@ -3919,7 +3910,7 @@ msgstr "Liste des relevés de caisse"
|
|||||||
msgid "Theoric sums"
|
msgid "Theoric sums"
|
||||||
msgstr "Sommes théoriques"
|
msgstr "Sommes théoriques"
|
||||||
|
|
||||||
#: counter/templates/counter/cash_summary_list.jinja:36 counter/views.py:941
|
#: counter/templates/counter/cash_summary_list.jinja:36 counter/views.py:942
|
||||||
msgid "Emptied"
|
msgid "Emptied"
|
||||||
msgstr "Coffre vidé"
|
msgstr "Coffre vidé"
|
||||||
|
|
||||||
@ -4165,81 +4156,81 @@ msgstr "L'utilisateur n'est pas barman."
|
|||||||
msgid "Bad location, someone is already logged in somewhere else"
|
msgid "Bad location, someone is already logged in somewhere else"
|
||||||
msgstr "Mauvais comptoir, quelqu'un est déjà connecté ailleurs"
|
msgstr "Mauvais comptoir, quelqu'un est déjà connecté ailleurs"
|
||||||
|
|
||||||
#: counter/views.py:252
|
#: counter/views.py:253
|
||||||
msgid "Too young for that product"
|
msgid "Too young for that product"
|
||||||
msgstr "Trop jeune pour ce produit"
|
msgstr "Trop jeune pour ce produit"
|
||||||
|
|
||||||
#: counter/views.py:255
|
#: counter/views.py:256
|
||||||
msgid "Not allowed for that product"
|
msgid "Not allowed for that product"
|
||||||
msgstr "Non autorisé pour ce produit"
|
msgstr "Non autorisé pour ce produit"
|
||||||
|
|
||||||
#: counter/views.py:258
|
#: counter/views.py:259
|
||||||
msgid "No date of birth provided"
|
msgid "No date of birth provided"
|
||||||
msgstr "Pas de date de naissance renseignée"
|
msgstr "Pas de date de naissance renseignée"
|
||||||
|
|
||||||
#: counter/views.py:547
|
#: counter/views.py:548
|
||||||
msgid "You have not enough money to buy all the basket"
|
msgid "You have not enough money to buy all the basket"
|
||||||
msgstr "Vous n'avez pas assez d'argent pour acheter le panier"
|
msgstr "Vous n'avez pas assez d'argent pour acheter le panier"
|
||||||
|
|
||||||
#: counter/views.py:674
|
#: counter/views.py:675
|
||||||
msgid "Counter administration"
|
msgid "Counter administration"
|
||||||
msgstr "Administration des comptoirs"
|
msgstr "Administration des comptoirs"
|
||||||
|
|
||||||
#: counter/views.py:694
|
#: counter/views.py:695
|
||||||
msgid "Product types"
|
msgid "Product types"
|
||||||
msgstr "Types de produit"
|
msgstr "Types de produit"
|
||||||
|
|
||||||
#: counter/views.py:898
|
#: counter/views.py:899
|
||||||
msgid "10 cents"
|
msgid "10 cents"
|
||||||
msgstr "10 centimes"
|
msgstr "10 centimes"
|
||||||
|
|
||||||
#: counter/views.py:899
|
#: counter/views.py:900
|
||||||
msgid "20 cents"
|
msgid "20 cents"
|
||||||
msgstr "20 centimes"
|
msgstr "20 centimes"
|
||||||
|
|
||||||
#: counter/views.py:900
|
#: counter/views.py:901
|
||||||
msgid "50 cents"
|
msgid "50 cents"
|
||||||
msgstr "50 centimes"
|
msgstr "50 centimes"
|
||||||
|
|
||||||
#: counter/views.py:901
|
#: counter/views.py:902
|
||||||
msgid "1 euro"
|
msgid "1 euro"
|
||||||
msgstr "1 €"
|
msgstr "1 €"
|
||||||
|
|
||||||
#: counter/views.py:902
|
#: counter/views.py:903
|
||||||
msgid "2 euros"
|
msgid "2 euros"
|
||||||
msgstr "2 €"
|
msgstr "2 €"
|
||||||
|
|
||||||
#: counter/views.py:903
|
#: counter/views.py:904
|
||||||
msgid "5 euros"
|
msgid "5 euros"
|
||||||
msgstr "5 €"
|
msgstr "5 €"
|
||||||
|
|
||||||
#: counter/views.py:904
|
#: counter/views.py:905
|
||||||
msgid "10 euros"
|
msgid "10 euros"
|
||||||
msgstr "10 €"
|
msgstr "10 €"
|
||||||
|
|
||||||
#: counter/views.py:905
|
#: counter/views.py:906
|
||||||
msgid "20 euros"
|
msgid "20 euros"
|
||||||
msgstr "20 €"
|
msgstr "20 €"
|
||||||
|
|
||||||
#: counter/views.py:906
|
#: counter/views.py:907
|
||||||
msgid "50 euros"
|
msgid "50 euros"
|
||||||
msgstr "50 €"
|
msgstr "50 €"
|
||||||
|
|
||||||
#: counter/views.py:908
|
#: counter/views.py:909
|
||||||
msgid "100 euros"
|
msgid "100 euros"
|
||||||
msgstr "100 €"
|
msgstr "100 €"
|
||||||
|
|
||||||
#: counter/views.py:911 counter/views.py:917 counter/views.py:923
|
#: counter/views.py:912 counter/views.py:918 counter/views.py:924
|
||||||
#: counter/views.py:929 counter/views.py:935
|
#: counter/views.py:930 counter/views.py:936
|
||||||
msgid "Check amount"
|
msgid "Check amount"
|
||||||
msgstr "Montant du chèque"
|
msgstr "Montant du chèque"
|
||||||
|
|
||||||
#: counter/views.py:914 counter/views.py:920 counter/views.py:926
|
#: counter/views.py:915 counter/views.py:921 counter/views.py:927
|
||||||
#: counter/views.py:932 counter/views.py:938
|
#: counter/views.py:933 counter/views.py:939
|
||||||
msgid "Check quantity"
|
msgid "Check quantity"
|
||||||
msgstr "Nombre de chèque"
|
msgstr "Nombre de chèque"
|
||||||
|
|
||||||
#: counter/views.py:1507
|
#: counter/views.py:1459
|
||||||
msgid "people(s)"
|
msgid "people(s)"
|
||||||
msgstr "personne(s)"
|
msgstr "personne(s)"
|
||||||
|
|
||||||
@ -4812,12 +4803,12 @@ msgid "Washing and drying"
|
|||||||
msgstr "Lavage et séchage"
|
msgstr "Lavage et séchage"
|
||||||
|
|
||||||
#: launderette/templates/launderette/launderette_book.jinja:27
|
#: launderette/templates/launderette/launderette_book.jinja:27
|
||||||
#: sith/settings.py:642
|
#: sith/settings.py:639
|
||||||
msgid "Washing"
|
msgid "Washing"
|
||||||
msgstr "Lavage"
|
msgstr "Lavage"
|
||||||
|
|
||||||
#: launderette/templates/launderette/launderette_book.jinja:31
|
#: launderette/templates/launderette/launderette_book.jinja:31
|
||||||
#: sith/settings.py:642
|
#: sith/settings.py:639
|
||||||
msgid "Drying"
|
msgid "Drying"
|
||||||
msgstr "Séchage"
|
msgstr "Séchage"
|
||||||
|
|
||||||
@ -5609,72 +5600,72 @@ msgstr "Membre actif⸱ve"
|
|||||||
msgid "Curious"
|
msgid "Curious"
|
||||||
msgstr "Curieux⸱euse"
|
msgstr "Curieux⸱euse"
|
||||||
|
|
||||||
#: sith/settings.py:646
|
#: sith/settings.py:643
|
||||||
msgid "A new poster needs to be moderated"
|
msgid "A new poster needs to be moderated"
|
||||||
msgstr "Une nouvelle affiche a besoin d'être modérée"
|
msgstr "Une nouvelle affiche a besoin d'être modérée"
|
||||||
|
|
||||||
#: sith/settings.py:647
|
#: sith/settings.py:644
|
||||||
msgid "A new mailing list needs to be moderated"
|
msgid "A new mailing list needs to be moderated"
|
||||||
msgstr "Une nouvelle mailing list a besoin d'être modérée"
|
msgstr "Une nouvelle mailing list a besoin d'être modérée"
|
||||||
|
|
||||||
#: sith/settings.py:650
|
#: sith/settings.py:647
|
||||||
msgid "A new pedagogy comment has been signaled for moderation"
|
msgid "A new pedagogy comment has been signaled for moderation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Un nouveau commentaire de la pédagogie a été signalé pour la modération"
|
"Un nouveau commentaire de la pédagogie a été signalé pour la modération"
|
||||||
|
|
||||||
#: sith/settings.py:652
|
#: sith/settings.py:649
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "There are %s fresh news to be moderated"
|
msgid "There are %s fresh news to be moderated"
|
||||||
msgstr "Il y a %s nouvelles toutes fraîches à modérer"
|
msgstr "Il y a %s nouvelles toutes fraîches à modérer"
|
||||||
|
|
||||||
#: sith/settings.py:653
|
#: sith/settings.py:650
|
||||||
msgid "New files to be moderated"
|
msgid "New files to be moderated"
|
||||||
msgstr "Nouveaux fichiers à modérer"
|
msgstr "Nouveaux fichiers à modérer"
|
||||||
|
|
||||||
#: sith/settings.py:654
|
#: sith/settings.py:651
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "There are %s pictures to be moderated in the SAS"
|
msgid "There are %s pictures to be moderated in the SAS"
|
||||||
msgstr "Il y a %s photos à modérer dans le SAS"
|
msgstr "Il y a %s photos à modérer dans le SAS"
|
||||||
|
|
||||||
#: sith/settings.py:655
|
#: sith/settings.py:652
|
||||||
msgid "You've been identified on some pictures"
|
msgid "You've been identified on some pictures"
|
||||||
msgstr "Vous avez été identifié sur des photos"
|
msgstr "Vous avez été identifié sur des photos"
|
||||||
|
|
||||||
#: sith/settings.py:656
|
#: sith/settings.py:653
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You just refilled of %s €"
|
msgid "You just refilled of %s €"
|
||||||
msgstr "Vous avez rechargé votre compte de %s€"
|
msgstr "Vous avez rechargé votre compte de %s€"
|
||||||
|
|
||||||
#: sith/settings.py:657
|
#: sith/settings.py:654
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You just bought %s"
|
msgid "You just bought %s"
|
||||||
msgstr "Vous avez acheté %s"
|
msgstr "Vous avez acheté %s"
|
||||||
|
|
||||||
#: sith/settings.py:658
|
#: sith/settings.py:655
|
||||||
msgid "You have a notification"
|
msgid "You have a notification"
|
||||||
msgstr "Vous avez une notification"
|
msgstr "Vous avez une notification"
|
||||||
|
|
||||||
#: sith/settings.py:670
|
#: sith/settings.py:667
|
||||||
msgid "Success!"
|
msgid "Success!"
|
||||||
msgstr "Succès !"
|
msgstr "Succès !"
|
||||||
|
|
||||||
#: sith/settings.py:671
|
#: sith/settings.py:668
|
||||||
msgid "Fail!"
|
msgid "Fail!"
|
||||||
msgstr "Échec !"
|
msgstr "Échec !"
|
||||||
|
|
||||||
#: sith/settings.py:672
|
#: sith/settings.py:669
|
||||||
msgid "You successfully posted an article in the Weekmail"
|
msgid "You successfully posted an article in the Weekmail"
|
||||||
msgstr "Article posté avec succès dans le Weekmail"
|
msgstr "Article posté avec succès dans le Weekmail"
|
||||||
|
|
||||||
#: sith/settings.py:673
|
#: sith/settings.py:670
|
||||||
msgid "You successfully edited an article in the Weekmail"
|
msgid "You successfully edited an article in the Weekmail"
|
||||||
msgstr "Article édité avec succès dans le Weekmail"
|
msgstr "Article édité avec succès dans le Weekmail"
|
||||||
|
|
||||||
#: sith/settings.py:674
|
#: sith/settings.py:671
|
||||||
msgid "You successfully sent the Weekmail"
|
msgid "You successfully sent the Weekmail"
|
||||||
msgstr "Weekmail envoyé avec succès"
|
msgstr "Weekmail envoyé avec succès"
|
||||||
|
|
||||||
#: sith/settings.py:682
|
#: sith/settings.py:679
|
||||||
msgid "AE tee-shirt"
|
msgid "AE tee-shirt"
|
||||||
msgstr "Tee-shirt AE"
|
msgstr "Tee-shirt AE"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user