Added 'order' term's attribute to sort terms manually
authorThierry Florac <thierry.florac@onf.fr>
Wed, 29 Aug 2018 13:56:54 +0200
changeset 87 dfe19304d980
parent 86 04f176e237cc
child 88 48b30fd5a29e
Added 'order' term's attribute to sort terms manually
src/pyams_thesaurus/interfaces/term.py
src/pyams_thesaurus/locales/fr/LC_MESSAGES/pyams_thesaurus.mo
src/pyams_thesaurus/locales/fr/LC_MESSAGES/pyams_thesaurus.po
src/pyams_thesaurus/locales/pyams_thesaurus.pot
src/pyams_thesaurus/term.py
src/pyams_thesaurus/thesaurus.py
src/pyams_thesaurus/zmi/extract.py
src/pyams_thesaurus/zmi/term.py
src/pyams_thesaurus/zmi/thesaurus.py
src/pyams_thesaurus/zmi/widget/__init__.py
--- a/src/pyams_thesaurus/interfaces/term.py	Tue Aug 28 17:02:29 2018 +0200
+++ b/src/pyams_thesaurus/interfaces/term.py	Wed Aug 29 13:56:54 2018 +0200
@@ -78,6 +78,10 @@
                                  description=_("Parent generic term of the current term"),
                                  required=False)
 
+    order = Int(title=_("Order"),
+                description=_("Term's position between it's siblings; default terms order is alphabetical"),
+                required=False)
+
     specifics = ThesaurusTermsListField(title=_("Specifics terms"),
                                         description=_("Child more specifics terms of the current term"),
                                         required=False)
Binary file src/pyams_thesaurus/locales/fr/LC_MESSAGES/pyams_thesaurus.mo has changed
--- a/src/pyams_thesaurus/locales/fr/LC_MESSAGES/pyams_thesaurus.po	Tue Aug 28 17:02:29 2018 +0200
+++ b/src/pyams_thesaurus/locales/fr/LC_MESSAGES/pyams_thesaurus.po	Wed Aug 29 13:56:54 2018 +0200
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2017-08-21 10:55+0200\n"
+"POT-Creation-Date: 2018-08-29 13:50+0200\n"
 "PO-Revision-Date: 2015-04-14 10:11+0200\n"
 "Last-Translator: Thierry Florac <tflorac@ulthar.net>\n"
 "Language-Team: French <traduc@traduc.org>\n"
@@ -16,92 +16,75 @@
 "Generated-By: Lingua 3.10.dev0\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: src/pyams_thesaurus/__init__.py:32
+#: src/pyams_thesaurus/__init__.py:34
+msgid "Create thesaurus"
+msgstr "Créer un thésaurus"
+
+#: src/pyams_thesaurus/__init__.py:36
 msgid "Manage thesaurus properties"
 msgstr "Gérer les propriétés d'un thésaurus"
 
-#: src/pyams_thesaurus/__init__.py:34
+#: src/pyams_thesaurus/__init__.py:38
 msgid "Manage thesaurus content"
 msgstr "Gérer le contenu d'un thésaurus"
 
-#: src/pyams_thesaurus/__init__.py:36
+#: src/pyams_thesaurus/__init__.py:40
 msgid "Manage thesaurus extract"
 msgstr "Gérer un extrait d'un thésaurus"
 
-#: src/pyams_thesaurus/__init__.py:40
+#: src/pyams_thesaurus/__init__.py:44
 msgid "Thesaurus administrator (role)"
 msgstr "Administrateur du thésaurus (rôle)"
 
-#: src/pyams_thesaurus/__init__.py:46
+#: src/pyams_thesaurus/__init__.py:51
 msgid "Thesaurus content manager (role)"
 msgstr "Gestionnaire du thésaurus (rôle)"
 
-#: src/pyams_thesaurus/__init__.py:51
+#: src/pyams_thesaurus/__init__.py:58
 msgid "Thesaurus extract manager (role)"
 msgstr "Gestionnaire d'un extrait du thésaurus"
 
-#: src/pyams_thesaurus/widget/templates/terms-list-input.pt:4
-#: src/pyams_thesaurus/widget/templates/terms-list-selector-input.pt:3
-msgid "Clear selected values"
-msgstr "Enlever les valeurs sélectionnées"
-
-#: src/pyams_thesaurus/widget/templates/term-input.pt:4
-msgid "Clear selected value"
-msgstr "Enlever la valeur sélectionnée"
-
-#: src/pyams_thesaurus/widget/templates/terms-list-selector-input.pt:9
-msgid "Show terms selector"
-msgstr "Afficher le sélecteur de termes"
-
-#: src/pyams_thesaurus/zmi/extract.py:58
+#: src/pyams_thesaurus/zmi/extract.py:60
 msgid "Thesaurus extracts"
 msgstr "Extraits du thésaurus"
 
-#: src/pyams_thesaurus/zmi/extract.py:85
+#: src/pyams_thesaurus/zmi/extract.py:87
 msgid "Extract contents"
 msgstr "Contenu de l'extrait"
 
-#: src/pyams_thesaurus/zmi/extract.py:109
+#: src/pyams_thesaurus/zmi/extract.py:111
 msgid "Switch extract"
 msgstr "Masquer ou afficher l'extrait"
 
-#: src/pyams_thesaurus/zmi/extract.py:119
+#: src/pyams_thesaurus/zmi/extract.py:121
 msgid "Delete extract"
 msgstr "Supprimer l'extrait"
 
-#: src/pyams_thesaurus/zmi/extract.py:128
+#: src/pyams_thesaurus/zmi/extract.py:137
 msgid "Add extract"
 msgstr "Ajouter un extrait"
 
-#: src/pyams_thesaurus/zmi/extract.py:141
+#: src/pyams_thesaurus/zmi/extract.py:150
 msgid "Add new extract"
 msgstr "Ajout d'un nouvel extrait"
 
-#: src/pyams_thesaurus/zmi/extract.py:183
-#: src/pyams_thesaurus/zmi/extract.py:226
+#: src/pyams_thesaurus/zmi/extract.py:194
+msgid "Edit extract properties"
+msgstr "Mise à jour des propriétés d'un extrait"
+
+#: src/pyams_thesaurus/zmi/extract.py:235
+msgid "Display extract terms"
+msgstr "Termes associés à cet extrait"
+
+#: src/pyams_thesaurus/zmi/extract.py:192
+#: src/pyams_thesaurus/zmi/extract.py:233
 #, python-format
 msgid "Thesaurus extract: {0}"
 msgstr "Extrait du thésaurus : {0}"
 
