add location and geonames resolvers and api
authorymh <ymh.work@gmail.com>
Tue, 27 Sep 2016 23:43:29 +0200
changeset 304 20071981ba2a
parent 303 2fef8007c2b2
child 305 ff6cf3fc5f40
add location and geonames resolvers and api
.hgignore
cms/app-client/mirage/config.js
cms/app-client/mirage/fixtures/geonames.js
cms/app-client/mirage/models/geonames.js
common/corpus-common-addon/.eslintrc.json
common/corpus-common-addon/addon/components/doc-location.js
common/corpus-common-addon/addon/helpers/get-link-type.js
common/corpus-common-addon/addon/templates/components/doc-language.hbs
common/corpus-common-addon/addon/templates/components/doc-location.hbs
common/corpus-common-addon/addon/templates/components/doc-subject.hbs
common/corpus-common-addon/addon/utils/constants.js
common/corpus-common-addon/addon/utils/utils.js
common/corpus-common-addon/app/components/doc-location.js
common/corpus-common-addon/app/services/geonames-resolver.js
common/corpus-common-addon/jsconfig.json
common/corpus-common-addon/package.json
server/bo_client/app/adapters/application.js
server/bo_client/app/locales/en/translations.js
server/bo_client/app/locales/fr/translations.js
server/bo_client/app/models/document.js
server/bo_client/app/pods/components/bo-doc-locations/component.js
server/bo_client/app/pods/components/bo-doc-locations/template.hbs
server/bo_client/app/templates/doc.hbs
server/bo_client/jsconfig.json
server/bo_client/package.json
server/bo_client/server/fixtures/documents.js
server/bo_client/server/fixtures/geonames.js
server/bo_client/server/mocks/geonames.js
server/bo_client/tests/integration/pods/components/bo-doc-locations/component-test.js
server/src/app/Http/Controllers/Api/DocumentController.php
server/src/app/Http/Controllers/Api/GeonamesController.php
server/src/app/Providers/GeonamesServiceProvider.php
server/src/app/Services/GeonamesResolver.php
server/src/app/Services/GeonamesResolverException.php
server/src/app/Services/GeonamesResolverInterface.php
server/src/app/Services/LexvoResolver.php
server/src/config/app.php
server/src/config/corpusparole.php
server/src/routes/api.php
server/src/tests/Controllers/GeonamesControllerTest.php
server/src/tests/Services/GeonamesResolverTest.php
server/src/tests/Services/files/GeonamesResolverTest/geonames_rdf_2968801.rdf
server/src/tests/Services/files/GeonamesResolverTest/geonames_rdf_2988507.rdf
server/src/tests/Services/files/GeonamesResolverTest/geonames_rdf_6255148.rdf
--- a/.hgignore	Tue Sep 27 01:50:53 2016 +0200
+++ b/.hgignore	Tue Sep 27 23:43:29 2016 +0200
@@ -65,3 +65,4 @@
 ^common/corpus-common-addonnpm-debug.log
 ^common/corpus-common-addontestem.log
 /\.\#
+\.vscode
--- a/cms/app-client/mirage/config.js	Tue Sep 27 01:50:53 2016 +0200
+++ b/cms/app-client/mirage/config.js	Tue Sep 27 23:43:29 2016 +0200
@@ -74,5 +74,22 @@
         };
     });
 
