mapbox-maps-ios icon indicating copy to clipboard operation
mapbox-maps-ios copied to clipboard

Unable to Change Map Language: localizeLabels(into:forLayerIds:) Method Not Working

Open Savva-Shuliatev opened this issue 1 year ago • 4 comments

Environment

  • Xcode version: Version 16.2 (16C5032a)
  • iOS version: 18+
  • Devices affected: All
  • Maps SDK Version: 11.9.0

Observed behavior and steps to reproduce

localizeLabels(into:forLayerIds:) Method Not Working

Simplest example:

import UIKit
import Combine
import MapboxMaps

class ViewController: UIViewController {

  private lazy var mapView = MapView(frame: .zero)

  private var cancellables: Set<AnyCancellable> = []

  override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(mapView)
    mapView.frame = view.bounds

    preconditionFailure("Set your accessToken!")
    MapboxOptions.accessToken = ""

    mapView.mapboxMap.onMapLoaded.observe { [weak self] _ in
      /// https://docs.mapbox.com/help/troubleshooting/change-language/#mapbox-maps-sdk-for-ios
      try! self!.mapView.mapboxMap.localizeLabels(into: Locale(identifier: "ar"))
      /// No effect
    }
    .store(in: &cancellables)
  }

}

Expected behavior

Based on the documentation, I expect a change in language. https://docs.mapbox.com/help/troubleshooting/change-language/#mapbox-maps-sdk-for-ios

Additional links and references

Demo project with bug https://github.com/Savva-Shuliatev/Mapbox-localization-bug

Savva-Shuliatev avatar Jan 09 '25 18:01 Savva-Shuliatev

I found an alternative solution with setting the language:

let locale = Locale.preferredLanguages.first ?? "en" // Updated
let settingsService = SettingsServiceFactory.getInstance(storageType: .persistent)
switch settingsService.set(key: MapboxCommonSettings.language, value: locale) {
case .success:
 print("Successfully set MapboxCommonSettings.language \(locale)")
case .failure(let error):
 assertionFailure("Failed to set MapboxCommonSettings.language with error: \(error)")
}

This works in my project and in the demo project. https://github.com/Savva-Shuliatev/Mapbox-localization-bug Thanks to the following article: https://www.mapbox.com/blog/maps-internationalization-34-languages

But, How safe is it to use this approach?

Updated:

⚠️ Be careful: Use a valid language/locale code for Mapbox (e.g., "en", "en-US"). Avoid Locale.current or full string representations (e.g., "en_DE (current)") — they can break styles (blank map, missing labels) and trigger errors like:

[Mapbox] [Warning, maps-core]: ... ?language=en_DE (current): unsupported URL(4)
[Mapbox] [Error, maps-core/style]: Failed to load source composite: unsupported URL

Savva-Shuliatev avatar Jan 09 '25 23:01 Savva-Shuliatev

Hi @Savva-Shuliatev --

Thanks for the report. You are correct that .localizeLabels() does not work for Mapbox Standard (our default style) or Mapbox Satellite Standard. We have an open issue for this here that you can use to follow updates. In short, Mapbox Standard introduced a new basemap approach that changed how layers are handled at runtime. As you've identified, this means that the .localizeLabels() approach to translating map labels does not work for these styles.

If translation using .localizeLabels() is important for your project, I recommend creating a style based on one of our classic styles, such as Mapbox Streets.

The alternative approach you identified here using MapboxCommonSettings remains in preview so we do not recommend it for production applications.

pjleonard37 avatar Jan 10 '25 20:01 pjleonard37

Hi @Savva-Shuliatev.

Locale from your snippet could produce string like "en_DE (current)" which breaks the map styles as it doesn't follow the expected format .

Map becomes blank – no style is applied, no labels shown. I got errors like these:

[Mapbox] [Warning, maps-core]: Errored respose from network for mapbox://mapbox.mapbox-streets-v8,mapbox.mapbox-terrain-v2,mapbox.mapbox-bathymetry-v2?language=en_DE (current): unsupported URL(4)
[Mapbox] [Error, maps-core/style]: Failed to load source composite: unsupported URL

But, setting locale like this seems to fix the issue:

let locale = Locale.preferredLanguages.first ?? "en"
let settingsService = SettingsServiceFactory.getInstance(storageType: .persistent)
_ = settingsService.set(key: MapboxCommonSettings.language, value: locale)

kirylkarabeika avatar Oct 03 '25 17:10 kirylkarabeika

Locale from your snippet could produce string like "en_DE (current)" which breaks the map styles as it doesn't follow the expected format .

Hi @kirylkarabeika Thanks for your report! I’ve updated my comment with an alternative solution and a demo project.

Savva-Shuliatev avatar Oct 05 '25 10:10 Savva-Shuliatev