-#: src/pyams_thesaurus/zmi/extract.py:185
-msgid "Edit extract properties"
-msgstr "Mise à jour des propriétés d'un extrait"
-
-#: src/pyams_thesaurus/zmi/extract.py:228
-msgid "Display extract terms"
-msgstr "Termes associés à cet extrait"
-
-#: src/pyams_thesaurus/zmi/extract.py:296
-msgid "No provided object_name argument!"
-msgstr "Aucun argument 'object_name' n'a été fourni !"
-
-#: src/pyams_thesaurus/zmi/extract.py:301
-msgid "Given extract name doesn't exist!"
-msgstr "Aucun extrait correspondant au nom indiqué n'a été trouvé !"
-
-#: src/pyams_thesaurus/zmi/manager.py:55 src/pyams_thesaurus/zmi/manager.py:117
-#: src/pyams_thesaurus/zmi/thesaurus.py:396
-#: src/pyams_thesaurus/zmi/thesaurus.py:465
+#: src/pyams_thesaurus/zmi/manager.py:55 src/pyams_thesaurus/zmi/manager.py:114
+#: src/pyams_thesaurus/zmi/thesaurus.py:404
+#: src/pyams_thesaurus/zmi/thesaurus.py:470
 msgid "Thesaurus"
 msgstr "Thésaurus"
 
@@ -109,118 +92,127 @@
 msgid "Registered thesaurus"
 msgstr "Liste des thésaurus"
 
-#: src/pyams_thesaurus/zmi/manager.py:89
+#: src/pyams_thesaurus/zmi/manager.py:87
 msgid "Delete thesaurus"
 msgstr "Supprimer ce thésaurus"
 
-#: src/pyams_thesaurus/zmi/manager.py:116
-msgid "Control panel"
-msgstr "Panneau de configuration"
-
-#: src/pyams_thesaurus/zmi/manager.py:125
+#: src/pyams_thesaurus/zmi/manager.py:122
 msgid "Add thesaurus"
 msgstr "Ajouter un thésaurus"
 
-#: src/pyams_thesaurus/zmi/term.py:51
+#: src/pyams_thesaurus/zmi/term.py:50
 msgid "Add term"
 msgstr "Ajouter un terme"
 
-#: src/pyams_thesaurus/zmi/term.py:64
+#: src/pyams_thesaurus/zmi/term.py:66
 msgid "Add new term"
 msgstr "Ajout d'un nouveau terme"
 
-#: src/pyams_thesaurus/zmi/term.py:109
+#: src/pyams_thesaurus/zmi/term.py:138
+msgid "Edit term properties"
+msgstr "Mise à jour des propriétés d'un terme"
+
+#: src/pyams_thesaurus/zmi/term.py:124
 msgid "Specified label is already used!"
 msgstr "Le libellé spécifié est déjà utilisé !"
 
-#: src/pyams_thesaurus/zmi/term.py:135
-msgid "Edit term properties"
-msgstr "Mise à jour des propriétés d'un terme"
-
-#: src/pyams_thesaurus/zmi/term.py:238
+#: src/pyams_thesaurus/zmi/term.py:264
 msgid "Specified new label is already used!"
 msgstr "Le nouveau libellé spécifié est déjà utilisé !"
 
-#: src/pyams_thesaurus/zmi/thesaurus.py:77
+#: src/pyams_thesaurus/zmi/thesaurus.py:80
 msgid "This thesaurus"
 msgstr "Ce thésaurus"
 
-#: src/pyams_thesaurus/zmi/thesaurus.py:87
-#: src/pyams_thesaurus/zmi/thesaurus.py:204
+#: src/pyams_thesaurus/zmi/thesaurus.py:109
+msgid "Add thesaurus..."
+msgstr "Ajouter un thésaurus"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:122
+msgid "Utilities"
+msgstr "Utilitaires"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:123
+msgid "Add new thesaurus"
+msgstr "Ajout d'un thésaurus"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:203
+msgid "Properties"
+msgstr "Propriétés"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:219
+msgid "Update thesaurus properties"
+msgstr "Mise à jour des propriétés"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:246
+msgid "Terms"
+msgstr "Termes"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:383
+msgid "Import terms..."
+msgstr "Importer des termes"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:405
+msgid "Import thesaurus terms"
+msgstr "Import des termes du thésaurus"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:449
+msgid "Export terms..."
+msgstr "Exporter des termes"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:471
+msgid "Export thesaurus terms"
+msgstr "Export des termes du thésaurus"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:393
+#: src/pyams_thesaurus/zmi/thesaurus.py:459
+msgid "Close"
+msgstr "Fermer"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:394
+msgid "Import terms"
+msgstr "Importer des termes"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:418
+#: src/pyams_thesaurus/zmi/thesaurus.py:419
+msgid "-- automatic selection -- (if available)"
+msgstr "-- sélection automatique -- (si possible)"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:460
+msgid "Export terms"
+msgstr "Exporter des termes"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:159
+msgid "Specified thesaurus name is already used!"
+msgstr "Le nom spécifié pour ce thésaurus est déjà utilisé !"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:162
+msgid "A thesaurus is already registered with this name!"
+msgstr "Un autre thésaurus est déjà enregistré avec ce nom !"
+
+#: src/pyams_thesaurus/zmi/thesaurus.py:101
+#: src/pyams_thesaurus/zmi/thesaurus.py:217
 #, python-format
 msgid "Thesaurus: {0}"
 msgstr "Thésaurus : {0}"
 
-#: src/pyams_thesaurus/zmi/thesaurus.py:95
-msgid "Add thesaurus..."
-msgstr "Ajouter un thésaurus"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:105
-msgid "Utilities"
-msgstr "Utilitaires"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:106
-msgid "Add new thesaurus"
-msgstr "Ajout d'un thésaurus"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:136
-msgid "Specified thesaurus name is already used!"
-msgstr "Le nom spécifié pour ce thésaurus est déjà utilisé !"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:139
-msgid "A thesaurus is already registered with this name!"
-msgstr "Un autre thésaurus est déjà enregistré avec ce nom !"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:181
+#: src/pyams_thesaurus/zmi/thesaurus.py:193
 #, python-format
 msgid "Thesaurus « {0} »"
 msgstr "Thésaurus : « {0} »"
 
-#: src/pyams_thesaurus/zmi/thesaurus.py:191
-msgid "Properties"
-msgstr "Propriétés"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:206
-msgid "Update thesaurus properties"
-msgstr "Mise à jour des propriétés"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:239
-msgid "Terms"
-msgstr "Termes"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:377
-msgid "Import terms..."
-msgstr "Importer des termes"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:387
-#: src/pyams_thesaurus/zmi/thesaurus.py:457
-msgid "Close"
-msgstr "Fermer"
+#: src/pyams_thesaurus/zmi/widget/templates/terms-list-input.pt:4
+#: src/pyams_thesaurus/zmi/widget/templates/terms-list-selector-input.pt:3
+msgid "Clear selected values"
+msgstr "Enlever les valeurs sélectionnées"
 
-#: src/pyams_thesaurus/zmi/thesaurus.py:388
-msgid "Import terms"
-msgstr "Importer des termes"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:397
-msgid "Import thesaurus terms"
-msgstr "Import des termes du thésaurus"
+#: src/pyams_thesaurus/zmi/widget/templates/term-input.pt:4
+msgid "Clear selected value"
+msgstr "Enlever la valeur sélectionnée"
 