+    this.get('/geonames/:ids', ({ geonames }, request) => {
+        var geonamesIds = decodeURIComponent(request.params.ids);
+        var resMap = _.reduce(geonamesIds.split(','), function(res, id) {
+            var code = id;
+            var m = code.match(constants.GEONAMES_BASE_URLS);
+            if(m) {
+                code = code.slice(m[0].length);
+            }
+            code = code.replace(/\/+$/, '');
+            var geonamesRes = geonames.find(code);
+            res[id] = geonamesRes?geonamesRes.label:null;
+            return res;
+        }, {});
+        return {
+            'geonamesids': resMap
+        };
+    });
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/mirage/fixtures/geonames.js	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,752 @@
+export default [
+    { 'id': '3038033', 'label': 'Alsace' },
+    { 'id': '6617404', 'label': 'Andlau' },
+    { 'id': '6450647', 'label': 'Battenheim' },
+    { 'id': '6450655', 'label': 'Berrwiller' },
+    { 'id': '6450585', 'label': 'Berstett' },
+    { 'id': '6450662', 'label': 'Bisel' },
+    { 'id': '6450665', 'label': 'Blotzheim' },
+    { 'id': '6614770', 'label': 'B\u0153senbiesen' },
+    { 'id': '6613081', 'label': 'Bretten' },
+    { 'id': '6450610', 'label': 'Brumath' },
+    { 'id': '6450616', 'label': 'Cleebourg' },
+    { 'id': '6455225', 'label': 'Dambach' },
+    { 'id': '6613079', 'label': 'Dehlingen' },
+    { 'id': '6450629', 'label': 'Diebolsheim' },
+    { 'id': '6614520', 'label': 'Dinsheim-sur-Bruche' },
+    { 'id': '6450691', 'label': 'Durmenach' },
+    { 'id': '6441075', 'label': 'Durstel' },
+    { 'id': '6441079', 'label': 'Eckartswiller' },
+    { 'id': '6450694', 'label': 'Eguisheim' },
+    { 'id': '6441094', 'label': 'Ettendorf' },
+    { 'id': '6441437', 'label': 'Geishouse' },
+    { 'id': '6441110', 'label': 'Geispolsheim' },
+    { 'id': '6441439', 'label': 'Geiswasser' },
+    { 'id': '6441112', 'label': 'Gerstheim' },
+    { 'id': '6617435', 'label': 'Gildwiller' },
+    { 'id': '6614642', 'label': 'G\u0153rlingen' },
+    { 'id': '6441116', 'label': 'Gottenhouse' },
+    { 'id': '6441117', 'label': 'Gottesheim' },
+    { 'id': '6441127', 'label': 'Gundershoffen' },
+    { 'id': '6441449', 'label': 'Gunsbach' },
+    { 'id': '6441128', 'label': 'Gunstett' },
+    { 'id': '6441131', 'label': 'Haguenau' },
+    { 'id': '6441134', 'label': 'Harskirchen' },
+    { 'id': '6441138', 'label': 'Heidolsheim' },
+    { 'id': '6441140', 'label': 'Heiligenstein' },
+    { 'id': '6441141', 'label': 'Hengwiller' },
+    { 'id': '6441150', 'label': 'Hirschland' },
+    { 'id': '6441470', 'label': 'Hirtzbach' },
+    { 'id': '6441471', 'label': 'Hirtzfelden' },
+    { 'id': '6614941', 'label': 'H\u0153rdt' },
+    { 'id': '6456344', 'label': 'Le Hohwald' },
+    { 'id': '6441156', 'label': 'Holtzheim' },
+    { 'id': '6441476', 'label': 'Houssen' },
+    { 'id': '6441479', 'label': 'Huningue' },
+    { 'id': '6441483', 'label': 'Illhaeusern' },
+    { 'id': '6441164', 'label': 'Ingolsheim' },
+    { 'id': '6441168', 'label': 'Ittenheim' },
+    { 'id': '6441487', 'label': 'Jebsheim' },
+    { 'id': '6614942', 'label': 'Kleing\u0153ft' },
+    { 'id': '6441184', 'label': 'Krautergersheim' },
+    { 'id': '6456345', 'label': 'La Petite-Pierre' },
+    { 'id': '6456347', 'label': 'La Wantzenau' },
+    { 'id': '6441510', 'label': 'Liebsdorf' },
+    { 'id': '6441199', 'label': 'Limersheim' },
+    { 'id': '6441205', 'label': 'Lochwiller' },
+    { 'id': '6441524', 'label': 'Manspach' },
+    { 'id': '6441214', 'label': 'Marckolsheim' },
+    { 'id': '6441215', 'label': 'Marlenheim' },
+    { 'id': '6441219', 'label': 'Memmelshoffen' },
+    { 'id': '6441220', 'label': 'Menchhoffen' },
+    { 'id': '6441528', 'label': 'Meyenheim' },
+    { 'id': '6441226', 'label': 'Mittelhausbergen' },
+    { 'id': '6441538', 'label': 'Le Haut Soultzbach' },
+    { 'id': '6441233', 'label': 'Mothern' },
+    { 'id': '6617442', 'label': 'Muespach' },
+    { 'id': '6454564', 'label': 'Munchhouse' },
+    { 'id': '6441543', 'label': 'Munwiller' },
+    { 'id': '6441237', 'label': 'Muttersholtz' },
+    { 'id': '6441297', 'label': 'Reichshoffen' },
+    { 'id': '6441242', 'label': 'Neuhaeusel' },
+    { 'id': '6615252', 'label': 'Neuwiller' },
+    { 'id': '6614997', 'label': 'Niederr\u0153dern' },
+    { 'id': '6441251', 'label': 'Niederschaeffolsheim' },
+    { 'id': '6441551', 'label': 'Niffer' },
+    { 'id': '6441555', 'label': 'Oberlarg' },
+    { 'id': '6441264', 'label': 'Oberlauterbach' },
+    { 'id': '6441268', 'label': 'Obersteinbach' },
+    { 'id': '6441270', 'label': 'Oermingen' },
+    { 'id': '6441271', 'label': 'Offendorf' },
+    { 'id': '6441273', 'label': 'Ohlungen' },
+    { 'id': '6441278', 'label': 'Osthouse' },
+    { 'id': '6441282', 'label': 'Ottrott' },
+    { 'id': '6441568', 'label': 'Pfetterhouse' },
+    { 'id': '6441296', 'label': 'Reichsfeld' },
+    { 'id': '6441298', 'label': 'Reichstett' },
+    { 'id': '6441576', 'label': 'Reiningue' },
+    { 'id': '6441300', 'label': 'Reipertswiller' },
+    { 'id': '6441304', 'label': 'Rhinau' },
+    { 'id': '6441579', 'label': 'Richwiller' },
+    { 'id': '6441583', 'label': 'Rimbach-pr\u00e8s-Guebwiller' },
+    { 'id': '6441585', 'label': 'Rimbachzell' },
+    { 'id': '6441310', 'label': 'Rittershoffen' },
+    { 'id': '6441587', 'label': 'Rixheim' },
+    { 'id': '6441595', 'label': 'Rosenau' },
+    { 'id': '6441316', 'label': 'Rossfeld' },
+    { 'id': '6441600', 'label': 'Rumersheim-le-Haut' },
+    { 'id': '6441343', 'label': 'Scheibenhard' },
+    { 'id': '6441345', 'label': 'Scherwiller' },
+    { 'id': '6441347', 'label': 'Schiltigheim' },
+    { 'id': '6441349', 'label': 'Schirrhein' },
+    { 'id': '6441351', 'label': 'Schleithal' },
+    { 'id': '6441610', 'label': 'Schlierbach' },
+    { 'id': '6614771', 'label': 'Sch\u0153nau' },
+    { 'id': '6617419', 'label': 'Betschdorf' },
+    { 'id': '6441616', 'label': 'Sewen' },
+    { 'id': '6441618', 'label': 'Sierentz' },
+    { 'id': '6441360', 'label': 'Siewiller' },
+    { 'id': '6612746', 'label': 'Siltzheim' },
+    { 'id': '6441365', 'label': 'Soufflenheim' },
+    { 'id': '6441626', 'label': 'Soultzeren' },
+    { 'id': '6454553', 'label': 'Saint-Pierre' },
+    { 'id': '6441607', 'label': 'Sainte-Marie-aux-Mines' },
+    { 'id': '6441631', 'label': 'Steinbach' },
+    { 'id': '6441637', 'label': 'Storckensohn' },
+    { 'id': '6617427', 'label': 'Stutzheim-Offenheim' },
+    { 'id': '6441379', 'label': 'Thanvill\u00e9' },
+    { 'id': '6441387', 'label': 'Uhrwiller' },
+    { 'id': '6441655', 'label': 'Village-Neuf' },
+    { 'id': '6617445', 'label': 'Volgelsheim' },
+    { 'id': '6454568', 'label': 'Waltenheim' },
+    { 'id': '6441661', 'label': 'Wasserbourg' },
+    { 'id': '6441407', 'label': 'Weiterswiller' },
+    { 'id': '6441670', 'label': 'Widensolen' },
+    { 'id': '6441673', 'label': 'Willer-sur-Thur' },
+    { 'id': '6617432', 'label': 'Wickersheim-Wilshausen' },
+    { 'id': '6454558', 'label': 'Wingen' },
+    { 'id': '6441674', 'label': 'Winkel' },
+    { 'id': '6441420', 'label': 'Wintzenheim-Kochersberg' },
+    { 'id': '6454559', 'label': 'Wissembourg' },
+    { 'id': '6441427', 'label': 'Wolfskirchen' },
+    { 'id': '6441680', 'label': 'Wolschwiller' },
+    { 'id': '6441429', 'label': 'Wolxheim' },
+    { 'id': '6441433', 'label': 'Zinswiller' },
+    { 'id': '6452479', 'label': 'Andolsheim' },
+    { 'id': '6614074', 'label': 'Artzenheim' },
+    { 'id': '6450566', 'label': 'Aschbach' },
+    { 'id': '6455226', 'label': 'Aspach' },
+    { 'id': '6450637', 'label': 'Aspach-Michelbach' },
+    { 'id': '6450574', 'label': 'Bassemberg' },
+    { 'id': '6450576', 'label': 'Beinheim' },
+    { 'id': '6614330', 'label': 'Bouxwiller' },
+    { 'id': '6450669', 'label': 'Br\u00e9chaumont' },
+    { 'id': '6450673', 'label': 'Bruebach' },
+    { 'id': '6450675', 'label': 'Buethwiller' },
+    { 'id': '6455228', 'label': 'Colmar' },
+    { 'id': '6450619', 'label': 'Cosswiller' },
+    { 'id': '6450685', 'label': 'Dessenheim' },
+    { 'id': '6441077', 'label': 'Ebersheim' },
+    { 'id': '6441089', 'label': 'Ernolsheim-Bruche' },
+    { 'id': '6441095', 'label': 'Eywiller' },
+    { 'id': '6441115', 'label': 'Gingsheim' },
+    { 'id': '6441441', 'label': 'Grentzingen' },
+    { 'id': '6441125', 'label': 'Griesheim-pr\u00e8s-Molsheim' },
+    { 'id': '6441444', 'label': 'Gueberschwihr' },
+    { 'id': '6441136', 'label': 'Hattmatt' },
+    { 'id': '6441153', 'label': 'Hoffen' },
+    { 'id': '6441477', 'label': 'Hunawihr' },
+    { 'id': '6441173', 'label': 'Kertzfeld' },
+    { 'id': '6441174', 'label': 'Keskastel' },
+    { 'id': '6441494', 'label': 'Kientzheim' },
+    { 'id': '6441352', 'label': 'Schnersheim' },
+    { 'id': '6441498', 'label': 'Kruth' },
+    { 'id': '6441317', 'label': 'Rosteig' },
+    { 'id': '6441196', 'label': 'Lembach' },
+    { 'id': '6441515', 'label': 'Logelheim' },
+    { 'id': '6441217', 'label': 'Meistratzheim' },
+    { 'id': '6614939', 'label': 'G\u0153rsdorf' },
+    { 'id': '6441541', 'label': 'Mulhouse' },
+    { 'id': '6441240', 'label': 'Natzwiller' },
+    { 'id': '6441246', 'label': 'Niederhaslach' },
+    { 'id': '6617421', 'label': 'Seebach' },
+    { 'id': '6617443', 'label': 'Orschwihr' },
+    { 'id': '6614644', 'label': 'Pfalzweyer' },
+    { 'id': '6441569', 'label': 'Pulversheim' },
+    { 'id': '6441294', 'label': 'Ratzwiller' },
+    { 'id': '6441307', 'label': 'Rimsdorf' },
+    { 'id': '6441312', 'label': 'Rohrwiller' },
+    { 'id': '6441314', 'label': 'Rosenwiller' },
+    { 'id': '6441326', 'label': 'Saessolsheim' },
+    { 'id': '6441605', 'label': 'Saint-Hippolyte' },
+    { 'id': '6441369', 'label': 'Stattmatten' },
+    { 'id': '6441643', 'label': 'Thannenkirch' },
+    { 'id': '6441380', 'label': 'Tieffenbach' },
+    { 'id': '6441646', 'label': 'Turckheim' },
+    { 'id': '6441658', 'label': 'Walbach' },
+    { 'id': '6441400', 'label': 'Waldolwisheim' },
+    { 'id': '6617411', 'label': 'Wangenbourg-Engenthal' },
+    { 'id': '6441408', 'label': 'Westhoffen' },
+    { 'id': '6441672', 'label': 'Wildenstein' },
+    { 'id': '6441413', 'label': 'Wilwisheim' },
+    { 'id': '6441423', 'label': 'Wittersheim' },
+    { 'id': '6450668', 'label': 'Bourbach-le-Haut' },
+    { 'id': '6450677', 'label': 'Burnhaupt-le-Haut' },
+    { 'id': '6450704', 'label': 'Fislis' },
+    { 'id': '6450708', 'label': 'Franken' },
+    { 'id': '6450710', 'label': 'Friesen' },
+    { 'id': '6614990', 'label': 'Fr\u0153ningen' },
+    { 'id': '6441436', 'label': 'Galfingue' },
+    { 'id': '6441162', 'label': 'Illkirch-Graffenstaden' },
+    { 'id': '6441122', 'label': 'Grendelbruch' },
+    { 'id': '6614913', 'label': 'K\u0153stlach' },
+    { 'id': '6441509', 'label': 'Liebenswiller' },
+    { 'id': '6441514', 'label': 'Linthal' },
+    { 'id': '6441522', 'label': 'Magstatt-le-Haut' },
+    { 'id': '6441530', 'label': 'Michelbach-le-Haut' },
+    { 'id': '6441540', 'label': 'Muhlbach-sur-Munster' },
+    { 'id': '6441545', 'label': 'Nambsheim' },
+    { 'id': '6441547', 'label': 'Niederbruck' },
+    { 'id': '6441554', 'label': 'Oberhergheim' },
+    { 'id': '6441557', 'label': 'Obermorschwiller' },
+    { 'id': '6441564', 'label': 'Ottmarsheim' },
+    { 'id': '6441289', 'label': 'Plobsheim' },
+    { 'id': '6441571', 'label': 'Raedersheim' },
+    { 'id': '6441620', 'label': 'Sondernach' },
+    { 'id': '6441604', 'label': 'Sainte-Croix-en-Plaine' },
+    { 'id': '6441375', 'label': 'Strasbourg' },
+    { 'id': '6452472', 'label': 'Altenheim' },
+    { 'id': '6450568', 'label': 'Auenheim' },
+    { 'id': '6450599', 'label': 'Blaesheim' },
+    { 'id': '6455224', 'label': 'Breitenbach' },
+    { 'id': '6450617', 'label': 'Climbach' },
+    { 'id': '6454560', 'label': 'Guebwiller' },
+    { 'id': '6456346', 'label': 'La Walck' },
+    { 'id': '6437717', 'label': 'Mittelbronn' },
+    { 'id': '6441230', 'label': 'Mommenheim' },
+    { 'id': '6617418', 'label': 'Neuviller-la-Roche' },
+    { 'id': '6617422', 'label': 'Ranrupt' },
+    { 'id': '6454570', 'label': 'Wintzenheim' },
+    { 'id': '3469058', 'label': 'Bras\u00edlia' },
+    { 'id': '934765', 'label': 'Beau Bassin' },
+    { 'id': '2138089', 'label': 'Tiabet' },
+    { 'id': '2140915', 'label': 'Kaala-Gom\u00e9n' },
+    { 'id': '6438526', 'label': 'Tourcoing' },
+    { 'id': '6450029', 'label': 'Auberchicourt' },
+    { 'id': '6450030', 'label': 'Aubers' },
+    { 'id': '6438420', 'label': 'Prisches' },
+    { 'id': '6438228', 'label': 'Felleries' },
+    { 'id': '6438284', 'label': 'Haynecourt' },
+    { 'id': '6438437', 'label': 'Raucourt-au-Bois' },
+    { 'id': '6438478', 'label': 'Saint-Remy-Chauss\u00e9e' },
+    { 'id': '6438261', 'label': 'Gommegnies' },
+    { 'id': '6455198', 'label': 'Beaufort' },
+    { 'id': '6454403', 'label': 'Cousolre' },
+    { 'id': '6438258', 'label': 'Glageon' },
+    { 'id': '6450041', 'label': 'Bachy' },
+    { 'id': '6438302', 'label': 'Houdain-lez-Bavay' },
+    { 'id': '6438452', 'label': 'Roubaix' },
+    { 'id': '6438156', 'label': 'Carnin' },
+    { 'id': '6438157', 'label': 'Cartignies' },
+    { 'id': '6438307', 'label': 'Illies' },
+    { 'id': '6438445', 'label': 'Rieux-en-Cambr\u00e9sis' },
+    { 'id': '6448637', 'label': 'Azay-le-Rideau' },
+    { 'id': '6432996', 'label': 'Tilly' },
+    { 'id': '6613137', 'label': 'Montreuil' },
+    { 'id': '6455259', 'label': 'Paris' },
+    { 'id': '6618617', 'label': 'Paris 11' },
+    { 'id': '6451982', 'label': 'Suresnes' },
+    { 'id': '6618619', 'label': 'Paris 13' },
+    { 'id': '6452021', 'label': 'Ivry-sur-Seine' },
+    { 'id': '6457187', 'label': 'Le Kremlin-Bic\u00eatre' },
+    { 'id': '6618613', 'label': 'Paris 07' },
+    { 'id': '6618618', 'label': 'Paris 12' },
+    { 'id': '6455342', 'label': 'Saint-Ouen' },
+    { 'id': '6618611', 'label': 'Paris 05' },
+    { 'id': '6452003', 'label': 'Rosny-sous-Bois' },
+    { 'id': '6618626', 'label': 'Paris 20' },
+    { 'id': '6454573', 'label': 'Lyon' },
+    { 'id': '3015948', 'label': 'D\u00e9partement de la Gironde' },
+    { 'id': '6455058', 'label': 'Bordeaux' },
+    { 'id': '2987410', 'label': 'D\u00e9partement du Rh\u00f4ne' },
+    { 'id': '6453974', 'label': 'Toulouse' },
+    { 'id': '6614831', 'label': 'Redon' },
+    { 'id': '2991879', 'label': 'D\u00e9partement du Morbihan' },
+    { 'id': '6432801', 'label': 'Rennes' },
+    { 'id': '6450845', 'label': 'Autun' },
+    { 'id': '3021042', 'label': 'D\u00e9partement de la Dordogne' },
+    { 'id': '3030293', 'label': 'Bretagne' },
+    { 'id': '2949188', 'label': 'Bielefeld' },
+    { 'id': '6455341', 'label': 'Saint-Denis' },
+    { 'id': '6431257', 'label': 'Santo-Pietro-di-Tenda' },
+    { 'id': '6616409', 'label': 'Patrimonio' },
+    { 'id': '6431166', 'label': 'Loreto-di-Casinca' },
+    { 'id': '6431208', 'label': 'Pietralba' },
+    { 'id': '6453941', 'label': 'Porto-Vecchio' },
+    { 'id': '6616378', 'label': 'Sainte-Lucie-de-Tallano' },
+    { 'id': '6455273', 'label': 'Amiens' },
+    { 'id': '6450264', 'label': 'Auxi-le-Ch\u00e2teau' },
+    { 'id': '6444688', 'label': 'Querrieu' },
+    { 'id': '6613695', 'label': 'Moyenneville' },
+    { 'id': '6444395', 'label': 'Doullens' },
+    { 'id': '6444557', 'label': 'Lanch\u00e8res' },
+    { 'id': '6451266', 'label': 'Ailly-sur-Noye' },
+    { 'id': '6454159', 'label': 'Orl\u00e9ans' },
+    { 'id': '6434221', 'label': 'P\u00e9lussin' },
+    { 'id': '3380895', 'label': 'Montagne Sable' },
+    { 'id': '3380994', 'label': 'Maripasoula' },
+    { 'id': '3382160', 'label': 'Cayenne' },
+    { 'id': '10372489', 'label': 'La Charbonni\u00e8re' },
+    { 'id': '3382124', 'label': 'Charvein' },
+    { 'id': '3380743', 'label': 'Papa\u00efchton' },
+    { 'id': '3383268', 'label': 'Pikien Santi' },
+    { 'id': '935814', 'label': 'Grand \u00celet' },
+    { 'id': '935248', 'label': 'Sainte-Suzanne' },
+    { 'id': '936089', 'label': 'Bois-Blanc' },
+    { 'id': '935382', 'label': 'Plaine des Gr\u00e8gues' },
+    { 'id': '935264', 'label': 'Saint-Denis' },
+    { 'id': '935317', 'label': 'La R\u00e9union' },
+    { 'id': '935268', 'label': 'Saint-Andr\u00e9' },
+    { 'id': '935345', 'label': 'Ravine des Cabris' },
+    { 'id': '935214', 'label': 'Saint-Pierre' },
+    { 'id': '935616', 'label': 'Le Port' },
+    { 'id': '3382484', 'label': 'Bada Tabiki' },
+    { 'id': '3380387', 'label': 'Saint-Laurent-du-Maroni' },
+    { 'id': '3383740', 'label': 'Langa Tabbetje' },
+    { 'id': '3383329', 'label': 'Paramaribo' },
+    { 'id': '3384285', 'label': 'Drietabbetje' },
+    { 'id': '3381654', 'label': 'Skien Tabbetje' },
+    { 'id': '3383976', 'label': 'Kaaimanston' },
+    { 'id': '3382314', 'label': 'Bonidoro' },
+    { 'id': '8555643', 'label': 'Cergy-Pontoise' },
+    { 'id': '2138103', 'label': 'Thio' },
+    { 'id': '10793959', 'label': 'K\u00e8r\u00e8ji' },
+    { 'id': '2139981', 'label': 'Nak\u00e9ty' },
+    { 'id': '2138836', 'label': 'Petit-Borindi' },
+    { 'id': '2141124', 'label': 'Grand-Borindi' },
+    { 'id': '2137680', 'label': 'Wen\u00e9ki' },
+    { 'id': '2139521', 'label': 'Noum\u00e9a' },
+    { 'id': '2140021', 'label': 'Mouly' },
+    { 'id': '2138274', 'label': 'Takedji' },
+    { 'id': '2138408', 'label': 'Saint-Joseph' },
+    { 'id': '2139490', 'label': 'Ognat' },
+    { 'id': '2140044', 'label': 'Mou' },
+    { 'id': '4034763', 'label': 'Utufua' },
+    { 'id': '4034755', 'label': 'Vaimalau' },
+    { 'id': '4034858', 'label': 'Haafusia' },
+    { 'id': '2141656', 'label': 'Canala' },
+    { 'id': '2138980', 'label': 'Pa\u00efta' },
+    { 'id': '2139032', 'label': 'Ouv\u00e9a Island' },
+    { 'id': '4034758', 'label': 'Wallis Island' },
+    { 'id': '4034885', 'label': 'Ono' },
+    { 'id': '4034865', 'label': 'Foi' },
+    { 'id': '10858671', 'label': 'Bouzegu\u00e8ne' },
+    { 'id': '10858634', 'label': 'Ihamziyen' },
+    { 'id': '2507705', 'label': 'A\u00eft Sa\u00efd' },
+    { 'id': '10858636', 'label': 'Abourgh\u00e8s' },
+    { 'id': '10858639', 'label': 'Maraghna' },
+    { 'id': '2490523', 'label': 'Mahagga' },
+    { 'id': '2140794', 'label': 'Kavatch' },
+    { 'id': '2139028', 'label': 'Ouyaguette' },
+    { 'id': '2141939', 'label': 'Bas-Coulna' },
+    { 'id': '2138147', 'label': 'Tendo' },
+    { 'id': '2139322', 'label': 'Ouarap' },
+    { 'id': '6426657', 'label': 'Douzens' },
+    { 'id': '6452134', 'label': 'Aix-en-Provence' },
+    { 'id': '6447117', 'label': 'Ch\u00e2teauneuf-le-Rouge' },
+    { 'id': '6453767', 'label': 'Dijon' },
+    { 'id': '6434483', 'label': 'Nantes' },
+    { 'id': '2970140', 'label': 'Vend\u00e9e' },
+    { 'id': '6613992', 'label': 'Roanne' },
+    { 'id': '6446110', 'label': 'Brunoy' },
+    { 'id': '3382530', 'label': 'Awala-Yalimapo' },
+    { 'id': '2282436', 'label': 'Le Plateau' },
+    { 'id': '2595323', 'label': 'Marcory' },
+    { 'id': '2290623', 'label': 'Cocody' },
+    { 'id': '2139069', 'label': 'Oundjo' },
+    { 'id': '2137973', 'label': 'Tioua\u00e9' },
+    { 'id': '2137753', 'label': 'Vieux-Touho' },
+    { 'id': '2138039', 'label': 'Ti\u00e9' },
+    { 'id': '2138515', 'label': 'Tribu de Poyes' },
+    { 'id': '2140716', 'label': 'Kokengone' },
+    { 'id': '6430862', 'label': 'Saint-Arnoult-des-Bois' },
+    { 'id': '6430869', 'label': 'Saint-Denis-les-Ponts' },
+    { 'id': '6434590', 'label': 'Engenville' },
+    { 'id': '6449177', 'label': 'Ch\u00e2teauneuf-sur-Loire' },
+    { 'id': '6434724', 'label': 'Saint-P\u00e9ravy-la-Colombe' },
+    { 'id': '6439305', 'label': 'Saint-Victor-de-R\u00e9no' },
+    { 'id': '6448929', 'label': 'Coulanges' },
+    { 'id': '6433069', 'label': 'Neuvy-le-Roi' },
+    { 'id': '6448898', 'label': 'Blois' },
+    { 'id': '6434117', 'label': 'Saint-Lubin-en-Vergonnois' },
+    { 'id': '6439212', 'label': 'R\u00e9malard en Perche' },
+    { 'id': '6446258', 'label': 'Ennery' },
+    { 'id': '6454157', 'label': 'Gien' },
+    { 'id': '6434726', 'label': 'Saint-Sigismond' },
+    { 'id': '6457004', 'label': 'La Chapelle-Montligeon' },
+    { 'id': '6446221', 'label': 'Videlles' },
+    { 'id': '6434591', 'label': '\u00c9pieds-en-Beauce' },
+    { 'id': '6456502', 'label': 'Les Mesnuls' },
+    { 'id': '6439198', 'label': 'Origny-le-Roux' },
+    { 'id': '6447987', 'label': 'Aunay-sous-Auneau' },
+    { 'id': '6424422', 'label': 'Nottonville' },
+    { 'id': '6448343', 'label': 'Biran' },
+    { 'id': '6432117', 'label': 'Saint-Sauvy' },
+    { 'id': '6454944', 'label': 'Bethmale' },
+    { 'id': '6426310', 'label': 'Saurat' },
+    { 'id': '6426695', 'label': 'Gramazie' },
+    { 'id': '6445011', 'label': 'Mouillac' },
+    { 'id': '6426809', 'label': 'Puivert' },
+    { 'id': '6613520', 'label': 'Saint-Simon' },
+    { 'id': '6453661', 'label': 'Savignac' },
+    { 'id': '6426328', 'label': 'Surba' },
+    { 'id': '6426816', 'label': 'Ribouisse' },
+    { 'id': '6618241', 'label': 'Antras' },
+    { 'id': '6446895', 'label': 'Castillon-en-Couserans' },
+    { 'id': '6455502', 'label': 'Le Port' },
+    { 'id': '6448296', 'label': 'Boussan' },
+    { 'id': '6448308', 'label': 'Cadours' },
+    { 'id': '6431574', 'label': 'Frouzins' },
+    { 'id': '6431644', 'label': 'L\u00e9guevin' },
+    { 'id': '6448248', 'label': 'Aspet' },
+    { 'id': '6431803', 'label': 'Sainte-Foy-d\'Aigrefeuille' },
+    { 'id': '6613251', 'label': 'Saint-Martin' },
+    { 'id': '6448410', 'label': 'Beychac-et-Caillau' },
+    { 'id': '6448412', 'label': 'Biganos' },
+    { 'id': '6455056', 'label': 'Blaignac' },
+    { 'id': '6448414', 'label': 'Blasimon' },
+    { 'id': '6448441', 'label': 'Captieux' },
+    { 'id': '6432174', 'label': 'Castelnau-de-M\u00e9doc' },
+    { 'id': '6432190', 'label': 'Cissac-M\u00e9doc' },
+    { 'id': '6432246', 'label': 'Gr\u00e9zillac' },
+    { 'id': '6432251', 'label': 'Hostens' },
+    { 'id': '6454003', 'label': 'Hourtin' },
+    { 'id': '6454004', 'label': 'Lacanau' },
+    { 'id': '6432320', 'label': 'Mourens' },
+    { 'id': '6454014', 'label': 'Pessac' },
+    { 'id': '6432351', 'label': 'Pujols-sur-Ciron' },
+    { 'id': '6454016', 'label': 'Puynormand' },
+    { 'id': '6616574', 'label': 'Salles' },
+    { 'id': '6432467', 'label': 'Saucats' },
+    { 'id': '6618265', 'label': 'Saint-Andr\u00e9-de-Cubzac' },
+    { 'id': '6616565', 'label': 'Saint-C\u00f4me' },
+    { 'id': '6432409', 'label': 'Saint-Jean-d\'Illac' },
+    { 'id': '6432456', 'label': 'Saint-Symphorien' },
+    { 'id': '6432461', 'label': 'Saint-Vivien-de-M\u00e9doc' },
+    { 'id': '6432464', 'label': 'Saint-Yzans-de-M\u00e9doc' },
+    { 'id': '6452298', 'label': 'Aire-sur-l\'Adour' },
+    { 'id': '6455089', 'label': 'Biscarrosse' },
+    { 'id': '6455091', 'label': 'Castets' },
+    { 'id': '6433826', 'label': 'Geaune' },
+    { 'id': '6433832', 'label': 'Grenade-sur-l\'Adour' },
+    { 'id': '6433834', 'label': 'Hagetmau' },
+    { 'id': '6433872', 'label': 'Lubbon' },
+    { 'id': '6618275', 'label': 'L\u00fce' },
+    { 'id': '6433890', 'label': 'M\u00e9zos' },
+    { 'id': '6454123', 'label': 'Mimizan' },
+    { 'id': '6433920', 'label': 'Parentis-en-Born' },
+    { 'id': '6433921', 'label': 'Parleboscq' },
+    { 'id': '6433930', 'label': 'Pomarez' },
+    { 'id': '6433935', 'label': 'Pouillon' },
+    { 'id': '6433945', 'label': 'Sabres' },
+    { 'id': '6433979', 'label': 'Sarbazan' },
+    { 'id': '6434000', 'label': 'Soustons' },
+    { 'id': '6433965', 'label': 'Saint-Martin-de-Hinx' },
+    { 'id': '6433974', 'label': 'Saint-Sever' },
+    { 'id': '6614680', 'label': 'Saint-Vincent-de-Paul' },
+    { 'id': '6434002', 'label': 'Tarnos' },
+    { 'id': '6434003', 'label': 'Tartas' },
+    { 'id': '6434015', 'label': 'Vielle-Saint-Girons' },
+    { 'id': '6434018', 'label': 'Villeneuve-de-Marsan' },
+    { 'id': '6434020', 'label': 'Ygos-Saint-Saturnin' },
+    { 'id': '6452451', 'label': 'Aast' },
+    { 'id': '6452455', 'label': 'Agnos' },
+    { 'id': '6450366', 'label': 'Anglet' },
+    { 'id': '6450380', 'label': 'Arette' },
+    { 'id': '6450397', 'label': 'Artix' },
+    { 'id': '6440287', 'label': 'Bedous' },
+    { 'id': '6440304', 'label': 'Bielle' },
+    { 'id': '6440390', 'label': 'Garlin' },
+    { 'id': '6614172', 'label': 'Gelos' },
+    { 'id': '6440406', 'label': 'Gurs' },
+    { 'id': '6617355', 'label': 'La Bastide-Clairence' },
+    { 'id': '6440461', 'label': 'Lasseube' },
+    { 'id': '6612723', 'label': 'Lembeye' },
+    { 'id': '6440514', 'label': 'Momas' },
+    { 'id': '6454512', 'label': 'Nay' },
+    { 'id': '6612729', 'label': 'Pontacq' },
+    { 'id': '6617360', 'label': 'Sauveterre-de-B\u00e9arn' },
+    { 'id': '6440621', 'label': 'Sedz\u00e8re' },
+    { 'id': '6440582', 'label': 'Saint-Armou' },
+    { 'id': '6440545', 'label': 'Orthez' },
+    { 'id': '6440647', 'label': 'Urt' },
+    { 'id': '6452458', 'label': 'Ad\u00e9' },
+    { 'id': '6450436', 'label': 'Aragnouet' },
+    { 'id': '6617364', 'label': 'Arrens-Marsous' },
+    { 'id': '6450459', 'label': 'Aureilhan' },
+    { 'id': '6440923', 'label': 'Sers' },
+    { 'id': '6450492', 'label': 'Betpouey' },
+    { 'id': '6450475', 'label': 'Barrancoueu' },
+    { 'id': '6454518', 'label': 'Bordes' },
+    { 'id': '6440689', 'label': 'Cauterets' },
+    { 'id': '6617371', 'label': 'Ferri\u00e8res' },
+    { 'id': '6440728', 'label': 'Galan' },
+    { 'id': '6615246', 'label': 'Gard\u00e8res' },
+    { 'id': '6440733', 'label': 'Gavarnie' },
+    { 'id': '6440740', 'label': 'Gerde' },
+    { 'id': '6440741', 'label': 'Germ' },
+    { 'id': '6440775', 'label': 'Labatut-Rivi\u00e8re' },
+    { 'id': '6440776', 'label': 'Laborde' },
+    { 'id': '6440788', 'label': 'Lannemezan' },
+    { 'id': '6450469', 'label': 'Bagn\u00e8res-de-Bigorre' },
+    { 'id': '6454530', 'label': 'Lourdes' },
+    { 'id': '6613501', 'label': 'Marseillan' },
+    { 'id': '6440859', 'label': 'Ourde' },
+    { 'id': '6440883', 'label': 'Rabastens-de-Bigorre' },
+    { 'id': '6617382', 'label': 'Salles' },
+    { 'id': '6440904', 'label': 'Sariac-Magnoac' },
+    { 'id': '6614801', 'label': 'Saint-L\u00e9zer' },
+    { 'id': '6617384', 'label': 'Trie-sur-Ba\u00efse' },
+    { 'id': '6449246', 'label': 'D\u00e9gagnac' },
+    { 'id': '6431673', 'label': 'Mauressac' },
+    { 'id': '6448244', 'label': 'Arguenos' },
+    { 'id': '6433848', 'label': 'Labrit' },
+    { 'id': '6433877', 'label': 'Luxey' },
+    { 'id': '6616732', 'label': 'Mazerolles' },
+    { 'id': '6440328', 'label': 'Cabidos' },
+    { 'id': '6433904', 'label': 'Moustey' },
+    { 'id': '6446859', 'label': 'Aulus-les-Bains' },
+    { 'id': '6426181', 'label': 'Couflens' },
+    { 'id': '6456691', 'label': 'La Bastide-de-S\u00e9rou' },
+    { 'id': '6453610', 'label': 'Lescure' },
+    { 'id': '6426228', 'label': 'L\u00e9zat-sur-L\u00e8ze' },
+    { 'id': '6431781', 'label': 'Rieumes' },
+    { 'id': '6452253', 'label': 'Anan' },
+    { 'id': '6448265', 'label': 'Bagn\u00e8res-de-Luchon' },
+    { 'id': '6448294', 'label': 'Bourg-d\'Oueil' },
+    { 'id': '6431494', 'label': 'Carbonne' },
+    { 'id': '6431569', 'label': 'Franquevielle' },
+    { 'id': '6431624', 'label': 'Lagr\u00e2ce-Dieu' },
+    { 'id': '6431627', 'label': 'Lahit\u00e8re' },
+    { 'id': '6431669', 'label': 'Martres-Tolosane' },
+    { 'id': '6431678', 'label': 'Melles' },
+    { 'id': '6431691', 'label': 'Mondilhan' },
+    { 'id': '6431831', 'label': 'Saleich' },
+    { 'id': '6431826', 'label': 'Saint-Plancard' },
+    { 'id': '6431883', 'label': 'Villeneuve-de-Rivi\u00e8re' },
+    { 'id': '6613277', 'label': 'Armous-et-Cau' },
+    { 'id': '6431900', 'label': 'D\u00e9mu' },
+    { 'id': '6431903', 'label': '\u00c9auze' },
+    { 'id': '6614459', 'label': 'Faget-Abbatial' },
+    { 'id': '6431925', 'label': 'Gimont' },
+    { 'id': '6455858', 'label': 'La Romieu' },
+    { 'id': '6431943', 'label': 'Ladev\u00e8ze-Rivi\u00e8re' },
+    { 'id': '6431967', 'label': 'Lavardens' },
+    { 'id': '6431971', 'label': 'Lectoure' },
+    { 'id': '6431975', 'label': 'Lombez' },
+    { 'id': '6431993', 'label': 'Marestaing' },
+    { 'id': '6616516', 'label': 'Montaut-les-Cr\u00e9neaux' },
+    { 'id': '6432039', 'label': 'Nogaro' },
+    { 'id': '6613651', 'label': 'Plaisance' },
+    { 'id': '6432079', 'label': 'Riscle' },
+    { 'id': '6451394', 'label': 'Beaumont-de-Lomagne' },
+    { 'id': '6445032', 'label': 'Saint-Jean-du-Bouzet' },
+    { 'id': '6431904', 'label': 'Esclassan-Labastide' },
+    { 'id': '6431958', 'label': 'Larressingle' },
+    { 'id': '6452345', 'label': 'Aiguillon' },
+    { 'id': '6449324', 'label': 'Espiens' },
+    { 'id': '6434965', 'label': 'Houeill\u00e8s' },
+    { 'id': '6434967', 'label': 'Labastide-Castel-Amouroux' },
+    { 'id': '6434972', 'label': 'Lafitte-sur-Lot' },
+    { 'id': '6434985', 'label': 'Layrac' },
+    { 'id': '6454182', 'label': 'M\u00e9zin' },
+    { 'id': '6453654', 'label': 'Najac' },
+    { 'id': '6426959', 'label': 'Mayran' },
+    { 'id': '6427018', 'label': 'Saint-F\u00e9lix-de-Lunel' },
+    { 'id': '6429427', 'label': 'Marnac' },
+    { 'id': '6426277', 'label': 'Prayols' },
+    { 'id': '6618205', 'label': 'Qu\u00e9rigut' },
+    { 'id': '6453612', 'label': 'Loubens' },
+    { 'id': '6618238', 'label': 'La Bastide-de-Lordat' },
+    { 'id': '6615269', 'label': 'M\u00e9rens-les-Vals' },
+    { 'id': '6426302', 'label': 'Saint-Martin-d\'Oydes' },
+    { 'id': '6446897', 'label': 'Caychax' },
+    { 'id': '6426188', 'label': 'Dun' },
+    { 'id': '6426260', 'label': 'Monts\u00e9gur' },
+    { 'id': '6426874', 'label': 'Sonnac-sur-l\'Hers' },
+    { 'id': '6426753', 'label': 'Molleville' },
+    { 'id': '6426853', 'label': 'Saint-Martin-Lalande' },
+    { 'id': '6427053', 'label': 'Sauveterre-de-Rouergue' },
+    { 'id': '6427069', 'label': 'Vabre-Tizac' },
+    { 'id': '6427054', 'label': 'S\u00e9bazac-Concour\u00e8s' },
+    { 'id': '6615868', 'label': 'Lanu\u00e9jouls' },
+    { 'id': '6447048', 'label': 'Auzits' },
+    { 'id': '6426961', 'label': 'Meljac' },
+    { 'id': '6426323', 'label': 'Siguer' },
+    { 'id': '6449329', 'label': 'Fauillet' },
+    { 'id': '6613032', 'label': 'Baleyssagues' },
+    { 'id': '6449272', 'label': 'Blanquefort-sur-Briolance' },
+    { 'id': '6449289', 'label': 'Cancon' },
+    { 'id': '6449320', 'label': 'Douzains' },
+    { 'id': '6435103', 'label': 'Tayrac' },
+    { 'id': '6435094', 'label': 'Savignac-sur-Leyze' },
+    { 'id': '6434978', 'label': 'Laparade' },
+    { 'id': '6449306', 'label': 'Clermont-Dessous' },
+    { 'id': '6434949', 'label': 'Foulayronnes' },
+    { 'id': '6435014', 'label': 'Montayral' },
+    { 'id': '6434968', 'label': 'Labretonie' },
+    { 'id': '6434990', 'label': 'Loub\u00e8s-Bernac' },
+    { 'id': '6614627', 'label': 'Cambes' },
+    { 'id': '6451339', 'label': 'Appelle' },
+    { 'id': '6444908', 'label': 'Pampelonne' },
+    { 'id': '6444897', 'label': 'Moulayr\u00e8s' },
+    { 'id': '6451386', 'label': 'Fauch' },
+    { 'id': '6451358', 'label': 'Cadalen' },
+    { 'id': '6617774', 'label': 'Brassac' },
+    { 'id': '6454787', 'label': 'Rabastens' },
+    { 'id': '6455388', 'label': 'Gaillac' },
+    { 'id': '6614427', 'label': 'Cordes-sur-Ciel' },
+    { 'id': '6454788', 'label': 'Rouairoux' },
+    { 'id': '6444930', 'label': 'Roussayrolles' },
+    { 'id': '6444832', 'label': 'Gijounet' },
+    { 'id': '6444946', 'label': 'Saint-Julien-Gaul\u00e8ne' },
+    { 'id': '6444902', 'label': 'Murat-sur-V\u00e8bre' },
+    { 'id': '6451340', 'label': 'Arfons' },
+    { 'id': '6444919', 'label': 'Puycelsi' },
+    { 'id': '6451367', 'label': 'Castelnau-de-L\u00e9vis' },
+    { 'id': '6452543', 'label': 'Aiguefonde' },
+    { 'id': '6452347', 'label': 'Allez-et-Cazeneuve' },
+    { 'id': '6449269', 'label': 'Beaupuy' },
+    { 'id': '6690693', 'label': 'Macouria' },
+    { 'id': '6615750', 'label': 'Albon-d\'Ard\u00e8che' },
+    { 'id': '6429307', 'label': 'Saint-Priest-la-Feuille' },
+    { 'id': '6455001', 'label': 'Gartempe' },
+    { 'id': '6444933', 'label': 'Saint-Amans-Valtoret' },
+    { 'id': '1090242', 'label': 'Mtsap\u00e9r\u00e9' },
+    { 'id': '6434674', 'label': 'Olivet' },
+    { 'id': '6434601', 'label': 'Fleury-les-Aubrais' },
+    { 'id': '6434619', 'label': 'Ingr\u00e9' },
+    { 'id': '6434714', 'label': 'Saint-Jean-de-Braye' },
+    { 'id': '6456924', 'label': 'La Chapelle-Saint-Mesmin' },
+    { 'id': '6434715', 'label': 'Saint-Jean-de-la-Ruelle' },
+    { 'id': '6434628', 'label': 'Lailly-en-Val' },
+    { 'id': '6434729', 'label': 'Saran' },
+    { 'id': '6454160', 'label': 'Ormes' },
+    { 'id': '6618260', 'label': 'Ouessant' },
+    { 'id': '6616347', 'label': '\u00cele-Mol\u00e8ne' },
+    { 'id': '6453931', 'label': 'Plouarzel' },
+    { 'id': '6431001', 'label': 'Plougonvelin' },
+    { 'id': '6448082', 'label': 'Guilers' },
+    { 'id': '6430954', 'label': 'Lanrivoar\u00e9' },
+    { 'id': '6453932', 'label': 'Ploudalm\u00e9zeau' },
+    { 'id': '6616357', 'label': 'Saint-Pabu' },
+    { 'id': '6430940', 'label': 'Land\u00e9da' },
+    { 'id': '6448043', 'label': 'Bourg-Blanc' },
+    { 'id': '6448074', 'label': 'Gouesnou' },
+    { 'id': '6448086', 'label': 'Guipavas' },
+    { 'id': '6448098', 'label': 'Kernilis' },
+    { 'id': '6431011', 'label': 'Ploun\u00e9our-Trez' },
+    { 'id': '6430992', 'label': 'Ploudaniel' },
+    { 'id': '6430993', 'label': 'Plou\u00e9dern' },
+    { 'id': '6431014', 'label': 'Ploun\u00e9vez-Lochrist' },
+    { 'id': '6448038', 'label': 'Bodilis' },
+    { 'id': '6455834', 'label': 'La Martyre' },
+    { 'id': '6448061', 'label': 'Collorec' },
+    { 'id': '6455838', 'label': 'Le Tr\u00e9hou' },
+    { 'id': '6453937', 'label': 'Sizun' },
+    { 'id': '6430960', 'label': 'Locm\u00e9lar' },
+    { 'id': '6455034', 'label': 'Guimiliau' },
+    { 'id': '6448081', 'label': 'Guiclan' },
+    { 'id': '6431016', 'label': 'Plouvorn' },
+    { 'id': '6431063', 'label': 'Sibiril' },
+    { 'id': '6616345', 'label': '\u00cele-de-Batz' },
+    { 'id': '6431037', 'label': 'Roscoff' },
+    { 'id': '6448051', 'label': 'Carantec' },
+    { 'id': '6431054', 'label': 'Sainte-S\u00e8ve' },
+    { 'id': '6431010', 'label': 'Ploun\u00e9our-M\u00e9nez' },
+    { 'id': '6431002', 'label': 'Plougonven' },
+    { 'id': '6431008', 'label': 'Plouigneau' },
+    { 'id': '6616353', 'label': 'Plouezoc\'h' },
+    { 'id': '6430981', 'label': 'Plo\u00e9ven' },
+    { 'id': '6614387', 'label': 'Loguivy-Plougras' },
+    { 'id': '6448080', 'label': 'Guerlesquin' },
+    { 'id': '6430999', 'label': 'Plougasnou' },
+    { 'id': '6430994', 'label': 'Plou\u00e9gat-Gu\u00e9rand' },
+    { 'id': '6612341', 'label': 'Plourac\'h' },
+    { 'id': '6429073', 'label': 'Plougonver' },
+    { 'id': '6612331', 'label': 'Lanvellec' },
+    { 'id': '6615125', 'label': 'Tr\u00e9drez-Locqu\u00e9meau' },
+    { 'id': '6429057', 'label': 'Pleumeur-Bodou' },
+    { 'id': '6430962', 'label': 'Locquirec' },
+    { 'id': '6429011', 'label': 'Louannec' },
+    { 'id': '6453798', 'label': 'Lannion' },
+    { 'id': '6453813', 'label': 'Le Vieux-March\u00e9' },
+    { 'id': '6429180', 'label': 'Tr\u00e9grom' },
+    { 'id': '6429177', 'label': 'Tr\u00e9glamus' },
+    { 'id': '6429080', 'label': 'Ploumagoar' },
+    { 'id': '6429163', 'label': 'Squiffiec' },
+    { 'id': '6429123', 'label': 'Saint-Clet' },
+    { 'id': '6453803', 'label': 'Prat' },
+    { 'id': '6429062', 'label': 'Plo\u00ebzal' },
+    { 'id': '6447629', 'label': 'Bourbriac' },
+    { 'id': '6447637', 'label': 'Camlez' },
+    { 'id': '6429074', 'label': 'Plougrescant' },
+    { 'id': '6429055', 'label': 'Pleubian' },
+    { 'id': '6429068', 'label': 'Ploubazlanec' },
+    { 'id': '6429084', 'label': 'Plourivo' },
+    { 'id': '6428993', 'label': 'Lanloup' },
+    { 'id': '6429040', 'label': 'Pl\u00e9guien' },
+    { 'id': '6447659', 'label': 'Goudelin' },
+    { 'id': '6428998', 'label': 'Lanrodec' },
+    { 'id': '6614006', 'label': 'Saint-Fiacre' },
+    { 'id': '6429132', 'label': 'Saint-Gilles-Pligeaux' },
+    { 'id': '6429095', 'label': 'Plussulien' },
+    { 'id': '6612977', 'label': 'Caurel' },
+    { 'id': '6437321', 'label': 'Neulliac' },
+    { 'id': '6428991', 'label': 'Laniscat' },
+    { 'id': '6429151', 'label': 'Saint-Nicolas-du-P\u00e9lem' },
+    { 'id': '6613786', 'label': 'Ploun\u00e9vez-Quintin' },
+    { 'id': '6429110', 'label': 'Rostrenen' },
+    { 'id': '6447675', 'label': 'Kergrist-Mo\u00eblou' },
+    { 'id': '6429014', 'label': 'Ma\u00ebl-Pestivien' },
+    { 'id': '6616125', 'label': 'Saint-Servais' },
+    { 'id': '6429007', 'label': 'Locarn' },
+    { 'id': '6429028', 'label': 'Paule' },
+    { 'id': '6455356', 'label': 'Berrien' },
+    { 'id': '6431029', 'label': 'Poullaouen' },
+    { 'id': '6430941', 'label': 'Landeleau' },
+    { 'id': '6431013', 'label': 'Ploun\u00e9v\u00e9zel' },
+    { 'id': '6612444', 'label': 'Motreff' },
+    { 'id': '6454335', 'label': 'Langonnet' },
+    { 'id': '6612647', 'label': 'Roudouallec' },
+    { 'id': '6448056', 'label': 'Cl\u00e9den-Poher' },
+    { 'id': '6430951', 'label': 'Lann\u00e9dern' },
+    { 'id': '6448041', 'label': 'Botmeur' },
+    { 'id': '6431052', 'label': 'Saint-Rivoal' },
+    { 'id': '6453930', 'label': 'Pleyben' },
+    { 'id': '6430957', 'label': 'Lennon' },
+    { 'id': '6431074', 'label': 'Tr\u00e9gourez' },
+    { 'id': '6448048', 'label': 'Briec' },
+    { 'id': '6616351', 'label': 'Lothey' },
+    { 'id': '6452232', 'label': 'B\u00e9nodet' },
+    { 'id': '6455033', 'label': 'Fouesnant' },
+    { 'id': '6431076', 'label': 'Tr\u00e9gunc' },
+    { 'id': '6448069', 'label': 'Elliant' },
+    { 'id': '6430944', 'label': 'Landudal' },
+    { 'id': '6431039', 'label': 'Rosporden' },
+    { 'id': '6453927', 'label': 'Nevez' },
+    { 'id': '6448064', 'label': 'Concarneau' },
+    { 'id': '6431022', 'label': 'Pont-Aven' },
+    { 'id': '6614190', 'label': 'Riec-sur-B\u00e9lon' },
+    { 'id': '6431061', 'label': 'Sca\u00ebr' },
+    { 'id': '6431057', 'label': 'Saint-Thurien' },
+    { 'id': '6453938', 'label': 'Tr\u00e9m\u00e9ven' },
+    { 'id': '6448058', 'label': 'Clohars-Carno\u00ebt' },
+    { 'id': '6447142', 'label': 'Marseille' },
+    { 'id': '6452137', 'label': 'Aubagne' },
+    { 'id': '6612800', 'label': 'Villeparisis' },
+    { 'id': '6451977', 'label': 'Neuilly-sur-Seine' },
+    { 'id': '6427502', 'label': 'Saon' },
+    { 'id': '6455546', 'label': 'Le Breuil-en-Bessin' },
+    { 'id': '6427527', 'label': 'Tourni\u00e8res' }
+];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/mirage/models/geonames.js	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,4 @@
+import { Model } from 'ember-cli-mirage';
+
+export default Model.extend({
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/corpus-common-addon/.eslintrc.json	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,11 @@
+{
+    "extends": "standard",
+    "plugins": [
+        "standard",
+        "promise"
+    ],
+    "rules": {
+        "semi": [2, "always"],
+        "space-before-function-paren": ["error", "never"]
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/corpus-common-addon/addon/components/doc-location.js	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,29 @@
+import Ember from 'ember';
+import * as constants from 'corpus-common-addon/utils/constants';
+import layout from '../templates/components/doc-location';
+
+export default Ember.Component.extend({
+  layout: layout,
+  tagName: 'span',
+
+  geonamesResolver: Ember.inject.service(),
+
+  _resolveGeonamesIds: Ember.on('init', Ember.observer('url', function() {
+    this.get('geonamesResolver').getLabel(this.get('url')).then(function(str) {
+      this.set('resolvedLabel', str);
+    }.bind(this));
+  })),
+
+  code: Ember.computed('url', function() {
+    var rawLocation = this.get('url');
+    var m = rawLocation.match(constants.GEONAMES_BASE_URLS);
+
+    if (m) {
+      rawLocation = rawLocation.slice(m[0].length);
+    }
+
+    return rawLocation.replace(/\/+$/, '');
+  }),
+  isLocationLink: Ember.computed.match('url', /^http:\/\//)
+
+});
--- a/common/corpus-common-addon/addon/helpers/get-link-type.js	Tue Sep 27 01:50:53 2016 +0200
+++ b/common/corpus-common-addon/addon/helpers/get-link-type.js	Tue Sep 27 23:43:29 2016 +0200
@@ -1,18 +1,21 @@
 import Ember from 'ember';
-import * as utils from 'corpus-common-addon/utils/utils'
+import * as utils from 'corpus-common-addon/utils/utils';
 
-export function getLinkType(params/*, hash*/) {
+export function getLinkType(params /*, hash */) {
   let url = params[0];
 
-  if(!url) {
+  if (!url) {
     return 'doc-literal';
   }
-  if(utils.isLexvoLink(url)) {
+  if (utils.isLexvoLink(url)) {
     return 'doc-language';
   }
-  if(utils.isBnfLink(url)) {
+  if (utils.isBnfLink(url)) {
     return 'doc-subject';
   }
+  if (utils.isGeonamesLink(url)) {
+    return 'doc-location';
+  }
   return 'doc-literal';
 }
 
--- a/common/corpus-common-addon/addon/templates/components/doc-language.hbs	Tue Sep 27 01:50:53 2016 +0200
+++ b/common/corpus-common-addon/addon/templates/components/doc-language.hbs	Tue Sep 27 23:43:29 2016 +0200
@@ -1,5 +1,5 @@
 {{#if isLanguageLink}}
-<a href="{{url}}" target="_blank" title={{resolvedName}} class="bo-doc-ref-link doc-link-lexvo">
+<a href="{{url}}" target="_blank" title={{url}} class="bo-doc-ref-link doc-link-lexvo">
   {{#if resolvedName}}{{resolvedName}}{{else}}{{code}}{{/if}}
 </a>
 {{else}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/corpus-common-addon/addon/templates/components/doc-location.hbs	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,7 @@
+{{#if isLocationLink}}
+<a href="{{url}}" target="_blank" title="{{url}}" class="bo-doc-ref-link doc-link-geonames">
+  {{#if resolvedLabel}}{{resolvedLabel}}{{else}}{{code}}{{/if}}
+</a>
+{{else}}
+{{#if resolvedLabel}}{{resolvedLabel}}{{else}}{{code}}{{/if}}
+{{/if}}
--- a/common/corpus-common-addon/addon/templates/components/doc-subject.hbs	Tue Sep 27 01:50:53 2016 +0200
+++ b/common/corpus-common-addon/addon/templates/components/doc-subject.hbs	Tue Sep 27 23:43:29 2016 +0200
@@ -1,5 +1,5 @@
 {{#if isSubjectLink}}
-<a href="{{url}}" target="_blank" title={{resolvedLabel}} class="bo-doc-ref-link doc-link-bnf">
+<a href="{{url}}" target="_blank" title={{url}} class="bo-doc-ref-link doc-link-bnf">
   {{#if resolvedLabel}}{{resolvedLabel}}{{else}}{{code}}{{/if}}
 </a>
 {{else}}
--- a/common/corpus-common-addon/addon/utils/constants.js	Tue Sep 27 01:50:53 2016 +0200
+++ b/common/corpus-common-addon/addon/utils/constants.js	Tue Sep 27 23:43:29 2016 +0200
@@ -1,4 +1,3 @@
-
 
 export const LEXVO_BASE_URL = 'http://lexvo.org/id/iso639-3/';
 
@@ -9,38 +8,40 @@
 export const BNF_ARK_BASE_URL = 'http://ark.bnf.fr/';
 export const BNF_ARK_BASE_ID = 'ark:/12148/';
 
+export const GEONAMES_BASE_URLS = 'https?:\\/\\/(?:www|sws)\\.geonames\\.org/';
+
 export const CORPUS_DISCOURSE_TYPES = {
-    'http://ark.bnf.fr/ark:/12148/cb12083158d' : 'argumentation',
-    'http://ark.bnf.fr/ark:/12148/cb119783362' : 'Bavardage',
-    'http://ark.bnf.fr/ark:/12148/cb13319048g' : 'chansons',
-    'http://ark.bnf.fr/ark:/12148/cb11931724n' : 'congrès et conférences',
-    'http://ark.bnf.fr/ark:/12148/cb11936159v' : 'contes',
-    'http://ark.bnf.fr/ark:/12148/cb119317924' : 'conversation',
-    'http://ark.bnf.fr/ark:/12148/cb12481481z' : 'dialogue',
-    'http://ark.bnf.fr/ark:/12148/cb11948542x' : 'discours',
-    'http://ark.bnf.fr/ark:/12148/cb119341539' : 'discussion',
-    'http://ark.bnf.fr/ark:/12148/cb120502737' : 'enquêtes linguistiques',
-    'http://ark.bnf.fr/ark:/12148/cb11932135w' : 'entretiens',
-    'http://ark.bnf.fr/ark:/12148/cb11953414d' : 'fables',
-    'http://ark.bnf.fr/ark:/12148/cb11955657q' : 'lecture à haute voix',
-    'http://ark.bnf.fr/ark:/12148/cb11957378b' : 'musique instrumentale',
-    'http://ark.bnf.fr/ark:/12148/cb11937212q' : 'narration',
-    'http://ark.bnf.fr/ark:/12148/cb11946100d' : 'paradigme (épistémologie)',
-    'http://ark.bnf.fr/ark:/12148/cb119829234' : 'questionnaires',
-    'http://ark.bnf.fr/ark:/12148/cb119834877' : 'récitation',
-    'http://ark.bnf.fr/ark:/12148/cb11976851v' : 'récits personnels',
-    'http://ark.bnf.fr/ark:/12148/cb11949715t' : 'réunions'
+  'http://ark.bnf.fr/ark:/12148/cb12083158d': 'argumentation',
+  'http://ark.bnf.fr/ark:/12148/cb119783362': 'Bavardage',
+  'http://ark.bnf.fr/ark:/12148/cb13319048g': 'chansons',
+  'http://ark.bnf.fr/ark:/12148/cb11931724n': 'congrès et conférences',
+  'http://ark.bnf.fr/ark:/12148/cb11936159v': 'contes',
+  'http://ark.bnf.fr/ark:/12148/cb119317924': 'conversation',
+  'http://ark.bnf.fr/ark:/12148/cb12481481z': 'dialogue',
+  'http://ark.bnf.fr/ark:/12148/cb11948542x': 'discours',
+  'http://ark.bnf.fr/ark:/12148/cb119341539': 'discussion',
+  'http://ark.bnf.fr/ark:/12148/cb120502737': 'enquêtes linguistiques',
+  'http://ark.bnf.fr/ark:/12148/cb11932135w': 'entretiens',
+  'http://ark.bnf.fr/ark:/12148/cb11953414d': 'fables',
+  'http://ark.bnf.fr/ark:/12148/cb11955657q': 'lecture à haute voix',
+  'http://ark.bnf.fr/ark:/12148/cb11957378b': 'musique instrumentale',
+  'http://ark.bnf.fr/ark:/12148/cb11937212q': 'narration',
+  'http://ark.bnf.fr/ark:/12148/cb11946100d': 'paradigme (épistémologie)',
+  'http://ark.bnf.fr/ark:/12148/cb119829234': 'questionnaires',
+  'http://ark.bnf.fr/ark:/12148/cb119834877': 'récitation',
+  'http://ark.bnf.fr/ark:/12148/cb11976851v': 'récits personnels',
+  'http://ark.bnf.fr/ark:/12148/cb11949715t': 'réunions'
 };
 
 export const DEFAULT_STORE_EXP = 3600000;
 
 export const NOID_CHARS = [
-    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-    'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'm', 'n',
-    'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z'
+  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+  'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'm', 'n',
+  'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z'
 ];
 export const NOID_CHARS_POS = {
-    '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
-    'b': 10, 'c': 11, 'd': 12, 'f': 13, 'g': 14, 'h': 15, 'j': 16, 'k': 17, 'm': 18, 'n': 19,
-    'p': 20, 'q': 21, 'r': 22, 's': 23, 't': 24, 'v': 25, 'w': 26, 'x': 27, 'z': 28
+  '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
+  'b': 10, 'c': 11, 'd': 12, 'f': 13, 'g': 14, 'h': 15, 'j': 16, 'k': 17, 'm': 18, 'n': 19,
+  'p': 20, 'q': 21, 'r': 22, 's': 23, 't': 24, 'v': 25, 'w': 26, 'x': 27, 'z': 28
 };
--- a/common/corpus-common-addon/addon/utils/utils.js	Tue Sep 27 01:50:53 2016 +0200
+++ b/common/corpus-common-addon/addon/utils/utils.js	Tue Sep 27 23:43:29 2016 +0200
@@ -1,5 +1,5 @@
 import * as constants from 'corpus-common-addon/utils/constants';
-import _ from "lodash/lodash";
+import _ from 'lodash/lodash';
 
 export function isLexvoLink(s) {
   return s && typeof s === 'string' && s.startsWith(constants.LEXVO_BASE_URL);
@@ -10,16 +10,20 @@
 };
 
 export function isArkBnfLink(s) {
-  return s && typeof s === 'string' && (s.startsWith(constants.BNF_BASE_URL+constants.BNF_ARK_BASE_ID) || s.startsWith(constants.BNF_ARK_BASE_URL+constants.BNF_ARK_BASE_ID));
+  return s && typeof s === 'string' && (s.startsWith(constants.BNF_BASE_URL + constants.BNF_ARK_BASE_ID) || s.startsWith(constants.BNF_ARK_BASE_URL + constants.BNF_ARK_BASE_ID));
 };
 
+export function isGeonamesLink(s) {
+  return (typeof s === 'string') && (s.match(constants.GEONAMES_BASE_URLS) !== null);
+}
+
 export function switchArkBnfLink(s) {
-  if(!s) {
+  if (!s) {
     return s;
   }
-  if(typeof s === 'string' && s.startsWith(constants.BNF_BASE_URL+constants.BNF_ARK_BASE_ID)) {
+  if (typeof s === 'string' && s.startsWith(constants.BNF_BASE_URL + constants.BNF_ARK_BASE_ID)) {
     return constants.BNF_ARK_BASE_URL + s.slice(constants.BNF_BASE_URL.length);
-  } else if (typeof s === 'string' && s.startsWith(constants.BNF_ARK_BASE_URL+constants.BNF_ARK_BASE_ID)) {
+  } else if (typeof s === 'string' && s.startsWith(constants.BNF_ARK_BASE_URL + constants.BNF_ARK_BASE_ID)) {
     return constants.BNF_BASE_URL + s.slice(constants.BNF_ARK_BASE_URL.length);
   } else {
     return s;
@@ -27,11 +31,11 @@
 };
 
 export function calculateBnfArkControlChar(id) {
-  if(!id) {
+  if (!id) {
     return null;
   }
   var sum = _.reduce(id, function(s, c, i) {
-    return s + (i+1) * (c in constants.NOID_CHARS_POS ? constants.NOID_CHARS_POS[c] : 0);
+    return s + (i + 1) * (c in constants.NOID_CHARS_POS ? constants.NOID_CHARS_POS[c] : 0);
   }, 0);
   return constants.NOID_CHARS[sum % constants.NOID_CHARS.length];
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/corpus-common-addon/app/components/doc-location.js	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,1 @@
+export { default } from 'corpus-common-addon/components/doc-location';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/corpus-common-addon/app/services/geonames-resolver.js	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,28 @@
+import * as constants from 'corpus-common-addon/utils/constants';
+
+import ResolverService from 'corpus-common-addon/services/resolver-service';
+
+export default ResolverService.extend({
+
+  storeKeyBase: 'geonames',
+  apiPath: '/api/v1/geonames/',
+  resDocRoot: 'geonamesids',
+
+  init() {
+    this._super(...arguments);
+  },
+
+  processId: function(id) {
+    var geonamesId = id;
+    var m = id.match(constants.GEONAMES_BASE_URLS);
+    if (m) {
+      geonamesId = id.slice(m[0].length);
+    }
+    return geonamesId.replace(/\/+$/, '');
+  },
+
+  getReturnDictKey: function(id) { return id; },
+
+  getLabel: function(id) { return this.getName(id); }
+
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/corpus-common-addon/jsconfig.json	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,16 @@
+{
+	// See https://go.microsoft.com/fwlink/?LinkId=759670
+	// for the documentation about the jsconfig.json format
+	"compilerOptions": {
+		"target": "es6",
+		"module": "commonjs",
+		"allowSyntheticDefaultImports": true
+	},
+	"exclude": [
+		"node_modules",
+		"bower_components",
+		"jspm_packages",
+		"tmp",
+		"temp"
+	]
+}
--- a/common/corpus-common-addon/package.json	Tue Sep 27 01:50:53 2016 +0200
+++ b/common/corpus-common-addon/package.json	Tue Sep 27 23:43:29 2016 +0200
@@ -37,6 +37,10 @@
     "ember-load-initializers": "^0.5.0",
     "ember-resolver": "^2.0.3",
     "ember-try": "^0.1.2",
+    "eslint": "^3.5.0",
+    "eslint-config-standard": "^6.0.1",
+    "eslint-plugin-promise": "^2.0.1",
+    "eslint-plugin-standard": "^2.0.0",
     "loader.js": "^4.0.0",
     "lodash": "^4.5.1",
     "q": "^1.4.1",
--- a/server/bo_client/app/adapters/application.js	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/bo_client/app/adapters/application.js	Tue Sep 27 23:43:29 2016 +0200
@@ -2,7 +2,7 @@
 import ENV from 'bo-client/config/environment';
 
 export default RESTAdapter.extend({
-  namespace: ENV.rootURL.replace(/\/$/,"")+'/api/v1',
-  //TODO: pass this as configuration
-  //host: 'http://localhost:8000'
+    namespace: ENV.rootURL.replace(/\/$/,'')+'/api/v1'
+    //TODO: pass this as configuration
+    //host: 'http://localhost:8000'
 });
--- a/server/bo_client/app/locales/en/translations.js	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/bo_client/app/locales/en/translations.js	Tue Sep 27 23:43:29 2016 +0200
@@ -6,9 +6,11 @@
     "document_list": "Document List",
     "document_list.id_col": "ID",
     "document_list.uri_col": "URI",
+
     "home": "home",
     "document_detail": "Document detail",
     "audio_support_error" : "Your browser does not support the audio tag",
+
     "document_audio": "Audio:",
     "document_content": "Content",
     "document_title": "Title:",
@@ -16,13 +18,17 @@
     "document_editors": "Editor(s):",
     "document_contributors": "Contributor(s):",
     "document_subjects": "Subject(s):",
+    "document_locations": "Recording location(s):",
+
     "contributors_th_name": "Name",
     "contributors_th_url": "URL",
     "contributors_th_role": "Role",
     "contributors_th_actions": "Actions",
+
     "subjects_th_label": "Label",
     "subjects_th_url": "URL",
     "subjects_th_actions": "Actions",
+
     "olac_role_annotator": "annotator",
     "olac_role_author": "author",
     "olac_role_compiler": "compiler",
--- a/server/bo_client/app/locales/fr/translations.js	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/bo_client/app/locales/fr/translations.js	Tue Sep 27 23:43:29 2016 +0200
@@ -7,7 +7,9 @@
     "document_list.id_col": "ID",
     "document_list.uri_col": "URI",
     "document_detail": "Détail document",
+
     "audio_support_error" : "Votre browser ne gère pas la balise audio.",
+
     "document_audio": "Audio :",
     "document_content": "Contenu",
     "document_title": "Titre :",
@@ -15,13 +17,17 @@
     "document_editors": "Editeur(s) :",
     "document_contributors": "Contributeur(s) :",
     "document_subjects": "Sujet(s) :",
+    "document_locations": "Lieu(x) d'enregistrement :",
+
     "contributors_th_name": "Nom",
     "contributors_th_url": "URL",
     "contributors_th_role": "Role",
     "contributors_th_actions": "Actions",
+
     "subjects_th_label": "Label",
     "subjects_th_url": "URL",
     "subjects_th_actions": "Actions",
+
     "olac_role_annotator": "annotateur",
     "olac_role_author": "auteur",
     "olac_role_compiler": "compilateur",
--- a/server/bo_client/app/models/document.js	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/bo_client/app/models/document.js	Tue Sep 27 23:43:29 2016 +0200
@@ -17,7 +17,7 @@
 
     subjects: DS.attr({defaultValue: function() { return []; }}),
 
-    reflocs: DS.attr({defaultValue: function() { return []; }}),
+    geoInfo: DS.attr({defaultValue: function() { return []; }}),
 
     mediaArray: DS.attr({defaultValue: function() { return []; }}),
 
@@ -41,6 +41,10 @@
         return res;
     }),
 
+    reflocs: Ember.computed('geoInfo', function() {
+        return this.get('geoInfo')['ref-locs'];
+    }),
+
     addContributor: function(contrib_def) {
         var contributors = this.get('contributors');
         if(_.findIndex(contributors, function(c) { return _.isEqual(c, contrib_def);}) < 0) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-locations/component.js	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-locations/template.hbs	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,11 @@
+<div class="col-md-1">
+    {{ fa-icon "pencil" class='bo-doc-edit-icons' }}
+</div>
+<div class="col-md-11">
+    <div class="row">
+	    <div class="col-md-12 content-title">{{t 'bo.document_locations'}}</div>
+    </div>
+    <div class="row" id="doc-locations-list-pane">
+        <div class="col-md-12 content-value">{{#each document.reflocs as |location index|}}{{if index ", "}}{{component (get-link-type location) url=location}}{{/each}}</div>
+    </div>
+</div>
--- a/server/bo_client/app/templates/doc.hbs	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/bo_client/app/templates/doc.hbs	Tue Sep 27 23:43:29 2016 +0200
@@ -40,6 +40,9 @@
               <div class="row">
                 {{bo-doc-subjects document=model}}
               </div>
+              <div class="row">
+                {{bo-doc-locations document=model}}
+              </div>
           </div>
           <div class="col-md-4">
             <div class="data">
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/jsconfig.json	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,16 @@
+{
+	// See https://go.microsoft.com/fwlink/?LinkId=759670
+	// for the documentation about the jsconfig.json format
+	"compilerOptions": {
+		"target": "es6",
+		"module": "commonjs",
+		"allowSyntheticDefaultImports": true
+	},
+	"exclude": [
+		"node_modules",
+		"bower_components",
+		"jspm_packages",
+		"tmp",
+		"temp"
+	]
+}
--- a/server/bo_client/package.json	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/bo_client/package.json	Tue Sep 27 23:43:29 2016 +0200
@@ -28,7 +28,7 @@
     "corpus-common-addon": "file:../../common/corpus-common-addon",
     "ember-ajax": "^2.0.1",
     "ember-aupac-typeahead": "IRI-Research/ember-aupac-typeahead#ember_2.8",
-    "ember-cli": "2.8.0-beta.2",
+    "ember-cli": "^2.8.0",
     "ember-cli-app-version": "^1.0.0",
     "ember-cli-babel": "^5.1.6",
     "ember-cli-dependency-checker": "^1.2.0",
@@ -52,7 +52,7 @@
     "ember-resolver": "^2.0.3",
     "ember-truth-helpers": "1.2.0",
     "ember-welcome-page": "^1.0.3",
-    "eslint": "^3.2.2",
+    "eslint": "^3.5.0",
     "eslint-config-google": "^0.6.0",
     "express": "^4.14.0",
     "glob": "^7.0.3",
@@ -61,7 +61,6 @@
     "lodash": "^4.7.0",
     "morgan": "^1.7.0",
     "npm-check-updates": "^2.6.1",
-    "walk-sync": "^0.3.1",
-    "loader.js": "^4.0.1"
+    "walk-sync": "^0.3.1"
   }
 }
--- a/server/bo_client/server/fixtures/documents.js	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/bo_client/server/fixtures/documents.js	Tue Sep 27 23:43:29 2016 +0200
@@ -118,7 +118,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "42.7925",
+      "longitude": "1.71889"
     }
   },
   {
@@ -240,7 +242,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "43.02722",
+      "longitude": "1.79917"
     }
   },
   {
@@ -362,7 +366,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "43.1442",
+      "longitude": "1.7135"
     }
   },
   {
@@ -484,7 +490,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "43.0452",
+      "longitude": "1.5461"
     }
   },
   {
@@ -606,7 +614,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "42.65806",
+      "longitude": "1.83611"
     }
   },
   {
@@ -728,7 +738,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "42.87139",
+      "longitude": "1.83333"
     }
   },
   {
@@ -840,7 +852,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "42.92722",
+      "longitude": "1.62361"
     }
   },
   {
@@ -962,7 +976,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "42.6987",
+      "longitude": "2.0996"
     }
   },
   {
@@ -1084,7 +1100,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "42.76472",
+      "longitude": "1.56556"
     }
   },
   {
@@ -1206,7 +1224,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "43.17028",
+      "longitude": "1.49611"
     }
   },
   {
@@ -1328,7 +1348,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "42.85889",
+      "longitude": "1.575"
     }
   },
   {
@@ -1450,7 +1472,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "43.13917",
+      "longitude": "2.09694"
     }
   },
   {
@@ -1572,7 +1596,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "43.31222",
+      "longitude": "1.83417"
     }
   },
   {
@@ -1694,7 +1720,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "42.921",
+      "longitude": "2.0474"
     }
   },
   {
@@ -1816,7 +1844,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "43.1825",
+      "longitude": "1.8975"
     }
   },
   {
@@ -1933,7 +1963,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "43.00389",
+      "longitude": "1.99306"
     }
   },
   {
@@ -2055,7 +2087,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "43.29944",
+      "longitude": "2.01944"
     }
   },
   {
@@ -2177,7 +2211,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.50694",
+      "longitude": "2.32778"
     }
   },
   {
@@ -2299,7 +2335,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.22056",
+      "longitude": "2.31778"
     }
   },
   {
@@ -2423,7 +2461,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": null,
+      "longitude": null
     }
   },
   {
@@ -2545,7 +2585,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.4249",
+      "longitude": "2.1608"
     }
   },
   {
@@ -2654,7 +2696,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.83694",
+      "longitude": "1.02583"
     }
   },
   {
@@ -2763,7 +2807,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.83694",
+      "longitude": "1.02583"
     }
   },
   {
@@ -2872,7 +2918,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.83694",
+      "longitude": "1.02583"
     }
   },
   {
@@ -2981,7 +3029,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.83694",
+      "longitude": "1.02583"
     }
   },
   {
@@ -3090,7 +3140,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.83694",
+      "longitude": "1.02583"
     }
   },
   {
@@ -3219,7 +3271,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.38833",
+      "longitude": "2.36361"
     }
   },
   {
@@ -3348,7 +3402,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.38833",
+      "longitude": "2.36361"
     }
   },
   {
@@ -3477,7 +3533,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.38833",
+      "longitude": "2.36361"
     }
   },
   {
@@ -3606,7 +3664,9 @@
           "datatype": null,
           "lang": "fr"
         }
