How to Localize a Map
- API or service
- Map Tiles + MapLibre GL
- Task
- Language preference → localized map labels
- Examples
- Difficulty
- Intermediate
- Time
- 10 min
Your application has users in one or more languages and needs map labels that match their language preference. With a style-based MapLibre map, label text is rendered from feature properties and can be changed without requesting a separate raster image for every language.
Localization is more than replacing every label. Some features may not have a name in the requested language, so the map needs a predictable fallback. The application should also preserve the chosen language when it changes the complete map style.
Plan map-label localization
Before changing label layers, decide:
- Language code: Use the language selected in the application rather than assuming it from the browser on every map update.
- Fallback order: Prefer
name:<language>, then a broadly readable name such asname:latin, and finally the defaultnamevalue. - Affected layers: Change text layers that display geographic names. Do not overwrite symbol layers used only for route shields, house numbers, or application data.
- Style changes: Reapply localization after calling
map.setStyle(), because the new style creates a new set of basemap layers. - Scripts and fonts: Test languages with non-Latin and right-to-left scripts and ensure that the style’s glyphs and renderer support them.
Raster map labels are part of the tile image and cannot be changed by MapLibre or Leaflet after the tile is downloaded. Use a style-based map when runtime label localization is required.
Localize and switch map labels with MapLibre GL
The function below finds symbol layers whose text expression refers to a name and replaces their text field with a localized expression. coalesce keeps a readable fallback when a translation is missing.
function localizeMap(language) {
const localizedName = [
"coalesce",
["get", `name:${language}`],
["get", "name:latin"],
["get", "name"]
];
for (const layer of map.getStyle().layers) {
const textField = layer.layout?.["text-field"];
const displaysName = JSON.stringify(textField || "").includes("name");
if (layer.type === "symbol" && textField && displaysName) {
map.setLayoutProperty(layer.id, "text-field", localizedName);
}
}
}
map.on("load", () => localizeMap("de"));
document.querySelector("#map-language").addEventListener("change", event => {
localizeMap(event.target.value);
});
The language selector can provide codes such as en, de, fr, or uk. If the application also switches full styles, call localizeMap() again from the new style’s style.load event.
Review the selected style’s label layers before production use. A product may intentionally keep international names for some layers while localizing cities, streets, and points of interest.