summaryrefslogtreecommitdiff
path: root/platform/darwin/src/MGLStyle.mm
diff options
context:
space:
mode:
Diffstat (limited to 'platform/darwin/src/MGLStyle.mm')
-rw-r--r--platform/darwin/src/MGLStyle.mm136
1 files changed, 136 insertions, 0 deletions
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index eb838085d7..1e0a2e02b7 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -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