Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

No localized low-zoom labels when system language is Simplified Chinese #12164

Closed
1ec5 opened this issue Jun 18, 2018 · 7 comments
Closed

No localized low-zoom labels when system language is Simplified Chinese #12164

1ec5 opened this issue Jun 18, 2018 · 7 comments
Assignees
Labels
bug iOS Mapbox Maps SDK for iOS localization Human language support and internationalization macOS Mapbox Maps SDK for macOS

Comments

@1ec5
Copy link
Contributor

1ec5 commented Jun 18, 2018

When the system language is set to Simplified Chinese, labels of countries, states and provinces, and oceans and seas disappear instead of being localized into Simplified Chinese. This is because +[MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:] assumes all Streets source layers offer the same languages. In fact, this documentation says (in a rather confusing way) that name_zh-Hans is unavailable for the country_label, state_label, and marine_label layers.

The language fallback logic being added for #11867 could address this issue, but a more targeted fix would involve special-casing these three source layers.

/ref #11867
/cc @friedbunny @nickidlugash @langsmith

@1ec5 1ec5 added bug iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS localization Human language support and internationalization labels Jun 18, 2018
@lilykaiser
Copy link

@lloydsheng do you have time to investigate this? cc @chriswu42

@lloydsheng
Copy link
Contributor

@lilykaiser Happy to help investigate this issue. cc @suntony

@lloydsheng lloydsheng self-assigned this Jul 4, 2018
@lloydsheng
Copy link
Contributor

@1ec5 I checked the tile data, These layers did have no name_zh-Hans field.

country_label marine_label state_label
image image image

My initial thought was that can we add the name_zh-Hans field to those layers from the data side? If can't, I have 2 options to fix it from SDK side.

  1. Check the layer when setting layer's text, if it is one of country_label, state_label,marine_label, then check the localizedText expression, fallback to name_zh if it is name_zh-Han.

  2. As we have the expression now, we could add a logic with the expression to check all the name field, fallback to name_zh if it is name_zh-Han and the value of it is empty.

@julianrex @1ec5 Glad to hear your thougts about this.

@1ec5
Copy link
Contributor Author

1ec5 commented Jul 13, 2018

My initial thought was that can we add the name_zh-Hans field to those layers from the data side?

Unfortunately, GL doesn’t currently support adding fields to vector tiles at runtime. (This is a concept sometimes called “data join”.) Better to alias one field with another in the expressions instead.

Check the layer when setting layer's text, if it is one of country_label, state_label,marine_label, then check the localizedText expression, fallback to name_zh if it is name_zh-Han.

The navigation SDK has similar logic that determines the locale to pass into -[NSExpression mgl_expressionLocalizedIntoLocale:] based on the layer’s source layer identifier.

The special case would have to live in -[MGLStyle localizeLabelsIntoLocale:], because -[NSExpression mgl_expressionLocalizedIntoLocale:] doesn’t know the current source name’s locale (and giving it that context would make little sense and would break backwards compatibility). If we put the special case in -[MGLStyle localizeLabelsIntoLocale:], then the caller of -[NSExpression mgl_expressionLocalizedIntoLocale:] is responsible for making sure the locale is appropriate for the current layer.

As we have the expression now, we could add a logic with the expression to check all the name field, fallback to name_zh if it is name_zh-Han and the value of it is empty.

The fallback could be implemented by wrapping key path expressions in mgl_coalesce() functions. This is the more robust approach. We need to take this approach anyways for #11867, since all the name_ fields in Streets source v8 are optional. The tricky part is that localizing the style a second time would needlessly complicate the expression. Localizing an already localized expression with the same locale could turn:

NSExpression(format: "mgl_coalesce({name_zh-Hans, name_zh})")

into:

NSExpression(format: """
    mgl_coalesce({
        mgl_coalesce({name_zh-Hans, name_zh}),
        mgl_coalesce({name_zh-Hans, name_zh})
    })
    """)

With a different locale the second time, it would become:

NSExpression(format: """
    mgl_coalesce({
        name_en,
        name_en
    })
    """)

If we could positively identify a coalescing expression as the result of an existing localization operation, then we might be able to replace the expression instead of more deeply nesting it, somewhere around here:

NSArray *arguments = self.arguments;
NSArray *localizedArguments = MGLLocalizedCollection(arguments, locale);
if (localizedArguments != arguments) {
return [NSExpression expressionForFunction:localizedOperand
selectorName:self.function
arguments:localizedArguments];
}
if (localizedOperand != operand) {
return [NSExpression expressionForFunction:localizedOperand
selectorName:self.function
arguments:self.arguments];
}

@lloydsheng
Copy link
Contributor

lloydsheng commented Jul 16, 2018

@1ec5 Thanks for your feedback 👍. I've pushed some changes to fix this issue #12387. I think it also made the SDK compatible with name fields of Mapbox Streets v8.

/cc @chriswu42 @suntony

@1ec5
Copy link
Contributor Author

1ec5 commented Jul 24, 2018

If we could positively identify a coalescing expression as the result of an existing localization operation, then we might be able to replace the expression instead of more deeply nesting it

We could append a dummy key path expression to the end of the coalescing array, something like com.mapbox.expressions.localized. Right around here, before localizing the arguments, we could check whether the dummy key path appears in the coalescing expression:

NSArray *localizedArguments = MGLLocalizedCollection(arguments, locale);

If it does, then we can replace the expression with a new localized one instead of relocalizing the existing expression (which would cause it to become more deeply nested):

NSExpression *localizedCoalescingExpressionMarker = [NSExpression expressionForKeyPath:@"com.mapbox.expressions.localized"];

if ([self.function isEqualToString:@"mgl_coalesce:"]) {
    // Check if the coalescing expression was the result of previously localizing an expression.
    NSArray *coalescedExpressions = (NSArray *)self.arguments.firstObject;
    if ([coalescedExpressions isKindOfClass:[NSArray array]] &&
        [coalescedExpressions.lastObject isEqual:localizedCoalescingExpressionMarker]) {
        // If so, replace the expression instead of relocalizing it.
        return [[NSExpression expressionForKeyPath:@"name"]
                mgl_expressionLocalizedIntoLocale:locale];
    }
}

NSArray *localizedArguments = MGLLocalizedCollection(arguments, locale);
//

@1ec5
Copy link
Contributor Author

1ec5 commented Aug 1, 2018

Fixed in #12387.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug iOS Mapbox Maps SDK for iOS localization Human language support and internationalization macOS Mapbox Maps SDK for macOS
Projects
None yet
Development

No branches or pull requests

3 participants