diff --git a/Release_Notes.md b/Changelog.md similarity index 58% rename from Release_Notes.md rename to Changelog.md index db55bcd4..ca6dfea1 100644 --- a/Release_Notes.md +++ b/Changelog.md @@ -1,4 +1,67 @@ -# LGR-Toolset Release notes +# Changelog for lgr-django + +## 2.0.0 (2018-09-06) +### New features +- Support of Python 3. Compatibility with python2 is preserved for this release. +- Add MSR-3 validating repertoire. +- Create a "Tag" management page. +- Create a function to assign tags/WLE to code points. +- Allow choosing reference id when adding reference in editor. +- Add tags in code point list view. +### Improvements +- Improve display of LGR validation when rebuild is valid. +- Catch exceptions generated when input file is not a UTF-8 encoded file. +- Add required file encoding on label fields in forms. +- Update harmonization tool. +- When adding an out-of-repertoire variant, automatically add it to the repertoire + add the mapping to the code point. +- Improve wording of landing page. +- Improve handling of output for comparison tools for large LGRs. +- Update variant type to blocked for sample French LGR. +- Add notice that import function is permissive. +- Remove length limitation on label validation. Process will be run asynchronously if label can generate too many variants. +- Export testing of variant symmetry and transitivity in AJAX view. +- Add combined form of sequences in HTML output. +- Sort resource/repertoire file lists. +- Remove script parameter for harmonization tools. +- Display rule name(s) when a code point does not comply with a contextual rule. +- Better notification for invalid language tags. +- Better consistency on forms' labels. +### Fixes +- Fix redirection when adding a code point fails. +- Fix link to label in "Validate label" view. +- Remove references from repertoire on deletion. +- Replace number of variants by number of variant mappings in LGR validation statistics. +- Add proper error message when adding a tag to a sequence. +- Add support for missing language exception. +- Fix script retrievals from repertoires. +- Do not display useless error message when editing existing references. +- Fix creation of references from code point/variant edition screen. +- Fix deletion of action. +- Display code points in hexadecimal in HTML output. +- Add identity mapping for newly added variants not present in repertoire. +- Fix header hiding page content. +- Catch error in HTML output on ill-formed LGR's WLE. + +## 1.9 (2017-03-09) +New features: +- New interface to view all forms of a label: display the U-label, A-label and code point sequence. +- Display the combined form of sequences. +- New tool to check that multiple LGRs are harmonized. +- New function to populate the missing symmetric and transitive variants. +- New function to add code point from a script. +- When adding a variant from another script, automatically add it to the repertoire if not present. +Fixes: +- Improve handling of large LGR. +- Fix variant type that could be be changed from "blocked". +- Fix label validation with ranges. +- Always display failed rule when validating a label. +- Improve display for summary (now renamed to LGR validation). +- Fix tag count in HTML output. +- Fix variant member count in HTML output. +- Use hyperlinks for the table of references in HTML output. +- Reduce number of rows in the variant set table in HTML output. +- Add number of mappings on variant set table in HTML output. +- Add link to save HTML output. ## 1.8.1 (2017-11-15) Fixes: diff --git a/Installation_Guide.md b/Installation_Guide.md index 64b9c9bc..2a7ff347 100644 --- a/Installation_Guide.md +++ b/Installation_Guide.md @@ -25,15 +25,11 @@ Install the nginx webserver used to serve as a frontend. On CentOS, you need to enable the EPEL repository before: # yum install epel-release - # yum install nginx + # yum install nginx redis Install virtualenv, used to create the Python environment: - # yum install python-virtualenv - -Install the dependencies needed to build the lxml module: - - # yum install make gcc libxml2-devel libxslt-devel + # yum install python34-virtualenv Create a new user/group that will be used to run the application, as well as the log directory where log files will be placed: @@ -55,7 +51,7 @@ and `lgr-django`) in a specific directory, and extract web-application: Create and configure the virtualenv: - $ virtualenv-2.7 /var/www/lgr/venv + $ virtualenv-3 /var/www/lgr/venv $ source /var/www/lgr/venv/bin/activate (venv)$ cd /var/www/lgr/lgr-django (venv)$ pip install -r etc/requirements.txt -f /var/www/lgr/packages @@ -64,17 +60,6 @@ Also install the application server: (venv)$ pip install gunicorn -Note: you may see the following error during the installation: - - File "/var/www/lgr/venv/lib/python2.7/site-packages/gunicorn/workers/_gaiohttp.py", line 68 - yield from self.wsgi.close() - ^ - SyntaxError: invalid syntax - -The error can be ignored, and gunicorn will still be installed sucessfully. -See [https://github.com/benoitc/gunicorn/issues/788](https://github.com/benoitc/gunicorn/issues/788). - - ## ICU installation If your distribution ships ICU, install it using the package manager. @@ -93,6 +78,10 @@ For example, to install ICU 52 (Unicode 6.3), as root: The current supported ICU versions (and their corresponding Unicode version) are: +* ICU 60 (Unicode 10.0) +* ICU 58 (Unicode 9.0) +* ICU 56 (Unicode 8.0) +* ICU 54 (Unicode 7.0) * ICU 52 (Unicode 6.3) * ICU 50 (Unicode 6.2) * ICU 49 (Unicode 6.1) @@ -107,6 +96,21 @@ binary packages from ICU website): # echo "/usr/local/lib" > /etc/ld.so.conf.d/lgr.conf # ldconfig +### Latest ICU versions + +Starting from ICU 58 (Unicode 9.0.0), binary distributions of ICU require a newer C++ runtime that what is available on Centos7. +You will need to recompile the library in order to support the newer versions. + + # yum install gcc gcc-c++ + # mkdir icu-60 ; cd icu-60 + # wget http://download.icu-project.org/files/icu4c/60.2/icu4c-60_2-src.tgz + # tar xvf icu4c-60_2-src.tgz + # mkdir build ; cd build + # # You should switch to an unpriviledged user to compile + # ../icu/source/runConfigureICU Linux + # make check + # make install + ## Django Configuration A template for production configuration is provided: @@ -169,6 +173,7 @@ To serve the application, the following architecture in used: * The celery application is used to launch background tasks. * The gunicorn application server is used to run the python code. +* A redis server is used to store messages between the webapp interface and the celery application. * The nginx webserver will act as a frontend proxy as well as serving static content. * Requests related to the application are relayed to the gunicorn server. @@ -195,7 +200,7 @@ Also copy the temporary files configuration and create them: # cp /var/www/lgr/lgr-django/etc/systemd/lgr-django.conf /etc/tmpfiles.d/ # systemd-tmpfiles --create -Reload systemd daemon and enable and start the gunicorn process: +Reload systemd daemon and enable and enable/start the following processes: # systemctl daemon-reload # systemctl enable lgr-django diff --git a/README.md b/README.md index 7bddb62f..17c95964 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ The following modules are reusable Django apps that can be included in other Dja * `lgr_editor` contains the code related to the LGR web-editor. * `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_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). ## Acknowledgment @@ -53,7 +53,7 @@ THE POSSIBILITY OF SUCH DAMAGE. ### Pre-requisites * Operating system: Tested on Linux and Mac OS X -* Python 2.7 +* Python 2.7, >= 3.4 * [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) @@ -65,7 +65,8 @@ THE POSSIBILITY OF SUCH DAMAGE. * [picu](https://pypi.python.org/pypi/picu) [MIT/X License] * [munidata](https://github.com/icann/munidata) [BSD License] * [natsort](https://pypi.python.org/pypi/natsort) [MIT License] -* A [redis](https://redis.io/) server for asynchronous computations + * [django-redis-cache](https://github.com/sebleier/django-redis-cache) [BSD License] +* A [redis](https://redis.io/) server for cache and asynchronous computations For documentation generation: @@ -203,47 +204,6 @@ of each Unicode version that we support. Keys are the Unicode version, like '6.3.0' Values are a dict of the kwargs to pass to the `munidata.manager.register` function along with the version. -## Deploying application on a Docker image - -### Pre-requisites - -* Install Docker (version 1.9). -* Copy the tarball archives of the project (lgr-core, lgr-django, munidata, picu) in the docker folder. - -### Create the Docker image - -The Docker image name and tag are set with the -t option name:tag. -Tag is optional (default: latest). - -Build arguments are specific options for our Docker image. -At the moment you can configure the allowed hosts for Django with the hosts argument and some e-mail parameters (server address and sender). - - # cd docker - # docker build -t lgr-toolset --build-arg hosts="lgr.example" --build-arg email_srv="email-srv.lgr.example" --build-arg email_from="webmaster@lgr.example" . - -### Run the Docker image - -The Docker image name and tag should be the same as in build command to run the -relevant container. - -The -h option should contain an allowed host specified in the hosts argument -when building the container. - - # docker run -h lgr.example -d -p 80:80 lgr-toolset - -### Debug the Docker image - -The following command allows to get a bash shell in the Docker image in order to perform debug operations: - - # docker run -h lgr.example -p 80:80 -i -t lgr-toolset bash - -Then to launch the server in the Docker image run: - - # ./start.sh & - -You can now debug the Docker image. - - ## Deploying application to production Please see Installation\_Guide diff --git a/bin/bootstrap b/bin/bootstrap index aa910c61..1694ccac 100755 --- a/bin/bootstrap +++ b/bin/bootstrap @@ -5,7 +5,7 @@ DSITE="src/lgr_web" if [ ! -e venv ]; then echo "==> Creating virtualenv" - virtualenv2 venv || exit 3 + virtualenv venv || exit 3 fi # activate virtualenv diff --git a/bin/gen_secret_key b/bin/gen_secret_key index a8f61bd6..60c8e1c9 100755 --- a/bin/gen_secret_key +++ b/bin/gen_secret_key @@ -1,4 +1,5 @@ #!/usr/bin/env python +from __future__ import print_function from random import choice @@ -31,4 +32,4 @@ def write_secret_key(path): if __name__ == '__main__': - print gen_secret_key() + print(gen_secret_key()) diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index 44dd535d..00000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,77 +0,0 @@ -FROM centos:7 -MAINTAINER ICANN - -# System configuration -#RUN setenforce 0 -RUN yum makecache \ - && yum install -y epel-release \ - && yum makecache \ - && yum install -y nginx python-pip python-devel make gcc libxml2-devel libxslt-devel redis \ - && yum clean all - -ENV HOME=/var/www/lgr -RUN mkdir ${HOME}/packages -p; mkdir /var/log/lgr/ -COPY picu-*.tar.gz munidata-*.tar.gz lgr-core-*.tar.gz lgr-django-*.tar.gz ${HOME}/packages/ -RUN mkdir ${HOME}/lgr-django; tar xvf ${HOME}/packages/lgr-django-*.tar.gz -C ${HOME}/lgr-django --strip-components=1 -WORKDIR ${HOME}/lgr-django -RUN pip install -r etc/requirements.txt -f ${HOME}/packages; pip install gunicorn - -# ICU installation -RUN mkdir /root/icu -WORKDIR /root/icu -ENV SHA256SUM_ICU442="8d3f5a0f7007b3863bfeeec4aa517e656b24972320995011e35bed45910144bd" \ - SHA256SUM_ICU461="07b862bc3ad7940445944ce2cd878d8e3386d119364d980bfc465d4ca096c74b" \ - SHA256SUM_ICU4912="7baea4a62db244267708947b52445fd11a69617180406734020a7991278a2bca" \ - SHA256SUM_ICU501="adbc30e891de409e1ff5c8a03ee925b60b3342742f6c6f41dc6684d821c18e6f" \ - SHA256SUM_ICU521="2a73302fa3556a113cd5e3de9c14cf6fc39e308fbe6970af6d84d723bf2c66a3" -RUN curl -OL http://download.icu-project.org/files/icu4c/4.4.2/icu4c-4_4_2-RHEL52-x64.tgz && \ - echo $SHA256SUM_ICU442 icu4c-4_4_2-RHEL52-x64.tgz | sha256sum -c - && \ - tar -xz -f icu4c-4_4_2-RHEL52-x64.tgz -C / --wildcards usr/local/lib/*.44* && \ - curl -OL http://download.icu-project.org/files/icu4c/4.6.1/icu4c-4_6_1-RHEL6-x64.tgz && \ - echo $SHA256SUM_ICU461 icu4c-4_6_1-RHEL6-x64.tgz | sha256sum -c - && \ - tar -xz -f icu4c-4_6_1-RHEL6-x64.tgz -C / --wildcards usr/local/lib/*.46* && \ - curl -OL http://download.icu-project.org/files/icu4c/49.1.2/icu4c-49_1_2-RHEL6-x64.tgz && \ - echo $SHA256SUM_ICU4912 icu4c-49_1_2-RHEL6-x64.tgz | sha256sum -c - && \ - tar -xz -f icu4c-49_1_2-RHEL6-x64.tgz -C / --wildcards usr/local/lib/*.49* && \ - curl -OL http://download.icu-project.org/files/icu4c/50.1/icu4c-50_1-RHEL6-x64.tgz && \ - echo $SHA256SUM_ICU501 icu4c-50_1-RHEL6-x64.tgz | sha256sum -c - && \ - tar -xz -f icu4c-50_1-RHEL6-x64.tgz -C / --wildcards usr/local/lib/*.50* && \ - curl -OL http://download.icu-project.org/files/icu4c/52.1/icu4c-52_1-RHEL6-x64.tgz && \ - echo $SHA256SUM_ICU521 icu4c-52_1-RHEL6-x64.tgz | sha256sum -c - && \ - tar -xz -f icu4c-52_1-RHEL6-x64.tgz -C / --wildcards usr/local/lib/*.52* && \ - echo "/usr/local/lib" > /etc/ld.so.conf.d/lgr.conf && ldconfig - -# Django, Gunicorn and nginx configuration -ARG hosts="" -ARG email_srv="" -ARG email_from="" -# TODO allow adjusting the following values as well - #SUPPORTED_UNICODE_VERSIONS - #UNICODE_DATABASES - #REPERTOIRE_STORAGE_LOCATION - #LGR_STORAGE_LOCATION - #LGR_RNG_FILE - #SESSION_COOKIE_SECURE - #CSRF_COOKIE_SECURE - -WORKDIR ${HOME}/lgr-django -COPY start.sh . -RUN sed -i "s#WORKDIR_TO_REPLACE#${HOME}/lgr-django#" start.sh; \ - cp ${HOME}/lgr-django/src/lgr_web/settings/deploy.py.template \ - ${HOME}/lgr-django/src/lgr_web/settings/local.py; \ - sed -i "s/ALLOWED_HOSTS = \[\]/ALLOWED_HOSTS = \[\"${hosts}\"\]/g" \ - ${HOME}/lgr-django/src/lgr_web/settings/local.py; \ - # TODO the following field are actually in comment so we can do that - echo "EMAIL_HOST = \"${email_srv}\"" >> ${HOME}/lgr-django/src/lgr_web/settings/local.py; \ - echo "DEFAULT_FROM_EMAIL = \"${email_from}\"" >> ${HOME}/lgr-django/src/lgr_web/settings/local.py; \ - echo "SESSION_COOKIE_SECURE = False" >> ${HOME}/lgr-django/src/lgr_web/settings/local.py; \ - echo "CSRF_COOKIE_SECURE = False" >> ${HOME}/lgr-django/src/lgr_web/settings/local.py; \ - python ./manage.py migrate; python ./manage.py collectstatic --noinput; \ - mkdir /run/lgr; \ - cp ${HOME}/lgr-django/etc/nginx/lgr-django.conf /etc/nginx/conf.d/nginx-django.conf; \ - sed -i "s/server_name.*/server_name ${hosts};/g" /etc/nginx/conf.d/nginx-django.conf - -EXPOSE 80 -#EXPOSE 443 -CMD ["/bin/bash", "start.sh"] - diff --git a/docker/start.sh b/docker/start.sh deleted file mode 100755 index c042abb4..00000000 --- a/docker/start.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -redis-server --daemonize yes -/usr/bin/gunicorn --error-log /var/log/lgr/gunicorn-lgr.log -w 3 -t 300 --max-requests 100 -b unix:/run/lgr/lgr-django.sock --chdir ${HOME}/lgr-django/src lgr_web.wsgi:application & -celery --app=lgr_tools --workdir=WORKDIR_TO_REPLACE/src -D --concurrency=1 --logfile=/var/log/lgr/celery-lgr.log worker & -exec nginx -g 'daemon off;' diff --git a/etc/requirements.txt b/etc/requirements.txt index af700164..bc3a9309 100644 --- a/etc/requirements.txt +++ b/etc/requirements.txt @@ -3,11 +3,12 @@ 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 # LGR/Unicode modules -picu==0.8 -munidata==1.2 -lgr-core==1.8.1 +picu==1.0 +munidata==2.0.0 +lgr-core==2.0.0 # Natural sorting implementation natsort==5.0.3 diff --git a/etc/systemd/lgr-django.service b/etc/systemd/lgr-django.service index 313383ce..00a915fe 100644 --- a/etc/systemd/lgr-django.service +++ b/etc/systemd/lgr-django.service @@ -1,7 +1,8 @@ [Unit] Description=LGR Django application After=network.target -Wants=lgr-celery.service +Wants=lgr-celery.service redis.service +After=redis.service [Service] WorkingDirectory=/var/www/lgr/lgr-django diff --git a/kubernetes/Dockerfile b/kubernetes/Dockerfile index c92904f8..44503308 100644 --- a/kubernetes/Dockerfile +++ b/kubernetes/Dockerfile @@ -18,9 +18,9 @@ LABEL com.example.component="$COMPONENT" \ run="/usr/bin/docker run -d -P 5000:5000 lgrtool-kubernetes"\ maintainer="Patrick Tudor https://github.com/ptudor" -ENV commit_lgr_django="v1.8.1" \ - commit_lgr_core="v1.8.1" \ - commit_munidata="v1.2" +ENV commit_lgr_django="v2.0.0" \ + commit_lgr_core="v2.0.0" \ + commit_munidata="v2.0.0" RUN echo "== prepare apache, redis, and others." \ && echo not with fedora, only centos: yum -y install epel-release \ @@ -92,6 +92,10 @@ ENV SHA256SUM_ICU442="8d3f5a0f7007b3863bfeeec4aa517e656b24972320995011e35bed4591 SHA256SUM_ICU4912="7baea4a62db244267708947b52445fd11a69617180406734020a7991278a2bca" \ SHA256SUM_ICU501="adbc30e891de409e1ff5c8a03ee925b60b3342742f6c6f41dc6684d821c18e6f" \ SHA256SUM_ICU521="2a73302fa3556a113cd5e3de9c14cf6fc39e308fbe6970af6d84d723bf2c66a3" \ + SHA256SUM_ICU541="c5ff22b96ecda87f2dd6e424346bedc6a6321c0bd56d8ad925f273f8361c7dd6" \ + SHA256SUM_ICU561="c3f9f1d85d0f0d5e6416f28bf5bee833a01e48521b16a5f65760c025a4d4e18e" \ + SHA256SUM_ICU582="daf5ec865026613d3da5309b47041ae7b581f3b601efcd4ddc23ad3afde2534f" \ + SHA256SUM_ICU602="cbd8281ccfa2d70f72b5bd2d7a411ffe573c6684e9e23ee3b289f76de3a05e30" \ LGR_HOME=/var/www/lgr # primary section for lgr-django and dependencies @@ -133,6 +137,18 @@ RUN export CFLAGS="-O2 -mtune=generic" \ && curl -OL http://download.icu-project.org/files/icu4c/52.1/icu4c-52_1-RHEL6-x64.tgz \ && echo $SHA256SUM_ICU521 icu4c-52_1-RHEL6-x64.tgz | sha256sum -c - \ && tar -xz -f icu4c-52_1-RHEL6-x64.tgz -C / --wildcards usr/local/lib/*.52* \ + && curl -OL http://download.icu-project.org/files/icu4c/54.1/icu4c-54_1-RHEL6-x64.tgz \ + && echo $SHA256SUM_ICU541 icu4c-54_1-RHEL6-x64.tgz | sha256sum -c - \ + && tar -xz -f icu4c-54_1-RHEL6-x64.tgz -C / --wildcards usr/local/lib/*.54* \ + && curl -OL http://download.icu-project.org/files/icu4c/56.1/icu4c-56_1-RHEL6-x64.tgz \ + && echo $SHA256SUM_ICU561 icu4c-56_1-RHEL6-x64.tgz | sha256sum -c - \ + && tar -xz -f icu4c-56_1-RHEL6-x64.tgz -C / --wildcards usr/local/lib/*.56* \ + && curl -OL http://download.icu-project.org/files/icu4c/58.2/icu4c-58_2-Fedora24-x64.tgz \ + && echo $SHA256SUM_ICU582 icu4c-58_2-Fedora24-x64.tgz | sha256sum -c - \ + && tar -xz -f icu4c-58_2-Fedora24-x64.tgz -C / --wildcards ./icu/usr/local/lib/*.58* --strip-components=2 \ + && curl -OL http://download.icu-project.org/files/icu4c/60.2/icu4c-60_2-Fedora27-x64.tgz \ + && echo $SHA256SUM_ICU602 icu4c-60_2-Fedora27-x64.tgz | sha256sum -c - \ + && tar -xz -f icu4c-60_2-Fedora27-x64.tgz -C / --wildcards ./icu/usr/local/lib/*.60* --strip-components=2 \ && if [ -d $SAFE_TMP ]; then rm -Rf $SAFE_TMP; else echo "not a directory?"; fi \ && echo "/usr/local/lib" > /etc/ld.so.conf.d/lgr.conf && ldconfig diff --git a/kubernetes/site-specific/template-local.py b/kubernetes/site-specific/template-local.py index a0550359..ad754f82 100644 --- a/kubernetes/site-specific/template-local.py +++ b/kubernetes/site-specific/template-local.py @@ -45,6 +45,10 @@ SUPPORTED_UNICODE_VERSIONS = ( '6.3.0', + '7.0.0', + '8.0.0', + '9.0.0', + '10.0.0' ) # UNICODE_DATABASES tells munidata how to instantiate the implementation of each Unicode version that we support. @@ -62,6 +66,26 @@ 'icu_i18n_lib': '/usr/local/lib/libicui18n.so.52', 'version_tag': 52, }, + '7.0.0': { + 'icu_uc_lib': '/usr/local/lib/libicuuc.so.54', + 'icu_i18n_lib': '/usr/local/lib/libicui18n.so.54', + 'version_tag': 54, + }, + '8.0.0': { + 'icu_uc_lib': '/usr/local/lib/libicuuc.so.56', + 'icu_i18n_lib': '/usr/local/lib/libicui18n.so.56', + 'version_tag': 56, + }, + '9.0.0': { + 'icu_uc_lib': '/usr/local/lib/libicuuc.so.58', + 'icu_i18n_lib': '/usr/local/lib/libicui18n.so.58', + 'version_tag': 58, + }, + '10.0.0': { + 'icu_uc_lib': '/usr/local/lib/libicuuc.so.60', + 'icu_i18n_lib': '/usr/local/lib/libicui18n.so.60', + 'version_tag': 60, + } } ##### /LGR Toolset Project-specific settings ##### diff --git a/setup.py b/setup.py index a81dee45..be98a9eb 100755 --- a/setup.py +++ b/setup.py @@ -1,17 +1,18 @@ -#!/bin/env python2 +#!/bin/env python # -*- coding: utf-8 -*- from setuptools import setup, find_packages +from io import open setup( name='lgr-django', - version='1.8.1', + version='2.0.0', author='Viagenie and Wil Tan', author_email='support@viagenie.ca', packages=find_packages('src'), package_dir={'': 'src'}, license='TODO', description='Web-application for LGR editing', - long_description=open('README.md').read(), + long_description=open('README.md', encoding='utf-8').read(), include_package_data=True, classifiers=[ 'Environment :: Web Environment', @@ -19,6 +20,9 @@ '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', ], install_requires=[ # Core stuff diff --git a/src/lgr_editor/api.py b/src/lgr_editor/api.py index 11250baf..8a7e88db 100644 --- a/src/lgr_editor/api.py +++ b/src/lgr_editor/api.py @@ -1,20 +1,19 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from functools import partial + import logging import base64 -from StringIO import StringIO import errno import os from uuid import uuid4 -from codecs import iterdecode - +from functools import partial from django.http import Http404 from django.utils import six from django.utils.text import slugify from django.conf import settings from django.core.files.storage import FileSystemStorage +from django.core.cache import cache from lgr.core import LGR from lgr.metadata import Metadata, Version @@ -22,6 +21,10 @@ from lgr.parser.xml_parser import XMLParser, LGR_NS from lgr.tools.merge_set import merge_lgr_set +from .utils import (LGR_CACHE_TIMEOUT, + LGR_OBJECT_CACHE_KEY, + clean_repertoire_cache, + make_lgr_session_key) from .exceptions import LGRValidationException from .repertoires import get_by_name from . import unidb @@ -58,31 +61,9 @@ def create(cls, name, unicode_version, validating_repertoire_name): return lgr_info @classmethod - def from_dict(cls, dct, lgr_loader_func=None): - name = dct.get('name', '') - xml = dct['xml'] - validate = dct.get('validate', False) - set_labels_info = None - if 'set_labels_info' in dct: - set_labels_info = LabelInfo.from_dict(dct['set_labels_info']) - lgr_set_dct = dct.get('lgr_set_dct', None) - lgr_set = None - if lgr_set_dct: - lgr_set = [] - for lgr_dct in lgr_set_dct: - lgr_set.append(cls.from_dict(lgr_dct, lgr_loader_func=lgr_loader_func)) - - # check if xml is of unicode type - if isinstance(xml, six.text_type): - # convert to a str (bytes in PY3) to be consistent - xml = xml.encode('utf-8') - - # Parse XML # - # Replace old namespace by the new one for compatibility purpose with - # old LGR - xml = unicode(xml, 'utf-8').replace(OLD_LGR_NS, LGR_NS) - # Create parser - parser = XMLParser(StringIO(xml.encode('utf-8')), name) + def _parse_lgr(cls, name, xml, validate): + # Create parser - Assume xml is unicode data + parser = XMLParser(six.BytesIO(xml.encode('utf-8')), name) # Do we need to validate the schema? if validate: @@ -109,7 +90,8 @@ def from_dict(cls, dct, lgr_loader_func=None): if validate: # Retrieve Unicode version to set appropriate Unicode database unicode_version = parser.unicode_version() - parser.unicode_database = unidb.manager.get_db_by_version(unicode_version) + parser.unicode_database = unidb.manager.get_db_by_version( + unicode_version) # Actually parse document lgr = parser.parse_document() @@ -118,7 +100,51 @@ def from_dict(cls, dct, lgr_loader_func=None): if not validate: # Retrieve Unicode version to set appropriate Unicode database unicode_version = lgr.metadata.unicode_version - lgr.unicode_database = unidb.manager.get_db_by_version(unicode_version) + lgr.unicode_database = unidb.manager.get_db_by_version( + unicode_version) + return lgr + + @classmethod + def from_dict(cls, dct, lgr_loader_func=None, request=None): + name = dct.get('name', '') + set_labels_info = None + if 'set_labels_info' in dct: + set_labels_info = LabelInfo.from_dict(dct['set_labels_info']) + lgr_set_dct = dct.get('lgr_set_dct', None) + lgr_set = None + if lgr_set_dct: + lgr_set = [] + for lgr_dct in lgr_set_dct: + lgr_set.append(cls.from_dict(lgr_dct, + lgr_loader_func=lgr_loader_func, + request=request)) + + xml = dct['xml'] + if not isinstance(xml, six.text_type): + xml = six.text_type(xml, 'utf-8') + + # Parse XML # + # Replace old namespace by the new one for compatibility purpose with old LGR + xml = xml.replace(OLD_LGR_NS, LGR_NS) + + if request is None: + lgr = cls._parse_lgr(name, xml, dct.get('validate', False)) + else: + lgr = cache.get(make_lgr_session_key(LGR_OBJECT_CACHE_KEY, + request, + name)) + if lgr is None: + lgr = cls._parse_lgr(name, xml, dct.get('validate', False)) + cache.set(make_lgr_session_key(LGR_OBJECT_CACHE_KEY, + request, + name), + lgr, + LGR_CACHE_TIMEOUT) + else: + # Need to manually load unicode database because + # it is stripped during serialization + unicode_version = lgr.metadata.unicode_version + lgr.unicode_database = unidb.manager.get_db_by_version(unicode_version) validating_repertoire = dct.get('validating_repertoire') val_lgr = lgr_loader_func(validating_repertoire) if (validating_repertoire and lgr_loader_func is not None) else None @@ -130,17 +156,27 @@ def from_dict(cls, dct, lgr_loader_func=None): set_labels_info=set_labels_info) return lgr_info - def to_dict(self): + def to_dict(self, request=None): + if not isinstance(self.xml, six.text_type): + self.xml = six.text_type(self.xml, 'utf-8') + dct = { 'name': self.name, 'xml': self.xml, 'validating_repertoire': self.validating_repertoire.name if self.validating_repertoire else None, - 'lgr_set_dct': [l.to_dict() for l in self.lgr_set] if self.is_set else None, + 'lgr_set_dct': [l.to_dict(request) for l in self.lgr_set] if self.is_set else None, 'is_set': self.is_set # for index.html } if self.set_labels_info is not None: dct['set_labels_info'] = self.set_labels_info.to_dict() + if request is not None: + cache.set(make_lgr_session_key(LGR_OBJECT_CACHE_KEY, + request, + self.name), + self.lgr, + LGR_CACHE_TIMEOUT) + return dct @property @@ -157,13 +193,15 @@ def __init__(self, name, labels=None, data=None): @classmethod def from_dict(cls, dct): - return cls(dct['name'], StringIO(base64.decodestring(dct['data']).decode('utf-8')), dct['data']) + return cls(dct['name'], + six.StringIO(base64.b64decode(dct['data']).decode('utf-8')), + dct['data']) @classmethod def from_form(cls, name, label_input): - data = label_input - labels = StringIO(data.decode('utf-8')) - b64data = base64.encodestring(label_input) + data = label_input.decode('utf-8') + labels = six.StringIO(data) + b64data = base64.b64encode(label_input).decode('utf-8') return cls(name, labels, b64data) @@ -180,7 +218,7 @@ def get_builtin_or_session_repertoire(repertoire_id, request): :param repertoire_id: a slug identifying the LGR :param request: Django request object - :return: `LGR` isntance + :return: `LGR` instance """ try: return get_by_name(repertoire_id) @@ -243,7 +281,7 @@ def session_open_lgr(request, lgr_id, lgr_xml, 'xml': lgr_xml, 'validating_repertoire': validating_repertoire_name, 'validate': validate, - 'lgr_set_dct': map(lambda x: x.to_dict(), lgr_set) if lgr_set else None, + 'lgr_set_dct': [lgr.to_dict() for lgr in lgr_set] if lgr_set else None, 'set_labels': set_labels }, lgr_loader_func=partial(get_builtin_or_session_repertoire, request=request) @@ -277,7 +315,8 @@ def session_select_lgr(request, lgr_id, lgr_set_id=None): raise Http404 lgr_dct = known_lgrs[lgr_id] return LGRInfo.from_dict(lgr_dct, - lgr_loader_func=partial(get_builtin_or_session_repertoire, request=request)) + lgr_loader_func=partial(get_builtin_or_session_repertoire, request=request), + request=request) if not lgr_dct.get('lgr_set_dct', None): raise Http404 @@ -285,11 +324,12 @@ def session_select_lgr(request, lgr_id, lgr_set_id=None): for lgr in lgr_dct.get('lgr_set_dct'): if lgr['name'] == lgr_id: return LGRInfo.from_dict(lgr, - lgr_loader_func=partial(get_builtin_or_session_repertoire, request=request)) + lgr_loader_func=partial(get_builtin_or_session_repertoire, request=request), + request=request) raise Http404 -def session_save_lgr(request, lgr_info, lgr_id=None, update_xml=True): +def session_save_lgr(request, lgr_info, lgr_id=None): """ Save the LGR object in session :param request: Django request object @@ -297,11 +337,12 @@ def session_save_lgr(request, lgr_info, lgr_id=None, update_xml=True): :param lgr_id: a slug identifying the LGR """ lgr_id = lgr_id if lgr_id is not None else lgr_info.name - if update_xml: - lgr_info.update_xml() # make sure we have updated XML before saving - request.session.setdefault(LGRS_SESSION_KEY, {})[lgr_id] = lgr_info.to_dict() + lgr_info.update_xml() # make sure we have updated XML before saving + request.session.setdefault(LGRS_SESSION_KEY, {})[lgr_id] = lgr_info.to_dict(request) # mark session as modified because we are possibly only changing the content of a dict request.session.modified = True + # As LGR has been modified, need to invalidate the template repertoire cache + clean_repertoire_cache(request, lgr_id) def session_delete_lgr(request, lgr_id): @@ -316,6 +357,8 @@ def session_delete_lgr(request, lgr_id): raise Http404 # mark session as modified because we are possibly only changing the content of a dict request.session.modified = True + # Remove cached repertoire + clean_repertoire_cache(request, lgr_id) def session_merge_set(request, lgr_info_set, lgr_set_name): @@ -327,7 +370,7 @@ def session_merge_set(request, lgr_info_set, lgr_set_name): :param lgr_set_name: The name of the LGR set :return: The LGR set merge id """ - merged_lgr = merge_lgr_set(map(lambda x: x.lgr, lgr_info_set), lgr_set_name) + merged_lgr = merge_lgr_set([l.lgr for l in lgr_info_set], lgr_set_name) merged_id = slugify(merged_lgr.name) merged_lgr_xml = serialize_lgr_xml(merged_lgr) diff --git a/src/lgr_editor/forms/__init__.py b/src/lgr_editor/forms/__init__.py index 3c8a7be7..eb95bf1d 100644 --- a/src/lgr_editor/forms/__init__.py +++ b/src/lgr_editor/forms/__init__.py @@ -5,3 +5,4 @@ from .metadata import * from .references import * from .codepoint import * +from .labels import * diff --git a/src/lgr_editor/forms/codepoint.py b/src/lgr_editor/forms/codepoint.py index ef1caf29..055c7cbe 100644 --- a/src/lgr_editor/forms/codepoint.py +++ b/src/lgr_editor/forms/codepoint.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from urllib import quote_plus +from django.utils.six.moves.urllib_parse import quote_plus from django.utils import six from django import forms from django.forms.formsets import formset_factory @@ -49,7 +49,10 @@ class CodepointVariantForm(forms.Form): 'cols': '30', 'class': 'form-control'})) # whether the variant codepoint is in LGR or not - in_lgr = forms.BooleanField(widget=forms.HiddenInput) + # Need required=False as we expect False values + # See https://docs.djangoproject.com/en/1.8/ref/forms/fields/#booleanfield + # for explanation on stupid behaviour... + in_lgr = forms.BooleanField(widget=forms.HiddenInput, required=False) def to_slug(self): return '{},{},{}'.format( diff --git a/src/lgr_editor/forms/codepoints.py b/src/lgr_editor/forms/codepoints.py index c5f4a546..a2e8972e 100644 --- a/src/lgr_editor/forms/codepoints.py +++ b/src/lgr_editor/forms/codepoints.py @@ -3,9 +3,12 @@ from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ +from django.utils.six import text_type from django import forms -from lgr.tools.utils import parse_label_input, parse_single_cp_input, parse_codepoint_input +from lgr.tools.utils import parse_single_cp_input, parse_codepoint_input +from .fields import (VALIDATING_REPERTOIRES, + DEFAULT_VALIDATING_REPERTOIRE) SUPPORTED_CODEPOINT_INPUT_FILES = [ ('rfc3743', 'RFC3743'), @@ -36,7 +39,7 @@ def clean(self, value): else: value = parse_codepoint_input(value) except ValueError as e: - raise ValidationError(unicode(e)) + raise ValidationError(text_type(e)) return value @@ -65,16 +68,31 @@ class AddRangeForm(forms.Form): def clean(self): cd = super(AddRangeForm, self).clean() # TODO check that we don't get sequences - if 'first_cp' in cd \ - and 'last_cp' in cd \ - and cd['first_cp'] > cd['last_cp']: + if 'first_cp' in cd and 'last_cp' in cd and cd['first_cp'] > cd['last_cp']: raise ValidationError(_('Last code point (%(last_cp)s) must not be ' 'smaller than the first code point ' '(%(first_cp)s)') % cd) +class AddCodepointFromScriptForm(forms.Form): + validating_repertoire = forms.ChoiceField(label=_("Validating repertoire"), + required=True, + choices=VALIDATING_REPERTOIRES, + initial=DEFAULT_VALIDATING_REPERTOIRE) + script = forms.ChoiceField(label=_("Script"), + required=True) + manual_import = forms.BooleanField(label=_("Manual import"), + required=False) + + def __init__(self, *args, **kwargs): + super(AddCodepointFromScriptForm, self).__init__(*args, **kwargs) + self.fields['script'].choices = self.initial.get('scripts', []) + + class ImportCodepointsFromFileForm(forms.Form): - file = forms.FileField(label=_("Select a file")) + file = forms.FileField(label=_("Select a file"), + help_text=_('File containing data to be imported. ' + 'File must be encoded in UTF-8 and using UNIX line ending.')) type = forms.ChoiceField(label=_("File type"), choices=SUPPORTED_CODEPOINT_INPUT_FILES) manual_import = forms.BooleanField(label=_("Manual import"), @@ -87,40 +105,40 @@ class AddVariantForm(forms.Form): required=False) -class ValidateLabelForm(forms.Form): - label = forms.CharField(label=_("Label")) - set_labels = forms.FileField(label=_("Allocated Set labels"), - required=False, - help_text=_('Optional list of labels already allocated ' - 'in the LGR set, that will be used to check ' - 'for collisions when evaluating labels using ' - 'the merged LGR set')) - script = forms.ChoiceField(label=_("Script"), - required=False, - help_text=_('The script used to validate the label')) +class MultipleChoiceFieldNoValidation(forms.MultipleChoiceField): + + def validate(self, value): + # do not enable default validation as it will refuse our values as they are not in form choices + # XXX we could validate that cp are in lgr + pass - def __init__(self, *args, **kwargs): - lgr_info = kwargs.pop('lgr_info', None) - max_label_len = kwargs.pop('max_label_len', None) - self.idna_decoder = kwargs.pop('idna_decoder', None) - scripts = kwargs.pop('scripts', None) - super(ValidateLabelForm, self).__init__(*args, **kwargs) - if max_label_len is not None: - self.fields['label'].help_text = _("Maximum length: %d code points" % max_label_len) - if scripts: - self.fields['script'].choices = scripts - self.fields['script'].required = True - if lgr_info is not None and lgr_info.set_labels_info is not None: - self.fields['set_labels'].initial = lgr_info.set_labels_info.name - - def clean_label(self): - value = self.cleaned_data['label'] - kwargs = {} - if self.idna_decoder: - kwargs['idna_decoder'] = self.idna_decoder - try: - value = parse_label_input(value, **kwargs) - except ValueError as e: - raise ValidationError(unicode(e)) - return value +class EditCodepointsForm(forms.Form): + when = forms.ChoiceField(label='when', required=False) + not_when = forms.ChoiceField(label='not-when', required=False) + tags = forms.CharField(label='Tags', required=False, help_text='space-separated tags') + cp_id = MultipleChoiceFieldNoValidation() # will contain a list of code points + + def __init__(self, post, *args, **kwargs): + rule_names = kwargs.pop('rule_names', None) + self.post = post + super(EditCodepointsForm, self).__init__(post, *args, **kwargs) + + if rule_names: + self.fields['when'].choices = rule_names + self.fields['not_when'].choices = rule_names + + 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') + 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') + + 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') + + return cleaned_data diff --git a/src/lgr_editor/forms/labels.py b/src/lgr_editor/forms/labels.py new file mode 100644 index 00000000..b8ed9e89 --- /dev/null +++ b/src/lgr_editor/forms/labels.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +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 + + +class LabelFormsForm(forms.Form): + label = forms.CharField(label=_("Label")) + unicode_version = forms.ChoiceField(label=_("Unicode version"), + required=True, + help_text=_('The unicode version used')) + + def __init__(self, *args, **kwargs): + unicode_versions = kwargs.pop('unicode_versions', None) + super(LabelFormsForm, self).__init__(*args, **kwargs) + if unicode_versions is not None: + self.fields['unicode_version'].choices = unicode_versions + + def clean(self): + label = self.cleaned_data['label'] + unicode_version = self.cleaned_data['unicode_version'] + udata = unidb.manager.get_db_by_version(unicode_version) + try: + value = parse_label_input(label, idna_decoder=udata.idna_decode_label) + except ValueError as e: + self.add_error('label', text_type(e)) + else: + self.cleaned_data['label'] = value + return self.cleaned_data diff --git a/src/lgr_editor/forms/references.py b/src/lgr_editor/forms/references.py index 4ccec989..ad3361c3 100644 --- a/src/lgr_editor/forms/references.py +++ b/src/lgr_editor/forms/references.py @@ -1,22 +1,38 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +import re + from django import forms from django.forms.formsets import formset_factory +from lgr.metadata import ReferenceManager from .utils import BaseDisableableFormSet, ReadOnlyTextInput class ReferenceForm(forms.Form): # Keep reference id # Not required since this form is also used to create new references - ref_id = forms.CharField(label='', required=False, - widget=ReadOnlyTextInput()) + ref_id = forms.CharField(label='', required=False) # Editable fields description = forms.CharField(label='') comment = forms.CharField(label='', required=False) + def __init__(self, *args, **kwargs): + ro_id = kwargs.pop('ro_id', True) + super(ReferenceForm, self).__init__(*args, **kwargs) + + if ro_id: + self.fields['ref_id'].widget = ReadOnlyTextInput() + + 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') + + return cleaned_data + ReferenceFormSet = formset_factory(ReferenceForm, formset=BaseDisableableFormSet, diff --git a/src/lgr_editor/lgr_exceptions.py b/src/lgr_editor/lgr_exceptions.py index a1ece87b..dfee98f4 100644 --- a/src/lgr_editor/lgr_exceptions.py +++ b/src/lgr_editor/lgr_exceptions.py @@ -56,8 +56,9 @@ def lgr_exception_to_text(exception): 'codepoint': format_cp(exception.cp) } elif isinstance(exception, lgr.exceptions.CharInvalidContextRule): - message = _('Code point %(codepoint)s has invalid context rule') % { - 'codepoint': format_cp(exception.cp) + message = _('Code point %(codepoint)s has invalid context rule %(rule)s') % { + 'codepoint': format_cp(exception.cp), + 'rule': exception.rule or '' } elif isinstance(exception, lgr.exceptions.RangeInvalidContextRule): message = _('Range %(first_cp)s - %(last_cp)s has invalid context rule') % { @@ -81,10 +82,12 @@ def lgr_exception_to_text(exception): } elif isinstance(exception, lgr.exceptions.LGRFormatException): reason = exception.reason - if reason == lgr.exceptions.LGRFormatException.LGRFormatReason.INVALID_DATE_TAG: - message = _('Invalid date value') + if reason == lgr.exceptions.LGRFormatException.LGRFormatReason.SEQUENCE_NO_TAG: + message = _('Sequence cannot have a tag') elif reason == lgr.exceptions.LGRFormatException.LGRFormatReason.INVALID_LANGUAGE_TAG: message = _('Invalid language') + elif reason == lgr.exceptions.LGRFormatException.LGRFormatReason.INVALID_DATE_TAG: + message = _('Invalid date value') elif reason == lgr.exceptions.LGRFormatException.LGRFormatReason.INVALID_UNICODE_VERSION_TAG: message = _('Invalid Unicode version') else: @@ -97,6 +100,10 @@ def lgr_exception_to_text(exception): message = _('Reference %(ref_id)s already exists') % { 'ref_id': exception.ref_id } + elif isinstance(exception, lgr.exceptions.ReferenceInvalidId): + message = _('Invalid reference id %(ref_id)s ') % { + 'ref_id': exception.ref_id + } elif isinstance(exception, lgr.exceptions.RuleError): message = _('Rule "%(rule_name)s" cannot be processed (%(message)s)') % { 'rule_name': exception.rule_name, @@ -118,6 +125,8 @@ def lgr_exception_to_text(exception): elif isinstance(exception, lgr.exceptions.InvalidSymmetry): message = _('The LGR contains a variant that do not have symmetric ' '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.LGRException): message = _('An unknown exception occurred in the LGR API') else: diff --git a/src/lgr_editor/locale/ar/LC_MESSAGES/django.mo b/src/lgr_editor/locale/ar/LC_MESSAGES/django.mo index d2bbacae..cfa97df1 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 5f2f30d7..6e5c0e27 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: 2017-10-30 20:24+0000\n" +"POT-Creation-Date: 2018-09-04 16:04+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -27,7 +27,8 @@ msgstr "" msgid "Not-When" msgstr "" -#: forms/codepoint.py:16 +#: forms/codepoint.py:16 templates/lgr_editor/_editor_base.html:31 +#: templates/lgr_editor/codepoint_list.html:40 msgid "Tags" msgstr "" @@ -35,88 +36,72 @@ msgstr "" msgid "space-separated tags" msgstr "" -#: forms/codepoints.py:45 forms/codepoints.py:85 -#: templates/lgr_editor/codepoint_list.html:16 -#: templates/lgr_editor/codepoint_list.html:56 +#: forms/codepoints.py:48 forms/codepoints.py:103 +#: templates/lgr_editor/codepoint_list.html:38 +#: templates/lgr_editor/codepoint_list.html:112 #: templates/lgr_editor/codepoint_view.html:49 msgid "Code point" msgstr "" -#: forms/codepoints.py:46 forms/codepoints.py:86 +#: forms/codepoints.py:49 forms/codepoints.py:104 msgid "Override repertoire" msgstr "" -#: forms/codepoints.py:51 templates/lgr_editor/_editor_base.html:20 +#: forms/codepoints.py:54 templates/lgr_editor/_editor_base.html:22 #: templates/lgr_editor/codepoint_view.html:22 msgid "Code points" msgstr "" -#: forms/codepoints.py:55 +#: forms/codepoints.py:58 msgid "Disabled code points" msgstr "" -#: forms/codepoints.py:62 +#: forms/codepoints.py:65 msgid "First code point" msgstr "" -#: forms/codepoints.py:63 +#: forms/codepoints.py:66 msgid "Last code point" msgstr "" -#: forms/codepoints.py:71 +#: forms/codepoints.py:72 #, python-format msgid "" "Last code point (%(last_cp)s) must not be smaller than the first code point " "(%(first_cp)s)" msgstr "" -#: forms/codepoints.py:77 -msgid "Select a file" +#: forms/codepoints.py:78 forms/importer.py:14 forms/importer.py:27 +#: forms/metadata.py:50 +msgid "Validating repertoire" msgstr "" -#: forms/codepoints.py:78 -msgid "File type" +#: forms/codepoints.py:82 +msgid "Script" msgstr "" -#: forms/codepoints.py:80 +#: forms/codepoints.py:84 forms/codepoints.py:98 msgid "Manual import" msgstr "" -#: forms/codepoints.py:91 -msgid "Label" -msgstr "" - -#: forms/codepoints.py:92 -msgid "Allocated Set labels" +#: forms/codepoints.py:93 +msgid "Select a file" msgstr "" #: forms/codepoints.py:94 msgid "" -"Optional list of labels already allocated in the LGR set, that will be used " -"to check for collisions when evaluating labels using the merged LGR set" +"File containing data to be imported. File must be encoded in UTF-8 and using " +"UNIX line ending." msgstr "" -#: forms/codepoints.py:98 -msgid "Script" -msgstr "" - -#: forms/codepoints.py:100 -msgid "The script used to validate the label" -msgstr "" - -#: forms/codepoints.py:109 -#, python-format -msgid "Maximum length: %d code points" +#: forms/codepoints.py:96 +msgid "File type" msgstr "" #: forms/importer.py:13 msgid "Name" msgstr "" -#: forms/importer.py:14 forms/importer.py:27 forms/metadata.py:50 -msgid "Validating repertoire" -msgstr "" - #: forms/importer.py:15 forms/importer.py:28 msgid "Code points will be limited to the selected repertoire" msgstr "" @@ -139,6 +124,18 @@ msgstr "" msgid "The name of the set" msgstr "" +#: forms/labels.py:14 +msgid "Label" +msgstr "" + +#: forms/labels.py:15 forms/metadata.py:46 +msgid "Unicode version" +msgstr "" + +#: forms/labels.py:17 +msgid "The unicode version used" +msgstr "" + #: forms/metadata.py:39 msgid "Version" msgstr "" @@ -167,13 +164,9 @@ msgstr "" msgid "Validity end" msgstr "" -#: forms/metadata.py:46 -msgid "Unicode version" -msgstr "" - -#: forms/metadata.py:47 templates/lgr_editor/codepoint_view.html:212 +#: forms/metadata.py:47 templates/lgr_editor/codepoint_view.html:227 #: templates/lgr_editor/references.html:14 -#: templates/lgr_editor/references.html:50 +#: templates/lgr_editor/references.html:51 msgid "Description" msgstr "" @@ -233,107 +226,121 @@ msgstr "" #: lgr_exceptions.py:59 #, python-format -msgid "Code point %(codepoint)s has invalid context rule" +msgid "Code point %(codepoint)s has invalid context rule %(rule)s" msgstr "" -#: lgr_exceptions.py:63 +#: lgr_exceptions.py:64 #, python-format msgid "Range %(first_cp)s - %(last_cp)s has invalid context rule" msgstr "" -#: lgr_exceptions.py:68 +#: lgr_exceptions.py:69 #, python-format msgid "" "Variant %(variant_codepoint)s of code point %(codepoint)shas invalid context " "rule" msgstr "" -#: lgr_exceptions.py:74 +#: lgr_exceptions.py:75 #, python-format msgid "Duplicate reference for code point %(codepoint)s" msgstr "" -#: lgr_exceptions.py:78 +#: lgr_exceptions.py:79 #, python-format msgid "Unspecified exception for input code point %(codepoint)s" msgstr "" -#: lgr_exceptions.py:85 -msgid "Invalid date value" +#: lgr_exceptions.py:86 +msgid "Sequence cannot have a tag" msgstr "" -#: lgr_exceptions.py:87 +#: lgr_exceptions.py:88 msgid "Invalid language" msgstr "" -#: lgr_exceptions.py:89 +#: lgr_exceptions.py:90 +msgid "Invalid date value" +msgstr "" + +#: lgr_exceptions.py:92 msgid "Invalid Unicode version" msgstr "" -#: lgr_exceptions.py:91 +#: lgr_exceptions.py:94 msgid "Invalid LGR XML file" msgstr "" -#: lgr_exceptions.py:93 +#: lgr_exceptions.py:96 #, python-format msgid "Reference %(ref_id)s is not defined" msgstr "" -#: lgr_exceptions.py:97 +#: lgr_exceptions.py:100 #, python-format msgid "Reference %(ref_id)s already exists" msgstr "" -#: lgr_exceptions.py:101 +#: lgr_exceptions.py:104 +#, python-format +msgid "Invalid reference id %(ref_id)s " +msgstr "" + +#: lgr_exceptions.py:108 #, python-format msgid "Rule \"%(rule_name)s\" cannot be processed (%(message)s)" msgstr "" -#: lgr_exceptions.py:106 +#: lgr_exceptions.py:113 msgid "Input parameter has invalid format" msgstr "" -#: lgr_exceptions.py:108 +#: lgr_exceptions.py:115 msgid "A general exception occurred in the LGR API" msgstr "" -#: lgr_exceptions.py:110 +#: lgr_exceptions.py:117 #, python-format msgid "LGR is not valid (%(args)s)" msgstr "" -#: lgr_exceptions.py:112 +#: lgr_exceptions.py:119 #, python-format msgid "Label %(label)s is not valid in the LGR (%(message)s)" msgstr "" -#: lgr_exceptions.py:117 +#: lgr_exceptions.py:124 msgid "Input label file contains collision(s)" msgstr "" -#: lgr_exceptions.py:119 +#: lgr_exceptions.py:126 msgid "The LGR contains a variant that do not have symmetric relations" msgstr "" -#: lgr_exceptions.py:122 +#: lgr_exceptions.py:129 +#, python-format +msgid "The LGR does not contain a valid language (%(message)s)" +msgstr "" + +#: lgr_exceptions.py:131 msgid "An unknown exception occurred in the LGR API" msgstr "" -#: templates/lgr_editor/_editor_base.html:23 +#: templates/lgr_editor/_editor_base.html:25 #: templates/lgr_editor/codepoint_view.html:54 msgid "References" msgstr "" -#: templates/lgr_editor/_editor_base.html:26 +#: templates/lgr_editor/_editor_base.html:28 msgid "Meta data" msgstr "" -#: templates/lgr_editor/_editor_base.html:29 templates/lgr_editor/rules.html:18 +#: templates/lgr_editor/_editor_base.html:34 templates/lgr_editor/rules.html:18 #: templates/lgr_editor/rules_edit.html:57 msgid "Rules" msgstr "" -#: templates/lgr_editor/_editor_base.html:34 +#: templates/lgr_editor/_editor_base.html:39 msgid "Embedded LGRs" msgstr "" @@ -348,7 +355,7 @@ msgid "%(lgr_name)s" msgstr "" #: templates/lgr_editor/_rule_editor_widgets.html:5 -#: templates/lgr_editor/codepoint_view.html:229 +#: templates/lgr_editor/codepoint_view.html:244 #: templates/lgr_editor/metadata.html:32 #: templates/lgr_editor/rules_edit.html:40 #: templates/lgr_editor/rules_edit.html:71 @@ -366,30 +373,38 @@ msgid "Save" msgstr "" #: templates/lgr_editor/_rule_editor_widgets.html:11 -#: templates/lgr_editor/codepoint_view.html:160 +#: templates/lgr_editor/codepoint_view.html:165 msgid "Edit" msgstr "" #: templates/lgr_editor/about.html:3 msgid "" -"This application provides a convenient interface for browsing and editing " -"LGR’s conforming to the Representing Label Generation Rulesets using XML specification." +"\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 "" #: templates/lgr_editor/about.html:10 msgid "Supported Unicode versions:" msgstr "" -#: templates/lgr_editor/about.html:17 +#: templates/lgr_editor/about.html:18 msgid "" -"This toolset was implemented by Viagenie and Wil Tan on an ICANN contract." +"This toolset was implemented by Viagénie and Wil Tan on an ICANN contract." msgstr "" #: templates/lgr_editor/add_list.html:8 +#: templates/lgr_editor/add_list_from_script.html:11 #: templates/lgr_editor/add_list_import.html:11 #: templates/lgr_editor/add_list_range.html:11 +#: templates/lgr_editor/codepoint_list.html:69 +#: templates/lgr_editor/codepoint_list.html:90 msgid "Next" msgstr "" @@ -400,54 +415,108 @@ msgid "" "are not redirected automatically." msgstr "" -#: templates/lgr_editor/codepoint_list.html:10 +#: templates/lgr_editor/codepoint_list.html:21 +msgid "Populate variants" +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:25 msgid "Expand range(s)" msgstr "" -#: templates/lgr_editor/codepoint_list.html:11 -#: templates/lgr_editor/codepoint_list.html:50 +#: templates/lgr_editor/codepoint_list.html:27 +#: templates/lgr_editor/codepoint_list.html:106 msgid "Add code point(s)" msgstr "" -#: templates/lgr_editor/codepoint_list.html:17 +#: templates/lgr_editor/codepoint_list.html:39 msgid "Character Name" msgstr "" -#: templates/lgr_editor/codepoint_list.html:18 +#: templates/lgr_editor/codepoint_list.html:41 #: templates/lgr_editor/codepoint_view.html:51 msgid "Comments" msgstr "" -#: templates/lgr_editor/codepoint_list.html:19 +#: templates/lgr_editor/codepoint_list.html:42 #: templates/lgr_editor/codepoint_view.html:56 -#: templates/lgr_editor/references.html:17 +#: templates/lgr_editor/references.html:17 templates/lgr_editor/tags.html:14 msgid "Action" msgstr "" -#: templates/lgr_editor/codepoint_list.html:29 -msgid "Variant(s)" +#: templates/lgr_editor/codepoint_list.html:52 +#: templates/lgr_editor/codepoint_list.html:82 +msgid "Add Rule" msgstr "" -#: templates/lgr_editor/codepoint_list.html:32 -msgid "See code point" +#: templates/lgr_editor/codepoint_list.html:57 +msgid "There is no rule in the current LGR" msgstr "" -#: templates/lgr_editor/codepoint_list.html:35 -msgid "Expand range" +#: templates/lgr_editor/codepoint_list.html:60 +msgid "Close" msgstr "" -#: templates/lgr_editor/codepoint_list.html:59 +#: templates/lgr_editor/codepoint_list.html:66 +msgid "" +"\n" +"

This rule will be added to codepoint(s)

\n" +" " +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:87 +msgid "" +"\n" +"

These tags will be added to codepoint(s)

\n" +" " +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:115 msgid "Code point range" msgstr "" -#: templates/lgr_editor/codepoint_list.html:62 +#: templates/lgr_editor/codepoint_list.html:118 +msgid "Code point from script" +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:121 msgid "Import from file" msgstr "" -#: templates/lgr_editor/codepoint_list.html:74 +#: templates/lgr_editor/codepoint_list.html:133 msgid "Add Code Point" msgstr "" +#: templates/lgr_editor/codepoint_list.html:224 +msgid "Variant(s)" +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:240 +msgid "See code point" +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:243 +msgid "Expand range" +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:273 +#: templates/lgr_editor/codepoint_list.html:297 +msgid "➡ Select code point(s) to apply batch action..." +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:274 +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 "" + #: templates/lgr_editor/codepoint_view.html:26 #, python-format msgid "Code point appeared in Unicode version: %(age)s" @@ -465,78 +534,86 @@ msgstr "" msgid "Not When" msgstr "" -#: templates/lgr_editor/codepoint_view.html:73 +#: templates/lgr_editor/codepoint_view.html:74 msgid "Code point is not in LGR" msgstr "" -#: templates/lgr_editor/codepoint_view.html:103 +#: templates/lgr_editor/codepoint_view.html:104 msgid "Are you sure you want delete this variant?" msgstr "" -#: templates/lgr_editor/codepoint_view.html:103 +#: templates/lgr_editor/codepoint_view.html:104 msgid "Delete variant" msgstr "" -#: templates/lgr_editor/codepoint_view.html:104 +#: templates/lgr_editor/codepoint_view.html:105 msgid "Edit references" msgstr "" -#: templates/lgr_editor/codepoint_view.html:113 +#: templates/lgr_editor/codepoint_view.html:114 msgid "Range characters do not have variants." msgstr "" -#: templates/lgr_editor/codepoint_view.html:115 +#: templates/lgr_editor/codepoint_view.html:116 msgid "Code point has not variant" msgstr "" -#: templates/lgr_editor/codepoint_view.html:132 +#: templates/lgr_editor/codepoint_view.html:137 msgid "Save variants, tags, context rules and comment" msgstr "" -#: templates/lgr_editor/codepoint_view.html:154 +#: templates/lgr_editor/codepoint_view.html:159 msgid "No references associated with code point." msgstr "" -#: templates/lgr_editor/codepoint_view.html:167 +#: templates/lgr_editor/codepoint_view.html:172 msgid "Are you sure you want delete this code point?" msgstr "" -#: templates/lgr_editor/codepoint_view.html:169 +#: templates/lgr_editor/codepoint_view.html:174 msgid "Delete code point" msgstr "" -#: templates/lgr_editor/codepoint_view.html:180 +#: templates/lgr_editor/codepoint_view.html:185 msgid "Edit References for " msgstr "" -#: templates/lgr_editor/codepoint_view.html:186 +#: templates/lgr_editor/codepoint_view.html:191 msgctxt "button title" msgid "Delete reference" msgstr "" -#: templates/lgr_editor/codepoint_view.html:195 +#: templates/lgr_editor/codepoint_view.html:200 msgid "Add an existing reference" msgstr "" -#: templates/lgr_editor/codepoint_view.html:204 -#: templates/lgr_editor/references.html:58 +#: templates/lgr_editor/codepoint_view.html:209 +#: templates/lgr_editor/references.html:60 msgid "Add" msgstr "" -#: templates/lgr_editor/codepoint_view.html:210 +#: templates/lgr_editor/codepoint_view.html:215 msgid "Create a new reference" msgstr "" -#: templates/lgr_editor/codepoint_view.html:216 +#: templates/lgr_editor/codepoint_view.html:219 +msgid "Error when adding reference" +msgstr "" + +#: templates/lgr_editor/codepoint_view.html:223 +msgid "Reference ID (optional)" +msgstr "" + +#: templates/lgr_editor/codepoint_view.html:231 msgid "URL (optional)" msgstr "" -#: templates/lgr_editor/codepoint_view.html:222 +#: templates/lgr_editor/codepoint_view.html:237 #: templates/lgr_editor/references.html:44 msgid "New reference" msgstr "" -#: templates/lgr_editor/codepoint_view.html:230 +#: templates/lgr_editor/codepoint_view.html:245 msgid "Save changes" msgstr "" @@ -554,15 +631,23 @@ msgid "" "automatically be created." msgstr "" -#: templates/lgr_editor/import_form.html:35 +#: templates/lgr_editor/import_form.html:12 +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 "" + +#: templates/lgr_editor/import_form.html:43 msgid "These LGRs are already imported. Click on one to access it." msgstr "" -#: templates/lgr_editor/import_form.html:42 +#: templates/lgr_editor/import_form.html:50 msgid "Import" msgstr "" -#: templates/lgr_editor/import_form.html:47 +#: templates/lgr_editor/import_form.html:55 msgid "" " " "Note that importing large LGR files may take significant time to load on " @@ -573,6 +658,22 @@ msgstr "" msgid "Cannot import LGR file(s):" msgstr "" +#: templates/lgr_editor/label_forms.html:11 +msgid "Display forms" +msgstr "" + +#: templates/lgr_editor/label_forms.html:18 +msgid "Code point sequence" +msgstr "" + +#: templates/lgr_editor/label_forms.html:19 +msgid "U-label" +msgstr "" + +#: templates/lgr_editor/label_forms.html:20 +msgid "A-label" +msgstr "" + #: templates/lgr_editor/metadata.html:11 msgid "There was an error saving; please see error(s) below" msgstr "" @@ -594,11 +695,12 @@ msgid "Existing references" msgstr "" #: templates/lgr_editor/references.html:13 +#: templates/lgr_editor/references.html:50 msgid "Reference id" msgstr "" #: templates/lgr_editor/references.html:15 -#: templates/lgr_editor/references.html:51 +#: templates/lgr_editor/references.html:52 msgid "URL" msgstr "" @@ -642,176 +744,247 @@ msgstr "" msgid "New action" msgstr "" -#: views.py:97 +#: templates/lgr_editor/tags.html:7 +msgid "Existing tags" +msgstr "" + +#: templates/lgr_editor/tags.html:11 +msgid "Tag name" +msgstr "" + +#: templates/lgr_editor/tags.html:12 +msgid "Associated code points" +msgstr "" + +#: templates/lgr_editor/tags.html:38 +#, python-format +msgid "View all (%(nb_cp)s)" +msgstr "" + +#: templates/lgr_editor/tags.html:56 +msgid "Delete Tag" +msgstr "" + +#: templates/lgr_editor/tags.html:57 +#, python-format +msgid "Are you sure you want delete tag %(tag)s?" +msgstr "" + +#: templates/lgr_editor/tags.html:70 +msgid "" +"To create a new tag:\n" +" Add it to a code point first to find it back in this list" +msgstr "" + +#: views.py:114 msgid "" "The LGR you have tried to create already exists in your working session. " "Please use a new name." msgstr "" -#: views.py:131 +#: views.py:148 msgid "" "The LGR you have tried to import already exists in your working session. " "Please rename it before importing it." msgstr "" -#: views.py:137 +#: views.py:154 msgid "" "The LGR you have tried to import already exists in your set. Please rename " "it before importing it." msgstr "" -#: views.py:160 +#: views.py:177 msgid "The LGR set name already exists. Please use another name." msgstr "" -#: views.py:253 -msgid "summary" +#: views.py:289 +#, python-format +msgid "New code point %s added" msgstr "" -#: views.py:280 +#: views.py:362 +msgid "Rule" +msgstr "" + +#: views.py:362 +msgid "Tag(s)" +msgstr "" + +#: views.py:363 +msgid "rule" +msgstr "" + +#: views.py:363 +msgid "tag(s)" +msgstr "" + +#: views.py:367 #, python-format -msgid "New code point %s added" +msgid "%(operation)s successfully added to %(nb_cp)s code point(s)" +msgstr "" + +#: views.py:372 +#, python-format +msgid "%(nb_cp)s code points were not updated to avoid invalid %(operation)s" msgstr "" -#: views.py:368 -msgid "New variant added" +#: views.py:504 +#, python-format +msgid "Automatically added codepoint %s from out-of-repertoire variant" +msgstr "" + +#: views.py:507 +#, python-format +msgid "New variant %s added" msgstr "" -#: views.py:441 +#: views.py:580 msgid "Code point edited" msgstr "" -#: views.py:621 views.py:657 +#: views.py:732 +msgid "Variants populated" +msgstr "" + +#: views.py:783 views.py:819 msgid "References updated successfully" msgstr "" -#: views.py:660 +#: views.py:822 #, 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:696 +#: views.py:858 #, python-format msgid "Code point %s has been deleted" msgstr "" -#: views.py:718 +#: views.py:880 #, python-format msgid "Variant %(var_cp)s with when='%(when)s' and not-when='%(not_when)s'" msgstr "" -#: views.py:724 +#: views.py:886 #, python-format msgid "%(var_msg_prefix)s has been deleted" msgstr "" -#: views.py:727 +#: views.py:889 #, python-format msgid "%(var_msg_prefix)s could not be deleted because it was not found" msgstr "" -#: views.py:756 +#: views.py:919 msgid "New reference created" msgstr "" -#: views.py:943 views.py:1106 views.py:1190 +#: views.py:1127 +#, 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 msgid "No body specified" msgstr "" -#: views.py:952 +#: views.py:1204 #, python-format msgid "Class \"%s\" does not exist" msgstr "" -#: views.py:956 +#: views.py:1208 #, python-format msgid "Class \"%s\" deleted." msgstr "" -#: views.py:961 +#: views.py:1213 msgid "No class element found" msgstr "" -#: views.py:963 views.py:1126 +#: views.py:1215 views.py:1377 msgid "Name attribute must be present" msgstr "" -#: views.py:967 views.py:984 views.py:1130 views.py:1147 views.py:1214 -#: views.py:1227 +#: views.py:1219 views.py:1236 views.py:1381 views.py:1398 views.py:1465 +#: views.py:1478 #, python-format msgid "" "Encountered XML syntax error: %s (line number may be wrong, try subtracting " "one from the reported line number)" msgstr "" -#: views.py:970 views.py:987 views.py:1133 views.py:1150 views.py:1217 -#: views.py:1230 +#: views.py:1222 views.py:1239 views.py:1384 views.py:1401 views.py:1468 +#: views.py:1481 msgid "Your XML is not valid" msgstr "" -#: views.py:975 +#: views.py:1227 #, python-format msgid "Class \"%s\" already exists" msgstr "" -#: views.py:977 +#: views.py:1229 #, python-format msgid "Class \"%s\" saved." msgstr "" -#: views.py:1115 +#: views.py:1366 #, python-format msgid "Rule \"%s\" does not exist" msgstr "" -#: views.py:1119 +#: views.py:1370 #, python-format msgid "Rule \"%s\" deleted." msgstr "" -#: views.py:1124 +#: views.py:1375 msgid "No rule element found" msgstr "" -#: views.py:1138 +#: views.py:1389 #, python-format msgid "Rule \"%s\" already exists" msgstr "" -#: views.py:1140 +#: views.py:1391 #, python-format msgid "Rule \"%s\" saved." msgstr "" -#: views.py:1201 +#: views.py:1452 #, python-format msgid "Action \"%s\" does not exist" msgstr "" -#: views.py:1205 +#: views.py:1456 #, python-format msgid "Action \"%s\" deleted." msgstr "" -#: views.py:1210 +#: views.py:1461 msgid "No action element found" msgstr "" -#: views.py:1220 +#: views.py:1471 msgid "Action saved." msgstr "" -#: views.py:1289 views.py:1435 +#: views.py:1540 views.py:1628 #, python-format msgid "%d code points added" msgstr "" -#: views.py:1404 +#: views.py:1597 msgid "No code point in input file" msgstr "" -#: views.py:1596 +#: views.py:1903 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 11d98eb6..8b5f6d89 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 8654efd6..6ebfb584 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: 2017-10-30 20:24+0000\n" +"POT-Creation-Date: 2018-09-04 16:04+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -25,7 +25,8 @@ msgstr "" msgid "Not-When" msgstr "" -#: forms/codepoint.py:16 +#: forms/codepoint.py:16 templates/lgr_editor/_editor_base.html:31 +#: templates/lgr_editor/codepoint_list.html:40 msgid "Tags" msgstr "" @@ -33,88 +34,72 @@ msgstr "" msgid "space-separated tags" msgstr "" -#: forms/codepoints.py:45 forms/codepoints.py:85 -#: templates/lgr_editor/codepoint_list.html:16 -#: templates/lgr_editor/codepoint_list.html:56 +#: forms/codepoints.py:48 forms/codepoints.py:103 +#: templates/lgr_editor/codepoint_list.html:38 +#: templates/lgr_editor/codepoint_list.html:112 #: templates/lgr_editor/codepoint_view.html:49 msgid "Code point" msgstr "" -#: forms/codepoints.py:46 forms/codepoints.py:86 +#: forms/codepoints.py:49 forms/codepoints.py:104 msgid "Override repertoire" msgstr "" -#: forms/codepoints.py:51 templates/lgr_editor/_editor_base.html:20 +#: forms/codepoints.py:54 templates/lgr_editor/_editor_base.html:22 #: templates/lgr_editor/codepoint_view.html:22 msgid "Code points" msgstr "" -#: forms/codepoints.py:55 +#: forms/codepoints.py:58 msgid "Disabled code points" msgstr "" -#: forms/codepoints.py:62 +#: forms/codepoints.py:65 msgid "First code point" msgstr "" -#: forms/codepoints.py:63 +#: forms/codepoints.py:66 msgid "Last code point" msgstr "" -#: forms/codepoints.py:71 +#: forms/codepoints.py:72 #, python-format msgid "" "Last code point (%(last_cp)s) must not be smaller than the first code point " "(%(first_cp)s)" msgstr "" -#: forms/codepoints.py:77 -msgid "Select a file" +#: forms/codepoints.py:78 forms/importer.py:14 forms/importer.py:27 +#: forms/metadata.py:50 +msgid "Validating repertoire" msgstr "" -#: forms/codepoints.py:78 -msgid "File type" +#: forms/codepoints.py:82 +msgid "Script" msgstr "" -#: forms/codepoints.py:80 +#: forms/codepoints.py:84 forms/codepoints.py:98 msgid "Manual import" msgstr "" -#: forms/codepoints.py:91 -msgid "Label" -msgstr "" - -#: forms/codepoints.py:92 -msgid "Allocated Set labels" +#: forms/codepoints.py:93 +msgid "Select a file" msgstr "" #: forms/codepoints.py:94 msgid "" -"Optional list of labels already allocated in the LGR set, that will be used " -"to check for collisions when evaluating labels using the merged LGR set" +"File containing data to be imported. File must be encoded in UTF-8 and using " +"UNIX line ending." msgstr "" -#: forms/codepoints.py:98 -msgid "Script" -msgstr "" - -#: forms/codepoints.py:100 -msgid "The script used to validate the label" -msgstr "" - -#: forms/codepoints.py:109 -#, python-format -msgid "Maximum length: %d code points" +#: forms/codepoints.py:96 +msgid "File type" msgstr "" #: forms/importer.py:13 msgid "Name" msgstr "" -#: forms/importer.py:14 forms/importer.py:27 forms/metadata.py:50 -msgid "Validating repertoire" -msgstr "" - #: forms/importer.py:15 forms/importer.py:28 msgid "Code points will be limited to the selected repertoire" msgstr "" @@ -137,6 +122,18 @@ msgstr "" msgid "The name of the set" msgstr "" +#: forms/labels.py:14 +msgid "Label" +msgstr "" + +#: forms/labels.py:15 forms/metadata.py:46 +msgid "Unicode version" +msgstr "" + +#: forms/labels.py:17 +msgid "The unicode version used" +msgstr "" + #: forms/metadata.py:39 msgid "Version" msgstr "" @@ -165,13 +162,9 @@ msgstr "" msgid "Validity end" msgstr "" -#: forms/metadata.py:46 -msgid "Unicode version" -msgstr "" - -#: forms/metadata.py:47 templates/lgr_editor/codepoint_view.html:212 +#: forms/metadata.py:47 templates/lgr_editor/codepoint_view.html:227 #: templates/lgr_editor/references.html:14 -#: templates/lgr_editor/references.html:50 +#: templates/lgr_editor/references.html:51 msgid "Description" msgstr "" @@ -231,107 +224,121 @@ msgstr "" #: lgr_exceptions.py:59 #, python-format -msgid "Code point %(codepoint)s has invalid context rule" +msgid "Code point %(codepoint)s has invalid context rule %(rule)s" msgstr "" -#: lgr_exceptions.py:63 +#: lgr_exceptions.py:64 #, python-format msgid "Range %(first_cp)s - %(last_cp)s has invalid context rule" msgstr "" -#: lgr_exceptions.py:68 +#: lgr_exceptions.py:69 #, python-format msgid "" "Variant %(variant_codepoint)s of code point %(codepoint)shas invalid context " "rule" msgstr "" -#: lgr_exceptions.py:74 +#: lgr_exceptions.py:75 #, python-format msgid "Duplicate reference for code point %(codepoint)s" msgstr "" -#: lgr_exceptions.py:78 +#: lgr_exceptions.py:79 #, python-format msgid "Unspecified exception for input code point %(codepoint)s" msgstr "" -#: lgr_exceptions.py:85 -msgid "Invalid date value" +#: lgr_exceptions.py:86 +msgid "Sequence cannot have a tag" msgstr "" -#: lgr_exceptions.py:87 +#: lgr_exceptions.py:88 msgid "Invalid language" msgstr "" -#: lgr_exceptions.py:89 +#: lgr_exceptions.py:90 +msgid "Invalid date value" +msgstr "" + +#: lgr_exceptions.py:92 msgid "Invalid Unicode version" msgstr "" -#: lgr_exceptions.py:91 +#: lgr_exceptions.py:94 msgid "Invalid LGR XML file" msgstr "" -#: lgr_exceptions.py:93 +#: lgr_exceptions.py:96 #, python-format msgid "Reference %(ref_id)s is not defined" msgstr "" -#: lgr_exceptions.py:97 +#: lgr_exceptions.py:100 #, python-format msgid "Reference %(ref_id)s already exists" msgstr "" -#: lgr_exceptions.py:101 +#: lgr_exceptions.py:104 +#, python-format +msgid "Invalid reference id %(ref_id)s " +msgstr "" + +#: lgr_exceptions.py:108 #, python-format msgid "Rule \"%(rule_name)s\" cannot be processed (%(message)s)" msgstr "" -#: lgr_exceptions.py:106 +#: lgr_exceptions.py:113 msgid "Input parameter has invalid format" msgstr "" -#: lgr_exceptions.py:108 +#: lgr_exceptions.py:115 msgid "A general exception occurred in the LGR API" msgstr "" -#: lgr_exceptions.py:110 +#: lgr_exceptions.py:117 #, python-format msgid "LGR is not valid (%(args)s)" msgstr "" -#: lgr_exceptions.py:112 +#: lgr_exceptions.py:119 #, python-format msgid "Label %(label)s is not valid in the LGR (%(message)s)" msgstr "" -#: lgr_exceptions.py:117 +#: lgr_exceptions.py:124 msgid "Input label file contains collision(s)" msgstr "" -#: lgr_exceptions.py:119 +#: lgr_exceptions.py:126 msgid "The LGR contains a variant that do not have symmetric relations" msgstr "" -#: lgr_exceptions.py:122 +#: lgr_exceptions.py:129 +#, python-format +msgid "The LGR does not contain a valid language (%(message)s)" +msgstr "" + +#: lgr_exceptions.py:131 msgid "An unknown exception occurred in the LGR API" msgstr "" -#: templates/lgr_editor/_editor_base.html:23 +#: templates/lgr_editor/_editor_base.html:25 #: templates/lgr_editor/codepoint_view.html:54 msgid "References" msgstr "" -#: templates/lgr_editor/_editor_base.html:26 +#: templates/lgr_editor/_editor_base.html:28 msgid "Meta data" msgstr "" -#: templates/lgr_editor/_editor_base.html:29 templates/lgr_editor/rules.html:18 +#: templates/lgr_editor/_editor_base.html:34 templates/lgr_editor/rules.html:18 #: templates/lgr_editor/rules_edit.html:57 msgid "Rules" msgstr "" -#: templates/lgr_editor/_editor_base.html:34 +#: templates/lgr_editor/_editor_base.html:39 msgid "Embedded LGRs" msgstr "" @@ -346,7 +353,7 @@ msgid "%(lgr_name)s" msgstr "" #: templates/lgr_editor/_rule_editor_widgets.html:5 -#: templates/lgr_editor/codepoint_view.html:229 +#: templates/lgr_editor/codepoint_view.html:244 #: templates/lgr_editor/metadata.html:32 #: templates/lgr_editor/rules_edit.html:40 #: templates/lgr_editor/rules_edit.html:71 @@ -364,30 +371,38 @@ msgid "Save" msgstr "" #: templates/lgr_editor/_rule_editor_widgets.html:11 -#: templates/lgr_editor/codepoint_view.html:160 +#: templates/lgr_editor/codepoint_view.html:165 msgid "Edit" msgstr "" #: templates/lgr_editor/about.html:3 msgid "" -"This application provides a convenient interface for browsing and editing " -"LGR’s conforming to the Representing Label Generation Rulesets using XML specification." +"\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 "" #: templates/lgr_editor/about.html:10 msgid "Supported Unicode versions:" msgstr "" -#: templates/lgr_editor/about.html:17 +#: templates/lgr_editor/about.html:18 msgid "" -"This toolset was implemented by Viagenie and Wil Tan on an ICANN contract." +"This toolset was implemented by Viagénie and Wil Tan on an ICANN contract." msgstr "" #: templates/lgr_editor/add_list.html:8 +#: templates/lgr_editor/add_list_from_script.html:11 #: templates/lgr_editor/add_list_import.html:11 #: templates/lgr_editor/add_list_range.html:11 +#: templates/lgr_editor/codepoint_list.html:69 +#: templates/lgr_editor/codepoint_list.html:90 msgid "Next" msgstr "" @@ -398,54 +413,108 @@ msgid "" "are not redirected automatically." msgstr "" -#: templates/lgr_editor/codepoint_list.html:10 +#: templates/lgr_editor/codepoint_list.html:21 +msgid "Populate variants" +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:25 msgid "Expand range(s)" msgstr "" -#: templates/lgr_editor/codepoint_list.html:11 -#: templates/lgr_editor/codepoint_list.html:50 +#: templates/lgr_editor/codepoint_list.html:27 +#: templates/lgr_editor/codepoint_list.html:106 msgid "Add code point(s)" msgstr "" -#: templates/lgr_editor/codepoint_list.html:17 +#: templates/lgr_editor/codepoint_list.html:39 msgid "Character Name" msgstr "" -#: templates/lgr_editor/codepoint_list.html:18 +#: templates/lgr_editor/codepoint_list.html:41 #: templates/lgr_editor/codepoint_view.html:51 msgid "Comments" msgstr "" -#: templates/lgr_editor/codepoint_list.html:19 +#: templates/lgr_editor/codepoint_list.html:42 #: templates/lgr_editor/codepoint_view.html:56 -#: templates/lgr_editor/references.html:17 +#: templates/lgr_editor/references.html:17 templates/lgr_editor/tags.html:14 msgid "Action" msgstr "" -#: templates/lgr_editor/codepoint_list.html:29 -msgid "Variant(s)" +#: templates/lgr_editor/codepoint_list.html:52 +#: templates/lgr_editor/codepoint_list.html:82 +msgid "Add Rule" msgstr "" -#: templates/lgr_editor/codepoint_list.html:32 -msgid "See code point" +#: templates/lgr_editor/codepoint_list.html:57 +msgid "There is no rule in the current LGR" msgstr "" -#: templates/lgr_editor/codepoint_list.html:35 -msgid "Expand range" +#: templates/lgr_editor/codepoint_list.html:60 +msgid "Close" msgstr "" -#: templates/lgr_editor/codepoint_list.html:59 +#: templates/lgr_editor/codepoint_list.html:66 +msgid "" +"\n" +"

