internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: GeotrekCE/Geotrek-admin

Issue:
Formulaire INTERVENTIONS - Onglet Avancé
Le référent SENTIERS préférerait que les champs COUTS et JOURS/HOMME soient affichés à la suite du formulaire plutôt que dans un onglet AVANCE car cela à revenir en haut du formulaire après avoir saisi les infos de base et du coup de nombreux agents passent à côté de la saisie de cette information.



Discussion:
Ok.

Sinon : 
- ré-afficher les onglets en bas
- laisser les onglets visibles en haut au défilement

Ré-afficher en bas serait une bonne idée. Idem dans le formulaire ITINERAIRES du coup.


Resolving patch:
diff --git a/geotrek/maintenance/forms.py b/geotrek/maintenance/forms.py
--- a/geotrek/maintenance/forms.py
+++ b/geotrek/maintenance/forms.py
@@ -51,6 +51,8 @@ class InterventionForm(CommonForm):
                                             queryset=BaseInfrastructure.objects.existing(),
                                             widget=forms.HiddenInput())
     length = FloatField(required=False, label=_("Length"))
+
+    leftpanel_scrollable = False
     fieldslayout = [
         Div(
             HTML("""
@@ -87,7 +89,7 @@ class InterventionForm(CommonForm):
                     css_id="advanced",  # used in Javascript for activating tab if error
                     css_class="tab-pane"
                 ),
-                css_class="tab-content"
+                css_class="scrollable tab-content"
             ),
             css_class="tabbable"
         ),
diff --git a/geotrek/trekking/forms.py b/geotrek/trekking/forms.py
--- a/geotrek/trekking/forms.py
+++ b/geotrek/trekking/forms.py
@@ -31,6 +31,9 @@ def __init__(self, *args, **kwargs):
 
 
 class TrekForm(TopologyForm):
+
+    leftpanel_scrollable = False
+
     fieldslayout = [
         Div(
             HTML("""
@@ -56,7 +59,7 @@ class TrekForm(TopologyForm):
                     'model',
 
                     css_id="main",
-                    css_class="tab-pane active"
+                    css_class="scrollable tab-pane active"
                 ),
                 Div(
                     'disabled_infrastructure',
@@ -71,7 +74,7 @@ class TrekForm(TopologyForm):
                     'information_desk',
                     Fieldset(_("Related treks"),),
                     css_id="advanced",  # used in Javascript for activating tab if error
-                    css_class="tab-pane"
+                    css_class="scrollable tab-pane"
                 ),
                 css_class="tab-content"
             ),


Test patch:
Repository: GeotrekCE/Geotrek-admin

Issue:
CHANTIERS - Cartes et exports de la carte
Nous avons déjà discuté du besoin de pouvoir faire un lien interactif entre la carte d'un chantier et la liste des différentes interventions qui le composent : https://github.com/makinacorpus/Geotrek/issues/214

La question se pose aussi sur la carte de l'export PDF d'un chantier pour identifier les interventions.
Afficher des numéros ? Des étiquettes ? 
Idem pour les aménagements et signalétique concernés par le chantier.



Discussion:
Related story : #871 


Resolving patch:
diff --git a/geotrek/maintenance/models.py b/geotrek/maintenance/models.py
--- a/geotrek/maintenance/models.py
+++ b/geotrek/maintenance/models.py
@@ -203,6 +203,10 @@ def total_cost(self):
                self.heliport_cost + \
                self.subcontract_cost
 
+    @classproperty
+    def total_cost_verbose_name(cls):
+        return _("Total cost")
+
     @classproperty
     def geomfield(cls):
         return Topology._meta.get_field('geom')
diff --git a/geotrek/trekking/views.py b/geotrek/trekking/views.py
--- a/geotrek/trekking/views.py
+++ b/geotrek/trekking/views.py
@@ -34,7 +34,7 @@ def get_template_names(self):
         template_names lookup.
         https://code.djangoproject.com/ticket/17484
         """
-        opts = self.model._meta
+        opts = self.get_model()._meta
         extra = ["%s/%s%s.html" % (opts.app_label, opts.object_name.lower(), self.template_name_suffix)]
         return extra + super(FlattenPicturesMixin, self).get_template_names()
 
@@ -42,8 +42,8 @@ def get_queryset(self):
         """ Override queryset to avoid attachment lookup while serializing.
         It will fetch attachments, and force ``pictures`` attribute of instances.
         """
-        app_label = self.model._meta.app_label
-        model_name = self.model._meta.object_name.lower()
+        app_label = self.get_model()._meta.app_label
+        model_name = self.get_model()._meta.object_name.lower()
         attachments = Attachment.objects.filter(content_type__app_label=app_label,
                                                 content_type__model=model_name)
         pictures = {}


Test patch:
Repository: GeotrekCE/Geotrek-admin

Issue:
Add overlay tiles layers from settings
https://github.com/makinacorpus/django-leaflet/issues/83 

Would allow to show cadastral parcels over orthophoto, "plans de circulation" etc.



Discussion:

Resolving patch:
diff --git a/geotrek/settings/dev.py b/geotrek/settings/dev.py
--- a/geotrek/settings/dev.py
+++ b/geotrek/settings/dev.py
@@ -19,13 +19,17 @@
 ) + INSTALLED_APPS
 
 #
-# Use Geotrek preprod tiles (uses default extent)
-# ................................................
+# Use some default tiles
+# ..........................
 
 LEAFLET_CONFIG['TILES'] = [
     (gettext_noop('Scan'), 'http://{s}.tile.osm.org/{z}/{x}/{y}.png', '(c) OpenStreetMap Contributors'),
     (gettext_noop('Ortho'), 'http://{s}.tiles.mapbox.com/v3/openstreetmap.map-4wvf9l0l/{z}/{x}/{y}.jpg', '(c) MapBox'),
 ]
+LEAFLET_CONFIG['OVERLAYS'] = [
+    (gettext_noop('Coeur de parc'), 'http://{s}.tilestream.makina-corpus.net/v2/coeur-ecrins/{z}/{x}/{y}.png', 'Ecrins'),
+]
+
 LEAFLET_CONFIG['SRID'] = 3857
 
 LOGGING['loggers']['geotrek']['level'] = 'DEBUG'


Test patch:
Repository: GeotrekCE/Geotrek-admin

Issue:
TRAIL filters
Add "communes, secteurs, type physique, type foncier..." for TRAILS filters as it is in other modules.



Discussion:

Resolving patch:
diff --git a/geotrek/land/filters.py b/geotrek/land/filters.py
--- a/geotrek/land/filters.py
+++ b/geotrek/land/filters.py
@@ -5,7 +5,7 @@
 from geotrek.common.models import Organism
 from geotrek.common.filters import StructureRelatedFilterSet
 
-from geotrek.core.filters import TopologyFilter, PathFilterSet
+from geotrek.core.filters import TopologyFilter, PathFilterSet, TrailFilterSet
 from geotrek.infrastructure.filters import InfrastructureFilterSet, SignageFilterSet
 from geotrek.maintenance.filters import InterventionFilterSet, ProjectFilterSet
 from geotrek.trekking.filters import TrekFilterSet, POIFilterSet
@@ -108,3 +108,4 @@ def add_edge_filters(filter_set):
 add_edge_filters(PathFilterSet)
 add_edge_filters(InfrastructureFilterSet)
 add_edge_filters(SignageFilterSet)
+add_edge_filters(TrailFilterSet)
diff --git a/geotrek/zoning/filters.py b/geotrek/zoning/filters.py
--- a/geotrek/zoning/filters.py
+++ b/geotrek/zoning/filters.py
@@ -1,6 +1,6 @@
 from django.utils.translation import ugettext_lazy as _
 
-from geotrek.core.filters import TopologyFilter, PathFilterSet
+from geotrek.core.filters import TopologyFilter, PathFilterSet, TrailFilterSet
 from geotrek.infrastructure.filters import InfrastructureFilterSet, SignageFilterSet
 from geotrek.maintenance.filters import InterventionFilterSet, ProjectFilterSet
 from geotrek.trekking.filters import TrekFilterSet, POIFilterSet
@@ -36,6 +36,7 @@ def add_edge_filters(filter_set):
 add_edge_filters(PathFilterSet)
 add_edge_filters(InfrastructureFilterSet)
 add_edge_filters(SignageFilterSet)
+add_edge_filters(TrailFilterSet)
 
 
 class IntersectionFilter(TopologyFilter):


Test patch:
Repository: GeotrekCE/Geotrek-admin

Issue:
Infrastructure list is filtered on "Ouvrage" by default
J'ai créé des points d'aménagements (8 au total), cependant la plupart ne s'affichent pas (ni dans la liste, ni sur la carte)...
![1](https://cloud.githubusercontent.com/assets/7872468/3261864/b950187a-f25e-11e3-90ce-49701ae4aa36.JPG)
Lorsque je rentre dans une fiche aménagement et que je reclique sur le bouton liste, là ils apparaissent tous mais seulement sur la carte.
![2](https://cloud.githubusercontent.com/assets/7872468/3261921/4d0614a2-f25f-11e3-8234-d1b44a293728.JPG)
Par contre, si je touche au zoom, ils disparaissent et je n'ai plus que les trois du début.



Discussion:
Merci !

Peut-être lié à #946 ? À investiguer...

_Pistes_: tester avec un autre navigateur, utiliser Ctrl+F5 pour forcer le cache, ...

C'est bon j'ai trouvé !
En fait il y a un filtre par défaut sur les ouvrages... Et les points qui n'apparaissent pas sont en équipement.
![3](https://cloud.githubusercontent.com/assets/7872468/3262997/97d4621a-f26c-11e3-85d1-9d4644fd1894.JPG)
Quand je mets le filtre équipement, mes 5 autres points apparaissent.
![4](https://cloud.githubusercontent.com/assets/7872468/3263002/ad2a41a2-f26c-11e3-926d-71e2d5d3929d.JPG)
P.S : Du coup, depuis ces mêmes filtres de la partie aménagement, on peut voir un filtre signalétique qui ne renvoie rien puisque la signalétique est gérée dans un autre onglet.
![5](https://cloud.githubusercontent.com/assets/7872468/3263194/0a354b42-f26f-11e3-8859-ace164d9db6a.jpg)

Bonne nouvelle :)

C'est quand-même un bug cela dit, mais mineur


Resolving patch:
diff --git a/geotrek/infrastructure/filters.py b/geotrek/infrastructure/filters.py
--- a/geotrek/infrastructure/filters.py
+++ b/geotrek/infrastructure/filters.py
@@ -20,6 +20,11 @@ def __init__(self, *args, **kwargs):
         field = self.form.fields['type']
         field.queryset = field.queryset.exclude(type=INFRASTRUCTURE_TYPES.SIGNAGE)
 
+        field = self.form.fields['type__type']
+        all_choices = field.widget.choices
+        all_choices = [c for c in all_choices if c[0] != INFRASTRUCTURE_TYPES.SIGNAGE]
+        field.widget.choices = [('', _(u"Category"))] + all_choices
+
     class Meta(StructureRelatedFilterSet.Meta):
         model = Infrastructure
         fields = StructureRelatedFilterSet.Meta.fields + ['type__type', 'type']
@@ -29,11 +34,6 @@ class SignageFilterSet(StructureRelatedFilterSet):
     intervention_year = YearFilter(name='interventions_set__date',
                                    widget=InfrastructureYearSelect)
 
-    def __init__(self, *args, **kwargs):
-        super(SignageFilterSet, self).__init__(*args, **kwargs)
-        field = self.form.fields['type']
-        field.queryset = field.queryset.filter(type=INFRASTRUCTURE_TYPES.SIGNAGE)
-
     class Meta(StructureRelatedFilterSet.Meta):
         model = Signage
-        fields = StructureRelatedFilterSet.Meta.fields + ['type']
+        fields = StructureRelatedFilterSet.Meta.fields


Test patch:
Repository: GeotrekCE/Geotrek-admin

Issue:
SEARCH_PATH for Geotrek DB user
Since Geotrek 0.28, tables and functions have be moved to different schemas, which is a very good point (https://github.com/makinacorpus/Geotrek/releases/tag/v0.28.0).

Schemas are not mentionned in triggers which is OK too, as Django is doing it in his connexions so it is not a problem for GEOTREK applications.

It gets a problem when you try to edit or insert a data from an external tool (QGIS, Talend...). 
You have to change the db_user search_path so that he can find tables and functions not only in public schemas.

It could be interesting to do it during GEOTREK installation for the Geotrek DB user mentionned in settings : 

ALTER USER $geotrek_db_user SET 
search_path=public,django,geotrek,gestion,rando,zonage,foncier,tourisme; 

Of course if you are using another user to edit datas in external tools, you will have to do it manually the first time. 



Discussion:
Search path can be set at database level too:
ALTER DATABASE $geotrek_db SET
search_path=public,django,geotrek,gestion,rando,zonage,foncier,tourisme; 

Yes of course, this is what I done. Because I got the informations.
But other users will not know nor understand why it dont work anymore when working in QGIS or Talend such as here : https://groups.google.com/forum/#!topic/geotrek-fr/rzqTyC0fElw

So it would be good to include the SQL in installation/migration script for Geotrek_DB_user as I guess most of people are editing the DB from external tools with the same user. 

Of course those who are using another db_user will have to change their search_path manually at DB level.

Yes, instead of specifying the search_path at the connection level, we could `ALTER USER` during the sync process ([here for example](https://github.com/makinacorpus/Geotrek/blob/v0.28.2/geotrek/common/utils/postgresql.py#L102-L141))

OK and will work for those who are installing Geotrek from scratch ? Not only for those who are updating it ? 

Yep :)


Resolving patch:
diff --git a/geotrek/common/utils/postgresql.py b/geotrek/common/utils/postgresql.py
--- a/geotrek/common/utils/postgresql.py
+++ b/geotrek/common/utils/postgresql.py
@@ -139,3 +139,12 @@ def move_models_to_schemas(app_label):
                 logger.info("Moved %s to schema %s" % (table_name, schema_name))
             except Exception:
                 logger.debug("Table %s already in schema %s" % (table_name, schema_name))
+
+    # For Django, search_path is set in connection options.
+    # But when accessing the database using QGis or ETL, search_path must be
+    # set database level (for all users, and for this database only).
+    if app_label == 'common':
+        dbname = settings.DATABASES['default']['NAME']
+        search_path = 'public,%s' % ','.join(set(settings.DATABASE_SCHEMAS.values()))
+        sql = "ALTER DATABASE %s SET search_path=%s;" % (dbname, search_path)
+        cursor.execute(sql)


Test patch:
Repository: GeotrekCE/Geotrek-admin

Issue:
Infrastructures are duplicated in list if they received multiple intervention the same year
- Filter infrastructures by year
- If the infrastructure has received several interventions this same year, it will appear multiple times in the list

Related #293 



Discussion:

Resolving patch:
diff --git a/geotrek/common/filters.py b/geotrek/common/filters.py
--- a/geotrek/common/filters.py
+++ b/geotrek/common/filters.py
@@ -26,7 +26,7 @@ class YearFilter(Filter):
     def do_filter(self, qs, year):
         return qs.filter(**{
             '%s__year' % self.name: year,
-        })
+        }).distinct()
 
     def filter(self, qs, value):
         try:
diff --git a/geotrek/land/views.py b/geotrek/land/views.py
--- a/geotrek/land/views.py
+++ b/geotrek/land/views.py
@@ -16,7 +16,7 @@ class PhysicalEdgeLayer(MapEntityLayer):
 class PhysicalEdgeList(MapEntityList):
     queryset = PhysicalEdge.objects.existing()
     filterform = PhysicalEdgeFilterSet
-    columns = ['id', 'physical_type']
+    columns = ['id', 'physical_type', 'length']
 
 
 class PhysicalEdgeJsonList(MapEntityJsonList, PhysicalEdgeList):
@@ -57,7 +57,7 @@ class LandEdgeLayer(MapEntityLayer):
 class LandEdgeList(MapEntityList):
     queryset = LandEdge.objects.existing()
     filterform = LandEdgeFilterSet
-    columns = ['id', 'land_type']
+    columns = ['id', 'land_type', 'length']
 
 
 class LandEdgeJsonList(MapEntityJsonList, LandEdgeList):
@@ -98,7 +98,7 @@ class CompetenceEdgeLayer(MapEntityLayer):
 class CompetenceEdgeList(MapEntityList):
     queryset = CompetenceEdge.objects.existing()
     filterform = CompetenceEdgeFilterSet
-    columns = ['id', 'organization']
+    columns = ['id', 'organization', 'length']
 
 
 class CompetenceEdgeJsonList(MapEntityJsonList, CompetenceEdgeList):
@@ -139,7 +139,7 @@ class WorkManagementEdgeLayer(MapEntityLayer):
 class WorkManagementEdgeList(MapEntityList):
     queryset = WorkManagementEdge.objects.existing()
     filterform = WorkManagementEdgeFilterSet
-    columns = ['id', 'organization']
+    columns = ['id', 'organization', 'length']
 
 
 class WorkManagementEdgeJsonList(MapEntityJsonList, WorkManagementEdgeList):
@@ -180,7 +180,7 @@ class SignageManagementEdgeLayer(MapEntityLayer):
 class SignageManagementEdgeList(MapEntityList):
     queryset = SignageManagementEdge.objects.existing()
     filterform = SignageManagementEdgeFilterSet
-    columns = ['id', 'organization']
+    columns = ['id', 'organization', 'length']
 
 
 class SignageManagementEdgeJsonList(MapEntityJsonList, SignageManagementEdgeList):


Test patch:
Repository: GeotrekCE/Geotrek-admin

Issue:
set_schema_ft() SQL function delete some triggers
set_schema_ft() contains as "DROP FUNCTION ... CASCADE" that delete some other functions or triggers, eg. e_t_evenement_geom_iu_tgr.

All 0.28.x releases are affected.

I think we should create functions directly in the right schema and drop functions from public schema rather than moving them.



Discussion:
Ouch... :( my fault


Resolving patch:
diff --git a/geotrek/common/utils/postgresql.py b/geotrek/common/utils/postgresql.py
--- a/geotrek/common/utils/postgresql.py
+++ b/geotrek/common/utils/postgresql.py
@@ -133,12 +133,12 @@ def move_models_to_schemas(app_label):
 
     for schema_name, tables in table_schemas.items():
         for table_name in tables:
-            try:
+            sql = "SELECT 1 FROM information_schema.tables WHERE table_name=%s AND table_schema!=%s"
+            cursor.execute(sql, [table_name, schema_name])
+            if cursor.fetchone():
                 sql = "ALTER TABLE %s SET SCHEMA %s;" % (table_name, schema_name)
                 cursor.execute(sql)
                 logger.info("Moved %s to schema %s" % (table_name, schema_name))
-            except Exception:
-                logger.debug("Table %s already in schema %s" % (table_name, schema_name))
 
     # For Django, search_path is set in connection options.
     # But when accessing the database using QGis or ETL, search_path must be


Test patch:
diff --git a/geotrek/common/tests.py b/geotrek/common/tests.py
--- a/geotrek/common/tests.py
+++ b/geotrek/common/tests.py
@@ -77,7 +77,7 @@ def test_postgresql_notices(self):
         def raisenotice():
             cursor = connection.cursor()
             cursor.execute("""
-                CREATE OR REPLACE FUNCTION raisenotice() RETURNS boolean AS $$
+                CREATE OR REPLACE FUNCTION geotrek.raisenotice() RETURNS boolean AS $$
                 BEGIN
                 RAISE NOTICE 'hello'; RETURN FALSE;
                 END; $$ LANGUAGE plpgsql;
Repository: GeotrekCE/Geotrek-admin

Issue:
WYSIWYG for static pages
Client-side WYSIWYG : 
- http://sofish.github.io/pen/
- https://github.com/mduvall/grande.js
- http://imperavi.com/redactor/
- https://github.com/tholman/zenpen



Discussion:

Resolving patch:
diff --git a/geotrek/flatpages/admin.py b/geotrek/flatpages/admin.py
--- a/geotrek/flatpages/admin.py
+++ b/geotrek/flatpages/admin.py
@@ -2,6 +2,7 @@
 from django.conf import settings
 
 from modeltranslation.admin import TranslationAdmin
+from tinymce.widgets import TinyMCE
 
 from geotrek.flatpages import models as flatpages_models
 
@@ -10,6 +11,11 @@ class FlatPagesAdmin(TranslationAdmin):
     list_display = ('title', 'published', 'publication_date', 'target')
     search_fields = ('title', 'content')
 
+    def formfield_for_dbfield(self, db_field, **kwargs):
+        if db_field.name[:7] == 'content':
+            return db_field.formfield(widget=TinyMCE)
+        return super(FlatPagesAdmin, self).formfield_for_dbfield(db_field, **kwargs)
+
 
 if settings.FLATPAGES_ENABLED:
     admin.site.register(flatpages_models.FlatPage, FlatPagesAdmin)
diff --git a/geotrek/flatpages/views.py b/geotrek/flatpages/views.py
--- a/geotrek/flatpages/views.py
+++ b/geotrek/flatpages/views.py
@@ -1,3 +1,4 @@
+from rest_framework import permissions as rest_permissions
 from rest_framework import viewsets
 
 from geotrek.flatpages.serializers import FlatPageSerializer
@@ -8,5 +9,9 @@ class FlatPageViewSet(viewsets.ModelViewSet):
     """
     A viewset for viewing and editing flat pages instances.
     """
+    model = flatpages_models.FlatPage
     serializer_class = FlatPageSerializer
-    queryset = flatpages_models.FlatPage.objects.all()
+    permission_classes = [rest_permissions.DjangoModelPermissionsOrAnonReadOnly]
+
+    def get_queryset(self):
+        return flatpages_models.FlatPage.objects.filter(published=True)


Test patch:
diff --git a/geotrek/flatpages/tests.py b/geotrek/flatpages/tests.py
--- a/geotrek/flatpages/tests.py
+++ b/geotrek/flatpages/tests.py
@@ -90,26 +90,16 @@ def test_flatpages_are_translatable(self):
 
 class RESTViewsTest(TestCase):
     def setUp(self):
-        FlatPageFactory.create_batch(10)
-
-    def login(self):
-        user = SuperUserFactory(password='booh')
-        success = self.client.login(username=user.username, password='booh')
-        self.assertTrue(success)
-
-    def test_endpoint_is_protected(self):
-        response = self.client.get('/api/flatpages/')
-        self.assertEquals(response.status_code, 403)
+        FlatPageFactory.create_batch(10, published=True)
+        FlatPageFactory.create(published=False)
 
     def test_records_list(self):
-        self.login()
         response = self.client.get('/api/flatpages/')
         self.assertEquals(response.status_code, 200)
         records = json.loads(response.content)
         self.assertEquals(len(records), 10)
 
     def test_serialized_attributes(self):
-        self.login()
         response = self.client.get('/api/flatpages/')
         records = json.loads(response.content)
         record = records[0]
Repository: GeotrekCE/Geotrek-admin

Issue:
SIGNAGES module / Type filter disappeared
I think TYPE filter was available before.
Crucial filter of course.



Discussion:
Any idea why these filters disappeared a few versions ago ?


Resolving patch:
diff --git a/geotrek/infrastructure/filters.py b/geotrek/infrastructure/filters.py
--- a/geotrek/infrastructure/filters.py
+++ b/geotrek/infrastructure/filters.py
@@ -12,8 +12,7 @@ class InfrastructureYearSelect(InterventionYearSelect):
 
 class InfrastructureFilterSet(StructureRelatedFilterSet):
     intervention_year = YearFilter(name='interventions_set__date',
-                                   widget=InfrastructureYearSelect,
-                                   label=_(u"Intervention year"))
+                                   widget=InfrastructureYearSelect)
 
     def __init__(self, *args, **kwargs):
         super(InfrastructureFilterSet, self).__init__(*args, **kwargs)
