Creating a localized map app

In this tutorial we extend the map app codesample to display a localized map based on vector tiles from PTV Developer.

Showing a localized map in a browser

All supported languages are listed in the Languages concepts. Localized labels are available for countries, cities, roads, buildings and backgrounds. This example will show how to display multi names by displaying two lines with the localized label and the original label below.

HTML code

As an example we provide a simple index.html file where we instantiate the MapBox renderer and set the displayed language. Use MARC country codes in lower case to display the desired language:

<!DOCTYPE html> <html> <head> <meta charset='utf-8' /> <title>Mapbox GL JS Examples</title> <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> <script type="text/javascript" src="https://unpkg.com/maplibre-gl@1.15.2/dist/maplibre-gl.js"></script> <link rel="stylesheet" type="text/css" href="https://unpkg.com/maplibre-gl@1.15.2/dist/maplibre-gl.css"> <style> body { margin:0; padding:0; } #map { position:absolute; top:0; bottom:0; width:100%; } </style> </head> <body> <div id='map'></div> <script> maplibregl.setRTLTextPlugin( 'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.2.3/mapbox-gl-rtl-text.js', null, true // Lazy load the plugin ); var apiKey = 'YOUR_API_KEY'; var map = new maplibregl.Map({ attributionControl: true, customAttribution: '&copy; 2021 PTV AG, HERE', container: 'map', zoom: 11, pitch: 0, minZoom: 2, center: [8.4055677, 49.0070036], antialias: true, hash: true, // you can also use our standard style "https://vectormaps-resources.myptv.com/styles/latest/standard.json" style: "https://<your_servername>/style.json", transformRequest: (url, resourceType) => { if (resourceType === 'Tile' && url.startsWith('https://api.myptv.com')) { return { url: url + '?apiKey=' + apiKey } } } }); map.addControl(new maplibregl.NavigationControl()); var showMultiNames = true; //use the desired language code based on MARC country codes in lower case. //a list of supported languages can be found here: https://developer.myptv.com/Documentation/Vector%20Maps%20API/Concepts/Languages.htm var language = "eng"; map.on('styledata', function() { alterNames(); }); function setMapProperty(labelName) { map.setLayoutProperty(labelName, 'text-field', ['case', ['==', ['get', 'country_language_code'], ['upcase', language]], ['get', 'name'], ['==', ['get', 'name'], ['get','name_' + language]], // if names are same, show only one ['get', 'name'], ['==', ['get','name_' + language], null], // ['case', ['!=', ['get','name_trans'], null], ['format', ['get','name_trans'], { 'font-scale': 1.0 }, '\n', ['get', 'name'], { 'font-scale': 0.8, 'text-font': ['literal', ['Noto Sans Italic']] } ], ['get', 'name'] ], ['!=', ['get','name_' + language], null], ['format', ['get','name_' + language], { 'font-scale': 1.0 }, '\n', ['get', 'name'], { 'font-scale': 0.8, 'text-font': ['literal', ['Noto Sans Italic']] } ], ['get', 'name']]); // fallback } function alterNames() { // Use setLayoutProperty to set the value of a layout property in a style layer. // The three arguments are the id of the layer, the name of the layout property, // and the new property value. if(language == "nat") { map.setLayoutProperty('LBL_Country_Big', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_Country_Medium', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_Country_Small', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMajorCapital', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMinorCapital', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMajorVeryLarge', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMinorVeryLarge', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMajorLarge', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMinorLarge', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMajorMedium', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMinorMedium', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMajorSmall', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMinorSmall', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMajorVillage', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_CityMinorVillage', 'text-field', ['get', 'name']); map.setLayoutProperty('LBL_Hamlet', 'text-field', ['get', 'name']); map.setLayoutProperty('TSP_RoadResidential_Label', 'text-field', ['get', 'street_name']); map.setLayoutProperty('TSP_RoadLocal_Label', 'text-field', ['get', 'street_name']); map.setLayoutProperty('TSP_RoadArterial_Label', 'text-field', ['get', 'street_name']); map.setLayoutProperty('TSP_RoadFederal_Label', 'text-field', ['get', 'street_name']); map.setLayoutProperty('TSP_RoadHighway_Label', 'text-field', ['get', 'street_name']); map.setLayoutProperty('TSP_RoadFerry_Label', 'text-field', ['get', 'ferry_name']); } else if(language == "trans") { map.setLayoutProperty('TSP_RoadResidential_Label', 'text-field', ['coalesce',['get','street_name_trans'],['get', 'street_name']]); map.setLayoutProperty('TSP_RoadLocal_Label', 'text-field', ['coalesce',['get','street_name_trans'],['get', 'street_name']]); map.setLayoutProperty('TSP_RoadArterial_Label', 'text-field', ['coalesce',['get','street_name_trans'],['get', 'street_name']]); map.setLayoutProperty('TSP_RoadFederal_Label', 'text-field', ['coalesce',['get','street_name_trans'],['get', 'street_name']]); map.setLayoutProperty('TSP_RoadHighway_Label', 'text-field', ['coalesce',['get','street_name_trans'],['get', 'street_name']]); map.setLayoutProperty('TSP_RoadFerry_Label', 'text-field', ['coalesce',['get','ferry_name_trans'],['get', 'ferry_name']]); map.setLayoutProperty('LBL_CityMajorCapital', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorCapital', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMajorVeryLarge', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorVeryLarge', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMajorLarge', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorLarge', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMajorMedium', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorMedium', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMajorSmall', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorSmall', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMajorVillage', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorVillage', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_Hamlet', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_Country_Big', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_Country_Medium', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_Country_Small', 'text-field', ['coalesce',['get','name_trans'],['get', 'name']]); } else { if(showMultiNames) { setMapProperty('LBL_CityMajorCapital'); setMapProperty('LBL_CityMinorCapital'); setMapProperty('LBL_CityMajorVeryLarge'); setMapProperty('LBL_CityMinorVeryLarge'); setMapProperty('LBL_CityMajorLarge'); setMapProperty('LBL_CityMinorLarge'); setMapProperty('LBL_CityMajorMedium'); setMapProperty('LBL_CityMinorMedium'); setMapProperty('LBL_CityMajorSmall'); setMapProperty('LBL_CityMinorSmall'); setMapProperty('LBL_CityMajorVillage'); setMapProperty('LBL_CityMinorVillage'); setMapProperty('LBL_Hamlet'); } else { map.setLayoutProperty('LBL_CityMajorCapital', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorCapital', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMajorVeryLarge', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorVeryLarge', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMajorLarge', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorLarge', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMajorMedium', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorMedium', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMajorSmall', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorSmall', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMajorVillage', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_CityMinorVillage', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_Hamlet', 'text-field', ['coalesce',['get','name_' + language],['get', 'name_trans'],['get', 'name']]); } map.setLayoutProperty('TSP_RoadResidential_Label', 'text-field', ['coalesce',['get','street_name_' + language],['get', 'street_name_trans'],['get', 'street_name']]); map.setLayoutProperty('TSP_RoadLocal_Label', 'text-field', ['coalesce',['get','street_name_' + language],['get', 'street_name_trans'],['get', 'street_name']]); map.setLayoutProperty('TSP_RoadArterial_Label', 'text-field', ['coalesce',['get','street_name_' + language],['get', 'street_name_trans'],['get', 'street_name']]); map.setLayoutProperty('TSP_RoadFederal_Label', 'text-field', ['coalesce',['get','street_name_' + language],['get', 'street_name_trans'],['get', 'street_name']]); map.setLayoutProperty('TSP_RoadHighway_Label', 'text-field', ['coalesce',['get','street_name_' + language],['get', 'street_name_trans'],['get', 'street_name']]); map.setLayoutProperty('TSP_RoadFerry_Label', 'text-field', ['coalesce',['get','ferry_name_' + language],['get', 'ferry_name_trans' ],['get', 'ferry_name' ]]); map.setLayoutProperty('LBL_Country_Big', 'text-field', ['coalesce',['get','name_' + language],['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_Country_Medium', 'text-field', ['coalesce',['get','name_' + language],['get','name_trans'],['get', 'name']]); map.setLayoutProperty('LBL_Country_Small', 'text-field', ['coalesce',['get','name_' + language],['get','name_trans'],['get', 'name']]); } } map.addControl(new maplibregl.GeolocateControl({ positionOptions: { enableHighAccuracy: true }, trackUserLocation: true }) ); </script> </body> </html>