This rule will be added to codepoint(s)

\n" +" " +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:87 +msgid "" +"\n" +"

These tags will be added to codepoint(s)

\n" +" " +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:115 msgid "Code point range" msgstr "" -#: templates/lgr_editor/codepoint_list.html:62 +#: templates/lgr_editor/codepoint_list.html:118 +msgid "Code point from script" +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:121 msgid "Import from file" msgstr "" -#: templates/lgr_editor/codepoint_list.html:74 +#: templates/lgr_editor/codepoint_list.html:133 msgid "Add Code Point" msgstr "" +#: templates/lgr_editor/codepoint_list.html:224 +msgid "Variant(s)" +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:240 +msgid "See code point" +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:243 +msgid "Expand range" +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:273 +#: templates/lgr_editor/codepoint_list.html:297 +msgid "➡ Select code point(s) to apply batch action..." +msgstr "" + +#: templates/lgr_editor/codepoint_list.html:274 +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 "" + #: templates/lgr_editor/codepoint_view.html:26 #, python-format msgid "Code point appeared in Unicode version: %(age)s" @@ -463,78 +532,86 @@ msgstr "" msgid "Not When" msgstr "" -#: templates/lgr_editor/codepoint_view.html:73 +#: templates/lgr_editor/codepoint_view.html:74 msgid "Code point is not in LGR" msgstr "" -#: templates/lgr_editor/codepoint_view.html:103 +#: templates/lgr_editor/codepoint_view.html:104 msgid "Are you sure you want delete this variant?" msgstr "" -#: templates/lgr_editor/codepoint_view.html:103 +#: templates/lgr_editor/codepoint_view.html:104 msgid "Delete variant" msgstr "" -#: templates/lgr_editor/codepoint_view.html:104 +#: templates/lgr_editor/codepoint_view.html:105 msgid "Edit references" msgstr "" -#: templates/lgr_editor/codepoint_view.html:113 +#: templates/lgr_editor/codepoint_view.html:114 msgid "Range characters do not have variants." msgstr "" -#: templates/lgr_editor/codepoint_view.html:115 +#: templates/lgr_editor/codepoint_view.html:116 msgid "Code point has not variant" msgstr "" -#: templates/lgr_editor/codepoint_view.html:132 +#: templates/lgr_editor/codepoint_view.html:137 msgid "Save variants, tags, context rules and comment" msgstr "" -#: templates/lgr_editor/codepoint_view.html:154 +#: templates/lgr_editor/codepoint_view.html:159 msgid "No references associated with code point." msgstr "" -#: templates/lgr_editor/codepoint_view.html:167 +#: templates/lgr_editor/codepoint_view.html:172 msgid "Are you sure you want delete this code point?" msgstr "" -#: templates/lgr_editor/codepoint_view.html:169 +#: templates/lgr_editor/codepoint_view.html:174 msgid "Delete code point" msgstr "" -#: templates/lgr_editor/codepoint_view.html:180 +#: templates/lgr_editor/codepoint_view.html:185 msgid "Edit References for " msgstr "" -#: templates/lgr_editor/codepoint_view.html:186 +#: templates/lgr_editor/codepoint_view.html:191 msgctxt "button title" msgid "Delete reference" msgstr "" -#: templates/lgr_editor/codepoint_view.html:195 +#: templates/lgr_editor/codepoint_view.html:200 msgid "Add an existing reference" msgstr "" -#: templates/lgr_editor/codepoint_view.html:204 -#: templates/lgr_editor/references.html:58 +#: templates/lgr_editor/codepoint_view.html:209 +#: templates/lgr_editor/references.html:60 msgid "Add" msgstr "" -#: templates/lgr_editor/codepoint_view.html:210 +#: templates/lgr_editor/codepoint_view.html:215 msgid "Create a new reference" msgstr "" -#: templates/lgr_editor/codepoint_view.html:216 +#: templates/lgr_editor/codepoint_view.html:219 +msgid "Error when adding reference" +msgstr "" + +#: templates/lgr_editor/codepoint_view.html:223 +msgid "Reference ID (optional)" +msgstr "" + +#: templates/lgr_editor/codepoint_view.html:231 msgid "URL (optional)" msgstr "" -#: templates/lgr_editor/codepoint_view.html:222 +#: templates/lgr_editor/codepoint_view.html:237 #: templates/lgr_editor/references.html:44 msgid "New reference" msgstr "" -#: templates/lgr_editor/codepoint_view.html:230 +#: templates/lgr_editor/codepoint_view.html:245 msgid "Save changes" msgstr "" @@ -552,15 +629,23 @@ msgid "" "automatically be created." msgstr "" -#: templates/lgr_editor/import_form.html:35 +#: templates/lgr_editor/import_form.html:12 +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 "" + +#: templates/lgr_editor/import_form.html:43 msgid "These LGRs are already imported. Click on one to access it." msgstr "" -#: templates/lgr_editor/import_form.html:42 +#: templates/lgr_editor/import_form.html:50 msgid "Import" msgstr "" -#: templates/lgr_editor/import_form.html:47 +#: templates/lgr_editor/import_form.html:55 msgid "" " " "Note that importing large LGR files may take significant time to load on " @@ -571,6 +656,22 @@ msgstr "" msgid "Cannot import LGR file(s):" msgstr "" +#: templates/lgr_editor/label_forms.html:11 +msgid "Display forms" +msgstr "" + +#: templates/lgr_editor/label_forms.html:18 +msgid "Code point sequence" +msgstr "" + +#: templates/lgr_editor/label_forms.html:19 +msgid "U-label" +msgstr "" + +#: templates/lgr_editor/label_forms.html:20 +msgid "A-label" +msgstr "" + #: templates/lgr_editor/metadata.html:11 msgid "There was an error saving; please see error(s) below" msgstr "" @@ -592,11 +693,12 @@ msgid "Existing references" msgstr "" #: templates/lgr_editor/references.html:13 +#: templates/lgr_editor/references.html:50 msgid "Reference id" msgstr "" #: templates/lgr_editor/references.html:15 -#: templates/lgr_editor/references.html:51 +#: templates/lgr_editor/references.html:52 msgid "URL" msgstr "" @@ -640,176 +742,247 @@ msgstr "" msgid "New action" msgstr "" -#: views.py:97 +#: templates/lgr_editor/tags.html:7 +msgid "Existing tags" +msgstr "" + +#: templates/lgr_editor/tags.html:11 +msgid "Tag name" +msgstr "" + +#: templates/lgr_editor/tags.html:12 +msgid "Associated code points" +msgstr "" + +#: templates/lgr_editor/tags.html:38 +#, python-format +msgid "View all (%(nb_cp)s)" +msgstr "" + +#: templates/lgr_editor/tags.html:56 +msgid "Delete Tag" +msgstr "" + +#: templates/lgr_editor/tags.html:57 +#, python-format +msgid "Are you sure you want delete tag %(tag)s?" +msgstr "" + +#: templates/lgr_editor/tags.html:70 +msgid "" +"To create a new tag:\n" +" Add it to a code point first to find it back in this list" +msgstr "" + +#: views.py:114 msgid "" "The LGR you have tried to create already exists in your working session. " "Please use a new name." msgstr "" -#: views.py:131 +#: views.py:148 msgid "" "The LGR you have tried to import already exists in your working session. " "Please rename it before importing it." msgstr "" -#: views.py:137 +#: views.py:154 msgid "" "The LGR you have tried to import already exists in your set. Please rename " "it before importing it." msgstr "" -#: views.py:160 +#: views.py:177 msgid "The LGR set name already exists. Please use another name." msgstr "" -#: views.py:253 -msgid "summary" +#: views.py:289 +#, python-format +msgid "New code point %s added" msgstr "" -#: views.py:280 +#: views.py:362 +msgid "Rule" +msgstr "" + +#: views.py:362 +msgid "Tag(s)" +msgstr "" + +#: views.py:363 +msgid "rule" +msgstr "" + +#: views.py:363 +msgid "tag(s)" +msgstr "" + +#: views.py:367 #, python-format -msgid "New code point %s added" +msgid "%(operation)s successfully added to %(nb_cp)s code point(s)" +msgstr "" + +#: views.py:372 +#, python-format +msgid "%(nb_cp)s code points were not updated to avoid invalid %(operation)s" msgstr "" -#: views.py:368 -msgid "New variant added" +#: views.py:504 +#, python-format +msgid "Automatically added codepoint %s from out-of-repertoire variant" +msgstr "" + +#: views.py:507 +#, python-format +msgid "New variant %s added" msgstr "" -#: views.py:441 +#: views.py:580 msgid "Code point edited" msgstr "" -#: views.py:621 views.py:657 +#: views.py:732 +msgid "Variants populated" +msgstr "" + +#: views.py:783 views.py:819 msgid "References updated successfully" msgstr "" -#: views.py:660 +#: views.py:822 #, 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:696 +#: views.py:858 #, python-format msgid "Code point %s has been deleted" msgstr "" -#: views.py:718 +#: views.py:880 #, python-format msgid "Variant %(var_cp)s with when='%(when)s' and not-when='%(not_when)s'" msgstr "" -#: views.py:724 +#: views.py:886 #, python-format msgid "%(var_msg_prefix)s has been deleted" msgstr "" -#: views.py:727 +#: views.py:889 #, python-format msgid "%(var_msg_prefix)s could not be deleted because it was not found" msgstr "" -#: views.py:756 +#: views.py:919 msgid "New reference created" msgstr "" -#: views.py:943 views.py:1106 views.py:1190 +#: views.py:1127 +#, 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 msgid "No body specified" msgstr "" -#: views.py:952 +#: views.py:1204 #, python-format msgid "Class \"%s\" does not exist" msgstr "" -#: views.py:956 +#: views.py:1208 #, python-format msgid "Class \"%s\" deleted." msgstr "" -#: views.py:961 +#: views.py:1213 msgid "No class element found" msgstr "" -#: views.py:963 views.py:1126 +#: views.py:1215 views.py:1377 msgid "Name attribute must be present" msgstr "" -#: views.py:967 views.py:984 views.py:1130 views.py:1147 views.py:1214 -#: views.py:1227 +#: views.py:1219 views.py:1236 views.py:1381 views.py:1398 views.py:1465 +#: views.py:1478 #, python-format msgid "" "Encountered XML syntax error: %s (line number may be wrong, try subtracting " "one from the reported line number)" msgstr "" -#: views.py:970 views.py:987 views.py:1133 views.py:1150 views.py:1217 -#: views.py:1230 +#: views.py:1222 views.py:1239 views.py:1384 views.py:1401 views.py:1468 +#: views.py:1481 msgid "Your XML is not valid" msgstr "" -#: views.py:975 +#: views.py:1227 #, python-format msgid "Class \"%s\" already exists" msgstr "" -#: views.py:977 +#: views.py:1229 #, python-format msgid "Class \"%s\" saved." msgstr "" -#: views.py:1115 +#: views.py:1366 #, python-format msgid "Rule \"%s\" does not exist" msgstr "" -#: views.py:1119 +#: views.py:1370 #, python-format msgid "Rule \"%s\" deleted." msgstr "" -#: views.py:1124 +#: views.py:1375 msgid "No rule element found" msgstr "" -#: views.py:1138 +#: views.py:1389 #, python-format msgid "Rule \"%s\" already exists" msgstr "" -#: views.py:1140 +#: views.py:1391 #, python-format msgid "Rule \"%s\" saved." msgstr "" -#: views.py:1201 +#: views.py:1452 #, python-format msgid "Action \"%s\" does not exist" msgstr "" -#: views.py:1205 +#: views.py:1456 #, python-format msgid "Action \"%s\" deleted." msgstr "" -#: views.py:1210 +#: views.py:1461 msgid "No action element found" msgstr "" -#: views.py:1220 +#: views.py:1471 msgid "Action saved." msgstr "" -#: views.py:1289 views.py:1435 +#: views.py:1540 views.py:1628 #, python-format msgid "%d code points added" msgstr "" -#: views.py:1404 +#: views.py:1597 msgid "No code point in input file" msgstr "" -#: views.py:1596 +#: views.py:1903 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 756c2f28..907f5a37 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 ff16d012..c0f71a92 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: 2017-10-30 20:24+0000\n" -"PO-Revision-Date: 2017-10-11 13:11-0400\n" +"POT-Creation-Date: 2018-09-04 16:04+0000\n" +"PO-Revision-Date: 2018-09-04 11:47-0400\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.0.3\n" +"X-Generator: Poedit 2.1.1\n" #: forms/codepoint.py:14 templates/lgr_editor/codepoint_view.html:52 msgid "When" @@ -26,43 +26,44 @@ msgstr "When" msgid "Not-When" msgstr "Not When" -#: forms/codepoint.py:16 +#: forms/codepoint.py:16 templates/lgr_editor/_editor_base.html:31 +#: templates/lgr_editor/codepoint_list.html:40 msgid "Tags" msgstr "Tags" #: forms/codepoint.py:16 msgid "space-separated tags" -msgstr "Liste de tags séparés par des espaces" +msgstr "liste de tags séparés par des espaces" -#: forms/codepoints.py:45 forms/codepoints.py:85 -#: templates/lgr_editor/codepoint_list.html:16 -#: templates/lgr_editor/codepoint_list.html:56 +#: forms/codepoints.py:48 forms/codepoints.py:103 +#: templates/lgr_editor/codepoint_list.html:38 +#: templates/lgr_editor/codepoint_list.html:112 #: templates/lgr_editor/codepoint_view.html:49 msgid "Code point" msgstr "Code point" -#: forms/codepoints.py:46 forms/codepoints.py:86 +#: forms/codepoints.py:49 forms/codepoints.py:104 msgid "Override repertoire" msgstr "Ignorer le répertoire" -#: forms/codepoints.py:51 templates/lgr_editor/_editor_base.html:20 +#: forms/codepoints.py:54 templates/lgr_editor/_editor_base.html:22 #: templates/lgr_editor/codepoint_view.html:22 msgid "Code points" msgstr "Code points" -#: forms/codepoints.py:55 +#: forms/codepoints.py:58 msgid "Disabled code points" msgstr "Code points indisponibles" -#: forms/codepoints.py:62 +#: forms/codepoints.py:65 msgid "First code point" msgstr "Premier code point" -#: forms/codepoints.py:63 +#: forms/codepoints.py:66 msgid "Last code point" msgstr "Dernier code point" -#: forms/codepoints.py:71 +#: forms/codepoints.py:72 #, python-format msgid "" "Last code point (%(last_cp)s) must not be smaller than the first code point " @@ -71,56 +72,39 @@ msgstr "" "Le dernier code point (%(last_cp)s) ne peut être plus petit que le premier " "code point (%(first_cp)s)" -#: forms/codepoints.py:77 -msgid "Select a file" -msgstr "Sélectionner un fichier" +#: forms/codepoints.py:78 forms/importer.py:14 forms/importer.py:27 +#: forms/metadata.py:50 +msgid "Validating repertoire" +msgstr "Répertoire de validation" -#: forms/codepoints.py:78 -msgid "File type" -msgstr "Type de fichier" +#: forms/codepoints.py:82 +msgid "Script" +msgstr "Script" -#: forms/codepoints.py:80 +#: forms/codepoints.py:84 forms/codepoints.py:98 msgid "Manual import" msgstr "Importation manuelle" -#: forms/codepoints.py:91 -msgid "Label" -msgstr "Label" - -#: forms/codepoints.py:92 -msgid "Allocated Set labels" -msgstr "Labels du set alloués" +#: forms/codepoints.py:93 +msgid "Select a file" +msgstr "Sélectionner un fichier" #: forms/codepoints.py:94 msgid "" -"Optional list of labels already allocated in the LGR set, that will be used " -"to check for collisions when evaluating labels using the merged LGR set" +"File containing data to be imported. File must be encoded in UTF-8 and using " +"UNIX line ending." msgstr "" -"Liste optionelle de labels déjà alloués dans le set LGR, qui seront utilisés " -"pour vérifier les collisions lors de l'évaluation de labels en utilisant le " -"set LGR fusionné" - -#: forms/codepoints.py:98 -msgid "Script" -msgstr "Script" - -#: forms/codepoints.py:100 -msgid "The script used to validate the label" -msgstr "Script utilisé pour valider le label" +"Fichier contenant les données à être importées. Le fichier doit être encodé " +"en UTF-8 et utiliser les retours à la ligne au format UNIX." -#: forms/codepoints.py:109 -#, python-format -msgid "Maximum length: %d code points" -msgstr "Longueur maximale : %d code points" +#: forms/codepoints.py:96 +msgid "File type" +msgstr "Type de fichier" #: forms/importer.py:13 msgid "Name" msgstr "Nom" -#: forms/importer.py:14 forms/importer.py:27 forms/metadata.py:50 -msgid "Validating repertoire" -msgstr "Répertoire de validation" - #: forms/importer.py:15 forms/importer.py:28 msgid "Code points will be limited to the selected repertoire" msgstr "Les code points seront limités au répertoire sélectionné" @@ -145,6 +129,18 @@ msgstr "" msgid "The name of the set" msgstr "Nom du set" +#: forms/labels.py:14 +msgid "Label" +msgstr "Label" + +#: forms/labels.py:15 forms/metadata.py:46 +msgid "Unicode version" +msgstr "Version d'Unicode" + +#: forms/labels.py:17 +msgid "The unicode version used" +msgstr "Version d'Unicode" + #: forms/metadata.py:39 msgid "Version" msgstr "Version" @@ -173,13 +169,9 @@ msgstr "Début de la validité" msgid "Validity end" msgstr "Fin de la validité" -#: forms/metadata.py:46 -msgid "Unicode version" -msgstr "Version d'Unicode" - -#: forms/metadata.py:47 templates/lgr_editor/codepoint_view.html:212 +#: forms/metadata.py:47 templates/lgr_editor/codepoint_view.html:227 #: templates/lgr_editor/references.html:14 -#: templates/lgr_editor/references.html:50 +#: templates/lgr_editor/references.html:51 msgid "Description" msgstr "Description" @@ -243,16 +235,16 @@ msgstr "" #: lgr_exceptions.py:59 #, python-format -msgid "Code point %(codepoint)s has invalid context rule" -msgstr "Le code point %(codepoint)s a une règle contextuelle invalide" +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:63 +#: lgr_exceptions.py:64 #, 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:68 +#: lgr_exceptions.py:69 #, python-format msgid "" "Variant %(variant_codepoint)s of code point %(codepoint)shas invalid context " @@ -261,92 +253,106 @@ msgstr "" "La variante %(variant_codepoint)s du code point %(codepoint)s a une règle " "contextuelle invalide" -#: lgr_exceptions.py:74 +#: lgr_exceptions.py:75 #, 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:78 +#: lgr_exceptions.py:79 #, 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:85 -msgid "Invalid date value" -msgstr "Date invalide" +#: lgr_exceptions.py:86 +msgid "Sequence cannot have a tag" +msgstr "Les séquences ne peuvent pas avoir de tag" -#: lgr_exceptions.py:87 +#: lgr_exceptions.py:88 msgid "Invalid language" msgstr "Langage invalide" -#: lgr_exceptions.py:89 +#: lgr_exceptions.py:90 +msgid "Invalid date value" +msgstr "Date invalide" + +#: lgr_exceptions.py:92 msgid "Invalid Unicode version" msgstr "Version d'unicode invalide" -#: lgr_exceptions.py:91 +#: lgr_exceptions.py:94 msgid "Invalid LGR XML file" msgstr "Fichier XML de LGR invalide" -#: lgr_exceptions.py:93 +#: lgr_exceptions.py:96 #, 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:97 +#: lgr_exceptions.py:100 #, python-format msgid "Reference %(ref_id)s already exists" msgstr "La référence %(ref_id)s existe déjà" -#: lgr_exceptions.py:101 +#: lgr_exceptions.py:104 +#, python-format +msgid "Invalid reference id %(ref_id)s " +msgstr "Identifiant de référence invalide %(ref_id)s " + +#: lgr_exceptions.py:108 #, 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:106 +#: lgr_exceptions.py:113 msgid "Input parameter has invalid format" msgstr "Le paramètre d'entrée a un format invalide" -#: lgr_exceptions.py:108 +#: lgr_exceptions.py:115 msgid "A general exception occurred in the LGR API" msgstr "Une exception s'est produite dans l'API LGR" -#: lgr_exceptions.py:110 +#: lgr_exceptions.py:117 #, python-format msgid "LGR is not valid (%(args)s)" msgstr "La LGR n'est pas valide (%(args)s)" -#: lgr_exceptions.py:112 +#: lgr_exceptions.py:119 #, 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:117 +#: lgr_exceptions.py:124 msgid "Input label file contains collision(s)" msgstr "Le fichier d'entrée des labels contient une/des collision(s)" -#: lgr_exceptions.py:119 +#: lgr_exceptions.py:126 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:122 +#: lgr_exceptions.py:129 +#, 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 msgid "An unknown exception occurred in the LGR API" msgstr "Une exception inconnue s'est produite dans l'API LGR" -#: templates/lgr_editor/_editor_base.html:23 +#: templates/lgr_editor/_editor_base.html:25 #: templates/lgr_editor/codepoint_view.html:54 msgid "References" msgstr "Références" -#: templates/lgr_editor/_editor_base.html:26 +#: templates/lgr_editor/_editor_base.html:28 msgid "Meta data" msgstr "Métadonnées" -#: templates/lgr_editor/_editor_base.html:29 templates/lgr_editor/rules.html:18 +#: templates/lgr_editor/_editor_base.html:34 templates/lgr_editor/rules.html:18 #: templates/lgr_editor/rules_edit.html:57 msgid "Rules" msgstr "Règles" -#: templates/lgr_editor/_editor_base.html:34 +#: templates/lgr_editor/_editor_base.html:39 msgid "Embedded LGRs" msgstr "LGR embarquées" @@ -361,7 +367,7 @@ msgid "%(lgr_name)s" msgstr "%(lgr_name)s" #: templates/lgr_editor/_rule_editor_widgets.html:5 -#: templates/lgr_editor/codepoint_view.html:229 +#: templates/lgr_editor/codepoint_view.html:244 #: templates/lgr_editor/metadata.html:32 #: templates/lgr_editor/rules_edit.html:40 #: templates/lgr_editor/rules_edit.html:71 @@ -379,37 +385,47 @@ msgid "Save" msgstr "Sauvegarder" #: templates/lgr_editor/_rule_editor_widgets.html:11 -#: templates/lgr_editor/codepoint_view.html:160 +#: templates/lgr_editor/codepoint_view.html:165 msgid "Edit" msgstr "Modifier" #: templates/lgr_editor/about.html:3 msgid "" -"This application provides a convenient interface for browsing and editing " -"LGR’s conforming to the Representing Label Generation Rulesets using XML specification." +"\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." +"XML.\n" +" " #: templates/lgr_editor/about.html:10 msgid "Supported Unicode versions:" msgstr "Versions d'Unicode supportées:" -#: templates/lgr_editor/about.html:17 +#: templates/lgr_editor/about.html:18 msgid "" -"This toolset was implemented by Viagenie and Wil Tan on an ICANN contract." +"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." +"Cette application a été implémentée par Viagénie et Wil Tan sous contrat ICANN." #: templates/lgr_editor/add_list.html:8 +#: templates/lgr_editor/add_list_from_script.html:11 #: templates/lgr_editor/add_list_import.html:11 #: templates/lgr_editor/add_list_range.html:11 +#: templates/lgr_editor/codepoint_list.html:69 +#: templates/lgr_editor/codepoint_list.html:90 msgid "Next" msgstr "Suivant" @@ -422,54 +438,117 @@ msgstr "" "Code point ajouté. Cliquez ici si vous " "n'êtes pas redirigé automatiquement." -#: templates/lgr_editor/codepoint_list.html:10 +#: templates/lgr_editor/codepoint_list.html:21 +msgid "Populate variants" +msgstr "Peupler les variantes" + +#: templates/lgr_editor/codepoint_list.html:25 msgid "Expand range(s)" msgstr "Convertir tous les ensembles" -#: templates/lgr_editor/codepoint_list.html:11 -#: templates/lgr_editor/codepoint_list.html:50 +#: templates/lgr_editor/codepoint_list.html:27 +#: templates/lgr_editor/codepoint_list.html:106 msgid "Add code point(s)" msgstr "Ajouter un/des code point(s)" -#: templates/lgr_editor/codepoint_list.html:17 +#: templates/lgr_editor/codepoint_list.html:39 msgid "Character Name" msgstr "Nom du caractère" -#: templates/lgr_editor/codepoint_list.html:18 +#: templates/lgr_editor/codepoint_list.html:41 #: templates/lgr_editor/codepoint_view.html:51 msgid "Comments" msgstr "Commentaires" -#: templates/lgr_editor/codepoint_list.html:19 +#: templates/lgr_editor/codepoint_list.html:42 #: templates/lgr_editor/codepoint_view.html:56 -#: templates/lgr_editor/references.html:17 +#: templates/lgr_editor/references.html:17 templates/lgr_editor/tags.html:14 msgid "Action" msgstr "Action" -#: templates/lgr_editor/codepoint_list.html:29 -msgid "Variant(s)" -msgstr "Variante(s)" +#: templates/lgr_editor/codepoint_list.html:52 +#: templates/lgr_editor/codepoint_list.html:82 +msgid "Add Rule" +msgstr "Ajouter une règle" -#: templates/lgr_editor/codepoint_list.html:32 -msgid "See code point" -msgstr "Voir le code point" +#: templates/lgr_editor/codepoint_list.html:57 +msgid "There is no rule in the current LGR" +msgstr "Il n'y a pas de règles dans la LGR courante" -#: templates/lgr_editor/codepoint_list.html:35 -msgid "Expand range" -msgstr "Convertir l'ensemble" +#: templates/lgr_editor/codepoint_list.html:60 +msgid "Close" +msgstr "Fermer" + +#: templates/lgr_editor/codepoint_list.html:66 +msgid "" +"\n" +"

