Merge branch 'makdown-editor' into 'master'

Add a nice markdown editor

See merge request ae/Sith!184
This commit is contained in:
Skia 2018-12-20 17:11:43 +01:00
commit 3898a13b25
14 changed files with 10851 additions and 330 deletions

View File

@ -1,10 +1,5 @@
{% extends "core/base.jinja" %}
{% from 'core/macros_pages.jinja' import markdown_preview_script, page_edit_form %}
{% block head %}
{{ super() }}
{{ markdown_preview_script(csrf_token) }}
{% endblock %}
{% from 'core/macros_pages.jinja' import page_edit_form %}
{% block content %}
{{ page_edit_form(page, form, url('club:club_edit_page', club_id=page.club.id), csrf_token) }}

View File

@ -49,7 +49,7 @@ from core.views import (
CanCreateMixin,
QuickNotifMixin,
)
from core.views.forms import SelectDateTime
from core.views.forms import SelectDateTime, MarkdownInput
from core.models import Notification, RealGroup, User
from club.models import Club, Mailing
@ -167,19 +167,25 @@ class ComEditView(ComTabsMixin, CanEditPropMixin, UpdateView):
class AlertMsgEditView(ComEditView):
fields = ["alert_msg"]
form_class = modelform_factory(
Sith, fields=["alert_msg"], widgets={"alert_msg": MarkdownInput}
)
current_tab = "alert"
success_url = reverse_lazy("com:alert_edit")
class InfoMsgEditView(ComEditView):
fields = ["info_msg"]
form_class = modelform_factory(
Sith, fields=["info_msg"], widgets={"info_msg": MarkdownInput}
)
current_tab = "info"
success_url = reverse_lazy("com:info_edit")
class IndexEditView(ComEditView):
fields = ["index_page"]
form_class = modelform_factory(
Sith, fields=["index_page"], widgets={"index_page": MarkdownInput}
)
current_tab = "index"
success_url = reverse_lazy("com:index_edit")
@ -197,7 +203,12 @@ class NewsForm(forms.ModelForm):
class Meta:
model = News
fields = ["type", "title", "club", "summary", "content", "author"]
widgets = {"author": forms.HiddenInput, "type": forms.RadioSelect}
widgets = {
"author": forms.HiddenInput,
"type": forms.RadioSelect,
"summary": MarkdownInput,
"content": MarkdownInput,
}
start_date = forms.DateTimeField(
["%Y-%m-%d %H:%M:%S"],
@ -461,6 +472,12 @@ class WeekmailEditView(ComTabsMixin, QuickNotifMixin, CanEditPropMixin, UpdateVi
Weekmail,
fields=["title", "intro", "joke", "protip", "conclusion"],
help_texts={"title": _("Delete and save to regenerate")},
widgets={
"intro": MarkdownInput,
"joke": MarkdownInput,
"protip": MarkdownInput,
"conclusion": MarkdownInput,
},
)
success_url = reverse_lazy("com:weekmail")
current_tab = "weekmail"
@ -533,7 +550,11 @@ class WeekmailArticleEditView(
"""Edit an article"""
model = WeekmailArticle
fields = ["title", "club", "content"]
form_class = modelform_factory(
WeekmailArticle,
fields=["title", "club", "content"],
widgets={"content": MarkdownInput},
)
pk_url_kwarg = "article_id"
template_name = "core/edit.jinja"
success_url = reverse_lazy("com:weekmail")
@ -545,7 +566,11 @@ class WeekmailArticleCreateView(QuickNotifMixin, CreateView):
"""Post an article"""
model = WeekmailArticle
fields = ["title", "club", "content"]
form_class = modelform_factory(
WeekmailArticle,
fields=["title", "club", "content"],
widgets={"content": MarkdownInput},
)
template_name = "core/create.jinja"
success_url = reverse_lazy("core:user_tools")
quick_notif_url_arg = "qn_weekmail_new_article"

View File

@ -43,3 +43,22 @@ $( function() {
function display_notif() {
$('#header_notif').toggle().parent().toggleClass("white");
}
// You can't get the csrf token from the template in a widget
// We get it from a cookie as a workaround, see this link
// https://docs.djangoproject.com/en/2.0/ref/csrf/#ajax
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i <ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}

File diff suppressed because one or more lines are too long

10362
core/static/core/simplemde/simplemde.min.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1644,26 +1644,6 @@ label {
}
}
.markdown_editor {
margin-top: 5px;
}
.markdown_editor a {
border: solid 1px $black-color;
padding: 2px;
min-width: 1em;
display: inline-block;
text-align: center;
margin: 0px 1px;
}
.markdown_editor a:hover {
text-decoration: none;
cursor: pointer;
box-shadow: 0px 0px 1px 1px $secondary-light-color;
transition: all 0.1s linear;
}
/*--------------------------------JQuery-------------------------------*/
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header

View File

@ -16,6 +16,11 @@
{% else %}
<link rel="stylesheet" href="{{ static('core/font-awesome/css/font-awesome.min.css') }}">
{% endif %}
<!-- Jquery declared here to be accessible in every django widgets -->
<script src="{{ static('core/js/jquery-3.1.0.min.js') }}"></script>
<!-- Put here to always have acces to those functions on django widgets -->
<script src="{{ static('core/js/script.js') }}"></script>
{% endblock %}
</head>
@ -248,14 +253,12 @@
{% endblock %}
-->
{% block script %}
<script src="{{ static('core/js/jquery-3.1.0.min.js') }}"></script>
<script src="{{ static('core/js/ui/jquery-ui.min.js') }}"></script>
<script src="{{ static('core/js/ui/i18n/datepicker-fr.js') }}"></script>
<script src="{{ static('core/js/jquery.datetimepicker.full.min.js') }}"></script>
<script src="{{ static('core/js/multiple-select.js') }}"></script>
<script src="{{ static('ajax_select/js/ajax_select.js') }}"></script>
<script src="{{ url('javascript-catalog') }}"></script>
<script src="{{ static('core/js/script.js') }}"></script>
<script>
$('.select_single').multipleSelect({
single: true,
@ -289,73 +292,8 @@ $(document).keydown(function (e) {
jQuery.datetimepicker.setLocale('{{ request.LANGUAGE_CODE|lower }}');
$('.select_datetime').datetimepicker({
format: 'Y-m-d H:i:s',
});
function add_syntax(e, choice) {
ta = $(e).parent().children('textarea')[0];
ta.focus();
var start = ta.selectionStart;
var end = ta.selectionEnd;
var before = ta.value.substring(0, start);
var after = ta.value.substring(end);
var between = ta.value.substring(start, end);
switch (choice) {
case "bold":
ta.value = before + "**" + between + "**" + after;
ta.selectionEnd = end + 2;
break;
case "italic":
ta.value = before + "*" + between + "*" + after;
ta.selectionEnd = end + 1;
break;
case "underline":
ta.value = before + "__" + between + "__" + after;
ta.selectionEnd = end + 2;
break;
case "strike":
ta.value = before + "~~" + between + "~~" + after;
ta.selectionEnd = end + 2;
break;
case "sub":
ta.value = before + "<sub>" + between + "</sub>" + after;
ta.selectionEnd = end + 5;
break;
case "sup":
ta.value = before + "<sup>" + between + "</sup>" + after;
ta.selectionEnd = end + 5;
break;
case "link":
if (between === "") {
between = "https://";
}
name = "{% trans %}name{% endtrans %}";
ta.value = before + "[" + name + "](" + between + ")" + after;
ta.selectionStart = start + 1;
ta.selectionEnd = start + 1 + name.length;
break;
case "image":
if (between === "") {
between = "{% trans %}https://path/to/image.gif{% endtrans %}";
}
alt = "{% trans %}alternative text{% endtrans %}";
ta.value = before + "![" + alt + "](" + between + "?42% \"{% trans %}Title{% endtrans %}\")" + after;
ta.selectionStart = start + 2;
ta.selectionEnd = start + 2 + alt.length;
break;
}
}
$(document).ready(function() {
editor = $('.markdown_editor');
editor.prepend('<a onclick="javascript:add_syntax(this, \'image\')">{% trans %}Image{% endtrans %}</a>');
editor.prepend('<a onclick="javascript:add_syntax(this, \'link\')">{% trans %}Link{% endtrans %}</a>');
editor.prepend('<a onclick="javascript:add_syntax(this, \'sup\')"><sup>{% trans %}sup{% endtrans %}</sup></a>');
editor.prepend('<a onclick="javascript:add_syntax(this, \'sub\')"><sub>{% trans %}sub{% endtrans %}</sub></a>');
editor.prepend('<a onclick="javascript:add_syntax(this, \'strike\')"><del>{% trans %}S{% endtrans %}</del></a>');
editor.prepend('<a onclick="javascript:add_syntax(this, \'underline\')"><u>{% trans %}U{% endtrans %}</u></a>');
editor.prepend('<a onclick="javascript:add_syntax(this, \'italic\')"><i>{% trans %}I{% endtrans %}</i></a>');
editor.prepend('<a onclick="javascript:add_syntax(this, \'bold\')"><b>{% trans %}B{% endtrans %}</b></a>');
});
</script>
{% endblock %}
</body>

View File

@ -22,29 +22,6 @@
<form action="{{ url }}" method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ token }}">
{{ form.as_p() }}
{{ markdown_preview_button() }}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
<div id="preview" class="page_content">
</div>
{% endmacro %}
{% macro markdown_preview_script(token) %}
<script>
function make_preview() {
text = $("#id_content").val();
console.log("Rendering text: " + text);
$.ajax({
url: "{{ url('api:api_markdown') }}",
method: "POST",
data: { text: text, csrfmiddlewaretoken: "{{ token }}"}
}).done(function (msg) {
$("#preview").html(msg);
});
}
</script>
{% endmacro %}
{% macro markdown_preview_button() %}
<p><input type="button" value="{% trans %}Preview{% endtrans %}" onclick="javascript:make_preview();" /></p>
{% endmacro %}

View File

@ -0,0 +1,171 @@
<div>
{# Depends on this package https://github.com/sparksuite/simplemde-markdown-editor #}
<textarea name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>{% if widget.value %}{{ widget.value }}{% endif %}</textarea>
{# The simplemde script can be included twice, it's safe in the code #}
<script src="{{ statics.js }}"> </script>
<script type="text/javascript">
var css = "{{ statics.css }}";
var lastAPICall;
// Only import the css once
if (!document.head.innerHTML.includes(css)){
document.head.innerHTML += '<link rel="stylesheet" href="' + css + '">';
}
// Custom markdown parser
function customMarkdownParser(plainText, preview) {
$.ajax({
url: "{{ markdown_api_url }}",
method: "POST",
data: { text: plainText, csrfmiddlewaretoken: getCookie('csrftoken') },
}).done(function (msg) {
preview.innerHTML = msg;
});
}
// Pretty markdown input
var simplemde = new SimpleMDE({
element: document.getElementById("{{ widget.attrs.id }}"),
spellChecker: false,
previewRender: function(plainText, preview){ // Async method
clearTimeout(lastAPICall);
lastAPICall = setTimeout(function (plainText, preview){
customMarkdownParser(plainText, preview);
}, 300, plainText, preview);
return preview.innerHTML;
},
forceSync: true, // Avoid validation error on generic create view
toolbar: [
{
name: "heading-smaller",
action: SimpleMDE.toggleHeadingSmaller,
className: "fa fa-header",
title: "{{ translations.heading_smaller }}"
},
{
name: "italic",
action: SimpleMDE.toggleItalic,
className: "fa fa-italic",
title: "{{ translations.italic }}"
},
{
name: "bold",
action: SimpleMDE.toggleBold,
className: "fa fa-bold",
title: "{{ translations.bold }}"
},
{
name: "strikethrough",
action: SimpleMDE.toggleStrikethrough,
className: "fa fa-strikethrough",
title: "{{ translations.strikethrough }}"
},
{
name: "underline",
action: function customFunction(editor){
var cm = editor.codemirror;
cm.replaceSelection('__' + cm.getSelection() + '__');
},
className: "fa fa-underline",
title: "{{ translations.underline }}"
},
{
name: "superscript",
action: function customFunction(editor){
var cm = editor.codemirror;
cm.replaceSelection('<sup>' + cm.getSelection() + '</sup>');
},
className: "fa fa-superscript",
title: "{{ translations.superscript }}"
},
{
name: "subscript",
action: function customFunction(editor){
var cm = editor.codemirror;
cm.replaceSelection('<sub>' + cm.getSelection() + '</sub>');
},
className: "fa fa-subscript",
title: "{{ translations.subscript }}"
},
{
name: "code",
action: SimpleMDE.toggleCodeBlock,
className: "fa fa-code",
title: "{{ translations.code }}"
},
"|",
{
name: "quote",
action: SimpleMDE.toggleBlockquote,
className: "fa fa-quote-left",
title: "{{ translations.quote }}"
},
{
name: "unordered-list",
action: SimpleMDE.toggleUnorderedList,
className: "fa fa-list-ul",
title: "{{ translations.unordered_list }}"
},
{
name: "ordered-list",
action: SimpleMDE.toggleOrderedList,
className: "fa fa-list-ol",
title: "{{ translations.ordered_list }}"
},
"|",
{
name: "link",
action: SimpleMDE.drawLink,
className: "fa fa-link",
title: "{{ translations.link }}"
},
{
name: "image",
action: SimpleMDE.drawImage,
className: "fa fa-picture-o",
title: "{{ translations.image }}"
},
{
name: "table",
action: SimpleMDE.drawTable,
className: "fa fa-table",
title: "{{ translations.table }}"
},
"|",
{
name: "clean-block",
action: SimpleMDE.cleanBlock,
className: "fa fa-eraser fa-clean-block",
title: "{{ translations.clean_block }}"
},
"|",
{
name: "preview",
action: SimpleMDE.togglePreview,
className: "fa fa-eye no-disable",
title: "{{ translations.preview }}"
},
{
name: "side-by-side",
action: SimpleMDE.toggleSideBySide,
className: "fa fa-columns no-disable no-mobile",
title: "{{ translations.side_by_side }}"
},
{
name: "fullscreen",
action: SimpleMDE.toggleFullScreen,
className: "fa fa-arrows-alt no-disable no-mobile",
title: "{{ translations.fullscreen }}"
},
"|",
{
name: "guide",
action: "/page/Aide_sur_la_syntaxe",
className: "fa fa-question-circle",
title: "{{ translations.guide }}"
},
]
});
</script>
</div>

View File

@ -1,10 +1,5 @@
{% extends "core/page.jinja" %}
{% from 'core/macros_pages.jinja' import markdown_preview_script, page_edit_form %}
{% block head %}
{{ super() }}
{{ markdown_preview_script(csrf_token) }}
{% endblock %}
{% from 'core/macros_pages.jinja' import page_edit_form %}
{% block page %}
{{ page_edit_form(page, form, url('core:page_edit', page_name=page.get_full_name()), csrf_token) }}

View File

@ -26,6 +26,8 @@ from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django import forms
from django.conf import settings
from django.db import transaction
from django.templatetags.static import static
from django.core.urlresolvers import reverse
from django.core.exceptions import ValidationError
from django.forms import (
CheckboxSelectMultiple,
@ -90,19 +92,38 @@ class SelectDate(DateInput):
class MarkdownInput(Textarea):
def render(self, name, value, attrs=None):
output = (
'<p><a href="%(syntax_url)s">%(help_text)s</a></p>'
'<div class="markdown_editor">%(content)s</div>'
% {
"syntax_url": Page.get_page_by_full_name(
settings.SITH_CORE_PAGE_SYNTAX
).get_absolute_url(),
"help_text": _("Help on the syntax"),
"content": super(MarkdownInput, self).render(name, value, attrs),
}
)
return output
template_name = "core/markdown_textarea.jinja"
def get_context(self, name, value, attrs):
context = super(MarkdownInput, self).get_context(name, value, attrs)
context["statics"] = {
"js": static("core/simplemde/simplemde.min.js"),
"css": static("core/simplemde/simplemde.min.css"),
}
context["translations"] = {
"heading_smaller": _("Heading"),
"italic": _("Italic"),
"bold": _("Bold"),
"strikethrough": _("Strikethrough"),
"underline": _("Underline"),
"superscript": _("Superscript"),
"subscript": _("Subscript"),
"code": _("Code"),
"quote": _("Quote"),
"unordered_list": _("Unordered list"),
"ordered_list": _("Ordered list"),
"image": _("Insert image"),
"link": _("Insert link"),
"table": _("Insert table"),
"clean_block": _("Clean block"),
"preview": _("Toggle preview"),
"side_by_side": _("Toggle side by side"),
"fullscreen": _("Toggle fullscreen"),
"guide": _("Markdown guide"),
}
context["markdown_api_url"] = reverse("api:api_markdown")
return context
class SelectFile(TextInput):

View File

@ -12,7 +12,7 @@ from django import forms
from core.views import CanViewMixin, CanEditMixin, CanCreateMixin
from django.db.models.query import QuerySet
from core.views.forms import SelectDateTime
from core.views.forms import SelectDateTime, MarkdownInput
from election.models import Election, Role, Candidature, ElectionList, Vote
from ajax_select.fields import AutoCompleteSelectField
@ -67,7 +67,7 @@ class CandidateForm(forms.ModelForm):
class Meta:
model = Candidature
fields = ["user", "role", "program", "election_list"]
widgets = {"program": forms.Textarea}
widgets = {"program": MarkdownInput}
user = AutoCompleteSelectField(
"users", label=_("User to candidate"), help_text=None, required=True

View File

@ -30,26 +30,8 @@
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p() }}
<p><input type="button" value="{% trans %}Preview{% endtrans %}" onclick="javascript:make_preview();" /></p>
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
<div id="preview_message" class="message" style="display: none;">
<div class="msg_author">
{% if user.avatar_pict %}
<img src="{{ user.avatar_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}" id="picture" />
{% else %}
<img src="{{ static('core/img/unknown.jpg') }}" alt="{% trans %}Profile{% endtrans %}" id="picture" />
{% endif %}
<br/>
<strong><a href="{{ user.get_absolute_url() }}">{{ user.get_short_name() }}</a></strong>
</div>
<div class="msg_content">
<hr>
<div id="preview" class="ib"></div>
<div class="forum_signature">{{ user.forum_signature|markdown }}</div>
</div>
</div>
<hr>
{% if topic %}
@ -62,26 +44,3 @@
</div>
{% endblock %}
{% block script %}
{{ super() }}
<script>
function make_preview() {
$("#preview_message").hide(300);
text = $("#id_message").val();
console.log("Rendering text: " + text);
$.ajax({
url: "{{ url('api:api_markdown') }}",
method: "POST",
data: { text: text, csrfmiddlewaretoken: "{{ csrf_token }}"}
}).done(function (msg) {
$("#preview").html(msg);
$("#preview_message").show(300);
});
}
</script>
{% endblock %}

View File

@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-12-11 20:07+0100\n"
"POT-Creation-Date: 2018-12-19 14:00+0100\n"
"PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Skia <skia@libskia.so>\n"
"Language-Team: AE info <ae.info@utbm.fr>\n"
@ -18,7 +18,7 @@ msgstr ""
#: accounting/models.py:61 accounting/models.py:110 accounting/models.py:138
#: accounting/models.py:203 club/models.py:48 com/models.py:231
#: com/models.py:248 core/templates/core/base.jinja:331 counter/models.py:119
#: com/models.py:248 core/templates/core/base.jinja:333 counter/models.py:119
#: counter/models.py:147 counter/models.py:209 forum/models.py:58
#: launderette/models.py:38 launderette/models.py:90 launderette/models.py:125
#: stock/models.py:40 stock/models.py:60 stock/models.py:100
@ -128,8 +128,8 @@ msgstr "numéro"
msgid "journal"
msgstr "classeur"
#: accounting/models.py:269 core/models.py:805 core/models.py:1341
#: core/models.py:1387 core/models.py:1416 counter/models.py:351
#: accounting/models.py:269 core/models.py:809 core/models.py:1345
#: core/models.py:1391 core/models.py:1420 counter/models.py:351
#: counter/models.py:444 counter/models.py:613 eboutic/models.py:42
#: eboutic/models.py:85 forum/models.py:298 forum/models.py:391
#: stock/models.py:99
@ -167,7 +167,7 @@ msgid "accounting type"
msgstr "type comptable"
#: accounting/models.py:304 accounting/models.py:450 accounting/models.py:485
#: accounting/models.py:519 core/models.py:1415 counter/models.py:410
#: accounting/models.py:519 core/models.py:1419 counter/models.py:410
msgid "label"
msgstr "étiquette"
@ -373,7 +373,7 @@ msgstr "Compte en banque : "
#: election/templates/election/election_detail.jinja:286
#: election/templates/election/election_detail.jinja:350
#: election/templates/election/election_detail.jinja:401
#: forum/templates/forum/macros.jinja:21 forum/templates/forum/macros.jinja:123
#: forum/templates/forum/macros.jinja:21 forum/templates/forum/macros.jinja:134
#: launderette/templates/launderette/launderette_admin.jinja:16
#: launderette/views.py:226 sas/templates/sas/album.jinja:26
#: sas/templates/sas/moderation.jinja:18 sas/templates/sas/picture.jinja:74
@ -428,7 +428,7 @@ msgstr "Nouveau compte club"
#: election/templates/election/election_detail.jinja:347
#: election/templates/election/election_detail.jinja:398
#: forum/templates/forum/macros.jinja:20 forum/templates/forum/macros.jinja:62
#: forum/templates/forum/macros.jinja:117
#: forum/templates/forum/macros.jinja:128
#: launderette/templates/launderette/launderette_list.jinja:16
#: sas/templates/sas/album.jinja:18 sas/templates/sas/picture.jinja:100
#: trombi/templates/trombi/detail.jinja:9
@ -643,6 +643,7 @@ msgid "Target"
msgstr "Cible"
#: accounting/templates/accounting/journal_details.jinja:38
#: core/views/forms.py:112
msgid "Code"
msgstr "Code"
@ -974,7 +975,7 @@ msgid "Enter a valid address. Only the root of the address is needed."
msgstr ""
"Entrez une adresse valide. Seule la racine de l'adresse est nécessaire."
#: club/models.py:344 com/models.py:79 com/models.py:260 core/models.py:806
#: club/models.py:344 com/models.py:79 com/models.py:260 core/models.py:810
msgid "is moderated"
msgstr "est modéré"
@ -1048,7 +1049,7 @@ msgid "Mark as old"
msgstr "Marquer comme ancien"
#: club/templates/club/club_members.jinja:30
#: core/templates/core/file_detail.jinja:19 core/views/forms.py:334
#: core/templates/core/file_detail.jinja:19 core/views/forms.py:355
#: launderette/views.py:226 trombi/templates/trombi/detail.jinja:19
msgid "Add"
msgstr "Ajouter"
@ -1255,7 +1256,7 @@ msgstr "Anciens membres"
msgid "History"
msgstr "Historique"
#: club/views.py:165 core/templates/core/base.jinja:113 core/views/user.py:228
#: club/views.py:165 core/templates/core/base.jinja:116 core/views/user.py:228
#: sas/templates/sas/picture.jinja:95 trombi/views.py:60
msgid "Tools"
msgstr "Outils"
@ -1278,7 +1279,7 @@ msgstr "Liste d'affiches"
msgid "Props"
msgstr "Propriétés"
#: club/views.py:322 core/views/forms.py:337 counter/views.py:113
#: club/views.py:322 core/views/forms.py:358 counter/views.py:113
#: trombi/views.py:141
msgid "Select user"
msgstr "Choisir un utilisateur"
@ -1347,7 +1348,7 @@ msgstr "résumé"
msgid "content"
msgstr "contenu"
#: com/models.py:73 core/models.py:1385 launderette/models.py:95
#: com/models.py:73 core/models.py:1389 launderette/models.py:95
#: launderette/models.py:130 launderette/models.py:182 stock/models.py:77
#: stock/models.py:131
msgid "type"
@ -1397,7 +1398,7 @@ msgstr "weekmail"
msgid "rank"
msgstr "rang"
#: com/models.py:250 core/models.py:776 core/models.py:820
#: com/models.py:250 core/models.py:780 core/models.py:824
msgid "file"
msgstr "fichier"
@ -1492,9 +1493,9 @@ msgstr "Type"
#: com/templates/com/news_admin_list.jinja:249
#: com/templates/com/news_admin_list.jinja:286
#: com/templates/com/weekmail.jinja:19 com/templates/com/weekmail.jinja:48
#: core/templates/core/base.jinja:341 forum/templates/forum/forum.jinja:30
#: forum/templates/forum/forum.jinja:49 forum/templates/forum/main.jinja:27
#: forum/views.py:213
#: core/templates/core/base.jinja:343 forum/templates/forum/forum.jinja:24
#: forum/templates/forum/forum.jinja:43 forum/templates/forum/main.jinja:27
#: forum/views.py:240
msgid "Title"
msgstr "Titre"
@ -1518,7 +1519,7 @@ msgstr "Résumé"
#: com/templates/com/news_admin_list.jinja:252
#: com/templates/com/news_admin_list.jinja:289
#: com/templates/com/weekmail.jinja:17 com/templates/com/weekmail.jinja:46
#: forum/templates/forum/forum.jinja:53
#: forum/templates/forum/forum.jinja:47
msgid "Author"
msgstr "Auteur"
@ -1571,7 +1572,7 @@ msgid "Calls to moderate"
msgstr "Appels à modérer"
#: com/templates/com/news_admin_list.jinja:242
#: core/templates/core/base.jinja:163
#: core/templates/core/base.jinja:166
msgid "Events"
msgstr "Événements"
@ -2000,7 +2001,7 @@ msgstr "-"
msgid "XS"
msgstr "XS"
#: core/models.py:214 core/templates/core/base.jinja:354
#: core/models.py:214 core/templates/core/base.jinja:356
msgid "S"
msgstr "S"
@ -2096,11 +2097,11 @@ msgstr "adresse des parents"
msgid "is subscriber viewable"
msgstr "profil visible par les cotisants"
#: core/models.py:476
#: core/models.py:480
msgid "A user with that username already exists"
msgstr "Un utilisateur de ce nom d'utilisateur existe déjà"
#: core/models.py:614 core/templates/core/macros.jinja:72
#: core/models.py:618 core/templates/core/macros.jinja:72
#: core/templates/core/macros.jinja:74 core/templates/core/macros.jinja:75
#: core/templates/core/user_detail.jinja:79
#: core/templates/core/user_detail.jinja:80
@ -2112,115 +2113,116 @@ msgstr "Un utilisateur de ce nom d'utilisateur existe déjà"
#: core/templates/core/user_detail.jinja:92
#: core/templates/core/user_edit.jinja:17
#: election/templates/election/election_detail.jinja:340
#: forum/templates/forum/macros.jinja:93 forum/templates/forum/macros.jinja:95
#: forum/templates/forum/reply.jinja:39 forum/templates/forum/reply.jinja:41
#: forum/templates/forum/macros.jinja:104
#: forum/templates/forum/macros.jinja:106 forum/templates/forum/reply.jinja:39
#: forum/templates/forum/reply.jinja:41
#: trombi/templates/trombi/user_tools.jinja:41
msgid "Profile"
msgstr "Profil"
#: core/models.py:734
#: core/models.py:738
msgid "Visitor"
msgstr "Visiteur"
#: core/models.py:740
#: core/models.py:744
msgid "do you want to receive the weekmail"
msgstr "voulez-vous recevoir le Weekmail"
#: core/models.py:742
#: core/models.py:746
msgid "show your stats to others"
msgstr "montrez vos statistiques aux autres"
#: core/models.py:744
#: core/models.py:748
msgid "get a notification for every click"
msgstr "recevez une notification pour chaque click"
#: core/models.py:747
#: core/models.py:751
msgid "get a notification for every refilling"
msgstr "recevez une notification pour chaque rechargement"
#: core/models.py:770
#: core/models.py:774
msgid "file name"
msgstr "nom du fichier"
#: core/models.py:772 core/models.py:1111
#: core/models.py:776 core/models.py:1115
msgid "parent"
msgstr "parent"
#: core/models.py:783
#: core/models.py:787
msgid "compressed file"
msgstr "version allégée"
#: core/models.py:790
#: core/models.py:794
msgid "thumbnail"
msgstr "miniature"
#: core/models.py:795 core/models.py:810
#: core/models.py:799 core/models.py:814
msgid "owner"
msgstr "propriétaire"
#: core/models.py:797 core/models.py:1130 core/views/files.py:193
#: core/models.py:801 core/models.py:1134 core/views/files.py:193
msgid "edit group"
msgstr "groupe d'édition"
#: core/models.py:800 core/models.py:1133 core/views/files.py:196
#: core/models.py:804 core/models.py:1137 core/views/files.py:196
msgid "view group"
msgstr "groupe de vue"
#: core/models.py:802
#: core/models.py:806
msgid "is folder"
msgstr "est un dossier"
#: core/models.py:803
#: core/models.py:807
msgid "mime type"
msgstr "type mime"
#: core/models.py:804
#: core/models.py:808
msgid "size"
msgstr "taille"
#: core/models.py:814
#: core/models.py:818
msgid "asked for removal"
msgstr "retrait demandé"
#: core/models.py:816
#: core/models.py:820
msgid "is in the SAS"
msgstr "est dans le SAS"
#: core/models.py:858
#: core/models.py:862
msgid "Character '/' not authorized in name"
msgstr "Le caractère '/' n'est pas autorisé dans les noms de fichier"
#: core/models.py:860 core/models.py:864
#: core/models.py:864 core/models.py:868
msgid "Loop in folder tree"
msgstr "Boucle dans l'arborescence des dossiers"
#: core/models.py:867
#: core/models.py:871
msgid "You can not make a file be a children of a non folder file"
msgstr ""
"Vous ne pouvez pas mettre un fichier enfant de quelque chose qui n'est pas "
"un dossier"
#: core/models.py:878
#: core/models.py:882
msgid "Duplicate file"
msgstr "Un fichier de ce nom existe déjà"
#: core/models.py:895
#: core/models.py:899
msgid "You must provide a file"
msgstr "Vous devez fournir un fichier"
#: core/models.py:1035
#: core/models.py:1039
msgid "Folder: "
msgstr "Dossier : "
#: core/models.py:1037
#: core/models.py:1041
msgid "File: "
msgstr "Fichier : "
#: core/models.py:1094
#: core/models.py:1098
msgid "page unix name"
msgstr "nom unix de la page"
#: core/models.py:1100
#: core/models.py:1104
msgid ""
"Enter a valid page name. This value may contain only unaccented letters, "
"numbers and ./+/-/_ characters."
@ -2228,51 +2230,51 @@ msgstr ""
"Entrez un nom de page correct. Uniquement des lettres non accentuées, "
"numéros, et ./+/-/_"
#: core/models.py:1118
#: core/models.py:1122
msgid "page name"
msgstr "nom de la page"
#: core/models.py:1126
#: core/models.py:1130
msgid "owner group"
msgstr "groupe propriétaire"
#: core/models.py:1138
#: core/models.py:1142
msgid "lock user"
msgstr "utilisateur bloquant"
#: core/models.py:1144
#: core/models.py:1148
msgid "lock_timeout"
msgstr "décompte du déblocage"
#: core/models.py:1175
#: core/models.py:1179
msgid "Duplicate page"
msgstr "Une page de ce nom existe déjà"
#: core/models.py:1178
#: core/models.py:1182
msgid "Loop in page tree"
msgstr "Boucle dans l'arborescence des pages"
#: core/models.py:1338
#: core/models.py:1342
msgid "revision"
msgstr "révision"
#: core/models.py:1339
#: core/models.py:1343
msgid "page title"
msgstr "titre de la page"
#: core/models.py:1340
#: core/models.py:1344
msgid "page content"
msgstr "contenu de la page"
#: core/models.py:1382
#: core/models.py:1386
msgid "url"
msgstr "url"
#: core/models.py:1383
#: core/models.py:1387
msgid "param"
msgstr "param"
#: core/models.py:1388
#: core/models.py:1392
msgid "viewed"
msgstr "vue"
@ -2292,96 +2294,95 @@ msgstr "500, Erreur Serveur"
msgid "Welcome!"
msgstr "Bienvenue!"
#: core/templates/core/base.jinja:45
#: core/templates/core/base.jinja:48
msgid "Username"
msgstr "Nom d'utilisateur"
#: core/templates/core/base.jinja:47
#: core/templates/core/base.jinja:50
msgid "Password"
msgstr "Mot de passe"
#: core/templates/core/base.jinja:49 core/templates/core/login.jinja:4
#: core/templates/core/base.jinja:52 core/templates/core/login.jinja:4
#: core/templates/core/password_reset_complete.jinja:5
msgid "Login"
msgstr "Connexion"
#: core/templates/core/base.jinja:51 core/templates/core/register.jinja:18
#: core/templates/core/base.jinja:54 core/templates/core/register.jinja:18
msgid "Register"
msgstr "S'enregister"
#: core/templates/core/base.jinja:75 core/templates/core/base.jinja:76
#: forum/templates/forum/macros.jinja:160
#: forum/templates/forum/macros.jinja:162
#: core/templates/core/base.jinja:78 core/templates/core/base.jinja:79
#: forum/templates/forum/macros.jinja:171
#: forum/templates/forum/macros.jinja:175
#: matmat/templates/matmat/search_form.jinja:37
#: matmat/templates/matmat/search_form.jinja:47
#: matmat/templates/matmat/search_form.jinja:58
msgid "Search"
msgstr "Recherche"
#: core/templates/core/base.jinja:102
#: core/templates/core/base.jinja:105
msgid "View more"
msgstr "Voir plus"
#: core/templates/core/base.jinja:106
#: core/templates/core/base.jinja:109
#: forum/templates/forum/last_unread.jinja:17
msgid "Mark all as read"
msgstr "Marquer tout commme lu"
#: core/templates/core/base.jinja:116
#: core/templates/core/base.jinja:119
msgid "Logout"
msgstr "Déconnexion"
#: core/templates/core/base.jinja:149
#: core/templates/core/base.jinja:152
msgid "Main"
msgstr "Accueil"
#: core/templates/core/base.jinja:151
#: core/templates/core/base.jinja:154
msgid "Associations & Clubs"
msgstr "Associations & Clubs"
#: core/templates/core/base.jinja:155
#: core/templates/core/base.jinja:158
msgid "AE"
msgstr "L'AE"
#: core/templates/core/base.jinja:156
#: core/templates/core/base.jinja:159
msgid "AE's clubs"
msgstr "Les clubs de L'AE"
#: core/templates/core/base.jinja:157
#: core/templates/core/base.jinja:160
msgid "BdF"
msgstr "Le BdF"
#: core/templates/core/base.jinja:158
#: core/templates/core/base.jinja:161
msgid "BDS"
msgstr "Le BDS"
#: core/templates/core/base.jinja:159
#: core/templates/core/base.jinja:162
msgid "CETU"
msgstr "Le CETU"
#: core/templates/core/base.jinja:167
#: core/templates/core/base.jinja:170
msgid "Calendar"
msgstr "Calendrier"
#: core/templates/core/base.jinja:168
#: core/templates/core/base.jinja:171
msgid "Big event"
msgstr "GA"
#: core/templates/core/base.jinja:171
#: core/templates/core/base.jinja:174
#: forum/templates/forum/favorite_topics.jinja:14
#: forum/templates/forum/forum.jinja:10
#: forum/templates/forum/last_unread.jinja:14
#: forum/templates/forum/main.jinja:6 forum/templates/forum/main.jinja:11
#: forum/templates/forum/main.jinja:14 forum/templates/forum/reply.jinja:16
#: forum/templates/forum/topic.jinja:31
#: forum/templates/forum/macros.jinja:90 forum/templates/forum/main.jinja:6
#: forum/templates/forum/main.jinja:11 forum/templates/forum/main.jinja:14
#: forum/templates/forum/reply.jinja:16
msgid "Forum"
msgstr "Forum"
#: core/templates/core/base.jinja:172
#: core/templates/core/base.jinja:175
msgid "Gallery"
msgstr "Photos"
#: core/templates/core/base.jinja:173 counter/models.py:217
#: core/templates/core/base.jinja:176 counter/models.py:217
#: counter/templates/counter/counter_list.jinja:11
#: eboutic/templates/eboutic/eboutic_main.jinja:4
#: eboutic/templates/eboutic/eboutic_main.jinja:24
@ -2391,107 +2392,107 @@ msgstr "Photos"
msgid "Eboutic"
msgstr "Eboutic"
#: core/templates/core/base.jinja:175
#: core/templates/core/base.jinja:178
msgid "Services"
msgstr "Services"
#: core/templates/core/base.jinja:179
#: core/templates/core/base.jinja:182
msgid "Matmatronch"
msgstr "Matmatronch"
#: core/templates/core/base.jinja:180 launderette/models.py:44
#: core/templates/core/base.jinja:183 launderette/models.py:44
#: launderette/templates/launderette/launderette_book.jinja:5
#: launderette/templates/launderette/launderette_book_choose.jinja:4
#: launderette/templates/launderette/launderette_main.jinja:4
msgid "Launderette"
msgstr "Laverie"
#: core/templates/core/base.jinja:181 core/templates/core/file.jinja:20
#: core/templates/core/base.jinja:184 core/templates/core/file.jinja:20
#: core/views/files.py:86
msgid "Files"
msgstr "Fichiers"
#: core/templates/core/base.jinja:182
#: core/templates/core/base.jinja:185
msgid "Pedagogy"
msgstr "Pédagogie"
#: core/templates/core/base.jinja:185
#: core/templates/core/base.jinja:188
msgid "Sponsors"
msgstr "Partenaires"
#: core/templates/core/base.jinja:187
#: core/templates/core/base.jinja:190
msgid "Help"
msgstr "Aide"
#: core/templates/core/base.jinja:191
#: core/templates/core/base.jinja:194
msgid "FAQ"
msgstr "FAQ"
#: core/templates/core/base.jinja:192 core/templates/core/base.jinja:234
#: core/templates/core/base.jinja:195 core/templates/core/base.jinja:237
msgid "Contacts"
msgstr "Contacts"
#: core/templates/core/base.jinja:193
#: core/templates/core/base.jinja:196
msgid "Wiki"
msgstr "Wiki"
#: core/templates/core/base.jinja:235
#: core/templates/core/base.jinja:238
msgid "Legal notices"
msgstr "Mentions légales"
#: core/templates/core/base.jinja:236
#: core/templates/core/base.jinja:239
msgid "Intellectual property"
msgstr "Propriété intellectuelle"
#: core/templates/core/base.jinja:237
#: core/templates/core/base.jinja:240
msgid "Help & Documentation"
msgstr "Aide & Documentation"
#: core/templates/core/base.jinja:238
#: core/templates/core/base.jinja:241
msgid "R&D"
msgstr "R&D"
#: core/templates/core/base.jinja:239
#: core/templates/core/base.jinja:242
msgid "Former website"
msgstr "Ancien site"
#: core/templates/core/base.jinja:241
#: core/templates/core/base.jinja:244
msgid "Site made by good people"
msgstr "Site réalisé par des gens bons"
#: core/templates/core/base.jinja:338
#: core/templates/core/base.jinja:340
msgid "https://path/to/image.gif"
msgstr "https://chemin/vers/image.gif"
#: core/templates/core/base.jinja:340
#: core/templates/core/base.jinja:342
msgid "alternative text"
msgstr "texte alternatif"
#: core/templates/core/base.jinja:350
#: core/templates/core/base.jinja:352
msgid "Image"
msgstr "Image"
#: core/templates/core/base.jinja:351
#: core/templates/core/base.jinja:353
msgid "Link"
msgstr "Lien"
#: core/templates/core/base.jinja:352
#: core/templates/core/base.jinja:354
msgid "sup"
msgstr "exp"
#: core/templates/core/base.jinja:353
#: core/templates/core/base.jinja:355
msgid "sub"
msgstr "ind"
#: core/templates/core/base.jinja:355
#: core/templates/core/base.jinja:357
msgid "U"
msgstr "S"
#: core/templates/core/base.jinja:356
#: core/templates/core/base.jinja:358
msgid "I"
msgstr "I"
#: core/templates/core/base.jinja:357
#: core/templates/core/base.jinja:359
msgid "B"
msgstr "G"
@ -3392,7 +3393,7 @@ msgstr "Ajouter un nouveau dossier"
msgid "Error creating folder %(folder_name)s: %(msg)s"
msgstr "Erreur de création du dossier %(folder_name)s : %(msg)s"
#: core/views/files.py:123 core/views/forms.py:302 core/views/forms.py:309
#: core/views/files.py:123 core/views/forms.py:323 core/views/forms.py:330
#: sas/views.py:93
#, python-format
msgid "Error uploading file %(file_name)s: %(msg)s"
@ -3402,23 +3403,91 @@ msgstr "Erreur d'envoi du fichier %(file_name)s : %(msg)s"
msgid "Apply rights recursively"
msgstr "Appliquer les droits récursivement"
#: core/views/forms.py:101
msgid "Help on the syntax"
msgstr "Aide sur la syntaxe"
#: core/views/forms.py:105
msgid "Heading"
msgstr "Titre"
#: core/views/forms.py:118 core/views/forms.py:126
#: core/views/forms.py:106
msgid "Italic"
msgstr "Italique"
#: core/views/forms.py:107
msgid "Bold"
msgstr "Gras"
#: core/views/forms.py:108
msgid "Strikethrough"
msgstr "Barré"
#: core/views/forms.py:109
msgid "Underline"
msgstr "Souligné"
#: core/views/forms.py:110
msgid "Superscript"
msgstr "Exposant"
#: core/views/forms.py:111
msgid "Subscript"
msgstr "Indice"
#: core/views/forms.py:113
msgid "Quote"
msgstr "Citation"
#: core/views/forms.py:114
msgid "Unordered list"
msgstr "Liste non ordonnée"
#: core/views/forms.py:115
msgid "Ordered list"
msgstr "Liste ordonnée"
#: core/views/forms.py:116
msgid "Insert image"
msgstr "Insérer image"
#: core/views/forms.py:117
msgid "Insert link"
msgstr "Insérer lien"
#: core/views/forms.py:118
msgid "Insert table"
msgstr "Insérer tableau"
#: core/views/forms.py:119
msgid "Clean block"
msgstr "Nettoyer bloc"
#: core/views/forms.py:120
msgid "Toggle preview"
msgstr "Activer la prévisualisation"
#: core/views/forms.py:121
msgid "Toggle side by side"
msgstr "Activer la vue côte à côte"
#: core/views/forms.py:122
msgid "Toggle fullscreen"
msgstr "Activer le plein écran"
#: core/views/forms.py:123
msgid "Markdown guide"
msgstr "Guide markdown"
#: core/views/forms.py:139 core/views/forms.py:147
msgid "Choose file"
msgstr "Choisir un fichier"
#: core/views/forms.py:142 core/views/forms.py:150
#: core/views/forms.py:163 core/views/forms.py:171
msgid "Choose user"
msgstr "Choisir un utilisateur"
#: core/views/forms.py:182
#: core/views/forms.py:203
msgid "Username, email, or account number"
msgstr "Nom d'utilisateur, email, ou numéro de compte AE"
#: core/views/forms.py:248
#: core/views/forms.py:269
msgid ""
"Profile: you need to be visible on the picture, in order to be recognized (e."
"g. by the barmen)"
@ -3426,32 +3495,32 @@ msgstr ""
"Photo de profil: vous devez être visible sur la photo afin d'être reconnu "
"(par exemple par les barmen)"
#: core/views/forms.py:250
#: core/views/forms.py:271
msgid "Avatar: used on the forum"
msgstr "Avatar : utilisé sur le forum"
#: core/views/forms.py:251
#: core/views/forms.py:272
msgid "Scrub: let other know how your scrub looks like!"
msgstr "Blouse : montrez aux autres à quoi ressemble votre blouse !"
#: core/views/forms.py:313
#: core/views/forms.py:334
msgid "Bad image format, only jpeg, png, and gif are accepted"
msgstr "Mauvais format d'image, seuls les jpeg, png, et gif sont acceptés"
#: core/views/forms.py:333
#: core/views/forms.py:354
msgid "Godfather"
msgstr "Parrain"
#: core/views/forms.py:333
#: core/views/forms.py:354
msgid "Godchild"
msgstr "Fillot"
#: core/views/forms.py:350 core/views/forms.py:368 election/models.py:24
#: core/views/forms.py:371 core/views/forms.py:389 election/models.py:24
#: election/views.py:167
msgid "edit groups"
msgstr "groupe d'édition"
#: core/views/forms.py:353 core/views/forms.py:371 election/models.py:31
#: core/views/forms.py:374 core/views/forms.py:392 election/models.py:31
#: election/views.py:170
msgid "view groups"
msgstr "groupe de vue"
@ -4178,7 +4247,7 @@ msgstr "Les votes ouvriront "
#: election/templates/election/election_list.jinja:35
#: election/templates/election/election_list.jinja:40
#: election/templates/election/election_list.jinja:43
#: forum/templates/forum/macros.jinja:137
#: forum/templates/forum/macros.jinja:148
msgid " at "
msgstr " à "
@ -4354,25 +4423,25 @@ msgstr "dernière date de lecture"
msgid "Favorite topics"
msgstr "Topics favoris"
#: forum/templates/forum/forum.jinja:20 forum/templates/forum/main.jinja:22
#: forum/templates/forum/forum.jinja:14 forum/templates/forum/main.jinja:22
msgid "New forum"
msgstr "Nouveau forum"
#: forum/templates/forum/forum.jinja:23 forum/templates/forum/reply.jinja:8
#: forum/templates/forum/forum.jinja:17 forum/templates/forum/reply.jinja:8
#: forum/templates/forum/reply.jinja:28
msgid "New topic"
msgstr "Nouveau sujet"
#: forum/templates/forum/forum.jinja:34 forum/templates/forum/main.jinja:31
#: forum/templates/forum/forum.jinja:28 forum/templates/forum/main.jinja:31
msgid "Topics"
msgstr "Sujets"
#: forum/templates/forum/forum.jinja:37 forum/templates/forum/forum.jinja:59
#: forum/templates/forum/forum.jinja:31 forum/templates/forum/forum.jinja:53
#: forum/templates/forum/main.jinja:34
msgid "Last message"
msgstr "Dernier message"
#: forum/templates/forum/forum.jinja:56
#: forum/templates/forum/forum.jinja:50
msgid "Messages"
msgstr "Messages"
@ -4386,23 +4455,23 @@ msgstr "Derniers messages non lus"
msgid "Refresh"
msgstr "Rafraîchir"
#: forum/templates/forum/macros.jinja:115
#: forum/templates/forum/macros.jinja:126
msgid "Reply as quote"
msgstr "Répondre en citant"
#: forum/templates/forum/macros.jinja:121
#: forum/templates/forum/macros.jinja:132
msgid "Undelete"
msgstr "Restaurer"
#: forum/templates/forum/macros.jinja:138
#: forum/templates/forum/macros.jinja:149
msgid " the "
msgstr " le "
#: forum/templates/forum/macros.jinja:150
#: forum/templates/forum/macros.jinja:161
msgid "Deleted or unreadable message."
msgstr "Message supprimé ou non-visible."
#: forum/templates/forum/macros.jinja:161
#: forum/templates/forum/macros.jinja:174
msgid "Order by date"
msgstr "Trier par date"
@ -4411,27 +4480,27 @@ msgid "View last unread messages"
msgstr "Voir les derniers messages non lus"
#: forum/templates/forum/reply.jinja:6 forum/templates/forum/reply.jinja:25
#: forum/templates/forum/topic.jinja:42 forum/templates/forum/topic.jinja:67
#: forum/templates/forum/topic.jinja:34 forum/templates/forum/topic.jinja:60
msgid "Reply"
msgstr "Répondre"
#: forum/templates/forum/search.jinja:16
#: forum/templates/forum/search.jinja:17
msgid "No result found"
msgstr "Pas de résultats"
#: forum/templates/forum/topic.jinja:44
#: forum/templates/forum/topic.jinja:36
msgid "Unmark as favorite"
msgstr "Enlever des favoris"
#: forum/templates/forum/topic.jinja:46
#: forum/templates/forum/topic.jinja:38
msgid "Mark as favorite"
msgstr "Ajouter aux favoris"
#: forum/views.py:159
#: forum/views.py:186
msgid "Apply rights and club owner recursively"
msgstr "Appliquer les droits et le club propriétaire récursivement"
#: forum/views.py:377
#: forum/views.py:404
#, python-format
msgid "%(author)s said"
msgstr "Citation de %(author)s"
@ -5470,3 +5539,6 @@ msgstr "Vous ne pouvez plus écrire de commentaires, la date est passée."
#, python-format
msgid "Maximum characters: %(max_length)s"
msgstr "Nombre de caractères max: %(max_length)s"
#~ msgid "Help on the syntax"
#~ msgstr "Aide sur la syntaxe"