Skip to content

Reimplement label localization atop Expression#2933

Closed
1ec5 wants to merge 1 commit into
release-v2.0from
1ec5-label-l10n
Closed

Reimplement label localization atop Expression#2933
1ec5 wants to merge 1 commit into
release-v2.0from
1ec5-label-l10n

Conversation

@1ec5
Copy link
Copy Markdown
Contributor

@1ec5 1ec5 commented Apr 15, 2021

Restored the NavigationMapView.localizeLabels() implementation for automatically localizing map labels into the user’s language. The previous implementation was removed as part of upgrading to map SDK v10 in #2808, because it relied on an NSExpression-based localization feature in map SDK v6.x, which has been replaced by a new Expression type system. This PR ports map SDK v6.x’s NSExpression-based localization feature to Expression as part of MapboxNavigation, in anticipation of a more cross-platform solution in future versions of the map SDK. Note that this implementation continues to differ from map SDK v6.x’s default behavior, in that road labels remain unlocalized by design.

More to come:

  • Port NSExpression-based localization to Expression (and from Objective-C to Swift)
  • Add support for localizing formatted expressions
  • Port MGLVectorStyleLayer-based localizable layer discovery to VectorLayer
  • Port NSExpression tests to Expression

/cc @mapbox/navigation-ios @mapbox/maps-ios-reviewers

Ported the NSExpression-based label localization in map SDK v6.x to Expression.
@1ec5 1ec5 added op-ex Refactoring, Tech Debt or any other operational excellence work. topic: localization labels Apr 15, 2021
@1ec5 1ec5 requested review from MaximAlien and ShanMa1991 April 15, 2021 01:21
@1ec5 1ec5 self-assigned this Apr 15, 2021
let streetsSourceIdentifiers: [String] = mapView.streetsSources().map { $0.id }

for layerInfo in layers where layerInfo.type == "symbol" {
guard var layer = try? mapView.style.getLayer(with: layerInfo.id, type: SymbolLayer.self).get(),
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This call fails on styles that set text-field to a formatted expression, such as Streets and Navigation Day: mapbox/mapbox-maps-ios#268. Unfortunately, the label localization feature has no effect in these styles.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per mapbox/mapbox-maps-ios#268 (comment), the bug is fixed in v2.0.0-beta.17.

@1ec5 1ec5 added this to the v2.0.0 (RC) milestone Apr 15, 2021
@1ec5 1ec5 added blocked Blocked by dependency or unclarity. release blocker Needs to be resolved before the release. and removed blocked Blocked by dependency or unclarity. labels Apr 15, 2021

navigationMapView.mapView.on(.styleLoaded, handler: { [weak self] _ in
guard let self = self else { return }
self.navigationMapView.localizeLabels()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were also calling localizeLabels() in RouteMapViewController, CarPlayMapViewController and CarPlayNavigationViewController in 1.x.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is still being called in RouteMapViewController, CarPlayMapViewController, and CarPlayNavigationViewController, but it must’ve fallen out of the example application by accident.

@@ -1,5 +1,11 @@
import MapboxMaps

extension VectorSource {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we move this VectorSource extension into VectorSource.swift?

Returns a boolean value indicating whether the tile source is a supported version of the Mapbox Streets source.
*/
func isMapboxStreets(_ identifiers: [String]) -> Bool {
return identifiers.contains("mapbox.mapbox-streets-v8") || identifiers.contains("mapbox.mapbox-streets-v7")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: IMO storing identifiers in array would be more agile. In some places we have too many or comparisons.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These methods were moved from RouteMapViewController. We’ll need to keep an eye on #2902, which also moves them elsewhere.

This might be a good opportunity to drop support for Mapbox Streets v7. We supported both versions of the Streets source initially as a migration path, but I don’t think we need to do so long-term.


let localizedTextField = textField.localized(into: locale)
if localizedTextField != textField {
layer.layout?.textField = .expression(localizedTextField)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this update work as expected? I thought that preferred way to update layers would be to call Style.updateLayer(id:type:update:).

Comment on lines +54 to +59
let preferences: [String]
if let identifier = locale?.identifier {
preferences = [identifier]
} else {
preferences = Locale.preferredLanguages
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd just set default value for preferences instead of introducing else statement.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s a matter of style, but in general, I prefer to minimize usage of local variables as much as possible to avoid mutability surprises further down in the code, even though it’s slightly more verbose.

}

func localized(into locale: Locale?) -> Expression {
switch elements.first {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This usage is now broken as of MapboxMaps v2.0.0-beta.18: mapbox/mapbox-maps-ios#299.

@1ec5 1ec5 marked this pull request as draft May 4, 2021 15:36
@bamx23
Copy link
Copy Markdown
Contributor

bamx23 commented Sep 1, 2021

Is this one still a release blocker?

@1ec5
Copy link
Copy Markdown
Contributor Author

1ec5 commented Sep 7, 2021

This proof of concept has run its course. The map SDK once again comes with a built-in label localization feature that the navigation SDK can hook into: #3330. The map SDK is missing some functionality that was included in this PR, but there are separate issues to track that work.

@1ec5 1ec5 closed this Sep 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked Blocked by dependency or unclarity. op-ex Refactoring, Tech Debt or any other operational excellence work. release blocker Needs to be resolved before the release. topic: localization

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants