Change a map's language
Replicates the MapLibre example Change a map’s language. The labels being translated belong to the basemap style, which the document references but does not author. Rewriting their text-field is therefore runtime work: the buttons in a corner slot point every symbol layer that reads a name at name:<lang>, falling back to the local name.
The YAML half
Section titled “The YAML half”# yaml-language-server: $schema=https://docs.maplibre-yaml.org/schema/latest/map.schema.json# Gallery twin of https://maplibre.org/maplibre-gl-js/docs/examples/change-a-maps-language/# The YAML half: just the map. The labels being translated belong to the# BASEMAP style, which the document references but does not author, so# rewriting their text-field is runtime work — see change-a-maps-language.js.# (Labels a document authors itself could read a `global-state` language# key instead, driven by an enum parameter with no JS at all.)type: mapid: change-a-maps-languageconfig: center: [16.05, 48] zoom: 2.9 mapStyle: "https://tiles.openfreemap.org/styles/bright"The page half
Section titled “The page half”This markup goes inside <ml-map>; children with a slot ride its corner system.
<div slot="top-left" class="gallery-panel" data-languages> <button type="button" data-lang="fr">French</button> <button type="button" data-lang="ru">Russian</button> <button type="button" data-lang="de">German</button> <button type="button" data-lang="es">Spanish</button></div>The JavaScript half
Section titled “The JavaScript half”// The JavaScript half: setLayoutProperty on the basemap's own label layers.// Every symbol layer whose text-field reads a name is pointed at// `name:<lang>`, falling back to the local name where a feature has no// translation (upstream patches three country-label layers by id; this// works on any OpenMapTiles-schema basemap).const mapEl = document.querySelector("ml-map");
document.querySelector("[data-languages]").addEventListener("click", async (e) => { const lang = e.target.closest("[data-lang]")?.dataset.lang; if (!lang) return; const map = await mapEl.mapReady(); for (const layer of map.getStyle().layers) { if (layer.type !== "symbol") continue; const field = map.getLayoutProperty(layer.id, "text-field"); if (field && JSON.stringify(field).includes("name")) { map.setLayoutProperty(layer.id, "text-field", [ "coalesce", ["get", `name:${lang}`], ["get", "name"], ]); } }});What to notice
Section titled “What to notice”- Upstream patches three country-label layers by id; checking each symbol layer’s
text-fieldfor a name works on any OpenMapTiles-schema basemap. - Labels the document authors itself need no JS: a
text-fieldreading["get", ["concat", "name:", ["global-state", "lang"]]]plus an enum parameter does it declaratively.