-#: src/pyams_thesaurus/zmi/thesaurus.py:410
-#: src/pyams_thesaurus/zmi/thesaurus.py:411
-msgid "-- automatic selection -- (if available)"
-msgstr "-- sélection automatique -- (si possible)"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:447
-msgid "Export terms..."
-msgstr "Exporter des termes"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:458
-msgid "Export terms"
-msgstr "Exporter des termes"
-
-#: src/pyams_thesaurus/zmi/thesaurus.py:466
-msgid "Export thesaurus terms"
-msgstr "Export des termes du thésaurus"
+#: src/pyams_thesaurus/zmi/widget/templates/terms-list-selector-input.pt:9
+msgid "Show terms selector"
+msgstr "Afficher le sélecteur de termes"
 
 #: src/pyams_thesaurus/zmi/templates/terms-tree.pt:11
 msgid "Thesaurus terms tree"
@@ -355,10 +347,6 @@
 msgid "Full keyword for the given term"
 msgstr "LIbellé de référence de ce terme"
 
-#: src/pyams_thesaurus/interfaces/term.py:59
-msgid "'/' character is forbidden in term's label"
-msgstr "Le caractère '/' est interdit dans le libellé d'un terme"
-
 #: src/pyams_thesaurus/interfaces/term.py:65
 msgid "Alternate label"
 msgstr "Libellé alternatif"
@@ -392,45 +380,116 @@
 msgstr "Terme de rattachement de ce terme"
 
 #: src/pyams_thesaurus/interfaces/term.py:81
+msgid "Order"
+msgstr "Ordre"
+
+#: src/pyams_thesaurus/interfaces/term.py:82
+msgid ""
+"Term's position between it's siblings; default terms order is alphabetical"
+msgstr ""
+"Position du terme parmi ses frères et soeurs ; l'ordre par défaut est alphabétique"
+
+#: src/pyams_thesaurus/interfaces/term.py:85
 msgid "Specifics terms"
 msgstr "Termes spécifiques"
 
-#: src/pyams_thesaurus/interfaces/term.py:82
+#: src/pyams_thesaurus/interfaces/term.py:86
 msgid "Child more specifics terms of the current term"
 msgstr "Autres termes rattachés à ce terme en tant que terme générique"
 
-#: src/pyams_thesaurus/interfaces/term.py:85
+#: src/pyams_thesaurus/interfaces/term.py:89
 msgid "Associated terms"
 msgstr "Termes associés"
 
-#: src/pyams_thesaurus/interfaces/term.py:86
+#: src/pyams_thesaurus/interfaces/term.py:90
 msgid "Other terms associated to the current term"
 msgstr "Autres termes associés à ce terme"
 
-#: src/pyams_thesaurus/interfaces/term.py:89
+#: src/pyams_thesaurus/interfaces/term.py:93
 msgid "Usage"
 msgstr "Terme d'usage"
 
-#: src/pyams_thesaurus/interfaces/term.py:90
+#: src/pyams_thesaurus/interfaces/term.py:94
 msgid "For synonyms, specify here the term's descriptor to use"
 msgstr ""
 "Dans le cas de synonymes, le terme d'usage est le terme 'officiel' à utiliser"
 
-#: src/pyams_thesaurus/interfaces/term.py:93
+#: src/pyams_thesaurus/interfaces/term.py:97
 msgid "Synonyms"
 msgstr "Synonymes"
 
-#: src/pyams_thesaurus/interfaces/term.py:94
+#: src/pyams_thesaurus/interfaces/term.py:98
 msgid "For a given allowed descriptor, specify here the list of synonyms"
 msgstr "Autres synonymes rattachés à ce terme en tant que terme d'usage"
 
-#: src/pyams_thesaurus/interfaces/term.py:102
+#: src/pyams_thesaurus/interfaces/term.py:111
+msgid "Extracts"
+msgstr "Extraits"
+
+#: src/pyams_thesaurus/interfaces/term.py:112
+msgid "List of thesaurus extracts including this term"
+msgstr "Liste des extraits du thésaurus incluant ce terme"
+
+#: src/pyams_thesaurus/interfaces/term.py:116
+msgid "Extensions"
+msgstr "Extensions"
+
+#: src/pyams_thesaurus/interfaces/term.py:117
+msgid "List of available extensions applied to this term"
+msgstr "Liste des extensions disponibles appliquées à ce terme"
+
+#: src/pyams_thesaurus/interfaces/term.py:121
+msgid "Status"
+msgstr "Statut"
+
+#: src/pyams_thesaurus/interfaces/term.py:122
+msgid "Term status"
+msgstr "Statut de ce terme"
+
+#: src/pyams_thesaurus/interfaces/term.py:127
+msgid "Level"
+msgstr "Niveau"
+
+#: src/pyams_thesaurus/interfaces/term.py:128
+msgid "Term's level in the thesaurus tree"
+msgstr "Indique le niveau de profondeur dans l'arborescence des termes"
+
+#: src/pyams_thesaurus/interfaces/term.py:133
+msgid "Micro-thesaurus?"
+msgstr "Micro thésaurus ?"
+
+#: src/pyams_thesaurus/interfaces/term.py:134
+msgid "Is the term part of a micro-thesaurus?"
+msgstr "Indique si ce terme fait partie d'un micro-thesaurus"
+
+#: src/pyams_thesaurus/interfaces/term.py:137
+msgid "First level parent"
+msgstr "Parent de niveau 1"
+
+#: src/pyams_thesaurus/interfaces/term.py:138
+msgid "Parent at level 1 of the current term, or None"
+msgstr "Parent de niveau 1 auquel est rattaché ce terme"
+
+#: src/pyams_thesaurus/interfaces/term.py:142
+#: src/pyams_thesaurus/interfaces/thesaurus.py:60
+msgid "Creation date"
+msgstr "Date de création"
+
+#: src/pyams_thesaurus/interfaces/term.py:145
+msgid "Modification date"
+msgstr "Date de modification"
+
+#: src/pyams_thesaurus/interfaces/term.py:59
+msgid "'/' character is forbidden in term's label"
+msgstr "Le caractère '/' est interdit dans le libellé d'un terme"
+
+#: src/pyams_thesaurus/interfaces/term.py:106
 msgid "A term can't be a synonym and attached to a generic term"
 msgstr ""
 "Un terme ne peut pas à la fois être un synonyme et rattaché à un terme "
 "générique"
 
-#: src/pyams_thesaurus/interfaces/term.py:104
+#: src/pyams_thesaurus/interfaces/term.py:108
 msgid ""
 "A term used as synonym can't have it's own synonyms (all synonyms should be "
 "attached to the descriptor)"
@@ -438,63 +497,6 @@
 "Un terme utilisé en tant que synonyme ne peut pas avoir ses propres "
 "synonymes (tous les synonymes doivent être associés au même terme d'usage)"
 
-#: src/pyams_thesaurus/interfaces/term.py:107
-msgid "Extracts"
-msgstr "Extraits"
-
-#: src/pyams_thesaurus/interfaces/term.py:108
-msgid "List of thesaurus extracts including this term"
-msgstr "Liste des extraits du thésaurus incluant ce terme"
-
-#: src/pyams_thesaurus/interfaces/term.py:112
-msgid "Extensions"
-msgstr "Extensions"
-
-#: src/pyams_thesaurus/interfaces/term.py:113
-msgid "List of available extensions applied to this term"
-msgstr "Liste des extensions disponibles appliquées à ce terme"
-
-#: src/pyams_thesaurus/interfaces/term.py:117
-msgid "Status"
-msgstr "Statut"
-
-#: src/pyams_thesaurus/interfaces/term.py:118
-msgid "Term status"
-msgstr "Statut de ce terme"
-
-#: src/pyams_thesaurus/interfaces/term.py:123
-msgid "Level"
-msgstr "Niveau"
-
-#: src/pyams_thesaurus/interfaces/term.py:124
-msgid "Term's level in the thesaurus tree"
-msgstr "Indique le niveau de profondeur dans l'arborescence des termes"
-
-#: src/pyams_thesaurus/interfaces/term.py:129
-msgid "Micro-thesaurus?"
-msgstr "Micro thésaurus ?"
-
-#: src/pyams_thesaurus/interfaces/term.py:130
-msgid "Is the term part of a micro-thesaurus?"
-msgstr "Indique si ce terme fait partie d'un micro-thesaurus"
-
-#: src/pyams_thesaurus/interfaces/term.py:133
-msgid "First level parent"
-msgstr "Parent de niveau 1"
-
-#: src/pyams_thesaurus/interfaces/term.py:134
-msgid "Parent at level 1 of the current term, or None"
-msgstr "Parent de niveau 1 auquel est rattaché ce terme"
-
-#: src/pyams_thesaurus/interfaces/term.py:138
-#: src/pyams_thesaurus/interfaces/thesaurus.py:60
-msgid "Creation date"
-msgstr "Date de création"
-
-#: src/pyams_thesaurus/interfaces/term.py:141
-msgid "Modification date"
-msgstr "Date de modification"
-
 #: src/pyams_thesaurus/interfaces/index.py:30
 #: src/pyams_thesaurus/interfaces/index.py:42
 msgid "Include term parents into index values"
@@ -605,6 +607,10 @@
 msgid "Thesaurus extract"
 msgstr "Nom de l'extrait"
 
+#: src/pyams_thesaurus/interfaces/extension.py:40
+msgid "Extension marker interface"
+msgstr "Interface de marquage"
+
 #: src/pyams_thesaurus/interfaces/extension.py:36
 msgid "Extension name"
 msgstr "Nom de l'extension"
@@ -613,10 +619,6 @@
 msgid "User name given to the extension"
 msgstr "Nom donné à l'extension"
 
-#: src/pyams_thesaurus/interfaces/extension.py:40
-msgid "Extension marker interface"
-msgstr "Interface de marquage"
-
 #: src/pyams_thesaurus/interfaces/extension.py:42
 msgid "Extension target view"
 msgstr "Vue associée à l'extension"
@@ -625,6 +627,15 @@
 msgid "Extension icon URI"
 msgstr "Icône associée à l'extension"
 
+#~ msgid "No provided object_name argument!"
+#~ msgstr "Aucun argument 'object_name' n'a été fourni !"
+
+#~ msgid "Given extract name doesn't exist!"
+#~ msgstr "Aucun extrait correspondant au nom indiqué n'a été trouvé !"
+
+#~ msgid "Control panel"
+#~ msgstr "Panneau de configuration"
+
 #~ msgid "Thesaurus properties"
 #~ msgstr "Propriétés"
 
--- a/src/pyams_thesaurus/locales/pyams_thesaurus.pot	Tue Aug 28 17:02:29 2018 +0200
+++ b/src/pyams_thesaurus/locales/pyams_thesaurus.pot	Wed Aug 29 13:56:54 2018 +0200
@@ -1,12 +1,12 @@
 #
 # SOME DESCRIPTIVE TITLE
 # This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2017.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2018.
 #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2017-08-21 10:55+0200\n"
+"POT-Creation-Date: 2018-08-29 13:50+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -14,95 +14,78 @@
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Lingua 4.13\n"
-
-#: ./src/pyams_thesaurus/__init__.py:32
-msgid "Manage thesaurus properties"
-msgstr ""
+"Generated-By: Lingua 3.10.dev0\n"
 
 #: ./src/pyams_thesaurus/__init__.py:34
-msgid "Manage thesaurus content"
+msgid "Create thesaurus"
 msgstr ""
 
 #: ./src/pyams_thesaurus/__init__.py:36
-msgid "Manage thesaurus extract"
+msgid "Manage thesaurus properties"
+msgstr ""
+
+#: ./src/pyams_thesaurus/__init__.py:38
+msgid "Manage thesaurus content"
 msgstr ""
 
 #: ./src/pyams_thesaurus/__init__.py:40
+msgid "Manage thesaurus extract"
+msgstr ""
+
+#: ./src/pyams_thesaurus/__init__.py:44
 msgid "Thesaurus administrator (role)"
 msgstr ""
 
-#: ./src/pyams_thesaurus/__init__.py:46
+#: ./src/pyams_thesaurus/__init__.py:51
 msgid "Thesaurus content manager (role)"
 msgstr ""
 
-#: ./src/pyams_thesaurus/__init__.py:51
+#: ./src/pyams_thesaurus/__init__.py:58
 msgid "Thesaurus extract manager (role)"
 msgstr ""
 
-#: ./src/pyams_thesaurus/widget/templates/terms-list-input.pt:4
-#: ./src/pyams_thesaurus/widget/templates/terms-list-selector-input.pt:3
-msgid "Clear selected values"
-msgstr ""
-
-#: ./src/pyams_thesaurus/widget/templates/term-input.pt:4
-msgid "Clear selected value"
-msgstr ""
-
-#: ./src/pyams_thesaurus/widget/templates/terms-list-selector-input.pt:9
-msgid "Show terms selector"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/extract.py:58
+#: ./src/pyams_thesaurus/zmi/extract.py:60
 msgid "Thesaurus extracts"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/extract.py:85
+#: ./src/pyams_thesaurus/zmi/extract.py:87
 msgid "Extract contents"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/extract.py:109
+#: ./src/pyams_thesaurus/zmi/extract.py:111
 msgid "Switch extract"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/extract.py:119
+#: ./src/pyams_thesaurus/zmi/extract.py:121
 msgid "Delete extract"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/extract.py:128
+#: ./src/pyams_thesaurus/zmi/extract.py:137
 msgid "Add extract"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/extract.py:141
+#: ./src/pyams_thesaurus/zmi/extract.py:150
 msgid "Add new extract"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/extract.py:183