@@ -34,6 +33,11 @@ class SignageFilterSet(StructureRelatedFilterSet):
     intervention_year = YearFilter(name='interventions_set__date',
                                    widget=InfrastructureYearSelect)
 
+    def __init__(self, *args, **kwargs):
+        super(SignageFilterSet, self).__init__(*args, **kwargs)
+        field = self.form.fields['type']
+        field.queryset = field.queryset.filter(type=INFRASTRUCTURE_TYPES.SIGNAGE)
+
     class Meta(StructureRelatedFilterSet.Meta):
         model = Signage
-        fields = StructureRelatedFilterSet.Meta.fields
+        fields = StructureRelatedFilterSet.Meta.fields + ['type']


Test patch:
Repository: GeotrekCE/Geotrek-admin

Issue:
Clarify 3D and 2D lengths
It is a good point that both lengths are now displayed in detail pages.

On lists, this is the 3D length that is displayed, good point too but it would be good to mention it in label (3D length).

In list exports, it would be great to have both length too. As actually it seems like there is only the 3D length in exports.



Discussion:

Resolving patch:
diff --git a/geotrek/core/models.py b/geotrek/core/models.py
--- a/geotrek/core/models.py
+++ b/geotrek/core/models.py
@@ -86,7 +86,7 @@ def length_2d(self):
 
     @classproperty
     def length_2d_verbose_name(cls):
-        return u"{} {}".format(_(u"2D"), _(u"Length"))
+        return _(u"2D Length")
 
     @property
     def length_2d_display(self):
@@ -231,7 +231,7 @@ def length_2d(self):
 
     @classproperty
     def length_2d_verbose_name(cls):
-        return u"{} {}".format(_(u"2D"), _(u"Length"))
+        return _(u"2D Length")
 
     @property
     def length_2d_display(self):


Test patch: