diff --git a/Changelog.md b/Changelog.md
index ca6dfea1..a419effb 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,35 @@
# Changelog for lgr-django
+## 3.0.0 (2020-12-04)
+### New features
+- Add MSR-4 validating repertoire
+- Add RZ-LGR validating repertoires
+- Add RZ-LGR in built in LGRs list
+- Allow collision tool to check collisions with existing set of TLDs downloaded from IANA
+- Add a new basic mode:
+ - new simplified interface
+ - validate labels against RZ-LGR
+ - allow checking for collisions as well
+- Add language autocompletion from IANA language registry
+- Stop support for python 2.7
+### Improvements
+- Update symetry report to consider contextual rules
+- Update Django to version 2.2.1
+- Update dependencies versions
+- Handle internationalized email addresses
+- Add translation to validation report
+- Cache scripts and repertoires
+- Improve memory consumption
+- Display IDNA error as user friendly strings
+- Correctly validate rule in LGR edition tool
+### Fixes
+- Fix memory leak
+- Fix error handling in label validation
+
+## 2.0.1 (2019-08-01)
+### Improvements
+- Mark out-of-script codepoints as warnings instead of errors (Fixes icann/lgr-core#15).
+
## 2.0.0 (2018-09-06)
### New features
- Support of Python 3. Compatibility with python2 is preserved for this release.
diff --git a/Makefile b/Makefile
index ef8d2f85..6e4f7657 100644
--- a/Makefile
+++ b/Makefile
@@ -22,6 +22,10 @@ MO_FILES= \
src/lgr_tools/locale/ar/LC_MESSAGES/django.mo \
src/lgr_tools/locale/en/LC_MESSAGES/django.mo \
src/lgr_tools/locale/fr/LC_MESSAGES/django.mo \
+ src/lgr_basic/locale/ar/LC_MESSAGES/django.mo \
+ src/lgr_basic/locale/en/LC_MESSAGES/django.mo \
+ src/lgr_basic/locale/fr/LC_MESSAGES/django.mo \
+
PO_FILES= \
src/lgr_web/locale/ar/LC_MESSAGES/django.po \
@@ -36,12 +40,16 @@ PO_FILES= \
src/lgr_tools/locale/ar/LC_MESSAGES/django.po \
src/lgr_tools/locale/en/LC_MESSAGES/django.po \
src/lgr_tools/locale/fr/LC_MESSAGES/django.po \
+ src/lgr_basic/locale/ar/LC_MESSAGES/django.po \
+ src/lgr_basic/locale/en/LC_MESSAGES/django.po \
+ src/lgr_basic/locale/fr/LC_MESSAGES/django.po \
+
all: messages
messages: $(MO_FILES)
-update: update-lgrweb update-lgreditor update-lgrvalidator update-lgrtools
+update: update-lgrweb update-lgreditor update-lgrvalidator update-lgrtools update-lgrbasic
update-lgrweb:
cd src/lgr_web && $(MAKEMESSAGES) $(LANGUAGES) $(MKMSG_OPTIONS)
@@ -55,6 +63,10 @@ update-lgrvalidator:
update-lgrtools:
cd src/lgr_tools && $(MAKEMESSAGES) $(LANGUAGES) $(MKMSG_OPTIONS)
+update-lgrbasic:
+ cd src/lgr_basic && $(MAKEMESSAGES) $(LANGUAGES) $(MKMSG_OPTIONS)
+
+
src/lgr_web/locale/%/LC_MESSAGES/django.po:
cd `echo "$@" | sed -e 's#\/locale/.*##'` && django-admin.py makemessages $(LANGUAGES) $(MKMSG_OPTIONS)
@@ -67,5 +79,8 @@ src/lgr_validator/locale/%/LC_MESSAGES/django.po:
src/lgr_tools/locale/%/LC_MESSAGES/django.po:
cd `echo "$@" | sed -e 's#\/locale/.*##'` && django-admin.py makemessages $(LANGUAGES) $(MKMSG_OPTIONS)
+src/lgr_basic/locale/%/LC_MESSAGES/django.po:
+ cd `echo "$@" | sed -e 's#\/locale/.*##'` && django-admin.py makemessages $(LANGUAGES) $(MKMSG_OPTIONS)
+
$(MO_FILES): $(PO_FILES)
cd `echo "$@" | sed -e 's#\/locale/.*##'` && $(COMPILEMESSAGES)
diff --git a/README.md b/README.md
index 17c95964..4ca84369 100644
--- a/README.md
+++ b/README.md
@@ -11,11 +11,12 @@ The following modules are reusable Django apps that can be included in other Dja
* `lgr_validator` contains the code related the label validation module.
* `lgr_tools` contains the code related to all utilities: testing LGR and label sets, LGR comparisons, etc.
* `lgr_renderer` contains the code and templates used to generate the static exports of the LGR (HTML only for now).
+* `lgr_basic` contains the code related to the simple LGR interface.
## Acknowledgment
This toolset was implemented by Viagenie (Audric Schiltknecht, Julien Bernard,
-David Drouin and Marc Blanchet) and Wil Tan on an ICANN contract.
+David Drouin, Vincent Gonzalez and Marc Blanchet) and Wil Tan on an ICANN contract.
## License
@@ -53,7 +54,7 @@ THE POSSIBILITY OF SUCH DAMAGE.
### Pre-requisites
* Operating system: Tested on Linux and Mac OS X
-* Python 2.7, >= 3.4
+* Python >=3.6
* [LibXML2](http://www.xmlsoft.org/) [MIT License] used by the lxml Python bindings
* [ICU4C](http://site.icu-project.org/) [ICU License]
* Python modules (listed in `etc/requirements.txt`, or dependencies thereof)
@@ -183,6 +184,7 @@ Some notes for developers
* `src/lgr_validator/templates` contains validator-specific templates
* `src/lgr_tools/templates` contains tool-specific templates
* `src/lgr_renderer/templates` contains renderers (HTML output) templates
+* `src/lgr_basic/templates` contains simple interface (HTML output) templates
#### Static Assets (CSS, Javascript, Images)
diff --git a/bin/bootstrap b/bin/bootstrap
index 1694ccac..7e6539fa 100755
--- a/bin/bootstrap
+++ b/bin/bootstrap
@@ -5,7 +5,7 @@ DSITE="src/lgr_web"
if [ ! -e venv ]; then
echo "==> Creating virtualenv"
- virtualenv venv || exit 3
+ virtualenv -p python3 venv || exit 3
fi
# activate virtualenv
diff --git a/etc/requirements.txt b/etc/requirements.txt
index bc3a9309..9dbabe5a 100644
--- a/etc/requirements.txt
+++ b/etc/requirements.txt
@@ -1,14 +1,17 @@
# Core stuff
-Django==1.8.4
-django-widget-tweaks==1.4.1
-django-multiupload==0.5.2
-celery[redis]==3.1.23
-django-redis-cache==1.7.1
+Django==2.2.1
+django-widget-tweaks==1.4.3
+#django-multiupload==0.5.2
+-e git+https://github.com/Chive/django-multiupload.git@ba52e161a68ce19062c3655e89544c2d377990a0#egg=django-multiupload
+celery[redis]==4.3.0
+django-redis-cache==2.0.0
+django-autocomplete-light==3.5.1
+vine==1.3.0
# LGR/Unicode modules
-picu==1.0
+picu==1.1
munidata==2.0.0
-lgr-core==2.0.0
+lgr-core==3.0.0
# Natural sorting implementation
-natsort==5.0.3
+natsort==6.0.0
diff --git a/setup.py b/setup.py
index be98a9eb..9834a23b 100755
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@
setup(
name='lgr-django',
- version='2.0.0',
+ version='3.0.0',
author='Viagenie and Wil Tan',
author_email='support@viagenie.ca',
packages=find_packages('src'),
@@ -19,15 +19,18 @@
'Framework :: Django :: 1.8',
'Operating System :: OS Independent',
'Programming Language :: Python',
- 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
],
install_requires=[
# Core stuff
'Django',
'django-widget-tweaks',
+ 'django-multiupload',
+ 'django-redis-cache',
+ 'django-autocomplete-light',
'celery',
# LGR/Unicode modules
'lgr-core',
diff --git a/src/lgr_basic/__init__.py b/src/lgr_basic/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/lgr_basic/forms.py b/src/lgr_basic/forms.py
new file mode 100644
index 00000000..9db1ff25
--- /dev/null
+++ b/src/lgr_basic/forms.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+from django import forms
+from django.core.exceptions import ValidationError
+from django.utils.translation import ugettext_lazy as _
+
+from lgr.tools.utils import parse_label_input
+from lgr_editor.api import LGRInfo
+from lgr_editor.forms.fields import ROOT_ZONES
+from lgr_editor.lgr_exceptions import lgr_exception_to_text
+from lgr_editor.repertoires import get_by_name
+from lgr_editor.unidb import get_db_by_version
+from lgr_tools.forms import UAEmailField
+
+
+class ValidateLabelSimpleForm(forms.Form):
+ rz_lgr = forms.ChoiceField(label='', required=True, choices=ROOT_ZONES, initial=ROOT_ZONES[-1][0])
+ labels = forms.CharField(label='', required=False,
+ widget=forms.TextInput(attrs={'name': '',
+ 'class': 'form-label form-control',
+ 'onkeyup': 'buttonValidateEnabled()',
+ 'placeholder': _('Label')}))
+ labels_file = forms.FileField(label='', help_text=_('File must be encoded in UTF-8 and using UNIX line ending.'),
+ required=False)
+ email = UAEmailField(label='', required=False,
+ widget=forms.TextInput(attrs={'id': 'email-task',
+ 'placeholder': _('Email address for tasks results')}),
+ help_text=_("As the computing may be very long, we will warn by e-mail once the result can "
+ "be downloaded."))
+ collisions = forms.BooleanField(label='', widget=forms.CheckboxInput(attrs={'id': 'check-for-collision'}),
+ required=False)
+
+ def clean(self):
+ cleaned_data = super(ValidateLabelSimpleForm, self).clean()
+ if (self.cleaned_data.get('collisions') and len(cleaned_data.get('labels', [])) > 1) or self.cleaned_data.get(
+ 'labels_file'):
+ if not self.cleaned_data.get('email'):
+ self.add_error('email', _('E-mail is mandatory to get the tasks results'))
+
+ if 'labels' not in self.errors and not cleaned_data.get('labels') and not cleaned_data.get('labels_file'):
+ self.add_error('labels', _('Required'))
+ self.add_error('labels_file', _('Required'))
+
+ if cleaned_data.get('labels') and cleaned_data.get('labels_file'):
+ # should not happen
+ self.add_error('labels', _('Unknown error, please report'))
+ self.add_error('labels_file', _('Unknown error, please report'))
+
+ return cleaned_data
+
+ def clean_labels(self):
+ rz_lgr = self.cleaned_data['rz_lgr']
+ lgr_info = LGRInfo(rz_lgr, lgr=get_by_name(rz_lgr, with_unidb=True))
+ udata = get_db_by_version(lgr_info.lgr.metadata.unicode_version)
+
+ value = self.cleaned_data['labels']
+ labels = list()
+ for label in set(value.split(';')):
+ if not label:
+ continue
+ try:
+ labels.append(parse_label_input(label, idna_decoder=udata.idna_decode_label))
+ except ValueError as e:
+ raise ValidationError(lgr_exception_to_text(e))
+ return labels
diff --git a/src/lgr_basic/locale/ar/LC_MESSAGES/django.mo b/src/lgr_basic/locale/ar/LC_MESSAGES/django.mo
new file mode 100644
index 00000000..74dbaf67
Binary files /dev/null and b/src/lgr_basic/locale/ar/LC_MESSAGES/django.mo differ
diff --git a/src/lgr_basic/locale/ar/LC_MESSAGES/django.po b/src/lgr_basic/locale/ar/LC_MESSAGES/django.po
new file mode 100644
index 00000000..85e5aa8a
--- /dev/null
+++ b/src/lgr_basic/locale/ar/LC_MESSAGES/django.po
@@ -0,0 +1,174 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-12-02 03:08+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
+"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
+
+#: forms.py:21
+msgid "Label"
+msgstr ""
+
+#: forms.py:22
+msgid "File must be encoded in UTF-8 and using UNIX line ending."
+msgstr ""
+
+#: forms.py:26
+msgid "Email address for tasks results"
+msgstr ""
+
+#: forms.py:27
+msgid ""
+"As the computing may be very long, we will warn by e-mail once the result "
+"can be downloaded."
+msgstr ""
+
+#: forms.py:37
+msgid "E-mail is mandatory to get the tasks results"
+msgstr ""
+
+#: forms.py:40 forms.py:41
+msgid "Required"
+msgstr ""
+
+#: forms.py:45 forms.py:46
+msgid "Unknown error, please report"
+msgstr ""
+
+#: templates/basic_mode.html:8 templates/basic_mode.html:39
+msgid "LGR Tool"
+msgstr ""
+
+#: templates/basic_mode.html:38 templates/basic_mode.html:39
+msgid "Go to home screen"
+msgstr ""
+
+#: templates/basic_mode.html:43
+msgid "Advanced mode"
+msgstr ""
+
+#: templates/basic_mode.html:47 templates/basic_mode.html:253
+msgid "Display all label forms"
+msgstr ""
+
+#: templates/basic_mode.html:48
+msgid "Label forms"
+msgstr ""
+
+#: templates/basic_mode.html:53
+msgid "About LGR Toolset"
+msgstr ""
+
+#: templates/basic_mode.html:54 templates/basic_mode.html:235
+msgid "About"
+msgstr ""
+
+#: templates/basic_mode.html:74
+msgid ""
+"The server was unable to complete the request, most likely because too many "
+"resources were required to compute the query. If you check for collision, "
+"the result may be still processing and will be sent to your email. Please "
+"wait before submitting again."
+msgstr ""
+
+#: templates/basic_mode.html:82
+msgid "A server error occurred."
+msgstr ""
+
+#: templates/basic_mode.html:82
+msgid "code:"
+msgstr ""
+
+#: templates/basic_mode.html:82
+msgid "Please contact the administrator before submitting again."
+msgstr ""
+
+#: templates/basic_mode.html:88
+msgid "Validate label(s) against"
+msgstr ""
+
+#: templates/basic_mode.html:93
+msgid "View LGR as"
+msgstr ""
+
+#: templates/basic_mode.html:106
+msgid "Manually input label(s)"
+msgstr ""
+
+#: templates/basic_mode.html:117
+msgid "Upload a list of labels"
+msgstr ""
+
+#: templates/basic_mode.html:136
+msgid "Check for collision with existing TLDs"
+msgstr ""
+
+#: templates/basic_mode.html:150
+#, python-format
+msgid ""
+"Your request was sent successfully, the collision and validation tasks "
+"processing can take minutes, even hours. The result will be sent to "
+"%(email)s. Do not resubmit until you receive the report."
+msgstr ""
+
+#: templates/basic_mode.html:162
+#, python-format
+msgid ""
+"Your request was sent successfully, the validation task processing can take "
+"minutes, even hours. The result will be sent to %(email)s. Do not "
+"resubmit until you receive the report."
+msgstr ""
+
+#: templates/basic_mode.html:174
+#, python-format
+msgid ""
+"Your request was sent successfully, the collision task processing can take "
+"minutes, even hours. The result will be sent to %(email)s. Do not "
+"resubmit until you receive the report."
+msgstr ""
+
+#: templates/basic_mode.html:184
+msgid "Validate"
+msgstr ""
+
+#: templates/basic_mode.html:197
+msgid "Your saved results"
+msgstr ""
+
+#: templates/basic_mode.html:198
+msgid "The following files contains your tools computation results."
+msgstr ""
+
+#: templates/basic_mode.html:201
+msgid "Note that these files could be cleaned up regularly."
+msgstr ""
+
+#: templates/basic_mode.html:206
+#, python-format
+msgid "Download %(file)s"
+msgstr ""
+
+#: templates/basic_mode.html:241
+msgid "Close"
+msgstr ""
+
+#: views.py:83
+msgid ""
+"Input label generates too many variants to compute them all quickly. You "
+"need to enter your email address and will receive a notification once "
+"process is done"
+msgstr ""
diff --git a/src/lgr_basic/locale/en/LC_MESSAGES/django.mo b/src/lgr_basic/locale/en/LC_MESSAGES/django.mo
new file mode 100644
index 00000000..6c5906d1
Binary files /dev/null and b/src/lgr_basic/locale/en/LC_MESSAGES/django.mo differ
diff --git a/src/lgr_basic/locale/en/LC_MESSAGES/django.po b/src/lgr_basic/locale/en/LC_MESSAGES/django.po
new file mode 100644
index 00000000..abd935e6
--- /dev/null
+++ b/src/lgr_basic/locale/en/LC_MESSAGES/django.po
@@ -0,0 +1,172 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-12-02 03:08+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: forms.py:21
+msgid "Label"
+msgstr ""
+
+#: forms.py:22
+msgid "File must be encoded in UTF-8 and using UNIX line ending."
+msgstr ""
+
+#: forms.py:26
+msgid "Email address for tasks results"
+msgstr ""
+
+#: forms.py:27
+msgid ""
+"As the computing may be very long, we will warn by e-mail once the result "
+"can be downloaded."
+msgstr ""
+
+#: forms.py:37
+msgid "E-mail is mandatory to get the tasks results"
+msgstr ""
+
+#: forms.py:40 forms.py:41
+msgid "Required"
+msgstr ""
+
+#: forms.py:45 forms.py:46
+msgid "Unknown error, please report"
+msgstr ""
+
+#: templates/basic_mode.html:8 templates/basic_mode.html:39
+msgid "LGR Tool"
+msgstr ""
+
+#: templates/basic_mode.html:38 templates/basic_mode.html:39
+msgid "Go to home screen"
+msgstr ""
+
+#: templates/basic_mode.html:43
+msgid "Advanced mode"
+msgstr ""
+
+#: templates/basic_mode.html:47 templates/basic_mode.html:253
+msgid "Display all label forms"
+msgstr ""
+
+#: templates/basic_mode.html:48
+msgid "Label forms"
+msgstr ""
+
+#: templates/basic_mode.html:53
+msgid "About LGR Toolset"
+msgstr ""
+
+#: templates/basic_mode.html:54 templates/basic_mode.html:235
+msgid "About"
+msgstr ""
+
+#: templates/basic_mode.html:74
+msgid ""
+"The server was unable to complete the request, most likely because too many "
+"resources were required to compute the query. If you check for collision, "
+"the result may be still processing and will be sent to your email. Please "
+"wait before submitting again."
+msgstr ""
+
+#: templates/basic_mode.html:82
+msgid "A server error occurred."
+msgstr ""
+
+#: templates/basic_mode.html:82
+msgid "code:"
+msgstr ""
+
+#: templates/basic_mode.html:82
+msgid "Please contact the administrator before submitting again."
+msgstr ""
+
+#: templates/basic_mode.html:88
+msgid "Validate label(s) against"
+msgstr ""
+
+#: templates/basic_mode.html:93
+msgid "View LGR as"
+msgstr ""
+
+#: templates/basic_mode.html:106
+msgid "Manually input label(s)"
+msgstr ""
+
+#: templates/basic_mode.html:117
+msgid "Upload a list of labels"
+msgstr ""
+
+#: templates/basic_mode.html:136
+msgid "Check for collision with existing TLDs"
+msgstr ""
+
+#: templates/basic_mode.html:150
+#, python-format
+msgid ""
+"Your request was sent successfully, the collision and validation tasks "
+"processing can take minutes, even hours. The result will be sent to "
+"%(email)s. Do not resubmit until you receive the report."
+msgstr ""
+
+#: templates/basic_mode.html:162
+#, python-format
+msgid ""
+"Your request was sent successfully, the validation task processing can take "
+"minutes, even hours. The result will be sent to %(email)s. Do not "
+"resubmit until you receive the report."
+msgstr ""
+
+#: templates/basic_mode.html:174
+#, python-format
+msgid ""
+"Your request was sent successfully, the collision task processing can take "
+"minutes, even hours. The result will be sent to %(email)s. Do not "
+"resubmit until you receive the report."
+msgstr ""
+
+#: templates/basic_mode.html:184
+msgid "Validate"
+msgstr ""
+
+#: templates/basic_mode.html:197
+msgid "Your saved results"
+msgstr ""
+
+#: templates/basic_mode.html:198
+msgid "The following files contains your tools computation results."
+msgstr ""
+
+#: templates/basic_mode.html:201
+msgid "Note that these files could be cleaned up regularly."
+msgstr ""
+
+#: templates/basic_mode.html:206
+#, python-format
+msgid "Download %(file)s"
+msgstr ""
+
+#: templates/basic_mode.html:241
+msgid "Close"
+msgstr ""
+
+#: views.py:83
+msgid ""
+"Input label generates too many variants to compute them all quickly. You "
+"need to enter your email address and will receive a notification once "
+"process is done"
+msgstr ""
diff --git a/src/lgr_basic/locale/fr/LC_MESSAGES/django.mo b/src/lgr_basic/locale/fr/LC_MESSAGES/django.mo
new file mode 100644
index 00000000..885977d5
Binary files /dev/null and b/src/lgr_basic/locale/fr/LC_MESSAGES/django.mo differ
diff --git a/src/lgr_basic/locale/fr/LC_MESSAGES/django.po b/src/lgr_basic/locale/fr/LC_MESSAGES/django.po
new file mode 100644
index 00000000..ba45c625
--- /dev/null
+++ b/src/lgr_basic/locale/fr/LC_MESSAGES/django.po
@@ -0,0 +1,1100 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-12-02 03:08+0000\n"
+"PO-Revision-Date: 2020-06-04 13:41-0400\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"X-Generator: Poedit 2.3\n"
+
+#: forms.py:21
+msgid "Label"
+msgstr "Label"
+
+#: forms.py:22
+msgid "File must be encoded in UTF-8 and using UNIX line ending."
+msgstr ""
+"Le fichier doit être encodé en UTF-8, et utiliser des retours à la ligne "
+"UNIX."
+
+#: forms.py:26
+msgid "Email address for tasks results"
+msgstr "Adresse e-mail utilisée pour recevoir le résultats des tâches"
+
+#: forms.py:27
+msgid ""
+"As the computing may be very long, we will warn by e-mail once the result "
+"can be downloaded."
+msgstr ""
+"Le temps de calcul peut être très long, vous serez averti par e-mail lorsque "
+"le résultat pourra être téléchargé. Fournissez une adresse e-mail valide "
+"s'il vous plaît."
+
+#: forms.py:37
+msgid "E-mail is mandatory to get the tasks results"
+msgstr ""
+"L'adresse e-mail est obligatoire pour recevoir les résultats des tâches"
+
+#: forms.py:40 forms.py:41
+msgid "Required"
+msgstr "Requis"
+
+#: forms.py:45 forms.py:46
+msgid "Unknown error, please report"
+msgstr "Erreur inconnue, reportez l'erreur s'il vous plait"
+
+#: templates/basic_mode.html:8 templates/basic_mode.html:39
+msgid "LGR Tool"
+msgstr "Outil de gestion de LGR"
+
+#: templates/basic_mode.html:38 templates/basic_mode.html:39
+msgid "Go to home screen"
+msgstr "Retourner à l'écran d'accueil"
+
+#: templates/basic_mode.html:43
+msgid "Advanced mode"
+msgstr "Mode avancé"
+
+#: templates/basic_mode.html:47 templates/basic_mode.html:253
+msgid "Display all label forms"
+msgstr "Afficher toutes les formes d'un label"
+
+#: templates/basic_mode.html:48
+msgid "Label forms"
+msgstr "Formes"
+
+#: templates/basic_mode.html:53
+msgid "About LGR Toolset"
+msgstr "À propos de l'application LGR"
+
+#: templates/basic_mode.html:54 templates/basic_mode.html:235
+msgid "About"
+msgstr "À propos"
+
+#: templates/basic_mode.html:74
+msgid ""
+"The server was unable to complete the request, most likely because too many "
+"resources were required to compute the query. If you check for collision, "
+"the result may be still processing and will be sent to your email. Please "
+"wait before submitting again."
+msgstr ""
+"Le serveur n'a pas pu compléter la requête, probablement parce que trop de "
+"ressources sont nécessaires pour calculer la requête. Si vous vérifiez une "
+"collision, le résultat peut être toujours en cours de traitement et vous "
+"sera envoyé par mail. Merci de patienter avant de soumettre à nouveau."
+
+#: templates/basic_mode.html:82
+msgid "A server error occurred."
+msgstr "Une erreur de serveur s'est produite."
+
+#: templates/basic_mode.html:82
+msgid "code:"
+msgstr "code :"
+
+#: templates/basic_mode.html:82
+msgid "Please contact the administrator before submitting again."
+msgstr ""
+"Veuillez contacter l'administrateur avant de soumettre votre requête à "
+"nouveau."
+
+#: templates/basic_mode.html:88
+msgid "Validate label(s) against"
+msgstr "Valider le(s) label(s) avec"
+
+#: templates/basic_mode.html:93
+msgid "View LGR as"
+msgstr "Voir la LGR en"
+
+#: templates/basic_mode.html:106
+msgid "Manually input label(s)"
+msgstr "Entrer le(s) label(s) manuellement"
+
+#: templates/basic_mode.html:117
+msgid "Upload a list of labels"
+msgstr "Télécharger une liste de labels"
+
+#: templates/basic_mode.html:136
+msgid "Check for collision with existing TLDs"
+msgstr "Vérifier les collisions avec la liste de TLDs"
+
+#: templates/basic_mode.html:150
+#, python-format
+msgid ""
+"Your request was sent successfully, the collision and validation tasks "
+"processing can take minutes, even hours. The result will be sent to "
+"%(email)s. Do not resubmit until you receive the report."
+msgstr ""
+"Votre requête a bien été envoyée, le calcul des collision et la tâche de "
+"validation peuvent prendre plusieurs minutes, voire plusieurs heures. Le "
+"résultat sera envoyé à %(email)s. Ne renvoyez pas de requête tant que vous "
+"n'avez pas reçu le rapport."
+
+#: templates/basic_mode.html:162
+#, python-format
+msgid ""
+"Your request was sent successfully, the validation task processing can take "
+"minutes, even hours. The result will be sent to %(email)s. Do not "
+"resubmit until you receive the report."
+msgstr ""
+"Votre requête a bien été envoyée, la tâche de validation peut prendre "
+"plusieurs minutes, voire plusieurs heures. Le résultat sera envoyé à "
+"%(email)s. Ne renvoyez pas de requête tant que vous n'avez pas reçu le "
+"rapport."
+
+#: templates/basic_mode.html:174
+#, python-format
+msgid ""
+"Your request was sent successfully, the collision task processing can take "
+"minutes, even hours. The result will be sent to %(email)s. Do not "
+"resubmit until you receive the report."
+msgstr ""
+"Votre requête a bien été envoyée, le calcul des collisions peut prendre "
+"plusieurs minutes, voire plusieurs heures. Le résultat sera envoyé à "
+"%(email)s. Ne renvoyez pas de requête tant que vous n'avez pas reçu le "
+"rapport."
+
+#: templates/basic_mode.html:184
+msgid "Validate"
+msgstr "Valider"
+
+#: templates/basic_mode.html:197
+msgid "Your saved results"
+msgstr "Vos résultats sauvegardés"
+
+#: templates/basic_mode.html:198
+msgid "The following files contains your tools computation results."
+msgstr ""
+"Ces fichiers contiennent les résultats des calculs fournis par les outils."
+
+#: templates/basic_mode.html:201
+msgid "Note that these files could be cleaned up regularly."
+msgstr ""
+"Veuillez noter que ces fichiers pourraient être régulièrement supprimés."
+
+#: templates/basic_mode.html:206
+#, python-format
+msgid "Download %(file)s"
+msgstr "Télécharger %(file)s"
+
+#: templates/basic_mode.html:241
+msgid "Close"
+msgstr "Fermer"
+
+#: views.py:83
+msgid ""
+"Input label generates too many variants to compute them all quickly. You "
+"need to enter your email address and will receive a notification once "
+"process is done"
+msgstr ""
+"Le label entré peut générer trop de variantes pour rapidement toutes les "
+"calculer. Vous devez rentrer votre adresse e-mail et recevrez une "
+"notification une fois que le processus est terminé"
+
+#, python-format
+#~ msgid ""
+#~ "Your request was sent successfully, the collision and validation tasks "
+#~ "processing can take minutes, even hours. Both results will be sent to "
+#~ "%(email)s in two separate emails. Do not resubmit until you receive both "
+#~ "reports."
+#~ msgstr ""
+#~ "Votre requête a bien été envoyée, les tâches de collision et de "
+#~ "validation peuvent prendre plusieurs minutes, voire plusieurs heures. "
+#~ "Les deux résultats seront envoyés à %(email)s en deux e-mails distincts. "
+#~ "Ne renvoyez pas de requête tant que vous n'avez pas reçu les deux "
+#~ "rapports."
+
+#~ msgid "Collision task result will be sent to "
+#~ msgstr "Le résultat du calcul de collisions sera envoyé à "
+
+#~ msgid "When"
+#~ msgstr "When"
+
+#~ msgid "Not-When"
+#~ msgstr "Not When"
+
+#~ msgid "Tags"
+#~ msgstr "Tags"
+
+#~ msgid "space-separated tags"
+#~ msgstr "liste de tags séparés par des espaces"
+
+#~ msgid "Code point"
+#~ msgstr "Code point"
+
+#~ msgid "Override repertoire"
+#~ msgstr "Ignorer le répertoire"
+
+#~ msgid "Code points"
+#~ msgstr "Code points"
+
+#~ msgid "Disabled code points"
+#~ msgstr "Code points indisponibles"
+
+#~ msgid "First code point"
+#~ msgstr "Premier code point"
+
+#~ msgid "Last code point"
+#~ msgstr "Dernier code point"
+
+#~ msgid ""
+#~ "Last code point (%(last_cp)s) must not be smaller than the first code "
+#~ "point (%(first_cp)s)"
+#~ msgstr ""
+#~ "Le dernier code point (%(last_cp)s) ne peut être plus petit que le "
+#~ "premier code point (%(first_cp)s)"
+
+#~ msgid "Validating repertoire"
+#~ msgstr "Répertoire de validation"
+
+#~ msgid "Script"
+#~ msgstr "Script"
+
+#~ msgid "Manual import"
+#~ msgstr "Importation manuelle"
+
+#~ msgid "Select a file"
+#~ msgstr "Sélectionner un fichier"
+
+#~ msgid "File type"
+#~ msgstr "Type de fichier"
+
+#~ msgid "Name"
+#~ msgstr "Nom"
+
+#~ msgid "Code points will be limited to the selected repertoire"
+#~ msgstr "Les code points seront limités au répertoire sélectionné"
+
+#~ msgid "Select file(s)"
+#~ msgstr "Sélectionner un/des fichier(s)"
+
+#~ msgid "LGR set name"
+#~ msgstr "Nom du set LGR"
+
+#~ msgid ""
+#~ "Enter a valid LGR set name. This value may contain only letters, numbers "
+#~ "and ./-/_ characters."
+#~ msgstr ""
+#~ "Entrer un nom de LGR valide. Cette valeur ne peut que contenir des "
+#~ "lettres, nombres et les caractères ./-/_."
+
+#~ msgid "The name of the set"
+#~ msgstr "Nom du set"
+
+#~ msgid "Unicode version"
+#~ msgstr "Version d'Unicode"
+
+#~ msgid "The unicode version used"
+#~ msgstr "Version d'Unicode"
+
+#~ msgid "Version"
+#~ msgstr "Version"
+
+#~ msgid "Version comment"
+#~ msgstr "Commentaire de version"
+
+#~ msgid "Date"
+#~ msgstr "Date"
+
+#~ msgid "Scope"
+#~ msgstr "Portée"
+
+#~ msgid "Scope type"
+#~ msgstr "Type de la portée"
+
+#~ msgid "Validity start"
+#~ msgstr "Début de la validité"
+
+#~ msgid "Description"
+#~ msgstr "Description"
+
+#~ msgid "Description type"
+#~ msgstr "Type de la description"
+
+#~ msgid "Built-in"
+#~ msgstr "Fournis"
+
+#~ msgid "My LGRs"
+#~ msgstr "Mes LGRs"
+
+#~ msgid "Language"
+#~ msgstr "Langage"
+
+#~ msgid "Input code point %(codepoint)s is not in the LGR"
+#~ msgstr "Le code point %(codepoint)s n'est pas dans la LGR"
+
+#~ msgid "Input code point %(codepoint)s is not in the reference repertoire"
+#~ msgstr ""
+#~ "Le code point %(codepoint)s n'est pas dans le répertoire de référence"
+
+#~ msgid ""
+#~ "Variant %(variant_codepoint)s already exists for code point %(codepoint)s"
+#~ msgstr ""
+#~ "La variante %(variant_codepoint)s existe déjà pour le code point "
+#~ "%(codepoint)s"
+
+#~ msgid "Range %(first_cp)s - %(last_cp)s already exists in the LGR"
+#~ msgstr "L'ensemble %(first_cp)s - %(last_cp)s existe déjà dans la LGR"
+
+#~ msgid "Input code point %(codepoint)s already exists in the LGR"
+#~ msgstr "Le code point %(codepoint)s existe déjà dans la LGR"
+
+#~ msgid "Input code point %(codepoint)s is not in LGR script"
+#~ msgstr "Le code point %(codepoint)s n'est pas dans le script de la LGR"
+
+#~ msgid ""
+#~ "Input code point %(codepoint)s is not a PVALID/CONTEXTO/CONTEXTJ code "
+#~ "point per IDNA2008"
+#~ msgstr ""
+#~ "Le code point %(codepoint)s n'est pas un code point PVALID/CONTEXTO/"
+#~ "CONTEXTJ d'après IDNA2008"
+
+#~ msgid "Code point %(codepoint)s has invalid context rule %(rule)s"
+#~ msgstr ""
+#~ "Le code point %(codepoint)s a une règle contextuelle invalide %(rule)s"
+
+#~ msgid "Range %(first_cp)s - %(last_cp)s has invalid context rule"
+#~ msgstr ""
+#~ "L'ensemble %(first_cp)s - %(last_cp)s a une règle contextuelle invalide"
+
+#~ msgid ""
+#~ "Variant %(variant_codepoint)s of code point %(codepoint)shas invalid "
+#~ "context rule"
+#~ msgstr ""
+#~ "La variante %(variant_codepoint)s du code point %(codepoint)s a une règle "
+#~ "contextuelle invalide"
+
+#~ msgid "Duplicate reference for code point %(codepoint)s"
+#~ msgstr "Référence dupliquée pour le code point %(codepoint)s"
+
+#~ msgid "Unspecified exception for input code point %(codepoint)s"
+#~ msgstr "Exception non-spécifiée pour le code point d'entrée %(codepoint)s"
+
+#~ msgid "Sequence cannot have a tag"
+#~ msgstr "Les séquences ne peuvent pas avoir de tag"
+
+#~ msgid "Invalid language"
+#~ msgstr "Langage invalide"
+
+#~ msgid "Invalid date value"
+#~ msgstr "Date invalide"
+
+#~ msgid "Invalid Unicode version"
+#~ msgstr "Version d'unicode invalide"
+
+#~ msgid "Invalid LGR XML file"
+#~ msgstr "Fichier XML de LGR invalide"
+
+#~ msgid "Reference %(ref_id)s is not defined"
+#~ msgstr "La référence %(ref_id)s n'est pas définie"
+
+#~ msgid "Reference %(ref_id)s already exists"
+#~ msgstr "La référence %(ref_id)s existe déjà"
+
+#~ msgid "Invalid reference id %(ref_id)s "
+#~ msgstr "Identifiant de référence invalide %(ref_id)s "
+
+#~ msgid "Rule \"%(rule_name)s\" cannot be processed (%(message)s)"
+#~ msgstr "La règle \"%(rule_name)s\" ne peut pas être traitée (%(message)s)"
+
+#~ msgid "Input parameter has invalid format"
+#~ msgstr "Le paramètre d'entrée a un format invalide"
+
+#~ msgid "A general exception occurred in the LGR API"
+#~ msgstr "Une exception s'est produite dans l'API LGR"
+
+#~ msgid "LGR is not valid (%(args)s)"
+#~ msgstr "La LGR n'est pas valide (%(args)s)"
+
+#~ msgid "Label %(label)s is not valid in the LGR (%(message)s)"
+#~ msgstr "Label %(label)s n'est pas valide dans la LGR (%(message)s)"
+
+#~ msgid "Input label file contains collision(s)"
+#~ msgstr "Le fichier d'entrée des labels contient une/des collision(s)"
+
+#~ msgid "The LGR contains a variant that do not have symmetric relations"
+#~ msgstr "La LGR contient des variantes ne respectant pas la symmétrie"
+
+#~ msgid "The LGR does not contain a valid language (%(message)s)"
+#~ msgstr "La LGR ne contient pas de langues valides (%(message)s)"
+
+#~ msgid "Cannot generate cross-script variant for LGR without (%(message)s)"
+#~ msgstr ""
+#~ "Impossible de générer les variantes cross-script pour la LGR sans "
+#~ "(%(message)s)"
+
+#~ msgid "An unknown exception occurred in the LGR API"
+#~ msgstr "Une exception inconnue s'est produite dans l'API LGR"
+
+#~ msgid "References"
+#~ msgstr "Références"
+
+#~ msgid "Meta data"
+#~ msgstr "Métadonnées"
+
+#~ msgid "Rules"
+#~ msgstr "Règles"
+
+#~ msgid "Embedded LGRs"
+#~ msgstr "LGR embarquées"
+
+#~ msgid "Sets:"
+#~ msgstr "Sets:"
+
+#~ msgid "%(lgr_name)s"
+#~ msgstr "%(lgr_name)s"
+
+#~ msgid "Cancel"
+#~ msgstr "Annuler"
+
+#~ msgid "Save"
+#~ msgstr "Sauvegarder"
+
+#~ msgid "Edit"
+#~ msgstr "Modifier"
+
+#~ msgid ""
+#~ "\n"
+#~ " This application provides a convenient interface for browsing\n"
+#~ " and editing LGR’s "
+#~ "conforming to the\n"
+#~ " Representing Label Generation Rulesets using XML\n"
+#~ " specification.\n"
+#~ " "
+#~ msgstr ""
+#~ "\n"
+#~ "Cette application fournit une interface adaptée à la navigation et la "
+#~ "modification de LGR "
+#~ "conformes à la spécification Representing Label Generation Rulesets "
+#~ "using XML.\n"
+#~ " "
+
+#~ msgid "Supported Unicode versions:"
+#~ msgstr "Versions d'Unicode supportées:"
+
+#~ msgid ""
+#~ "This toolset was implemented by Viagénie and Wil Tan on an ICANN contract."
+#~ msgstr ""
+#~ "Cette application a été implémentée par Viagénie et Wil Tan sous contrat ICANN."
+
+#~ msgid "Next"
+#~ msgstr "Suivant"
+
+#~ msgid ""
+#~ "Code points added. Click here if "
+#~ "you are not redirected automatically."
+#~ msgstr ""
+#~ "Code point ajouté. Cliquez ici si "
+#~ "vous n'êtes pas redirigé automatiquement."
+
+#~ msgid "Populate variants"
+#~ msgstr "Peupler les variantes"
+
+#~ msgid "Expand range(s)"
+#~ msgstr "Convertir tous les ensembles"
+
+#~ msgid "Add code point(s)"
+#~ msgstr "Ajouter un/des code point(s)"
+
+#~ msgid "Character Name"
+#~ msgstr "Nom du caractère"
+
+#~ msgid "Comments"
+#~ msgstr "Commentaires"
+
+#~ msgid "Action"
+#~ msgstr "Action"
+
+#~ msgid "Add Rule"
+#~ msgstr "Ajouter une règle"
+
+#~ msgid "There is no rule in the current LGR"
+#~ msgstr "Il n'y a pas de règles dans la LGR courante"
+
+#~ msgid ""
+#~ "\n"
+#~ "
This rule will be added to "
+#~ " codepoint(s)
\n"
+#~ " "
+#~ msgstr ""
+#~ "\n"
+#~ "
Cette règle va être ajoutée à "
+#~ " code point(s)
\n"
+#~ " "
+
+#~ msgid "Code point range"
+#~ msgstr "Ensemble de Code points"
+
+#~ msgid "Code point from script"
+#~ msgstr "Code point depuis un script"
+
+#~ msgid "Import from file"
+#~ msgstr "Importer depuis un fichier"
+
+#~ msgid "Add Code Point"
+#~ msgstr "Ajouter un Code Point"
+
+#~ msgid "Variant(s)"
+#~ msgstr "Variante(s)"
+
+#~ msgid "See code point"
+#~ msgstr "Voir le code point"
+
+#~ msgid "Expand range"
+#~ msgstr "Convertir l'ensemble"
+
+#~ msgid "➡ Select code point(s) to apply batch action..."
+#~ msgstr ""
+#~ "➡ Sélectionner les code points sur lesquels appliquer une action par "
+#~ "lots..."
+
+#~ msgid "Add WLE"
+#~ msgstr "Ajouter une WLE"
+
+#~ msgid "➡ Apply batch action..."
+#~ msgstr "➡ Appliquer action par lots..."
+
+#~ msgid "Code point appeared in Unicode version: %(age)s"
+#~ msgstr "Le code point est apparu dans Unicode version : %(age)s"
+
+#~ msgid "Add variant"
+#~ msgstr "Ajouter une variante"
+
+#~ msgid "Type"
+#~ msgstr "Type"
+
+#~ msgid "Not When"
+#~ msgstr "Not When"
+
+#~ msgid "Code point is not in LGR"
+#~ msgstr "Le code point n'est pas dans la LGR"
+
+#~ msgid "Are you sure you want delete this variant?"
+#~ msgstr "Êtes-vous sûr(e) de vouloir supprimer cette variante ?"
+
+#~ msgid "Delete variant"
+#~ msgstr "Supprimer la variante"
+
+#~ msgid "Edit references"
+#~ msgstr "Modifier les références"
+
+#~ msgid "Range characters do not have variants."
+#~ msgstr "Les ensembles de caractères n'ont pas de variantes."
+
+#~ msgid "Code point has not variant"
+#~ msgstr "Le code point n'a pas de variante"
+
+#~ msgid "Save variants, tags, context rules and comment"
+#~ msgstr ""
+#~ "Sauvegarder les variantes, tags, règles contextuelles et commentaires"
+
+#~ msgid "No references associated with code point."
+#~ msgstr "Aucune référence associée au code point."
+
+#~ msgid "Are you sure you want delete this code point?"
+#~ msgstr "Êtes-vous sûr(e) de vouloir supprimer ce code point ?"
+
+#~ msgid "Delete code point"
+#~ msgstr "Supprimer le code point"
+
+#~ msgid "Edit References for "
+#~ msgstr "Modifier les références pour "
+
+#~ msgctxt "button title"
+#~ msgid "Delete reference"
+#~ msgstr "Supprimer la référence"
+
+#~ msgid "Add an existing reference"
+#~ msgstr "Ajouter un référence existante"
+
+#~ msgid "Add"
+#~ msgstr "Ajouter"
+
+#~ msgid "Create a new reference"
+#~ msgstr "Créer une nouvelle référence"
+
+#~ msgid "Error when adding reference"
+#~ msgstr "Erreur lors de l'ajout d'une référence"
+
+#~ msgid "Reference ID (optional)"
+#~ msgstr "Id de référence (optionnel)"
+
+#~ msgid "URL (optional)"
+#~ msgstr "URL (optionnelle)"
+
+#~ msgid "New reference"
+#~ msgstr "Nouvelle référence"
+
+#~ msgid "Save changes"
+#~ msgstr "Sauvegarder les changements"
+
+#~ msgid "List of LGRs in the set"
+#~ msgstr "Liste des LGR dans le set"
+
+#~ msgid "Import existing LGR"
+#~ msgstr "Importer une LGR existante"
+
+#~ msgid ""
+#~ "To import LGR set, select the XML files composing the LGR set. The set "
+#~ "will automatically be created."
+#~ msgstr ""
+#~ "Pour importer un set LGR, sélectionner les fichiers XML le set LGR. Le "
+#~ "set sera créé automatiquement."
+
+#~ msgid ""
+#~ " Import function "
+#~ "will only perfom some basic checking (example: XML validity). Once the "
+#~ "LGR has been imported, you need to use the Validate LGR "
+#~ "button to do a complete check. "
+#~ msgstr ""
+#~ " La fonction "
+#~ "d'importation effectue uniquement quelques tests de base (par exemple, la "
+#~ "validité du XML). Une fois la LGR importée, vous devez utiliser le bouton "
+#~ "Valider la LGR pour effectuer un test complet. "
+
+#~ msgid "These LGRs are already imported. Click on one to access it."
+#~ msgstr "Les LGRs suivantes sont déjà importées. Cliquer pour y accéder."
+
+#~ msgid "Import"
+#~ msgstr "Importer"
+
+#~ msgid ""
+#~ " "
+#~ "Note that importing large LGR files may take significant time to load on "
+#~ "your browser."
+#~ msgstr ""
+#~ " "
+#~ "L’importation de gros fichiers LGR peut être lente à charger dans le "
+#~ "navigateur."
+
+#~ msgid "Cannot import LGR file(s):"
+#~ msgstr "Impossible d'importer le(s) fichier(s) LGR :"
+
+#~ msgid "Code point sequence"
+#~ msgstr "Séquence de code points"
+
+#~ msgid "U-label"
+#~ msgstr "U-Label"
+
+#~ msgid "A-label"
+#~ msgstr "A-Label"
+
+#~ msgid "There was an error saving; please see error(s) below"
+#~ msgstr ""
+#~ "Il y a eu une erreur lors de la sauvegarde, merci de regarder ci-dessous"
+
+#~ msgid "Create a new LGR"
+#~ msgstr "Créer une nouvelle LGR"
+
+#~ msgid "These LGRs are already created. Click on one to access it."
+#~ msgstr "Les LGRs suivantes sont déjà créées. Cliquez pour y accéder."
+
+#~ msgid "Create"
+#~ msgstr "Créer"
+
+#~ msgid "Existing references"
+#~ msgstr "Références existantes"
+
+#~ msgid "Reference id"
+#~ msgstr "Identifiant de référence"
+
+#~ msgid "URL"
+#~ msgstr "URL"
+
+#~ msgid "Delete reference"
+#~ msgstr "Supprimer la référence"
+
+#~ msgid "Are you sure you want delete this reference?"
+#~ msgstr "Êtes-vous sûr(e) de vouloir supprimer cette référence ?"
+
+#~ msgid "Classes"
+#~ msgstr "Classes"
+
+#~ msgid "The LGR has no class"
+#~ msgstr "La LGR n'a pas de classes"
+
+#~ msgid "The LGR has no rule"
+#~ msgstr "La LGR n'a pas de règles"
+
+#~ msgid "Actions"
+#~ msgstr "Actions"
+
+#~ msgid "The LGR has no action"
+#~ msgstr "La LGR n'a pas d'actions"
+
+#~ msgid "New class"
+#~ msgstr "Nouvelle classe"
+
+#~ msgid "New rule"
+#~ msgstr "Nouvelle règle"
+
+#~ msgid "New action"
+#~ msgstr "Nouvelle action"
+
+#~ msgid "Existing tags"
+#~ msgstr "Tags existants"
+
+#~ msgid "Tag name"
+#~ msgstr "Nom du tag"
+
+#~ msgid "Associated code points"
+#~ msgstr "Code points associés"
+
+#~ msgid "View all (%(nb_cp)s)"
+#~ msgstr "Voir tout (%(nb_cp)s)"
+
+#~ msgid "Delete Tag"
+#~ msgstr "Supprimer le tag"
+
+#~ msgid "Are you sure you want delete tag %(tag)s?"
+#~ msgstr "Êtes-vous sûr(e) de vouloir supprimer ce tag %(tag)s ?"
+
+#~ msgid ""
+#~ "To create a new tag:\n"
+#~ " Add it to a code point first to find it back in this list"
+#~ msgstr ""
+#~ "Pour créer un nouveau tag:\n"
+#~ " Ajouter le tag à un code point afin de le retrouver dans "
+#~ "cette list"
+
+#~ msgid "Erroneous conditional code points"
+#~ msgstr "Erreur dans les code points conditionels"
+
+#~ msgid ""
+#~ "Code point %(cp)s has invalid %(rule_type)s rule %(rule)s for variant "
+#~ "%(variant)s"
+#~ msgstr ""
+#~ "Le code point %(cp)s a la règle %(rule_type)s %(rule)s invalide pour les "
+#~ "variantes %(variant)s"
+
+#~ msgid "Conditional variants OK"
+#~ msgstr "Variantes conditionnelles OK"
+
+#~ msgid "Missing code points or rules"
+#~ msgstr "Code points ou règles manquants"
+
+#~ msgid "Code point %(cp)s:"
+#~ msgstr "Code point %(cp)s:"
+
+#~ msgid "Variant %(variant)s is not in repertoire"
+#~ msgstr "La variante %(variant)s n'est pas dans le répertoire"
+
+#~ msgid "%(variant)s has not original code point in its variants"
+#~ msgstr "%(variant)s n'a pas le code point original dans ses variantes"
+
+#~ msgid ""
+#~ "%(variant)s has not symmetric %(rule_type)s rule %(rule)s on its "
+#~ "symmetric variants"
+#~ msgstr ""
+#~ "%(variant)s n'a pas la règle %(rule_type)s %(rule)s dans ses variantes "
+#~ "symmétriques"
+
+#~ msgid "Symmetry OK"
+#~ msgstr "Symétrie OK"
+
+#~ msgid "Missing variants"
+#~ msgstr "Variantes manquantes"
+
+#~ msgid "Code point %(cp)s is missing variant %(variant)s"
+#~ msgstr "Le code point %(cp)s n'a pas la variante %(variant)s"
+
+#~ msgid "Transitivity OK"
+#~ msgstr "Transitivité OK"
+
+#~ msgid "XML is valid and complies with RNG."
+#~ msgstr "XML valide et conforme au RNG."
+
+#~ msgid "Invalid XML for lgr: %(res)s"
+#~ msgstr "Fichier XML invalide pour la LGR: %(res)s"
+
+#~ msgid "General stats"
+#~ msgstr "Statistiques générales"
+
+#~ msgid "Number of code points: %(nbr)s"
+#~ msgstr "Nombre de code points: %(nbr)s"
+
+#~ msgid "Number of ranges: %(nbr)s"
+#~ msgstr "Nombre d'intervalles: %(nbr)s"
+
+#~ msgid "Largest range: %(largest)s (length: %(largest_len)s)"
+#~ msgstr "Plus grand intervalle: %(largest)s (longueur: %(largest_len)s)"
+
+#~ msgid "Number of sequences: %(nbr)s"
+#~ msgstr "Nombre de séquences: %(nbr)s"
+
+#~ msgid "Largest sequence: %(largest)s (length: %(largest_len)s)"
+#~ msgstr "Plus grande séquence: %(largest)s (longueur: %(largest_len)s)"
+
+#~ msgid "Variants"
+#~ msgstr "Variante(s)"
+
+#~ msgid "Total number of variant mappings: %(nbr)s"
+#~ msgstr "Nombre total de variantes mappées: %(nbr)s"
+
+#~ msgid "Average number of variants per code point: %(nbr)s"
+#~ msgstr "Nombre moyen de variantes par code point: %(nbr)s"
+
+#~ msgid "Largest variant set: %(largest_set)s"
+#~ msgstr "Plus grand ensemble de variantes: %(largest_set)s"
+
+#~ msgid "Variants per type:"
+#~ msgstr "Variantes par type:"
+
+#~ msgid "Number of variants for type %(variant_type)s: %(number)s"
+#~ msgstr "Nombre de variantes pour le type %(variant_type)s: %(number)s"
+
+#~ msgid "Number of code points for tag %(tag_name)s: %(number)s"
+#~ msgstr "Nombre de code points pour le tag %(tag_name)s: %(number)s"
+
+#~ msgid "Number of defined rules: %(nbr)s"
+#~ msgstr "Nombre de règles définies: %(nbr)s"
+
+#~ msgid "Unicode version %(version)s"
+#~ msgstr "Version d'Unicode %(version)s"
+
+#~ msgid "Validating repertoire '%(repertoire)s'"
+#~ msgstr "Répertoire de validation '%(repertoire)s'"
+
+#~ msgid ""
+#~ "Target Unicode version %(version)s differs from UnicodeDatabase "
+#~ "%(database)s"
+#~ msgstr ""
+#~ "La version Unicode cible %(version)s diffère de UnicodeDatabase "
+#~ "%(database)s"
+
+#~ msgid "Invalid characters"
+#~ msgstr "Caractères invalides"
+
+#~ msgid "Invalid character %(cp)s:"
+#~ msgstr "Caractère invalide %(cp)s:"
+
+#~ msgid "Error: %(err)s"
+#~ msgstr "Erreur: %(err)s"
+
+#~ msgid "Variant: %(variant|render_char)s"
+#~ msgstr "Variante: %(variant|render_char)s"
+
+#~ msgid "LGR rebuild OK"
+#~ msgstr "Reconstruction de la LGR OK"
+
+#~ msgid ""
+#~ "The LGR you have tried to create already exists in your working session. "
+#~ "Please use a new name."
+#~ msgstr ""
+#~ "La LGR que vous essayez de créer existe déjà dans votre session de "
+#~ "travail. Merci d'utiliser un nouveau nom."
+
+#~ msgid ""
+#~ "The LGR you have tried to import already exists in your working session. "
+#~ "Please rename it before importing it."
+#~ msgstr ""
+#~ "La LGR que vous essayez d'importer existe déjà dans votre session de "
+#~ "travail. Merci de renommer le fichier avant de l'importer."
+
+#~ msgid ""
+#~ "The LGR you have tried to import already exists in your set. Please "
+#~ "rename it before importing it."
+#~ msgstr ""
+#~ "La LGR que vous essayez d'importer existe déjà dans votre ensemble. Merci "
+#~ "de renommer le fichier avant de l'importer."
+
+#~ msgid "The LGR set name already exists. Please use another name."
+#~ msgstr "Ce nom de set LGR existe déjà. Merci d'utiliser un autre nom."
+
+#~ msgid "Testing XML validity using RNG"
+#~ msgstr "Validation du XML par le RNG"
+
+#~ msgid "Testing symmetry"
+#~ msgstr "Test de la symmétrie"
+
+#~ msgid "Testing transitivity"
+#~ msgstr "Test de la transitivité"
+
+#~ msgid "Testing conditional variants"
+#~ msgstr "Test des variantes conditionnelles"
+
+#~ msgid "Generate stats"
+#~ msgstr "Génération des statistiques"
+
+#~ msgid "Rebuilding LGR"
+#~ msgstr "Reconstruction de la LGR"
+
+#~ msgid "New code point %s added"
+#~ msgstr "Nouveau code point ajouté %s"
+
+#~ msgid "Rule"
+#~ msgstr "Règle"
+
+#~ msgid "Tag(s)"
+#~ msgstr "Tag(s)"
+
+#~ msgid "rule"
+#~ msgstr "règle"
+
+#~ msgid "tag(s)"
+#~ msgstr "tag(s)"
+
+#~ msgid "%(operation)s successfully added to %(nb_cp)s code point(s)"
+#~ msgstr "%(operation)s ajouté(s) avec succès à %(nb_cp)s code point(s)"
+
+#~ msgid ""
+#~ "%(nb_cp)s code points were not updated to avoid invalid %(operation)s"
+#~ msgstr ""
+#~ "%(nb_cp)s code points n'ont pas été mis à jour pour éviter des "
+#~ "%(operation)s invalides"
+
+#~ msgid "Automatically added codepoint %s from out-of-repertoire variant"
+#~ msgstr ""
+#~ "Code point %s automatiquement ajouté depuis une variante hors-répertoire"
+
+#~ msgid "New variant %s added"
+#~ msgstr "Nouvelle variante %s ajoutée"
+
+#~ msgid "Code point edited"
+#~ msgstr "Code point modifié"
+
+#~ msgid "Variants populated"
+#~ msgstr "Les variantes ont été peuplées"
+
+#~ msgid "References updated successfully"
+#~ msgstr "Les références ont été correctement mises à jour"
+
+#~ msgid ""
+#~ "Variant %(var_codepoint)s for code point %(codepoint)s with when=%(when)s "
+#~ "and not-when=%(not_when)s could not be found"
+#~ msgstr ""
+#~ "La variante %(var_codepoint)s du code point %(codepoint)s avec when="
+#~ "%(when)s et not-when=%(not_when)s n'a pas été trouvée"
+
+#~ msgid "Code point %s has been deleted"
+#~ msgstr "Le code point %s a été supprimé"
+
+#~ msgid "Variant %(var_cp)s with when='%(when)s' and not-when='%(not_when)s'"
+#~ msgstr ""
+#~ "La variante %(var_cp)s avec when='%(when)s' and not-when='%(not_when)s'"
+
+#~ msgid "%(var_msg_prefix)s has been deleted"
+#~ msgstr "%(var_msg_prefix)s a été supprimée"
+
+#~ msgid "%(var_msg_prefix)s could not be deleted because it was not found"
+#~ msgstr ""
+#~ "%(var_msg_prefix)s n'a pas pu être supprimée car elle n'a pas été trouvée"
+
+#~ msgid "New reference created"
+#~ msgstr "Nouvelle référence créée"
+
+#~ msgid ""
+#~ "References to tag %(tag)s have been removed from the repertoire. Do not "
+#~ "forget to update any WLE that might reference it."
+#~ msgstr ""
+#~ "Les références au %(tag)s ont été supprimées du répertoire. N'oubliez pas "
+#~ "de mettre à jour les WLE qui pourraient les utiliser."
+
+#~ msgid "No body specified"
+#~ msgstr "Aucun contenu spécifié"
+
+#~ msgid "Class \"%s\" does not exist"
+#~ msgstr "La classe \"%s\" n'existe pas"
+
+#~ msgid "Class \"%s\" deleted."
+#~ msgstr "Classe \"%s\" supprimée."
+
+#~ msgid "No class element found"
+#~ msgstr "Aucune classe trouvée"
+
+#~ msgid "Name attribute must be present"
+#~ msgstr "L'attribut name est obligatoire"
+
+#~ msgid ""
+#~ "Encountered XML syntax error: %s (line number may be wrong, try "
+#~ "subtracting one from the reported line number)"
+#~ msgstr ""
+#~ "Erreur de syntaxe XML : %s (le numéro de ligne peut-être incorrect, "
+#~ "essayer de soustraire un au numéro reporté)"
+
+#~ msgid "Your XML is not valid"
+#~ msgstr "Votre XML n'est pas valide"
+
+#~ msgid "Class \"%s\" already exists"
+#~ msgstr "La classe \"%s\" existe déjà"
+
+#~ msgid "Class \"%s\" saved."
+#~ msgstr "Classe \"%s\" sauvegardée."
+
+#~ msgid "Rule \"%s\" does not exist"
+#~ msgstr "La règle \"%s\" n'existe pas"
+
+#~ msgid "Rule \"%s\" deleted."
+#~ msgstr "Règle \"%s\" supprimée."
+
+#~ msgid "No rule element found"
+#~ msgstr "Aucune règle trouvée"
+
+#~ msgid "Rule \"%s\" already exists"
+#~ msgstr "La règle \"%s\" existe déjà"
+
+#~ msgid "Rule \"%s\" saved."
+#~ msgstr "Règle \"%s\" sauvegardée."
+
+#~ msgid "Action \"%s\" does not exist"
+#~ msgstr "Action \"%s\" n'existe pas"
+
+#~ msgid "Action \"%s\" deleted."
+#~ msgstr "Action \"%s\" supprimée."
+
+#~ msgid "No action element found"
+#~ msgstr "Aucune action trouvée"
+
+#~ msgid "Action saved."
+#~ msgstr "Action sauvée."
+
+#~ msgid "%d code points added"
+#~ msgstr "%d code points ont été ajoutés"
+
+#~ msgid "No code point in input file"
+#~ msgstr "Le fichier d'entrée ne contient aucun code point"
+
+#~ msgid "Meta data saved"
+#~ msgstr "Metadonnées sauvegardées"
+
+#, fuzzy
+#~| msgid "Description"
+#~ msgid "%(description)s"
+#~ msgstr "Description"
+
+#~ msgid " with Unicode version {}"
+#~ msgstr " avec la version d'Unicode {}"
+
+#~ msgid " and validating repertoire '{}'"
+#~ msgstr " et le repertoire de validation '{}'"
+
+#~ msgid " "
+#~ msgstr " "
diff --git a/src/lgr_basic/templates/basic_mode.html b/src/lgr_basic/templates/basic_mode.html
new file mode 100644
index 00000000..f83318d9
--- /dev/null
+++ b/src/lgr_basic/templates/basic_mode.html
@@ -0,0 +1,549 @@
+
+{% load i18n static %}
+{% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %}
+
+
+
+
+ {% block html_title %}{% trans 'LGR Tool' %}{% endblock %}
+
+
+
+
+
+
+
+
+ {% block html_head_more %}{% endblock %}
+
+
+
+ {% for result in results %}
+ {% include "lgr_validator/_validated_results.html" with result=result lgr_id=lgr_id index=forloop.counter only %}
+ {% endfor %}
+
+
+ {% if storage %}
+
+ {% trans 'Your saved results' %}
+
{% trans 'The following files contains your tools computation results.' %}
+
+
+ {% trans 'Note that these files could be cleaned up regularly.' %}
+
+
+
+
+
+
+
+
+ {% block html_body_more %}{% endblock %}
+
+
+
+
+
+
+
diff --git a/src/lgr_basic/urls.py b/src/lgr_basic/urls.py
new file mode 100644
index 00000000..3ee5eeac
--- /dev/null
+++ b/src/lgr_basic/urls.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.conf.urls import url
+
+from lgr_basic.views import BasicModeView
+
+LGR_SLUG_FORMAT = r'(?P[\w\_\-\.]+)'
+
+urlpatterns = [
+ url(r'^$', BasicModeView.as_view(), name='lgr_basic_mode')
+]
diff --git a/src/lgr_basic/views.py b/src/lgr_basic/views.py
new file mode 100644
index 00000000..a3397095
--- /dev/null
+++ b/src/lgr_basic/views.py
@@ -0,0 +1,100 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+import six
+from django.conf import settings
+from django.contrib import messages
+from django.shortcuts import redirect
+from django.utils.translation import ugettext as _
+from django.views.generic import FormView
+
+from lgr.exceptions import LGRException
+from lgr.tools.utils import download_file, read_labels
+from lgr.utils import cp_to_ulabel
+from lgr_editor.api import LabelInfo, session_get_storage, LGRInfo, session_list_storage
+from lgr_editor.lgr_exceptions import lgr_exception_to_text
+from lgr_editor.repertoires import get_by_name
+from lgr_tools.tasks import annotate_task, basic_collision_task
+from lgr_validator.views import evaluate_label_from_info, NeedAsyncProcess
+from lgr_web.views import ADVANCED_INTERFACE_SESSION_KEY
+from .forms import ValidateLabelSimpleForm
+
+
+class BasicModeView(FormView):
+ form_class = ValidateLabelSimpleForm
+ template_name = 'basic_mode.html'
+
+ def get(self, request, *args, **kwargs):
+ # we want to stay in basic mode
+ request.session[ADVANCED_INTERFACE_SESSION_KEY] = False
+ return super(BasicModeView, self).get(request, *args, **kwargs)
+
+ def form_valid(self, form):
+ ctx = {}
+ results = []
+
+ email_address = form.cleaned_data['email']
+ labels_cp = form.cleaned_data['labels']
+ labels_file = form.cleaned_data.get('labels_file')
+ rz_lgr = form.cleaned_data['rz_lgr']
+ ctx['lgr_id'] = rz_lgr # needed to download results as csv
+ collisions = form.cleaned_data['collisions']
+ tlds = None
+ tld_json = {}
+ if collisions:
+ tlds = download_file(settings.ICANN_TLDS)[1].read().lower()
+ tld_json = LabelInfo.from_form('TLDs', tlds).to_dict()
+ lgr_info = LGRInfo(rz_lgr, lgr=get_by_name(rz_lgr, with_unidb=True))
+ lgr_info.update_xml()
+ lgr_json = lgr_info.to_dict()
+ storage_path = session_get_storage(self.request)
+
+ if labels_file:
+ labels_json = LabelInfo.from_form(labels_file.name, labels_file.read()).to_dict()
+ # data will be sent by email instead of on the ui
+ ctx['validation_to'] = email_address
+ if collisions:
+ basic_collision_task.delay(lgr_json, labels_json, tld_json, email_address, storage_path, True)
+ ctx['collision_to'] = email_address
+ else:
+ annotate_task.delay(lgr_json, labels_json, email_address, storage_path)
+
+ else:
+ labels_json = LabelInfo.from_list('labels', [cp_to_ulabel(l) for l in labels_cp]).to_dict()
+ check_collisions = None
+ if collisions:
+ if len(labels_cp) == 1:
+ # if only one label include collisions directly in result
+ data = tlds.decode('utf-8')
+ check_collisions = [l[0] for l in read_labels(six.StringIO(data))]
+ else:
+ basic_collision_task.delay(lgr_json, labels_json, tld_json, email_address, storage_path,
+ False)
+ ctx['collision_to'] = email_address
+
+ for label_cplist in labels_cp:
+ try:
+ results.append(evaluate_label_from_info(self.request, lgr_info, label_cplist, None, email_address,
+ check_collisions=check_collisions))
+ except UnicodeError as ex:
+ messages.add_message(self.request, messages.ERROR, lgr_exception_to_text(ex))
+ except NeedAsyncProcess:
+ messages.add_message(self.request, messages.INFO,
+ _('Input label generates too many variants to compute them all quickly. '
+ 'You need to enter your email address and will receive a notification once '
+ 'process is done'))
+ ctx['email_required'] = True
+ except LGRException as ex:
+ messages.add_message(self.request, messages.ERROR, lgr_exception_to_text(ex))
+ # redirect to myself to refresh display
+ return redirect('lgr_basic_mode')
+
+ return self.render_to_response(self.get_context_data(results=results, **ctx))
+
+ def get_context_data(self, **kwargs):
+ ctx = super(BasicModeView, self).get_context_data(**kwargs)
+ if 'results' in kwargs:
+ ctx['results'] = kwargs.pop('results')
+ ctx['storage'] = session_list_storage(self.request)
+ ctx.update(kwargs)
+ return ctx
diff --git a/src/lgr_editor/api.py b/src/lgr_editor/api.py
index 8a7e88db..d58b5b19 100644
--- a/src/lgr_editor/api.py
+++ b/src/lgr_editor/api.py
@@ -24,7 +24,7 @@
from .utils import (LGR_CACHE_TIMEOUT,
LGR_OBJECT_CACHE_KEY,
clean_repertoire_cache,
- make_lgr_session_key)
+ make_lgr_session_key, list_root_zones)
from .exceptions import LGRValidationException
from .repertoires import get_by_name
from . import unidb
@@ -45,9 +45,17 @@ def __init__(self, name, lgr=None, xml=None, validating_repertoire=None, lgr_set
self.lgr_set = lgr_set
self.set_labels_info = set_labels_info # List of labels defined for the LGR set, optional
- def update_xml(self, pretty_print=False):
+ def update_xml(self, pretty_print=False, validate=False):
# if something was changed in `lgr`, calling this will re-generate the xml
- self.xml = serialize_lgr_xml(self.lgr, pretty_print=pretty_print)
+ new_xml = serialize_lgr_xml(self.lgr, pretty_print=pretty_print)
+ if validate:
+ parser = XMLParser(six.BytesIO(new_xml), self.name)
+
+ validation_result = parser.validate_document(settings.LGR_RNG_FILE)
+ if validation_result is not None:
+ raise LGRValidationException(validation_result)
+
+ self.xml = new_xml
@classmethod
def create(cls, name, unicode_version, validating_repertoire_name):
@@ -205,6 +213,14 @@ def from_form(cls, name, label_input):
return cls(name, labels, b64data)
+ @classmethod
+ def from_list(cls, name, labels):
+ data = '\n'.join(labels)
+ labels = six.StringIO(data)
+ b64data = base64.b64encode(data.encode('utf-8')).decode('utf-8')
+
+ return cls(name, labels, b64data)
+
def to_dict(self):
return {
'name': self.name,
@@ -298,6 +314,7 @@ def session_open_lgr(request, lgr_id, lgr_xml,
def session_select_lgr(request, lgr_id, lgr_set_id=None):
"""
Find the LGR identified by `lgr_id` in the session.
+ Can also retrieve a root zone LGR.
:param request: Django request object
:param lgr_id: a slug identifying the LGR
@@ -306,6 +323,10 @@ def session_select_lgr(request, lgr_id, lgr_set_id=None):
"""
known_lgrs = request.session.get(LGRS_SESSION_KEY, {})
+ # handle RZ LGR selection
+ if lgr_id not in known_lgrs and lgr_id in list_root_zones():
+ return LGRInfo(lgr_id, lgr=get_by_name(lgr_id, with_unidb=True))
+
if lgr_set_id:
if lgr_set_id not in known_lgrs:
raise Http404
diff --git a/src/lgr_editor/forms/codepoints.py b/src/lgr_editor/forms/codepoints.py
index a2e8972e..247b49be 100644
--- a/src/lgr_editor/forms/codepoints.py
+++ b/src/lgr_editor/forms/codepoints.py
@@ -132,13 +132,13 @@ def clean(self):
cleaned_data = super(EditCodepointsForm, self).clean()
if self.post and 'add-rules' in self.post:
if cleaned_data['when'] and cleaned_data['not_when']:
- self.add_error('when', 'Cannot add when and not-when rules simultaneously')
- self.add_error('not_when', 'Cannot add when and not-when rules simultaneously')
+ self.add_error('when', _('Cannot add when and not-when rules simultaneously'))
+ self.add_error('not_when', _('Cannot add when and not-when rules simultaneously'))
elif not cleaned_data.get('when') and not cleaned_data.get('not_when'):
- self.add_error('when', 'Please provide at least one value')
- self.add_error('not_when', 'Please provide at least one value')
+ self.add_error('when', _('Please provide at least one value'))
+ self.add_error('not_when', _('Please provide at least one value'))
if self.post and 'add-tags' in self.post and not cleaned_data.get('tags'):
- self.add_error('tags', 'Please provide at least one value')
+ self.add_error('tags', _('Please provide at least one value'))
return cleaned_data
diff --git a/src/lgr_editor/forms/fields.py b/src/lgr_editor/forms/fields.py
index cc634d42..a2ca06ea 100644
--- a/src/lgr_editor/forms/fields.py
+++ b/src/lgr_editor/forms/fields.py
@@ -1,11 +1,15 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
+import re
from django.conf import settings
-from lgr_editor.utils import list_validating_repertoires
-
+from lgr_editor.utils import list_validating_repertoires, list_root_zones, parse_language_registry
UNICODE_VERSIONS = tuple((v, v) for v in settings.SUPPORTED_UNICODE_VERSIONS)
DEFAULT_UNICODE_VERSION = settings.SUPPORTED_UNICODE_VERSIONS[0]
VALIDATING_REPERTOIRES = tuple((v, v) for v in list_validating_repertoires())
DEFAULT_VALIDATING_REPERTOIRE = ''
+
+ROOT_ZONES = tuple((v, re.sub(r'lgr-([1-9]+)-.*', r'RZ-LGR version \1', v)) for v in sorted(list_root_zones()))
+
+IANA_LANG_REGISTRY = parse_language_registry()
diff --git a/src/lgr_editor/forms/importer.py b/src/lgr_editor/forms/importer.py
index 4458ab38..7f7a126e 100644
--- a/src/lgr_editor/forms/importer.py
+++ b/src/lgr_editor/forms/importer.py
@@ -38,5 +38,4 @@ class ImportLGRForm(forms.Form):
'This value may contain only letters, numbers '
'and ./-/_ characters.'), 'invalid'),
],
- help_text=_('The name of the set'),
- )
+ help_text=_('The name of the set'))
diff --git a/src/lgr_editor/forms/labels.py b/src/lgr_editor/forms/labels.py
index b8ed9e89..831ab9ce 100644
--- a/src/lgr_editor/forms/labels.py
+++ b/src/lgr_editor/forms/labels.py
@@ -3,11 +3,10 @@
from django import forms
from django.utils.translation import ugettext_lazy as _
-from django.utils.six import text_type
-
-from lgr_editor import unidb
from lgr.tools.utils import parse_label_input
+from lgr_editor import unidb
+from lgr_editor.lgr_exceptions import lgr_exception_to_text
class LabelFormsForm(forms.Form):
@@ -29,7 +28,7 @@ def clean(self):
try:
value = parse_label_input(label, idna_decoder=udata.idna_decode_label)
except ValueError as e:
- self.add_error('label', text_type(e))
+ self.add_error('label', lgr_exception_to_text(e))
else:
self.cleaned_data['label'] = value
return self.cleaned_data
diff --git a/src/lgr_editor/forms/metadata.py b/src/lgr_editor/forms/metadata.py
index 3fcc7f87..e433ace1 100644
--- a/src/lgr_editor/forms/metadata.py
+++ b/src/lgr_editor/forms/metadata.py
@@ -3,15 +3,16 @@
from datetime import date
-from django.utils import six
+from dal import autocomplete
from django import forms
from django.forms.formsets import formset_factory
+from django.utils import six
from django.utils.translation import ugettext_lazy as _
+from .fields import UNICODE_VERSIONS, DEFAULT_UNICODE_VERSION, VALIDATING_REPERTOIRES, DEFAULT_VALIDATING_REPERTOIRE, \
+ IANA_LANG_REGISTRY
from .utils import BaseDisableableFormSet
-from .fields import UNICODE_VERSIONS, DEFAULT_UNICODE_VERSION, VALIDATING_REPERTOIRES, DEFAULT_VALIDATING_REPERTOIRE
-
def DateInputPlaceHolder(placeholder=''):
"""
@@ -28,6 +29,7 @@ def TextInputPlaceHolder(placeholder):
"""
return forms.TextInput(attrs={'placeholder': placeholder})
+
DESCRIPTION_CONTENT_TYPES = (
('', ''),
('text/plain', 'text/plain'),
@@ -39,11 +41,14 @@ class MetadataForm(forms.Form):
version = forms.CharField(label=_("Version"), max_length=255, required=False)
version_comment = forms.CharField(label=_("Version comment"), required=False)
date = forms.DateField(label=_("Date"), widget=DateInputPlaceHolder(date.today().isoformat()), required=False)
- scope = forms.CharField(label=_("Scope"), max_length=255, required=False, widget=TextInputPlaceHolder('example')) # XXX: we may need to support multiple scope elements
- scope_type = forms.CharField(label=_("Scope type"), max_length=255, required=False, widget=TextInputPlaceHolder('domain'))
+ scope = forms.CharField(label=_("Scope"), max_length=255, required=False, widget=TextInputPlaceHolder(
+ 'example')) # XXX: we may need to support multiple scope elements
+ scope_type = forms.CharField(label=_("Scope type"), max_length=255, required=False,
+ widget=TextInputPlaceHolder('domain'))
validity_start = forms.DateField(label=_("Validity start"), widget=DateInputPlaceHolder(), required=False)
validity_end = forms.DateField(label=_("Validity end"), widget=DateInputPlaceHolder(), required=False)
- unicode_version = forms.ChoiceField(label=_("Unicode version"), choices=UNICODE_VERSIONS, initial=DEFAULT_UNICODE_VERSION, required=False)
+ unicode_version = forms.ChoiceField(label=_("Unicode version"), choices=UNICODE_VERSIONS,
+ initial=DEFAULT_UNICODE_VERSION, required=False)
description = forms.CharField(label=_("Description"), widget=forms.Textarea, required=False)
description_type = forms.ChoiceField(label=_("Description type"), choices=DESCRIPTION_CONTENT_TYPES, required=False)
@@ -72,7 +77,9 @@ def __init__(self, *args, **kwargs):
class LanguageForm(forms.Form):
# validate using language_tags function
- language = forms.CharField(label=_("Language"), max_length=50, required=False) # https://tools.ietf.org/html/rfc5646#section-4.4
+ language = autocomplete.Select2ListChoiceField(label=_("Language"), choice_list=[''] + sorted(IANA_LANG_REGISTRY),
+ widget=autocomplete.ListSelect2(url='language-autocomplete'),
+ initial='', required=False)
LanguageFormSet = formset_factory(LanguageForm,
diff --git a/src/lgr_editor/forms/references.py b/src/lgr_editor/forms/references.py
index ad3361c3..3450bf25 100644
--- a/src/lgr_editor/forms/references.py
+++ b/src/lgr_editor/forms/references.py
@@ -5,6 +5,7 @@
from django import forms
from django.forms.formsets import formset_factory
+from django.utils.translation import ugettext_lazy as _
from lgr.metadata import ReferenceManager
from .utils import BaseDisableableFormSet, ReadOnlyTextInput
@@ -29,7 +30,7 @@ def __init__(self, *args, **kwargs):
def clean(self):
cleaned_data = super(ReferenceForm, self).clean()
if cleaned_data['ref_id'] and not re.match(ReferenceManager.REFERENCE_REGEX, str(cleaned_data['ref_id'])):
- self.add_error('ref_id', 'Invalid format')
+ self.add_error('ref_id', _('Invalid format'))
return cleaned_data
diff --git a/src/lgr_editor/lgr_exceptions.py b/src/lgr_editor/lgr_exceptions.py
index dfee98f4..612f1a70 100644
--- a/src/lgr_editor/lgr_exceptions.py
+++ b/src/lgr_editor/lgr_exceptions.py
@@ -3,10 +3,13 @@
lgr_exceptions.py - Map LGR exception to user terms.
"""
from __future__ import unicode_literals
+
+from django.utils.translation import ugettext
from django.utils.translation import ugettext_lazy as _
import lgr.exceptions
from lgr.utils import format_cp
+from picu.exceptions import IDNAException
from .exceptions import LGRValidationException
@@ -28,14 +31,14 @@ def lgr_exception_to_text(exception):
elif isinstance(exception, lgr.exceptions.NotInRepertoire):
message = _('Input code point %(codepoint)s is not in '
'the reference repertoire') % {
- 'codepoint': format_cp(exception.cp)
- }
+ 'codepoint': format_cp(exception.cp)
+ }
elif isinstance(exception, lgr.exceptions.VariantAlreadyExists):
message = _('Variant %(variant_codepoint)s already exists for '
'code point %(codepoint)s') % {
- 'variant_codepoint': format_cp(exception.variant),
- 'codepoint': format_cp(exception.cp)
- }
+ 'variant_codepoint': format_cp(exception.variant),
+ 'codepoint': format_cp(exception.cp)
+ }
elif isinstance(exception, lgr.exceptions.RangeAlreadyExists):
message = _('Range %(first_cp)s - %(last_cp)s already exists in the LGR') % {
'first_cp': format_cp(exception.first_cp),
@@ -44,8 +47,8 @@ def lgr_exception_to_text(exception):
elif isinstance(exception, lgr.exceptions.CharAlreadyExists):
message = _('Input code point %(codepoint)s already exists '
'in the LGR') % {
- 'codepoint': format_cp(exception.cp)
- }
+ 'codepoint': format_cp(exception.cp)
+ }
elif isinstance(exception, lgr.exceptions.CharNotInScript):
message = _('Input code point %(codepoint)s is not in LGR script') % {
'codepoint': format_cp(exception.cp)
@@ -53,8 +56,8 @@ def lgr_exception_to_text(exception):
elif isinstance(exception, lgr.exceptions.CharInvalidIdnaProperty):
message = _('Input code point %(codepoint)s is not a '
'PVALID/CONTEXTO/CONTEXTJ code point per IDNA2008') % {
- 'codepoint': format_cp(exception.cp)
- }
+ 'codepoint': format_cp(exception.cp)
+ }
elif isinstance(exception, lgr.exceptions.CharInvalidContextRule):
message = _('Code point %(codepoint)s has invalid context rule %(rule)s') % {
'codepoint': format_cp(exception.cp),
@@ -68,9 +71,9 @@ def lgr_exception_to_text(exception):
elif isinstance(exception, lgr.exceptions.VariantInvalidContextRule):
message = _('Variant %(variant_codepoint)s of code point %(codepoint)s'
'has invalid context rule') % {
- 'variant_codepoint': format_cp(exception.variant),
- 'codepoint': format_cp(exception.cp)
- }
+ 'variant_codepoint': format_cp(exception.variant),
+ 'codepoint': format_cp(exception.cp)
+ }
elif isinstance(exception, lgr.exceptions.DuplicateReference):
message = _('Duplicate reference for code point %(codepoint)s') % {
'codepoint': format_cp(exception.cp)
@@ -78,8 +81,8 @@ def lgr_exception_to_text(exception):
elif isinstance(exception, lgr.exceptions.CharLGRException):
message = _('Unspecified exception for input code point '
'%(codepoint)s') % {
- 'codepoint': format_cp(exception.cp)
- }
+ 'codepoint': format_cp(exception.cp)
+ }
elif isinstance(exception, lgr.exceptions.LGRFormatException):
reason = exception.reason
if reason == lgr.exceptions.LGRFormatException.LGRFormatReason.SEQUENCE_NO_TAG:
@@ -127,8 +130,79 @@ def lgr_exception_to_text(exception):
'relations')
elif isinstance(exception, lgr.exceptions.MissingLanguage):
message = _('The LGR does not contain a valid language (%(message)s)' % {'message': exception.message})
+ elif isinstance(exception, lgr.exceptions.LGRCrossScriptMissingDataException):
+ message = _('Cannot generate cross-script variant for LGR without (%(message)s)' % {
+ 'message': exception.missing_part
+ })
elif isinstance(exception, lgr.exceptions.LGRException):
message = _('An unknown exception occurred in the LGR API')
+ elif isinstance(exception, IDNAException):
+ messages = []
+ for error in exception.error_labels:
+ if error == 'UIDNA_ERROR_EMPTY_LABEL':
+ messages.append(ugettext('Label is empty'))
+ elif error == 'UIDNA_ERROR_LABEL_TOO_LONG':
+ messages.append(ugettext('%(label)s is invalid due to its length being longer than 63 bytes.') % {
+ 'label': exception.obj
+ })
+ # elif error == 'UIDNA_ERROR_DOMAIN_NAME_TOO_LONG':
+ elif error == 'UIDNA_ERROR_LEADING_HYPHEN':
+ messages.append(ugettext('%(label)s is invalid due to hypen restrictions in the RFC5891 as it starts '
+ 'with a hyphen-minus.' % {
+ 'label': exception.obj
+ }))
+ elif error == 'UIDNA_ERROR_TRAILING_HYPHEN':
+ messages.append(ugettext('%(label)s is invalid due to hyphen restrictions in the RFC5891 as it ends '
+ 'with a hyphen-minus.' % {
+ 'label': exception.obj
+ }))
+ elif error == 'UIDNA_ERROR_HYPHEN_3_4':
+ messages.append(ugettext('%(label)s is invalid due to hyphen restrictions in the RFC5891 as it '
+ 'contains hyphen-minus in the third and fourth positions.' % {
+ 'label': exception.obj
+ }))
+ elif error == 'UIDNA_ERROR_LEADING_COMBINING_MARK':
+ messages.append(ugettext('%(label)s is invalid due to leading combining marks restriction in the '
+ 'RFC5891.' % {
+ 'label': exception.obj
+ }))
+ elif error == 'UIDNA_ERROR_DISALLOWED':
+ messages.append(ugettext('%(label)s is invalid as it contains disallowed characters.' % {
+ 'label': exception.obj
+ }))
+ elif error == 'UIDNA_ERROR_PUNYCODE':
+ messages.append(ugettext('%(label)s is invalid as it starts with ‘xn--’ but does not contain valid '
+ 'Punycode.' % {
+ 'label': exception.obj
+ }))
+ elif error == 'UIDNA_ERROR_LABEL_HAS_DOT':
+ messages.append(ugettext('%(label)s is invalid as it contains full stop (dot).' % {
+ 'label': exception.obj
+ }))
+ elif error == 'UIDNA_ERROR_INVALID_ACE_LABEL':
+ messages.append(ugettext('%(label)s is invalid due to invalid Punycode.' % {'label': exception.obj}))
+ elif error == 'UIDNA_ERROR_BIDI':
+ messages.append(ugettext('%(label)s is invalid due to the Bidi rule in the RFC5893.' % {
+ 'label': exception.obj
+ }))
+ elif error == 'UIDNA_ERROR_CONTEXTJ':
+ messages.append(ugettext('%(label)s is invalid due to the IDNA contextual rule for Zero Width '
+ 'Joiner.' % {
+ 'label': exception.obj
+ }))
+ elif error == 'UIDNA_ERROR_CONTEXTO_PUNCTUATION':
+ messages.append(ugettext('%(label)s is invalid due to the IDNA contextual rule for punctuation in '
+ 'the RFC5892.' % {
+ 'label': exception.obj
+ }))
+ elif error == 'UIDNA_ERROR_CONTEXTO_DIGITS':
+ messages.append(ugettext('%(label)s is invalid due to the IDNA contextual rule for digits in the '
+ 'RFC5892.' % {
+ 'label': exception.obj
+ }))
+ else:
+ messages.append(exception)
+ message = '\n'.join(messages)
else:
message = '%s' % exception
diff --git a/src/lgr_editor/locale/ar/LC_MESSAGES/django.mo b/src/lgr_editor/locale/ar/LC_MESSAGES/django.mo
index cfa97df1..74dbaf67 100644
Binary files a/src/lgr_editor/locale/ar/LC_MESSAGES/django.mo and b/src/lgr_editor/locale/ar/LC_MESSAGES/django.mo differ
diff --git a/src/lgr_editor/locale/ar/LC_MESSAGES/django.po b/src/lgr_editor/locale/ar/LC_MESSAGES/django.po
index 6e5c0e27..9ee52dc8 100644
--- a/src/lgr_editor/locale/ar/LC_MESSAGES/django.po
+++ b/src/lgr_editor/locale/ar/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-09-04 16:04+0000\n"
+"POT-Creation-Date: 2020-12-02 03:08+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -29,6 +29,7 @@ msgstr ""
#: forms/codepoint.py:16 templates/lgr_editor/_editor_base.html:31
#: templates/lgr_editor/codepoint_list.html:40
+#: templates/lgr_editor/validate_lgr/compute_stats.html:71
msgid "Tags"
msgstr ""
@@ -72,7 +73,7 @@ msgid ""
msgstr ""
#: forms/codepoints.py:78 forms/importer.py:14 forms/importer.py:27
-#: forms/metadata.py:50
+#: forms/metadata.py:55
msgid "Validating repertoire"
msgstr ""
@@ -98,6 +99,14 @@ msgstr ""
msgid "File type"
msgstr ""
+#: forms/codepoints.py:135 forms/codepoints.py:136
+msgid "Cannot add when and not-when rules simultaneously"
+msgstr ""
+
+#: forms/codepoints.py:138 forms/codepoints.py:139 forms/codepoints.py:142
+msgid "Please provide at least one value"
+msgstr ""
+
#: forms/importer.py:13
msgid "Name"
msgstr ""
@@ -124,208 +133,301 @@ msgstr ""
msgid "The name of the set"
msgstr ""
-#: forms/labels.py:14
+#: forms/labels.py:13
msgid "Label"
msgstr ""
-#: forms/labels.py:15 forms/metadata.py:46
+#: forms/labels.py:14 forms/metadata.py:50
msgid "Unicode version"
msgstr ""
-#: forms/labels.py:17
+#: forms/labels.py:16
msgid "The unicode version used"
msgstr ""
-#: forms/metadata.py:39
+#: forms/metadata.py:41
msgid "Version"
msgstr ""
-#: forms/metadata.py:40
+#: forms/metadata.py:42
msgid "Version comment"
msgstr ""
-#: forms/metadata.py:41
+#: forms/metadata.py:43
msgid "Date"
msgstr ""
-#: forms/metadata.py:42
+#: forms/metadata.py:44
msgid "Scope"
msgstr ""
-#: forms/metadata.py:43
+#: forms/metadata.py:46
msgid "Scope type"
msgstr ""
-#: forms/metadata.py:44
+#: forms/metadata.py:48
msgid "Validity start"
msgstr ""
-#: forms/metadata.py:45
+#: forms/metadata.py:49
msgid "Validity end"
msgstr ""
-#: forms/metadata.py:47 templates/lgr_editor/codepoint_view.html:227
+#: forms/metadata.py:52 templates/lgr_editor/codepoint_view.html:227
#: templates/lgr_editor/references.html:14
#: templates/lgr_editor/references.html:51
msgid "Description"
msgstr ""
-#: forms/metadata.py:48
+#: forms/metadata.py:53
msgid "Description type"
msgstr ""
-#: forms/metadata.py:53
+#: forms/metadata.py:58
msgid "Built-in"
msgstr ""
-#: forms/metadata.py:65
+#: forms/metadata.py:70
msgid "My LGRs"
msgstr ""
-#: forms/metadata.py:75
+#: forms/metadata.py:80
msgid "Language"
msgstr ""
-#: lgr_exceptions.py:25
+#: forms/references.py:33
+msgid "Invalid format"
+msgstr ""
+
+#: lgr_exceptions.py:28
#, python-format
msgid "Input code point %(codepoint)s is not in the LGR"
msgstr ""
-#: lgr_exceptions.py:29
+#: lgr_exceptions.py:32
#, python-format
msgid "Input code point %(codepoint)s is not in the reference repertoire"
msgstr ""
-#: lgr_exceptions.py:34
+#: lgr_exceptions.py:37
#, python-format
msgid ""
"Variant %(variant_codepoint)s already exists for code point %(codepoint)s"
msgstr ""
-#: lgr_exceptions.py:40
+#: lgr_exceptions.py:43
#, python-format
msgid "Range %(first_cp)s - %(last_cp)s already exists in the LGR"
msgstr ""
-#: lgr_exceptions.py:45
+#: lgr_exceptions.py:48
#, python-format
msgid "Input code point %(codepoint)s already exists in the LGR"
msgstr ""
-#: lgr_exceptions.py:50
+#: lgr_exceptions.py:53
#, python-format
msgid "Input code point %(codepoint)s is not in LGR script"
msgstr ""
-#: lgr_exceptions.py:54
+#: lgr_exceptions.py:57
#, python-format
msgid ""
"Input code point %(codepoint)s is not a PVALID/CONTEXTO/CONTEXTJ code point "
"per IDNA2008"
msgstr ""
-#: lgr_exceptions.py:59
+#: lgr_exceptions.py:62
#, python-format
msgid "Code point %(codepoint)s has invalid context rule %(rule)s"
msgstr ""
-#: lgr_exceptions.py:64
+#: lgr_exceptions.py:67
#, python-format
msgid "Range %(first_cp)s - %(last_cp)s has invalid context rule"
msgstr ""
-#: lgr_exceptions.py:69
+#: lgr_exceptions.py:72
#, python-format
msgid ""
"Variant %(variant_codepoint)s of code point %(codepoint)shas invalid context "
"rule"
msgstr ""
-#: lgr_exceptions.py:75
+#: lgr_exceptions.py:78
#, python-format
msgid "Duplicate reference for code point %(codepoint)s"
msgstr ""
-#: lgr_exceptions.py:79
+#: lgr_exceptions.py:82
#, python-format
msgid "Unspecified exception for input code point %(codepoint)s"
msgstr ""
-#: lgr_exceptions.py:86
+#: lgr_exceptions.py:89
msgid "Sequence cannot have a tag"
msgstr ""
-#: lgr_exceptions.py:88
+#: lgr_exceptions.py:91
msgid "Invalid language"
msgstr ""
-#: lgr_exceptions.py:90
+#: lgr_exceptions.py:93
msgid "Invalid date value"
msgstr ""
-#: lgr_exceptions.py:92
+#: lgr_exceptions.py:95
msgid "Invalid Unicode version"
msgstr ""
-#: lgr_exceptions.py:94
+#: lgr_exceptions.py:97
msgid "Invalid LGR XML file"
msgstr ""
-#: lgr_exceptions.py:96
+#: lgr_exceptions.py:99
#, python-format
msgid "Reference %(ref_id)s is not defined"
msgstr ""
-#: lgr_exceptions.py:100
+#: lgr_exceptions.py:103
#, python-format
msgid "Reference %(ref_id)s already exists"
msgstr ""
-#: lgr_exceptions.py:104
+#: lgr_exceptions.py:107
#, python-format
msgid "Invalid reference id %(ref_id)s "
msgstr ""
-#: lgr_exceptions.py:108
+#: lgr_exceptions.py:111
#, python-format
msgid "Rule \"%(rule_name)s\" cannot be processed (%(message)s)"
msgstr ""
-#: lgr_exceptions.py:113
+#: lgr_exceptions.py:116
msgid "Input parameter has invalid format"
msgstr ""
-#: lgr_exceptions.py:115
+#: lgr_exceptions.py:118
msgid "A general exception occurred in the LGR API"
msgstr ""
-#: lgr_exceptions.py:117
+#: lgr_exceptions.py:120
#, python-format
msgid "LGR is not valid (%(args)s)"
msgstr ""
-#: lgr_exceptions.py:119
+#: lgr_exceptions.py:122
#, python-format
msgid "Label %(label)s is not valid in the LGR (%(message)s)"
msgstr ""
-#: lgr_exceptions.py:124
+#: lgr_exceptions.py:127
msgid "Input label file contains collision(s)"
msgstr ""
-#: lgr_exceptions.py:126
+#: lgr_exceptions.py:129
msgid "The LGR contains a variant that do not have symmetric relations"
msgstr ""
-#: lgr_exceptions.py:129
+#: lgr_exceptions.py:132
#, python-format
msgid "The LGR does not contain a valid language (%(message)s)"
msgstr ""
-#: lgr_exceptions.py:131
+#: lgr_exceptions.py:134
+#, python-format
+msgid "Cannot generate cross-script variant for LGR without (%(message)s)"
+msgstr ""
+
+#: lgr_exceptions.py:138
msgid "An unknown exception occurred in the LGR API"
msgstr ""
+#: lgr_exceptions.py:143
+msgid "Label is empty"
+msgstr ""
+
+#: lgr_exceptions.py:145
+#, python-format
+msgid "%(label)s is invalid due to its length being longer than 63 bytes."
+msgstr ""
+
+#: lgr_exceptions.py:150
+#, python-format
+msgid ""
+"%(label)s is invalid due to hypen restrictions in the RFC5891 as it starts "
+"with a hyphen-minus."
+msgstr ""
+
+#: lgr_exceptions.py:155
+#, python-format
+msgid ""
+"%(label)s is invalid due to hyphen restrictions in the RFC5891 as it ends "
+"with a hyphen-minus."
+msgstr ""
+
+#: lgr_exceptions.py:160
+#, python-format
+msgid ""
+"%(label)s is invalid due to hyphen restrictions in the RFC5891 as it "
+"contains hyphen-minus in the third and fourth positions."
+msgstr ""
+
+#: lgr_exceptions.py:165
+#, python-format
+msgid ""
+"%(label)s is invalid due to leading combining marks restriction in the "
+"RFC5891."
+msgstr ""
+
+#: lgr_exceptions.py:170
+#, python-format
+msgid "%(label)s is invalid as it contains disallowed characters."
+msgstr ""
+
+#: lgr_exceptions.py:174
+#, python-format
+msgid ""
+"%(label)s is invalid as it starts with ‘xn--’ but does not contain valid "
+"Punycode."
+msgstr ""
+
+#: lgr_exceptions.py:179
+#, python-format
+msgid "%(label)s is invalid as it contains full stop (dot)."
+msgstr ""
+
+#: lgr_exceptions.py:183
+#, python-format
+msgid "%(label)s is invalid due to invalid Punycode."
+msgstr ""
+
+#: lgr_exceptions.py:185
+#, python-format
+msgid "%(label)s is invalid due to the Bidi rule in the RFC5893."
+msgstr ""
+
+#: lgr_exceptions.py:189
+#, python-format
+msgid ""
+"%(label)s is invalid due to the IDNA contextual rule for Zero Width Joiner."
+msgstr ""
+
+#: lgr_exceptions.py:194
+#, python-format
+msgid ""
+"%(label)s is invalid due to the IDNA contextual rule for punctuation in the "
+"RFC5892."
+msgstr ""
+
+#: lgr_exceptions.py:199
+#, python-format
+msgid ""
+"%(label)s is invalid due to the IDNA contextual rule for digits in the "
+"RFC5892."
+msgstr ""
+
#: templates/lgr_editor/_editor_base.html:25
#: templates/lgr_editor/codepoint_view.html:54
msgid "References"
@@ -337,6 +439,7 @@ msgstr ""
#: templates/lgr_editor/_editor_base.html:34 templates/lgr_editor/rules.html:18
#: templates/lgr_editor/rules_edit.html:57
+#: templates/lgr_editor/validate_lgr/compute_stats.html:79
msgid "Rules"
msgstr ""
@@ -356,7 +459,7 @@ msgstr ""
#: templates/lgr_editor/_rule_editor_widgets.html:5
#: templates/lgr_editor/codepoint_view.html:244
-#: templates/lgr_editor/metadata.html:32
+#: templates/lgr_editor/metadata.html:45
#: templates/lgr_editor/rules_edit.html:40
#: templates/lgr_editor/rules_edit.html:71
#: templates/lgr_editor/rules_edit.html:103
@@ -364,7 +467,7 @@ msgid "Cancel"
msgstr ""
#: templates/lgr_editor/_rule_editor_widgets.html:8
-#: templates/lgr_editor/metadata.html:33
+#: templates/lgr_editor/metadata.html:46
#: templates/lgr_editor/references.html:39
#: templates/lgr_editor/rules_edit.html:43
#: templates/lgr_editor/rules_edit.html:74
@@ -444,7 +547,6 @@ msgid "Action"
msgstr ""
#: templates/lgr_editor/codepoint_list.html:52
-#: templates/lgr_editor/codepoint_list.html:82
msgid "Add Rule"
msgstr ""
@@ -464,6 +566,11 @@ msgid ""
" "
msgstr ""
+#: templates/lgr_editor/codepoint_list.html:82
+#: templates/lgr_editor/codepoint_list.html:275
+msgid "Add Tags"
+msgstr ""
+
#: templates/lgr_editor/codepoint_list.html:87
msgid ""
"\n"
@@ -509,10 +616,6 @@ msgstr ""
msgid "Add WLE"
msgstr ""
-#: templates/lgr_editor/codepoint_list.html:275
-msgid "Add Tags"
-msgstr ""
-
#: templates/lgr_editor/codepoint_list.html:295
msgid "➡ Apply batch action..."
msgstr ""
@@ -658,23 +761,23 @@ msgstr ""
msgid "Cannot import LGR file(s):"
msgstr ""
-#: templates/lgr_editor/label_forms.html:11
+#: templates/lgr_editor/label_forms.html:10
msgid "Display forms"
msgstr ""
-#: templates/lgr_editor/label_forms.html:18
+#: templates/lgr_editor/label_forms.html:16
msgid "Code point sequence"
msgstr ""
-#: templates/lgr_editor/label_forms.html:19
+#: templates/lgr_editor/label_forms.html:17
msgid "U-label"
msgstr ""
-#: templates/lgr_editor/label_forms.html:20
+#: templates/lgr_editor/label_forms.html:18
msgid "A-label"
msgstr ""
-#: templates/lgr_editor/metadata.html:11
+#: templates/lgr_editor/metadata.html:23
msgid "There was an error saving; please see error(s) below"
msgstr ""
@@ -776,215 +879,423 @@ msgid ""
" Add it to a code point first to find it back in this list"
msgstr ""
-#: views.py:114
+#: templates/lgr_editor/validate_lgr/check_conditional_variants.html:7
+msgid "Erroneous conditional code points"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_conditional_variants.html:11
+#, python-format
+msgid ""
+"Code point %(cp)s has invalid %(rule_type)s rule %(rule)s for variant "
+"%(variant)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_conditional_variants.html:18
+msgid "Conditional variants OK"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:7
+msgid "Missing code points or rules"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:11
+#, python-format
+msgid "Code point %(cp)s:"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:15
+#, python-format
+msgid "Variant %(variant)s is not in repertoire"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:19
+#, python-format
+msgid "%(variant)s has not original code point in its variants"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:23
+#, python-format
+msgid ""
+"%(variant)s has not symmetric %(rule_type)s rule %(rule)s on its symmetric "
+"variants"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:27
+#, python-format
+msgid "%(variant)s unknown symmetry problem, please report"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:35
+msgid "Symmetry OK"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_transitivity.html:7
+msgid "Missing variants"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_transitivity.html:11
+#, python-format
+msgid "Code point %(cp)s is missing variant %(variant)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_transitivity.html:18
+msgid "Transitivity OK"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_xml_validity.html:7
+msgid "XML is valid and complies with RNG."
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_xml_validity.html:9
+#, python-format
+msgid "Invalid XML for lgr: %(res)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:6
+msgid "General stats"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:9
+#, python-format
+msgid "Number of code points: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:15
+#, python-format
+msgid "Number of ranges: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:21
+#, python-format
+msgid "Largest range: %(largest)s (length: %(largest_len)s)"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:28
+#, python-format
+msgid "Number of sequences: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:34
+#, python-format
+msgid "Largest sequence: %(largest)s (length: %(largest_len)s)"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:41
+msgid "Variants"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:44
+#, python-format
+msgid "Total number of variant mappings: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:49
+#, python-format
+msgid "Average number of variants per code point: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:54
+#, python-format
+msgid "Largest variant set: %(largest_set)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:60
+msgid "Variants per type:"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:63
+#, python-format
+msgid "Number of variants for type %(variant_type)s: %(number)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:74
+#, python-format
+msgid "Number of code points for tag %(tag_name)s: %(number)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:82
+#, python-format
+msgid "Number of defined rules: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:6
+#, python-format
+msgid "Unicode version %(version)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:8
+#, python-format
+msgid "Validating repertoire '%(repertoire)s'"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:13
+#, python-format
+msgid ""
+"Target Unicode version %(version)s differs from UnicodeDatabase %(database)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:19
+msgid "Possibly erroneous characters"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:23
+#, python-format
+msgid "Character %(cp)s:"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:29
+#, python-format
+msgid "Warning: %(warn)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:36
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:49
+#, python-format
+msgid "Error: %(err)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:43
+#, python-format
+msgid "Variant: %(variant|render_char)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:60
+msgid "LGR rebuild OK"
+msgstr ""
+
+#: views.py:115
msgid ""
"The LGR you have tried to create already exists in your working session. "
"Please use a new name."
msgstr ""
-#: views.py:148
+#: views.py:149
msgid ""
"The LGR you have tried to import already exists in your working session. "
"Please rename it before importing it."
msgstr ""
-#: views.py:154
+#: views.py:155
msgid ""
"The LGR you have tried to import already exists in your set. Please rename "
"it before importing it."
msgstr ""
-#: views.py:177
+#: views.py:178
msgid "The LGR set name already exists. Please use another name."
msgstr ""
-#: views.py:289
+#: views.py:249
+msgid "Testing XML validity using RNG"
+msgstr ""
+
+#: views.py:250
+msgid "Testing symmetry"
+msgstr ""
+
+#: views.py:251
+msgid "Testing transitivity"
+msgstr ""
+
+#: views.py:252
+msgid "Testing conditional variants"
+msgstr ""
+
+#: views.py:253
+msgid "Generate stats"
+msgstr ""
+
+#: views.py:254
+msgid "Rebuilding LGR"
+msgstr ""
+
+#: views.py:302
#, python-format
msgid "New code point %s added"
msgstr ""
-#: views.py:362
+#: views.py:375
msgid "Rule"
msgstr ""
-#: views.py:362
+#: views.py:375
msgid "Tag(s)"
msgstr ""
-#: views.py:363
+#: views.py:376
msgid "rule"
msgstr ""
-#: views.py:363
+#: views.py:376
msgid "tag(s)"
msgstr ""
-#: views.py:367
+#: views.py:380
#, python-format
msgid "%(operation)s successfully added to %(nb_cp)s code point(s)"
msgstr ""
-#: views.py:372
+#: views.py:385
#, python-format
msgid "%(nb_cp)s code points were not updated to avoid invalid %(operation)s"
msgstr ""
-#: views.py:504
+#: views.py:517
#, python-format
-msgid "Automatically added codepoint %s from out-of-repertoire variant"
+msgid "Automatically added codepoint %s from out-of-repertoire-var variant"
msgstr ""
-#: views.py:507
+#: views.py:520
#, python-format
msgid "New variant %s added"
msgstr ""
-#: views.py:580
+#: views.py:593
msgid "Code point edited"
msgstr ""
-#: views.py:732
+#: views.py:745
msgid "Variants populated"
msgstr ""
-#: views.py:783 views.py:819
+#: views.py:798 views.py:834
msgid "References updated successfully"
msgstr ""
-#: views.py:822
+#: views.py:837
#, python-format
msgid ""
"Variant %(var_codepoint)s for code point %(codepoint)s with when=%(when)s "
"and not-when=%(not_when)s could not be found"
msgstr ""
-#: views.py:858
+#: views.py:873
#, python-format
msgid "Code point %s has been deleted"
msgstr ""
-#: views.py:880
+#: views.py:895
#, python-format
msgid "Variant %(var_cp)s with when='%(when)s' and not-when='%(not_when)s'"
msgstr ""
-#: views.py:886
+#: views.py:901
#, python-format
msgid "%(var_msg_prefix)s has been deleted"
msgstr ""
-#: views.py:889
+#: views.py:904
#, python-format
msgid "%(var_msg_prefix)s could not be deleted because it was not found"
msgstr ""
-#: views.py:919
+#: views.py:934
msgid "New reference created"
msgstr ""
-#: views.py:1127
+#: views.py:1142
#, python-format
msgid ""
"References to tag %(tag)s have been removed from the repertoire. Do not "
"forget to update any WLE that might reference it."
msgstr ""
-#: views.py:1195 views.py:1357 views.py:1441
+#: views.py:1210 views.py:1372 views.py:1460
msgid "No body specified"
msgstr ""
-#: views.py:1204
+#: views.py:1219
#, python-format
msgid "Class \"%s\" does not exist"
msgstr ""
-#: views.py:1208
+#: views.py:1223
#, python-format
msgid "Class \"%s\" deleted."
msgstr ""
-#: views.py:1213
+#: views.py:1228
msgid "No class element found"
msgstr ""
-#: views.py:1215 views.py:1377
+#: views.py:1230 views.py:1392
msgid "Name attribute must be present"
msgstr ""
-#: views.py:1219 views.py:1236 views.py:1381 views.py:1398 views.py:1465
-#: views.py:1478
+#: views.py:1234 views.py:1251 views.py:1405 views.py:1417 views.py:1484
+#: views.py:1497
#, python-format
msgid ""
"Encountered XML syntax error: %s (line number may be wrong, try subtracting "
"one from the reported line number)"
msgstr ""
-#: views.py:1222 views.py:1239 views.py:1384 views.py:1401 views.py:1468
-#: views.py:1481
+#: views.py:1237 views.py:1254 views.py:1408 views.py:1420 views.py:1487
+#: views.py:1500
msgid "Your XML is not valid"
msgstr ""
-#: views.py:1227
+#: views.py:1242
#, python-format
msgid "Class \"%s\" already exists"
msgstr ""
-#: views.py:1229
+#: views.py:1244
#, python-format
msgid "Class \"%s\" saved."
msgstr ""
-#: views.py:1366
+#: views.py:1381
#, python-format
msgid "Rule \"%s\" does not exist"
msgstr ""
-#: views.py:1370
+#: views.py:1385
#, python-format
msgid "Rule \"%s\" deleted."
msgstr ""
-#: views.py:1375
+#: views.py:1390
msgid "No rule element found"
msgstr ""
-#: views.py:1389
+#: views.py:1397
#, python-format
msgid "Rule \"%s\" already exists"
msgstr ""
-#: views.py:1391
+#: views.py:1410
#, python-format
msgid "Rule \"%s\" saved."
msgstr ""
-#: views.py:1452
+#: views.py:1471
#, python-format
msgid "Action \"%s\" does not exist"
msgstr ""
-#: views.py:1456
+#: views.py:1475
#, python-format
msgid "Action \"%s\" deleted."
msgstr ""
-#: views.py:1461
+#: views.py:1480
msgid "No action element found"
msgstr ""
-#: views.py:1471
+#: views.py:1490
msgid "Action saved."
msgstr ""
-#: views.py:1540 views.py:1628
+#: views.py:1559 views.py:1647
#, python-format
msgid "%d code points added"
msgstr ""
-#: views.py:1597
+#: views.py:1616
msgid "No code point in input file"
msgstr ""
-#: views.py:1903
+#: views.py:1922
msgid "Meta data saved"
msgstr ""
diff --git a/src/lgr_editor/locale/en/LC_MESSAGES/django.mo b/src/lgr_editor/locale/en/LC_MESSAGES/django.mo
index 8b5f6d89..6c5906d1 100644
Binary files a/src/lgr_editor/locale/en/LC_MESSAGES/django.mo and b/src/lgr_editor/locale/en/LC_MESSAGES/django.mo differ
diff --git a/src/lgr_editor/locale/en/LC_MESSAGES/django.po b/src/lgr_editor/locale/en/LC_MESSAGES/django.po
index 6ebfb584..1dfaaa63 100644
--- a/src/lgr_editor/locale/en/LC_MESSAGES/django.po
+++ b/src/lgr_editor/locale/en/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-09-04 16:04+0000\n"
+"POT-Creation-Date: 2020-12-02 03:08+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -27,6 +27,7 @@ msgstr ""
#: forms/codepoint.py:16 templates/lgr_editor/_editor_base.html:31
#: templates/lgr_editor/codepoint_list.html:40
+#: templates/lgr_editor/validate_lgr/compute_stats.html:71
msgid "Tags"
msgstr ""
@@ -70,7 +71,7 @@ msgid ""
msgstr ""
#: forms/codepoints.py:78 forms/importer.py:14 forms/importer.py:27
-#: forms/metadata.py:50
+#: forms/metadata.py:55
msgid "Validating repertoire"
msgstr ""
@@ -96,6 +97,14 @@ msgstr ""
msgid "File type"
msgstr ""
+#: forms/codepoints.py:135 forms/codepoints.py:136
+msgid "Cannot add when and not-when rules simultaneously"
+msgstr ""
+
+#: forms/codepoints.py:138 forms/codepoints.py:139 forms/codepoints.py:142
+msgid "Please provide at least one value"
+msgstr ""
+
#: forms/importer.py:13
msgid "Name"
msgstr ""
@@ -122,208 +131,301 @@ msgstr ""
msgid "The name of the set"
msgstr ""
-#: forms/labels.py:14
+#: forms/labels.py:13
msgid "Label"
msgstr ""
-#: forms/labels.py:15 forms/metadata.py:46
+#: forms/labels.py:14 forms/metadata.py:50
msgid "Unicode version"
msgstr ""
-#: forms/labels.py:17
+#: forms/labels.py:16
msgid "The unicode version used"
msgstr ""
-#: forms/metadata.py:39
+#: forms/metadata.py:41
msgid "Version"
msgstr ""
-#: forms/metadata.py:40
+#: forms/metadata.py:42
msgid "Version comment"
msgstr ""
-#: forms/metadata.py:41
+#: forms/metadata.py:43
msgid "Date"
msgstr ""
-#: forms/metadata.py:42
+#: forms/metadata.py:44
msgid "Scope"
msgstr ""
-#: forms/metadata.py:43
+#: forms/metadata.py:46
msgid "Scope type"
msgstr ""
-#: forms/metadata.py:44
+#: forms/metadata.py:48
msgid "Validity start"
msgstr ""
-#: forms/metadata.py:45
+#: forms/metadata.py:49
msgid "Validity end"
msgstr ""
-#: forms/metadata.py:47 templates/lgr_editor/codepoint_view.html:227
+#: forms/metadata.py:52 templates/lgr_editor/codepoint_view.html:227
#: templates/lgr_editor/references.html:14
#: templates/lgr_editor/references.html:51
msgid "Description"
msgstr ""
-#: forms/metadata.py:48
+#: forms/metadata.py:53
msgid "Description type"
msgstr ""
-#: forms/metadata.py:53
+#: forms/metadata.py:58
msgid "Built-in"
msgstr ""
-#: forms/metadata.py:65
+#: forms/metadata.py:70
msgid "My LGRs"
msgstr ""
-#: forms/metadata.py:75
+#: forms/metadata.py:80
msgid "Language"
msgstr ""
-#: lgr_exceptions.py:25
+#: forms/references.py:33
+msgid "Invalid format"
+msgstr ""
+
+#: lgr_exceptions.py:28
#, python-format
msgid "Input code point %(codepoint)s is not in the LGR"
msgstr ""
-#: lgr_exceptions.py:29
+#: lgr_exceptions.py:32
#, python-format
msgid "Input code point %(codepoint)s is not in the reference repertoire"
msgstr ""
-#: lgr_exceptions.py:34
+#: lgr_exceptions.py:37
#, python-format
msgid ""
"Variant %(variant_codepoint)s already exists for code point %(codepoint)s"
msgstr ""
-#: lgr_exceptions.py:40
+#: lgr_exceptions.py:43
#, python-format
msgid "Range %(first_cp)s - %(last_cp)s already exists in the LGR"
msgstr ""
-#: lgr_exceptions.py:45
+#: lgr_exceptions.py:48
#, python-format
msgid "Input code point %(codepoint)s already exists in the LGR"
msgstr ""
-#: lgr_exceptions.py:50
+#: lgr_exceptions.py:53
#, python-format
msgid "Input code point %(codepoint)s is not in LGR script"
msgstr ""
-#: lgr_exceptions.py:54
+#: lgr_exceptions.py:57
#, python-format
msgid ""
"Input code point %(codepoint)s is not a PVALID/CONTEXTO/CONTEXTJ code point "
"per IDNA2008"
msgstr ""
-#: lgr_exceptions.py:59
+#: lgr_exceptions.py:62
#, python-format
msgid "Code point %(codepoint)s has invalid context rule %(rule)s"
msgstr ""
-#: lgr_exceptions.py:64
+#: lgr_exceptions.py:67
#, python-format
msgid "Range %(first_cp)s - %(last_cp)s has invalid context rule"
msgstr ""
-#: lgr_exceptions.py:69
+#: lgr_exceptions.py:72
#, python-format
msgid ""
"Variant %(variant_codepoint)s of code point %(codepoint)shas invalid context "
"rule"
msgstr ""
-#: lgr_exceptions.py:75
+#: lgr_exceptions.py:78
#, python-format
msgid "Duplicate reference for code point %(codepoint)s"
msgstr ""
-#: lgr_exceptions.py:79
+#: lgr_exceptions.py:82
#, python-format
msgid "Unspecified exception for input code point %(codepoint)s"
msgstr ""
-#: lgr_exceptions.py:86
+#: lgr_exceptions.py:89
msgid "Sequence cannot have a tag"
msgstr ""
-#: lgr_exceptions.py:88
+#: lgr_exceptions.py:91
msgid "Invalid language"
msgstr ""
-#: lgr_exceptions.py:90
+#: lgr_exceptions.py:93
msgid "Invalid date value"
msgstr ""
-#: lgr_exceptions.py:92
+#: lgr_exceptions.py:95
msgid "Invalid Unicode version"
msgstr ""
-#: lgr_exceptions.py:94
+#: lgr_exceptions.py:97
msgid "Invalid LGR XML file"
msgstr ""
-#: lgr_exceptions.py:96
+#: lgr_exceptions.py:99
#, python-format
msgid "Reference %(ref_id)s is not defined"
msgstr ""
-#: lgr_exceptions.py:100
+#: lgr_exceptions.py:103
#, python-format
msgid "Reference %(ref_id)s already exists"
msgstr ""
-#: lgr_exceptions.py:104
+#: lgr_exceptions.py:107
#, python-format
msgid "Invalid reference id %(ref_id)s "
msgstr ""
-#: lgr_exceptions.py:108
+#: lgr_exceptions.py:111
#, python-format
msgid "Rule \"%(rule_name)s\" cannot be processed (%(message)s)"
msgstr ""
-#: lgr_exceptions.py:113
+#: lgr_exceptions.py:116
msgid "Input parameter has invalid format"
msgstr ""
-#: lgr_exceptions.py:115
+#: lgr_exceptions.py:118
msgid "A general exception occurred in the LGR API"
msgstr ""
-#: lgr_exceptions.py:117
+#: lgr_exceptions.py:120
#, python-format
msgid "LGR is not valid (%(args)s)"
msgstr ""
-#: lgr_exceptions.py:119
+#: lgr_exceptions.py:122
#, python-format
msgid "Label %(label)s is not valid in the LGR (%(message)s)"
msgstr ""
-#: lgr_exceptions.py:124
+#: lgr_exceptions.py:127
msgid "Input label file contains collision(s)"
msgstr ""
-#: lgr_exceptions.py:126
+#: lgr_exceptions.py:129
msgid "The LGR contains a variant that do not have symmetric relations"
msgstr ""
-#: lgr_exceptions.py:129
+#: lgr_exceptions.py:132
#, python-format
msgid "The LGR does not contain a valid language (%(message)s)"
msgstr ""
-#: lgr_exceptions.py:131
+#: lgr_exceptions.py:134
+#, python-format
+msgid "Cannot generate cross-script variant for LGR without (%(message)s)"
+msgstr ""
+
+#: lgr_exceptions.py:138
msgid "An unknown exception occurred in the LGR API"
msgstr ""
+#: lgr_exceptions.py:143
+msgid "Label is empty"
+msgstr ""
+
+#: lgr_exceptions.py:145
+#, python-format
+msgid "%(label)s is invalid due to its length being longer than 63 bytes."
+msgstr ""
+
+#: lgr_exceptions.py:150
+#, python-format
+msgid ""
+"%(label)s is invalid due to hypen restrictions in the RFC5891 as it starts "
+"with a hyphen-minus."
+msgstr ""
+
+#: lgr_exceptions.py:155
+#, python-format
+msgid ""
+"%(label)s is invalid due to hyphen restrictions in the RFC5891 as it ends "
+"with a hyphen-minus."
+msgstr ""
+
+#: lgr_exceptions.py:160
+#, python-format
+msgid ""
+"%(label)s is invalid due to hyphen restrictions in the RFC5891 as it "
+"contains hyphen-minus in the third and fourth positions."
+msgstr ""
+
+#: lgr_exceptions.py:165
+#, python-format
+msgid ""
+"%(label)s is invalid due to leading combining marks restriction in the "
+"RFC5891."
+msgstr ""
+
+#: lgr_exceptions.py:170
+#, python-format
+msgid "%(label)s is invalid as it contains disallowed characters."
+msgstr ""
+
+#: lgr_exceptions.py:174
+#, python-format
+msgid ""
+"%(label)s is invalid as it starts with ‘xn--’ but does not contain valid "
+"Punycode."
+msgstr ""
+
+#: lgr_exceptions.py:179
+#, python-format
+msgid "%(label)s is invalid as it contains full stop (dot)."
+msgstr ""
+
+#: lgr_exceptions.py:183
+#, python-format
+msgid "%(label)s is invalid due to invalid Punycode."
+msgstr ""
+
+#: lgr_exceptions.py:185
+#, python-format
+msgid "%(label)s is invalid due to the Bidi rule in the RFC5893."
+msgstr ""
+
+#: lgr_exceptions.py:189
+#, python-format
+msgid ""
+"%(label)s is invalid due to the IDNA contextual rule for Zero Width Joiner."
+msgstr ""
+
+#: lgr_exceptions.py:194
+#, python-format
+msgid ""
+"%(label)s is invalid due to the IDNA contextual rule for punctuation in the "
+"RFC5892."
+msgstr ""
+
+#: lgr_exceptions.py:199
+#, python-format
+msgid ""
+"%(label)s is invalid due to the IDNA contextual rule for digits in the "
+"RFC5892."
+msgstr ""
+
#: templates/lgr_editor/_editor_base.html:25
#: templates/lgr_editor/codepoint_view.html:54
msgid "References"
@@ -335,6 +437,7 @@ msgstr ""
#: templates/lgr_editor/_editor_base.html:34 templates/lgr_editor/rules.html:18
#: templates/lgr_editor/rules_edit.html:57
+#: templates/lgr_editor/validate_lgr/compute_stats.html:79
msgid "Rules"
msgstr ""
@@ -354,7 +457,7 @@ msgstr ""
#: templates/lgr_editor/_rule_editor_widgets.html:5
#: templates/lgr_editor/codepoint_view.html:244
-#: templates/lgr_editor/metadata.html:32
+#: templates/lgr_editor/metadata.html:45
#: templates/lgr_editor/rules_edit.html:40
#: templates/lgr_editor/rules_edit.html:71
#: templates/lgr_editor/rules_edit.html:103
@@ -362,7 +465,7 @@ msgid "Cancel"
msgstr ""
#: templates/lgr_editor/_rule_editor_widgets.html:8
-#: templates/lgr_editor/metadata.html:33
+#: templates/lgr_editor/metadata.html:46
#: templates/lgr_editor/references.html:39
#: templates/lgr_editor/rules_edit.html:43
#: templates/lgr_editor/rules_edit.html:74
@@ -442,7 +545,6 @@ msgid "Action"
msgstr ""
#: templates/lgr_editor/codepoint_list.html:52
-#: templates/lgr_editor/codepoint_list.html:82
msgid "Add Rule"
msgstr ""
@@ -462,6 +564,11 @@ msgid ""
" "
msgstr ""
+#: templates/lgr_editor/codepoint_list.html:82
+#: templates/lgr_editor/codepoint_list.html:275
+msgid "Add Tags"
+msgstr ""
+
#: templates/lgr_editor/codepoint_list.html:87
msgid ""
"\n"
@@ -507,10 +614,6 @@ msgstr ""
msgid "Add WLE"
msgstr ""
-#: templates/lgr_editor/codepoint_list.html:275
-msgid "Add Tags"
-msgstr ""
-
#: templates/lgr_editor/codepoint_list.html:295
msgid "➡ Apply batch action..."
msgstr ""
@@ -656,23 +759,23 @@ msgstr ""
msgid "Cannot import LGR file(s):"
msgstr ""
-#: templates/lgr_editor/label_forms.html:11
+#: templates/lgr_editor/label_forms.html:10
msgid "Display forms"
msgstr ""
-#: templates/lgr_editor/label_forms.html:18
+#: templates/lgr_editor/label_forms.html:16
msgid "Code point sequence"
msgstr ""
-#: templates/lgr_editor/label_forms.html:19
+#: templates/lgr_editor/label_forms.html:17
msgid "U-label"
msgstr ""
-#: templates/lgr_editor/label_forms.html:20
+#: templates/lgr_editor/label_forms.html:18
msgid "A-label"
msgstr ""
-#: templates/lgr_editor/metadata.html:11
+#: templates/lgr_editor/metadata.html:23
msgid "There was an error saving; please see error(s) below"
msgstr ""
@@ -774,215 +877,423 @@ msgid ""
" Add it to a code point first to find it back in this list"
msgstr ""
-#: views.py:114
+#: templates/lgr_editor/validate_lgr/check_conditional_variants.html:7
+msgid "Erroneous conditional code points"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_conditional_variants.html:11
+#, python-format
+msgid ""
+"Code point %(cp)s has invalid %(rule_type)s rule %(rule)s for variant "
+"%(variant)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_conditional_variants.html:18
+msgid "Conditional variants OK"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:7
+msgid "Missing code points or rules"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:11
+#, python-format
+msgid "Code point %(cp)s:"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:15
+#, python-format
+msgid "Variant %(variant)s is not in repertoire"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:19
+#, python-format
+msgid "%(variant)s has not original code point in its variants"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:23
+#, python-format
+msgid ""
+"%(variant)s has not symmetric %(rule_type)s rule %(rule)s on its symmetric "
+"variants"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:27
+#, python-format
+msgid "%(variant)s unknown symmetry problem, please report"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:35
+msgid "Symmetry OK"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_transitivity.html:7
+msgid "Missing variants"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_transitivity.html:11
+#, python-format
+msgid "Code point %(cp)s is missing variant %(variant)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_transitivity.html:18
+msgid "Transitivity OK"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_xml_validity.html:7
+msgid "XML is valid and complies with RNG."
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/check_xml_validity.html:9
+#, python-format
+msgid "Invalid XML for lgr: %(res)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:6
+msgid "General stats"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:9
+#, python-format
+msgid "Number of code points: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:15
+#, python-format
+msgid "Number of ranges: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:21
+#, python-format
+msgid "Largest range: %(largest)s (length: %(largest_len)s)"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:28
+#, python-format
+msgid "Number of sequences: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:34
+#, python-format
+msgid "Largest sequence: %(largest)s (length: %(largest_len)s)"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:41
+msgid "Variants"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:44
+#, python-format
+msgid "Total number of variant mappings: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:49
+#, python-format
+msgid "Average number of variants per code point: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:54
+#, python-format
+msgid "Largest variant set: %(largest_set)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:60
+msgid "Variants per type:"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:63
+#, python-format
+msgid "Number of variants for type %(variant_type)s: %(number)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:74
+#, python-format
+msgid "Number of code points for tag %(tag_name)s: %(number)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:82
+#, python-format
+msgid "Number of defined rules: %(nbr)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:6
+#, python-format
+msgid "Unicode version %(version)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:8
+#, python-format
+msgid "Validating repertoire '%(repertoire)s'"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:13
+#, python-format
+msgid ""
+"Target Unicode version %(version)s differs from UnicodeDatabase %(database)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:19
+msgid "Possibly erroneous characters"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:23
+#, python-format
+msgid "Character %(cp)s:"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:29
+#, python-format
+msgid "Warning: %(warn)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:36
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:49
+#, python-format
+msgid "Error: %(err)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:43
+#, python-format
+msgid "Variant: %(variant|render_char)s"
+msgstr ""
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:60
+msgid "LGR rebuild OK"
+msgstr ""
+
+#: views.py:115
msgid ""
"The LGR you have tried to create already exists in your working session. "
"Please use a new name."
msgstr ""
-#: views.py:148
+#: views.py:149
msgid ""
"The LGR you have tried to import already exists in your working session. "
"Please rename it before importing it."
msgstr ""
-#: views.py:154
+#: views.py:155
msgid ""
"The LGR you have tried to import already exists in your set. Please rename "
"it before importing it."
msgstr ""
-#: views.py:177
+#: views.py:178
msgid "The LGR set name already exists. Please use another name."
msgstr ""
-#: views.py:289
+#: views.py:249
+msgid "Testing XML validity using RNG"
+msgstr ""
+
+#: views.py:250
+msgid "Testing symmetry"
+msgstr ""
+
+#: views.py:251
+msgid "Testing transitivity"
+msgstr ""
+
+#: views.py:252
+msgid "Testing conditional variants"
+msgstr ""
+
+#: views.py:253
+msgid "Generate stats"
+msgstr ""
+
+#: views.py:254
+msgid "Rebuilding LGR"
+msgstr ""
+
+#: views.py:302
#, python-format
msgid "New code point %s added"
msgstr ""
-#: views.py:362
+#: views.py:375
msgid "Rule"
msgstr ""
-#: views.py:362
+#: views.py:375
msgid "Tag(s)"
msgstr ""
-#: views.py:363
+#: views.py:376
msgid "rule"
msgstr ""
-#: views.py:363
+#: views.py:376
msgid "tag(s)"
msgstr ""
-#: views.py:367
+#: views.py:380
#, python-format
msgid "%(operation)s successfully added to %(nb_cp)s code point(s)"
msgstr ""
-#: views.py:372
+#: views.py:385
#, python-format
msgid "%(nb_cp)s code points were not updated to avoid invalid %(operation)s"
msgstr ""
-#: views.py:504
+#: views.py:517
#, python-format
-msgid "Automatically added codepoint %s from out-of-repertoire variant"
+msgid "Automatically added codepoint %s from out-of-repertoire-var variant"
msgstr ""
-#: views.py:507
+#: views.py:520
#, python-format
msgid "New variant %s added"
msgstr ""
-#: views.py:580
+#: views.py:593
msgid "Code point edited"
msgstr ""
-#: views.py:732
+#: views.py:745
msgid "Variants populated"
msgstr ""
-#: views.py:783 views.py:819
+#: views.py:798 views.py:834
msgid "References updated successfully"
msgstr ""
-#: views.py:822
+#: views.py:837
#, python-format
msgid ""
"Variant %(var_codepoint)s for code point %(codepoint)s with when=%(when)s "
"and not-when=%(not_when)s could not be found"
msgstr ""
-#: views.py:858
+#: views.py:873
#, python-format
msgid "Code point %s has been deleted"
msgstr ""
-#: views.py:880
+#: views.py:895
#, python-format
msgid "Variant %(var_cp)s with when='%(when)s' and not-when='%(not_when)s'"
msgstr ""
-#: views.py:886
+#: views.py:901
#, python-format
msgid "%(var_msg_prefix)s has been deleted"
msgstr ""
-#: views.py:889
+#: views.py:904
#, python-format
msgid "%(var_msg_prefix)s could not be deleted because it was not found"
msgstr ""
-#: views.py:919
+#: views.py:934
msgid "New reference created"
msgstr ""
-#: views.py:1127
+#: views.py:1142
#, python-format
msgid ""
"References to tag %(tag)s have been removed from the repertoire. Do not "
"forget to update any WLE that might reference it."
msgstr ""
-#: views.py:1195 views.py:1357 views.py:1441
+#: views.py:1210 views.py:1372 views.py:1460
msgid "No body specified"
msgstr ""
-#: views.py:1204
+#: views.py:1219
#, python-format
msgid "Class \"%s\" does not exist"
msgstr ""
-#: views.py:1208
+#: views.py:1223
#, python-format
msgid "Class \"%s\" deleted."
msgstr ""
-#: views.py:1213
+#: views.py:1228
msgid "No class element found"
msgstr ""
-#: views.py:1215 views.py:1377
+#: views.py:1230 views.py:1392
msgid "Name attribute must be present"
msgstr ""
-#: views.py:1219 views.py:1236 views.py:1381 views.py:1398 views.py:1465
-#: views.py:1478
+#: views.py:1234 views.py:1251 views.py:1405 views.py:1417 views.py:1484
+#: views.py:1497
#, python-format
msgid ""
"Encountered XML syntax error: %s (line number may be wrong, try subtracting "
"one from the reported line number)"
msgstr ""
-#: views.py:1222 views.py:1239 views.py:1384 views.py:1401 views.py:1468
-#: views.py:1481
+#: views.py:1237 views.py:1254 views.py:1408 views.py:1420 views.py:1487
+#: views.py:1500
msgid "Your XML is not valid"
msgstr ""
-#: views.py:1227
+#: views.py:1242
#, python-format
msgid "Class \"%s\" already exists"
msgstr ""
-#: views.py:1229
+#: views.py:1244
#, python-format
msgid "Class \"%s\" saved."
msgstr ""
-#: views.py:1366
+#: views.py:1381
#, python-format
msgid "Rule \"%s\" does not exist"
msgstr ""
-#: views.py:1370
+#: views.py:1385
#, python-format
msgid "Rule \"%s\" deleted."
msgstr ""
-#: views.py:1375
+#: views.py:1390
msgid "No rule element found"
msgstr ""
-#: views.py:1389
+#: views.py:1397
#, python-format
msgid "Rule \"%s\" already exists"
msgstr ""
-#: views.py:1391
+#: views.py:1410
#, python-format
msgid "Rule \"%s\" saved."
msgstr ""
-#: views.py:1452
+#: views.py:1471
#, python-format
msgid "Action \"%s\" does not exist"
msgstr ""
-#: views.py:1456
+#: views.py:1475
#, python-format
msgid "Action \"%s\" deleted."
msgstr ""
-#: views.py:1461
+#: views.py:1480
msgid "No action element found"
msgstr ""
-#: views.py:1471
+#: views.py:1490
msgid "Action saved."
msgstr ""
-#: views.py:1540 views.py:1628
+#: views.py:1559 views.py:1647
#, python-format
msgid "%d code points added"
msgstr ""
-#: views.py:1597
+#: views.py:1616
msgid "No code point in input file"
msgstr ""
-#: views.py:1903
+#: views.py:1922
msgid "Meta data saved"
msgstr ""
diff --git a/src/lgr_editor/locale/fr/LC_MESSAGES/django.mo b/src/lgr_editor/locale/fr/LC_MESSAGES/django.mo
index 907f5a37..76593377 100644
Binary files a/src/lgr_editor/locale/fr/LC_MESSAGES/django.mo and b/src/lgr_editor/locale/fr/LC_MESSAGES/django.mo differ
diff --git a/src/lgr_editor/locale/fr/LC_MESSAGES/django.po b/src/lgr_editor/locale/fr/LC_MESSAGES/django.po
index c0f71a92..a358716b 100644
--- a/src/lgr_editor/locale/fr/LC_MESSAGES/django.po
+++ b/src/lgr_editor/locale/fr/LC_MESSAGES/django.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-09-04 16:04+0000\n"
-"PO-Revision-Date: 2018-09-04 11:47-0400\n"
+"POT-Creation-Date: 2020-12-02 03:08+0000\n"
+"PO-Revision-Date: 2020-12-01 22:10-0500\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: fr\n"
@@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-"X-Generator: Poedit 2.1.1\n"
+"X-Generator: Poedit 2.4.1\n"
#: forms/codepoint.py:14 templates/lgr_editor/codepoint_view.html:52
msgid "When"
@@ -28,6 +28,7 @@ msgstr "Not When"
#: forms/codepoint.py:16 templates/lgr_editor/_editor_base.html:31
#: templates/lgr_editor/codepoint_list.html:40
+#: templates/lgr_editor/validate_lgr/compute_stats.html:71
msgid "Tags"
msgstr "Tags"
@@ -73,7 +74,7 @@ msgstr ""
"code point (%(first_cp)s)"
#: forms/codepoints.py:78 forms/importer.py:14 forms/importer.py:27
-#: forms/metadata.py:50
+#: forms/metadata.py:55
msgid "Validating repertoire"
msgstr "Répertoire de validation"
@@ -101,6 +102,14 @@ msgstr ""
msgid "File type"
msgstr "Type de fichier"
+#: forms/codepoints.py:135 forms/codepoints.py:136
+msgid "Cannot add when and not-when rules simultaneously"
+msgstr "Impossible d'ajouter when et not-when simultanément"
+
+#: forms/codepoints.py:138 forms/codepoints.py:139 forms/codepoints.py:142
+msgid "Please provide at least one value"
+msgstr "Fournissez au moins une valeur s'il vous plait"
+
#: forms/importer.py:13
msgid "Name"
msgstr "Nom"
@@ -129,79 +138,83 @@ msgstr ""
msgid "The name of the set"
msgstr "Nom du set"
-#: forms/labels.py:14
+#: forms/labels.py:13
msgid "Label"
msgstr "Label"
-#: forms/labels.py:15 forms/metadata.py:46
+#: forms/labels.py:14 forms/metadata.py:50
msgid "Unicode version"
msgstr "Version d'Unicode"
-#: forms/labels.py:17
+#: forms/labels.py:16
msgid "The unicode version used"
msgstr "Version d'Unicode"
-#: forms/metadata.py:39
+#: forms/metadata.py:41
msgid "Version"
msgstr "Version"
-#: forms/metadata.py:40
+#: forms/metadata.py:42
msgid "Version comment"
msgstr "Commentaire de version"
-#: forms/metadata.py:41
+#: forms/metadata.py:43
msgid "Date"
msgstr "Date"
-#: forms/metadata.py:42
+#: forms/metadata.py:44
msgid "Scope"
msgstr "Portée"
-#: forms/metadata.py:43
+#: forms/metadata.py:46
msgid "Scope type"
msgstr "Type de la portée"
-#: forms/metadata.py:44
+#: forms/metadata.py:48
msgid "Validity start"
msgstr "Début de la validité"
-#: forms/metadata.py:45
+#: forms/metadata.py:49
msgid "Validity end"
msgstr "Fin de la validité"
-#: forms/metadata.py:47 templates/lgr_editor/codepoint_view.html:227
+#: forms/metadata.py:52 templates/lgr_editor/codepoint_view.html:227
#: templates/lgr_editor/references.html:14
#: templates/lgr_editor/references.html:51
msgid "Description"
msgstr "Description"
-#: forms/metadata.py:48
+#: forms/metadata.py:53
msgid "Description type"
msgstr "Type de la description"
-#: forms/metadata.py:53
+#: forms/metadata.py:58
msgid "Built-in"
msgstr "Fournis"
-#: forms/metadata.py:65
+#: forms/metadata.py:70
msgid "My LGRs"
msgstr "Mes LGRs"
-#: forms/metadata.py:75
+#: forms/metadata.py:80
msgid "Language"
msgstr "Langage"
-#: lgr_exceptions.py:25
+#: forms/references.py:33
+msgid "Invalid format"
+msgstr "Format invalide"
+
+#: lgr_exceptions.py:28
#, python-format
msgid "Input code point %(codepoint)s is not in the LGR"
msgstr "Le code point %(codepoint)s n'est pas dans la LGR"
-#: lgr_exceptions.py:29
+#: lgr_exceptions.py:32
#, python-format
msgid "Input code point %(codepoint)s is not in the reference repertoire"
msgstr "Le code point %(codepoint)s n'est pas dans le répertoire de référence"
-#: lgr_exceptions.py:34
+#: lgr_exceptions.py:37
#, python-format
msgid ""
"Variant %(variant_codepoint)s already exists for code point %(codepoint)s"
@@ -209,22 +222,22 @@ msgstr ""
"La variante %(variant_codepoint)s existe déjà pour le code point "
"%(codepoint)s"
-#: lgr_exceptions.py:40
+#: lgr_exceptions.py:43
#, python-format
msgid "Range %(first_cp)s - %(last_cp)s already exists in the LGR"
msgstr "L'ensemble %(first_cp)s - %(last_cp)s existe déjà dans la LGR"
-#: lgr_exceptions.py:45
+#: lgr_exceptions.py:48
#, python-format
msgid "Input code point %(codepoint)s already exists in the LGR"
msgstr "Le code point %(codepoint)s existe déjà dans la LGR"
-#: lgr_exceptions.py:50
+#: lgr_exceptions.py:53
#, python-format
msgid "Input code point %(codepoint)s is not in LGR script"
msgstr "Le code point %(codepoint)s n'est pas dans le script de la LGR"
-#: lgr_exceptions.py:54
+#: lgr_exceptions.py:57
#, python-format
msgid ""
"Input code point %(codepoint)s is not a PVALID/CONTEXTO/CONTEXTJ code point "
@@ -233,18 +246,18 @@ msgstr ""
"Le code point %(codepoint)s n'est pas un code point PVALID/CONTEXTO/CONTEXTJ "
"d'après IDNA2008"
-#: lgr_exceptions.py:59
+#: lgr_exceptions.py:62
#, python-format
msgid "Code point %(codepoint)s has invalid context rule %(rule)s"
msgstr "Le code point %(codepoint)s a une règle contextuelle invalide %(rule)s"
-#: lgr_exceptions.py:64
+#: lgr_exceptions.py:67
#, python-format
msgid "Range %(first_cp)s - %(last_cp)s has invalid context rule"
msgstr ""
"L'ensemble %(first_cp)s - %(last_cp)s a une règle contextuelle invalide"
-#: lgr_exceptions.py:69
+#: lgr_exceptions.py:72
#, python-format
msgid ""
"Variant %(variant_codepoint)s of code point %(codepoint)shas invalid context "
@@ -253,91 +266,202 @@ msgstr ""
"La variante %(variant_codepoint)s du code point %(codepoint)s a une règle "
"contextuelle invalide"
-#: lgr_exceptions.py:75
+#: lgr_exceptions.py:78
#, python-format
msgid "Duplicate reference for code point %(codepoint)s"
msgstr "Référence dupliquée pour le code point %(codepoint)s"
-#: lgr_exceptions.py:79
+#: lgr_exceptions.py:82
#, python-format
msgid "Unspecified exception for input code point %(codepoint)s"
msgstr "Exception non-spécifiée pour le code point d'entrée %(codepoint)s"
-#: lgr_exceptions.py:86
+#: lgr_exceptions.py:89
msgid "Sequence cannot have a tag"
msgstr "Les séquences ne peuvent pas avoir de tag"
-#: lgr_exceptions.py:88
+#: lgr_exceptions.py:91
msgid "Invalid language"
msgstr "Langage invalide"
-#: lgr_exceptions.py:90
+#: lgr_exceptions.py:93
msgid "Invalid date value"
msgstr "Date invalide"
-#: lgr_exceptions.py:92
+#: lgr_exceptions.py:95
msgid "Invalid Unicode version"
msgstr "Version d'unicode invalide"
-#: lgr_exceptions.py:94
+#: lgr_exceptions.py:97
msgid "Invalid LGR XML file"
msgstr "Fichier XML de LGR invalide"
-#: lgr_exceptions.py:96
+#: lgr_exceptions.py:99
#, python-format
msgid "Reference %(ref_id)s is not defined"
msgstr "La référence %(ref_id)s n'est pas définie"
-#: lgr_exceptions.py:100
+#: lgr_exceptions.py:103
#, python-format
msgid "Reference %(ref_id)s already exists"
msgstr "La référence %(ref_id)s existe déjà"
-#: lgr_exceptions.py:104
+#: lgr_exceptions.py:107
#, python-format
msgid "Invalid reference id %(ref_id)s "
msgstr "Identifiant de référence invalide %(ref_id)s "
-#: lgr_exceptions.py:108
+#: lgr_exceptions.py:111
#, python-format
msgid "Rule \"%(rule_name)s\" cannot be processed (%(message)s)"
msgstr "La règle \"%(rule_name)s\" ne peut pas être traitée (%(message)s)"
-#: lgr_exceptions.py:113
+#: lgr_exceptions.py:116
msgid "Input parameter has invalid format"
msgstr "Le paramètre d'entrée a un format invalide"
-#: lgr_exceptions.py:115
+#: lgr_exceptions.py:118
msgid "A general exception occurred in the LGR API"
msgstr "Une exception s'est produite dans l'API LGR"
-#: lgr_exceptions.py:117
+#: lgr_exceptions.py:120
#, python-format
msgid "LGR is not valid (%(args)s)"
msgstr "La LGR n'est pas valide (%(args)s)"
-#: lgr_exceptions.py:119
+#: lgr_exceptions.py:122
#, python-format
msgid "Label %(label)s is not valid in the LGR (%(message)s)"
msgstr "Label %(label)s n'est pas valide dans la LGR (%(message)s)"
-#: lgr_exceptions.py:124
+#: lgr_exceptions.py:127
msgid "Input label file contains collision(s)"
msgstr "Le fichier d'entrée des labels contient une/des collision(s)"
-#: lgr_exceptions.py:126
+#: lgr_exceptions.py:129
msgid "The LGR contains a variant that do not have symmetric relations"
msgstr "La LGR contient des variantes ne respectant pas la symmétrie"
-#: lgr_exceptions.py:129
+#: lgr_exceptions.py:132
#, python-format
msgid "The LGR does not contain a valid language (%(message)s)"
msgstr "La LGR ne contient pas de langues valides (%(message)s)"
-#: lgr_exceptions.py:131
+#: lgr_exceptions.py:134
+#, python-format
+msgid "Cannot generate cross-script variant for LGR without (%(message)s)"
+msgstr ""
+"Impossible de générer les variantes cross-script pour la LGR sans "
+"(%(message)s)"
+
+#: lgr_exceptions.py:138
msgid "An unknown exception occurred in the LGR API"
msgstr "Une exception inconnue s'est produite dans l'API LGR"
+#: lgr_exceptions.py:143
+msgid "Label is empty"
+msgstr "Le label est vide"
+
+#: lgr_exceptions.py:145
+#, python-format
+msgid "%(label)s is invalid due to its length being longer than 63 bytes."
+msgstr ""
+"le label %(label)s est invalide car sa longueur est supérieure à 63 octets."
+
+#: lgr_exceptions.py:150
+#, python-format
+msgid ""
+"%(label)s is invalid due to hypen restrictions in the RFC5891 as it starts "
+"with a hyphen-minus."
+msgstr ""
+"le label %(label)s est invalide en raison des restrictions sur les traits "
+"d'union dans la RFC5891 car il débute par le signe moins."
+
+#: lgr_exceptions.py:155
+#, python-format
+msgid ""
+"%(label)s is invalid due to hyphen restrictions in the RFC5891 as it ends "
+"with a hyphen-minus."
+msgstr ""
+"le label %(label)s est invalide en raison des restrictions sur les traits "
+"d'union dans la RFC5891 car il termine par le signe moins."
+
+#: lgr_exceptions.py:160
+#, python-format
+msgid ""
+"%(label)s is invalid due to hyphen restrictions in the RFC5891 as it "
+"contains hyphen-minus in the third and fourth positions."
+msgstr ""
+"le label %(label)s est invalide en raison des restrictions sur les traits "
+"d'union dans la RFC5891 car contient le signe moins à la troisième et "
+"quatrième position."
+
+#: lgr_exceptions.py:165
+#, python-format
+msgid ""
+"%(label)s is invalid due to leading combining marks restriction in the "
+"RFC5891."
+msgstr ""
+"le label %(label)s est invalide en raison des restrictions sur signes "
+"combinatoires de tête dans la RFC5891."
+
+#: lgr_exceptions.py:170
+#, python-format
+msgid "%(label)s is invalid as it contains disallowed characters."
+msgstr ""
+"le label %(label)s est invalide car il contient des caractères interdits."
+
+#: lgr_exceptions.py:174
+#, python-format
+msgid ""
+"%(label)s is invalid as it starts with ‘xn--’ but does not contain valid "
+"Punycode."
+msgstr ""
+"le label %(label)s est invalide car ils débute par 'xn--' et ne contient pas "
+"de Punycode valide."
+
+#: lgr_exceptions.py:179
+#, python-format
+msgid "%(label)s is invalid as it contains full stop (dot)."
+msgstr "le label %(label)s est invalide car il contient un point final."
+
+#: lgr_exceptions.py:183
+#, python-format
+msgid "%(label)s is invalid due to invalid Punycode."
+msgstr "le label %(label)s est invalide en raison de Punycode invalide."
+
+#: lgr_exceptions.py:185
+#, python-format
+msgid "%(label)s is invalid due to the Bidi rule in the RFC5893."
+msgstr ""
+"le label %(label)s est invalide en raison de la règle Bidi dans la RFC5893."
+
+#: lgr_exceptions.py:189
+#, python-format
+msgid ""
+"%(label)s is invalid due to the IDNA contextual rule for Zero Width Joiner."
+msgstr ""
+"le label %(label)s est invalide en raison de la règle IDNA contextuelle pour "
+"les liant sans chasse (Zero Width Joiner)."
+
+#: lgr_exceptions.py:194
+#, python-format
+msgid ""
+"%(label)s is invalid due to the IDNA contextual rule for punctuation in the "
+"RFC5892."
+msgstr ""
+"le label %(label)s est invalide en raison de la règle IDNA contextuelle pour "
+"la ponctuation ans la RFC5892."
+
+#: lgr_exceptions.py:199
+#, python-format
+msgid ""
+"%(label)s is invalid due to the IDNA contextual rule for digits in the "
+"RFC5892."
+msgstr ""
+"le label %(label)s est invalide en raison de la règle IDNA contextuelle pour "
+"les chiffres ans la RFC5892."
+
#: templates/lgr_editor/_editor_base.html:25
#: templates/lgr_editor/codepoint_view.html:54
msgid "References"
@@ -349,6 +473,7 @@ msgstr "Métadonnées"
#: templates/lgr_editor/_editor_base.html:34 templates/lgr_editor/rules.html:18
#: templates/lgr_editor/rules_edit.html:57
+#: templates/lgr_editor/validate_lgr/compute_stats.html:79
msgid "Rules"
msgstr "Règles"
@@ -368,7 +493,7 @@ msgstr "%(lgr_name)s"
#: templates/lgr_editor/_rule_editor_widgets.html:5
#: templates/lgr_editor/codepoint_view.html:244
-#: templates/lgr_editor/metadata.html:32
+#: templates/lgr_editor/metadata.html:45
#: templates/lgr_editor/rules_edit.html:40
#: templates/lgr_editor/rules_edit.html:71
#: templates/lgr_editor/rules_edit.html:103
@@ -376,7 +501,7 @@ msgid "Cancel"
msgstr "Annuler"
#: templates/lgr_editor/_rule_editor_widgets.html:8
-#: templates/lgr_editor/metadata.html:33
+#: templates/lgr_editor/metadata.html:46
#: templates/lgr_editor/references.html:39
#: templates/lgr_editor/rules_edit.html:43
#: templates/lgr_editor/rules_edit.html:74
@@ -467,7 +592,6 @@ msgid "Action"
msgstr "Action"
#: templates/lgr_editor/codepoint_list.html:52
-#: templates/lgr_editor/codepoint_list.html:82
msgid "Add Rule"
msgstr "Ajouter une règle"
@@ -491,6 +615,11 @@ msgstr ""
" code point(s)
\n"
" "
+#: templates/lgr_editor/codepoint_list.html:82
+#: templates/lgr_editor/codepoint_list.html:275
+msgid "Add Tags"
+msgstr "Ajouter des Tags"
+
#: templates/lgr_editor/codepoint_list.html:87
msgid ""
"\n"
@@ -541,10 +670,6 @@ msgstr ""
msgid "Add WLE"
msgstr "Ajouter une WLE"
-#: templates/lgr_editor/codepoint_list.html:275
-msgid "Add Tags"
-msgstr "Ajouter des Tags"
-
#: templates/lgr_editor/codepoint_list.html:295
msgid "➡ Apply batch action..."
msgstr "➡ Appliquer action par lots..."
@@ -699,23 +824,23 @@ msgstr ""
msgid "Cannot import LGR file(s):"
msgstr "Impossible d'importer le(s) fichier(s) LGR :"
-#: templates/lgr_editor/label_forms.html:11
+#: templates/lgr_editor/label_forms.html:10
msgid "Display forms"
msgstr "Afficher les formes"
-#: templates/lgr_editor/label_forms.html:18
+#: templates/lgr_editor/label_forms.html:16
msgid "Code point sequence"
msgstr "Séquence de code points"
-#: templates/lgr_editor/label_forms.html:19
+#: templates/lgr_editor/label_forms.html:17
msgid "U-label"
msgstr "U-Label"
-#: templates/lgr_editor/label_forms.html:20
+#: templates/lgr_editor/label_forms.html:18
msgid "A-label"
msgstr "A-Label"
-#: templates/lgr_editor/metadata.html:11
+#: templates/lgr_editor/metadata.html:23
msgid "There was an error saving; please see error(s) below"
msgstr ""
"Il y a eu une erreur lors de la sauvegarde, merci de regarder ci-dessous"
@@ -821,7 +946,197 @@ msgstr ""
" Ajouter le tag à un code point afin de le retrouver dans "
"cette list"
-#: views.py:114
+#: templates/lgr_editor/validate_lgr/check_conditional_variants.html:7
+msgid "Erroneous conditional code points"
+msgstr "Erreur dans les code points conditionels"
+
+#: templates/lgr_editor/validate_lgr/check_conditional_variants.html:11
+#, python-format
+msgid ""
+"Code point %(cp)s has invalid %(rule_type)s rule %(rule)s for variant "
+"%(variant)s"
+msgstr ""
+"Le code point %(cp)s a la règle %(rule_type)s %(rule)s invalide pour les "
+"variantes %(variant)s"
+
+#: templates/lgr_editor/validate_lgr/check_conditional_variants.html:18
+msgid "Conditional variants OK"
+msgstr "Variantes conditionnelles OK"
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:7
+msgid "Missing code points or rules"
+msgstr "Code points ou règles manquants"
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:11
+#, python-format
+msgid "Code point %(cp)s:"
+msgstr "Code point %(cp)s:"
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:15
+#, python-format
+msgid "Variant %(variant)s is not in repertoire"
+msgstr "La variante %(variant)s n'est pas dans le répertoire"
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:19
+#, python-format
+msgid "%(variant)s has not original code point in its variants"
+msgstr "%(variant)s n'a pas le code point original dans ses variantes"
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:23
+#, python-format
+msgid ""
+"%(variant)s has not symmetric %(rule_type)s rule %(rule)s on its symmetric "
+"variants"
+msgstr ""
+"%(variant)s n'a pas la règle %(rule_type)s %(rule)s dans ses variantes "
+"symmétriques"
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:27
+#, python-format
+msgid "%(variant)s unknown symmetry problem, please report"
+msgstr ""
+"%(variant)s problème de symétrie inconnu, veuillez contacter le support"
+
+#: templates/lgr_editor/validate_lgr/check_symmetry.html:35
+msgid "Symmetry OK"
+msgstr "Symétrie OK"
+
+#: templates/lgr_editor/validate_lgr/check_transitivity.html:7
+msgid "Missing variants"
+msgstr "Variantes manquantes"
+
+#: templates/lgr_editor/validate_lgr/check_transitivity.html:11
+#, python-format
+msgid "Code point %(cp)s is missing variant %(variant)s"
+msgstr "Le code point %(cp)s n'a pas la variante %(variant)s"
+
+#: templates/lgr_editor/validate_lgr/check_transitivity.html:18
+msgid "Transitivity OK"
+msgstr "Transitivité OK"
+
+#: templates/lgr_editor/validate_lgr/check_xml_validity.html:7
+msgid "XML is valid and complies with RNG."
+msgstr "XML valide et conforme au RNG."
+
+#: templates/lgr_editor/validate_lgr/check_xml_validity.html:9
+#, python-format
+msgid "Invalid XML for lgr: %(res)s"
+msgstr "Fichier XML invalide pour la LGR: %(res)s"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:6
+msgid "General stats"
+msgstr "Statistiques générales"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:9
+#, python-format
+msgid "Number of code points: %(nbr)s"
+msgstr "Nombre de code points: %(nbr)s"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:15
+#, python-format
+msgid "Number of ranges: %(nbr)s"
+msgstr "Nombre d'intervalles: %(nbr)s"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:21
+#, python-format
+msgid "Largest range: %(largest)s (length: %(largest_len)s)"
+msgstr "Plus grand intervalle: %(largest)s (longueur: %(largest_len)s)"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:28
+#, python-format
+msgid "Number of sequences: %(nbr)s"
+msgstr "Nombre de séquences: %(nbr)s"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:34
+#, python-format
+msgid "Largest sequence: %(largest)s (length: %(largest_len)s)"
+msgstr "Plus grande séquence: %(largest)s (longueur: %(largest_len)s)"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:41
+msgid "Variants"
+msgstr "Variante(s)"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:44
+#, python-format
+msgid "Total number of variant mappings: %(nbr)s"
+msgstr "Nombre total de variantes mappées: %(nbr)s"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:49
+#, python-format
+msgid "Average number of variants per code point: %(nbr)s"
+msgstr "Nombre moyen de variantes par code point: %(nbr)s"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:54
+#, python-format
+msgid "Largest variant set: %(largest_set)s"
+msgstr "Plus grand ensemble de variantes: %(largest_set)s"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:60
+msgid "Variants per type:"
+msgstr "Variantes par type:"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:63
+#, python-format
+msgid "Number of variants for type %(variant_type)s: %(number)s"
+msgstr "Nombre de variantes pour le type %(variant_type)s: %(number)s"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:74
+#, python-format
+msgid "Number of code points for tag %(tag_name)s: %(number)s"
+msgstr "Nombre de code points pour le tag %(tag_name)s: %(number)s"
+
+#: templates/lgr_editor/validate_lgr/compute_stats.html:82
+#, python-format
+msgid "Number of defined rules: %(nbr)s"
+msgstr "Nombre de règles définies: %(nbr)s"
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:6
+#, python-format
+msgid "Unicode version %(version)s"
+msgstr "Version d'Unicode %(version)s"
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:8
+#, python-format
+msgid "Validating repertoire '%(repertoire)s'"
+msgstr "Répertoire de validation '%(repertoire)s'"
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:13
+#, python-format
+msgid ""
+"Target Unicode version %(version)s differs from UnicodeDatabase %(database)s"
+msgstr ""
+"La version Unicode cible %(version)s diffère de UnicodeDatabase %(database)s"
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:19
+msgid "Possibly erroneous characters"
+msgstr "Caractères possiblement erronés"
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:23
+#, python-format
+msgid "Character %(cp)s:"
+msgstr "Caractère %(cp)s:"
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:29
+#, python-format
+msgid "Warning: %(warn)s"
+msgstr "Attention : %(warn)s"
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:36
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:49
+#, python-format
+msgid "Error: %(err)s"
+msgstr "Erreur: %(err)s"
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:43
+#, python-format
+msgid "Variant: %(variant|render_char)s"
+msgstr "Variante: %(variant|render_char)s"
+
+#: templates/lgr_editor/validate_lgr/rebuild_lgr.html:60
+msgid "LGR rebuild OK"
+msgstr "Reconstruction de la LGR OK"
+
+#: views.py:115
msgid ""
"The LGR you have tried to create already exists in your working session. "
"Please use a new name."
@@ -829,7 +1144,7 @@ msgstr ""
"La LGR que vous essayez de créer existe déjà dans votre session de travail. "
"Merci d'utiliser un nouveau nom."
-#: views.py:148
+#: views.py:149
msgid ""
"The LGR you have tried to import already exists in your working session. "
"Please rename it before importing it."
@@ -837,7 +1152,7 @@ msgstr ""
"La LGR que vous essayez d'importer existe déjà dans votre session de "
"travail. Merci de renommer le fichier avant de l'importer."
-#: views.py:154
+#: views.py:155
msgid ""
"The LGR you have tried to import already exists in your set. Please rename "
"it before importing it."
@@ -845,67 +1160,91 @@ msgstr ""
"La LGR que vous essayez d'importer existe déjà dans votre ensemble. Merci de "
"renommer le fichier avant de l'importer."
-#: views.py:177
+#: views.py:178
msgid "The LGR set name already exists. Please use another name."
msgstr "Ce nom de set LGR existe déjà. Merci d'utiliser un autre nom."
-#: views.py:289
+#: views.py:249
+msgid "Testing XML validity using RNG"
+msgstr "Validation du XML par le RNG"
+
+#: views.py:250
+msgid "Testing symmetry"
+msgstr "Test de la symmétrie"
+
+#: views.py:251
+msgid "Testing transitivity"
+msgstr "Test de la transitivité"
+
+#: views.py:252
+msgid "Testing conditional variants"
+msgstr "Test des variantes conditionnelles"
+
+#: views.py:253
+msgid "Generate stats"
+msgstr "Génération des statistiques"
+
+#: views.py:254
+msgid "Rebuilding LGR"
+msgstr "Reconstruction de la LGR"
+
+#: views.py:302
#, python-format
msgid "New code point %s added"
msgstr "Nouveau code point ajouté %s"
-#: views.py:362
+#: views.py:375
msgid "Rule"
msgstr "Règle"
-#: views.py:362
+#: views.py:375
msgid "Tag(s)"
msgstr "Tag(s)"
-#: views.py:363
+#: views.py:376
msgid "rule"
msgstr "règle"
-#: views.py:363
+#: views.py:376
msgid "tag(s)"
msgstr "tag(s)"
-#: views.py:367
+#: views.py:380
#, python-format
msgid "%(operation)s successfully added to %(nb_cp)s code point(s)"
msgstr "%(operation)s ajouté(s) avec succès à %(nb_cp)s code point(s)"
-#: views.py:372
+#: views.py:385
#, python-format
msgid "%(nb_cp)s code points were not updated to avoid invalid %(operation)s"
msgstr ""
"%(nb_cp)s code points n'ont pas été mis à jour pour éviter des %(operation)s "
"invalides"
-#: views.py:504
+#: views.py:517
#, python-format
-msgid "Automatically added codepoint %s from out-of-repertoire variant"
+msgid "Automatically added codepoint %s from out-of-repertoire-var variant"
msgstr ""
"Code point %s automatiquement ajouté depuis une variante hors-répertoire"
-#: views.py:507
+#: views.py:520
#, python-format
msgid "New variant %s added"
msgstr "Nouvelle variante %s ajoutée"
-#: views.py:580
+#: views.py:593
msgid "Code point edited"
msgstr "Code point modifié"
-#: views.py:732
+#: views.py:745
msgid "Variants populated"
msgstr "Les variantes ont été peuplées"
-#: views.py:783 views.py:819
+#: views.py:798 views.py:834
msgid "References updated successfully"
msgstr "Les références ont été correctement mises à jour"
-#: views.py:822
+#: views.py:837
#, python-format
msgid ""
"Variant %(var_codepoint)s for code point %(codepoint)s with when=%(when)s "
@@ -914,33 +1253,33 @@ msgstr ""
"La variante %(var_codepoint)s du code point %(codepoint)s avec when="
"%(when)s et not-when=%(not_when)s n'a pas été trouvée"
-#: views.py:858
+#: views.py:873
#, python-format
msgid "Code point %s has been deleted"
msgstr "Le code point %s a été supprimé"
-#: views.py:880
+#: views.py:895
#, python-format
msgid "Variant %(var_cp)s with when='%(when)s' and not-when='%(not_when)s'"
msgstr ""
"La variante %(var_cp)s avec when='%(when)s' and not-when='%(not_when)s'"
-#: views.py:886
+#: views.py:901
#, python-format
msgid "%(var_msg_prefix)s has been deleted"
msgstr "%(var_msg_prefix)s a été supprimée"
-#: views.py:889
+#: views.py:904
#, python-format
msgid "%(var_msg_prefix)s could not be deleted because it was not found"
msgstr ""
"%(var_msg_prefix)s n'a pas pu être supprimée car elle n'a pas été trouvée"
-#: views.py:919
+#: views.py:934
msgid "New reference created"
msgstr "Nouvelle référence créée"
-#: views.py:1127
+#: views.py:1142
#, python-format
msgid ""
"References to tag %(tag)s have been removed from the repertoire. Do not "
@@ -949,30 +1288,30 @@ msgstr ""
"Les références au %(tag)s ont été supprimées du répertoire. N'oubliez pas de "
"mettre à jour les WLE qui pourraient les utiliser."
-#: views.py:1195 views.py:1357 views.py:1441
+#: views.py:1210 views.py:1372 views.py:1460
msgid "No body specified"
msgstr "Aucun contenu spécifié"
-#: views.py:1204
+#: views.py:1219
#, python-format
msgid "Class \"%s\" does not exist"
msgstr "La classe \"%s\" n'existe pas"
-#: views.py:1208
+#: views.py:1223
#, python-format
msgid "Class \"%s\" deleted."
msgstr "Classe \"%s\" supprimée."
-#: views.py:1213
+#: views.py:1228
msgid "No class element found"
msgstr "Aucune classe trouvée"
-#: views.py:1215 views.py:1377
+#: views.py:1230 views.py:1392
msgid "Name attribute must be present"
msgstr "L'attribut name est obligatoire"
-#: views.py:1219 views.py:1236 views.py:1381 views.py:1398 views.py:1465
-#: views.py:1478
+#: views.py:1234 views.py:1251 views.py:1405 views.py:1417 views.py:1484
+#: views.py:1497
#, python-format
msgid ""
"Encountered XML syntax error: %s (line number may be wrong, try subtracting "
@@ -981,72 +1320,86 @@ msgstr ""
"Erreur de syntaxe XML : %s (le numéro de ligne peut-être incorrect, essayer "
"de soustraire un au numéro reporté)"
-#: views.py:1222 views.py:1239 views.py:1384 views.py:1401 views.py:1468
-#: views.py:1481
+#: views.py:1237 views.py:1254 views.py:1408 views.py:1420 views.py:1487
+#: views.py:1500
msgid "Your XML is not valid"
msgstr "Votre XML n'est pas valide"
-#: views.py:1227
+#: views.py:1242
#, python-format
msgid "Class \"%s\" already exists"
msgstr "La classe \"%s\" existe déjà"
-#: views.py:1229
+#: views.py:1244
#, python-format
msgid "Class \"%s\" saved."
msgstr "Classe \"%s\" sauvegardée."
-#: views.py:1366
+#: views.py:1381
#, python-format
msgid "Rule \"%s\" does not exist"
msgstr "La règle \"%s\" n'existe pas"
-#: views.py:1370
+#: views.py:1385
#, python-format
msgid "Rule \"%s\" deleted."
msgstr "Règle \"%s\" supprimée."
-#: views.py:1375
+#: views.py:1390
msgid "No rule element found"
msgstr "Aucune règle trouvée"
-#: views.py:1389
+#: views.py:1397
#, python-format
msgid "Rule \"%s\" already exists"
msgstr "La règle \"%s\" existe déjà"
-#: views.py:1391
+#: views.py:1410
#, python-format
msgid "Rule \"%s\" saved."
msgstr "Règle \"%s\" sauvegardée."
-#: views.py:1452
+#: views.py:1471
#, python-format
msgid "Action \"%s\" does not exist"
msgstr "Action \"%s\" n'existe pas"
-#: views.py:1456
+#: views.py:1475
#, python-format
msgid "Action \"%s\" deleted."
msgstr "Action \"%s\" supprimée."
-#: views.py:1461
+#: views.py:1480
msgid "No action element found"
msgstr "Aucune action trouvée"
-#: views.py:1471
+#: views.py:1490
msgid "Action saved."
msgstr "Action sauvée."
-#: views.py:1540 views.py:1628
+#: views.py:1559 views.py:1647
#, python-format
msgid "%d code points added"
msgstr "%d code points ont été ajoutés"
-#: views.py:1597
+#: views.py:1616
msgid "No code point in input file"
msgstr "Le fichier d'entrée ne contient aucun code point"
-#: views.py:1903
+#: views.py:1922
msgid "Meta data saved"
msgstr "Metadonnées sauvegardées"
+
+#, fuzzy
+#~| msgid "Description"
+#~ msgid "%(description)s"
+#~ msgstr "Description"
+
+#~ msgid " with Unicode version {}"
+#~ msgstr " avec la version d'Unicode {}"
+
+#~ msgid " and validating repertoire '{}'"
+#~ msgstr " et le repertoire de validation '{}'"
+
+#~ msgid " "
+#~ msgstr " "
diff --git a/src/lgr_editor/repertoires.py b/src/lgr_editor/repertoires.py
index 398e7f9e..04abee39 100644
--- a/src/lgr_editor/repertoires.py
+++ b/src/lgr_editor/repertoires.py
@@ -12,26 +12,45 @@
from lgr.parser.xml_parser import XMLParser
from .utils import list_validating_repertoires
+from . import unidb
+
+from django.core.cache import cache
logger = logging.getLogger(__name__)
-REPERTOIRES = {}
-SCRIPTS = {}
+REPERTOIRE_CACHE_KEY = 'validating-repertoire'
+SCRIPTS_CACHE_KEY = 'scripts'
+CACHE_TIMEOUT = 3600*24*30
-def get_by_name(repertoire_name):
- if repertoire_name not in REPERTOIRES:
- logger.debug("%s parsing file", repertoire_name)
+def get_by_name(repertoire_name, with_unidb=False):
+ repertoire_cache_key = "{}{}".format(REPERTOIRE_CACHE_KEY, repertoire_name)
+ repertoire = cache.get(repertoire_cache_key)
+ logger.debug("Get repertoire by name %s", repertoire_name)
+ if not repertoire:
+ logger.info("%s parsing file as not in cache", repertoire_name)
repertoire_path = os.path.join(settings.REPERTOIRE_STORAGE_LOCATION, '{}.xml'.format(repertoire_name))
parser = XMLParser(repertoire_path, repertoire_name)
- doc = parser.parse_document()
- doc.expand_ranges() # need to get through all code points
- REPERTOIRES[repertoire_name] = doc
+ if with_unidb:
+ unicode_version = parser.unicode_version()
+ parser.unicode_database = unidb.manager.get_db_by_version(unicode_version)
+ repertoire = parser.parse_document()
+ repertoire.expand_ranges() # need to get through all code points
+ cache.set(repertoire_cache_key, repertoire, CACHE_TIMEOUT)
+ elif with_unidb:
+ # need to retrieve unicode database as it is not retrieved from cache
+ unicode_version = repertoire.metadata.unicode_version
+ repertoire.unicode_database = unidb.manager.get_db_by_version(unicode_version)
- return REPERTOIRES[repertoire_name]
+ return repertoire
def get_all_scripts_from_repertoire(unicode_database):
- if unicode_database not in SCRIPTS:
+ # XXX should we add database class name in cache key?
+ scripts_cache_key = "{}:{}".format(SCRIPTS_CACHE_KEY, unicode_database.get_unicode_version())
+ scripts = cache.get(scripts_cache_key)
+ logger.debug("Get scripts for Unicode %s", unicode_database.get_unicode_version())
+ if not scripts:
+ logger.info("Scripts not in cache")
scripts = set()
for rep in list_validating_repertoires():
validating_repertoire = get_by_name(rep)
@@ -46,6 +65,6 @@ def get_all_scripts_from_repertoire(unicode_database):
unicode_database.get_unicode_version(),
e)
- SCRIPTS[unicode_database] = scripts
+ cache.set(scripts_cache_key, scripts, CACHE_TIMEOUT)
- return SCRIPTS[unicode_database]
+ return scripts
diff --git a/src/lgr_editor/templates/lgr_editor/_form_field.html b/src/lgr_editor/templates/lgr_editor/_form_field.html
index 41c479b1..9c61768c 100644
--- a/src/lgr_editor/templates/lgr_editor/_form_field.html
+++ b/src/lgr_editor/templates/lgr_editor/_form_field.html
@@ -1,8 +1,11 @@
{% load widget_tweaks %}
-
- {{ field|add_class:"form-control" }}
+
+ {{ field|add_class:"form-control" }}
+ {% if field.field.widget.input_type == 'text' %}
+
+ {% endif %}
{% if field.errors %}
{% for error in field.errors %}{{ error }}{% endfor %}
@@ -14,3 +17,8 @@
{% endif %}
+
\ No newline at end of file
diff --git a/src/lgr_editor/templates/lgr_editor/codepoint_list.html b/src/lgr_editor/templates/lgr_editor/codepoint_list.html
index e7ca933c..b4b6e091 100644
--- a/src/lgr_editor/templates/lgr_editor/codepoint_list.html
+++ b/src/lgr_editor/templates/lgr_editor/codepoint_list.html
@@ -79,7 +79,7 @@
{% trans "Add Rule" %}
-
{% trans "Add Rule" %}
+
{% trans "Add Tags" %}
{% include "lgr_editor/_form_field.html" with field=edit_codepoints_form.tags %}
diff --git a/src/lgr_editor/templates/lgr_editor/label_forms.html b/src/lgr_editor/templates/lgr_editor/label_forms.html
index 75d4ca5e..fad6dab9 100644
--- a/src/lgr_editor/templates/lgr_editor/label_forms.html
+++ b/src/lgr_editor/templates/lgr_editor/label_forms.html
@@ -5,11 +5,9 @@
{% block content %}
{% if u_label %}
diff --git a/src/lgr_editor/templates/lgr_editor/metadata.html b/src/lgr_editor/templates/lgr_editor/metadata.html
index 401ad2f2..cb6cb57c 100644
--- a/src/lgr_editor/templates/lgr_editor/metadata.html
+++ b/src/lgr_editor/templates/lgr_editor/metadata.html
@@ -1,6 +1,18 @@
{% extends "lgr_editor/_editor_base.html" %}
{% load i18n %}
+{% block html_head_more %}
+ {{ block.super }}
+
+
+{% endblock %}
+
{% block pane-md-active %}active{% endblock %}
{% block content-pane %}
@@ -14,6 +26,7 @@
{% include "lgr_editor/_form_field.html" with field=form.version_comment %}
{% include "lgr_editor/_form_field.html" with field=form.date %}
{{ language_formset.management_form }}
+ {{ language_formset.media }}
{% for langform in language_formset %}
{% for field in langform %}
{% include "lgr_editor/_form_field.html" %}
diff --git a/src/lgr_editor/templates/lgr_editor/validate_lgr/check_conditional_variants.html b/src/lgr_editor/templates/lgr_editor/validate_lgr/check_conditional_variants.html
index 3c85b670..a553261e 100644
--- a/src/lgr_editor/templates/lgr_editor/validate_lgr/check_conditional_variants.html
+++ b/src/lgr_editor/templates/lgr_editor/validate_lgr/check_conditional_variants.html
@@ -1,15 +1,20 @@
{% extends "lgr_editor/validate_lgr/_base.html" %}
+{% load i18n static %}
{% load lgr_editor %}
{% block result_contents %}
{% if result.repertoire %}
-
Erroneous conditional code points
+
{% trans "Erroneous conditional code points" %}
{% for entry in result.repertoire %}
-
Code point {{ entry.char|render_char }} has invalid {{ entry.rule_type }} rule {{ entry.rule }} for variant {{ entry.variant|render_char }}
+
+ {% blocktrans trimmed with cp=entry.char|render_char rule_type=entry.rule_type rule=entry.rule variant=entry.variant|render_char %}
+ Code point {{ cp }} has invalid {{ rule_type }} rule {{ rule }} for variant {{ variant }}
+ {% endblocktrans %}
+
{% endfor %}
{% else %}
- Conditional variants OK
+ {% trans "Conditional variants OK" %}
{% endif %}
{% endblock %}
\ No newline at end of file
diff --git a/src/lgr_editor/templates/lgr_editor/validate_lgr/check_symmetry.html b/src/lgr_editor/templates/lgr_editor/validate_lgr/check_symmetry.html
index be559097..30a4f3b3 100644
--- a/src/lgr_editor/templates/lgr_editor/validate_lgr/check_symmetry.html
+++ b/src/lgr_editor/templates/lgr_editor/validate_lgr/check_symmetry.html
@@ -1,21 +1,37 @@
{% extends "lgr_editor/validate_lgr/_base.html" %}
+{% load i18n static %}
{% load lgr_editor %}
{% block result_contents %}
{% if result.repertoire %}
-
Missing code points
+
{% trans "Missing code points or rules" %}
{% for entry in result.repertoire %}
-
Code point {{ entry.char|render_char }}:
+
+ {% blocktrans trimmed with cp=entry.char|render_char %}
+ Code point {{ cp }}:
+ {% endblocktrans %}
{% if entry.type == 'not-in-repertoire' %}
- Variant {{ entry.variant|render_char }} is not in repertoire
- {% else %}
- {{ entry.variant|render_char }} has not original code point in its variants
+ {% blocktrans trimmed with variant=entry.variant|render_char %}
+ Variant {{ variant }} is not in repertoire
+ {% endblocktrans %}
+ {% elif entry.type == 'missing-symmetric-variant' %}
+ {% blocktrans trimmed with variant=entry.variant|render_char %}
+ {{ variant }} has not original code point in its variants
+ {% endblocktrans %}
+ {% elif entry.type == 'variant-contextual-rule-missing' %}
+ {% blocktrans trimmed with rule_type=entry.rule_type rule=entry.rule variant=entry.variant|render_char %}
+ {{ variant }} has not symmetric {{ rule_type }} rule {{ rule }} on its symmetric variants
+ {% endblocktrans %}
+ {% else %}
+ {% blocktrans trimmed with variant=entry.variant|render_char %}
+ {{ variant }} unknown symmetry problem, please report
+ {% endblocktrans %}
{% endif %}
{% endfor %}
{% else %}
- Symmetry OK
+ {% trans "Symmetry OK" %}
{% endif %}
{% endblock %}
\ No newline at end of file
diff --git a/src/lgr_editor/templates/lgr_editor/validate_lgr/check_transitivity.html b/src/lgr_editor/templates/lgr_editor/validate_lgr/check_transitivity.html
index d10b56ba..192c42af 100644
--- a/src/lgr_editor/templates/lgr_editor/validate_lgr/check_transitivity.html
+++ b/src/lgr_editor/templates/lgr_editor/validate_lgr/check_transitivity.html
@@ -1,15 +1,20 @@
{% extends "lgr_editor/validate_lgr/_base.html" %}
+{% load i18n static %}
{% load lgr_editor %}
{% block result_contents %}
{% if result.repertoire %}
-
Missing variants
+
{% trans "Missing variants" %}
{% for entry in result.repertoire %}
-
Code point {{ entry.char|render_char }} is missing variant {{ entry.variant|render_char }}
+
+ {% blocktrans trimmed with cp=entry.char|render_char variant=entry.variant|render_char %}
+ Code point {{ cp }} is missing variant {{ variant }}
+ {% endblocktrans %}
+
{% endfor %}
{% else %}
- Transitivity OK
+ {% trans "Transitivity OK" %}
{% endif %}
{% endblock %}
\ No newline at end of file
diff --git a/src/lgr_editor/templates/lgr_editor/validate_lgr/check_xml_validity.html b/src/lgr_editor/templates/lgr_editor/validate_lgr/check_xml_validity.html
index 52527e23..f8f0c82e 100644
--- a/src/lgr_editor/templates/lgr_editor/validate_lgr/check_xml_validity.html
+++ b/src/lgr_editor/templates/lgr_editor/validate_lgr/check_xml_validity.html
@@ -1,10 +1,13 @@
{% extends "lgr_editor/validate_lgr/_base.html" %}
+{% load i18n static %}
{% load lgr_editor %}
{% block result_contents %}
{% if result.rng_result %}
- XML is valid and complies with RNG.
+ {% trans "XML is valid and complies with RNG." %}
{% else %}
- Invalid XML for lgr: {{ result.validation_result|linebreaks }}
+ {% blocktrans trimmed with res=result.validation_result|linebreaks %}
+ Invalid XML for lgr: {{ res }}
+ {% endblocktrans %}
{% endif %}
{% endblock %}
\ No newline at end of file
diff --git a/src/lgr_editor/templates/lgr_editor/validate_lgr/compute_stats.html b/src/lgr_editor/templates/lgr_editor/validate_lgr/compute_stats.html
index 6004f9bf..63f14228 100644
--- a/src/lgr_editor/templates/lgr_editor/validate_lgr/compute_stats.html
+++ b/src/lgr_editor/templates/lgr_editor/validate_lgr/compute_stats.html
@@ -1,33 +1,66 @@
{% extends "lgr_editor/validate_lgr/_base.html" %}
+{% load i18n static %}
{% load lgr_editor %}
{% block result_contents %}
-
General stats
+
{% trans "General stats" %}
-
Number of code points: {{ result.stats.codepoint_number }}
+
+ {% blocktrans trimmed with nbr=result.stats.codepoint_number %}
+ Number of code points: {{ nbr }}
+ {% endblocktrans %}
+
-
Number of ranges: {{ result.stats.range_number }}
+
+ {% blocktrans trimmed with nbr=result.stats.range_number %}
+ Number of ranges: {{ nbr }}
+ {% endblocktrans %}
+
{% if result.stats.range_number > 0 %}
-
Largest range: {{ result.stats.largest_range|render_char }} (length: {{ result.stats.largest_range_len }})
+
+ {% blocktrans trimmed with largest=result.stats.largest_range|render_char largest_len=result.stats.largest_range_len %}
+ Largest range: {{ largest }} (length: {{ largest_len }})
+ {% endblocktrans %}
+
{% endif %}
-
Number of sequences: {{ result.stats.sequence_number }}
+
+ {% blocktrans trimmed with nbr=result.stats.sequence_number %}
+ Number of sequences: {{ nbr }}
+ {% endblocktrans %}
+
{% if result.stats.sequence_number > 0 %}
-
Largest sequence: {{ result.stats.largest_sequence|render_char }} (length: {{ result.stats.largest_sequence_len }})
+
+ {% blocktrans trimmed with largest=result.stats.largest_sequence|render_char largest_len=result.stats.largest_sequence_len %}
+ Largest sequence: {{ largest }} (length: {{ largest_len }})
+ {% endblocktrans %}
+
{% endif %}
-
Variants
+
{% trans "Variants" %}
-
Total number of variant mappings: {{ result.stats.mapping_number }}
-
Average number of variants per code point: {{ result.stats.average_variants }}
-
Largest variant set: {{ result.stats.largest_variant_set }}
+
+ {% blocktrans trimmed with nbr=result.stats.mapping_number %}
+ Total number of variant mappings: {{ nbr }}
+ {% endblocktrans %}
+
+
+ {% blocktrans trimmed with nbr=result.stats.average_variants %}
+ Average number of variants per code point: {{ nbr }}
+ {% endblocktrans %}
+
+
+ {% blocktrans trimmed with largest_set=result.stats.largest_variant_set %}
+ Largest variant set: {{ largest_set }}
+ {% endblocktrans %}
+
{% if result.stats.variants_by_type %}
- Variants per type:
+ {% trans "Variants per type:" %}
{% for variant_type, number in result.stats.variants_by_type.items %}
-
Number of variants for type {{ variant_type }}: {{ number }}
+
{% blocktrans %}Number of variants for type {{ variant_type }}: {{ number }}{% endblocktrans %}
{% endfor %}
@@ -35,16 +68,20 @@
Variants
{% if result.stats.codepoints_by_tag %}
-
Tags
+
{% trans "Tags" %}
{% for tag_name, number in result.stats.codepoints_by_tag.items %}
-
Number of code points for tag {{ tag_name }}: {{ number }}
+
{% blocktrans %}Number of code points for tag {{ tag_name }}: {{ number }}{% endblocktrans %}
{% endfor %}
{% endif %}
-
Rules
+
{% trans "Rules" %}
-
Number of defined rules: {{ result.stats.rule_number }}
+
+ {% blocktrans trimmed with nbr=result.stats.rule_number %}
+ Number of defined rules: {{ nbr }}
+ {% endblocktrans %}
+
{% endblock %}
\ No newline at end of file
diff --git a/src/lgr_editor/templates/lgr_editor/validate_lgr/rebuild_lgr.html b/src/lgr_editor/templates/lgr_editor/validate_lgr/rebuild_lgr.html
index ffa0dad0..c3df9964 100644
--- a/src/lgr_editor/templates/lgr_editor/validate_lgr/rebuild_lgr.html
+++ b/src/lgr_editor/templates/lgr_editor/validate_lgr/rebuild_lgr.html
@@ -1,20 +1,55 @@
{% extends "lgr_editor/validate_lgr/_base.html" %}
+{% load i18n static %}
{% load lgr_editor %}
{% block result_contents %}
+
{% blocktrans with version=result.unicode_version %}Unicode version {{ version }}{% endblocktrans %}
+
+ {# collision if this is a LGR set but not an LGR in a set #}
+ {% if result.collisions_checked and is_set and not lgr_set_id or result.collisions_checked and not is_set %}
+
+ {% if result.collisions_error or result.collision %}
+
+ {% endif %}
+
+ {# Only display variants if label is eligible and no collision for sets #}
+ {% if result.eligible and not result.collisions_error and not result.collision or result.eligible and not is_set %}
+
+
+
{% trans "Variant labels" %}{% if result.num_variants %}{% trans " (including original as last)" %}{% endif %}
+ {% endfor %}
+
+ {% elif result.num_variants > result.threshold_include_vars %}
+ {% if not is_set or lgr_set_id %} {# TODO Remove download at the moment as we cannot retrieve label file here #}
+
+
+ {% blocktrans trimmed %}
+ Too many variant labels to be displayed in the browser. Please download the results in .csv instead.
+ {% endblocktrans %}
+
+
+ {% endif %}
+ {% endif %}
+
+ {% endif %}
+
+ {% if result.num_variants > result.threshold_include_vars %}
+ {# TODO: Need to pass set_labels along #}
+ {% if lgr_set_id %}
+ {% url 'lgr_validate_csv' lgr_set_id=lgr_set_id lgr_id=lgr_id as lgr_validate_csv_url %}
+ {% else %}
+ {% url 'lgr_validate_csv' lgr_id=lgr_id as lgr_validate_csv_url %}
+ {% endif %}
+ {% if not is_set or lgr_set_id %} {# TODO Remove download at the moment as we cannot retrieve label file here #}
+
+
+ {% blocktrans %}Download results in CSV{% endblocktrans %}
+
+ {% endif %}
+ {% endif %}
+
+ {% endif %}
+{% endblock content %}
+