-#: ./src/pyams_thesaurus/zmi/extract.py:226
+#: ./src/pyams_thesaurus/zmi/extract.py:194
+msgid "Edit extract properties"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/extract.py:235
+msgid "Display extract terms"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/extract.py:192
+#: ./src/pyams_thesaurus/zmi/extract.py:233
 #, python-format
 msgid "Thesaurus extract: {0}"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/extract.py:185
-msgid "Edit extract properties"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/extract.py:228
-msgid "Display extract terms"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/extract.py:296
-msgid "No provided object_name argument!"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/extract.py:301
-msgid "Given extract name doesn't exist!"
-msgstr ""
-
 #: ./src/pyams_thesaurus/zmi/manager.py:55
-#: ./src/pyams_thesaurus/zmi/manager.py:117
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:396
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:465
+#: ./src/pyams_thesaurus/zmi/manager.py:114
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:404
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:470
 msgid "Thesaurus"
 msgstr ""
 
@@ -110,117 +93,126 @@
 msgid "Registered thesaurus"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/manager.py:89
+#: ./src/pyams_thesaurus/zmi/manager.py:87
 msgid "Delete thesaurus"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/manager.py:116
-msgid "Control panel"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/manager.py:125
+#: ./src/pyams_thesaurus/zmi/manager.py:122
 msgid "Add thesaurus"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/term.py:51
+#: ./src/pyams_thesaurus/zmi/term.py:50
 msgid "Add term"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/term.py:64
+#: ./src/pyams_thesaurus/zmi/term.py:66
 msgid "Add new term"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/term.py:109
+#: ./src/pyams_thesaurus/zmi/term.py:138
+msgid "Edit term properties"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/term.py:124
 msgid "Specified label is already used!"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/term.py:135
-msgid "Edit term properties"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/term.py:238
+#: ./src/pyams_thesaurus/zmi/term.py:264
 msgid "Specified new label is already used!"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:77
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:80
 msgid "This thesaurus"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:87
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:204
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:109
+msgid "Add thesaurus..."
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:122
+msgid "Utilities"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:123
+msgid "Add new thesaurus"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:203
+msgid "Properties"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:219
+msgid "Update thesaurus properties"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:246
+msgid "Terms"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:383
+msgid "Import terms..."
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:405
+msgid "Import thesaurus terms"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:449
+msgid "Export terms..."
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:471
+msgid "Export thesaurus terms"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:393
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:459
+msgid "Close"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:394
+msgid "Import terms"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:418
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:419
+msgid "-- automatic selection -- (if available)"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:460
+msgid "Export terms"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:159
+msgid "Specified thesaurus name is already used!"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:162
+msgid "A thesaurus is already registered with this name!"
+msgstr ""
+
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:101
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:217
 #, python-format
 msgid "Thesaurus: {0}"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:95
-msgid "Add thesaurus..."
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:105
-msgid "Utilities"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:106
-msgid "Add new thesaurus"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:136
-msgid "Specified thesaurus name is already used!"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:139
-msgid "A thesaurus is already registered with this name!"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:181
+#: ./src/pyams_thesaurus/zmi/thesaurus.py:193
 #, python-format
 msgid "Thesaurus « {0} »"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:191
-msgid "Properties"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:206
-msgid "Update thesaurus properties"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:239
-msgid "Terms"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:377
-msgid "Import terms..."
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:387
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:457
-msgid "Close"
+#: ./src/pyams_thesaurus/zmi/widget/templates/terms-list-input.pt:4
+#: ./src/pyams_thesaurus/zmi/widget/templates/terms-list-selector-input.pt:3
+msgid "Clear selected values"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:388
-msgid "Import terms"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:397
-msgid "Import thesaurus terms"
+#: ./src/pyams_thesaurus/zmi/widget/templates/term-input.pt:4
+msgid "Clear selected value"
 msgstr ""
 
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:410
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:411
-msgid "-- automatic selection -- (if available)"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:447
-msgid "Export terms..."
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:458
-msgid "Export terms"
-msgstr ""
-
-#: ./src/pyams_thesaurus/zmi/thesaurus.py:466
-msgid "Export thesaurus terms"
+#: ./src/pyams_thesaurus/zmi/widget/templates/terms-list-selector-input.pt:9
+msgid "Show terms selector"
 msgstr ""
 
 #: ./src/pyams_thesaurus/zmi/templates/terms-tree.pt:11
@@ -347,10 +339,6 @@
 msgid "Full keyword for the given term"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:59
-msgid "'/' character is forbidden in term's label"
-msgstr ""
-
 #: ./src/pyams_thesaurus/interfaces/term.py:65
 msgid "Alternate label"
 msgstr ""
@@ -384,104 +372,117 @@
 msgstr ""
 
 #: ./src/pyams_thesaurus/interfaces/term.py:81
-msgid "Specifics terms"
+msgid "Order"
 msgstr ""
 
 #: ./src/pyams_thesaurus/interfaces/term.py:82
-msgid "Child more specifics terms of the current term"
+msgid ""
+"Term's position between it's siblings; default terms order is alphabetical"
 msgstr ""
 
 #: ./src/pyams_thesaurus/interfaces/term.py:85
-msgid "Associated terms"
+msgid "Specifics terms"
 msgstr ""
 
 #: ./src/pyams_thesaurus/interfaces/term.py:86
-msgid "Other terms associated to the current term"
+msgid "Child more specifics terms of the current term"
 msgstr ""
 
 #: ./src/pyams_thesaurus/interfaces/term.py:89
-msgid "Usage"
+msgid "Associated terms"
 msgstr ""
 
 #: ./src/pyams_thesaurus/interfaces/term.py:90
-msgid "For synonyms, specify here the term's descriptor to use"
+msgid "Other terms associated to the current term"
 msgstr ""
 
 #: ./src/pyams_thesaurus/interfaces/term.py:93
+msgid "Usage"
+msgstr ""
+
+#: ./src/pyams_thesaurus/interfaces/term.py:94
+msgid "For synonyms, specify here the term's descriptor to use"
+msgstr ""
+
+#: ./src/pyams_thesaurus/interfaces/term.py:97
 msgid "Synonyms"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:94
+#: ./src/pyams_thesaurus/interfaces/term.py:98
 msgid "For a given allowed descriptor, specify here the list of synonyms"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:102
-msgid "A term can't be a synonym and attached to a generic term"
-msgstr ""
-
-#: ./src/pyams_thesaurus/interfaces/term.py:104
-msgid ""
-"A term used as synonym can't have it's own synonyms (all synonyms should be "
-"attached to the descriptor)"
-msgstr ""
-
-#: ./src/pyams_thesaurus/interfaces/term.py:107
+#: ./src/pyams_thesaurus/interfaces/term.py:111
 msgid "Extracts"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:108
+#: ./src/pyams_thesaurus/interfaces/term.py:112
 msgid "List of thesaurus extracts including this term"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:112
+#: ./src/pyams_thesaurus/interfaces/term.py:116
 msgid "Extensions"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:113
+#: ./src/pyams_thesaurus/interfaces/term.py:117
 msgid "List of available extensions applied to this term"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:117
+#: ./src/pyams_thesaurus/interfaces/term.py:121
 msgid "Status"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:118
+#: ./src/pyams_thesaurus/interfaces/term.py:122
 msgid "Term status"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:123
+#: ./src/pyams_thesaurus/interfaces/term.py:127
 msgid "Level"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:124
+#: ./src/pyams_thesaurus/interfaces/term.py:128
 msgid "Term's level in the thesaurus tree"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:129
+#: ./src/pyams_thesaurus/interfaces/term.py:133
 msgid "Micro-thesaurus?"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:130
+#: ./src/pyams_thesaurus/interfaces/term.py:134
 msgid "Is the term part of a micro-thesaurus?"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:133
+#: ./src/pyams_thesaurus/interfaces/term.py:137
 msgid "First level parent"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:134
+#: ./src/pyams_thesaurus/interfaces/term.py:138
 msgid "Parent at level 1 of the current term, or None"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:138
+#: ./src/pyams_thesaurus/interfaces/term.py:142
 #: ./src/pyams_thesaurus/interfaces/thesaurus.py:60
 msgid "Creation date"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/term.py:141
+#: ./src/pyams_thesaurus/interfaces/term.py:145
 msgid "Modification date"
 msgstr ""
 
+#: ./src/pyams_thesaurus/interfaces/term.py:59
+msgid "'/' character is forbidden in term's label"
+msgstr ""
+
+#: ./src/pyams_thesaurus/interfaces/term.py:106
+msgid "A term can't be a synonym and attached to a generic term"
+msgstr ""
+
+#: ./src/pyams_thesaurus/interfaces/term.py:108
+msgid ""
+"A term used as synonym can't have it's own synonyms (all synonyms should be "
+"attached to the descriptor)"
+msgstr ""
+
 #: ./src/pyams_thesaurus/interfaces/index.py:30
 #: ./src/pyams_thesaurus/interfaces/index.py:42
 msgid "Include term parents into index values"
@@ -589,6 +590,10 @@
 msgid "Thesaurus extract"
 msgstr ""
 
+#: ./src/pyams_thesaurus/interfaces/extension.py:40
+msgid "Extension marker interface"
+msgstr ""
+
 #: ./src/pyams_thesaurus/interfaces/extension.py:36
 msgid "Extension name"
 msgstr ""
@@ -597,10 +602,6 @@
 msgid "User name given to the extension"
 msgstr ""
 
-#: ./src/pyams_thesaurus/interfaces/extension.py:40
-msgid "Extension marker interface"
-msgstr ""
-
 #: ./src/pyams_thesaurus/interfaces/extension.py:42
 msgid "Extension target view"
 msgstr ""
--- a/src/pyams_thesaurus/term.py	Tue Aug 28 17:02:29 2018 +0200
+++ b/src/pyams_thesaurus/term.py	Wed Aug 29 13:56:54 2018 +0200
@@ -68,6 +68,7 @@
     definition = FieldProperty(IThesaurusTerm['definition'])
     note = FieldProperty(IThesaurusTerm['note'])
     _generic = FieldProperty(IThesaurusTerm['generic'])
+    order = FieldProperty(IThesaurusTerm['order'])
     _specifics = FieldProperty(IThesaurusTerm['specifics'])
     _associations = FieldProperty(IThesaurusTerm['associations'])
     _usage = FieldProperty(IThesaurusTerm['usage'])
@@ -133,7 +134,8 @@
 
     @property
     def specifics(self):
-        return self._specifics
+        return sorted(self._specifics,
+                      key=lambda x: (x.order or 999, x.label))
 
     @specifics.setter
     def specifics(self, value):
--- a/src/pyams_thesaurus/thesaurus.py	Tue Aug 28 17:02:29 2018 +0200
+++ b/src/pyams_thesaurus/thesaurus.py	Wed Aug 29 13:56:54 2018 +0200
@@ -281,7 +281,7 @@
     """Thesaurus tree adapter"""
 
     def get_root_nodes(self):
-        return self.context.top_terms
+        return sorted(self.context.top_terms, key=lambda x: (x.order or 999, x.label))
 
 
 #
--- a/src/pyams_thesaurus/zmi/extract.py	Tue Aug 28 17:02:29 2018 +0200
+++ b/src/pyams_thesaurus/zmi/extract.py	Wed Aug 29 13:56:54 2018 +0200
@@ -250,7 +250,7 @@
         extract = self.context.name
         return sorted((INode(node) for node in ITree(thesaurus).get_root_nodes()
                        if extract in (node.extracts or ())),
-                      key=lambda x: x.label)
+                      key=lambda x: (x.order or 999, x.label))
 
 
 class BaseTreeNodesView(object):
@@ -291,5 +291,5 @@
         self.get_nodes(term, result)
         return {
             'term': label,
-            'nodes': sorted(result, key=lambda x: x['label'])
+            'nodes': result
         }
--- a/src/pyams_thesaurus/zmi/term.py	Tue Aug 28 17:02:29 2018 +0200
+++ b/src/pyams_thesaurus/zmi/term.py	Wed Aug 29 13:56:54 2018 +0200
@@ -26,7 +26,7 @@
 from z3c.form.interfaces import IDataExtractedEvent, DISPLAY_MODE
 
 # import packages
-from pyams_form.form import AJAXAddForm, AJAXEditForm
+from pyams_form.form import AJAXAddForm, ajax_config
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_skin.viewlet.toolbar import ToolbarAction
 from pyams_thesaurus.term import ThesaurusTerm
@@ -36,7 +36,6 @@
 from pyams_viewlet.viewlet import viewlet_config
 from pyams_zmi.form import AdminDialogAddForm, AdminDialogEditForm
 from pyramid.events import subscriber
-from pyramid.view import view_config
 from z3c.form import field
 from zope.interface import Invalid
 
@@ -53,7 +52,10 @@
     modal_target = True
 
 
-@pagelet_config(name='add-term.html', context=IThesaurus, layer=IPyAMSLayer, permission=MANAGE_THESAURUS_CONTENT_PERMISSION)
+@pagelet_config(name='add-term.html', context=IThesaurus, layer=IPyAMSLayer,
+                permission=MANAGE_THESAURUS_CONTENT_PERMISSION)
+@ajax_config(name='add-term.json', context=IThesaurus, layer=IPyAMSLayer,
+             permission=MANAGE_THESAURUS_CONTENT_PERMISSION, base=AJAXAddForm)
 class ThesaurusTermAddForm(AdminDialogAddForm):
     """Thesaurus term add form"""
 
@@ -64,8 +66,8 @@
     legend = _("Add new term")
     icon_css_class = 'fa fa-fw fa-tag'
 
-    fields = field.Fields(IThesaurusTerm).select('label', 'alt', 'definition', 'note', 'generic', 'associations',
-                                                 'usage', 'extensions', 'status', 'created')
+    fields = field.Fields(IThesaurusTerm).select('label', 'alt', 'definition', 'note', 'generic', 'order',
+                                                 'associations', 'usage', 'extensions', 'status', 'created')
 
     ajax_handler = 'add-term.json'
     edit_permission = None
