diff --git a/Makefile b/Makefile index ff80bb32748..2e09e99d9e8 100644 --- a/Makefile +++ b/Makefile @@ -60,6 +60,14 @@ test-osx: osx node_modules/express -configuration $(BUILDTYPE) \ -workspace $(OSX_WORK_PATH) -scheme CI test | xcpretty +genstrings: + genstrings -u -o platform/osx/sdk/Base.lproj platform/darwin/src/*.{m,mm} + genstrings -u -o platform/osx/sdk/Base.lproj platform/osx/src/*.{m,mm} + genstrings -u -o platform/ios/resources/Base.lproj platform/ios/src/*.{m,mm} + mv platform/osx/sdk/Base.lproj/Foundation.strings platform/darwin/resources/Base.lproj/ + -find platform/{darwin,ios,osx}/ -path '*/Base.lproj/*.strings' -exec \ + textutil -convert txt -extension strings -inputencoding UTF-16 -encoding UTF-8 {} \; + #### iOS targets ############################################################## IOS_OUTPUT_PATH = build/ios @@ -101,17 +109,14 @@ test-ios: ios ipackage: $(IOS_PROJ_PATH) BITCODE=$(BITCODE) FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=$(SYMBOLS) \ - BUNDLE_RESOURCES=YES PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK=YES \ ./platform/ios/scripts/package.sh ipackage-strip: $(IOS_PROJ_PATH) BITCODE=$(BITCODE) FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=NO \ - BUNDLE_RESOURCES=YES PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK=YES \ ./platform/ios/scripts/package.sh ipackage-sim: $(IOS_PROJ_PATH) BUILDTYPE=Debug BITCODE=$(BITCODE) FORMAT=dynamic BUILD_DEVICE=false SYMBOLS=$(SYMBOLS) \ - BUNDLE_RESOURCES=YES PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK=YES \ ./platform/ios/scripts/package.sh iframework: $(IOS_PROJ_PATH) @@ -119,7 +124,7 @@ iframework: $(IOS_PROJ_PATH) ./platform/ios/scripts/package.sh ifabric: $(IOS_PROJ_PATH) - BITCODE=$(BITCODE) FORMAT=static BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=NO BUNDLE_RESOURCES=YES \ + BITCODE=$(BITCODE) FORMAT=static BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=NO SELF_CONTAINED=YES \ ./platform/ios/scripts/package.sh idocument: diff --git a/platform/darwin/resources/Base.lproj/Foundation.strings b/platform/darwin/resources/Base.lproj/Foundation.strings new file mode 100644 index 00000000000..9d63dfa6970 --- /dev/null +++ b/platform/darwin/resources/Base.lproj/Foundation.strings @@ -0,0 +1,291 @@ +/* Clock position format, long: {hours} o’clock */ +"CLOCK_FMT_LONG" = "%@ o’clock"; + +/* Clock position format, medium: {hours} o’clock */ +"CLOCK_FMT_MEDIUM" = "%@ o’clock"; + +/* Clock position format, short: {hours}:00 */ +"CLOCK_FMT_SHORT" = "%@:00"; + +/* East, long */ +"COMPASS_E_LONG" = "east"; + +/* East, short */ +"COMPASS_E_SHORT" = "E"; + +/* East by north, long */ +"COMPASS_EbN_LONG" = "east by north"; + +/* East by north, short */ +"COMPASS_EbN_SHORT" = "EbN"; + +/* East by south, long */ +"COMPASS_EbS_LONG" = "east by south"; + +/* East by south, short */ +"COMPASS_EbS_SHORT" = "EbS"; + +/* East-northeast, long */ +"COMPASS_ENE_LONG" = "east-northeast"; + +/* East-northeast, short */ +"COMPASS_ENE_SHORT" = "ENE"; + +/* East-southeast, long */ +"COMPASS_ESE_LONG" = "east-southeast"; + +/* East-southeast, short */ +"COMPASS_ESE_SHORT" = "ESE"; + +/* North, long */ +"COMPASS_N_LONG" = "north"; + +/* North, short */ +"COMPASS_N_SHORT" = "N"; + +/* North by east, long */ +"COMPASS_NbE_LONG" = "north by east"; + +/* North by east, short */ +"COMPASS_NbE_SHORT" = "NbE"; + +/* North by west, long */ +"COMPASS_NbW_LONG" = "north by west"; + +/* North by west, short */ +"COMPASS_NbW_SHORT" = "NbW"; + +/* Northeast, long */ +"COMPASS_NE_LONG" = "northeast"; + +/* Northeast, short */ +"COMPASS_NE_SHORT" = "NE"; + +/* Northeast by east, long */ +"COMPASS_NEbE_LONG" = "northeast by east"; + +/* Northeast by east, short */ +"COMPASS_NEbE_SHORT" = "NEbE"; + +/* Northeast by north, long */ +"COMPASS_NEbN_LONG" = "northeast by north"; + +/* Northeast by north, short */ +"COMPASS_NEbN_SHORT" = "NEbN"; + +/* North-northeast, long */ +"COMPASS_NNE_LONG" = "north-northeast"; + +/* North-northeast, short */ +"COMPASS_NNE_SHORT" = "NNE"; + +/* North-northwest, long */ +"COMPASS_NNW_LONG" = "north-northwest"; + +/* North-northwest, short */ +"COMPASS_NNW_SHORT" = "NNW"; + +/* Northwest, long */ +"COMPASS_NW_LONG" = "northwest"; + +/* Northwest, short */ +"COMPASS_NW_SHORT" = "NW"; + +/* Northwest by north, long */ +"COMPASS_NWbN_LONG" = "northwest by north"; + +/* Northwest by north, short */ +"COMPASS_NWbN_SHORT" = "NWbN"; + +/* Northwest by west, long */ +"COMPASS_NWbW_LONG" = "northwest by west"; + +/* Northwest by west, short */ +"COMPASS_NWbW_SHORT" = "NWbW"; + +/* South, long */ +"COMPASS_S_LONG" = "south"; + +/* South, short */ +"COMPASS_S_SHORT" = "S"; + +/* South by east, long */ +"COMPASS_SbE_LONG" = "south by east"; + +/* South by east, short */ +"COMPASS_SbE_SHORT" = "SbE"; + +/* South by west, long */ +"COMPASS_SbW_LONG" = "south by west"; + +/* South by west, short */ +"COMPASS_SbW_SHORT" = "SbW"; + +/* Southeast, long */ +"COMPASS_SE_LONG" = "southeast"; + +/* Southeast, short */ +"COMPASS_SE_SHORT" = "SE"; + +/* Southeast by east, long */ +"COMPASS_SEbE_LONG" = "southeast by east"; + +/* Southeast by east, short */ +"COMPASS_SEbE_SHORT" = "SEbE"; + +/* Southeast by south, long */ +"COMPASS_SEbS_LONG" = "southeast by south"; + +/* Southeast by south, short */ +"COMPASS_SEbS_SHORT" = "SEbS"; + +/* South-southeast, long */ +"COMPASS_SSE_LONG" = "south-southeast"; + +/* South-southeast, short */ +"COMPASS_SSE_SHORT" = "SSE"; + +/* South-southwest, long */ +"COMPASS_SSW_LONG" = "south-southwest"; + +/* South-southwest, short */ +"COMPASS_SSW_SHORT" = "SSW"; + +/* Southwest, long */ +"COMPASS_SW_LONG" = "southwest"; + +/* Southwest, short */ +"COMPASS_SW_SHORT" = "SW"; + +/* Southwest by south, long */ +"COMPASS_SWbS_LONG" = "southwest by south"; + +/* Southwest by south, short */ +"COMPASS_SWbS_SHORT" = "SWbS"; + +/* Southwest by west, long */ +"COMPASS_SWbW_LONG" = "southwest by west"; + +/* Southwest by west, short */ +"COMPASS_SWbW_SHORT" = "SWbW"; + +/* West, long */ +"COMPASS_W_LONG" = "west"; + +/* West, short */ +"COMPASS_W_SHORT" = "W"; + +/* West by north, long */ +"COMPASS_WbN_LONG" = "west by north"; + +/* West by north, short */ +"COMPASS_WbN_SHORT" = "WbN"; + +/* West by south, long */ +"COMPASS_WbS_LONG" = "west by south"; + +/* West by south, short */ +"COMPASS_WbS_SHORT" = "WbS"; + +/* West-northwest, long */ +"COMPASS_WNW_LONG" = "west-northwest"; + +/* West-northwest, short */ +"COMPASS_WNW_SHORT" = "WNW"; + +/* West-southwest, long */ +"COMPASS_WSW_LONG" = "west-southwest"; + +/* West-southwest, short */ +"COMPASS_WSW_SHORT" = "WSW"; + +/* Degrees format, long */ +"COORD_DEG_LONG" = "%d degree(s)"; + +/* Degrees format, medium: {degrees} */ +"COORD_DEG_MEDIUM" = "%d°"; + +/* Degrees format, short: {degrees} */ +"COORD_DEG_SHORT" = "%d°"; + +/* Coordinate format, long: {degrees}{minutes} */ +"COORD_DM_LONG" = "%1$@ and %2$@"; + +/* Coordinate format, medium: {degrees}{minutes} */ +"COORD_DM_MEDIUM" = "%1$@%2$@"; + +/* Coordinate format, short: {degrees}{minutes} */ +"COORD_DM_SHORT" = "%1$@%2$@"; + +/* Coordinate format, long: {degrees}{minutes}{seconds} */ +"COORD_DMS_LONG" = "%1$@, %2$@, and %3$@"; + +/* Coordinate format, medium: {degrees}{minutes}{seconds} */ +"COORD_DMS_MEDIUM" = "%1$@%2$@%3$@"; + +/* Coordinate format, short: {degrees}{minutes}{seconds} */ +"COORD_DMS_SHORT" = "%1$@%2$@%3$@"; + +/* East longitude format, long: {longitude} */ +"COORD_E_LONG" = "%@ east"; + +/* East longitude format, medium: {longitude} */ +"COORD_E_MEDIUM" = "%@ east"; + +/* East longitude format, short: {longitude} */ +"COORD_E_SHORT" = "%@E"; + +/* Coordinate pair format, long: {latitude}, {longitude} */ +"COORD_FMT_LONG" = "%1$@ by %2$@"; + +/* Coordinate pair format, medium: {latitude}, {longitude} */ +"COORD_FMT_MEDIUM" = "%1$@, %2$@"; + +/* Coordinate pair format, short: {latitude}, {longitude} */ +"COORD_FMT_SHORT" = "%1$@, %2$@"; + +/* Minutes format, long */ +"COORD_MIN_LONG" = "%d minute(s)"; + +/* Minutes format, medium: {minutes} */ +"COORD_MIN_MEDIUM" = "%d′"; + +/* Minutes format, short: {minutes} */ +"COORD_MIN_SHORT" = "%d′"; + +/* North latitude format, long: {latitude} */ +"COORD_N_LONG" = "%@ north"; + +/* North latitude format, medium: {latitude} */ +"COORD_N_MEDIUM" = "%@ north"; + +/* North latitude format, short: {latitude} */ +"COORD_N_SHORT" = "%@N"; + +/* South latitude format, long: {latitude} */ +"COORD_S_LONG" = "%@ south"; + +/* South latitude format, medium: {latitude} */ +"COORD_S_MEDIUM" = "%@ south"; + +/* South latitude format, short: {latitude} */ +"COORD_S_SHORT" = "%@S"; + +/* Seconds format, long */ +"COORD_SEC_LONG" = "%d second(s)"; + +/* Seconds format, medium: {seconds} */ +"COORD_SEC_MEDIUM" = "%d″"; + +/* Seconds format, short: {seconds} */ +"COORD_SEC_SHORT" = "%d″"; + +/* West longitude format, long: {longitude} */ +"COORD_W_LONG" = "%@ west"; + +/* West longitude format, medium: {longitude} */ +"COORD_W_MEDIUM" = "%@ west"; + +/* West longitude format, short: {longitude} */ +"COORD_W_SHORT" = "%@W"; + diff --git a/platform/darwin/resources/en.lproj/Foundation.stringsdict b/platform/darwin/resources/en.lproj/Foundation.stringsdict new file mode 100644 index 00000000000..5f23fff93b3 --- /dev/null +++ b/platform/darwin/resources/en.lproj/Foundation.stringsdict @@ -0,0 +1,54 @@ + + + + + COORD_DEG_LONG + + NSStringLocalizedFormatKey + %#@degrees@ + degrees + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d degree + other + %d degrees + + + COORD_MIN_LONG + + NSStringLocalizedFormatKey + %#@minutes@ + minutes + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d minute + other + %d minutes + + + COORD_SEC_LONG + + NSStringLocalizedFormatKey + %#@seconds@ + seconds + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d second + other + %d seconds + + + + diff --git a/platform/darwin/src/MGLClockDirectionFormatter.h b/platform/darwin/src/MGLClockDirectionFormatter.h index e748a158473..e467b20e06c 100644 --- a/platform/darwin/src/MGLClockDirectionFormatter.h +++ b/platform/darwin/src/MGLClockDirectionFormatter.h @@ -25,13 +25,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic) NSFormattingUnitStyle unitStyle; -/** - The locale of the receiver. - - The locale determines the output language and numeral system of the output. - */ -@property (copy) NSLocale *locale; - /** Returns a clock position string for the provided value. diff --git a/platform/darwin/src/MGLClockDirectionFormatter.m b/platform/darwin/src/MGLClockDirectionFormatter.m index 56740e74e37..c8c07487bac 100644 --- a/platform/darwin/src/MGLClockDirectionFormatter.m +++ b/platform/darwin/src/MGLClockDirectionFormatter.m @@ -1,5 +1,7 @@ #import "MGLClockDirectionFormatter.h" +#import "NSBundle+MGLAdditions.h" + #define wrap(value, min, max) \ (fmod((fmod((value - min), (max - min)) + (max - min)), (max - min)) + min) @@ -11,41 +13,31 @@ - (instancetype)init { if (self = [super init]) { _unitStyle = NSFormattingUnitStyleMedium; _numberFormatter = [[NSNumberFormatter alloc] init]; + _numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; } return self; } -- (NSLocale *)locale { - return _numberFormatter.locale; -} - -- (void)setLocale:(NSLocale *)locale { - _numberFormatter.locale = locale; -} - - (NSString *)stringFromDirection:(CLLocationDirection)direction { NSInteger hour = round(-wrap(-direction, -360, 0) / 360 * 12); NSString *format; - NSNumberFormatterStyle style = NSNumberFormatterDecimalStyle; switch (self.unitStyle) { case NSFormattingUnitStyleShort: - format = NSLocalizedString(@"%@:00", @"Clock position format, short style"); + format = NSLocalizedStringWithDefaultValue(@"CLOCK_FMT_SHORT", @"Foundation", nil, @"%@:00", @"Clock position format, short: {hours}:00"); break; case NSFormattingUnitStyleMedium: - format = NSLocalizedString(@"%@ o’clock", @"Clock position format, medium style"); + format = NSLocalizedStringWithDefaultValue(@"CLOCK_FMT_MEDIUM", @"Foundation", nil, @"%@ o’clock", @"Clock position format, medium: {hours} o’clock"); break; case NSFormattingUnitStyleLong: - format = NSLocalizedString(@"%@ o’clock", @"Clock position format, long style"); - style = NSNumberFormatterSpellOutStyle; + format = NSLocalizedStringWithDefaultValue(@"CLOCK_FMT_LONG", @"Foundation", nil, @"%@ o’clock", @"Clock position format, long: {hours} o’clock"); break; default: break; } - _numberFormatter.numberStyle = style; return [NSString stringWithFormat:format, [_numberFormatter stringFromNumber:@(hour)]]; } diff --git a/platform/darwin/src/MGLCompassDirectionFormatter.m b/platform/darwin/src/MGLCompassDirectionFormatter.m index efda5705a4c..8a4118ba555 100644 --- a/platform/darwin/src/MGLCompassDirectionFormatter.m +++ b/platform/darwin/src/MGLCompassDirectionFormatter.m @@ -1,5 +1,7 @@ #import "MGLCompassDirectionFormatter.h" +#import "NSBundle+MGLAdditions.h" + #define wrap(value, min, max) \ (fmod((fmod((value - min), (max - min)) + (max - min)), (max - min)) + min) @@ -18,79 +20,79 @@ - (NSString *)stringFromDirection:(CLLocationDirection)direction { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ shortStrings = @[ - NSLocalizedString(@"N", @"North, short"), - NSLocalizedString(@"N×E", @"North by east, short"), - NSLocalizedString(@"NNE", @"North-northeast, short"), - NSLocalizedString(@"NE×N", @"Northeast by north, short"), - NSLocalizedString(@"NE", @"Northeast, short"), - NSLocalizedString(@"NE×E", @"Northeast by east, short"), - NSLocalizedString(@"ENE", @"East-northeast, short"), - NSLocalizedString(@"E×N", @"East by north, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_N_SHORT", @"Foundation", nil, @"N", @"North, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NbE_SHORT", @"Foundation", nil, @"NbE", @"North by east, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NNE_SHORT", @"Foundation", nil, @"NNE", @"North-northeast, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NEbN_SHORT", @"Foundation", nil, @"NEbN", @"Northeast by north, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NE_SHORT", @"Foundation", nil, @"NE", @"Northeast, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NEbE_SHORT", @"Foundation", nil, @"NEbE", @"Northeast by east, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_ENE_SHORT", @"Foundation", nil, @"ENE", @"East-northeast, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_EbN_SHORT", @"Foundation", nil, @"EbN", @"East by north, short"), - NSLocalizedString(@"E", @"East, short"), - NSLocalizedString(@"E×S", @"East by south, short"), - NSLocalizedString(@"ESE", @"East-southeast, short"), - NSLocalizedString(@"SE×E", @"Southeast by east, short"), - NSLocalizedString(@"SE", @"Southeast, short"), - NSLocalizedString(@"SE×S", @"Southeast by south, short"), - NSLocalizedString(@"SSE", @"South-southeast, short"), - NSLocalizedString(@"S×E", @"South by east, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_E_SHORT", @"Foundation", nil, @"E", @"East, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_EbS_SHORT", @"Foundation", nil, @"EbS", @"East by south, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_ESE_SHORT", @"Foundation", nil, @"ESE", @"East-southeast, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SEbE_SHORT", @"Foundation", nil, @"SEbE", @"Southeast by east, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SE_SHORT", @"Foundation", nil, @"SE", @"Southeast, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SEbS_SHORT", @"Foundation", nil, @"SEbS", @"Southeast by south, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SSE_SHORT", @"Foundation", nil, @"SSE", @"South-southeast, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SbE_SHORT", @"Foundation", nil, @"SbE", @"South by east, short"), - NSLocalizedString(@"S", @"South, short"), - NSLocalizedString(@"S×W", @"South by west, short"), - NSLocalizedString(@"SSW", @"South-southwest, short"), - NSLocalizedString(@"SW×S", @"Southwest by south, short"), - NSLocalizedString(@"SW", @"Southwest, short"), - NSLocalizedString(@"SW×W", @"Southwest by west, short"), - NSLocalizedString(@"WSW", @"West-southwest, short"), - NSLocalizedString(@"W×S", @"West by south, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_S_SHORT", @"Foundation", nil, @"S", @"South, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SbW_SHORT", @"Foundation", nil, @"SbW", @"South by west, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SSW_SHORT", @"Foundation", nil, @"SSW", @"South-southwest, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SWbS_SHORT", @"Foundation", nil, @"SWbS", @"Southwest by south, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SW_SHORT", @"Foundation", nil, @"SW", @"Southwest, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SWbW_SHORT", @"Foundation", nil, @"SWbW", @"Southwest by west, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_WSW_SHORT", @"Foundation", nil, @"WSW", @"West-southwest, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_WbS_SHORT", @"Foundation", nil, @"WbS", @"West by south, short"), - NSLocalizedString(@"W", @"West, short"), - NSLocalizedString(@"W×N", @"West by north, short"), - NSLocalizedString(@"WNW", @"West-northwest, short"), - NSLocalizedString(@"NW×W", @"Northwest by west, short"), - NSLocalizedString(@"NW", @"Northwest, short"), - NSLocalizedString(@"NW×N", @"Northwest by north, short"), - NSLocalizedString(@"NNW", @"North-northwest, short"), - NSLocalizedString(@"N×W", @"North by west, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_W_SHORT", @"Foundation", nil, @"W", @"West, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_WbN_SHORT", @"Foundation", nil, @"WbN", @"West by north, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_WNW_SHORT", @"Foundation", nil, @"WNW", @"West-northwest, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NWbW_SHORT", @"Foundation", nil, @"NWbW", @"Northwest by west, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NW_SHORT", @"Foundation", nil, @"NW", @"Northwest, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NWbN_SHORT", @"Foundation", nil, @"NWbN", @"Northwest by north, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NNW_SHORT", @"Foundation", nil, @"NNW", @"North-northwest, short"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NbW_SHORT", @"Foundation", nil, @"NbW", @"North by west, short"), ]; longStrings = @[ - NSLocalizedString(@"north", @"North, long"), - NSLocalizedString(@"north by east", @"North by east, long"), - NSLocalizedString(@"north-northeast", @"North-northeast, long"), - NSLocalizedString(@"northeast by north", @"Northeast by north, long"), - NSLocalizedString(@"northeast", @"Northeast, long"), - NSLocalizedString(@"northeast by east", @"Northeast by east, long"), - NSLocalizedString(@"east-northeast", @"East-northeast, long"), - NSLocalizedString(@"east by north", @"East by north, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_N_LONG", @"Foundation", nil, @"north", @"North, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NbE_LONG", @"Foundation", nil, @"north by east", @"North by east, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NNE_LONG", @"Foundation", nil, @"north-northeast", @"North-northeast, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NEbN_LONG", @"Foundation", nil, @"northeast by north", @"Northeast by north, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NE_LONG", @"Foundation", nil, @"northeast", @"Northeast, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NEbE_LONG", @"Foundation", nil, @"northeast by east", @"Northeast by east, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_ENE_LONG", @"Foundation", nil, @"east-northeast", @"East-northeast, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_EbN_LONG", @"Foundation", nil, @"east by north", @"East by north, long"), - NSLocalizedString(@"east", @"East, long"), - NSLocalizedString(@"east by south", @"East by south, long"), - NSLocalizedString(@"east-southeast", @"East-southeast, long"), - NSLocalizedString(@"southeast by east", @"Southeast by east, long"), - NSLocalizedString(@"southeast", @"Southeast, long"), - NSLocalizedString(@"southeast by south", @"Southeast by south, long"), - NSLocalizedString(@"south-southeast", @"South-southeast, long"), - NSLocalizedString(@"south by east", @"South by east, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_E_LONG", @"Foundation", nil, @"east", @"East, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_EbS_LONG", @"Foundation", nil, @"east by south", @"East by south, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_ESE_LONG", @"Foundation", nil, @"east-southeast", @"East-southeast, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SEbE_LONG", @"Foundation", nil, @"southeast by east", @"Southeast by east, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SE_LONG", @"Foundation", nil, @"southeast", @"Southeast, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SEbS_LONG", @"Foundation", nil, @"southeast by south", @"Southeast by south, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SSE_LONG", @"Foundation", nil, @"south-southeast", @"South-southeast, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SbE_LONG", @"Foundation", nil, @"south by east", @"South by east, long"), - NSLocalizedString(@"south", @"South, long"), - NSLocalizedString(@"south by west", @"South by west, long"), - NSLocalizedString(@"south-southwest", @"South-southwest, long"), - NSLocalizedString(@"southwest by south", @"Southwest by south, long"), - NSLocalizedString(@"southwest", @"Southwest, long"), - NSLocalizedString(@"southwest by west", @"Southwest by west, long"), - NSLocalizedString(@"west-southwest", @"West-southwest, long"), - NSLocalizedString(@"west by south", @"West by south, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_S_LONG", @"Foundation", nil, @"south", @"South, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SbW_LONG", @"Foundation", nil, @"south by west", @"South by west, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SSW_LONG", @"Foundation", nil, @"south-southwest", @"South-southwest, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SWbS_LONG", @"Foundation", nil, @"southwest by south", @"Southwest by south, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SW_LONG", @"Foundation", nil, @"southwest", @"Southwest, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_SWbW_LONG", @"Foundation", nil, @"southwest by west", @"Southwest by west, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_WSW_LONG", @"Foundation", nil, @"west-southwest", @"West-southwest, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_WbS_LONG", @"Foundation", nil, @"west by south", @"West by south, long"), - NSLocalizedString(@"west", @"West, long"), - NSLocalizedString(@"west by north", @"West by north, long"), - NSLocalizedString(@"west-northwest", @"West-northwest, long"), - NSLocalizedString(@"northwest by west", @"Northwest by west, long"), - NSLocalizedString(@"northwest", @"Northwest, long"), - NSLocalizedString(@"northwest by north", @"Northwest by north, long"), - NSLocalizedString(@"north-northwest", @"North-northwest, long"), - NSLocalizedString(@"north by west", @"North by west, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_W_LONG", @"Foundation", nil, @"west", @"West, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_WbN_LONG", @"Foundation", nil, @"west by north", @"West by north, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_WNW_LONG", @"Foundation", nil, @"west-northwest", @"West-northwest, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NWbW_LONG", @"Foundation", nil, @"northwest by west", @"Northwest by west, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NW_LONG", @"Foundation", nil, @"northwest", @"Northwest, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NWbN_LONG", @"Foundation", nil, @"northwest by north", @"Northwest by north, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NNW_LONG", @"Foundation", nil, @"north-northwest", @"North-northwest, long"), + NSLocalizedStringWithDefaultValue(@"COMPASS_NbW_LONG", @"Foundation", nil, @"north by west", @"North by west, long"), ]; NSAssert(shortStrings.count == longStrings.count, @"Long and short compass direction string arrays must have the same size."); diff --git a/platform/darwin/src/MGLCoordinateFormatter.h b/platform/darwin/src/MGLCoordinateFormatter.h index 885471c36e0..3759576d2a4 100644 --- a/platform/darwin/src/MGLCoordinateFormatter.h +++ b/platform/darwin/src/MGLCoordinateFormatter.h @@ -12,6 +12,30 @@ NS_ASSUME_NONNULL_BEGIN */ @interface MGLCoordinateFormatter : NSFormatter +/** + Determines whether the output may contain minutes of arc when nonzero. + + The default value of this property is `YES`, causing the receiver to include + minutes of arc in its output. If `allowsSeconds` is `YES`, this property is + ignored and the output always includes minutes of arc. + */ +@property (nonatomic) BOOL allowsMinutes; + +/** + Determines whether the output may contain seconds of arc when nonzero. + + The default value of this property is `YES`, causing the receiver to include + seconds of arc in its output. + */ +@property (nonatomic) BOOL allowsSeconds; + +/** + The unit style used by this formatter. + + The default value of this property is `NSFormattingUnitStyleMedium`. + */ +@property (nonatomic) NSFormattingUnitStyle unitStyle; + /** Returns a coordinate string for the provided value. diff --git a/platform/darwin/src/MGLCoordinateFormatter.m b/platform/darwin/src/MGLCoordinateFormatter.m index 259917717fb..682f771faa9 100644 --- a/platform/darwin/src/MGLCoordinateFormatter.m +++ b/platform/darwin/src/MGLCoordinateFormatter.m @@ -1,44 +1,110 @@ #import "MGLCoordinateFormatter.h" +#import "NSBundle+MGLAdditions.h" #import "NSValue+MGLAdditions.h" -@implementation MGLCoordinateFormatter { - NSNumberFormatter *_numberFormatter; -} +@implementation MGLCoordinateFormatter - (instancetype)init { if (self = [super init]) { - _numberFormatter = [[NSNumberFormatter alloc] init]; - _numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; - _numberFormatter.maximumFractionDigits = 0; + _allowsMinutes = YES; + _allowsSeconds = YES; + _unitStyle = NSFormattingUnitStyleMedium; } return self; } - (NSString *)stringFromCoordinate:(CLLocationCoordinate2D)coordinate { - return [NSString stringWithFormat:NSLocalizedString(@"%@, %@", @"Latitude, longitude format"), - [self stringFromLocationDegrees:coordinate.latitude - positiveFormat:NSLocalizedString(@"%@N", @"North latitude format") - negativeFormat:NSLocalizedString(@"%@S", @"South latitude format")], - [self stringFromLocationDegrees:coordinate.longitude - positiveFormat:NSLocalizedString(@"%@E", @"East longitude format") - negativeFormat:NSLocalizedString(@"%@W", @"West longitude format")]]; + NSString *positiveLatitudeFormat; + NSString *negativeLatitudeFormat; + NSString *positiveLongitudeFormat; + NSString *negativeLongitudeFormat; + NSString *stringFormat; + switch (self.unitStyle) { + case NSFormattingUnitStyleShort: + positiveLatitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_N_SHORT", @"Foundation", nil, @"%@N", @"North latitude format, short: {latitude}"); + negativeLatitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_S_SHORT", @"Foundation", nil, @"%@S", @"South latitude format, short: {latitude}"); + positiveLongitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_E_SHORT", @"Foundation", nil, @"%@E", @"East longitude format, short: {longitude}"); + negativeLongitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_W_SHORT", @"Foundation", nil, @"%@W", @"West longitude format, short: {longitude}"); + stringFormat = NSLocalizedStringWithDefaultValue(@"COORD_FMT_SHORT", @"Foundation", nil, @"%@, %@", @"Coordinate pair format, short: {latitude}, {longitude}"); + break; + + case NSFormattingUnitStyleMedium: + positiveLatitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_N_MEDIUM", @"Foundation", nil, @"%@ north", @"North latitude format, medium: {latitude}"); + negativeLatitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_S_MEDIUM", @"Foundation", nil, @"%@ south", @"South latitude format, medium: {latitude}"); + positiveLongitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_E_MEDIUM", @"Foundation", nil, @"%@ east", @"East longitude format, medium: {longitude}"); + negativeLongitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_W_MEDIUM", @"Foundation", nil, @"%@ west", @"West longitude format, medium: {longitude}"); + stringFormat = NSLocalizedStringWithDefaultValue(@"COORD_FMT_MEDIUM", @"Foundation", nil, @"%@, %@", @"Coordinate pair format, medium: {latitude}, {longitude}"); + break; + + case NSFormattingUnitStyleLong: + positiveLatitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_N_LONG", @"Foundation", nil, @"%@ north", @"North latitude format, long: {latitude}"); + negativeLatitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_S_LONG", @"Foundation", nil, @"%@ south", @"South latitude format, long: {latitude}"); + positiveLongitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_E_LONG", @"Foundation", nil, @"%@ east", @"East longitude format, long: {longitude}"); + negativeLongitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_W_LONG", @"Foundation", nil, @"%@ west", @"West longitude format, long: {longitude}"); + stringFormat = NSLocalizedStringWithDefaultValue(@"COORD_FMT_LONG", @"Foundation", nil, @"%@ by %@", @"Coordinate pair format, long: {latitude}, {longitude}"); + break; + } + NSString *latitudeString = [self stringFromLocationDegrees:coordinate.latitude + positiveFormat:positiveLatitudeFormat + negativeFormat:negativeLatitudeFormat]; + NSString *longitudeString = [self stringFromLocationDegrees:coordinate.longitude + positiveFormat:positiveLongitudeFormat + negativeFormat:negativeLongitudeFormat]; + return [NSString stringWithFormat:stringFormat, latitudeString, longitudeString]; } - (NSString *)stringFromLocationDegrees:(CLLocationDegrees)degrees positiveFormat:(NSString *)positiveFormat negativeFormat:(NSString *)negativeFormat { CLLocationDegrees minutes = (fabs(degrees) - floor(fabs(degrees))) * 60; CLLocationDegrees seconds = (minutes - floor(minutes)) * 60; - NSMutableString *string = [NSMutableString stringWithFormat:NSLocalizedString(@"%@°", @"Degrees of arc format"), - [_numberFormatter stringFromNumber:@(floor(fabs(degrees)))]]; - if (trunc(minutes) > 0 || trunc(seconds) > 0) { - [string appendFormat:NSLocalizedString(@"%@′", @"Arcminutes format"), - [_numberFormatter stringFromNumber:@(floor(minutes))]]; + NSString *degreesFormat; + NSString *minutesFormat; + NSString *secondsFormat; + NSString *degreesMinutesFormat; + NSString *degreesMinutesSecondsFormat; + switch (self.unitStyle) { + case NSFormattingUnitStyleShort: + degreesFormat = NSLocalizedStringWithDefaultValue(@"COORD_DEG_SHORT", @"Foundation", nil, @"%d°", @"Degrees format, short: {degrees}"); + minutesFormat = NSLocalizedStringWithDefaultValue(@"COORD_MIN_SHORT", @"Foundation", nil, @"%d′", @"Minutes format, short: {minutes}"); + secondsFormat = NSLocalizedStringWithDefaultValue(@"COORD_SEC_SHORT", @"Foundation", nil, @"%d″", @"Seconds format, short: {seconds}"); + degreesMinutesFormat = NSLocalizedStringWithDefaultValue(@"COORD_DM_SHORT", @"Foundation", nil, @"%@%@", @"Coordinate format, short: {degrees}{minutes}"); + degreesMinutesSecondsFormat = NSLocalizedStringWithDefaultValue(@"COORD_DMS_SHORT", @"Foundation", nil, @"%@%@%@", @"Coordinate format, short: {degrees}{minutes}{seconds}"); + break; + + case NSFormattingUnitStyleMedium: + degreesFormat = NSLocalizedStringWithDefaultValue(@"COORD_DEG_MEDIUM", @"Foundation", nil, @"%d°", @"Degrees format, medium: {degrees}"); + minutesFormat = NSLocalizedStringWithDefaultValue(@"COORD_MIN_MEDIUM", @"Foundation", nil, @"%d′", @"Minutes format, medium: {minutes}"); + secondsFormat = NSLocalizedStringWithDefaultValue(@"COORD_SEC_MEDIUM", @"Foundation", nil, @"%d″", @"Seconds format, medium: {seconds}"); + degreesMinutesFormat = NSLocalizedStringWithDefaultValue(@"COORD_DM_MEDIUM", @"Foundation", nil, @"%@%@", @"Coordinate format, medium: {degrees}{minutes}"); + degreesMinutesSecondsFormat = NSLocalizedStringWithDefaultValue(@"COORD_DMS_MEDIUM", @"Foundation", nil, @"%@%@%@", @"Coordinate format, medium: {degrees}{minutes}{seconds}"); + break; + + case NSFormattingUnitStyleLong: + degreesFormat = NSLocalizedStringWithDefaultValue(@"COORD_DEG_LONG", @"Foundation", nil, @"%d degree(s)", @"Degrees format, long"); + minutesFormat = NSLocalizedStringWithDefaultValue(@"COORD_MIN_LONG", @"Foundation", nil, @"%d minute(s)", @"Minutes format, long"); + secondsFormat = NSLocalizedStringWithDefaultValue(@"COORD_SEC_LONG", @"Foundation", nil, @"%d second(s)", @"Seconds format, long"); + degreesMinutesFormat = NSLocalizedStringWithDefaultValue(@"COORD_DM_LONG", @"Foundation", nil, @"%@ and %@", @"Coordinate format, long: {degrees}{minutes}"); + degreesMinutesSecondsFormat = NSLocalizedStringWithDefaultValue(@"COORD_DMS_LONG", @"Foundation", nil, @"%@, %@, and %@", @"Coordinate format, long: {degrees}{minutes}{seconds}"); + break; } - if (trunc(seconds) > 0) { - [string appendFormat:NSLocalizedString(@"%@″", @"Arcseconds format"), - [_numberFormatter stringFromNumber:@(seconds)]]; + + NSString *degreesString = [NSString stringWithFormat:degreesFormat, (int)floor(fabs(degrees))]; + + NSString *string; + if (trunc(seconds) > 0 && self.allowsSeconds) { + NSString *minutesString = [NSString stringWithFormat:minutesFormat, (int)floor(minutes)]; + NSString *secondsString = [NSString stringWithFormat:secondsFormat, (int)round(seconds)]; + string = [NSString stringWithFormat:degreesMinutesSecondsFormat, + degreesString, minutesString, secondsString]; + } else if (trunc(minutes) > 0 && self.allowsMinutes) { + NSString *minutesString = [NSString stringWithFormat:minutesFormat, (int)round(minutes)]; + string = [NSString stringWithFormat:degreesMinutesFormat, + degreesString, minutesString]; + } else { + string = [NSString stringWithFormat:degreesFormat, (int)round(fabs(degrees))]; } + if (degrees == 0) { return string; } diff --git a/platform/darwin/src/NSBundle+MGLAdditions.h b/platform/darwin/src/NSBundle+MGLAdditions.h index 8a3e5c3c2ef..1fc9e8b8963 100644 --- a/platform/darwin/src/NSBundle+MGLAdditions.h +++ b/platform/darwin/src/NSBundle+MGLAdditions.h @@ -4,6 +4,29 @@ NS_ASSUME_NONNULL_BEGIN +// Strings in the SDK targets must be retrieved from the framework bundle rather +// than the main bundle, which is usually the application bundle. Redefining +// these macros ensures that the framework bundle’s string tables are used at +// runtime yet tools like genstrings and Xcode can still find the localizable +// string identifiers. (genstrings has an -s option that would allow us to +// define our own macros, but Xcode’s Export Localization feature lacks support +// for it.) +// +// As a consequence of this approach, this header must be included in all SDK +// files that include localizable strings. + +#undef NSLocalizedString +#define NSLocalizedString(key, comment) \ + [[NSBundle mgl_frameworkBundle] localizedStringForKey:(key) value:@"" table:nil] + +#undef NSLocalizedStringFromTable +#define NSLocalizedStringFromTable(key, tbl, comment) \ + [[NSBundle mgl_frameworkBundle] localizedStringForKey:(key) value:@"" table:(tbl)] + +#undef NSLocalizedStringWithDefaultValue +#define NSLocalizedStringWithDefaultValue(key, tbl, bundle, val, comment) \ + [[NSBundle mgl_frameworkBundle] localizedStringForKey:(key) value:(val) table:(tbl)] + @interface NSBundle (MGLAdditions) /// Returns the bundle containing the SDK’s classes and Info.plist file. diff --git a/platform/darwin/test/MGLClockDirectionFormatterTests.m b/platform/darwin/test/MGLClockDirectionFormatterTests.m index b85f4bed8c7..2b98de0861e 100644 --- a/platform/darwin/test/MGLClockDirectionFormatterTests.m +++ b/platform/darwin/test/MGLClockDirectionFormatterTests.m @@ -12,38 +12,43 @@ @implementation MGLClockDirectionFormatterTests - (void)testClockDirections { MGLClockDirectionFormatter *shortFormatter = [[MGLClockDirectionFormatter alloc] init]; shortFormatter.unitStyle = NSFormattingUnitStyleShort; - shortFormatter.locale = [NSLocale localeWithLocaleIdentifier:MGLTestLocaleIdentifier]; MGLClockDirectionFormatter *mediumFormatter = [[MGLClockDirectionFormatter alloc] init]; - mediumFormatter.locale = [NSLocale localeWithLocaleIdentifier:MGLTestLocaleIdentifier]; MGLClockDirectionFormatter *longFormatter = [[MGLClockDirectionFormatter alloc] init]; longFormatter.unitStyle = NSFormattingUnitStyleLong; - longFormatter.locale = [NSLocale localeWithLocaleIdentifier:MGLTestLocaleIdentifier]; - XCTAssertEqualObjects(@"9:00", [shortFormatter stringFromDirection:-90]); - XCTAssertEqualObjects(@"9 o’clock", [mediumFormatter stringFromDirection:-90]); - XCTAssertEqualObjects(@"nine o’clock", [longFormatter stringFromDirection:-90]); - - XCTAssertEqualObjects(@"12:00", [shortFormatter stringFromDirection:0]); - XCTAssertEqualObjects(@"12 o’clock", [mediumFormatter stringFromDirection:0]); - XCTAssertEqualObjects(@"twelve o’clock", [longFormatter stringFromDirection:0]); - - XCTAssertEqualObjects(@"2:00", [shortFormatter stringFromDirection:45]); - XCTAssertEqualObjects(@"2 o’clock", [mediumFormatter stringFromDirection:45]); - XCTAssertEqualObjects(@"two o’clock", [longFormatter stringFromDirection:45]); - - XCTAssertEqualObjects(@"3:00", [shortFormatter stringFromDirection:90]); - XCTAssertEqualObjects(@"3 o’clock", [mediumFormatter stringFromDirection:90]); - XCTAssertEqualObjects(@"three o’clock", [longFormatter stringFromDirection:90]); - - XCTAssertEqualObjects(@"6:00", [shortFormatter stringFromDirection:180]); - XCTAssertEqualObjects(@"6 o’clock", [mediumFormatter stringFromDirection:180]); - XCTAssertEqualObjects(@"six o’clock", [longFormatter stringFromDirection:180]); - - XCTAssertEqualObjects(@"9:00", [shortFormatter stringFromDirection:270]); - XCTAssertEqualObjects(@"9 o’clock", [mediumFormatter stringFromDirection:270]); - XCTAssertEqualObjects(@"nine o’clock", [longFormatter stringFromDirection:270]); + CLLocationDirection direction; + + direction = -90; + XCTAssertEqualObjects(@"9:00", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"9 o’clock", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"9 o’clock", [longFormatter stringFromDirection:direction]); + + direction = 0; + XCTAssertEqualObjects(@"12:00", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"12 o’clock", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"12 o’clock", [longFormatter stringFromDirection:direction]); + + direction = 45; + XCTAssertEqualObjects(@"2:00", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"2 o’clock", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"2 o’clock", [longFormatter stringFromDirection:direction]); + + direction = 90; + XCTAssertEqualObjects(@"3:00", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"3 o’clock", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"3 o’clock", [longFormatter stringFromDirection:direction]); + + direction = 180; + XCTAssertEqualObjects(@"6:00", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"6 o’clock", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"6 o’clock", [longFormatter stringFromDirection:direction]); + + direction = 270; + XCTAssertEqualObjects(@"9:00", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"9 o’clock", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"9 o’clock", [longFormatter stringFromDirection:direction]); } @end diff --git a/platform/darwin/test/MGLCompassDirectionFormatterTests.m b/platform/darwin/test/MGLCompassDirectionFormatterTests.m index 034e07818bd..08b0b92f0bf 100644 --- a/platform/darwin/test/MGLCompassDirectionFormatterTests.m +++ b/platform/darwin/test/MGLCompassDirectionFormatterTests.m @@ -17,49 +17,62 @@ - (void)testCompassDirections { MGLCompassDirectionFormatter *longFormatter = [[MGLCompassDirectionFormatter alloc] init]; longFormatter.unitStyle = NSFormattingUnitStyleLong; - XCTAssertEqualObjects(@"NW", [shortFormatter stringFromDirection:-45]); - XCTAssertEqualObjects(@"northwest", [mediumFormatter stringFromDirection:-45]); - XCTAssertEqualObjects([mediumFormatter stringFromDirection:-45], [longFormatter stringFromDirection:-45]); + CLLocationDirection direction; - XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:0]); - XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:0]); - XCTAssertEqualObjects([mediumFormatter stringFromDirection:0], [longFormatter stringFromDirection:0]); + direction = -45; + XCTAssertEqualObjects(@"NW", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"northwest", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"northwest", [longFormatter stringFromDirection:direction]); - XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:1]); - XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:1]); - XCTAssertEqualObjects([mediumFormatter stringFromDirection:1], [longFormatter stringFromDirection:1]); + direction = 0; + XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north", [longFormatter stringFromDirection:direction]); - XCTAssertEqualObjects(@"N×E", [shortFormatter stringFromDirection:10]); - XCTAssertEqualObjects(@"north by east", [mediumFormatter stringFromDirection:10]); - XCTAssertEqualObjects([mediumFormatter stringFromDirection:10], [longFormatter stringFromDirection:10]); + direction = 1; + XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north", [longFormatter stringFromDirection:direction]); - XCTAssertEqualObjects(@"NNE", [shortFormatter stringFromDirection:20]); - XCTAssertEqualObjects(@"north-northeast", [mediumFormatter stringFromDirection:20]); - XCTAssertEqualObjects([mediumFormatter stringFromDirection:20], [longFormatter stringFromDirection:20]); + direction = 10; + XCTAssertEqualObjects(@"NbE", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north by east", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north by east", [longFormatter stringFromDirection:direction]); - XCTAssertEqualObjects(@"NE", [shortFormatter stringFromDirection:45]); - XCTAssertEqualObjects(@"northeast", [mediumFormatter stringFromDirection:45]); - XCTAssertEqualObjects([mediumFormatter stringFromDirection:45], [longFormatter stringFromDirection:45]); + direction = 20; + XCTAssertEqualObjects(@"NNE", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north-northeast", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north-northeast", [longFormatter stringFromDirection:direction]); - XCTAssertEqualObjects(@"E", [shortFormatter stringFromDirection:90]); - XCTAssertEqualObjects(@"east", [mediumFormatter stringFromDirection:90]); - XCTAssertEqualObjects([mediumFormatter stringFromDirection:90], [longFormatter stringFromDirection:90]); + direction = 45; + XCTAssertEqualObjects(@"NE", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"northeast", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"northeast", [longFormatter stringFromDirection:direction]); - XCTAssertEqualObjects(@"S", [shortFormatter stringFromDirection:180]); - XCTAssertEqualObjects(@"south", [mediumFormatter stringFromDirection:180]); - XCTAssertEqualObjects([mediumFormatter stringFromDirection:180], [longFormatter stringFromDirection:180]); + direction = 90; + XCTAssertEqualObjects(@"E", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"east", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"east", [longFormatter stringFromDirection:direction]); - XCTAssertEqualObjects(@"W", [shortFormatter stringFromDirection:270]); - XCTAssertEqualObjects(@"west", [mediumFormatter stringFromDirection:270]); - XCTAssertEqualObjects([mediumFormatter stringFromDirection:270], [longFormatter stringFromDirection:270]); + direction = 180; + XCTAssertEqualObjects(@"S", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"south", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"south", [longFormatter stringFromDirection:direction]); - XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:360]); - XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:360]); - XCTAssertEqualObjects([mediumFormatter stringFromDirection:360], [longFormatter stringFromDirection:360]); + direction = 270; + XCTAssertEqualObjects(@"W", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"west", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"west", [longFormatter stringFromDirection:direction]); - XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:720]); - XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:720]); - XCTAssertEqualObjects([mediumFormatter stringFromDirection:720], [longFormatter stringFromDirection:720]); + direction = 360; + XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north", [longFormatter stringFromDirection:direction]); + + direction = 720; + XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:direction]); + XCTAssertEqualObjects(@"north", [longFormatter stringFromDirection:direction]); } @end diff --git a/platform/darwin/test/MGLCoordinateFormatterTests.m b/platform/darwin/test/MGLCoordinateFormatterTests.m index 84a17596b19..6a6c7a3b2e6 100644 --- a/platform/darwin/test/MGLCoordinateFormatterTests.m +++ b/platform/darwin/test/MGLCoordinateFormatterTests.m @@ -8,8 +8,41 @@ @interface MGLCoordinateFormatterTests : XCTestCase @implementation MGLCoordinateFormatterTests - (void)testStrings { - MGLCoordinateFormatter *formatter = [[MGLCoordinateFormatter alloc] init]; - XCTAssertEqualObjects([formatter stringFromCoordinate:CLLocationCoordinate2DMake(38.9131982, -77.0325453144239)], @"38°54′48″N, 77°1′57″W"); + MGLCoordinateFormatter *shortFormatter = [[MGLCoordinateFormatter alloc] init]; + shortFormatter.unitStyle = NSFormattingUnitStyleShort; + XCTAssertTrue(shortFormatter.allowsSeconds, @"Arcseconds should be allowed by default."); + XCTAssertTrue(shortFormatter.allowsMinutes, @"Arcminutes should be allowed by default."); + + MGLCoordinateFormatter *mediumFormatter = [[MGLCoordinateFormatter alloc] init]; + XCTAssertEqual(mediumFormatter.unitStyle, NSFormattingUnitStyleMedium, @"Unit style should be medium by default."); + + MGLCoordinateFormatter *longFormatter = [[MGLCoordinateFormatter alloc] init]; + longFormatter.unitStyle = NSFormattingUnitStyleLong; + + CLLocationCoordinate2D coordinate; + + coordinate = CLLocationCoordinate2DMake(38.9131982, -77.0325453144239); + XCTAssertEqualObjects([shortFormatter stringFromCoordinate:coordinate], @"38°54′48″N, 77°1′57″W"); + XCTAssertEqualObjects([mediumFormatter stringFromCoordinate:coordinate], @"38°54′48″ north, 77°1′57″ west"); + XCTAssertEqualObjects([longFormatter stringFromCoordinate:coordinate], @"38 degrees, 54 minutes, and 48 seconds north by 77 degrees, 1 minute, and 57 seconds west"); + + shortFormatter.allowsSeconds = NO; + mediumFormatter.allowsSeconds = NO; + longFormatter.allowsSeconds = NO; + + coordinate = CLLocationCoordinate2DMake(38.9131982, -77.0325453144239); + XCTAssertEqualObjects([shortFormatter stringFromCoordinate:coordinate], @"38°55′N, 77°2′W"); + XCTAssertEqualObjects([mediumFormatter stringFromCoordinate:coordinate], @"38°55′ north, 77°2′ west"); + XCTAssertEqualObjects([longFormatter stringFromCoordinate:coordinate], @"38 degrees and 55 minutes north by 77 degrees and 2 minutes west"); + + shortFormatter.allowsMinutes = NO; + mediumFormatter.allowsMinutes = NO; + longFormatter.allowsMinutes = NO; + + coordinate = CLLocationCoordinate2DMake(38.9131982, -77.0325453144239); + XCTAssertEqualObjects([shortFormatter stringFromCoordinate:coordinate], @"39°N, 77°W"); + XCTAssertEqualObjects([mediumFormatter stringFromCoordinate:coordinate], @"39° north, 77° west"); + XCTAssertEqualObjects([longFormatter stringFromCoordinate:coordinate], @"39 degrees north by 77 degrees west"); } @end diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 842fadd2fc8..2377da7cf18 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -9,6 +9,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CON - The user dot now moves smoothly between user location updates while user location tracking is disabled. ([#1582](https://github.com/mapbox/mapbox-gl-native/pull/1582)) - An MGLAnnotation can be relocated by changing its `coordinate` property in a KVO-compliant way. An MGLMultiPoint cannot be relocated. ([#3835](https://github.com/mapbox/mapbox-gl-native/pull/3835)) - Setting the `image` property of an MGLAnnotationImage to `nil` resets it to the default red pin image and reclaims resources that can be used to customize additional annotations. ([#3835](https://github.com/mapbox/mapbox-gl-native/pull/3835)) +- The SDK is now localizable. No localizations are currently provided, other than English, but if you need a particular localization, you can install the SDK manually and drop a .lproj folder into the framework. ([#4783](https://github.com/mapbox/mapbox-gl-native/pull/4783)) - Fixed an issue preventing KVO change notifications from being generated on MGLMapView’s `userTrackingMode` key path when `-setUserTrackingMode:animated:` is called. ([#4724](https://github.com/mapbox/mapbox-gl-native/pull/4724)) - Rendering now occurs on the main thread, fixing a hang when calling `-[MGLMapView styleURL]` before the map view has fully loaded or while the application is in the background. ([#2909](https://github.com/mapbox/mapbox-gl-native/pull/2909)) - Improved responsiveness when zooming in then immediately panning around. ([#4595](https://github.com/mapbox/mapbox-gl-native/pull/4595)) diff --git a/platform/ios/DEVELOPING.md b/platform/ios/DEVELOPING.md index 3120ff84b56..5f07f410c1c 100644 --- a/platform/ios/DEVELOPING.md +++ b/platform/ios/DEVELOPING.md @@ -2,11 +2,11 @@ This document explains how to build the Mapbox iOS SDK from source. It is intended for advanced developers who wish to contribute to Mapbox GL and the Mapbox iOS SDK. -### Requirements +## Requirements The Mapbox iOS SDK and iosapp demo application build against the iOS 7.0 SDK. The SDK is intended to run on iOS 7.0 and above, while iosapp is intended to run on iOS 8.0 and above due to the use of a dynamic framework. Both require Xcode on a computer running OS X. -### Build +## Building the SDK [Install core dependencies](../../INSTALL.md), then run @@ -16,6 +16,14 @@ make iproj which will create and open an Xcode workspace that includes both the SDK source and some Objective-C test applications. Before building, use the scheme picker button in the toolbar to change the scheme to “iosapp” and the destination to one of the simulators or connected devices listed in the menu. +“iosapp” is only one of several shared schemes. Others include: + +* “CI” builds exactly what gets built for continuous integration on Bitrise. +* “bench” is a simple benchmarking application. For more consistent results between runs, run platform/ios/benchmark/assets/{glyphs,tiles}/download.sh to download any necessary resources. +* “dynamic” builds the SDK as a dynamic framework. +* “static” builds the SDK as a static library and separate resource bundle. +* “dynamic+static” is a combination of the “dynamic” and “static” schemes. + If you don’t have an Apple Developer account, change the destination to a simulator such as “iPhone 6s” before you run and build the app. `iproj` is only one of several available `make` rules. Others include: @@ -24,6 +32,7 @@ If you don’t have an Apple Developer account, change the destination to a simu * `make ipackage-sim` builds a dynamic framework in the Debug configuration for the iOS simulator. This is the fastest target. * `make ipackage-strip` builds both dynamic and static frameworks in the Release configuration, stripped of debug symbols, for devices and the iOS Simulator. * `make iframework` builds a dynamic framework in the Release configuration for devices and the iOS Simulator. The CocoaPods pod downloads the output of this target. +* `make ifabric` builds a special static framework for compatibility with the Fabric Mac application. You can customize the build output by passing the following arguments into the `make` invocation: @@ -37,11 +46,37 @@ These targets require that you install [jazzy](https://github.com/realm/jazzy) f [sudo] gem install jazzy ``` -### Access tokens +## Contributing -The included applications use Mapbox vector tiles, which require a Mapbox account and API access token. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). You will be prompted for this access token the first time you launch the demo or benchmarking application. In the iOS Simulator, you can paste your access token by pressing Command-V, holding down the left mouse button in the text field, and pressing the Paste button that appears. +### Adding a source code file + +To add an Objective-C header or implementation file to the iOS SDK: + +1. Add the file to the Headers or Compile Sources build phase, as appropriate, of both the “dynamic” and “static” targets. You can either use the Build Phases tab of the project editor or the Target Membership section of the File inspector. +1. _(Optional.)_ If it’s a public header, change its visibility from Project to Public and import it in [the iOS SDK’s umbrella header](./src/Mapbox.h). +1. _(Optional.)_ If the file would also be used by the OS X SDK, make sure it’s in [platform/darwin/src/](../darwin/src/), then consult [the companion OS X document](../osx/DEVELOPING.md#adding-a-source-code-file) for further instructions. + +### Adding a resource + +To add a resource (such as an image, SSL certificate, property list, or strings table) to the iOS SDK: -### Test +1. Add the header to the Copy Bundle Resources build phase of both the “dynamic” and “bundle” targets. You can either use the Build Phases tab of the project editor or the Target Membership section of the File inspector. +1. _(Optional.)_ If the resource would also be used by the OS X SDK, make sure it’s in [platform/darwin/resources/](../darwin/resources/), then consult [the companion OS X document](../osx/DEVELOPING.md#adding-a-resource) for further instructions. + +### Adding user-facing text + +To add or update text that the user may see in the iOS SDK: + +1. Make sure the implementation file imports [NSBundle+MGLAdditions.h](../darwin/src/NSBundle+MGLAdditions.h). +1. Use the `NSLocalizedStringWithDefaultValue()` macro: + * `key` is a unique identifier that won’t change if the user-facing text ever needs to change. + * `tbl` is `Foundation` in code shared between the iOS and OS X SDKs, or `nil` otherwise. + * `bundle` is `nil`; the redefined macro looks for the SDK bundle at runtime and ignores this argument. + * `val` is the English string. +1. _(Optional.)_ When dealing with a number followed by a pluralized word, do not split the string. Instead, use a format string and make `val` ambiguous, like `%d file(s)`. Then pluralize for English in the appropriate [.stringsdict file](https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html). See [platform/darwin/resources/en.lproj/Foundation.stringsdict](../darwin/resources/en.lproj/Foundation.stringsdict) for an example. Localizers should do likewise for their languages. +1. Run `make genstrings` and commit any changes it makes to .strings files. The make rule also updates the OS X SDK’s strings tables. + +## Testing `make test-ios` builds and runs unit tests of cross-platform code as well as the SDK. @@ -58,7 +93,11 @@ To instead run the tests in Xcode: 1. Change the scheme to “test (platform project)” and press Command-R to run core unit tests. 1. Change the scheme to “CI” and press Command-U to run SDK integration tests. -### iosapp usage +## Access tokens + +The included applications use Mapbox vector tiles, which require a Mapbox account and API access token. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). You will be prompted for this access token the first time you launch the demo or benchmarking application. In the iOS Simulator, you can paste your access token by pressing Command-V, holding down the left mouse button in the text field, and pressing the Paste button that appears. + +## Using iosapp - Pan to move - Pinch to zoom diff --git a/platform/ios/app/Info.plist b/platform/ios/app/Info.plist index e56954833bb..3602ab79641 100644 --- a/platform/ios/app/Info.plist +++ b/platform/ios/app/Info.plist @@ -5,15 +5,15 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - ${PRODUCT_NAME} + $(PRODUCT_NAME) CFBundleExecutable - ${EXECUTABLE_NAME} + $(EXECUTABLE_NAME) CFBundleIdentifier com.mapbox.MapboxGL CFBundleInfoDictionaryVersion 6.0 CFBundleName - ${PRODUCT_NAME} + $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString diff --git a/platform/ios/app/Base.lproj/LaunchScreen.storyboard b/platform/ios/app/LaunchScreen.storyboard similarity index 100% rename from platform/ios/app/Base.lproj/LaunchScreen.storyboard rename to platform/ios/app/LaunchScreen.storyboard diff --git a/platform/ios/app/MBXOfflinePacksTableViewController.m b/platform/ios/app/MBXOfflinePacksTableViewController.m index 9b1a12a9333..008d843b1e4 100644 --- a/platform/ios/app/MBXOfflinePacksTableViewController.m +++ b/platform/ios/app/MBXOfflinePacksTableViewController.m @@ -173,7 +173,7 @@ - (void)updateTableViewCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)i numberStyle:NSNumberFormatterDecimalStyle]; } if (progress.maximumResourcesExpected > progress.countOfResourcesExpected) { - expectedString = [@"at least " stringByAppendingString:expectedString]; + expectedString = [NSString stringWithFormat:@"at least %@", expectedString]; } statusString = [NSString stringWithFormat:@"Downloading %@ of %@ resources (%@ so far)…", completedString, expectedString, byteCountString]; @@ -247,7 +247,7 @@ - (void)offlinePackDidReceiveError:(NSNotification *)notification { NSError *error = notification.userInfo[MGLOfflinePackErrorUserInfoKey]; NSAssert([error isKindOfClass:[NSError class]], @"MGLOfflineStorage notification has a non-error error."); - NSString *message = [NSString stringWithFormat:@"iosapp encountered an error while downloading the offline pack “%@”: %@", pack.name, error.localizedFailureReason]; + NSString *message = [NSString stringWithFormat:@"Mapbox GL encountered an error while downloading the offline pack “%@”: %@", pack.name, error.localizedFailureReason]; if (error.code == MGLErrorCodeConnectionFailed) { NSLog(@"%@", message); } else { diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index f6e0cc0ae86..8f628e8126c 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -10,8 +10,6 @@ #import #import -static NSString * const kCustomCalloutTitle = @"Custom Callout"; - static const CLLocationCoordinate2D WorldTourDestinations[] = { { .latitude = 38.9131982, .longitude = -77.0325453144239 }, { .latitude = 37.7757368, .longitude = -122.4135302 }, @@ -19,6 +17,18 @@ { .latitude = -13.15589555, .longitude = -74.2178961777998 }, }; +@interface MBXDroppedPinAnnotation : MGLPointAnnotation +@end + +@implementation MBXDroppedPinAnnotation +@end + +@interface MBXCustomCalloutAnnotation : MGLPointAnnotation +@end + +@implementation MBXCustomCalloutAnnotation +@end + @interface MBXViewController () @property (nonatomic) IBOutlet MGLMapView *mapView; @@ -155,32 +165,32 @@ - (IBAction)showSettings:(__unused id)sender cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles: - @"Reset Position", - ((debugMask & MGLMapDebugTileBoundariesMask) - ? @"Hide Tile Boundaries" - : @"Show Tile Boundaries"), - ((debugMask & MGLMapDebugTileInfoMask) - ? @"Hide Tile Info" - : @"Show Tile Info"), - ((debugMask & MGLMapDebugTimestampsMask) - ? @"Hide Tile Timestamps" - : @"Show Tile Timestamps"), - ((debugMask & MGLMapDebugCollisionBoxesMask) - ? @"Hide Collision Boxes" - : @"Show Collision Boxes"), - @"Add 100 Points", - @"Add 1,000 Points", - @"Add 10,000 Points", - @"Add Test Shapes", - @"Start World Tour", - @"Add Custom Callout Point", - @"Remove Annotations", - (_isShowingCustomStyleLayer - ? @"Hide Custom Style Layer" - : @"Show Custom Style Layer"), - @"Print Telemetry Logfile", - @"Delete Telemetry Logfile", - nil]; + @"Reset Position", + ((debugMask & MGLMapDebugTileBoundariesMask) + ? @"Hide Tile Boundaries" + : @"Show Tile Boundaries"), + ((debugMask & MGLMapDebugTileInfoMask) + ? @"Hide Tile Info" + : @"Show Tile Info"), + ((debugMask & MGLMapDebugTimestampsMask) + ? @"Hide Tile Timestamps" + : @"Show Tile Timestamps"), + ((debugMask & MGLMapDebugCollisionBoxesMask) + ? @"Hide Collision Boxes" + : @"Show Collision Boxes"), + @"Add 100 Points", + @"Add 1,000 Points", + @"Add 10,000 Points", + @"Add Test Shapes", + @"Start World Tour", + @"Add Custom Callout Point", + @"Remove Annotations", + (_isShowingCustomStyleLayer + ? @"Hide Custom Style Layer" + : @"Show Custom Style Layer"), + @"Print Telemetry Logfile", + @"Delete Telemetry Logfile", + nil]; [sheet showFromBarButtonItem:self.navigationItem.leftBarButtonItem animated:YES]; } @@ -434,9 +444,9 @@ - (void)presentAnnotationWithCustomCallout { [self.mapView removeAnnotations:self.mapView.annotations]; - MGLPointAnnotation *annotation = [MGLPointAnnotation new]; + MBXCustomCalloutAnnotation *annotation = [[MBXCustomCalloutAnnotation alloc] init]; annotation.coordinate = CLLocationCoordinate2DMake(48.8533940, 2.3775439); - annotation.title = kCustomCalloutTitle; + annotation.title = @"Custom Callout"; [self.mapView addAnnotation:annotation]; [self.mapView showAnnotations:@[annotation] animated:YES]; @@ -446,10 +456,10 @@ - (IBAction)handleLongPress:(UILongPressGestureRecognizer *)longPress { if (longPress.state == UIGestureRecognizerStateBegan) { - MGLPointAnnotation *point = [MGLPointAnnotation new]; + MBXDroppedPinAnnotation *point = [[MBXDroppedPinAnnotation alloc] init]; point.coordinate = [self.mapView convertPoint:[longPress locationInView:longPress.view] toCoordinateFromView:self.mapView]; - point.title = @"Dropped Marker"; + point.title = @"Dropped Pin"; point.subtitle = [[[MGLCoordinateFormatter alloc] init] stringFromCoordinate:point.coordinate]; [self.mapView addAnnotation:point]; [self.mapView selectAnnotation:point animated:YES]; @@ -594,8 +604,8 @@ - (void)dealloc - (MGLAnnotationImage *)mapView:(MGLMapView * __nonnull)mapView imageForAnnotation:(id __nonnull)annotation { - if ([annotation.title isEqualToString:@"Dropped Marker"] - || [annotation.title isEqualToString:kCustomCalloutTitle]) + if ([annotation isKindOfClass:[MBXDroppedPinAnnotation class]] + || [annotation isKindOfClass:[MBXCustomCalloutAnnotation class]]) { return nil; // use default marker } @@ -720,7 +730,7 @@ - (void)mapView:(__unused MGLMapView *)mapView didChangeUserTrackingMode:(MGLUse - (UIView *)mapView:(__unused MGLMapView *)mapView calloutViewForAnnotation:(id)annotation { if ([annotation respondsToSelector:@selector(title)] - && [annotation.title isEqualToString:kCustomCalloutTitle]) + && [annotation isKindOfClass:[MBXCustomCalloutAnnotation class]]) { MBXCustomCalloutView *calloutView = [[MBXCustomCalloutView alloc] init]; calloutView.representedObject = annotation; diff --git a/platform/ios/app/Base.lproj/Main.storyboard b/platform/ios/app/Main.storyboard similarity index 99% rename from platform/ios/app/Base.lproj/Main.storyboard rename to platform/ios/app/Main.storyboard index 75b2b68f9a0..72f9a02219f 100644 --- a/platform/ios/app/Base.lproj/Main.storyboard +++ b/platform/ios/app/Main.storyboard @@ -1,6 +1,7 @@ + diff --git a/platform/ios/benchmark/Info.plist b/platform/ios/benchmark/Info.plist index 22ea46152b5..98ae65e1704 100644 --- a/platform/ios/benchmark/Info.plist +++ b/platform/ios/benchmark/Info.plist @@ -5,15 +5,15 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - ${PRODUCT_NAME} + $(PRODUCT_NAME) CFBundleExecutable - ${EXECUTABLE_NAME} + $(EXECUTABLE_NAME) CFBundleIdentifier com.mapbox.GL.benchmark CFBundleInfoDictionaryVersion 6.0 CFBundleName - ${PRODUCT_NAME} + $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString diff --git a/platform/ios/framework/Info-static.plist b/platform/ios/framework/Info-static.plist new file mode 100644 index 00000000000..b42a23322db --- /dev/null +++ b/platform/ios/framework/Info-static.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundleShortVersionString + $(CURRENT_SHORT_VERSION) + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + MGLCommitHash + $(CURRENT_COMMIT_HASH) + MGLSemanticVersionString + $(CURRENT_SEMANTIC_VERSION) + NSPrincipalClass + + + diff --git a/platform/ios/framework/Info.plist b/platform/ios/framework/Info.plist index d3de8eefb69..d8962c53ab3 100644 --- a/platform/ios/framework/Info.plist +++ b/platform/ios/framework/Info.plist @@ -15,11 +15,15 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + $(CURRENT_SHORT_VERSION) CFBundleSignature ???? CFBundleVersion $(CURRENT_PROJECT_VERSION) + MGLCommitHash + $(CURRENT_COMMIT_HASH) + MGLSemanticVersionString + $(CURRENT_SEMANTIC_VERSION) NSPrincipalClass diff --git a/platform/ios/framework/Settings.bundle/Base.lproj/Root.strings b/platform/ios/framework/Settings.bundle/Base.lproj/Root.strings new file mode 100644 index 00000000000..1945fe1141d --- /dev/null +++ b/platform/ios/framework/Settings.bundle/Base.lproj/Root.strings @@ -0,0 +1,3 @@ +"TELEMETRY_GROUP_TITLE" = "Privacy Settings"; +"TELEMETRY_SWITCH_TITLE" = "Mapbox Telemetry"; +"TELEMETRY_GROUP_FOOTER" = "This setting allows the application to share anonymized location and usage data with Mapbox."; diff --git a/platform/ios/framework/Settings.bundle/Root.plist b/platform/ios/framework/Settings.bundle/Root.plist index 889610e1520..fba2065a8f1 100644 --- a/platform/ios/framework/Settings.bundle/Root.plist +++ b/platform/ios/framework/Settings.bundle/Root.plist @@ -6,11 +6,11 @@ Title - Privacy Settings + TELEMETRY_GROUP_TITLE Type PSGroupSpecifier FooterText - This setting allows the application to share anonymized location and usage data with Mapbox. + TELEMETRY_GROUP_FOOTER DefaultValue @@ -18,7 +18,7 @@ Key MGLMapboxMetricsEnabled Title - Mapbox Telemetry + TELEMETRY_SWITCH_TITLE Type PSToggleSwitchSpecifier TrueValue diff --git a/platform/ios/framework/Settings.bundle/en.lproj/Root.strings b/platform/ios/framework/Settings.bundle/en.lproj/Root.strings deleted file mode 100644 index e7658d692de..00000000000 Binary files a/platform/ios/framework/Settings.bundle/en.lproj/Root.strings and /dev/null differ diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index c7367a68a02..db90c43a442 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -13,13 +13,15 @@ DA1DC96B1CB6C6B7006E619F /* MBXOfflinePacksTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA1DC9691CB6C6B7006E619F /* MBXOfflinePacksTableViewController.m */; }; DA1DC9701CB6C6CE006E619F /* points.geojson in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC96C1CB6C6CE006E619F /* points.geojson */; }; DA1DC9711CB6C6CE006E619F /* polyline.geojson in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC96D1CB6C6CE006E619F /* polyline.geojson */; }; - DA1DC9721CB6C6CE006E619F /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC96E1CB6C6CE006E619F /* Settings.bundle */; }; DA1DC9731CB6C6CE006E619F /* threestates.geojson in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC96F1CB6C6CE006E619F /* threestates.geojson */; }; DA1DC9971CB6E046006E619F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DA1DC9961CB6E046006E619F /* main.m */; }; DA1DC9991CB6E054006E619F /* MBXAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DA1DC9981CB6E054006E619F /* MBXAppDelegate.m */; }; DA1DC99B1CB6E064006E619F /* MBXViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA1DC99A1CB6E064006E619F /* MBXViewController.m */; }; DA1DC99D1CB6E076006E619F /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC99C1CB6E076006E619F /* Default-568h@2x.png */; }; DA1DC99F1CB6E088006E619F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC99E1CB6E088006E619F /* Assets.xcassets */; }; + DA25D5C01CCD9F8400607828 /* Root.plist in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5BF1CCD9F8400607828 /* Root.plist */; }; + DA25D5C61CCDA06800607828 /* Root.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5C41CCDA06800607828 /* Root.strings */; }; + DA25D5CD1CCDA11500607828 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5B91CCD9EDE00607828 /* Settings.bundle */; }; DA27C24E1CBB3811000B0ECD /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA27C24D1CBB3811000B0ECD /* GLKit.framework */; }; DA27C24F1CBB4C11000B0ECD /* MGLAccountManager_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8847FF1CBAFA6200AB86E3 /* MGLAccountManager_Private.h */; }; DA2E88561CC036F400F24E7B /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; }; @@ -47,8 +49,8 @@ DA35A2CA1CCAAAD200E826B2 /* NSValue+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2C71CCAAAD200E826B2 /* NSValue+MGLAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA35A2CB1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */; }; DA35A2CC1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */; }; - DA4A26941CB6E337000B7809 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC9561CB6C1C2006E619F /* Main.storyboard */; }; - DA4A26951CB6E337000B7809 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC95B1CB6C1C2006E619F /* LaunchScreen.storyboard */; }; + DA821D061CCC6D59007508D4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA821D041CCC6D59007508D4 /* LaunchScreen.storyboard */; }; + DA821D071CCC6D59007508D4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA821D051CCC6D59007508D4 /* Main.storyboard */; }; DA8847D91CBAF91600AB86E3 /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; }; DA8847DA1CBAF91600AB86E3 /* Mapbox.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; DA8847EF1CBAFA5100AB86E3 /* MGLAccountManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8847DF1CBAFA5100AB86E3 /* MGLAccountManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -134,6 +136,25 @@ DA88488C1CBB037E00AB86E3 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = DA88488A1CBB037E00AB86E3 /* SMCalloutView.m */; }; DA88488E1CBB047F00AB86E3 /* reachability.h in Headers */ = {isa = PBXBuildFile; fileRef = DA88488D1CBB047F00AB86E3 /* reachability.h */; }; DA8848901CBB048E00AB86E3 /* reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = DA88488F1CBB048E00AB86E3 /* reachability.m */; }; + DA8933A31CCC95B000E68420 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA89339F1CCC951200E68420 /* Localizable.strings */; }; + DA8933BC1CCD2CA100E68420 /* Foundation.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA8933BA1CCD2CA100E68420 /* Foundation.strings */; }; + DA8933BF1CCD2CAD00E68420 /* Foundation.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DA8933BD1CCD2CAD00E68420 /* Foundation.stringsdict */; }; + DA8933DB1CCD31D400E68420 /* Foundation.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA8933BA1CCD2CA100E68420 /* Foundation.strings */; }; + DA8933DC1CCD31D400E68420 /* Foundation.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DA8933BD1CCD2CAD00E68420 /* Foundation.stringsdict */; }; + DA8933DD1CCD31D400E68420 /* api_mapbox_com-digicert.der in Resources */ = {isa = PBXBuildFile; fileRef = DA8848771CBAFD5C00AB86E3 /* api_mapbox_com-digicert.der */; }; + DA8933DE1CCD31D400E68420 /* api_mapbox_com-geotrust.der in Resources */ = {isa = PBXBuildFile; fileRef = DA8848781CBAFD5C00AB86E3 /* api_mapbox_com-geotrust.der */; }; + DA8933DF1CCD31D400E68420 /* star_tilestream_net.der in Resources */ = {isa = PBXBuildFile; fileRef = DA8848791CBAFD5C00AB86E3 /* star_tilestream_net.der */; }; + DA8933E01CCD31DF00E68420 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA89339F1CCC951200E68420 /* Localizable.strings */; }; + DA8933E11CCD31DF00E68420 /* Compass.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848631CBAFCC100AB86E3 /* Compass.png */; }; + DA8933E21CCD31DF00E68420 /* Compass@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848641CBAFCC100AB86E3 /* Compass@2x.png */; }; + DA8933E31CCD31DF00E68420 /* Compass@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848651CBAFCC100AB86E3 /* Compass@3x.png */; }; + DA8933E41CCD31DF00E68420 /* default_marker.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848661CBAFCC100AB86E3 /* default_marker.png */; }; + DA8933E51CCD31DF00E68420 /* default_marker@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848671CBAFCC100AB86E3 /* default_marker@2x.png */; }; + DA8933E61CCD31DF00E68420 /* default_marker@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848681CBAFCC100AB86E3 /* default_marker@3x.png */; }; + DA8933E71CCD31DF00E68420 /* mapbox.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848691CBAFCC100AB86E3 /* mapbox.png */; }; + DA8933E81CCD31DF00E68420 /* mapbox@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA88486A1CBAFCC100AB86E3 /* mapbox@2x.png */; }; + DA8933E91CCD31DF00E68420 /* mapbox@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA88486B1CBAFCC100AB86E3 /* mapbox@3x.png */; }; + DA8933F01CCD387900E68420 /* strip-frameworks.sh in Resources */ = {isa = PBXBuildFile; fileRef = DA8933EF1CCD387900E68420 /* strip-frameworks.sh */; }; DA8963371CC549A100684375 /* glyphs in Resources */ = {isa = PBXBuildFile; fileRef = DA8963331CC549A100684375 /* glyphs */; }; DA8963381CC549A100684375 /* sprites in Resources */ = {isa = PBXBuildFile; fileRef = DA8963341CC549A100684375 /* sprites */; }; DA8963391CC549A100684375 /* styles in Resources */ = {isa = PBXBuildFile; fileRef = DA8963351CC549A100684375 /* styles */; }; @@ -202,6 +223,27 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + DA25D5C71CCDA0C100607828 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DA1DC9421CB6C1C2006E619F /* Project object */; + proxyType = 1; + remoteGlobalIDString = DA25D5B81CCD9EDE00607828; + remoteInfo = settings; + }; + DA25D5C91CCDA0CC00607828 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DA1DC9421CB6C1C2006E619F /* Project object */; + proxyType = 1; + remoteGlobalIDString = DA8933D41CCD306400E68420; + remoteInfo = bundle; + }; + DA25D5CB1CCDA0CC00607828 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DA1DC9421CB6C1C2006E619F /* Project object */; + proxyType = 1; + remoteGlobalIDString = DA25D5B81CCD9EDE00607828; + remoteInfo = settings; + }; DA2E88571CC036F400F24E7B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DA1DC9421CB6C1C2006E619F /* Project object */; @@ -264,8 +306,6 @@ DA1DC94A1CB6C1C2006E619F /* Mapbox GL.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Mapbox GL.app"; sourceTree = BUILT_PRODUCTS_DIR; }; DA1DC9501CB6C1C2006E619F /* MBXAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBXAppDelegate.h; sourceTree = ""; }; DA1DC9531CB6C1C2006E619F /* MBXViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBXViewController.h; sourceTree = ""; }; - DA1DC9571CB6C1C2006E619F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - DA1DC95C1CB6C1C2006E619F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; DA1DC95E1CB6C1C2006E619F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DA1DC9661CB6C6B7006E619F /* MBXCustomCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXCustomCalloutView.h; sourceTree = ""; }; DA1DC9671CB6C6B7006E619F /* MBXCustomCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXCustomCalloutView.m; sourceTree = ""; }; @@ -273,13 +313,15 @@ DA1DC9691CB6C6B7006E619F /* MBXOfflinePacksTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXOfflinePacksTableViewController.m; sourceTree = ""; }; DA1DC96C1CB6C6CE006E619F /* points.geojson */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = points.geojson; sourceTree = ""; }; DA1DC96D1CB6C6CE006E619F /* polyline.geojson */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = polyline.geojson; sourceTree = ""; }; - DA1DC96E1CB6C6CE006E619F /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Settings.bundle; path = ../framework/Settings.bundle; sourceTree = ""; }; DA1DC96F1CB6C6CE006E619F /* threestates.geojson */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = threestates.geojson; sourceTree = ""; }; DA1DC9961CB6E046006E619F /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; DA1DC9981CB6E054006E619F /* MBXAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXAppDelegate.m; sourceTree = ""; }; DA1DC99A1CB6E064006E619F /* MBXViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXViewController.m; sourceTree = ""; }; DA1DC99C1CB6E076006E619F /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; DA1DC99E1CB6E088006E619F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + DA25D5B91CCD9EDE00607828 /* Settings.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Settings.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + DA25D5BF1CCD9F8400607828 /* Root.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Root.plist; sourceTree = ""; }; + DA25D5C51CCDA06800607828 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Root.strings; sourceTree = ""; }; DA27C24D1CBB3811000B0ECD /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; }; DA2E88511CC036F400F24E7B /* test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = test.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DA2E88551CC036F400F24E7B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -301,6 +343,8 @@ DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSValue+MGLAdditions.m"; sourceTree = ""; }; DA35A2D11CCAB25200E826B2 /* jazzy.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = jazzy.yml; sourceTree = ""; }; DA4A26961CB6E795000B7809 /* Mapbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Mapbox.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DA821D041CCC6D59007508D4 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + DA821D051CCC6D59007508D4 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; DA8847D21CBAF91600AB86E3 /* Mapbox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Mapbox.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DA8847D61CBAF91600AB86E3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DA8847DF1CBAFA5100AB86E3 /* MGLAccountManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAccountManager.h; sourceTree = ""; }; @@ -387,6 +431,12 @@ DA88488A1CBB037E00AB86E3 /* SMCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMCalloutView.m; sourceTree = ""; }; DA88488D1CBB047F00AB86E3 /* reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = reachability.h; path = ../../include/mbgl/platform/darwin/reachability.h; sourceTree = ""; }; DA88488F1CBB048E00AB86E3 /* reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = reachability.m; path = src/reachability.m; sourceTree = ""; }; + DA8933A01CCC951200E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + DA8933BB1CCD2CA100E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Foundation.strings; sourceTree = ""; }; + DA8933BE1CCD2CAD00E68420 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Foundation.stringsdict; sourceTree = ""; }; + DA8933D51CCD306400E68420 /* Mapbox.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Mapbox.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + DA8933EF1CCD387900E68420 /* strip-frameworks.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = "strip-frameworks.sh"; path = "framework/strip-frameworks.sh"; sourceTree = SOURCE_ROOT; }; + DA8933F11CCD3FD700E68420 /* Info-static.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-static.plist"; sourceTree = ""; }; DA8963331CC549A100684375 /* glyphs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = glyphs; sourceTree = ""; }; DA8963341CC549A100684375 /* sprites */ = {isa = PBXFileReference; lastKnownFileType = folder; path = sprites; sourceTree = ""; }; DA8963351CC549A100684375 /* styles */ = {isa = PBXFileReference; lastKnownFileType = folder; path = styles; sourceTree = ""; }; @@ -479,6 +529,8 @@ DA8847D21CBAF91600AB86E3 /* Mapbox.framework */, DAA4E4131CBB71D400178DFB /* libMapbox.a */, DA2E88511CC036F400F24E7B /* test.xctest */, + DA8933D51CCD306400E68420 /* Mapbox.bundle */, + DA25D5B91CCD9EDE00607828 /* Settings.bundle */, ); name = Products; sourceTree = ""; @@ -494,13 +546,12 @@ DA1DC9691CB6C6B7006E619F /* MBXOfflinePacksTableViewController.m */, DA1DC9531CB6C1C2006E619F /* MBXViewController.h */, DA1DC99A1CB6E064006E619F /* MBXViewController.m */, - DA1DC9561CB6C1C2006E619F /* Main.storyboard */, - DA1DC95B1CB6C1C2006E619F /* LaunchScreen.storyboard */, + DA821D051CCC6D59007508D4 /* Main.storyboard */, + DA821D041CCC6D59007508D4 /* LaunchScreen.storyboard */, DA1DC99E1CB6E088006E619F /* Assets.xcassets */, DA1DC96C1CB6C6CE006E619F /* points.geojson */, DA1DC96D1CB6C6CE006E619F /* polyline.geojson */, DA1DC96F1CB6C6CE006E619F /* threestates.geojson */, - DA1DC96E1CB6C6CE006E619F /* Settings.bundle */, DA1DC95E1CB6C1C2006E619F /* Info.plist */, DA1DC99C1CB6E076006E619F /* Default-568h@2x.png */, DA1DC94D1CB6C1C2006E619F /* Supporting Files */, @@ -531,6 +582,16 @@ name = Frameworks; sourceTree = ""; }; + DA25D5BA1CCD9EDE00607828 /* Example Settings Bundle */ = { + isa = PBXGroup; + children = ( + DA25D5BF1CCD9F8400607828 /* Root.plist */, + DA25D5C41CCDA06800607828 /* Root.strings */, + ); + name = "Example Settings Bundle"; + path = Settings.bundle; + sourceTree = ""; + }; DA2E88521CC036F400F24E7B /* SDK Tests */ = { isa = PBXGroup; children = ( @@ -553,9 +614,12 @@ children = ( DA88485E1CBAFC2E00AB86E3 /* Mapbox.h */, DA8847DE1CBAFA3E00AB86E3 /* Foundation */, + DA8933B91CCD2C6700E68420 /* Foundation Resources */, DA8848331CBAFB2A00AB86E3 /* Kit */, - DA8848621CBAFCC100AB86E3 /* Resources */, + DA8848621CBAFCC100AB86E3 /* Kit Resources */, + DA25D5BA1CCD9EDE00607828 /* Example Settings Bundle */, DA8847D61CBAF91600AB86E3 /* Info.plist */, + DA8933F11CCD3FD700E68420 /* Info-static.plist */, ); name = SDK; path = framework; @@ -652,11 +716,13 @@ path = src; sourceTree = SOURCE_ROOT; }; - DA8848621CBAFCC100AB86E3 /* Resources */ = { + DA8848621CBAFCC100AB86E3 /* Kit Resources */ = { isa = PBXGroup; children = ( + DA89339F1CCC951200E68420 /* Localizable.strings */, DA8848771CBAFD5C00AB86E3 /* api_mapbox_com-digicert.der */, DA8848781CBAFD5C00AB86E3 /* api_mapbox_com-geotrust.der */, + DA8848791CBAFD5C00AB86E3 /* star_tilestream_net.der */, DA8848631CBAFCC100AB86E3 /* Compass.png */, DA8848641CBAFCC100AB86E3 /* Compass@2x.png */, DA8848651CBAFCC100AB86E3 /* Compass@3x.png */, @@ -666,9 +732,9 @@ DA8848691CBAFCC100AB86E3 /* mapbox.png */, DA88486A1CBAFCC100AB86E3 /* mapbox@2x.png */, DA88486B1CBAFCC100AB86E3 /* mapbox@3x.png */, - DA8848791CBAFD5C00AB86E3 /* star_tilestream_net.der */, + DA8933EF1CCD387900E68420 /* strip-frameworks.sh */, ); - name = Resources; + name = "Kit Resources"; path = resources; sourceTree = SOURCE_ROOT; }; @@ -704,6 +770,16 @@ path = ..; sourceTree = ""; }; + DA8933B91CCD2C6700E68420 /* Foundation Resources */ = { + isa = PBXGroup; + children = ( + DA8933BA1CCD2CA100E68420 /* Foundation.strings */, + DA8933BD1CCD2CAD00E68420 /* Foundation.stringsdict */, + ); + name = "Foundation Resources"; + path = ../../darwin/resources; + sourceTree = ""; + }; DA8963321CC5498400684375 /* Fixtures */ = { isa = PBXGroup; children = ( @@ -870,6 +946,21 @@ productReference = DA1DC94A1CB6C1C2006E619F /* Mapbox GL.app */; productType = "com.apple.product-type.application"; }; + DA25D5B81CCD9EDE00607828 /* settings */ = { + isa = PBXNativeTarget; + buildConfigurationList = DA25D5BE1CCD9EDE00607828 /* Build configuration list for PBXNativeTarget "settings" */; + buildPhases = ( + DA25D5B71CCD9EDE00607828 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = settings; + productName = settings; + productReference = DA25D5B91CCD9EDE00607828 /* Settings.bundle */; + productType = "com.apple.product-type.bundle"; + }; DA2E88501CC036F400F24E7B /* test */ = { isa = PBXNativeTarget; buildConfigurationList = DA2E88591CC036F400F24E7B /* Build configuration list for PBXNativeTarget "test" */; @@ -900,12 +991,28 @@ buildRules = ( ); dependencies = ( + DA25D5C81CCDA0C100607828 /* PBXTargetDependency */, ); name = dynamic; productName = framework; productReference = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; productType = "com.apple.product-type.framework"; }; + DA8933D41CCD306400E68420 /* bundle */ = { + isa = PBXNativeTarget; + buildConfigurationList = DA8933D81CCD306400E68420 /* Build configuration list for PBXNativeTarget "bundle" */; + buildPhases = ( + DA8933D31CCD306400E68420 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = bundle; + productName = bundle; + productReference = DA8933D51CCD306400E68420 /* Mapbox.bundle */; + productType = "com.apple.product-type.bundle"; + }; DAA4E4121CBB71D400178DFB /* static */ = { isa = PBXNativeTarget; buildConfigurationList = DAA4E4191CBB71D500178DFB /* Build configuration list for PBXNativeTarget "static" */; @@ -918,6 +1025,8 @@ buildRules = ( ); dependencies = ( + DA25D5CA1CCDA0CC00607828 /* PBXTargetDependency */, + DA25D5CC1CCDA0CC00607828 /* PBXTargetDependency */, ); name = static; productName = static; @@ -956,12 +1065,18 @@ DA1DC9491CB6C1C2006E619F = { CreatedOnToolsVersion = 7.3; }; + DA25D5B81CCD9EDE00607828 = { + CreatedOnToolsVersion = 7.3; + }; DA2E88501CC036F400F24E7B = { CreatedOnToolsVersion = 7.3; }; DA8847D11CBAF91600AB86E3 = { CreatedOnToolsVersion = 7.3; }; + DA8933D41CCD306400E68420 = { + CreatedOnToolsVersion = 7.3; + }; DAA4E4121CBB71D400178DFB = { CreatedOnToolsVersion = 7.3; }; @@ -987,6 +1102,8 @@ DABCABA71CB80692000A7C39 /* bench */, DA8847D11CBAF91600AB86E3 /* dynamic */, DAA4E4121CBB71D400178DFB /* static */, + DA8933D41CCD306400E68420 /* bundle */, + DA25D5B81CCD9EDE00607828 /* settings */, DA2E88501CC036F400F24E7B /* test */, ); }; @@ -997,14 +1114,23 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - DA4A26941CB6E337000B7809 /* Main.storyboard in Resources */, - DA4A26951CB6E337000B7809 /* LaunchScreen.storyboard in Resources */, + DA25D5CD1CCDA11500607828 /* Settings.bundle in Resources */, DA1DC9701CB6C6CE006E619F /* points.geojson in Resources */, DA1DC9711CB6C6CE006E619F /* polyline.geojson in Resources */, DA1DC99D1CB6E076006E619F /* Default-568h@2x.png in Resources */, + DA821D071CCC6D59007508D4 /* Main.storyboard in Resources */, DA1DC9731CB6C6CE006E619F /* threestates.geojson in Resources */, + DA821D061CCC6D59007508D4 /* LaunchScreen.storyboard in Resources */, DA1DC99F1CB6E088006E619F /* Assets.xcassets in Resources */, - DA1DC9721CB6C6CE006E619F /* Settings.bundle in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA25D5B71CCD9EDE00607828 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DA25D5C61CCDA06800607828 /* Root.strings in Resources */, + DA25D5C01CCD9F8400607828 /* Root.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1020,8 +1146,10 @@ buildActionMask = 2147483647; files = ( DA8848731CBAFCC100AB86E3 /* mapbox.png in Resources */, + DA8933BC1CCD2CA100E68420 /* Foundation.strings in Resources */, DA8848741CBAFCC100AB86E3 /* mapbox@2x.png in Resources */, DA88487A1CBAFD5C00AB86E3 /* api_mapbox_com-digicert.der in Resources */, + DA8933A31CCC95B000E68420 /* Localizable.strings in Resources */, DA88486D1CBAFCC100AB86E3 /* Compass.png in Resources */, DA8848721CBAFCC100AB86E3 /* default_marker@3x.png in Resources */, DA88487C1CBAFD5C00AB86E3 /* star_tilestream_net.der in Resources */, @@ -1029,8 +1157,32 @@ DA88486E1CBAFCC100AB86E3 /* Compass@2x.png in Resources */, DA8848701CBAFCC100AB86E3 /* default_marker.png in Resources */, DA8848711CBAFCC100AB86E3 /* default_marker@2x.png in Resources */, + DA8933F01CCD387900E68420 /* strip-frameworks.sh in Resources */, DA8848751CBAFCC100AB86E3 /* mapbox@3x.png in Resources */, DA88487B1CBAFD5C00AB86E3 /* api_mapbox_com-geotrust.der in Resources */, + DA8933BF1CCD2CAD00E68420 /* Foundation.stringsdict in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DA8933D31CCD306400E68420 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DA8933E01CCD31DF00E68420 /* Localizable.strings in Resources */, + DA8933E11CCD31DF00E68420 /* Compass.png in Resources */, + DA8933E21CCD31DF00E68420 /* Compass@2x.png in Resources */, + DA8933E31CCD31DF00E68420 /* Compass@3x.png in Resources */, + DA8933E41CCD31DF00E68420 /* default_marker.png in Resources */, + DA8933E51CCD31DF00E68420 /* default_marker@2x.png in Resources */, + DA8933E61CCD31DF00E68420 /* default_marker@3x.png in Resources */, + DA8933E71CCD31DF00E68420 /* mapbox.png in Resources */, + DA8933E81CCD31DF00E68420 /* mapbox@2x.png in Resources */, + DA8933E91CCD31DF00E68420 /* mapbox@3x.png in Resources */, + DA8933DB1CCD31D400E68420 /* Foundation.strings in Resources */, + DA8933DC1CCD31D400E68420 /* Foundation.stringsdict in Resources */, + DA8933DD1CCD31D400E68420 /* api_mapbox_com-digicert.der in Resources */, + DA8933DE1CCD31D400E68420 /* api_mapbox_com-geotrust.der in Resources */, + DA8933DF1CCD31D400E68420 /* star_tilestream_net.der in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1165,6 +1317,21 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + DA25D5C81CCDA0C100607828 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DA25D5B81CCD9EDE00607828 /* settings */; + targetProxy = DA25D5C71CCDA0C100607828 /* PBXContainerItemProxy */; + }; + DA25D5CA1CCDA0CC00607828 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DA8933D41CCD306400E68420 /* bundle */; + targetProxy = DA25D5C91CCDA0CC00607828 /* PBXContainerItemProxy */; + }; + DA25D5CC1CCDA0CC00607828 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DA25D5B81CCD9EDE00607828 /* settings */; + targetProxy = DA25D5CB1CCDA0CC00607828 /* PBXContainerItemProxy */; + }; DA2E88581CC036F400F24E7B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DA8847D11CBAF91600AB86E3 /* dynamic */; @@ -1183,20 +1350,36 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - DA1DC9561CB6C1C2006E619F /* Main.storyboard */ = { + DA25D5C41CCDA06800607828 /* Root.strings */ = { isa = PBXVariantGroup; children = ( - DA1DC9571CB6C1C2006E619F /* Base */, + DA25D5C51CCDA06800607828 /* Base */, ); - name = Main.storyboard; + name = Root.strings; sourceTree = ""; }; - DA1DC95B1CB6C1C2006E619F /* LaunchScreen.storyboard */ = { + DA89339F1CCC951200E68420 /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( - DA1DC95C1CB6C1C2006E619F /* Base */, + DA8933A01CCC951200E68420 /* Base */, ); - name = LaunchScreen.storyboard; + name = Localizable.strings; + sourceTree = ""; + }; + DA8933BA1CCD2CA100E68420 /* Foundation.strings */ = { + isa = PBXVariantGroup; + children = ( + DA8933BB1CCD2CA100E68420 /* Base */, + ); + name = Foundation.strings; + sourceTree = ""; + }; + DA8933BD1CCD2CAD00E68420 /* Foundation.stringsdict */ = { + isa = PBXVariantGroup; + children = ( + DA8933BE1CCD2CAD00E68420 /* en */, + ); + name = Foundation.stringsdict; sourceTree = ""; }; DABCABB81CB80692000A7C39 /* LaunchScreen.storyboard */ = { @@ -1230,6 +1413,9 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; + CURRENT_COMMIT_HASH = deadbeef; + CURRENT_SEMANTIC_VERSION = 1.0.0; + CURRENT_SHORT_VERSION = 1.0; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -1276,6 +1462,9 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; + CURRENT_COMMIT_HASH = deadbeef; + CURRENT_SEMANTIC_VERSION = 1.0.0; + CURRENT_SHORT_VERSION = 1.0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1320,6 +1509,24 @@ }; name = Release; }; + DA25D5BC1CCD9EDE00607828 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = Settings; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + DA25D5BD1CCD9EDE00607828 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = Settings; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; DA2E885A1CC036F400F24E7B /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = DAC07C961CBB2CD6000CB309 /* mbgl.xcconfig */; @@ -1426,6 +1633,28 @@ }; name = Release; }; + DA8933D91CCD306400E68420 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "framework/Info-static.plist"; + PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.sdk.ios; + PRODUCT_NAME = Mapbox; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + DA8933DA1CCD306400E68420 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "framework/Info-static.plist"; + PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.sdk.ios; + PRODUCT_NAME = Mapbox; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; DAA4E41A1CBB71D500178DFB /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = DAC07C961CBB2CD6000CB309 /* mbgl.xcconfig */; @@ -1531,6 +1760,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + DA25D5BE1CCD9EDE00607828 /* Build configuration list for PBXNativeTarget "settings" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DA25D5BC1CCD9EDE00607828 /* Debug */, + DA25D5BD1CCD9EDE00607828 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; DA2E88591CC036F400F24E7B /* Build configuration list for PBXNativeTarget "test" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -1549,6 +1787,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + DA8933D81CCD306400E68420 /* Build configuration list for PBXNativeTarget "bundle" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DA8933D91CCD306400E68420 /* Debug */, + DA8933DA1CCD306400E68420 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; DAA4E4191CBB71D500178DFB /* Build configuration list for PBXNativeTarget "static" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme index 6db7f773c7e..8293b8e2a9d 100644 --- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme +++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme @@ -29,6 +29,15 @@ shouldUseLaunchSchemeArgsEnv = "YES"> + + + + diff --git a/platform/ios/resources/Base.lproj/Localizable.strings b/platform/ios/resources/Base.lproj/Localizable.strings new file mode 100644 index 00000000000..cf6de337c41 --- /dev/null +++ b/platform/ios/resources/Base.lproj/Localizable.strings @@ -0,0 +1,75 @@ +/* No comment provided by engineer. */ +"API_CLIENT_400_DESC" = "The session data task failed. Original request was: %@"; + +/* No comment provided by engineer. */ +"API_CLIENT_400_REASON" = "The status code was %ld"; + +/* No comment provided by engineer. */ +"CANCEL" = "Cancel"; + +/* Accessibility label */ +"COMPASS_A11Y_LABEL" = "Compass"; + +/* Compass abbreviation for north */ +"COMPASS_NORTH" = "N"; + +/* Copyright notice in attribution sheet */ +"COPY_MAPBOX" = "© Mapbox"; + +/* Copyright notice in attribution sheet */ +"COPY_OSM" = "© OpenStreetMap"; + +/* Instructions in Interface Builder designable; {key}, {plist file name} */ +"DESIGNABLE" = "To display a Mapbox-hosted map here, set %1$@ to your access token in %2$@\n\nFor detailed instructions, see:"; + +/* Setup documentation URL display string; keep as short as possible */ +"FIRST_STEPS_URL" = "mapbox.com/help/first-steps-ios-sdk"; + +/* Accessibility label */ +"INFO_A11Y_LABEL" = "Attribution info"; + +/* Accessibility label */ +"LOGO_A11Y_LABEL" = "Mapbox logo"; + +/* Accessibility label */ +"MAP_A11Y_LABEL" = "Map"; + +/* Action in attribution sheet */ +"MAP_FEEDBACK" = "Improve This Map"; + +/* Action sheet title */ +"SDK_NAME" = "Mapbox iOS SDK"; + +/* Telemetry prompt message */ +"TELEMETRY_DISABLED_MSG" = "You can help make OpenStreetMap and Mapbox maps better by contributing anonymous usage data."; + +/* Telemetry prompt button */ +"TELEMETRY_DISABLED_OFF" = "Don’t Participate"; + +/* Telemetry prompt button */ +"TELEMETRY_DISABLED_ON" = "Participate"; + +/* Telemetry prompt message */ +"TELEMETRY_ENABLED_MSG" = "You are helping to make OpenStreetMap and Mapbox maps better by contributing anonymous usage data."; + +/* Telemetry prompt button */ +"TELEMETRY_ENABLED_OFF" = "Stop Participating"; + +/* Telemetry prompt button */ +"TELEMETRY_ENABLED_ON" = "Keep Participating"; + +/* Telemetry prompt button */ +"TELEMETRY_MORE" = "Tell Me More"; + +/* Action in attribution sheet */ +"TELEMETRY_NAME" = "Mapbox Telemetry"; + +/* Telemetry prompt title */ +"TELEMETRY_TITLE" = "Make Mapbox Maps Better"; + +/* Accessibility label */ +"USER_DOT_A11Y_LABEL" = "User location"; + +/* Default user location annotation title */ +"USER_DOT_TITLE" = "You Are Here"; + diff --git a/platform/ios/resources/Compass.png b/platform/ios/resources/Compass.png index e6b0b52c586..08bed0591b4 100644 Binary files a/platform/ios/resources/Compass.png and b/platform/ios/resources/Compass.png differ diff --git a/platform/ios/resources/Compass@2x.png b/platform/ios/resources/Compass@2x.png index 2bd8a286dad..8473a2d1ecf 100644 Binary files a/platform/ios/resources/Compass@2x.png and b/platform/ios/resources/Compass@2x.png differ diff --git a/platform/ios/resources/Compass@3x.png b/platform/ios/resources/Compass@3x.png index 9308a46a510..9cf66ca483e 100644 Binary files a/platform/ios/resources/Compass@3x.png and b/platform/ios/resources/Compass@3x.png differ diff --git a/platform/ios/scripts/package.sh b/platform/ios/scripts/package.sh index e1f07ff435e..8f41003b79f 100755 --- a/platform/ios/scripts/package.sh +++ b/platform/ios/scripts/package.sh @@ -21,25 +21,19 @@ elif [[ ${FORMAT} == "dynamic" ]]; then BUILD_STATIC=false fi -BUNDLE_RESOURCES=${BUNDLE_RESOURCES:-} -BUNDLE_PATH= -if [[ ${BUNDLE_RESOURCES} ]]; then - BUNDLE_PATH="/${NAME}.bundle" -fi - -PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK=${PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK:-} -STATIC_BUNDLE_PATH= -if [[ ${PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK} ]]; then - STATIC_BUNDLE_PATH="${OUTPUT}/static${BUNDLE_PATH}" +SELF_CONTAINED=${SELF_CONTAINED:-} +STATIC_BUNDLE_DIR= +if [[ ${SELF_CONTAINED} ]]; then + STATIC_BUNDLE_DIR="${OUTPUT}/static/${NAME}.framework" else - STATIC_BUNDLE_PATH="${OUTPUT}/static/${NAME}.framework${BUNDLE_PATH}" + STATIC_BUNDLE_DIR="${OUTPUT}/static" fi -STATIC_SETTINGS_DIRECTORY= -if [[ ${PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK} ]]; then - STATIC_SETTINGS_DIRECTORY="${OUTPUT}" +STATIC_SETTINGS_DIR= +if [[ ${SELF_CONTAINED} ]]; then + STATIC_SETTINGS_DIR="${OUTPUT}/static/${NAME}.framework" else - STATIC_SETTINGS_DIRECTORY="${OUTPUT}/static/${NAME}.framework" + STATIC_SETTINGS_DIR="${OUTPUT}" fi SDK=iphonesimulator @@ -48,7 +42,7 @@ if [[ ${BUILD_FOR_DEVICE} == true ]]; then fi IOS_SDK_VERSION=`xcrun --sdk ${SDK} --show-sdk-version` -echo "Configuring ${FORMAT:-dynamic and static} ${BUILDTYPE} framework for ${SDK}; symbols: ${GCC_GENERATE_DEBUGGING_SYMBOLS}; Mapbox.bundle: ${BUNDLE_RESOURCES} bundle.outside: ${PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK}" +echo "Configuring ${FORMAT:-dynamic and static} ${BUILDTYPE} framework for ${SDK}; symbols: ${GCC_GENERATE_DEBUGGING_SYMBOLS}; self-contained static framework: ${SELF_CONTAINED:-NO}" function step { >&2 echo -e "\033[1m\033[36m* $@\033[0m"; } function finish { >&2 echo -en "\033[0m"; } @@ -71,10 +65,11 @@ echo -n "mapbox-gl-native " echo ${HASH} echo ${HASH} >> ${VERSION} - PROJ_VERSION=$(git rev-list --count HEAD) +SEM_VERSION=$( git describe --tags --match=ios-v*.*.* --abbrev=0 | sed 's/^ios-v//' ) +SHORT_VERSION=${SEM_VERSION%-*} -step "Building targets (build ${PROJ_VERSION})…" +step "Building targets (build ${PROJ_VERSION}, version ${SEM_VERSION})…" SCHEME='dynamic' if [[ ${BUILD_DYNAMIC} == true && ${BUILD_STATIC} == true ]]; then @@ -86,6 +81,9 @@ fi xcodebuild \ GCC_GENERATE_DEBUGGING_SYMBOLS=${GCC_GENERATE_DEBUGGING_SYMBOLS} \ CURRENT_PROJECT_VERSION=${PROJ_VERSION} \ + CURRENT_SHORT_VERSION=${SHORT_VERSION} \ + CURRENT_SEMANTIC_VERSION=${SEM_VERSION} \ + CURRENT_COMMIT_HASH=${HASH} \ -derivedDataPath ${DERIVED_DATA} \ -workspace ./platform/ios/ios.xcworkspace \ -scheme ${SCHEME} \ @@ -97,6 +95,9 @@ if [[ ${BUILD_FOR_DEVICE} == true ]]; then xcodebuild \ GCC_GENERATE_DEBUGGING_SYMBOLS=${GCC_GENERATE_DEBUGGING_SYMBOLS} \ CURRENT_PROJECT_VERSION=${PROJ_VERSION} \ + CURRENT_SHORT_VERSION=${SHORT_VERSION} \ + CURRENT_SEMANTIC_VERSION=${SEM_VERSION} \ + CURRENT_COMMIT_HASH=${HASH} \ -derivedDataPath ${DERIVED_DATA} \ -workspace ./platform/ios/ios.xcworkspace \ -scheme ${SCHEME} \ @@ -117,6 +118,8 @@ if [[ "${BUILD_FOR_DEVICE}" == true ]]; then -o ${OUTPUT}/static/${NAME}.framework/${NAME} \ ${LIBS[@]/#/${PRODUCTS}/${BUILDTYPE}-iphoneos/libmbgl-} \ ${LIBS[@]/#/${PRODUCTS}/${BUILDTYPE}-iphonesimulator/libmbgl-} + + cp -rv ${PRODUCTS}/${BUILDTYPE}-iphoneos/${NAME}.bundle ${STATIC_BUNDLE_DIR} fi if [[ ${BUILD_DYNAMIC} == true ]]; then @@ -135,6 +138,8 @@ if [[ "${BUILD_FOR_DEVICE}" == true ]]; then ${PRODUCTS}/${BUILDTYPE}-iphonesimulator/${NAME}.framework/${NAME} \ -create -output ${OUTPUT}/dynamic/${NAME}.framework/${NAME} | echo fi + + cp -rv ${PRODUCTS}/${BUILDTYPE}-iphoneos/Settings.bundle ${STATIC_SETTINGS_DIR} else if [[ ${BUILD_STATIC} == true ]]; then step "Assembling static library for iOS Simulator…" @@ -143,6 +148,8 @@ else `find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libgeojsonvt.a` \ -o ${OUTPUT}/static/${NAME}.framework/${NAME} \ ${LIBS[@]/#/${PRODUCTS}/${BUILDTYPE}-iphonesimulator/libmbgl-} + + cp -rv ${PRODUCTS}/${BUILDTYPE}-iphonesimulator/${NAME}.bundle ${STATIC_BUNDLE_DIR} fi if [[ ${BUILD_DYNAMIC} == true ]]; then @@ -155,6 +162,8 @@ else ${OUTPUT}/dynamic/ fi fi + + cp -rv ${PRODUCTS}/${BUILDTYPE}-iphonesimulator/Settings.bundle ${STATIC_SETTINGS_DIR} fi if [[ "${GCC_GENERATE_DEBUGGING_SYMBOLS}" == false ]]; then @@ -182,41 +191,13 @@ if [[ ${BUILD_STATIC} == true ]]; then fi step "Copying library resources…" -SEM_VERSION=$( git describe --tags --match=ios-v*.*.* --abbrev=0 | sed 's/^ios-v//' ) -SHORT_VERSION=${SEM_VERSION%-*} -if [[ ${BUNDLE_RESOURCES} ]]; then - cp -pv LICENSE.md ${STATIC_SETTINGS_DIRECTORY} - cp -rv platform/ios/framework/Settings.bundle ${STATIC_SETTINGS_DIRECTORY} -else - cp -pv LICENSE.md "${OUTPUT}" - cp -rv platform/ios/framework/Settings.bundle "${OUTPUT}" -fi +cp -pv LICENSE.md ${STATIC_SETTINGS_DIR} if [[ ${BUILD_STATIC} == true ]]; then - mkdir -p ${STATIC_BUNDLE_PATH} - cp -pv platform/{default,ios}/resources/* ${STATIC_BUNDLE_PATH} - INFO_PLIST_PATH="${OUTPUT}/static/${NAME}.framework/Info.plist" - cp -pv platform/ios/framework/Info.plist "${INFO_PLIST_PATH}" - plutil -remove CFBundleExecutable "${INFO_PLIST_PATH}" - plutil -remove CFBundlePackageType "${INFO_PLIST_PATH}" - plutil -replace CFBundleIdentifier -string com.mapbox.sdk.ios "${INFO_PLIST_PATH}" - plutil -replace CFBundleName -string ${NAME} "${INFO_PLIST_PATH}" - plutil -replace CFBundleShortVersionString -string "${SHORT_VERSION}" "${INFO_PLIST_PATH}" - plutil -replace CFBundleVersion -string ${PROJ_VERSION} "${INFO_PLIST_PATH}" - plutil -replace MGLSemanticVersionString -string "${SEM_VERSION}" "${INFO_PLIST_PATH}" - plutil -replace MGLCommitHash -string "${HASH}" "${INFO_PLIST_PATH}" - if [[ ${BUNDLE_RESOURCES} ]]; then - cp -pv "${INFO_PLIST_PATH}" "${STATIC_BUNDLE_PATH}/Info.plist" - fi + cp -pv "${STATIC_BUNDLE_DIR}/${NAME}.bundle/Info.plist" "${OUTPUT}/static/${NAME}.framework/Info.plist" + plutil -replace CFBundlePackageType -string FMWK "${OUTPUT}/static/${NAME}.framework/Info.plist" mkdir "${OUTPUT}/static/${NAME}.framework/Modules" cp -pv platform/ios/framework/modulemap "${OUTPUT}/static/${NAME}.framework/Modules/module.modulemap" fi -if [[ ${BUILD_DYNAMIC} == true ]]; then - plutil -replace CFBundleShortVersionString -string "${SHORT_VERSION}" "${OUTPUT}/dynamic/${NAME}.framework/Info.plist" - plutil -replace CFBundleVersion -string "${PROJ_VERSION}" "${OUTPUT}/dynamic/${NAME}.framework/Info.plist" - plutil -replace MGLSemanticVersionString -string "${SEM_VERSION}" "${OUTPUT}/dynamic/${NAME}.framework/Info.plist" - plutil -replace MGLCommitHash -string "${HASH}" "${OUTPUT}/dynamic/${NAME}.framework/Info.plist" - cp -pv platform/ios/framework/strip-frameworks.sh "${OUTPUT}/dynamic/${NAME}.framework/strip-frameworks.sh" -fi sed -n -e '/^## /,$p' platform/ios/CHANGELOG.md > "${OUTPUT}/CHANGELOG.md" rm -rf /tmp/mbgl diff --git a/platform/ios/src/MGLAPIClient.m b/platform/ios/src/MGLAPIClient.m index 62886713eb6..86f57e4e88b 100644 --- a/platform/ios/src/MGLAPIClient.m +++ b/platform/ios/src/MGLAPIClient.m @@ -47,8 +47,8 @@ - (void)postEvents:(nonnull NS_ARRAY_OF(MGLMapboxEventAttributes *) *)events com NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; NSError *statusError = nil; if (httpResponse.statusCode >= 400) { - NSString *description = [NSString stringWithFormat:NSLocalizedString(@"The session data task failed. Original request was: %@", nil), dataTask.originalRequest]; - NSString *reason = [NSString stringWithFormat:NSLocalizedString(@"The status code was %ld", nil), (long)httpResponse.statusCode]; + NSString *description = [NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"API_CLIENT_400_DESC", nil, nil, @"The session data task failed. Original request was: %@", nil), dataTask.originalRequest]; + NSString *reason = [NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"API_CLIENT_400_REASON", nil, nil, @"The status code was %ld", nil), (long)httpResponse.statusCode]; NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description, NSLocalizedFailureReasonErrorKey: reason}; statusError = [NSError errorWithDomain:MGLErrorDomain code:1 userInfo:userInfo]; diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 9f982f7843b..3d3666c6f65 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -27,9 +27,9 @@ #include #import "Mapbox.h" -#import "../../darwin/src/MGLGeometry_Private.h" -#import "../../darwin/src/MGLMultiPoint_Private.h" -#import "../../darwin/src/MGLOfflineStorage_Private.h" +#import "MGLGeometry_Private.h" +#import "MGLMultiPoint_Private.h" +#import "MGLOfflineStorage_Private.h" #import "NSBundle+MGLAdditions.h" #import "NSString+MGLAdditions.h" @@ -59,8 +59,6 @@ typedef NS_ENUM(NSUInteger, MGLUserTrackingState) { MGLUserTrackingStateChanged, }; -NSString *const MGLMapboxSetupDocumentationURLDisplayString = @"mapbox.com/help/first-steps-ios-sdk"; - const NSTimeInterval MGLAnimationDuration = 0.3; /// Duration of an animation due to a user location update, typically chosen to @@ -305,7 +303,7 @@ - (void)commonInit [self createGLView]; } - self.accessibilityLabel = @"Map"; + self.accessibilityLabel = NSLocalizedStringWithDefaultValue(@"MAP_A11Y_LABEL", nil, nil, @"Map", @"Accessibility label"); self.backgroundColor = [UIColor clearColor]; self.clipsToBounds = YES; @@ -350,7 +348,7 @@ - (void)commonInit // UIImage *logo = [[MGLMapView resourceImageNamed:@"mapbox.png"] imageWithAlignmentRectInsets:UIEdgeInsetsMake(1.5, 4, 3.5, 2)]; _logoView = [[UIImageView alloc] initWithImage:logo]; - _logoView.accessibilityLabel = @"Mapbox logo"; + _logoView.accessibilityLabel = NSLocalizedStringWithDefaultValue(@"LOGO_A11Y_LABEL", nil, nil, @"Mapbox logo", @"Accessibility label"); _logoView.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:_logoView]; _logoViewConstraints = [NSMutableArray array]; @@ -358,7 +356,7 @@ - (void)commonInit // setup attribution // _attributionButton = [UIButton buttonWithType:UIButtonTypeInfoLight]; - _attributionButton.accessibilityLabel = @"Attribution info"; + _attributionButton.accessibilityLabel = NSLocalizedStringWithDefaultValue(@"INFO_A11Y_LABEL", nil, nil, @"Attribution info", @"Accessibility label"); [_attributionButton addTarget:self action:@selector(showAttribution) forControlEvents:UIControlEventTouchUpInside]; _attributionButton.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:_attributionButton]; @@ -367,8 +365,8 @@ - (void)commonInit // setup compass // - _compassView = [[UIImageView alloc] initWithImage:[MGLMapView resourceImageNamed:@"Compass.png"]]; - _compassView.accessibilityLabel = @"Compass"; + _compassView = [[UIImageView alloc] initWithImage:self.compassImage]; + _compassView.accessibilityLabel = NSLocalizedStringWithDefaultValue(@"COMPASS_A11Y_LABEL", nil, nil, @"Compass", @"Accessibility label"); _compassView.frame = CGRectMake(0, 0, _compassView.image.size.width, _compassView.image.size.height); _compassView.alpha = 0; _compassView.userInteractionEnabled = YES; @@ -493,6 +491,26 @@ - (void)createGLView }); } +- (UIImage *)compassImage +{ + UIImage *scaleImage = [MGLMapView resourceImageNamed:@"Compass.png"]; + UIGraphicsBeginImageContextWithOptions(scaleImage.size, NO, [UIScreen mainScreen].scale); + [scaleImage drawInRect:{ CGPointZero, scaleImage.size }]; + + NSAttributedString *north = [[NSAttributedString alloc] initWithString:NSLocalizedStringWithDefaultValue(@"COMPASS_NORTH", nil, nil, @"N", @"Compass abbreviation for north") attributes:@{ + NSFontAttributeName: [UIFont systemFontOfSize:9 weight:UIFontWeightUltraLight], + NSForegroundColorAttributeName: [UIColor whiteColor], + }]; + CGRect stringRect = CGRectMake((scaleImage.size.width - north.size.width) / 2, + scaleImage.size.height * 0.45, + north.size.width, north.size.height); + [north drawInRect:stringRect]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; +} + - (void)reachabilityChanged:(NSNotification *)notification { MGLReachability *reachability = [notification object]; @@ -1518,15 +1536,15 @@ - (void)showAttribution { if ( ! self.attributionSheet) { - self.attributionSheet = [[UIActionSheet alloc] initWithTitle:@"Mapbox iOS SDK" + self.attributionSheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedStringWithDefaultValue(@"SDK_NAME", nil, nil, @"Mapbox iOS SDK", @"Action sheet title") delegate:self - cancelButtonTitle:@"Cancel" + cancelButtonTitle:NSLocalizedStringWithDefaultValue(@"CANCEL", nil, nil, @"Cancel", @"") destructiveButtonTitle:nil otherButtonTitles: - @"© Mapbox", - @"© OpenStreetMap", - @"Improve This Map", - @"Mapbox Telemetry", + NSLocalizedStringWithDefaultValue(@"COPY_MAPBOX", nil, nil, @"© Mapbox", @"Copyright notice in attribution sheet"), + NSLocalizedStringWithDefaultValue(@"COPY_OSM", nil, nil, @"© OpenStreetMap", @"Copyright notice in attribution sheet"), + NSLocalizedStringWithDefaultValue(@"MAP_FEEDBACK", nil, nil, @"Improve This Map", @"Action in attribution sheet"), + NSLocalizedStringWithDefaultValue(@"TELEMETRY_NAME", nil, nil, @"Mapbox Telemetry", @"Action in attribution sheet"), nil]; } @@ -1561,22 +1579,22 @@ - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSIn if ([[NSUserDefaults standardUserDefaults] boolForKey:@"MGLMapboxMetricsEnabled"]) { - message = @"You are helping to make OpenStreetMap and Mapbox maps better by contributing anonymous usage data."; - participate = @"Keep Participating"; - optOut = @"Stop Participating"; + message = NSLocalizedStringWithDefaultValue(@"TELEMETRY_ENABLED_MSG", nil, nil, @"You are helping to make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.", @"Telemetry prompt message"); + participate = NSLocalizedStringWithDefaultValue(@"TELEMETRY_ENABLED_ON", nil, nil, @"Keep Participating", @"Telemetry prompt button"); + optOut = NSLocalizedStringWithDefaultValue(@"TELEMETRY_ENABLED_OFF", nil, nil, @"Stop Participating", @"Telemetry prompt button"); } else { - message = @"You can help make OpenStreetMap and Mapbox maps better by contributing anonymous usage data."; - participate = @"Participate"; - optOut = @"Don’t Participate"; + message = NSLocalizedStringWithDefaultValue(@"TELEMETRY_DISABLED_MSG", nil, nil, @"You can help make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.", @"Telemetry prompt message"); + participate = NSLocalizedStringWithDefaultValue(@"TELEMETRY_DISABLED_ON", nil, nil, @"Participate", @"Telemetry prompt button"); + optOut = NSLocalizedStringWithDefaultValue(@"TELEMETRY_DISABLED_OFF", nil, nil, @"Don’t Participate", @"Telemetry prompt button"); } - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Make Mapbox Maps Better" + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedStringWithDefaultValue(@"TELEMETRY_TITLE", nil, nil, @"Make Mapbox Maps Better", @"Telemetry prompt title") message:message delegate:self cancelButtonTitle:participate - otherButtonTitles:@"Tell Me More", optOut, nil]; + otherButtonTitles:NSLocalizedStringWithDefaultValue(@"TELEMETRY_MORE", nil, nil, @"Tell Me More", @"Telemetry prompt button"), optOut, nil]; [alert show]; } } @@ -1590,7 +1608,7 @@ - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger) else if (buttonIndex == alertView.firstOtherButtonIndex) { [[UIApplication sharedApplication] openURL: - [NSURL URLWithString:@"https://mapbox.com/telemetry/"]]; + [NSURL URLWithString:@"https://www.mapbox.com/telemetry/"]]; } else if (buttonIndex == alertView.firstOtherButtonIndex + 1) { @@ -4042,7 +4060,7 @@ - (void)prepareForInterfaceBuilder // Headline UILabel *headlineLabel = [[UILabel alloc] init]; - headlineLabel.text = @"MGLMapView"; + headlineLabel.text = NSStringFromClass([self class]); headlineLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; headlineLabel.textAlignment = NSTextAlignmentCenter; headlineLabel.numberOfLines = 1; @@ -4053,8 +4071,7 @@ - (void)prepareForInterfaceBuilder // Explanation UILabel *explanationLabel = [[UILabel alloc] init]; - explanationLabel.text = (@"To display a Mapbox-hosted map here, set MGLMapboxAccessToken to your access token in Info.plist\n\n" - @"For detailed instructions, see:"); + explanationLabel.text = [NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"DESIGNABLE", nil, nil, @"To display a Mapbox-hosted map here, set %@ to your access token in %@\n\nFor detailed instructions, see:", @"Instructions in Interface Builder designable; {key}, {plist file name}"), @"MGLMapboxAccessToken", @"Info.plist"]; explanationLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; explanationLabel.numberOfLines = 0; explanationLabel.translatesAutoresizingMaskIntoConstraints = NO; @@ -4064,7 +4081,7 @@ - (void)prepareForInterfaceBuilder // Link UIButton *linkButton = [UIButton buttonWithType:UIButtonTypeSystem]; - [linkButton setTitle:MGLMapboxSetupDocumentationURLDisplayString forState:UIControlStateNormal]; + [linkButton setTitle:NSLocalizedStringWithDefaultValue(@"FIRST_STEPS_URL", nil, nil, @"mapbox.com/help/first-steps-ios-sdk", @"Setup documentation URL display string; keep as short as possible") forState:UIControlStateNormal]; linkButton.translatesAutoresizingMaskIntoConstraints = NO; linkButton.titleLabel.numberOfLines = 0; [linkButton setContentCompressionResistancePriority:UILayoutPriorityDefaultLow diff --git a/platform/ios/src/MGLUserLocation.m b/platform/ios/src/MGLUserLocation.m index 0ee90a3c2c9..a568ec8be1e 100644 --- a/platform/ios/src/MGLUserLocation.m +++ b/platform/ios/src/MGLUserLocation.m @@ -1,6 +1,7 @@ #import "MGLUserLocation_Private.h" #import "MGLMapView.h" +#import "NSBundle+MGLAdditions.h" NS_ASSUME_NONNULL_BEGIN @@ -68,7 +69,7 @@ - (CLLocationCoordinate2D)coordinate - (NSString *)title { - return (_title ? _title : @"You Are Here"); + return _title ?: NSLocalizedStringWithDefaultValue(@"USER_DOT_TITLE", nil, nil, @"You Are Here", @"Default user location annotation title"); } - (NSString *)description diff --git a/platform/ios/src/MGLUserLocationAnnotationView.m b/platform/ios/src/MGLUserLocationAnnotationView.m index ac8dd0790b8..be93b788418 100644 --- a/platform/ios/src/MGLUserLocationAnnotationView.m +++ b/platform/ios/src/MGLUserLocationAnnotationView.m @@ -4,6 +4,7 @@ #import "MGLUserLocation_Private.h" #import "MGLAnnotation.h" #import "MGLMapView.h" +#import "NSBundle+MGLAdditions.h" const CGFloat MGLUserLocationAnnotationDotSize = 22.0; const CGFloat MGLUserLocationAnnotationHaloSize = 115.0; @@ -53,7 +54,7 @@ - (instancetype)initInMapView:(MGLMapView *)mapView self.annotation = [[MGLUserLocation alloc] initWithMapView:mapView]; _mapView = mapView; [self setupLayers]; - self.accessibilityLabel = @"User location"; + self.accessibilityLabel = NSLocalizedStringWithDefaultValue(@"USER_DOT_A11Y_LABEL", nil, nil, @"User location", @"Accessibility label"); } return self; } diff --git a/platform/ios/uitest/Images.xcassets/AppIcon.appiconset/Contents.json b/platform/ios/uitest/Images.xcassets/AppIcon.appiconset/Contents.json index f535da681c6..eeea76c2db5 100644 --- a/platform/ios/uitest/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/platform/ios/uitest/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,10 +1,5 @@ { "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "1x" - }, { "idiom" : "iphone", "size" : "29x29", @@ -25,16 +20,6 @@ "size" : "40x40", "scale" : "3x" }, - { - "idiom" : "iphone", - "size" : "57x57", - "scale" : "1x" - }, - { - "idiom" : "iphone", - "size" : "57x57", - "scale" : "2x" - }, { "idiom" : "iphone", "size" : "60x60", @@ -65,26 +50,6 @@ "size" : "40x40", "scale" : "2x" }, - { - "idiom" : "ipad", - "size" : "50x50", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "50x50", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "72x72", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "72x72", - "scale" : "2x" - }, { "idiom" : "ipad", "size" : "76x76", @@ -99,65 +64,6 @@ "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" - }, - { - "size" : "24x24", - "idiom" : "watch", - "scale" : "2x", - "role" : "notificationCenter", - "subtype" : "38mm" - }, - { - "size" : "27.5x27.5", - "idiom" : "watch", - "scale" : "2x", - "role" : "notificationCenter", - "subtype" : "42mm" - }, - { - "size" : "29x29", - "idiom" : "watch", - "role" : "companionSettings", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "watch", - "role" : "companionSettings", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "watch", - "scale" : "2x", - "role" : "appLauncher", - "subtype" : "38mm" - }, - { - "size" : "44x44", - "idiom" : "watch", - "scale" : "2x", - "role" : "longLook", - "subtype" : "42mm" - }, - { - "size" : "86x86", - "idiom" : "watch", - "scale" : "2x", - "role" : "quickLook", - "subtype" : "38mm" - }, - { - "size" : "98x98", - "idiom" : "watch", - "scale" : "2x", - "role" : "quickLook", - "subtype" : "42mm" - }, - { - "idiom" : "car", - "size" : "120x120", - "scale" : "1x" } ], "info" : { diff --git a/platform/ios/uitest/ios-tests.xcodeproj/project.pbxproj b/platform/ios/uitest/ios-tests.xcodeproj/project.pbxproj index f033d51da38..1e932090990 100644 --- a/platform/ios/uitest/ios-tests.xcodeproj/project.pbxproj +++ b/platform/ios/uitest/ios-tests.xcodeproj/project.pbxproj @@ -400,7 +400,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; - SYMROOT = "../../../build/ios"; + SYMROOT = ../../../build/ios; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -434,7 +434,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; SDKROOT = iphoneos; - SYMROOT = "../../../build/ios"; + SYMROOT = ../../../build/ios; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -445,10 +445,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/../../../build/ios/pkg/dynamic/", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "$(SRCROOT)/App-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -466,10 +463,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/../../../build/ios/pkg/dynamic/", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "$(SRCROOT)/App-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; diff --git a/platform/osx/DEVELOPING.md b/platform/osx/DEVELOPING.md index 4b071138473..dcba9db1a14 100644 --- a/platform/osx/DEVELOPING.md +++ b/platform/osx/DEVELOPING.md @@ -2,21 +2,51 @@ This document explains how to build the Mapbox OS X SDK from source. It is intended for advanced developers who wish to contribute to Mapbox GL and the Mapbox iOS SDK. -### Requirements +## Requirements The Mapbox OS X SDK and the osxapp demo application run on OS X 10.10.0 and above. -### Build +## Building the SDK 1. [Install core dependencies](../../INSTALL.md). 1. Run `make xproj`. -1. Switch to the dynamic or osxapp scheme. The former builds just the Cocoa framework, while the latter also builds a Cocoa demo application based on it. +1. Switch to the “dynamic” or “osxapp” scheme. The former builds just the Cocoa framework, while the latter also builds a Cocoa demo application based on it. -### Access tokens +## Contributing + +### Adding a source code file + +To add an Objective-C header or implementation file to the OS X SDK: + +1. Add the file to the “dynamic” target’s Headers or Compile Sources build phase, as appropriate. You can either use the Build Phases tab of the project editor or the Target Membership section of the File inspector. +1. _(Optional.)_ If it’s a public header, change its visibility from Project to Public and import it in [the OS X SDK’s umbrella header](./src/Mapbox.h). +1. _(Optional.)_ If the file would also be used by the iOS SDK, make sure it’s in [platform/darwin/src/](../darwin/src/), then consult [the companion iOS document](../ios/DEVELOPING.md#adding-a-source-code-file) for further instructions. + +### Adding a resource + +To add a resource (such as an image, SSL certificate, property list, or strings table) to the OS X SDK: + +1. Add the header to the Copy Bundle Resources build phase of the “dynamic” target. You can either use the Build Phases tab of the project editor or the Target Membership section of the File inspector. +1. _(Optional.)_ If the resource would also be used by the iOS SDK, make sure it’s in [platform/darwin/resources/](../darwin/resources/), then consult [the companion iOS document](../ios/DEVELOPING.md#adding-a-resource) for further instructions. + +### Adding user-facing text + +To add or update text that the user may see in the OS X SDK: + +1. Make sure the implementation file imports [NSBundle+MGLAdditions.h](../darwin/src/NSBundle+MGLAdditions.h). +1. Use the `NSLocalizedStringWithDefaultValue()` macro: + * `key` is a unique identifier that won’t change if the user-facing text ever needs to change. + * `tbl` is `Foundation` in code shared between the iOS and OS X SDKs, or `nil` otherwise. + * `bundle` is `nil`; the redefined macro looks for the SDK bundle at runtime and ignores this argument. + * `val` is the English string. +1. _(Optional.)_ When dealing with a number followed by a pluralized word, do not split the string. Instead, use a format string and make `val` ambiguous, like `%d file(s)`. Then pluralize for English in the appropriate [.stringsdict file](https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html). See [platform/darwin/resources/en.lproj/Foundation.stringsdict](../darwin/resources/en.lproj/Foundation.stringsdict) for an example. Localizers should do likewise for their languages. +1. Run `make genstrings` and commit any changes it makes to .strings files. The make rule also updates the iOS SDK’s strings tables. + +## Access tokens The demo applications use Mapbox vector tiles, which require a Mapbox account and API access token. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). You will be prompted for this access token the first time you launch the demo application. -### Usage +## Using osxapp Through the OS X SDK, the demo application supports a variety of standard gestures and keyboard shortcuts. For more details, open Mapbox GL Help from the Help menu. diff --git a/platform/osx/app/LocationCoordinate2DTransformer.m b/platform/osx/app/LocationCoordinate2DTransformer.m index aeede234976..f58dfecc062 100644 --- a/platform/osx/app/LocationCoordinate2DTransformer.m +++ b/platform/osx/app/LocationCoordinate2DTransformer.m @@ -25,7 +25,7 @@ - (id)transformedValue:(id)value { if (![value isKindOfClass:[NSValue class]]) { return nil; } - return [_coordinateFormatter stringForObjectValue:value]; + return [_coordinateFormatter stringForObjectValue:value].localizedCapitalizedString; } @end diff --git a/platform/osx/osx.xcodeproj/project.pbxproj b/platform/osx/osx.xcodeproj/project.pbxproj index d3c2f8c9bb3..4a74f352f9c 100644 --- a/platform/osx/osx.xcodeproj/project.pbxproj +++ b/platform/osx/osx.xcodeproj/project.pbxproj @@ -25,6 +25,10 @@ DA839EA01CC2E3400062CAFB /* MapDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA839E9E1CC2E3400062CAFB /* MapDocument.xib */; }; DA839EA21CC2E3400062CAFB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA839EA11CC2E3400062CAFB /* Assets.xcassets */; }; DA839EA51CC2E3400062CAFB /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA839EA31CC2E3400062CAFB /* MainMenu.xib */; }; + DA8933A51CCD287300E68420 /* MGLAnnotationCallout.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA8933A71CCD287300E68420 /* MGLAnnotationCallout.xib */; }; + DA8933AE1CCD290700E68420 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA8933AB1CCD290700E68420 /* Localizable.strings */; }; + DA8933B51CCD2C2500E68420 /* Foundation.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA8933B31CCD2C2500E68420 /* Foundation.strings */; }; + DA8933B81CCD2C2D00E68420 /* Foundation.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DA8933B61CCD2C2D00E68420 /* Foundation.stringsdict */; }; DAC2ABC51CC6D343006D18C4 /* MGLAnnotationImage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */; }; DAE6C2E21CC304F900DB3429 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = DAE6C2E11CC304F900DB3429 /* Credits.rtf */; }; DAE6C2ED1CC3050F00DB3429 /* DroppedPinAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C2E41CC3050F00DB3429 /* DroppedPinAnnotation.m */; }; @@ -94,7 +98,6 @@ DAE6C3BA1CC31EF300DB3429 /* MGLOpenGLLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C3B01CC31EF300DB3429 /* MGLOpenGLLayer.mm */; }; DAE6C3BE1CC31F2E00DB3429 /* default_marker.pdf in Resources */ = {isa = PBXBuildFile; fileRef = DAE6C3BB1CC31F2E00DB3429 /* default_marker.pdf */; }; DAE6C3BF1CC31F2E00DB3429 /* mapbox.pdf in Resources */ = {isa = PBXBuildFile; fileRef = DAE6C3BC1CC31F2E00DB3429 /* mapbox.pdf */; }; - DAE6C3C01CC31F2E00DB3429 /* MGLAnnotationCallout.xib in Resources */ = {isa = PBXBuildFile; fileRef = DAE6C3BD1CC31F2E00DB3429 /* MGLAnnotationCallout.xib */; }; DAE6C3C21CC31F4500DB3429 /* Mapbox.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE6C3C11CC31F4500DB3429 /* Mapbox.h */; settings = {ATTRIBUTES = (Public, ); }; }; DAE6C3C71CC3499100DB3429 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE6C3C61CC3499100DB3429 /* libsqlite3.tbd */; }; DAE6C3D21CC34C9900DB3429 /* MGLGeometryTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C3C81CC34BD800DB3429 /* MGLGeometryTests.mm */; }; @@ -165,6 +168,10 @@ DA839EA11CC2E3400062CAFB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; DA839EA41CC2E3400062CAFB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; DA839EA61CC2E3400062CAFB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DA8933A61CCD287300E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MGLAnnotationCallout.xib; sourceTree = ""; }; + DA8933AC1CCD290700E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + DA8933B41CCD2C2500E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Foundation.strings; sourceTree = ""; }; + DA8933B71CCD2C2D00E68420 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Foundation.stringsdict; sourceTree = ""; }; DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationImage_Private.h; sourceTree = ""; }; DAE6C2E11CC304F900DB3429 /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = ""; }; DAE6C2E31CC3050F00DB3429 /* DroppedPinAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DroppedPinAnnotation.h; sourceTree = ""; }; @@ -238,8 +245,7 @@ DAE6C3AF1CC31EF300DB3429 /* MGLOpenGLLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLOpenGLLayer.h; sourceTree = ""; }; DAE6C3B01CC31EF300DB3429 /* MGLOpenGLLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLOpenGLLayer.mm; sourceTree = ""; }; DAE6C3BB1CC31F2E00DB3429 /* default_marker.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = default_marker.pdf; sourceTree = ""; }; - DAE6C3BC1CC31F2E00DB3429 /* mapbox.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = mapbox.pdf; path = sdk/mapbox.pdf; sourceTree = SOURCE_ROOT; }; - DAE6C3BD1CC31F2E00DB3429 /* MGLAnnotationCallout.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MGLAnnotationCallout.xib; path = sdk/MGLAnnotationCallout.xib; sourceTree = SOURCE_ROOT; }; + DAE6C3BC1CC31F2E00DB3429 /* mapbox.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = mapbox.pdf; sourceTree = ""; }; DAE6C3C11CC31F4500DB3429 /* Mapbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Mapbox.h; path = src/Mapbox.h; sourceTree = SOURCE_ROOT; }; DAE6C3C51CC31F9100DB3429 /* mbgl.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = mbgl.xcconfig; path = ../../build/osx/mbgl.xcconfig; sourceTree = ""; }; DAE6C3C61CC3499100DB3429 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; @@ -337,6 +343,27 @@ name = "Supporting Files"; sourceTree = ""; }; + DA8933A81CCD28D100E68420 /* Kit Resources */ = { + isa = PBXGroup; + children = ( + DA8933AB1CCD290700E68420 /* Localizable.strings */, + DAE6C3BB1CC31F2E00DB3429 /* default_marker.pdf */, + DAE6C3BC1CC31F2E00DB3429 /* mapbox.pdf */, + DA8933A71CCD287300E68420 /* MGLAnnotationCallout.xib */, + ); + name = "Kit Resources"; + sourceTree = ""; + }; + DA8933B21CCD2C0700E68420 /* Foundation Resources */ = { + isa = PBXGroup; + children = ( + DA8933B31CCD2C2500E68420 /* Foundation.strings */, + DA8933B61CCD2C2D00E68420 /* Foundation.stringsdict */, + ); + name = "Foundation Resources"; + path = ../../darwin/resources; + sourceTree = ""; + }; DAE6C31E1CC308BC00DB3429 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -353,10 +380,9 @@ children = ( DAE6C3C11CC31F4500DB3429 /* Mapbox.h */, DAE6C3491CC31DF500DB3429 /* Foundation */, + DA8933B21CCD2C0700E68420 /* Foundation Resources */, DAE6C39E1CC31E7C00DB3429 /* Kit */, - DAE6C3BB1CC31F2E00DB3429 /* default_marker.pdf */, - DAE6C3BC1CC31F2E00DB3429 /* mapbox.pdf */, - DAE6C3BD1CC31F2E00DB3429 /* MGLAnnotationCallout.xib */, + DA8933A81CCD28D100E68420 /* Kit Resources */, DAE6C32C1CC30DB200DB3429 /* Info.plist */, ); name = SDK; @@ -635,9 +661,12 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + DA8933AE1CCD290700E68420 /* Localizable.strings in Resources */, DAE6C3BE1CC31F2E00DB3429 /* default_marker.pdf in Resources */, DAE6C3BF1CC31F2E00DB3429 /* mapbox.pdf in Resources */, - DAE6C3C01CC31F2E00DB3429 /* MGLAnnotationCallout.xib in Resources */, + DA8933A51CCD287300E68420 /* MGLAnnotationCallout.xib in Resources */, + DA8933B51CCD2C2500E68420 /* Foundation.strings in Resources */, + DA8933B81CCD2C2D00E68420 /* Foundation.stringsdict in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -750,6 +779,38 @@ name = MainMenu.xib; sourceTree = ""; }; + DA8933A71CCD287300E68420 /* MGLAnnotationCallout.xib */ = { + isa = PBXVariantGroup; + children = ( + DA8933A61CCD287300E68420 /* Base */, + ); + name = MGLAnnotationCallout.xib; + sourceTree = ""; + }; + DA8933AB1CCD290700E68420 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + DA8933AC1CCD290700E68420 /* Base */, + ); + name = Localizable.strings; + sourceTree = ""; + }; + DA8933B31CCD2C2500E68420 /* Foundation.strings */ = { + isa = PBXVariantGroup; + children = ( + DA8933B41CCD2C2500E68420 /* Base */, + ); + name = Foundation.strings; + sourceTree = ""; + }; + DA8933B61CCD2C2D00E68420 /* Foundation.stringsdict */ = { + isa = PBXVariantGroup; + children = ( + DA8933B71CCD2C2D00E68420 /* en */, + ); + name = Foundation.stringsdict; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ diff --git a/platform/osx/sdk/Base.lproj/Localizable.strings b/platform/osx/sdk/Base.lproj/Localizable.strings new file mode 100644 index 00000000000..818c82b2ec0 --- /dev/null +++ b/platform/osx/sdk/Base.lproj/Localizable.strings @@ -0,0 +1,30 @@ +/* Linked part of copyright notice */ +"COPYRIGHT_MAPBOX" = "Mapbox"; + +/* Copyright notice link */ +"COPYRIGHT_MAPBOX_LINK" = "https://www.mapbox.com/about/maps/"; + +/* Linked part of copyright notice */ +"COPYRIGHT_OSM" = "OpenStreetMap"; + +/* Copyright notice link */ +"COPYRIGHT_OSM_LINK" = "http://www.openstreetmap.org/about/"; + +/* Copyright notice prefix */ +"COPYRIGHT_PREFIX" = "© "; + +/* Accessibility title */ +"MAP_A11Y_TITLE" = "Mapbox"; + +/* Label of Zoom In button */ +"ZOOM_IN_LABEL" = "+"; + +/* Tooltip of Zoom In button */ +"ZOOM_IN_TOOLTIP" = "Zoom In"; + +/* Label of Zoom Out button; U+2212 MINUS SIGN */ +"ZOOM_OUT_LABEL" = "−"; + +/* Tooltip of Zoom Out button */ +"ZOOM_OUT_TOOLTIP" = "Zoom Out"; + diff --git a/platform/osx/sdk/MGLAnnotationCallout.xib b/platform/osx/sdk/Base.lproj/MGLAnnotationCallout.xib similarity index 74% rename from platform/osx/sdk/MGLAnnotationCallout.xib rename to platform/osx/sdk/Base.lproj/MGLAnnotationCallout.xib index edf84a26a79..c8e29bc29ed 100644 --- a/platform/osx/sdk/MGLAnnotationCallout.xib +++ b/platform/osx/sdk/Base.lproj/MGLAnnotationCallout.xib @@ -1,7 +1,7 @@ - + - + @@ -22,6 +22,14 @@ + + + + + + + + @@ -33,6 +41,14 @@ + + + + + + + + diff --git a/platform/osx/src/MGLAttributionButton.m b/platform/osx/src/MGLAttributionButton.m index b14d36cffd7..e21b8607942 100644 --- a/platform/osx/src/MGLAttributionButton.m +++ b/platform/osx/src/MGLAttributionButton.m @@ -1,5 +1,7 @@ #import "MGLAttributionButton.h" +#import "NSBundle+MGLAdditions.h" + @implementation MGLAttributionButton { NSTrackingRectTag _trackingAreaTag; } @@ -10,8 +12,7 @@ - (instancetype)initWithTitle:(NSString *)title URL:(NSURL *)url { self.bezelStyle = NSRegularSquareBezelStyle; // Start with a copyright symbol. The whole string will be mini. - NSMutableAttributedString *attributedTitle = [[NSMutableAttributedString alloc] initWithString:@"© " - attributes:@{ + NSMutableAttributedString *attributedTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringWithDefaultValue(@"COPYRIGHT_PREFIX", nil, nil, @"© ", @"Copyright notice prefix") attributes:@{ NSFontAttributeName: [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]], }]; // Append the specified title, underlining it like a hyperlink. diff --git a/platform/osx/src/MGLMapView.mm b/platform/osx/src/MGLMapView.mm index 280706b7988..767bcb81a85 100644 --- a/platform/osx/src/MGLMapView.mm +++ b/platform/osx/src/MGLMapView.mm @@ -80,8 +80,14 @@ /// URL to open when the attribution button is clicked. NSString *urlString; } MGLAttributions[] = { - { .title = @"Mapbox", .urlString = @"https://www.mapbox.com/about/maps/" }, - { .title = @"OpenStreetMap", .urlString = @"http://www.openstreetmap.org/about/" }, + { + .title = NSLocalizedStringWithDefaultValue(@"COPYRIGHT_MAPBOX", nil, nil, @"Mapbox", @"Linked part of copyright notice"), + .urlString = NSLocalizedStringWithDefaultValue(@"COPYRIGHT_MAPBOX_LINK", nil, nil, @"https://www.mapbox.com/about/maps/", @"Copyright notice link"), + }, + { + .title = NSLocalizedStringWithDefaultValue(@"COPYRIGHT_OSM", nil, nil, @"OpenStreetMap", @"Linked part of copyright notice"), + .urlString = NSLocalizedStringWithDefaultValue(@"COPYRIGHT_OSM_LINK", nil, nil, @"http://www.openstreetmap.org/about/", @"Copyright notice link"), + }, }; /// Unique identifier representing a single annotation in mbgl. @@ -302,12 +308,12 @@ - (void)installZoomControls { [(NSSegmentedCell *)_zoomControls.cell setTrackingMode:NSSegmentSwitchTrackingMomentary]; _zoomControls.continuous = YES; _zoomControls.segmentCount = 2; - [_zoomControls setLabel:@"−" forSegment:0]; // U+2212 MINUS SIGN + [_zoomControls setLabel:NSLocalizedStringWithDefaultValue(@"ZOOM_OUT_LABEL", nil, nil, @"−", @"Label of Zoom Out button; U+2212 MINUS SIGN") forSegment:0]; [(NSSegmentedCell *)_zoomControls.cell setTag:0 forSegment:0]; - [(NSSegmentedCell *)_zoomControls.cell setToolTip:@"Zoom Out" forSegment:0]; - [_zoomControls setLabel:@"+" forSegment:1]; + [(NSSegmentedCell *)_zoomControls.cell setToolTip:NSLocalizedStringWithDefaultValue(@"ZOOM_OUT_TOOLTIP", nil, nil, @"Zoom Out", @"Tooltip of Zoom Out button") forSegment:0]; + [_zoomControls setLabel:NSLocalizedStringWithDefaultValue(@"ZOOM_IN_LABEL", nil, nil, @"+", @"Label of Zoom In button") forSegment:1]; [(NSSegmentedCell *)_zoomControls.cell setTag:1 forSegment:1]; - [(NSSegmentedCell *)_zoomControls.cell setToolTip:@"Zoom In" forSegment:1]; + [(NSSegmentedCell *)_zoomControls.cell setToolTip:NSLocalizedStringWithDefaultValue(@"ZOOM_IN_TOOLTIP", nil, nil, @"Zoom In", @"Tooltip of Zoom In button") forSegment:1]; _zoomControls.target = self; _zoomControls.action = @selector(zoomInOrOut:); _zoomControls.controlSize = NSRegularControlSize; @@ -340,7 +346,7 @@ - (void)installLogoView { logoImage.alignmentRect = NSInsetRect(logoImage.alignmentRect, 3, 3); _logoView.image = logoImage; _logoView.translatesAutoresizingMaskIntoConstraints = NO; - _logoView.accessibilityTitle = @"Mapbox"; + _logoView.accessibilityTitle = NSLocalizedStringWithDefaultValue(@"MAP_A11Y_TITLE", nil, nil, @"Mapbox", @"Accessibility title"); [self addSubview:_logoView]; }