This rule will be added to codepoint(s)

\n" +" " +msgstr "" +"\n" +"

Cette règle va être ajoutée à " +" code point(s)

\n" +" " + +#: templates/lgr_editor/codepoint_list.html:87 +msgid "" +"\n" +"

These tags will be added to codepoint(s)

\n" +" " +msgstr "" +"\n" +"

Ces tags vont être ajoutées à code point(s)

\n" +" " -#: templates/lgr_editor/codepoint_list.html:59 +#: templates/lgr_editor/codepoint_list.html:115 msgid "Code point range" msgstr "Ensemble de Code points" -#: templates/lgr_editor/codepoint_list.html:62 +#: templates/lgr_editor/codepoint_list.html:118 +msgid "Code point from script" +msgstr "Code point depuis un script" + +#: templates/lgr_editor/codepoint_list.html:121 msgid "Import from file" msgstr "Importer depuis un fichier" -#: templates/lgr_editor/codepoint_list.html:74 +#: templates/lgr_editor/codepoint_list.html:133 msgid "Add Code Point" msgstr "Ajouter un Code Point" +#: templates/lgr_editor/codepoint_list.html:224 +msgid "Variant(s)" +msgstr "Variante(s)" + +#: templates/lgr_editor/codepoint_list.html:240 +msgid "See code point" +msgstr "Voir le code point" + +#: templates/lgr_editor/codepoint_list.html:243 +msgid "Expand range" +msgstr "Convertir l'ensemble" + +#: templates/lgr_editor/codepoint_list.html:273 +#: templates/lgr_editor/codepoint_list.html:297 +msgid "➡ Select code point(s) to apply batch action..." +msgstr "" +"➡ Sélectionner les code points sur lesquels appliquer une action par lots..." + +#: templates/lgr_editor/codepoint_list.html:274 +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..." + #: templates/lgr_editor/codepoint_view.html:26 #, python-format msgid "Code point appeared in Unicode version: %(age)s" @@ -487,78 +566,86 @@ msgstr "Type" msgid "Not When" msgstr "Not When" -#: templates/lgr_editor/codepoint_view.html:73 +#: templates/lgr_editor/codepoint_view.html:74 msgid "Code point is not in LGR" msgstr "Le code point n'est pas dans la LGR" -#: templates/lgr_editor/codepoint_view.html:103 +#: templates/lgr_editor/codepoint_view.html:104 msgid "Are you sure you want delete this variant?" msgstr "Êtes-vous sûr(e) de vouloir supprimer cette variante ?" -#: templates/lgr_editor/codepoint_view.html:103 +#: templates/lgr_editor/codepoint_view.html:104 msgid "Delete variant" msgstr "Supprimer la variante" -#: templates/lgr_editor/codepoint_view.html:104 +#: templates/lgr_editor/codepoint_view.html:105 msgid "Edit references" msgstr "Modifier les références" -#: templates/lgr_editor/codepoint_view.html:113 +#: templates/lgr_editor/codepoint_view.html:114 msgid "Range characters do not have variants." msgstr "Les ensembles de caractères n'ont pas de variantes." -#: templates/lgr_editor/codepoint_view.html:115 +#: templates/lgr_editor/codepoint_view.html:116 msgid "Code point has not variant" msgstr "Le code point n'a pas de variante" -#: templates/lgr_editor/codepoint_view.html:132 +#: templates/lgr_editor/codepoint_view.html:137 msgid "Save variants, tags, context rules and comment" msgstr "Sauvegarder les variantes, tags, règles contextuelles et commentaires" -#: templates/lgr_editor/codepoint_view.html:154 +#: templates/lgr_editor/codepoint_view.html:159 msgid "No references associated with code point." msgstr "Aucune référence associée au code point." -#: templates/lgr_editor/codepoint_view.html:167 +#: templates/lgr_editor/codepoint_view.html:172 msgid "Are you sure you want delete this code point?" msgstr "Êtes-vous sûr(e) de vouloir supprimer ce code point ?" -#: templates/lgr_editor/codepoint_view.html:169 +#: templates/lgr_editor/codepoint_view.html:174 msgid "Delete code point" msgstr "Supprimer le code point" -#: templates/lgr_editor/codepoint_view.html:180 +#: templates/lgr_editor/codepoint_view.html:185 msgid "Edit References for " msgstr "Modifier les références pour " -#: templates/lgr_editor/codepoint_view.html:186 +#: templates/lgr_editor/codepoint_view.html:191 msgctxt "button title" msgid "Delete reference" msgstr "Supprimer la référence" -#: templates/lgr_editor/codepoint_view.html:195 +#: templates/lgr_editor/codepoint_view.html:200 msgid "Add an existing reference" msgstr "Ajouter un référence existante" -#: templates/lgr_editor/codepoint_view.html:204 -#: templates/lgr_editor/references.html:58 +#: templates/lgr_editor/codepoint_view.html:209 +#: templates/lgr_editor/references.html:60 msgid "Add" msgstr "Ajouter" -#: templates/lgr_editor/codepoint_view.html:210 +#: templates/lgr_editor/codepoint_view.html:215 msgid "Create a new reference" msgstr "Créer une nouvelle référence" -#: templates/lgr_editor/codepoint_view.html:216 +#: templates/lgr_editor/codepoint_view.html:219 +msgid "Error when adding reference" +msgstr "Erreur lors de l'ajout d'une référence" + +#: templates/lgr_editor/codepoint_view.html:223 +msgid "Reference ID (optional)" +msgstr "Id de référence (optionnel)" + +#: templates/lgr_editor/codepoint_view.html:231 msgid "URL (optional)" msgstr "URL (optionnelle)" -#: templates/lgr_editor/codepoint_view.html:222 +#: templates/lgr_editor/codepoint_view.html:237 #: templates/lgr_editor/references.html:44 msgid "New reference" msgstr "Nouvelle référence" -#: templates/lgr_editor/codepoint_view.html:230 +#: templates/lgr_editor/codepoint_view.html:245 msgid "Save changes" msgstr "Sauvegarder les changements" @@ -578,15 +665,27 @@ msgstr "" "Pour importer un set LGR, sélectionner les fichiers XML le set LGR. Le set " "sera créé automatiquement." -#: templates/lgr_editor/import_form.html:35 +#: templates/lgr_editor/import_form.html:12 +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. " + +#: templates/lgr_editor/import_form.html:43 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." -#: templates/lgr_editor/import_form.html:42 +#: templates/lgr_editor/import_form.html:50 msgid "Import" msgstr "Importer" -#: templates/lgr_editor/import_form.html:47 +#: templates/lgr_editor/import_form.html:55 msgid "" " " "Note that importing large LGR files may take significant time to load on " @@ -600,6 +699,22 @@ msgstr "" msgid "Cannot import LGR file(s):" msgstr "Impossible d'importer le(s) fichier(s) LGR :" +#: templates/lgr_editor/label_forms.html:11 +msgid "Display forms" +msgstr "Afficher les formes" + +#: templates/lgr_editor/label_forms.html:18 +msgid "Code point sequence" +msgstr "Séquence de code points" + +#: templates/lgr_editor/label_forms.html:19 +msgid "U-label" +msgstr "U-Label" + +#: templates/lgr_editor/label_forms.html:20 +msgid "A-label" +msgstr "A-Label" + #: templates/lgr_editor/metadata.html:11 msgid "There was an error saving; please see error(s) below" msgstr "" @@ -622,11 +737,12 @@ msgid "Existing references" msgstr "Références existantes" #: templates/lgr_editor/references.html:13 +#: templates/lgr_editor/references.html:50 msgid "Reference id" msgstr "Identifiant de référence" #: templates/lgr_editor/references.html:15 -#: templates/lgr_editor/references.html:51 +#: templates/lgr_editor/references.html:52 msgid "URL" msgstr "URL" @@ -670,7 +786,42 @@ msgstr "Nouvelle règle" msgid "New action" msgstr "Nouvelle action" -#: views.py:97 +#: templates/lgr_editor/tags.html:7 +msgid "Existing tags" +msgstr "Tags existants" + +#: templates/lgr_editor/tags.html:11 +msgid "Tag name" +msgstr "Nom du tag" + +#: templates/lgr_editor/tags.html:12 +msgid "Associated code points" +msgstr "Code points associés" + +#: templates/lgr_editor/tags.html:38 +#, python-format +msgid "View all (%(nb_cp)s)" +msgstr "Voir tout (%(nb_cp)s)" + +#: templates/lgr_editor/tags.html:56 +msgid "Delete Tag" +msgstr "Supprimer le tag" + +#: templates/lgr_editor/tags.html:57 +#, python-format +msgid "Are you sure you want delete tag %(tag)s?" +msgstr "Êtes-vous sûr(e) de vouloir supprimer ce tag %(tag)s ?" + +#: templates/lgr_editor/tags.html:70 +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" + +#: views.py:114 msgid "" "The LGR you have tried to create already exists in your working session. " "Please use a new name." @@ -678,7 +829,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:131 +#: views.py:148 msgid "" "The LGR you have tried to import already exists in your working session. " "Please rename it before importing it." @@ -686,7 +837,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:137 +#: views.py:154 msgid "" "The LGR you have tried to import already exists in your set. Please rename " "it before importing it." @@ -694,32 +845,67 @@ 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:160 +#: views.py:177 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:253 -msgid "summary" -msgstr "résumé" - -#: views.py:280 +#: views.py:289 #, python-format msgid "New code point %s added" msgstr "Nouveau code point ajouté %s" -#: views.py:368 -msgid "New variant added" -msgstr "Nouvelle variante ajoutée" +#: views.py:362 +msgid "Rule" +msgstr "Règle" + +#: views.py:362 +msgid "Tag(s)" +msgstr "Tag(s)" + +#: views.py:363 +msgid "rule" +msgstr "règle" + +#: views.py:363 +msgid "tag(s)" +msgstr "tag(s)" + +#: views.py:367 +#, 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:441 +#: views.py:372 +#, 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 +#, python-format +msgid "Automatically added codepoint %s from out-of-repertoire variant" +msgstr "" +"Code point %s automatiquement ajouté depuis une variante hors-répertoire" + +#: views.py:507 +#, python-format +msgid "New variant %s added" +msgstr "Nouvelle variante %s ajoutée" + +#: views.py:580 msgid "Code point edited" msgstr "Code point modifié" -#: views.py:621 views.py:657 +#: views.py:732 +msgid "Variants populated" +msgstr "Les variantes ont été peuplées" + +#: views.py:783 views.py:819 msgid "References updated successfully" msgstr "Les références ont été correctement mises à jour" -#: views.py:660 +#: views.py:822 #, python-format msgid "" "Variant %(var_codepoint)s for code point %(codepoint)s with when=%(when)s " @@ -728,56 +914,65 @@ 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:696 +#: views.py:858 #, python-format msgid "Code point %s has been deleted" msgstr "Le code point %s a été supprimé" -#: views.py:718 +#: views.py:880 #, 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:724 +#: views.py:886 #, python-format msgid "%(var_msg_prefix)s has been deleted" msgstr "%(var_msg_prefix)s a été supprimée" -#: views.py:727 +#: views.py:889 #, 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:756 +#: views.py:919 msgid "New reference created" msgstr "Nouvelle référence créée" -#: views.py:943 views.py:1106 views.py:1190 +#: views.py:1127 +#, 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 "" +"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 msgid "No body specified" msgstr "Aucun contenu spécifié" -#: views.py:952 +#: views.py:1204 #, python-format msgid "Class \"%s\" does not exist" msgstr "La classe \"%s\" n'existe pas" -#: views.py:956 +#: views.py:1208 #, python-format msgid "Class \"%s\" deleted." msgstr "Classe \"%s\" supprimée." -#: views.py:961 +#: views.py:1213 msgid "No class element found" msgstr "Aucune classe trouvée" -#: views.py:963 views.py:1126 +#: views.py:1215 views.py:1377 msgid "Name attribute must be present" msgstr "L'attribut name est obligatoire" -#: views.py:967 views.py:984 views.py:1130 views.py:1147 views.py:1214 -#: views.py:1227 +#: views.py:1219 views.py:1236 views.py:1381 views.py:1398 views.py:1465 +#: views.py:1478 #, python-format msgid "" "Encountered XML syntax error: %s (line number may be wrong, try subtracting " @@ -786,72 +981,72 @@ msgstr "" "Erreur de syntaxe XML : %s (le numéro de ligne peut-être incorrect, essayer " "de soustraire un au numéro reporté)" -#: views.py:970 views.py:987 views.py:1133 views.py:1150 views.py:1217 -#: views.py:1230 +#: views.py:1222 views.py:1239 views.py:1384 views.py:1401 views.py:1468 +#: views.py:1481 msgid "Your XML is not valid" msgstr "Votre XML n'est pas valide" -#: views.py:975 +#: views.py:1227 #, python-format msgid "Class \"%s\" already exists" msgstr "La classe \"%s\" existe déjà" -#: views.py:977 +#: views.py:1229 #, python-format msgid "Class \"%s\" saved." msgstr "Classe \"%s\" sauvegardée." -#: views.py:1115 +#: views.py:1366 #, python-format msgid "Rule \"%s\" does not exist" msgstr "La règle \"%s\" n'existe pas" -#: views.py:1119 +#: views.py:1370 #, python-format msgid "Rule \"%s\" deleted." msgstr "Règle \"%s\" supprimée." -#: views.py:1124 +#: views.py:1375 msgid "No rule element found" msgstr "Aucune règle trouvée" -#: views.py:1138 +#: views.py:1389 #, python-format msgid "Rule \"%s\" already exists" msgstr "La règle \"%s\" existe déjà" -#: views.py:1140 +#: views.py:1391 #, python-format msgid "Rule \"%s\" saved." msgstr "Règle \"%s\" sauvegardée." -#: views.py:1201 +#: views.py:1452 #, python-format msgid "Action \"%s\" does not exist" msgstr "Action \"%s\" n'existe pas" -#: views.py:1205 +#: views.py:1456 #, python-format msgid "Action \"%s\" deleted." msgstr "Action \"%s\" supprimée." -#: views.py:1210 +#: views.py:1461 msgid "No action element found" msgstr "Aucune action trouvée" -#: views.py:1220 +#: views.py:1471 msgid "Action saved." msgstr "Action sauvée." -#: views.py:1289 views.py:1435 +#: views.py:1540 views.py:1628 #, python-format msgid "%d code points added" msgstr "%d code points ont été ajoutés" -#: views.py:1404 +#: views.py:1597 msgid "No code point in input file" msgstr "Le fichier d'entrée ne contient aucun code point" -#: views.py:1596 +#: views.py:1903 msgid "Meta data saved" msgstr "Metadonnées sauvegardées" diff --git a/src/lgr_editor/repertoires.py b/src/lgr_editor/repertoires.py index 8aca491f..398e7f9e 100644 --- a/src/lgr_editor/repertoires.py +++ b/src/lgr_editor/repertoires.py @@ -4,20 +4,48 @@ """ from __future__ import unicode_literals -import os + import logging +import os + from django.conf import settings -from lgr.parser.xml_parser import XMLParser +from lgr.parser.xml_parser import XMLParser +from .utils import list_validating_repertoires logger = logging.getLogger(__name__) REPERTOIRES = {} +SCRIPTS = {} def get_by_name(repertoire_name): if repertoire_name not in REPERTOIRES: logger.debug("%s parsing file", repertoire_name) - with open(os.path.join(settings.REPERTOIRE_STORAGE_LOCATION, '{}.xml'.format(repertoire_name))) as f: - parser = XMLParser(f, repertoire_name) - REPERTOIRES[repertoire_name] = parser.parse_document() + 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 + return REPERTOIRES[repertoire_name] + + +def get_all_scripts_from_repertoire(unicode_database): + if unicode_database not in SCRIPTS: + scripts = set() + for rep in list_validating_repertoires(): + validating_repertoire = get_by_name(rep) + for char in validating_repertoire.repertoire.all_repertoire(): + for cp in char.cp: + try: + # XXX: unicode version here may be different than validating repertoire one + scripts.add(unicode_database.get_script(cp, alpha4=True)) + except Exception as e: + logger.error('Get script failed for cp %s (validating repertoire: %s, unicode_database: %s) (%s)', + cp, validating_repertoire, + unicode_database.get_unicode_version(), + e) + + SCRIPTS[unicode_database] = scripts + + return SCRIPTS[unicode_database] diff --git a/src/lgr_editor/templates/lgr_editor/_editor_base.html b/src/lgr_editor/templates/lgr_editor/_editor_base.html index c236f9f5..ac5c5c26 100644 --- a/src/lgr_editor/templates/lgr_editor/_editor_base.html +++ b/src/lgr_editor/templates/lgr_editor/_editor_base.html @@ -8,11 +8,13 @@ {% url 'codepoint_list' lgr_set_id lgr_id as codepoint_list_url %} {% url 'references' lgr_set_id lgr_id as references_url %} {% url 'metadata' lgr_set_id lgr_id as metadata_url %} + {% url 'tags' lgr_set_id lgr_id as tags_url %} {% url 'rules' lgr_set_id lgr_id as rules_url %} {% else %} {% url 'codepoint_list' lgr_id as codepoint_list_url %} {% url 'references' lgr_id as references_url %} {% url 'metadata' lgr_id as metadata_url %} + {% url 'tags' lgr_id as tags_url %} {% url 'rules' lgr_id as rules_url %} {% endif %} +
-