@@ -100,23 +102,9 @@
     def nextURL(self):
         return absolute_url(self.context, self.request, 'terms.html')
 
-
-@subscriber(IDataExtractedEvent, form_selector=ThesaurusTermAddForm)
-def handle_new_term_data_extraction(event):
-    """Handle new term data extraction"""
-    data = event.data
-    if data.get('label') in event.form.context.terms:
-        event.form.widgets.errors += (Invalid(_("Specified label is already used!")), )
-
-
-@view_config(name='add-term.json', context=IThesaurus, request_type=IPyAMSLayer,
-             permission=MANAGE_THESAURUS_CONTENT_PERMISSION, renderer='json', xhr=True)
-class ThesaurusTermAJAXAddForm(AJAXAddForm, ThesaurusTermAddForm):
-    """Thesaurus term add form, AJAX view"""
-
     def get_ajax_output(self, changes):
         if changes.generic is None:
-            return super(ThesaurusTermAJAXAddForm, self).get_ajax_output(changes)
+            return super(self.__class__, self).get_ajax_output(changes)
         else:
             label = changes.label.replace("'", "&#039;")
             return {
@@ -128,7 +116,16 @@
             }
 
 
+@subscriber(IDataExtractedEvent, form_selector=ThesaurusTermAddForm)
+def handle_new_term_data_extraction(event):
+    """Handle new term data extraction"""
+    data = event.data
+    if data.get('label') in event.form.context.terms:
+        event.form.widgets.errors += (Invalid(_("Specified label is already used!")), )
+
+
 @pagelet_config(name='properties.html', context=IThesaurusTerm, layer=IPyAMSLayer, permission=VIEW_PERMISSION)
+@ajax_config(name='properties.json', context=IThesaurusTerm, layer=IPyAMSLayer)
 class ThesaurusTermEditForm(AdminDialogEditForm):
     """Thesaurus term edit form"""
 
@@ -141,11 +138,10 @@
     legend = _("Edit term properties")
     icon_css_class = 'fa fa-fw fa-tag'
 
-    fields = field.Fields(IThesaurusTerm).select('label', 'alt', 'definition', 'note', 'generic', 'specifics',
+    fields = field.Fields(IThesaurusTerm).select('label', 'alt', 'definition', 'note', 'generic', 'order', 'specifics',
                                                  'associations', 'usage', 'used_for', 'extracts', 'extensions',
                                                  'status', 'level', 'created', 'modified')
 
-    ajax_handler = 'properties.json'
     edit_permission = MANAGE_THESAURUS_CONTENT_PERMISSION
 
     generic_changed = False
@@ -233,34 +229,18 @@
                     term.usage.used_for += [term, ]
         return changes
 
-
-@subscriber(IDataExtractedEvent, form_selector=ThesaurusTermEditForm)
-def handle_term_properties_data_extraction(event):
-    """Handle term properties data extraction"""
-    context = event.form.context
-    thesaurus = get_parent(context, IThesaurus)
-    label = event.data.get('label')
-    if (label != context.label) and (label in thesaurus.terms):
-        event.form.widgets.errors += (Invalid(_("Specified new label is already used!")), )
-
-
-@pagelet_config(name='properties.json', context=IThesaurusTerm, request_type=IPyAMSLayer,
-                permission=MANAGE_THESAURUS_CONTENT_PERMISSION, renderer='json', xhr=True)
-class ThesaurusTermAJAXEditForm(AJAXEditForm, ThesaurusTermEditForm):
-    """Thesaurus term edit form, AJAX view"""
-
     def get_ajax_output(self, changes):
-        if self.generic_changed:
+        term_changes = changes.get(IThesaurusTerm, ())
+        if self.generic_changed or ('order' in term_changes):
             label = self.context.label.replace("'", "&#039;")
             return {
                 'status': 'reload',
-                'callback': 'PyAMS_thesaurus.tree.findTerm',
-                'options': {
+                'post_reload': 'PyAMS_thesaurus.tree.findTerm',
+                'post_reload_options': {
                     'term': label
                 }
             }
         else:
-            term_changes = changes.get(IThesaurusTerm, ())
             if ('status' in term_changes) or ('label' in term_changes) or ('extensions' in term_changes):
                 label = (self.context.generic or self.context).label.replace("'", "&#039;")
                 return {
@@ -271,4 +251,14 @@
                     }
                 }
             else:
-                return super(ThesaurusTermAJAXEditForm, self).get_ajax_output(changes)
+                return super(self.__class__, self).get_ajax_output(changes)
+
+
+@subscriber(IDataExtractedEvent, form_selector=ThesaurusTermEditForm)
+def handle_term_properties_data_extraction(event):
+    """Handle term properties data extraction"""
+    context = event.form.context
+    thesaurus = get_parent(context, IThesaurus)
+    label = event.data.get('label')
+    if (label != context.label) and (label in thesaurus.terms):
+        event.form.widgets.errors += (Invalid(_("Specified new label is already used!")), )
--- a/src/pyams_thesaurus/zmi/thesaurus.py	Tue Aug 28 17:02:29 2018 +0200
+++ b/src/pyams_thesaurus/zmi/thesaurus.py	Wed Aug 29 13:56:54 2018 +0200
@@ -37,7 +37,7 @@
 from z3c.form.interfaces import IDataExtractedEvent, DISPLAY_MODE
 
 # import packages
-from pyams_form.form import AJAXAddForm, AJAXEditForm
+from pyams_form.form import AJAXAddForm, ajax_config
 from pyams_form.schema import CloseButton
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_skin.layer import IPyAMSLayer
@@ -112,7 +112,10 @@
     modal_target = True
 
 
-@pagelet_config(name='add-thesaurus.html', context=ISite, layer=IPyAMSLayer, permission=CREATE_THESAURUS_PERMISSION)
+@pagelet_config(name='add-thesaurus.html', context=ISite, layer=IPyAMSLayer,
+                permission=CREATE_THESAURUS_PERMISSION)
+@ajax_config(name='add-thesaurus.json', context=ISite, layer=IPyAMSLayer,
+             permission=CREATE_THESAURUS_PERMISSION, base=AJAXAddForm)
 class ThesaurusAddForm(AdminDialogAddForm):
     """Thesaurus add form"""
 
@@ -122,7 +125,6 @@
 
     fields = field.Fields(IThesaurusInfo).select('name', 'title', 'subject', 'description', 'language', 'creator',
                                                  'publisher', 'created')
-    ajax_handler = 'add-thesaurus.json'
     edit_permission = None
 
     def updateWidgets(self, prefix=None):
@@ -140,6 +142,13 @@
     def nextURL(self):
         return absolute_url(self.context, self.request, 'thesaurus.html')
 
+    def get_ajax_output(self, changes):
+        return {
+            'status': 'redirect',
+            'location': absolute_url(self.context, self.request, 'admin#thesaurus.html'),
+            'close_form': True
+        }
+
 
 @subscriber(IDataExtractedEvent, form_selector=ThesaurusAddForm)
 def handle_new_thesaurus_data_extraction(event):
@@ -153,19 +162,6 @@
         event.form.widgets.errors += (Invalid(_("A thesaurus is already registered with this name!")), )
 
 
-@view_config(name='add-thesaurus.json', context=ISite, request_type=IPyAMSLayer,
-             permission=CREATE_THESAURUS_PERMISSION, renderer='json', xhr=True)
-class ThesaurusAJAXAddForm(AJAXAddForm, ThesaurusAddForm):
-    """Thesaurus add form, AJAX view"""
-
-    def get_ajax_output(self, changes):
-        return {
-            'status': 'redirect',
-            'location': absolute_url(self.context, self.request, 'admin#thesaurus.html'),
-            'close_form': True
-        }
-
-
 @adapter_config(context=(IThesaurus, IAdminLayer, Interface), provides=ITableElementEditor)
 class ThesaurusTableElementEditor(DefaultElementEditorAdapter):
     """Thesaurus table element editor"""
@@ -210,6 +206,7 @@
 
 
 @pagelet_config(name='properties.html', context=IThesaurus, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
+@ajax_config(name='properties.json', context=IThesaurus, layer=IPyAMSLayer)
 @implementer(IWidgetForm, IInnerPage, IThesaurusView)
 class ThesaurusPropertiesEditForm(AdminEditForm):
     """Thesaurus properties edit form"""
@@ -235,12 +232,6 @@
             self.widgets['description'].widget_css_class = 'input textarea'
 
 
-@view_config(name='properties.json', context=IThesaurus, request_type=IPyAMSLayer,
-             permission=ADMIN_THESAURUS_PERMISSION, renderer='json', xhr=True)
-class ThesaurusPropertiesAJAXEditForm(AJAXEditForm, ThesaurusPropertiesEditForm):
-    """Thesaurus properties edit form, AJAX view"""
-
-
 #
 # Thesaurus terms views
 #
@@ -274,8 +265,7 @@
 
     @property
     def tree(self):
-        return sorted([INode(node) for node in ITree(self.context).get_root_nodes()],
-                      key=lambda x: x.label)
+        return [INode(node) for node in ITree(self.context).get_root_nodes()]
 
     @property
     def search_query_params(self):
@@ -326,7 +316,7 @@
         result = []
         self.get_nodes(term, result)
         return {'term': label,
-                'nodes': sorted(result, key=lambda x: x['label'])}
+                'nodes': result}
 
 
 @view_config(name='get-parent-nodes.json', context=IThesaurus, request_type=IPyAMSLayer,
@@ -406,6 +396,8 @@
 
 @pagelet_config(name='import.html', context=IThesaurus, layer=IPyAMSLayer,
                 permission=ADMIN_THESAURUS_PERMISSION)
+@ajax_config(name='import.json', context=IThesaurus, layer=IPyAMSLayer,
+             permission=ADMIN_THESAURUS_PERMISSION, base=AJAXAddForm)
 class ThesaurusImportForm(AdminDialogAddForm):
     """Thesaurus import form"""
 
@@ -413,8 +405,8 @@
     legend = _("Import thesaurus terms")
     icon_css_class = 'fa fa-fw fa-upload'
 
-    fields = field.Fields(IThesaurusUpdaterConfiguration).select('clear', 'conflict_suffix', 'data', 'format',
-                                                                 'import_synonyms', 'language', 'encoding')
+    fields = field.Fields(IThesaurusUpdaterConfiguration).select(
+        'clear', 'conflict_suffix', 'data', 'format', 'import_synonyms', 'language', 'encoding')
     buttons = button.Buttons(IThesaurusFormImportButtons)
 
     ajax_handler = 'import.json'
@@ -445,18 +437,12 @@
         return absolute_url(self.context, self.request, 'admin#terms.html')
 
 
-@view_config(name='import.json', context=IThesaurus, request_type=IPyAMSLayer,
-             permission=ADMIN_THESAURUS_PERMISSION, renderer='json', xhr=True)
-class ThesaurusImportAJAXForm(AJAXAddForm, ThesaurusImportForm):
-    """Thesaurus import form, AJAX view"""
-
-
 #
 # Terms export views
 #
 
-@viewlet_config(name='export.menu', context=IThesaurus, layer=IAdminLayer, manager=IThesaurusTermsMenu,
-                permission=VIEW_SYSTEM_PERMISSION, weight=15)
+@viewlet_config(name='export.menu', context=IThesaurus, layer=IAdminLayer,
+                manager=IThesaurusTermsMenu, permission=VIEW_SYSTEM_PERMISSION, weight=15)
 class ThesaurusExportMenuItem(MenuItem):
     """Thesaurus export menu"""
 
@@ -474,7 +460,10 @@
     add = button.Button(name='add', title=_("Export terms"))
 
 
-@pagelet_config(name='export.html', context=IThesaurus, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
+@pagelet_config(name='export.html', context=IThesaurus, layer=IPyAMSLayer,
+                permission=VIEW_SYSTEM_PERMISSION)
+@ajax_config(name='export.xml', context=IThesaurus, layer=IPyAMSLayer,
+             permission=VIEW_SYSTEM_PERMISSION, base=AJAXAddForm)
 class ThesaurusExportForm(AdminDialogAddForm):
     """Thesaurus export form"""
 
@@ -485,7 +474,6 @@
     fields = field.Fields(IThesaurusExporterConfiguration)
     buttons = button.Buttons(IThesaurusFormExportButtons)
 
-    ajax_handler = 'export.xml'
     download_target = 'download_frame'
     edit_permission = None
 
@@ -498,11 +486,6 @@
         exporter = self.exporter = get_utility(IThesaurusExporter, name=configuration.format)
         return exporter.export(self.context, configuration)
 
-
-@view_config(name='export.xml', context=IThesaurus, request_type=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
-class ThesaurusExportAJAXForm(AJAXAddForm, ThesaurusExportForm):
-    """Thesaurus export form, AJAX view"""
-
     def get_ajax_output(self, changes):
         changes.seek(0)
         headers = {'Content-Disposition': 'attachment; filename="{0}"'.format(self.configuration.filename)}
--- a/src/pyams_thesaurus/zmi/widget/__init__.py	Tue Aug 28 17:02:29 2018 +0200
+++ b/src/pyams_thesaurus/zmi/widget/__init__.py	Wed Aug 29 13:56:54 2018 +0200
@@ -181,7 +181,7 @@
         thesaurus = query_utility(IThesaurus, name=self.thesaurus_name or '')
         if thesaurus is not None:
             return sorted(thesaurus.get_top_terms(extract=self.extract_name),
-                          key=lambda x: x.label)
+                          key=lambda x: (x.order or 999, x.label))
         else:
             return ()