[ios] adapt Mapbox Streets–sourced layers for user preferred language (#9582)
* [ios] Update label localization * [ios, macos] Move MGLVectorSource+MBXAdditions.h to darwin. * [ios, macos] Adapt Mapbox Streets to the user preferred language. * [ios, macos] Clarify style localization documentation. * [ios, macos] Update localization examples * [ios, macos] Add style language reset to original. * [ios, macos] Update changelogs. * [ios, macos] Rename Vector Source Additions to MGL standard. * [ios, macos] Add suport for stop localization.
This commit is contained in:
committed by
GitHub
parent
a523b710ac
commit
afd4df9dbc
@@ -610,6 +610,21 @@ MGL_EXPORT
|
||||
*/
|
||||
@property (nonatomic, strong) MGLLight *light;
|
||||
|
||||
#pragma mark Localizing Map Content
|
||||
|
||||
/**
|
||||
A Boolean value that determines whether the style attempts to localize labels in
|
||||
the style into the system’s preferred language.
|
||||
|
||||
When this property is enabled, the style automatically modifies the text property
|
||||
of any symbol style layer whose source is the
|
||||
<a href="https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview">Mapbox
|
||||
Streets source</a>. On iOS, the user can set the system’s preferred language in
|
||||
Settings, General Settings, Language & Region. On macOS, the user can set the
|
||||
system’s preferred language in the Language & Region pane of System Preferences.
|
||||
*/
|
||||
@property (nonatomic) BOOL localizesLabels;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#import "MGLSource.h"
|
||||
#import "MGLTileSource_Private.h"
|
||||
#import "MGLVectorSource.h"
|
||||
#import "MGLVectorSource+MGLAdditions.h"
|
||||
#import "MGLRasterSource.h"
|
||||
#import "MGLShapeSource.h"
|
||||
|
||||
@@ -48,11 +49,34 @@
|
||||
#import "NSImage+MGLAdditions.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
Model class for localization changes.
|
||||
*/
|
||||
@interface MGLTextLanguage: NSObject
|
||||
@property (strong, nonatomic) NSString *originalTextField;
|
||||
@property (strong, nonatomic) NSString *updatedTextField;
|
||||
|
||||
- (instancetype)initWithTextLanguage:(NSString *)originalTextField updatedTextField:(NSString *)updatedTextField;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MGLTextLanguage
|
||||
- (instancetype)initWithTextLanguage:(NSString *)originalTextField updatedTextField:(NSString *)updatedTextField
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_originalTextField = originalTextField;
|
||||
_updatedTextField = updatedTextField;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface MGLStyle()
|
||||
|
||||
@property (nonatomic, readwrite, weak) MGLMapView *mapView;
|
||||
@property (readonly, copy, nullable) NSURL *URL;
|
||||
@property (nonatomic, readwrite, strong) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLOpenGLStyleLayer *) *openGLLayers;
|
||||
@property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, NS_DICTIONARY_OF(NSObject *, MGLTextLanguage *) *) *localizedLayersByIdentifier;
|
||||
|
||||
@end
|
||||
|
||||
@@ -116,6 +140,7 @@ static NSURL *MGLStyleURL_emerald;
|
||||
if (self = [super init]) {
|
||||
_mapView = mapView;
|
||||
_openGLLayers = [NSMutableDictionary dictionary];
|
||||
_localizedLayersByIdentifier = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -609,4 +634,115 @@ static NSURL *MGLStyleURL_emerald;
|
||||
self.URL ? [NSString stringWithFormat:@"\"%@\"", self.URL] : self.URL];
|
||||
}
|
||||
|
||||
#pragma mark Style language preferences
|
||||
|
||||
- (void)setLocalizesLabels:(BOOL)localizesLabels
|
||||
{
|
||||
if (_localizesLabels != localizesLabels) {
|
||||
_localizesLabels = localizesLabels;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_localizesLabels) {
|
||||
NSString *preferredLanguage = [MGLVectorSource preferredMapboxStreetsLanguage];
|
||||
NSMutableDictionary *localizedKeysByKeyBySourceIdentifier = [NSMutableDictionary dictionary];
|
||||
for (MGLSymbolStyleLayer *layer in self.layers) {
|
||||
if (![layer isKindOfClass:[MGLSymbolStyleLayer class]]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MGLVectorSource *source = (MGLVectorSource *)[self sourceWithIdentifier:layer.sourceIdentifier];
|
||||
if (![source isKindOfClass:[MGLVectorSource class]] || !source.mapboxStreets) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NSDictionary *localizedKeysByKey = localizedKeysByKeyBySourceIdentifier[layer.sourceIdentifier];
|
||||
if (!localizedKeysByKey) {
|
||||
localizedKeysByKey = localizedKeysByKeyBySourceIdentifier[layer.sourceIdentifier] = [source localizedKeysByKeyForPreferredLanguage:preferredLanguage];
|
||||
}
|
||||
|
||||
NSString *(^stringByLocalizingString)(NSString *) = ^ NSString * (NSString *string) {
|
||||
NSMutableString *localizedString = string.mutableCopy;
|
||||
[localizedKeysByKey enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull localizedKey, BOOL * _Nonnull stop) {
|
||||
NSAssert([key isKindOfClass:[NSString class]], @"key is not a string");
|
||||
NSAssert([localizedKey isKindOfClass:[NSString class]], @"localizedKey is not a string");
|
||||
[localizedString replaceOccurrencesOfString:[NSString stringWithFormat:@"{%@}", key]
|
||||
withString:[NSString stringWithFormat:@"{%@}", localizedKey]
|
||||
options:0
|
||||
range:NSMakeRange(0, localizedString.length)];
|
||||
}];
|
||||
return localizedString;
|
||||
};
|
||||
|
||||
if ([layer.text isKindOfClass:[MGLConstantStyleValue class]]) {
|
||||
NSString *textField = [(MGLConstantStyleValue<NSString *> *)layer.text rawValue];
|
||||
NSString *localizingString = stringByLocalizingString(textField);
|
||||
if (![textField isEqualToString:localizingString]) {
|
||||
MGLTextLanguage *textLanguage = [[MGLTextLanguage alloc] initWithTextLanguage:textField
|
||||
updatedTextField:localizingString];
|
||||
[self.localizedLayersByIdentifier setObject:@{ textField : textLanguage } forKey:layer.identifier];
|
||||
layer.text = [MGLStyleValue<NSString *> valueWithRawValue:localizingString];
|
||||
}
|
||||
}
|
||||
else if ([layer.text isKindOfClass:[MGLCameraStyleFunction class]]) {
|
||||
MGLCameraStyleFunction *function = (MGLCameraStyleFunction<NSString *> *)layer.text;
|
||||
NSMutableDictionary *stops = function.stops.mutableCopy;
|
||||
NSMutableDictionary *cameraStops = [NSMutableDictionary dictionary];
|
||||
[stops enumerateKeysAndObjectsUsingBlock:^(NSNumber *zoomLevel, MGLConstantStyleValue<NSString *> *stop, BOOL *done) {
|
||||
NSString *textField = stop.rawValue;
|
||||
NSString *localizingString = stringByLocalizingString(textField);
|
||||
if (![textField isEqualToString:localizingString]) {
|
||||
MGLTextLanguage *textLanguage = [[MGLTextLanguage alloc] initWithTextLanguage:textField
|
||||
updatedTextField:localizingString];
|
||||
[cameraStops setObject:textLanguage forKey:zoomLevel];
|
||||
stops[zoomLevel] = [MGLStyleValue<NSString *> valueWithRawValue:localizingString];
|
||||
}
|
||||
|
||||
}];
|
||||
if (cameraStops.count > 0) {
|
||||
[self.localizedLayersByIdentifier setObject:cameraStops forKey:layer.identifier];
|
||||
}
|
||||
function.stops = stops;
|
||||
layer.text = function;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
[self.localizedLayersByIdentifier enumerateKeysAndObjectsUsingBlock:^(NSString *identifier, NSDictionary<NSObject *, MGLTextLanguage *> *textFields, BOOL *done) {
|
||||
MGLSymbolStyleLayer *layer = (MGLSymbolStyleLayer *)[self.mapView.style layerWithIdentifier:identifier];
|
||||
|
||||
if ([layer.text isKindOfClass:[MGLConstantStyleValue class]]) {
|
||||
NSString *textField = [(MGLConstantStyleValue<NSString *> *)layer.text rawValue];
|
||||
[textFields enumerateKeysAndObjectsUsingBlock:^(NSObject *originalLanguage, MGLTextLanguage *textLanguage, BOOL *done) {
|
||||
if ([textLanguage.updatedTextField isEqualToString:textField]) {
|
||||
layer.text = [MGLStyleValue<NSString *> valueWithRawValue:textLanguage.originalTextField];
|
||||
}
|
||||
}];
|
||||
|
||||
}
|
||||
else if ([layer.text isKindOfClass:[MGLCameraStyleFunction class]]) {
|
||||
MGLCameraStyleFunction *function = (MGLCameraStyleFunction<NSString *> *)layer.text;
|
||||
NSMutableDictionary *stops = function.stops.mutableCopy;
|
||||
[textFields enumerateKeysAndObjectsUsingBlock:^(NSObject *zoomKey, MGLTextLanguage *textLanguage, BOOL *done) {
|
||||
if ([zoomKey isKindOfClass:[NSNumber class]]) {
|
||||
NSNumber *zoomLevel = (NSNumber*)zoomKey;
|
||||
MGLConstantStyleValue<NSString *> *stop = [stops objectForKey:zoomLevel];
|
||||
NSString *textField = stop.rawValue;
|
||||
if ([textLanguage.updatedTextField isEqualToString:textField]) {
|
||||
stops[zoomLevel] = [MGLStyleValue<NSString *> valueWithRawValue:textLanguage.originalTextField];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
function.stops = stops;
|
||||
layer.text = function;
|
||||
}
|
||||
|
||||
}];
|
||||
|
||||
self.localizedLayersByIdentifier = [NSMutableDictionary dictionary];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MGLVectorSource (MBXAdditions)
|
||||
@interface MGLVectorSource (MGLAdditions)
|
||||
|
||||
+ (NSString *)preferredMapboxStreetsLanguage;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#import "MGLVectorSource+MBXAdditions.h"
|
||||
#import "MGLVectorSource+MGLAdditions.h"
|
||||
|
||||
@implementation MGLVectorSource (MBXAdditions)
|
||||
@implementation MGLVectorSource (MGLAdditions)
|
||||
|
||||
+ (NS_SET_OF(NSString *) *)mapboxStreetsLanguages {
|
||||
// https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
|
||||
@@ -2,7 +2,11 @@
|
||||
|
||||
Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started.
|
||||
|
||||
## 3.6.1
|
||||
## 3.6.2
|
||||
|
||||
* Added an MGLStyle.localizesLabels property, off by default, that localizes any Mapbox Streets–sourced symbol layer into the user’s preferred language. ([#9582](https://github.com/mapbox/mapbox-gl-native/pull/9582))
|
||||
|
||||
## 3.6.1 - July 28, 2017
|
||||
|
||||
* Reduced the size of the dynamic framework by optimizing symbol visibility. ([#7604](https://github.com/mapbox/mapbox-gl-native/pull/7604))
|
||||
* Fixed an issue where the attribution button would have its custom tint color reset when the map view received a tint color change notification, such as when an alert controller was presented. ([#9598](https://github.com/mapbox/mapbox-gl-native/pull/9598))
|
||||
|
||||
@@ -343,7 +343,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
|
||||
@"Update Shape Source: Features",
|
||||
@"Style Vector Source",
|
||||
@"Style Raster Source",
|
||||
[NSString stringWithFormat:@"Label Countries in %@", (_usingLocaleBasedCountryLabels ? @"Local Language" : [[NSLocale currentLocale] displayNameForKey:NSLocaleIdentifier value:[self bestLanguageForUser]])],
|
||||
[NSString stringWithFormat:@"Show Labels in %@", (_usingLocaleBasedCountryLabels ? @"Local Language" : [[NSLocale currentLocale] displayNameForKey:NSLocaleIdentifier value:[self bestLanguageForUser]])],
|
||||
@"Add Route Line",
|
||||
@"Dynamically Style Polygon",
|
||||
]];
|
||||
@@ -1274,12 +1274,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
|
||||
|
||||
-(void)styleCountryLabelsLanguage
|
||||
{
|
||||
NSArray<NSString *> *labelLayers = @[
|
||||
@"country-label-lg",
|
||||
@"country-label-md",
|
||||
@"country-label-sm",
|
||||
];
|
||||
[self styleLabelLanguageForLayersNamed:labelLayers];
|
||||
_usingLocaleBasedCountryLabels = !_usingLocaleBasedCountryLabels;
|
||||
self.mapView.style.localizesLabels = _usingLocaleBasedCountryLabels;
|
||||
}
|
||||
|
||||
- (void)styleRouteLine
|
||||
@@ -1362,39 +1358,6 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
|
||||
[self.mapView.style addLayer:fillStyleLayer];
|
||||
}
|
||||
|
||||
- (void)styleLabelLanguageForLayersNamed:(NSArray<NSString *> *)layers
|
||||
{
|
||||
_usingLocaleBasedCountryLabels = !_usingLocaleBasedCountryLabels;
|
||||
NSString *bestLanguageForUser = [NSString stringWithFormat:@"{name_%@}", [self bestLanguageForUser]];
|
||||
NSString *language = _usingLocaleBasedCountryLabels ? bestLanguageForUser : @"{name}";
|
||||
|
||||
for (NSString *layerName in layers) {
|
||||
MGLSymbolStyleLayer *layer = (MGLSymbolStyleLayer *)[self.mapView.style layerWithIdentifier:layerName];
|
||||
|
||||
if ([layer isKindOfClass:[MGLSymbolStyleLayer class]]) {
|
||||
if ([layer.text isKindOfClass:[MGLConstantStyleValue class]]) {
|
||||
MGLConstantStyleValue *label = (MGLConstantStyleValue<NSString *> *)layer.text;
|
||||
if ([label.rawValue hasPrefix:@"{name"]) {
|
||||
layer.text = [MGLStyleValue valueWithRawValue:language];
|
||||
}
|
||||
}
|
||||
else if ([layer.text isKindOfClass:[MGLCameraStyleFunction class]]) {
|
||||
MGLCameraStyleFunction *function = (MGLCameraStyleFunction<NSString *> *)layer.text;
|
||||
NSMutableDictionary *stops = function.stops.mutableCopy;
|
||||
[stops enumerateKeysAndObjectsUsingBlock:^(NSNumber *zoomLevel, MGLConstantStyleValue<NSString *> *stop, BOOL *done) {
|
||||
if ([stop.rawValue hasPrefix:@"{name"]) {
|
||||
stops[zoomLevel] = [MGLStyleValue<NSString *> valueWithRawValue:language];
|
||||
}
|
||||
}];
|
||||
function.stops = stops;
|
||||
layer.text = function;
|
||||
}
|
||||
} else {
|
||||
NSLog(@"%@ is not a symbol style layer", layerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)bestLanguageForUser
|
||||
{
|
||||
// https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
1F7454971ECD450D00021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454941ECD450D00021D39 /* MGLLight_Private.h */; };
|
||||
1F7454A91ED08AB400021D39 /* MGLLightTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454A61ED08AB400021D39 /* MGLLightTest.mm */; };
|
||||
1F95931D1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */; };
|
||||
1FB7DAAF1F2A4DBD00410606 /* MGLVectorSource+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FDD9D6D1F26936400252B09 /* MGLVectorSource+MGLAdditions.h */; };
|
||||
1FB7DAB01F2A4DC200410606 /* MGLVectorSource+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FDD9D6D1F26936400252B09 /* MGLVectorSource+MGLAdditions.h */; };
|
||||
1FB7DAB11F2A4DC800410606 /* MGLVectorSource+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FDD9D6E1F26936400252B09 /* MGLVectorSource+MGLAdditions.m */; };
|
||||
1FB7DAB21F2A4DC900410606 /* MGLVectorSource+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FDD9D6E1F26936400252B09 /* MGLVectorSource+MGLAdditions.m */; };
|
||||
30E578171DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578111DAA7D690050F07E /* UIImage+MGLAdditions.h */; };
|
||||
30E578181DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578111DAA7D690050F07E /* UIImage+MGLAdditions.h */; };
|
||||
30E578191DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 30E578121DAA7D690050F07E /* UIImage+MGLAdditions.mm */; };
|
||||
@@ -547,6 +551,8 @@
|
||||
1F7454941ECD450D00021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = "<group>"; };
|
||||
1F7454A61ED08AB400021D39 /* MGLLightTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLLightTest.mm; path = ../../darwin/test/MGLLightTest.mm; sourceTree = "<group>"; };
|
||||
1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLNSDateAdditionsTests.mm; path = ../../darwin/test/MGLNSDateAdditionsTests.mm; sourceTree = "<group>"; };
|
||||
1FDD9D6D1F26936400252B09 /* MGLVectorSource+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLVectorSource+MGLAdditions.h"; sourceTree = "<group>"; };
|
||||
1FDD9D6E1F26936400252B09 /* MGLVectorSource+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLVectorSource+MGLAdditions.m"; sourceTree = "<group>"; };
|
||||
20DABE861DF78148007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Foundation.strings"; sourceTree = "<group>"; };
|
||||
20DABE881DF78148007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
20DABE8A1DF78149007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Root.strings"; sourceTree = "<group>"; };
|
||||
@@ -1537,6 +1543,8 @@
|
||||
DAD165831CF4CFED001FF4B9 /* Categories */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1FDD9D6D1F26936400252B09 /* MGLVectorSource+MGLAdditions.h */,
|
||||
1FDD9D6E1F26936400252B09 /* MGLVectorSource+MGLAdditions.m */,
|
||||
7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */,
|
||||
7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */,
|
||||
7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */,
|
||||
@@ -1642,6 +1650,7 @@
|
||||
350098DC1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */,
|
||||
DA8848231CBAFA6200AB86E3 /* MGLOfflineStorage_Private.h in Headers */,
|
||||
404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */,
|
||||
1FB7DAAF1F2A4DBD00410606 /* MGLVectorSource+MGLAdditions.h in Headers */,
|
||||
DA88483B1CBAFB8500AB86E3 /* MGLCalloutView.h in Headers */,
|
||||
35E0CFE61D3E501500188327 /* MGLStyle_Private.h in Headers */,
|
||||
3510FFF01D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */,
|
||||
@@ -1819,6 +1828,7 @@
|
||||
35136D4D1D4277FC00C20EFD /* MGLSource.h in Headers */,
|
||||
DA35A2BC1CCA9A6900E826B2 /* MGLClockDirectionFormatter.h in Headers */,
|
||||
35D13AC41D3D19DD00AFB4E0 /* MGLFillStyleLayer.h in Headers */,
|
||||
1FB7DAB01F2A4DC200410606 /* MGLVectorSource+MGLAdditions.h in Headers */,
|
||||
DABFB86E1CBE9A0F00D62B32 /* MGLCalloutView.h in Headers */,
|
||||
1F7454971ECD450D00021D39 /* MGLLight_Private.h in Headers */,
|
||||
DABFB8601CBE99E500D62B32 /* MGLMapCamera.h in Headers */,
|
||||
@@ -2197,6 +2207,7 @@
|
||||
9620BB3A1E69FE1700705A1D /* MGLSDKUpdateChecker.mm in Sources */,
|
||||
354B83981D2E873E005D9406 /* MGLUserLocationAnnotationView.m in Sources */,
|
||||
DA88485D1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.m in Sources */,
|
||||
1FB7DAB11F2A4DC800410606 /* MGLVectorSource+MGLAdditions.m in Sources */,
|
||||
DAD165701CF41981001FF4B9 /* MGLFeature.mm in Sources */,
|
||||
30E578191DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */,
|
||||
40EDA1C11CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */,
|
||||
@@ -2279,6 +2290,7 @@
|
||||
9620BB3B1E69FE1700705A1D /* MGLSDKUpdateChecker.mm in Sources */,
|
||||
DAA4E4221CBB730400178DFB /* MGLPointAnnotation.mm in Sources */,
|
||||
DAED38661D62D0FC00D7640F /* NSURL+MGLAdditions.m in Sources */,
|
||||
1FB7DAB21F2A4DC900410606 /* MGLVectorSource+MGLAdditions.m in Sources */,
|
||||
DAD165711CF41981001FF4B9 /* MGLFeature.mm in Sources */,
|
||||
30E5781A1DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */,
|
||||
40EDA1C21CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */,
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Changelog for Mapbox macOS SDK
|
||||
|
||||
## 0.5.1
|
||||
|
||||
* Added an MGLStyle.localizesLabels property, off by default, that localizes any Mapbox Streets–sourced symbol layer into the user’s preferred language. ([#9582](https://github.com/mapbox/mapbox-gl-native/pull/9582))
|
||||
|
||||
## 0.5.0
|
||||
|
||||
This version of the Mapbox macOS SDK corresponds to version 3.6.0 of the Mapbox iOS SDK.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#import "DroppedPinAnnotation.h"
|
||||
|
||||
#import "MGLStyle+MBXAdditions.h"
|
||||
#import "MGLVectorSource+MBXAdditions.h"
|
||||
#import "MGLVectorSource+MGLAdditions.h"
|
||||
|
||||
#import <Mapbox/Mapbox.h>
|
||||
|
||||
@@ -344,52 +344,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
|
||||
}
|
||||
|
||||
- (void)updateLabels {
|
||||
MGLStyle *style = self.mapView.style;
|
||||
NSString *preferredLanguage = _isLocalizingLabels ? [MGLVectorSource preferredMapboxStreetsLanguage] : nil;
|
||||
NSMutableDictionary *localizedKeysByKeyBySourceIdentifier = [NSMutableDictionary dictionary];
|
||||
for (MGLSymbolStyleLayer *layer in style.layers) {
|
||||
if (![layer isKindOfClass:[MGLSymbolStyleLayer class]]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MGLVectorSource *source = (MGLVectorSource *)[style sourceWithIdentifier:layer.sourceIdentifier];
|
||||
if (![source isKindOfClass:[MGLVectorSource class]] || !source.mapboxStreets) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NSDictionary *localizedKeysByKey = localizedKeysByKeyBySourceIdentifier[layer.sourceIdentifier];
|
||||
if (!localizedKeysByKey) {
|
||||
localizedKeysByKey = localizedKeysByKeyBySourceIdentifier[layer.sourceIdentifier] = [source localizedKeysByKeyForPreferredLanguage:preferredLanguage];
|
||||
}
|
||||
|
||||
NSString *(^stringByLocalizingString)(NSString *) = ^ NSString * (NSString *string) {
|
||||
NSMutableString *localizedString = string.mutableCopy;
|
||||
[localizedKeysByKey enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull localizedKey, BOOL * _Nonnull stop) {
|
||||
NSAssert([key isKindOfClass:[NSString class]], @"key is not a string");
|
||||
NSAssert([localizedKey isKindOfClass:[NSString class]], @"localizedKey is not a string");
|
||||
[localizedString replaceOccurrencesOfString:[NSString stringWithFormat:@"{%@}", key]
|
||||
withString:[NSString stringWithFormat:@"{%@}", localizedKey]
|
||||
options:0
|
||||
range:NSMakeRange(0, localizedString.length)];
|
||||
}];
|
||||
return localizedString;
|
||||
};
|
||||
|
||||
if ([layer.text isKindOfClass:[MGLConstantStyleValue class]]) {
|
||||
NSString *textField = [(MGLConstantStyleValue<NSString *> *)layer.text rawValue];
|
||||
layer.text = [MGLStyleValue<NSString *> valueWithRawValue:stringByLocalizingString(textField)];
|
||||
}
|
||||
else if ([layer.text isKindOfClass:[MGLCameraStyleFunction class]]) {
|
||||
MGLCameraStyleFunction *function = (MGLCameraStyleFunction<NSString *> *)layer.text;
|
||||
NSMutableDictionary *stops = function.stops.mutableCopy;
|
||||
[stops enumerateKeysAndObjectsUsingBlock:^(NSNumber *zoomLevel, MGLConstantStyleValue<NSString *> *stop, BOOL *done) {
|
||||
NSString *textField = stop.rawValue;
|
||||
stops[zoomLevel] = [MGLStyleValue<NSString *> valueWithRawValue:stringByLocalizingString(textField)];
|
||||
}];
|
||||
function.stops = stops;
|
||||
layer.text = function;
|
||||
}
|
||||
}
|
||||
self.mapView.style.localizesLabels = _isLocalizingLabels;
|
||||
}
|
||||
|
||||
- (void)applyPendingState {
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
1F7454A51ECFB00300021D39 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454A21ECFB00300021D39 /* MGLLight.mm */; };
|
||||
1F7454AB1ED1DDBD00021D39 /* MGLLightTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454AA1ED1DDBD00021D39 /* MGLLightTest.mm */; };
|
||||
1F95931B1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F95931A1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm */; };
|
||||
1FCDF1421F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FCDF1401F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.h */; };
|
||||
1FCDF1431F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FCDF1411F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.m */; };
|
||||
30E5781B1DAA857E0050F07E /* NSImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578141DAA7D920050F07E /* NSImage+MGLAdditions.h */; };
|
||||
3508EC641D749D39009B0EE4 /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3508EC621D749D39009B0EE4 /* NSExpression+MGLAdditions.h */; };
|
||||
3508EC651D749D39009B0EE4 /* NSExpression+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3508EC631D749D39009B0EE4 /* NSExpression+MGLAdditions.mm */; };
|
||||
@@ -233,7 +235,6 @@
|
||||
DAEDC4371D606291000224FF /* MGLAttributionButtonTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEDC4361D606291000224FF /* MGLAttributionButtonTests.m */; };
|
||||
DAF0D80E1DFE0E5D00B28378 /* MGLPointCollection_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D80D1DFE0E5D00B28378 /* MGLPointCollection_Private.h */; };
|
||||
DAF0D8161DFE6B1800B28378 /* MGLAttributionInfo_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8151DFE6B1800B28378 /* MGLAttributionInfo_Private.h */; };
|
||||
DAF0D81C1DFF567C00B28378 /* MGLVectorSource+MBXAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DAF0D81B1DFF567C00B28378 /* MGLVectorSource+MBXAdditions.m */; };
|
||||
DD0902B21DB1AC6400C5BDCE /* MGLNetworkConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0902AF1DB1AC6400C5BDCE /* MGLNetworkConfiguration.m */; };
|
||||
DD0902B31DB1AC6400C5BDCE /* MGLNetworkConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DD0902B01DB1AC6400C5BDCE /* MGLNetworkConfiguration.h */; };
|
||||
DD58A4C91D822C6700E1F038 /* MGLExpressionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DD58A4C71D822C6200E1F038 /* MGLExpressionTests.mm */; };
|
||||
@@ -277,6 +278,8 @@
|
||||
1F7454A21ECFB00300021D39 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = "<group>"; };
|
||||
1F7454AA1ED1DDBD00021D39 /* MGLLightTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLightTest.mm; sourceTree = "<group>"; };
|
||||
1F95931A1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLNSDateAdditionsTests.mm; path = ../../darwin/test/MGLNSDateAdditionsTests.mm; sourceTree = "<group>"; };
|
||||
1FCDF1401F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLVectorSource+MGLAdditions.h"; sourceTree = "<group>"; };
|
||||
1FCDF1411F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLVectorSource+MGLAdditions.m"; sourceTree = "<group>"; };
|
||||
30E578141DAA7D920050F07E /* NSImage+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSImage+MGLAdditions.h"; path = "src/NSImage+MGLAdditions.h"; sourceTree = SOURCE_ROOT; };
|
||||
3508EC621D749D39009B0EE4 /* NSExpression+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSExpression+MGLAdditions.h"; sourceTree = "<group>"; };
|
||||
3508EC631D749D39009B0EE4 /* NSExpression+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSExpression+MGLAdditions.mm"; sourceTree = "<group>"; };
|
||||
@@ -568,8 +571,6 @@
|
||||
DAEDC4361D606291000224FF /* MGLAttributionButtonTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLAttributionButtonTests.m; sourceTree = "<group>"; };
|
||||
DAF0D80D1DFE0E5D00B28378 /* MGLPointCollection_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPointCollection_Private.h; sourceTree = "<group>"; };
|
||||
DAF0D8151DFE6B1800B28378 /* MGLAttributionInfo_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo_Private.h; sourceTree = "<group>"; };
|
||||
DAF0D81A1DFF567C00B28378 /* MGLVectorSource+MBXAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLVectorSource+MBXAdditions.h"; sourceTree = "<group>"; };
|
||||
DAF0D81B1DFF567C00B28378 /* MGLVectorSource+MBXAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLVectorSource+MBXAdditions.m"; sourceTree = "<group>"; };
|
||||
DAFBD0D51E3FA969000CD6BF /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
DAFBD0D61E3FA983000CD6BF /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Foundation.strings"; sourceTree = "<group>"; };
|
||||
DD0902AF1DB1AC6400C5BDCE /* MGLNetworkConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLNetworkConfiguration.m; sourceTree = "<group>"; };
|
||||
@@ -740,8 +741,6 @@
|
||||
DA839E9E1CC2E3400062CAFB /* MapDocument.xib */,
|
||||
DACB0C371E18DFFD005DDBEA /* MGLStyle+MBXAdditions.h */,
|
||||
DACB0C381E18DFFD005DDBEA /* MGLStyle+MBXAdditions.m */,
|
||||
DAF0D81A1DFF567C00B28378 /* MGLVectorSource+MBXAdditions.h */,
|
||||
DAF0D81B1DFF567C00B28378 /* MGLVectorSource+MBXAdditions.m */,
|
||||
DAE6C2E91CC3050F00DB3429 /* OfflinePackNameValueTransformer.h */,
|
||||
DAE6C2EA1CC3050F00DB3429 /* OfflinePackNameValueTransformer.m */,
|
||||
DAA48EFB1D6A4731006A7E36 /* StyleLayerIconTransformer.h */,
|
||||
@@ -920,6 +919,8 @@
|
||||
DAD1657F1CF4CF50001FF4B9 /* Categories */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1FCDF1401F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.h */,
|
||||
1FCDF1411F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.m */,
|
||||
408AA8601DAEED3300022900 /* MGLPolygon+MGLAdditions.h */,
|
||||
408AA85C1DAEED3300022900 /* MGLPolygon+MGLAdditions.m */,
|
||||
408AA8611DAEED3300022900 /* MGLPolyline+MGLAdditions.h */,
|
||||
@@ -1154,6 +1155,7 @@
|
||||
DAE6C3601CC31E0400DB3429 /* MGLOfflineRegion.h in Headers */,
|
||||
DAE6C3681CC31E0400DB3429 /* MGLTilePyramidOfflineRegion.h in Headers */,
|
||||
DA35A2CF1CCAAED300E826B2 /* NSValue+MGLAdditions.h in Headers */,
|
||||
1FCDF1421F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.h in Headers */,
|
||||
DAE6C3A61CC31E9400DB3429 /* MGLMapViewDelegate.h in Headers */,
|
||||
DAE6C38B1CC31E2A00DB3429 /* MGLOfflinePack_Private.h in Headers */,
|
||||
558DE7A61E56161C00C7916D /* MGLFoundation_Private.h in Headers */,
|
||||
@@ -1378,7 +1380,6 @@
|
||||
DACB0C391E18DFFD005DDBEA /* MGLStyle+MBXAdditions.m in Sources */,
|
||||
DA839E9A1CC2E3400062CAFB /* main.m in Sources */,
|
||||
DA839E971CC2E3400062CAFB /* AppDelegate.m in Sources */,
|
||||
DAF0D81C1DFF567C00B28378 /* MGLVectorSource+MBXAdditions.m in Sources */,
|
||||
DAE6C2F01CC3050F00DB3429 /* OfflinePackNameValueTransformer.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -1394,6 +1395,7 @@
|
||||
40B77E461DB11BCD003DA2FE /* NSArray+MGLAdditions.mm in Sources */,
|
||||
DAE6C38C1CC31E2A00DB3429 /* MGLOfflinePack.mm in Sources */,
|
||||
35D65C5B1D65AD5500722C23 /* NSDate+MGLAdditions.mm in Sources */,
|
||||
1FCDF1431F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.m in Sources */,
|
||||
DD0902B21DB1AC6400C5BDCE /* MGLNetworkConfiguration.m in Sources */,
|
||||
1F7454A51ECFB00300021D39 /* MGLLight.mm in Sources */,
|
||||
DAE6C3B11CC31EF300DB3429 /* MGLAnnotationImage.m in Sources */,
|
||||
|
||||
Reference in New Issue
Block a user