{% trans 'This toolset was implemented by Viagenie and Wil Tan on an ICANN contract.' %}

+

{% trans 'This toolset was implemented by Viagénie and Wil Tan on an ICANN contract.' %}

diff --git a/src/lgr_editor/templates/lgr_editor/add_list_from_script.html b/src/lgr_editor/templates/lgr_editor/add_list_from_script.html new file mode 100644 index 00000000..c9c7bd19 --- /dev/null +++ b/src/lgr_editor/templates/lgr_editor/add_list_from_script.html @@ -0,0 +1,14 @@ +{% extends "_base_noframe.html" %} +{% load i18n %} + +{% block content %} +
+ {% csrf_token %} + {% include "lgr_editor/_form_field.html" with field=form.script %} + {% include "lgr_editor/_form_field.html" with field=form.validating_repertoire %} + {% include "lgr_editor/_form_field_checkbox.html" with field=form.manual_import %} +
+ +
+
+{% endblock content %} diff --git a/src/lgr_editor/templates/lgr_editor/codepoint_list.html b/src/lgr_editor/templates/lgr_editor/codepoint_list.html index 095ca4e6..e7ca933c 100644 --- a/src/lgr_editor/templates/lgr_editor/codepoint_list.html +++ b/src/lgr_editor/templates/lgr_editor/codepoint_list.html @@ -1,52 +1,108 @@ {% extends "lgr_editor/_editor_base.html" %} {% load i18n %} +{% load cache %} +{% block html_head_more %} + {{ block.super }} + +{% endblock %} {% block pane-cp-active %}active{% endblock %} {% block content-pane %} {% if not is_set %}
- {% url 'expand_ranges' lgr_id=lgr_id as expand_ranges_url %} - {% trans "Expand range(s)" %} + + {% if has_range %} + {% url 'expand_ranges' lgr_id=lgr_id as expand_ranges_url %} + {% trans "Expand range(s)" %} + {% endif %} {% trans "Add code point(s)" %}
{% endif %} - - - - - - - - {% for char in repertoire %} - {% if lgr_set_id %} - {% url 'codepoint_view' lgr_set_id=lgr_set_id lgr_id=lgr_id codepoint_id=char.cp as cp_url %} - {% else %} - {% url 'codepoint_view' lgr_id=lgr_id codepoint_id=char.cp as cp_url %} - {% endif %} - {% url 'expand_range' lgr_id=lgr_id codepoint_id=char.cp as expand_range_url %} - - - - - - - {% endfor %} -
{% trans "Code point" %}{% trans "Character Name" %}{% trans "Comments" %}{% trans "Action" %}
{{ char.cp_disp }} {% if not char.is_range %}{{ char.variant_number }} {% trans "Variant(s)" %}{% endif %}{{ char.name }}{{ char.comment }}{% trans "See code point" %} - {% if char.is_range %} - {% if not is_set %} - {% trans "Expand range" %} - {% endif %} - {% endif %} -
+
+ {% csrf_token %} + + + + + {% if not is_set %}{% endif %} + + + + + + + +
{% trans "Code point" %}{% trans "Character Name" %}{% trans "Tags" %}{% trans "Comments" %}{% trans "Action" %}
+ + + + + +
{#### BEGIN add codepoint modal ####} + {% if not is_set %}