-      ]
+      ],
+      "latitude": "44.38833",
+      "longitude": "2.36361"
     }
   }
 ];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/server/fixtures/geonames.js	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,752 @@
+module.exports = {
+    '3038033': 'Alsace',
+    '6617404': 'Andlau',
+    '6450647': 'Battenheim',
+    '6450655': 'Berrwiller',
+    '6450585': 'Berstett',
+    '6450662': 'Bisel',
+    '6450665': 'Blotzheim',
+    '6614770': 'B\u0153senbiesen',
+    '6613081': 'Bretten',
+    '6450610': 'Brumath',
+    '6450616': 'Cleebourg',
+    '6455225': 'Dambach',
+    '6613079': 'Dehlingen',
+    '6450629': 'Diebolsheim',
+    '6614520': 'Dinsheim-sur-Bruche',
+    '6450691': 'Durmenach',
+    '6441075': 'Durstel',
+    '6441079': 'Eckartswiller',
+    '6450694': 'Eguisheim',
+    '6441094': 'Ettendorf',
+    '6441437': 'Geishouse',
+    '6441110': 'Geispolsheim',
+    '6441439': 'Geiswasser',
+    '6441112': 'Gerstheim',
+    '6617435': 'Gildwiller',
+    '6614642': 'G\u0153rlingen',
+    '6441116': 'Gottenhouse',
+    '6441117': 'Gottesheim',
+    '6441127': 'Gundershoffen',
+    '6441449': 'Gunsbach',
+    '6441128': 'Gunstett',
+    '6441131': 'Haguenau',
+    '6441134': 'Harskirchen',
+    '6441138': 'Heidolsheim',
+    '6441140': 'Heiligenstein',
+    '6441141': 'Hengwiller',
+    '6441150': 'Hirschland',
+    '6441470': 'Hirtzbach',
+    '6441471': 'Hirtzfelden',
+    '6614941': 'H\u0153rdt',
+    '6456344': 'Le Hohwald',
+    '6441156': 'Holtzheim',
+    '6441476': 'Houssen',
+    '6441479': 'Huningue',
+    '6441483': 'Illhaeusern',
+    '6441164': 'Ingolsheim',
+    '6441168': 'Ittenheim',
+    '6441487': 'Jebsheim',
+    '6614942': 'Kleing\u0153ft',
+    '6441184': 'Krautergersheim',
+    '6456345': 'La Petite-Pierre',
+    '6456347': 'La Wantzenau',
+    '6441510': 'Liebsdorf',
+    '6441199': 'Limersheim',
+    '6441205': 'Lochwiller',
+    '6441524': 'Manspach',
+    '6441214': 'Marckolsheim',
+    '6441215': 'Marlenheim',
+    '6441219': 'Memmelshoffen',
+    '6441220': 'Menchhoffen',
+    '6441528': 'Meyenheim',
+    '6441226': 'Mittelhausbergen',
+    '6441538': 'Le Haut Soultzbach',
+    '6441233': 'Mothern',
+    '6617442': 'Muespach',
+    '6454564': 'Munchhouse',
+    '6441543': 'Munwiller',
+    '6441237': 'Muttersholtz',
+    '6441297': 'Reichshoffen',
+    '6441242': 'Neuhaeusel',
+    '6615252': 'Neuwiller',
+    '6614997': 'Niederr\u0153dern',
+    '6441251': 'Niederschaeffolsheim',
+    '6441551': 'Niffer',
+    '6441555': 'Oberlarg',
+    '6441264': 'Oberlauterbach',
+    '6441268': 'Obersteinbach',
+    '6441270': 'Oermingen',
+    '6441271': 'Offendorf',
+    '6441273': 'Ohlungen',
+    '6441278': 'Osthouse',
+    '6441282': 'Ottrott',
+    '6441568': 'Pfetterhouse',
+    '6441296': 'Reichsfeld',
+    '6441298': 'Reichstett',
+    '6441576': 'Reiningue',
+    '6441300': 'Reipertswiller',
+    '6441304': 'Rhinau',
+    '6441579': 'Richwiller',
+    '6441583': 'Rimbach-pr\u00e8s-Guebwiller',
+    '6441585': 'Rimbachzell',
+    '6441310': 'Rittershoffen',
+    '6441587': 'Rixheim',
+    '6441595': 'Rosenau',
+    '6441316': 'Rossfeld',
+    '6441600': 'Rumersheim-le-Haut',
+    '6441343': 'Scheibenhard',
+    '6441345': 'Scherwiller',
+    '6441347': 'Schiltigheim',
+    '6441349': 'Schirrhein',
+    '6441351': 'Schleithal',
+    '6441610': 'Schlierbach',
+    '6614771': 'Sch\u0153nau',
+    '6617419': 'Betschdorf',
+    '6441616': 'Sewen',
+    '6441618': 'Sierentz',
+    '6441360': 'Siewiller',
+    '6612746': 'Siltzheim',
+    '6441365': 'Soufflenheim',
+    '6441626': 'Soultzeren',
+    '6454553': 'Saint-Pierre',
+    '6441607': 'Sainte-Marie-aux-Mines',
+    '6441631': 'Steinbach',
+    '6441637': 'Storckensohn',
+    '6617427': 'Stutzheim-Offenheim',
+    '6441379': 'Thanvill\u00e9',
+    '6441387': 'Uhrwiller',
+    '6441655': 'Village-Neuf',
+    '6617445': 'Volgelsheim',
+    '6454568': 'Waltenheim',
+    '6441661': 'Wasserbourg',
+    '6441407': 'Weiterswiller',
+    '6441670': 'Widensolen',
+    '6441673': 'Willer-sur-Thur',
+    '6617432': 'Wickersheim-Wilshausen',
+    '6454558': 'Wingen',
+    '6441674': 'Winkel',
+    '6441420': 'Wintzenheim-Kochersberg',
+    '6454559': 'Wissembourg',
+    '6441427': 'Wolfskirchen',
+    '6441680': 'Wolschwiller',
+    '6441429': 'Wolxheim',
+    '6441433': 'Zinswiller',
+    '6452479': 'Andolsheim',
+    '6614074': 'Artzenheim',
+    '6450566': 'Aschbach',
+    '6455226': 'Aspach',
+    '6450637': 'Aspach-Michelbach',
+    '6450574': 'Bassemberg',
+    '6450576': 'Beinheim',
+    '6614330': 'Bouxwiller',
+    '6450669': 'Br\u00e9chaumont',
+    '6450673': 'Bruebach',
+    '6450675': 'Buethwiller',
+    '6455228': 'Colmar',
+    '6450619': 'Cosswiller',
+    '6450685': 'Dessenheim',
+    '6441077': 'Ebersheim',
+    '6441089': 'Ernolsheim-Bruche',
+    '6441095': 'Eywiller',
+    '6441115': 'Gingsheim',
+    '6441441': 'Grentzingen',
+    '6441125': 'Griesheim-pr\u00e8s-Molsheim',
+    '6441444': 'Gueberschwihr',
+    '6441136': 'Hattmatt',
+    '6441153': 'Hoffen',
+    '6441477': 'Hunawihr',
+    '6441173': 'Kertzfeld',
+    '6441174': 'Keskastel',
+    '6441494': 'Kientzheim',
+    '6441352': 'Schnersheim',
+    '6441498': 'Kruth',
+    '6441317': 'Rosteig',
+    '6441196': 'Lembach',
+    '6441515': 'Logelheim',
+    '6441217': 'Meistratzheim',
+    '6614939': 'G\u0153rsdorf',
+    '6441541': 'Mulhouse',
+    '6441240': 'Natzwiller',
+    '6441246': 'Niederhaslach',
+    '6617421': 'Seebach',
+    '6617443': 'Orschwihr',
+    '6614644': 'Pfalzweyer',
+    '6441569': 'Pulversheim',
+    '6441294': 'Ratzwiller',
+    '6441307': 'Rimsdorf',
+    '6441312': 'Rohrwiller',
+    '6441314': 'Rosenwiller',
+    '6441326': 'Saessolsheim',
+    '6441605': 'Saint-Hippolyte',
+    '6441369': 'Stattmatten',
+    '6441643': 'Thannenkirch',
+    '6441380': 'Tieffenbach',
+    '6441646': 'Turckheim',
+    '6441658': 'Walbach',
+    '6441400': 'Waldolwisheim',
+    '6617411': 'Wangenbourg-Engenthal',
+    '6441408': 'Westhoffen',
+    '6441672': 'Wildenstein',
+    '6441413': 'Wilwisheim',
+    '6441423': 'Wittersheim',
+    '6450668': 'Bourbach-le-Haut',
+    '6450677': 'Burnhaupt-le-Haut',
+    '6450704': 'Fislis',
+    '6450708': 'Franken',
+    '6450710': 'Friesen',
+    '6614990': 'Fr\u0153ningen',
+    '6441436': 'Galfingue',
+    '6441162': 'Illkirch-Graffenstaden',
+    '6441122': 'Grendelbruch',
+    '6614913': 'K\u0153stlach',
+    '6441509': 'Liebenswiller',
+    '6441514': 'Linthal',
+    '6441522': 'Magstatt-le-Haut',
+    '6441530': 'Michelbach-le-Haut',
+    '6441540': 'Muhlbach-sur-Munster',
+    '6441545': 'Nambsheim',
+    '6441547': 'Niederbruck',
+    '6441554': 'Oberhergheim',
+    '6441557': 'Obermorschwiller',
+    '6441564': 'Ottmarsheim',
+    '6441289': 'Plobsheim',
+    '6441571': 'Raedersheim',
+    '6441620': 'Sondernach',
+    '6441604': 'Sainte-Croix-en-Plaine',
+    '6441375': 'Strasbourg',
+    '6452472': 'Altenheim',
+    '6450568': 'Auenheim',
+    '6450599': 'Blaesheim',
+    '6455224': 'Breitenbach',
+    '6450617': 'Climbach',
+    '6454560': 'Guebwiller',
+    '6456346': 'La Walck',
+    '6437717': 'Mittelbronn',
+    '6441230': 'Mommenheim',
+    '6617418': 'Neuviller-la-Roche',
+    '6617422': 'Ranrupt',
+    '6454570': 'Wintzenheim',
+    '3469058': 'Bras\u00edlia',
+    '934765': 'Beau Bassin',
+    '2138089': 'Tiabet',
+    '2140915': 'Kaala-Gom\u00e9n',
+    '6438526': 'Tourcoing',
+    '6450029': 'Auberchicourt',
+    '6450030': 'Aubers',
+    '6438420': 'Prisches',
+    '6438228': 'Felleries',
+    '6438284': 'Haynecourt',
+    '6438437': 'Raucourt-au-Bois',
+    '6438478': 'Saint-Remy-Chauss\u00e9e',
+    '6438261': 'Gommegnies',
+    '6455198': 'Beaufort',
+    '6454403': 'Cousolre',
+    '6438258': 'Glageon',
+    '6450041': 'Bachy',
+    '6438302': 'Houdain-lez-Bavay',
+    '6438452': 'Roubaix',
+    '6438156': 'Carnin',
+    '6438157': 'Cartignies',
+    '6438307': 'Illies',
+    '6438445': 'Rieux-en-Cambr\u00e9sis',
+    '6448637': 'Azay-le-Rideau',
+    '6432996': 'Tilly',
+    '6613137': 'Montreuil',
+    '6455259': 'Paris',
+    '6618617': 'Paris 11',
+    '6451982': 'Suresnes',
+    '6618619': 'Paris 13',
+    '6452021': 'Ivry-sur-Seine',
+    '6457187': 'Le Kremlin-Bic\u00eatre',
+    '6618613': 'Paris 07',
+    '6618618': 'Paris 12',
+    '6455342': 'Saint-Ouen',
+    '6618611': 'Paris 05',
+    '6452003': 'Rosny-sous-Bois',
+    '6618626': 'Paris 20',
+    '6454573': 'Lyon',
+    '3015948': 'D\u00e9partement de la Gironde',
+    '6455058': 'Bordeaux',
+    '2987410': 'D\u00e9partement du Rh\u00f4ne',
+    '6453974': 'Toulouse',
+    '6614831': 'Redon',
+    '2991879': 'D\u00e9partement du Morbihan',
+    '6432801': 'Rennes',
+    '6450845': 'Autun',
+    '3021042': 'D\u00e9partement de la Dordogne',
+    '3030293': 'Bretagne',
+    '2949188': 'Bielefeld',
+    '6455341': 'Saint-Denis',
+    '6431257': 'Santo-Pietro-di-Tenda',
+    '6616409': 'Patrimonio',
+    '6431166': 'Loreto-di-Casinca',
+    '6431208': 'Pietralba',
+    '6453941': 'Porto-Vecchio',
+    '6616378': 'Sainte-Lucie-de-Tallano',
+    '6455273': 'Amiens',
+    '6450264': 'Auxi-le-Ch\u00e2teau',
+    '6444688': 'Querrieu',
+    '6613695': 'Moyenneville',
+    '6444395': 'Doullens',
+    '6444557': 'Lanch\u00e8res',
+    '6451266': 'Ailly-sur-Noye',
+    '6454159': 'Orl\u00e9ans',
+    '6434221': 'P\u00e9lussin',
+    '3380895': 'Montagne Sable',
+    '3380994': 'Maripasoula',
+    '3382160': 'Cayenne',
+    '10372489': 'La Charbonni\u00e8re',
+    '3382124': 'Charvein',
+    '3380743': 'Papa\u00efchton',
+    '3383268': 'Pikien Santi',
+    '935814': 'Grand \u00celet',
+    '935248': 'Sainte-Suzanne',
+    '936089': 'Bois-Blanc',
+    '935382': 'Plaine des Gr\u00e8gues',
+    '935264': 'Saint-Denis',
+    '935317': 'La R\u00e9union',
+    '935268': 'Saint-Andr\u00e9',
+    '935345': 'Ravine des Cabris',
+    '935214': 'Saint-Pierre',
+    '935616': 'Le Port',
+    '3382484': 'Bada Tabiki',
+    '3380387': 'Saint-Laurent-du-Maroni',
+    '3383740': 'Langa Tabbetje',
+    '3383329': 'Paramaribo',
+    '3384285': 'Drietabbetje',
+    '3381654': 'Skien Tabbetje',
+    '3383976': 'Kaaimanston',
+    '3382314': 'Bonidoro',
+    '8555643': 'Cergy-Pontoise',
+    '2138103': 'Thio',
+    '10793959': 'K\u00e8r\u00e8ji',
+    '2139981': 'Nak\u00e9ty',
+    '2138836': 'Petit-Borindi',
+    '2141124': 'Grand-Borindi',
+    '2137680': 'Wen\u00e9ki',
+    '2139521': 'Noum\u00e9a',
+    '2140021': 'Mouly',
+    '2138274': 'Takedji',
+    '2138408': 'Saint-Joseph',
+    '2139490': 'Ognat',
+    '2140044': 'Mou',
+    '4034763': 'Utufua',
+    '4034755': 'Vaimalau',
+    '4034858': 'Haafusia',
+    '2141656': 'Canala',
+    '2138980': 'Pa\u00efta',
+    '2139032': 'Ouv\u00e9a Island',
+    '4034758': 'Wallis Island',
+    '4034885': 'Ono',
+    '4034865': 'Foi',
+    '10858671': 'Bouzegu\u00e8ne',
+    '10858634': 'Ihamziyen',
+    '2507705': 'A\u00eft Sa\u00efd',
+    '10858636': 'Abourgh\u00e8s',
+    '10858639': 'Maraghna',
+    '2490523': 'Mahagga',
+    '2140794': 'Kavatch',
+    '2139028': 'Ouyaguette',
+    '2141939': 'Bas-Coulna',
+    '2138147': 'Tendo',
+    '2139322': 'Ouarap',
+    '6426657': 'Douzens',
+    '6452134': 'Aix-en-Provence',
+    '6447117': 'Ch\u00e2teauneuf-le-Rouge',
+    '6453767': 'Dijon',
+    '6434483': 'Nantes',
+    '2970140': 'Vend\u00e9e',
+    '6613992': 'Roanne',
+    '6446110': 'Brunoy',
+    '3382530': 'Awala-Yalimapo',
+    '2282436': 'Le Plateau',
+    '2595323': 'Marcory',
+    '2290623': 'Cocody',
+    '2139069': 'Oundjo',
+    '2137973': 'Tioua\u00e9',
+    '2137753': 'Vieux-Touho',
+    '2138039': 'Ti\u00e9',
+    '2138515': 'Tribu de Poyes',
+    '2140716': 'Kokengone',
+    '6430862': 'Saint-Arnoult-des-Bois',
+    '6430869': 'Saint-Denis-les-Ponts',
+    '6434590': 'Engenville',
+    '6449177': 'Ch\u00e2teauneuf-sur-Loire',
+    '6434724': 'Saint-P\u00e9ravy-la-Colombe',
+    '6439305': 'Saint-Victor-de-R\u00e9no',
+    '6448929': 'Coulanges',
+    '6433069': 'Neuvy-le-Roi',
+    '6448898': 'Blois',
+    '6434117': 'Saint-Lubin-en-Vergonnois',
+    '6439212': 'R\u00e9malard en Perche',
+    '6446258': 'Ennery',
+    '6454157': 'Gien',
+    '6434726': 'Saint-Sigismond',
+    '6457004': 'La Chapelle-Montligeon',
+    '6446221': 'Videlles',
+    '6434591': '\u00c9pieds-en-Beauce',
+    '6456502': 'Les Mesnuls',
+    '6439198': 'Origny-le-Roux',
+    '6447987': 'Aunay-sous-Auneau',
+    '6424422': 'Nottonville',
+    '6448343': 'Biran',
+    '6432117': 'Saint-Sauvy',
+    '6454944': 'Bethmale',
+    '6426310': 'Saurat',
+    '6426695': 'Gramazie',
+    '6445011': 'Mouillac',
+    '6426809': 'Puivert',
+    '6613520': 'Saint-Simon',
+    '6453661': 'Savignac',
+    '6426328': 'Surba',
+    '6426816': 'Ribouisse',
+    '6618241': 'Antras',
+    '6446895': 'Castillon-en-Couserans',
+    '6455502': 'Le Port',
+    '6448296': 'Boussan',
+    '6448308': 'Cadours',
+    '6431574': 'Frouzins',
+    '6431644': 'L\u00e9guevin',
+    '6448248': 'Aspet',
+    '6431803': 'Sainte-Foy-d\'Aigrefeuille',
+    '6613251': 'Saint-Martin',
+    '6448410': 'Beychac-et-Caillau',
+    '6448412': 'Biganos',
+    '6455056': 'Blaignac',
+    '6448414': 'Blasimon',
+    '6448441': 'Captieux',
+    '6432174': 'Castelnau-de-M\u00e9doc',
+    '6432190': 'Cissac-M\u00e9doc',
+    '6432246': 'Gr\u00e9zillac',
+    '6432251': 'Hostens',
+    '6454003': 'Hourtin',
+    '6454004': 'Lacanau',
+    '6432320': 'Mourens',
+    '6454014': 'Pessac',
+    '6432351': 'Pujols-sur-Ciron',
+    '6454016': 'Puynormand',
+    '6616574': 'Salles',
+    '6432467': 'Saucats',
+    '6618265': 'Saint-Andr\u00e9-de-Cubzac',
+    '6616565': 'Saint-C\u00f4me',
+    '6432409': 'Saint-Jean-d\'Illac',
+    '6432456': 'Saint-Symphorien',
+    '6432461': 'Saint-Vivien-de-M\u00e9doc',
+    '6432464': 'Saint-Yzans-de-M\u00e9doc',
+    '6452298': 'Aire-sur-l\'Adour',
+    '6455089': 'Biscarrosse',
+    '6455091': 'Castets',
+    '6433826': 'Geaune',
+    '6433832': 'Grenade-sur-l\'Adour',
+    '6433834': 'Hagetmau',
+    '6433872': 'Lubbon',
+    '6618275': 'L\u00fce',
+    '6433890': 'M\u00e9zos',
+    '6454123': 'Mimizan',
+    '6433920': 'Parentis-en-Born',
+    '6433921': 'Parleboscq',
+    '6433930': 'Pomarez',
+    '6433935': 'Pouillon',
+    '6433945': 'Sabres',
+    '6433979': 'Sarbazan',
+    '6434000': 'Soustons',
+    '6433965': 'Saint-Martin-de-Hinx',
+    '6433974': 'Saint-Sever',
+    '6614680': 'Saint-Vincent-de-Paul',
+    '6434002': 'Tarnos',
+    '6434003': 'Tartas',
+    '6434015': 'Vielle-Saint-Girons',
+    '6434018': 'Villeneuve-de-Marsan',
+    '6434020': 'Ygos-Saint-Saturnin',
+    '6452451': 'Aast',
+    '6452455': 'Agnos',
+    '6450366': 'Anglet',
+    '6450380': 'Arette',
+    '6450397': 'Artix',
+    '6440287': 'Bedous',
+    '6440304': 'Bielle',
+    '6440390': 'Garlin',
+    '6614172': 'Gelos',
+    '6440406': 'Gurs',
+    '6617355': 'La Bastide-Clairence',
+    '6440461': 'Lasseube',
+    '6612723': 'Lembeye',
+    '6440514': 'Momas',
+    '6454512': 'Nay',
+    '6612729': 'Pontacq',
+    '6617360': 'Sauveterre-de-B\u00e9arn',
+    '6440621': 'Sedz\u00e8re',
+    '6440582': 'Saint-Armou',
+    '6440545': 'Orthez',
+    '6440647': 'Urt',
+    '6452458': 'Ad\u00e9',
+    '6450436': 'Aragnouet',
+    '6617364': 'Arrens-Marsous',
+    '6450459': 'Aureilhan',
+    '6440923': 'Sers',
+    '6450492': 'Betpouey',
+    '6450475': 'Barrancoueu',
+    '6454518': 'Bordes',
+    '6440689': 'Cauterets',
+    '6617371': 'Ferri\u00e8res',
+    '6440728': 'Galan',
+    '6615246': 'Gard\u00e8res',
+    '6440733': 'Gavarnie',
+    '6440740': 'Gerde',
+    '6440741': 'Germ',
+    '6440775': 'Labatut-Rivi\u00e8re',
+    '6440776': 'Laborde',
+    '6440788': 'Lannemezan',
+    '6450469': 'Bagn\u00e8res-de-Bigorre',
+    '6454530': 'Lourdes',
+    '6613501': 'Marseillan',
+    '6440859': 'Ourde',
+    '6440883': 'Rabastens-de-Bigorre',
+    '6617382': 'Salles',
+    '6440904': 'Sariac-Magnoac',
+    '6614801': 'Saint-L\u00e9zer',
+    '6617384': 'Trie-sur-Ba\u00efse',
+    '6449246': 'D\u00e9gagnac',
+    '6431673': 'Mauressac',
+    '6448244': 'Arguenos',
+    '6433848': 'Labrit',
+    '6433877': 'Luxey',
+    '6616732': 'Mazerolles',
+    '6440328': 'Cabidos',
+    '6433904': 'Moustey',
+    '6446859': 'Aulus-les-Bains',
+    '6426181': 'Couflens',
+    '6456691': 'La Bastide-de-S\u00e9rou',
+    '6453610': 'Lescure',
+    '6426228': 'L\u00e9zat-sur-L\u00e8ze',
+    '6431781': 'Rieumes',
+    '6452253': 'Anan',
+    '6448265': 'Bagn\u00e8res-de-Luchon',
+    '6448294': 'Bourg-d\'Oueil',
+    '6431494': 'Carbonne',
+    '6431569': 'Franquevielle',
+    '6431624': 'Lagr\u00e2ce-Dieu',
+    '6431627': 'Lahit\u00e8re',
+    '6431669': 'Martres-Tolosane',
+    '6431678': 'Melles',
+    '6431691': 'Mondilhan',
+    '6431831': 'Saleich',
+    '6431826': 'Saint-Plancard',
+    '6431883': 'Villeneuve-de-Rivi\u00e8re',
+    '6613277': 'Armous-et-Cau',
+    '6431900': 'D\u00e9mu',
+    '6431903': '\u00c9auze',
+    '6614459': 'Faget-Abbatial',
+    '6431925': 'Gimont',
+    '6455858': 'La Romieu',
+    '6431943': 'Ladev\u00e8ze-Rivi\u00e8re',
+    '6431967': 'Lavardens',
+    '6431971': 'Lectoure',
+    '6431975': 'Lombez',
+    '6431993': 'Marestaing',
+    '6616516': 'Montaut-les-Cr\u00e9neaux',
+    '6432039': 'Nogaro',
+    '6613651': 'Plaisance',
+    '6432079': 'Riscle',
+    '6451394': 'Beaumont-de-Lomagne',
+    '6445032': 'Saint-Jean-du-Bouzet',
+    '6431904': 'Esclassan-Labastide',
+    '6431958': 'Larressingle',
+    '6452345': 'Aiguillon',
+    '6449324': 'Espiens',
+    '6434965': 'Houeill\u00e8s',
+    '6434967': 'Labastide-Castel-Amouroux',
+    '6434972': 'Lafitte-sur-Lot',
+    '6434985': 'Layrac',
+    '6454182': 'M\u00e9zin',
+    '6453654': 'Najac',
+    '6426959': 'Mayran',
+    '6427018': 'Saint-F\u00e9lix-de-Lunel',
+    '6429427': 'Marnac',
+    '6426277': 'Prayols',
+    '6618205': 'Qu\u00e9rigut',
+    '6453612': 'Loubens',
+    '6618238': 'La Bastide-de-Lordat',
+    '6615269': 'M\u00e9rens-les-Vals',
+    '6426302': 'Saint-Martin-d\'Oydes',
+    '6446897': 'Caychax',
+    '6426188': 'Dun',
+    '6426260': 'Monts\u00e9gur',
+    '6426874': 'Sonnac-sur-l\'Hers',
+    '6426753': 'Molleville',
+    '6426853': 'Saint-Martin-Lalande',
+    '6427053': 'Sauveterre-de-Rouergue',
+    '6427069': 'Vabre-Tizac',
+    '6427054': 'S\u00e9bazac-Concour\u00e8s',
+    '6615868': 'Lanu\u00e9jouls',
+    '6447048': 'Auzits',
+    '6426961': 'Meljac',
+    '6426323': 'Siguer',
+    '6449329': 'Fauillet',
+    '6613032': 'Baleyssagues',
+    '6449272': 'Blanquefort-sur-Briolance',
+    '6449289': 'Cancon',
+    '6449320': 'Douzains',
+    '6435103': 'Tayrac',
+    '6435094': 'Savignac-sur-Leyze',
+    '6434978': 'Laparade',
+    '6449306': 'Clermont-Dessous',
+    '6434949': 'Foulayronnes',
+    '6435014': 'Montayral',
+    '6434968': 'Labretonie',
+    '6434990': 'Loub\u00e8s-Bernac',
+    '6614627': 'Cambes',
+    '6451339': 'Appelle',
+    '6444908': 'Pampelonne',
+    '6444897': 'Moulayr\u00e8s',
+    '6451386': 'Fauch',
+    '6451358': 'Cadalen',
+    '6617774': 'Brassac',
+    '6454787': 'Rabastens',
+    '6455388': 'Gaillac',
+    '6614427': 'Cordes-sur-Ciel',
+    '6454788': 'Rouairoux',
+    '6444930': 'Roussayrolles',
+    '6444832': 'Gijounet',
+    '6444946': 'Saint-Julien-Gaul\u00e8ne',
+    '6444902': 'Murat-sur-V\u00e8bre',
+    '6451340': 'Arfons',
+    '6444919': 'Puycelsi',
+    '6451367': 'Castelnau-de-L\u00e9vis',
+    '6452543': 'Aiguefonde',
+    '6452347': 'Allez-et-Cazeneuve',
+    '6449269': 'Beaupuy',
+    '6690693': 'Macouria',
+    '6615750': 'Albon-d\'Ard\u00e8che',
+    '6429307': 'Saint-Priest-la-Feuille',
+    '6455001': 'Gartempe',
+    '6444933': 'Saint-Amans-Valtoret',
+    '1090242': 'Mtsap\u00e9r\u00e9',
+    '6434674': 'Olivet',
+    '6434601': 'Fleury-les-Aubrais',
+    '6434619': 'Ingr\u00e9',
+    '6434714': 'Saint-Jean-de-Braye',
+    '6456924': 'La Chapelle-Saint-Mesmin',
+    '6434715': 'Saint-Jean-de-la-Ruelle',
+    '6434628': 'Lailly-en-Val',
+    '6434729': 'Saran',
+    '6454160': 'Ormes',
+    '6618260': 'Ouessant',
+    '6616347': '\u00cele-Mol\u00e8ne',
+    '6453931': 'Plouarzel',
+    '6431001': 'Plougonvelin',
+    '6448082': 'Guilers',
+    '6430954': 'Lanrivoar\u00e9',
+    '6453932': 'Ploudalm\u00e9zeau',
+    '6616357': 'Saint-Pabu',
+    '6430940': 'Land\u00e9da',
+    '6448043': 'Bourg-Blanc',
+    '6448074': 'Gouesnou',
+    '6448086': 'Guipavas',
+    '6448098': 'Kernilis',
+    '6431011': 'Ploun\u00e9our-Trez',
+    '6430992': 'Ploudaniel',
+    '6430993': 'Plou\u00e9dern',
+    '6431014': 'Ploun\u00e9vez-Lochrist',
+    '6448038': 'Bodilis',
+    '6455834': 'La Martyre',
+    '6448061': 'Collorec',
+    '6455838': 'Le Tr\u00e9hou',
+    '6453937': 'Sizun',
+    '6430960': 'Locm\u00e9lar',
+    '6455034': 'Guimiliau',
+    '6448081': 'Guiclan',
+    '6431016': 'Plouvorn',
+    '6431063': 'Sibiril',
+    '6616345': '\u00cele-de-Batz',
+    '6431037': 'Roscoff',
+    '6448051': 'Carantec',
+    '6431054': 'Sainte-S\u00e8ve',
+    '6431010': 'Ploun\u00e9our-M\u00e9nez',
+    '6431002': 'Plougonven',
+    '6431008': 'Plouigneau',
+    '6616353': 'Plouezoc\'h',
+    '6430981': 'Plo\u00e9ven',
+    '6614387': 'Loguivy-Plougras',
+    '6448080': 'Guerlesquin',
+    '6430999': 'Plougasnou',
+    '6430994': 'Plou\u00e9gat-Gu\u00e9rand',
+    '6612341': 'Plourac\'h',
+    '6429073': 'Plougonver',
+    '6612331': 'Lanvellec',
+    '6615125': 'Tr\u00e9drez-Locqu\u00e9meau',
+    '6429057': 'Pleumeur-Bodou',
+    '6430962': 'Locquirec',
+    '6429011': 'Louannec',
+    '6453798': 'Lannion',
+    '6453813': 'Le Vieux-March\u00e9',
+    '6429180': 'Tr\u00e9grom',
+    '6429177': 'Tr\u00e9glamus',
+    '6429080': 'Ploumagoar',
+    '6429163': 'Squiffiec',
+    '6429123': 'Saint-Clet',
+    '6453803': 'Prat',
+    '6429062': 'Plo\u00ebzal',
+    '6447629': 'Bourbriac',
+    '6447637': 'Camlez',
+    '6429074': 'Plougrescant',
+    '6429055': 'Pleubian',
+    '6429068': 'Ploubazlanec',
+    '6429084': 'Plourivo',
+    '6428993': 'Lanloup',
+    '6429040': 'Pl\u00e9guien',
+    '6447659': 'Goudelin',
+    '6428998': 'Lanrodec',
+    '6614006': 'Saint-Fiacre',
+    '6429132': 'Saint-Gilles-Pligeaux',
+    '6429095': 'Plussulien',
+    '6612977': 'Caurel',
+    '6437321': 'Neulliac',
+    '6428991': 'Laniscat',
+    '6429151': 'Saint-Nicolas-du-P\u00e9lem',
+    '6613786': 'Ploun\u00e9vez-Quintin',
+    '6429110': 'Rostrenen',
+    '6447675': 'Kergrist-Mo\u00eblou',
+    '6429014': 'Ma\u00ebl-Pestivien',
+    '6616125': 'Saint-Servais',
+    '6429007': 'Locarn',
+    '6429028': 'Paule',
+    '6455356': 'Berrien',
+    '6431029': 'Poullaouen',
+    '6430941': 'Landeleau',
+    '6431013': 'Ploun\u00e9v\u00e9zel',
+    '6612444': 'Motreff',
+    '6454335': 'Langonnet',
+    '6612647': 'Roudouallec',
+    '6448056': 'Cl\u00e9den-Poher',
+    '6430951': 'Lann\u00e9dern',
+    '6448041': 'Botmeur',
+    '6431052': 'Saint-Rivoal',
+    '6453930': 'Pleyben',
+    '6430957': 'Lennon',
+    '6431074': 'Tr\u00e9gourez',
+    '6448048': 'Briec',
+    '6616351': 'Lothey',
+    '6452232': 'B\u00e9nodet',
+    '6455033': 'Fouesnant',
+    '6431076': 'Tr\u00e9gunc',
+    '6448069': 'Elliant',
+    '6430944': 'Landudal',
+    '6431039': 'Rosporden',
+    '6453927': 'Nevez',
+    '6448064': 'Concarneau',
+    '6431022': 'Pont-Aven',
+    '6614190': 'Riec-sur-B\u00e9lon',
+    '6431061': 'Sca\u00ebr',
+    '6431057': 'Saint-Thurien',
+    '6453938': 'Tr\u00e9m\u00e9ven',
+    '6448058': 'Clohars-Carno\u00ebt',
+    '6447142': 'Marseille',
+    '6452137': 'Aubagne',
+    '6612800': 'Villeparisis',
+    '6451977': 'Neuilly-sur-Seine',
+    '6427502': 'Saon',
+    '6455546': 'Le Breuil-en-Bessin',
+    '6427527': 'Tourni\u00e8res'
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/server/mocks/geonames.js	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,21 @@
+/*jshint node:true*/
+module.exports = function(app) {
+    var express = require('express');
+    var _ = require('lodash');
+
+    var v1GeonamesRouter = express.Router();
+
+    var geonamesMappings = require('../fixtures/geonames');
+
+    v1GeonamesRouter.get('/:id', function(req, res) {
+        var idList = req.params.id.split(',');
+        res.send({
+            'geonamesids': _.reduce(idList, function(r, id) {
+                r[id] = (id in geonamesMappings)?geonamesMappings[id]:null;
+                return r;
+            }, {}),
+        });
+    });
+
+    app.use('/api/v1/geonames', v1GeonamesRouter);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/integration/pods/components/bo-doc-locations/component-test.js	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,24 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bo-doc-locations', 'Integration | Component | bo doc locations', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });
+
+  this.render(hbs`{{bo-doc-locations}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:
+  this.render(hbs`
+    {{#bo-doc-locations}}
+      template block text
+    {{/bo-doc-locations}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- a/server/src/app/Http/Controllers/Api/DocumentController.php	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/src/app/Http/Controllers/Api/DocumentController.php	Tue Sep 27 23:43:29 2016 +0200
@@ -67,6 +67,7 @@
      */
     public function show(Request $request, $id)
     {
+        $id= urldecode($id);
         $short = filter_var($request->input('short', false), FILTER_VALIDATE_BOOLEAN);
         $doc = $this->documentRepository->get($id, $short);
         if(is_null($doc)) {
@@ -83,6 +84,8 @@
      * @return Response
      */
     public function transcript($id) {
+        $id= urldecode($id);
+
         $doc = $this->documentRepository->get($id);
         if(is_null($doc) || is_null($doc->getTranscript()) ) {
             abort(404);
@@ -117,6 +120,8 @@
      */
     public function update(Request $request, $id)
     {
+        $id= urldecode($id);
+
         $data = $request->json();
         $document = $data->get('document');
         $doc = $this->documentRepository->get($id);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Http/Controllers/Api/GeonamesController.php	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,32 @@
+<?php
+
+namespace CorpusParole\Http\Controllers\Api;
+
+use Illuminate\Http\Request;
+use CorpusParole\Http\Requests;
+use CorpusParole\Http\Controllers\Controller;
+use CorpusParole\Services\GeonamesResolverInterface;
+use CorpusParole\Services\GeonamesResolverException;
+
+class GeonamesController extends Controller
+{
+    public function __construct(GeonamesResolverInterface $geonamesResolver) {
+        $this->geonamesResolver = $geonamesResolver;
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  int  $id od comma separatedlist of ids
+     * @return \Illuminate\Http\Response
+     */
+    public function show($id)
+    {
+        try {
+            return response()->json(['geonamesids' => $this->geonamesResolver->getLabels(explode(",", $id))]);
+        } catch (GeonamesResolverException $e) {
+            abort($e->getCode(), $e->getMessage());
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Providers/GeonamesServiceProvider.php	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,26 @@
+<?php
+
+namespace CorpusParole\Providers;
+
+use Illuminate\Support\ServiceProvider;
+
+use Config;
+
+use CorpusParole\Services\GeonamesResolver;
+
+
+class GeonamesServiceProvider extends ServiceProvider
+{
+
+    /**
+     * Register the application services.
+     *
+     * @return void
+     */
+    public function register()
+    {
+        $this->app->bind('CorpusParole\Services\GeonamesResolverInterface', function($app) {
+            return new GeonamesResolver($app['Guzzle']);
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Services/GeonamesResolver.php	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,123 @@
+<?php
+namespace CorpusParole\Services;
+
+use CorpusParole\Services\GeonamesResolverInterface;
+
+use Cache;
+use Config;
+use EasyRdf\Graph;
+use GuzzleHttp\Client;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Exception\ClientException;
+use GuzzleHttp\Exception\GuzzleException;
+use Illuminate\Contracts\Cache\Repository as CacheRepository;
+
+class GeonamesResolver implements GeonamesResolverInterface {
+
+    private $client = null;
+
+    public function __construct(Client $httpClient) {
+        $this->client = $httpClient;
+    }
+
+    /**
+     * make the Geonames query.
+     */
+    public function queryLabel($id) {
+
+        $url = config('corpusparole.geonames_base_url').$id."/";
+
+        try {
+            $response = $this->client->get($url, ['headers'=>['Accept' => 'application/rdf+xml'],]);
+        }
+        catch(ClientException $e) {
+            if($e->getResponse()->getStatusCode() === 404) {
+                return null;
+            } else {
+                throw new GeonamesResolverException(
+                    $e->getMessage(),
+                    $e->getResponse()->getStatusCode(),
+                    $e
+                );
+            }
+        }
+        catch(RequestException $e) {
+            throw new GeonamesResolverException(
+                $e->getMessage(),
+                $e->hasResponse()?$e->getResponse()->getStatusCode():500,
+                $e
+            );
+        }
+
+        $graph = new Graph($url, $response->getBody());
+        $labels = [];
+        // search First offficial name in fr then name
+        foreach ($graph->allLiterals("<$url>", "<http://www.geonames.org/ontology#officialName>") as $labelLit) {
+            $lang = $labelLit->getLang();
+            if(!$lang && !isset($labels[''])) {
+                $labels[''] = $labelLit->getvalue();
+            }
+            elseif (strpos($lang, 'fr') === 0 && !isset($labels['fr'])) {
+                $labels['fr'] = $labelLit->getvalue();
+            }
+        }
+
+        $label = isset($labels['fr']) ? $labels['fr'] : ( isset($labels[''])? $labels['']: null) ;
+
+        if(is_null($label)) {
+            $labelLit = $graph->getLiteral("<$url>", "<http://www.geonames.org/ontology#name>");            
+            $label = (!is_null($labelLit)) ? $labelLit->getValue() : null;
+        }
+
+        return $label;
+    }
+
+    /**
+     * Check Geonames id format
+     */
+    private function checkGeonamesIdFormat($geonamesid) {
+        return ctype_digit($geonamesid);
+    }
+
+    /**
+     * Get name from Geonames id
+     * @param string $id The id to resolve. Can be an url starting with http://sws.geonames.org/
+     * @return a string with the name
+     */
+    public function getLabel($id) {
+        $geonamesid = $id;
+        if(strpos($id, config('corpusparole.geonames_base_url')) === 0) {
+            $geonamesid = substr($id, strlen(config('corpusparole.geonames_base_url')));
+        }
+        $geonamesid = rtrim($geonamesid, '/');
+
+        if(!$this->checkGeonamesIdFormat($geonamesid)) {
+            throw new GeonamesResolverException("GeonamesId not in correct format", 400);
+        }
+
+        $that = $this;
+
+        return Cache::remember("geonames:$geonamesid", config('corpusparole.geonames_cache_expiration'), function() use ($that, $geonamesid)  {
+
+            return $that->queryLabel($geonamesid);
+
+        });
+
+    }
+
+    /**
+     * Get a list of names from an array of geonames ids.
+     * @param array $ids The array of ids to resolve.
+     *                   Each id can be an url starting with http://geonames.org/geonames/
+     */
+    public function getLabels(array $ids) {
+
+        if(count($ids) > config('corpusparole.geonames_max_ids')) {
+            throw new GeonamesResolverException("Too manys ids provided");
+        }
+
+        return array_combine($ids, array_map([$this,'getLabel'], $ids));
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Services/GeonamesResolverException.php	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,6 @@
+<?php
+namespace CorpusParole\Services;
+
+class GeonamesResolverException extends \Exception {
+    // just extend...
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Services/GeonamesResolverInterface.php	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,20 @@
+<?php
+namespace CorpusParole\Services;
+
+interface GeonamesResolverInterface {
+
+    /**
+     * Get label from Geonames id
+     * @param string $id The id to resolve. Can be an url starting with http(s)://(wwww|sws).geonames.org
+     * @return a string with the label
+     */
+    public function getLabel($id);
+
+    /**
+     * Get a list of labels from an array of geonames ids.
+     * @param array $ids The array of ids to resolve.
+     *                   Each id can be an url starting with http(s)://(wwww|sws).geonames.org
+     */
+    public function getLabels(array $ids);
+
+}
--- a/server/src/app/Services/LexvoResolver.php	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/src/app/Services/LexvoResolver.php	Tue Sep 27 23:43:29 2016 +0200
@@ -23,8 +23,8 @@
     }
 
     /**
-     * Get name from Viaf id
-     * @param string $id The id to resolve. Can be an url starting with http://viaf.org/viaf/
+     * Get name from Lexvo id
+     * @param string $id The id to resolve. Can be an url starting with http://lexvo.org/
      * @return a string with the name
      */
     public function getName($id) {
@@ -34,9 +34,9 @@
     }
 
     /**
-     * Get a list of names from an array of viaf ids.
+     * Get a list of names from an array of Lexvo ids.
      * @param array $ids The array of ids to resolve.
-     *                   Each id can be an url starting with http://viaf.org/viaf/
+     *                   Each id can be an url starting with http://lexvo.org/
      * @return array key is id, value is the name
      */
     public function getNames(array $ids) {
--- a/server/src/config/app.php	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/src/config/app.php	Tue Sep 27 23:43:29 2016 +0200
@@ -157,6 +157,7 @@
         'CorpusParole\Providers\ViafServiceProvider',
         'CorpusParole\Providers\LexvoServiceProvider',
         'CorpusParole\Providers\BnfServiceProvider',
+        'CorpusParole\Providers\GeonamesServiceProvider',
         'CorpusParole\Providers\VersionServiceProvider',
 
     ],
--- a/server/src/config/corpusparole.php	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/src/config/corpusparole.php	Tue Sep 27 23:43:29 2016 +0200
@@ -124,6 +124,10 @@
     'bnf_query_url' => 'http://data.bnf.fr/sparql',
     'bnf_completion_url' => 'http://data.bnf.fr/search-letter/',
 
+    'geonames_base_url' => 'http://sws.geonames.org/',
+    'geonames_cache_expiration' => 60*24*30,
+    'geonames_max_ids' => 500,
+
     'bo_client_environment' => [
         "modulePrefix" => "bo-client",
         "podModulePrefix" => "bo-client/pods",
--- a/server/src/routes/api.php	Tue Sep 27 01:50:53 2016 +0200
+++ b/server/src/routes/api.php	Tue Sep 27 23:43:29 2016 +0200
@@ -21,6 +21,8 @@
                     ['only' => ['show']]);
     Route::resource('bnf', 'Api\BnfController',
                     ['only' => ['index','show']]);
+    Route::resource('geonames', 'Api\GeonamesController',
+                    ['only' => ['index','show']]);
     Route::resource('languages', 'Api\LanguageController',
                     ['only' => ['index']]);
     Route::resource('themes', 'Api\ThemeController',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/Controllers/GeonamesControllerTest.php	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,79 @@
+<?php
+
+use Mockery as m;
+
+use CorpusParole\Services\GeonamesResolverException;
+
+/**
+ *
+ */
+class GeonamesControllerTest extends TestCase {
+
+    private $geonamesResolver;
+
+    public function setUp() {
+
+        parent::setup();
+
+        // create a mock of the post repository interface and inject it into the
+        // IoC container
+        $this->geonamesResolver = m::mock('CorpusParole\Services\GeonamesResolverInterface');
+        $this->app->instance('CorpusParole\Services\GeonamesResolverInterface', $this->geonamesResolver);
+    }
+
+    public function tearDown() {
+        m::close();
+        parent::tearDown();
+    }
+
+    public function testShow() {
+        $this->geonamesResolver
+            ->shouldReceive('getLabels')
+            ->with(['2968801', '2988507', '6255148'])
+            ->once()
+            ->andReturn(['2968801' => 'Villedieu-les-Poêles', '2988507' => 'Paris', '6255148' => 'Europe']);
+
+        $response = $this->get('/api/v1/geonames/2968801,2988507,6255148')->
+            seeJsonEquals(['geonamesids' => ['2968801' => 'Villedieu-les-Poêles', '2988507' => 'Paris', '6255148' => 'Europe']]);
+    }
+
+    public function testShowOne() {
+        $this->geonamesResolver
+            ->shouldReceive('getLabels')
+            ->with(['2968801'])
+            ->once()
+            ->andReturn([
+                '2968801' => 'Villedieu-les-Poêles'
+            ]);
+        $response = $this->get('/api/v1/geonames/2968801')->
+            seeJsonEquals(['geonamesids' => [
+                '2968801' => 'Villedieu-les-Poêles'
+            ]]);
+    }
+
+    public function testShowUnknown() {
+        $this->geonamesResolver
+            ->shouldReceive('getLabels')
+            ->with(['12345'])
+            ->once()
+            ->andReturn([
+                '12345' => null
+            ]);
+        $response = $this->get('/api/v1/geonames/12345')->
+            seeJsonEquals(['geonamesids' => [
+                '12345' => null
+            ]]);
+    }
+
+    public function testShowMalformed() {
+        $this->geonamesResolver
+            ->shouldReceive('getLabels')
+            ->with(['abcdef','ghij'])
+            ->once()
+            ->andThrow('CorpusParole\Services\GeonamesResolverException', "GeonamesId not in correct format", 400);
+        $response = $this->get('/api/v1/geonames/abcdef,ghij');
+
+        $this->assertResponseStatus(400);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/Services/GeonamesResolverTest.php	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,224 @@
+<?php
+
+use GuzzleHttp\Client;
+use GuzzleHttp\Handler\MockHandler;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Psr7\Response;
+use GuzzleHttp\Psr7\Request;
+use GuzzleHttp\Middleware;
+use GuzzleHttp\Exception\RequestException;
+
+
+class GeonamesResolverTest extends TestCase
+{
+
+    const TEST_INPUT_DOCS = [
+        '2968801' => __DIR__.'/files/GeonamesResolverTest/geonames_rdf_2968801.rdf',
+        '2988507' => __DIR__.'/files/GeonamesResolverTest/geonames_rdf_2988507.rdf',
+        '6255148' => __DIR__.'/files/GeonamesResolverTest/geonames_rdf_6255148.rdf',
+    ];
+
+    private $inputGraphes = [];
+
+    private function getClient($keys, &$container) {
+        $history = Middleware::history($container);
+        $responses = [];
+        foreach ($keys as $key) {
+            if(array_key_exists($key, self::TEST_INPUT_DOCS)) {
+                array_push($responses, new Response(200, [], file_get_contents(self::TEST_INPUT_DOCS[$key])));
+            }
+            else {
+                array_push($responses, new Response(intval($key)));  
+            }
+
+        }
+        $mock = new MockHandler($responses);
+        $handler = HandlerStack::create($mock);
+        $handler->push($history);
+
+        return new Client(['handler' => $handler]);
+    }
+
+    public function setUp() {
+        parent::setup();
+
+        foreach(self::TEST_INPUT_DOCS as $key => $inputDoc) {
+            $this->inputGraphes[$key] =  new EasyRdf\Graph(config('corpusparole.geonames_base_url').$key."/", file_get_contents($inputDoc));
+        }
+    }    
+
+    /**
+     * Just test the setup.
+     *
+     * @return void
+     */
+    public function testSetup()
+    {
+        $this->assertTrue(true);
+    }
+
+    /**
+     * test getLabel
+     */
+    public function testGetLabel() {
+
+        $container = [];
+        $client = $this->getClient(['2968801'], $container);
+
+        $resolver = $this->app->make('CorpusParole\Services\GeonamesResolver', [$client]);
+        $label = $resolver->getLabel('2968801');
+
+        $this->assertEquals('Villedieu-les-Poêles', $label, "Label is Villedieu-les-Poêles");
+
+        $this->assertCount(1, $container);
+
+        $this->assertEquals("http://sws.geonames.org/2968801/", (string)$container[0]['request']->getUri());
+
+    }
+
+    /**
+     * test getLabel
+     */
+    public function testGetLabel2988507() {
+
+        $container = [];
+        $client = $this->getClient(['2988507'], $container);
+
+        $resolver = $this->app->make('CorpusParole\Services\GeonamesResolver', [$client]);
+        $label = $resolver->getLabel('2988507');
+
+        $this->assertEquals('Paris', $label, "Label is Paris");
+
+        $this->assertCount(1, $container);
+
+        $this->assertEquals("http://sws.geonames.org/2988507/", (string)$container[0]['request']->getUri());
+
+    }
+
+    /**
+     * test getLabel
+     */
+    public function testGetLabel6255148() {
+
+        $container = [];
+        $client = $this->getClient(['6255148'], $container);
+
+        $resolver = $this->app->make('CorpusParole\Services\GeonamesResolver', [$client]);
+        $label = $resolver->getLabel('6255148');
+
+        $this->assertEquals('Europe', $label, "Label is Europe");
+
+        $this->assertCount(1, $container);
+
+        $this->assertEquals("http://sws.geonames.org/6255148/", (string)$container[0]['request']->getUri());
+
+    }
+
+
+    /**
+     * test getLabel 404
+     */
+    public function testGetLabel404() {
+        $container = [];
+        $client = $this->getClient(['404'], $container);
+
+        $resolver = $this->app->make('CorpusParole\Services\GeonamesResolver', [$client]);
+
+        $name = $resolver->getLabel('12345');
+
+        $this->assertNull($name);
+        
+        $this->assertCount(1, $container);
+        $this->assertEquals("http://sws.geonames.org/12345/", (string)$container[0]['request']->getUri());
+
+    }
+
+    /**
+     * test getLabel unknown
+     */
+    public function testGetLabelUnknown() {
+        $container = [];
+        $client = $this->getClient(['6255148'], $container);
+
+        $resolver = $this->app->make('CorpusParole\Services\GeonamesResolver', [$client]);
+
+        $name = $resolver->getLabel('12345');
+
+        $this->assertNull($name);
+        
+        $this->assertCount(1, $container);
+        $this->assertEquals("http://sws.geonames.org/12345/", (string)$container[0]['request']->getUri());
+
+    }
+
+    /**
+     * test getLabels
+     */
+    public function testGetLabels() {
+
+        $container = [];
+        $client = $this->getClient(['2968801', '2988507', '6255148'], $container);
+
+        $resolver = $this->app->make('CorpusParole\Services\GeonamesResolver', [$client]);
+        $labels = $resolver->getLabels(['2968801', '2988507', '6255148']);
+
+        $this->assertEquals(['2968801' => 'Villedieu-les-Poêles', '2988507' => 'Paris', '6255148' => 'Europe'] , $labels);
+
+        $this->assertCount(3, $container);
+
+        $this->assertEquals("http://sws.geonames.org/2968801/", (string)$container[0]['request']->getUri());
+        $this->assertEquals("http://sws.geonames.org/2988507/", (string)$container[1]['request']->getUri());
+        $this->assertEquals("http://sws.geonames.org/6255148/", (string)$container[2]['request']->getUri());
+
+    }
+
+    /**
+     * Test exception 401
+     * @expectedException        CorpusParole\Services\GeonamesResolverException
+     * @expectedExceptionMessage Client error: `GET http://sws.geonames.org/12345/` resulted in a `401 Unauthorized` response:
+     * @expectedExceptionCode 401
+     */
+    public function test401Error() {
+        $container = [];
+        $client = $this->getClient(['401'], $container);
+
+        $resolver = $this->app->make('CorpusParole\Services\GeonamesResolver', [$client]);
+
+        $name = $resolver->getLabel('12345');
+    }
+
+
+    /**
+     * Test exception 500
+     * @expectedException        CorpusParole\Services\GeonamesResolverException
+     * @expectedExceptionMessage Server error: `GET http://sws.geonames.org/12345/` resulted in a `500 Internal Server Error` response:
+     * @expectedExceptionCode 500
+     */
+    public function test500Error() {
+        $container = [];
+        $client = $this->getClient(['500'], $container);
+
+        $resolver = $this->app->make('CorpusParole\Services\GeonamesResolver', [$client]);
+
+        $name = $resolver->getLabel('12345');
+    }
+
+    /**
+     * Test exception malformed
+     * @expectedException        CorpusParole\Services\GeonamesResolverException
+     * @expectedExceptionMessage GeonamesId not in correct format
+     * @expectedExceptionCode 400
+     */
+    public function testMalformedError() {
+        $container = [];
+        $client = $this->getClient(['200'], $container);
+
+        $resolver = $this->app->make('CorpusParole\Services\GeonamesResolver', [$client]);
+
+        $name = $resolver->getLabel('abcd');
+    }
+
+
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/Services/files/GeonamesResolverTest/geonames_rdf_2968801.rdf	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<rdf:RDF xmlns:cc="http://creativecommons.org/ns#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:gn="http://www.geonames.org/ontology#" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:wgs84_pos="http://www.w3.org/2003/01/geo/wgs84_pos#">
+<gn:Feature rdf:about="http://sws.geonames.org/2968801/">
+<rdfs:isDefinedBy rdf:resource="http://sws.geonames.org/2968801/about.rdf"/>
+<gn:name>Villedieu-les-Poêles</gn:name>
+<gn:alternateName>Villedieu</gn:alternateName>
+<gn:alternateName xml:lang="kk">Вильдье-ле-Поель</gn:alternateName>
+<gn:alternateName xml:lang="uk">Вільдьє-ле-Поель</gn:alternateName>
+<gn:alternateName xml:lang="zh">维莱迪厄莱波埃莱</gn:alternateName>
+<gn:featureClass rdf:resource="http://www.geonames.org/ontology#P"/>
+<gn:featureCode rdf:resource="http://www.geonames.org/ontology#P.PPL"/>
+<gn:countryCode>FR</gn:countryCode>
+<gn:population>3927</gn:population>
+<gn:postalCode>50800</gn:postalCode>
+<wgs84_pos:lat>48.83333</wgs84_pos:lat>
+<wgs84_pos:long>-1.21667</wgs84_pos:long>
+<gn:parentFeature rdf:resource="http://sws.geonames.org/6613732/"/>
+<gn:parentCountry rdf:resource="http://sws.geonames.org/3017382/"/>
+<gn:parentADM1 rdf:resource="http://sws.geonames.org/11071621/"/>
+<gn:parentADM2 rdf:resource="http://sws.geonames.org/2996268/"/>
+<gn:parentADM3 rdf:resource="http://sws.geonames.org/2978757/"/>
+<gn:parentADM4 rdf:resource="http://sws.geonames.org/6613732/"/>
+<gn:nearbyFeatures rdf:resource="http://sws.geonames.org/2968801/nearby.rdf"/>
+<gn:locationMap rdf:resource="http://www.geonames.org/2968801/villedieu-les-poeles.html"/>
+<gn:wikipediaArticle rdf:resource="http://en.wikipedia.org/wiki/Villedieu-les-Po%C3%AAles"/>
+<rdfs:seeAlso rdf:resource="http://dbpedia.org/resource/Villedieu-les-Po%C3%AAles"/>
+</gn:Feature>
+<foaf:Document rdf:about="http://sws.geonames.org/2968801/about.rdf">
+<foaf:primaryTopic rdf:resource="http://sws.geonames.org/2968801/"/>
+<cc:license rdf:resource="http://creativecommons.org/licenses/by/3.0/"/>
+<cc:attributionURL rdf:resource="http://sws.geonames.org/2968801/"/>
+<cc:attributionName rdf:datatype="http://www.w3.org/2001/XMLSchema#string">GeoNames</cc:attributionName>
+<dcterms:created rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2006-01-15</dcterms:created>
+<dcterms:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-02-18</dcterms:modified>
+</foaf:Document>
+</rdf:RDF>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/Services/files/GeonamesResolverTest/geonames_rdf_2988507.rdf	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<rdf:RDF xmlns:cc="http://creativecommons.org/ns#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:gn="http://www.geonames.org/ontology#" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:wgs84_pos="http://www.w3.org/2003/01/geo/wgs84_pos#">
+<gn:Feature rdf:about="http://sws.geonames.org/2988507/">
+<rdfs:isDefinedBy rdf:resource="http://sws.geonames.org/2988507/about.rdf"/>
+<gn:name>Paris</gn:name>
+<gn:alternateName xml:lang="ja">パリ</gn:alternateName>
+<gn:alternateName xml:lang="ko">파리</gn:alternateName>
+<gn:alternateName xml:lang="am">ፓሪስ</gn:alternateName>
+<gn:alternateName xml:lang="arc">ܦܐܪܝܣ</gn:alternateName>
+<gn:alternateName xml:lang="th">ปารีส</gn:alternateName>
+<gn:alternateName xml:lang="km">ប៉ារីស</gn:alternateName>
+<gn:alternateName xml:lang="so">Baariis</gn:alternateName>
+<gn:alternateName xml:lang="za">Bahliz</gn:alternateName>
+<gn:alternateName xml:lang="tl">Lungsod ng Paris</gn:alternateName>
+<gn:alternateName xml:lang="fr">Lutèce</gn:alternateName>
+<gn:alternateName xml:lang="la">Lutetia</gn:alternateName>
+<gn:alternateName xml:lang="la">Lutetia Parisorum</gn:alternateName>
+<gn:alternateName xml:lang="gv">Paarys</gn:alternateName>
+<gn:alternateName xml:lang="haw">Palika</gn:alternateName>
+<gn:alternateName xml:lang="fr">Paname</gn:alternateName>
+<gn:alternateName xml:lang="fr">Pantruche</gn:alternateName>
+<gn:alternateName xml:lang="lb">Paräis</gn:alternateName>
+<gn:alternateName xml:lang="ga">Páras</gn:alternateName>
+<gn:alternateName xml:lang="ln">Pari</gn:alternateName>
+<gn:alternateName xml:lang="wo">Pari</gn:alternateName>
+<gn:alternateName xml:lang="vi">Pa-ri</gn:alternateName>
+<gn:alternateName xml:lang="gn">Parĩ</gn:alternateName>
+<gn:alternateName xml:lang="mi">Parī</gn:alternateName>
+<gn:alternateName xml:lang="li">Paries</gn:alternateName>
+<gn:alternateName xml:lang="nap">Parigge</gn:alternateName>
+<gn:alternateName xml:lang="lij">Pariggi</gn:alternateName>
+<gn:alternateName xml:lang="scn">Pariggi</gn:alternateName>
+<gn:alternateName xml:lang="co">Parighji</gn:alternateName>
+<gn:alternateName xml:lang="it">Parigi</gn:alternateName>
+<gn:alternateName xml:lang="sc">Parigi</gn:alternateName>
+<gn:alternateName xml:lang="et">Pariis</gn:alternateName>
+<gn:alternateName xml:lang="ha">Pariis</gn:alternateName>
+<gn:alternateName xml:lang="fi">Pariisi</gn:alternateName>
+<gn:alternateName xml:lang="olo">Pariižu</gn:alternateName>
+<gn:alternateName xml:lang="uz">Parij</gn:alternateName>
+<gn:alternateName xml:lang="nl">Parijs</gn:alternateName>
+<gn:alternateName xml:lang="jbo">paris</gn:alternateName>
+<gn:alternateName xml:lang="als">Paris</gn:alternateName>
+<gn:alternateName xml:lang="cy">Paris</gn:alternateName>
+<gn:alternateName xml:lang="da">Paris</gn:alternateName>
+<gn:alternateName xml:lang="de">Paris</gn:alternateName>
+<gn:officialName xml:lang="en">Paris</gn:officialName>
+<gn:alternateName xml:lang="eu">Paris</gn:alternateName>
+<gn:officialName xml:lang="fr">Paris</gn:officialName>
+<gn:alternateName xml:lang="gd">Paris</gn:alternateName>
+<gn:alternateName xml:lang="ia">Paris</gn:alternateName>
+<gn:alternateName xml:lang="id">Paris</gn:alternateName>
+<gn:alternateName xml:lang="io">Paris</gn:alternateName>
+<gn:alternateName xml:lang="ksh">Paris</gn:alternateName>
+<gn:alternateName xml:lang="kw">Paris</gn:alternateName>
+<gn:alternateName xml:lang="lad">Paris</gn:alternateName>
+<gn:alternateName xml:lang="lmo">Paris</gn:alternateName>
+<gn:alternateName xml:lang="mg">Paris</gn:alternateName>
+<gn:alternateName xml:lang="ms">Paris</gn:alternateName>
+<gn:alternateName xml:lang="na">Paris</gn:alternateName>
+<gn:alternateName xml:lang="nds">Paris</gn:alternateName>
+<gn:alternateName xml:lang="nn">Paris</gn:alternateName>
+<gn:alternateName xml:lang="no">Paris</gn:alternateName>
+<gn:alternateName xml:lang="pms">Paris</gn:alternateName>
+<gn:alternateName xml:lang="pt">Paris</gn:alternateName>
+<gn:alternateName xml:lang="ro">Paris</gn:alternateName>
+<gn:alternateName xml:lang="sco">Paris</gn:alternateName>
+<gn:alternateName xml:lang="sq">Paris</gn:alternateName>
+<gn:alternateName xml:lang="sv">Paris</gn:alternateName>
+<gn:alternateName xml:lang="sw">Paris</gn:alternateName>
+<gn:alternateName xml:lang="tl">Paris</gn:alternateName>
+<gn:alternateName xml:lang="tr">Paris</gn:alternateName>
+<gn:alternateName xml:lang="ty">Paris</gn:alternateName>
+<gn:officialName xml:lang="vi">Paris</gn:officialName>
+<gn:alternateName xml:lang="an">París</gn:alternateName>
+<gn:alternateName xml:lang="ast">París</gn:alternateName>
+<gn:alternateName xml:lang="ca">París</gn:alternateName>
+<gn:officialName xml:lang="es">París</gn:officialName>
+<gn:alternateName xml:lang="ext">París</gn:alternateName>
+<gn:alternateName xml:lang="gl">París</gn:alternateName>
+<gn:alternateName xml:lang="is">París</gn:alternateName>
+<gn:alternateName xml:lang="oc">París</gn:alternateName>
+<gn:alternateName xml:lang="tet">París</gn:alternateName>
+<gn:alternateName xml:lang="fur">Parîs</gn:alternateName>
+<gn:alternateName xml:lang="ku">Parîs</gn:alternateName>
+<gn:alternateName xml:lang="sq">Parisi</gn:alternateName>
+<gn:alternateName xml:lang="yo">Parisi</gn:alternateName>
+<gn:alternateName xml:lang="vec">Parixe</gn:alternateName>
+<gn:alternateName xml:lang="br">Pariz</gn:alternateName>
+<gn:alternateName xml:lang="bs">Pariz</gn:alternateName>
+<gn:alternateName xml:lang="hbs">Pariz</gn:alternateName>
+<gn:alternateName xml:lang="hr">Pariz</gn:alternateName>
+<gn:alternateName xml:lang="sl">Pariz</gn:alternateName>
+<gn:alternateName xml:lang="tk">Pariž</gn:alternateName>
+<gn:alternateName xml:lang="sk">Paríž</gn:alternateName>
+<gn:alternateName xml:lang="cs">Paříž</gn:alternateName>
+<gn:alternateName xml:lang="lv">Parīze</gn:alternateName>
+<gn:alternateName xml:lang="eo">Parizo</gn:alternateName>
+<gn:alternateName xml:lang="hu">Párizs</gn:alternateName>
+<gn:alternateName xml:lang="af">Parys</gn:alternateName>
+<gn:alternateName xml:lang="fy">Parys</gn:alternateName>
+<gn:alternateName xml:lang="vls">Parys</gn:alternateName>
+<gn:alternateName xml:lang="pl">Paryż</gn:alternateName>
+<gn:alternateName xml:lang="szl">Paryż</gn:alternateName>
+<gn:alternateName xml:lang="lt">Paryžius</gn:alternateName>
+<gn:alternateName xml:lang="fr">Ville-Lumière</gn:alternateName>
+<gn:alternateName xml:lang="ar">باريس</gn:alternateName>
+<gn:alternateName xml:lang="arz">باريس</gn:alternateName>
+<gn:alternateName xml:lang="ckb">پاریس</gn:alternateName>
+<gn:alternateName xml:lang="fa">پاریس</gn:alternateName>
+<gn:alternateName xml:lang="mzn">پاریس</gn:alternateName>
+<gn:alternateName xml:lang="ug">پارىژ</gn:alternateName>
+<gn:alternateName xml:lang="ps">پاريس</gn:alternateName>
+<gn:alternateName xml:lang="pnb">پیرس</gn:alternateName>
+<gn:alternateName xml:lang="ur">پیرس</gn:alternateName>
+<gn:alternateName xml:lang="yi">פאריז</gn:alternateName>
+<gn:alternateName xml:lang="he">פריז</gn:alternateName>
+<gn:alternateName xml:lang="el">Παρίσι</gn:alternateName>
+<gn:alternateName xml:lang="be">Горад Парыж</gn:alternateName>
+<gn:alternateName xml:lang="ba">Париж</gn:alternateName>
+<gn:alternateName xml:lang="bg">Париж</gn:alternateName>
+<gn:alternateName xml:lang="kk">Париж</gn:alternateName>
+<gn:alternateName xml:lang="krc">Париж</gn:alternateName>
+<gn:alternateName xml:lang="kv">Париж</gn:alternateName>
+<gn:alternateName xml:lang="ky">Париж</gn:alternateName>
+<gn:alternateName xml:lang="mhr">Париж</gn:alternateName>
+<gn:alternateName xml:lang="mrj">Париж</gn:alternateName>
+<gn:alternateName xml:lang="os">Париж</gn:alternateName>
+<gn:alternateName xml:lang="ru">Париж</gn:alternateName>
+<gn:alternateName xml:lang="sah">Париж</gn:alternateName>
+<gn:alternateName xml:lang="tg">Париж</gn:alternateName>
+<gn:alternateName xml:lang="tt">Париж</gn:alternateName>
+<gn:alternateName xml:lang="udm">Париж</gn:alternateName>
+<gn:alternateName xml:lang="uk">Париж</gn:alternateName>
+<gn:alternateName xml:lang="myv">Париж ош</gn:alternateName>
+<gn:alternateName xml:lang="cu">Парижь</gn:alternateName>
+<gn:alternateName xml:lang="mk">Париз</gn:alternateName>
+<gn:alternateName xml:lang="sr">Париз</gn:alternateName>
+<gn:alternateName xml:lang="cv">Парис</gn:alternateName>
+<gn:alternateName xml:lang="mn">Парис</gn:alternateName>
+<gn:alternateName xml:lang="rue">Паріж</gn:alternateName>
+<gn:alternateName xml:lang="bo">ཕ་རི།</gn:alternateName>
+<gn:alternateName xml:lang="hy">Փարիզ</gn:alternateName>
+<gn:alternateName xml:lang="ka">პარიზი</gn:alternateName>
+<gn:alternateName xml:lang="xmf">პარიზი</gn:alternateName>
+<gn:alternateName xml:lang="mr">पॅरिस</gn:alternateName>
+<gn:alternateName xml:lang="ne">पेरिस</gn:alternateName>
+<gn:alternateName xml:lang="hi">पैरिस</gn:alternateName>
+<gn:alternateName xml:lang="gu">પૅરિસ</gn:alternateName>
+<gn:alternateName xml:lang="te">పారిస్</gn:alternateName>
+<gn:alternateName xml:lang="pa">ਪੈਰਿਸ</gn:alternateName>
+<gn:alternateName xml:lang="kn">ಪ್ಯಾರಿಸ್</gn:alternateName>
+<gn:alternateName xml:lang="ta">பாரிஸ்</gn:alternateName>
+<gn:alternateName xml:lang="ml">പാരിസ്</gn:alternateName>
+<gn:alternateName xml:lang="bn">প্যারিস</gn:alternateName>
+<gn:alternateName xml:lang="my">ပါရီမြို့</gn:alternateName>
+<gn:alternateName xml:lang="gan">巴黎</gn:alternateName>
+<gn:alternateName xml:lang="zh">巴黎</gn:alternateName>
+<gn:featureClass rdf:resource="http://www.geonames.org/ontology#P"/>
+<gn:featureCode rdf:resource="http://www.geonames.org/ontology#P.PPLC"/>
+<gn:countryCode>FR</gn:countryCode>
+<gn:population>2138551</gn:population>
+<gn:postalCode>75000</gn:postalCode>
+<gn:postalCode>75020</gn:postalCode>
+<wgs84_pos:lat>48.85341</wgs84_pos:lat>
+<wgs84_pos:long>2.3488</wgs84_pos:long>
+<gn:parentFeature rdf:resource="http://sws.geonames.org/6455259/"/>
+<gn:parentCountry rdf:resource="http://sws.geonames.org/3017382/"/>
+<gn:parentADM1 rdf:resource="http://sws.geonames.org/3012874/"/>
+<gn:parentADM2 rdf:resource="http://sws.geonames.org/2968815/"/>
+<gn:parentADM3 rdf:resource="http://sws.geonames.org/2988506/"/>
+<gn:parentADM4 rdf:resource="http://sws.geonames.org/6455259/"/>
+<gn:nearbyFeatures rdf:resource="http://sws.geonames.org/2988507/nearby.rdf"/>
+<gn:locationMap rdf:resource="http://www.geonames.org/2988507/paris.html"/>
+<gn:wikipediaArticle rdf:resource="http://en.wikipedia.org/wiki/Paris"/>
+<rdfs:seeAlso rdf:resource="http://dbpedia.org/resource/Paris"/>
+<gn:wikipediaArticle rdf:resource="http://uk.wikipedia.org/wiki/%D0%9F%D0%B0%D1%80%D0%B8%D0%B6"/>
+</gn:Feature>
+<foaf:Document rdf:about="http://sws.geonames.org/2988507/about.rdf">
+<foaf:primaryTopic rdf:resource="http://sws.geonames.org/2988507/"/>
+<cc:license rdf:resource="http://creativecommons.org/licenses/by/3.0/"/>
+<cc:attributionURL rdf:resource="http://sws.geonames.org/2988507/"/>
+<cc:attributionName rdf:datatype="http://www.w3.org/2001/XMLSchema#string">GeoNames</cc:attributionName>
+<dcterms:created rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2006-01-15</dcterms:created>
+<dcterms:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-02-18</dcterms:modified>
+</foaf:Document>
+</rdf:RDF>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/Services/files/GeonamesResolverTest/geonames_rdf_6255148.rdf	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<rdf:RDF xmlns:cc="http://creativecommons.org/ns#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:gn="http://www.geonames.org/ontology#" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:wgs84_pos="http://www.w3.org/2003/01/geo/wgs84_pos#">
+<gn:Feature rdf:about="http://sws.geonames.org/6255148/">
+<rdfs:isDefinedBy rdf:resource="http://sws.geonames.org/6255148/about.rdf"/>
+<gn:name>Europe</gn:name>
+<gn:officialName xml:lang="ko">유럽</gn:officialName>
+<gn:alternateName xml:lang="th">ยุโรป</gn:alternateName>
+<gn:alternateName xml:lang="ja">ヨーロッパ</gn:alternateName>
+<gn:alternateName xml:lang="ga">an Eoraip</gn:alternateName>
+<gn:alternateName xml:lang="tr">Avrupa</gn:alternateName>
+<gn:alternateName xml:lang="vi">Châu Âu</gn:alternateName>
+<gn:alternateName xml:lang="lv">Eiropa</gn:alternateName>
+<gn:alternateName xml:lang="es">El viejo continente</gn:alternateName>
+<gn:alternateName xml:lang="id">Eropa</gn:alternateName>
+<gn:alternateName xml:lang="se">Eurohpá</gn:alternateName>
+<gn:officialName xml:lang="et">Euroopa</gn:officialName>
+<gn:alternateName xml:lang="fi">Eurooppa</gn:alternateName>
+<gn:officialName xml:lang="ca">Europa</gn:officialName>
+<gn:alternateName xml:lang="da">Europa</gn:alternateName>
+<gn:alternateName xml:lang="de">Europa</gn:alternateName>
+<gn:officialName xml:lang="es">Europa</gn:officialName>
+<gn:alternateName xml:lang="eu">Europa</gn:alternateName>
+<gn:alternateName xml:lang="it">Europa</gn:alternateName>
+<gn:alternateName xml:lang="la">Europa</gn:alternateName>
+<gn:alternateName xml:lang="lt">Europa</gn:alternateName>
+<gn:alternateName xml:lang="nb">Europa</gn:alternateName>
+<gn:officialName xml:lang="nl">Europa</gn:officialName>
+<gn:alternateName xml:lang="no">Europa</gn:alternateName>
+<gn:alternateName xml:lang="pl">Europa</gn:alternateName>
+<gn:alternateName xml:lang="pt">Europa</gn:alternateName>
+<gn:officialName xml:lang="ro">Europa</gn:officialName>
+<gn:alternateName xml:lang="sv">Europa</gn:alternateName>
+<gn:alternateName xml:lang="hu">Európa</gn:alternateName>
+<gn:officialName xml:lang="sk">Európa</gn:officialName>
+<gn:officialName xml:lang="en">Europe</gn:officialName>
+<gn:alternateName xml:lang="fr">Europe</gn:alternateName>
+<gn:alternateName xml:lang="eo">Eŭropo</gn:alternateName>
+<gn:alternateName xml:lang="bs">Evropa</gn:alternateName>
+<gn:alternateName xml:lang="cs">Evropa</gn:alternateName>
+<gn:alternateName xml:lang="is">Evrópa</gn:alternateName>
+<gn:alternateName xml:lang="cy">Ewrop</gn:alternateName>
+<gn:alternateName xml:lang="ar">أوروبا</gn:alternateName>
+<gn:alternateName xml:lang="he">אירופה</gn:alternateName>
+<gn:alternateName xml:lang="el">Ευρώπη</gn:alternateName>
+<gn:alternateName xml:lang="bg">Европа</gn:alternateName>
+<gn:officialName xml:lang="ru">Европа</gn:officialName>
+<gn:alternateName xml:lang="be">Еўропа</gn:alternateName>
+<gn:alternateName xml:lang="uk">Європа</gn:alternateName>
+<gn:alternateName xml:lang="hi">यूरोप</gn:alternateName>
+<gn:alternateName xml:lang="zh">欧洲</gn:alternateName>
+<gn:featureClass rdf:resource="http://www.geonames.org/ontology#L"/>
+<gn:featureCode rdf:resource="http://www.geonames.org/ontology#L.CONT"/>
+<wgs84_pos:lat>48.69096</wgs84_pos:lat>
+<wgs84_pos:long>9.14062</wgs84_pos:long>
+<gn:parentFeature rdf:resource="http://sws.geonames.org/6295630/"/>
+<gn:childrenFeatures rdf:resource="http://sws.geonames.org/6255148/contains.rdf"/>
+<gn:locationMap rdf:resource="http://www.geonames.org/6255148/europe.html"/>
+<gn:wikipediaArticle rdf:resource="http://en.wikipedia.org/wiki/Europe"/>
+<rdfs:seeAlso rdf:resource="http://dbpedia.org/resource/Europe"/>
+</gn:Feature>
+<foaf:Document rdf:about="http://sws.geonames.org/6255148/about.rdf">
+<foaf:primaryTopic rdf:resource="http://sws.geonames.org/6255148/"/>
+<cc:license rdf:resource="http://creativecommons.org/licenses/by/3.0/"/>
+<cc:attributionURL rdf:resource="http://sws.geonames.org/6255148/"/>
+<cc:attributionName rdf:datatype="http://www.w3.org/2001/XMLSchema#string">GeoNames</cc:attributionName>
+<dcterms:created rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2006-06-15</dcterms:created>
+<dcterms:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-06-01</dcterms:modified>
+</foaf:Document>
+</rdf:RDF>
\ No newline at end of file