[ios, osx] Corrected clock, coordinate formats

Long unit style isn’t intended to be spelled out, so the clock and coordinate direction formatters now use numerals for long unit style, differing from medium unit style in less drastic ways. The locale no longer needs to be exposed, since it’ll always match the overall string’s locale. Added support to the coordinate formatter for different unit styles. Made minutes and seconds of arc optional.

Maintain strings for darwin/ formatter classes in a separate Foundation strings table that can be shared between the iOS and OS X SDKs. Added an English .stringsdict override that correctly pluralizes units.

Capitalize osxapp window titles, now that they spell out the directions.
This commit is contained in:
Minh Nguyễn
2016-04-23 11:36:46 -07:00
committed by Minh Nguyễn
parent 6c9ca4be50
commit e4752912da
13 changed files with 635 additions and 164 deletions

View File

@@ -127,8 +127,9 @@ idocument:
igenstrings:
genstrings -u -o platform/ios/app/Base.lproj platform/ios/app/*.{m,mm}
genstrings -u -o platform/ios/resources/Base.lproj platform/darwin/src/*.{m,mm}
genstrings -u -o platform/ios/resources/Base.lproj platform/ios/src/*.{m,mm}
-find platform/ios/ -path '*/Base.lproj/Localizable.strings' -exec \
-find platform/{darwin,ios}/ -path '*/Base.lproj/*.strings' -exec \
textutil -convert txt -extension strings -inputencoding UTF-16 -encoding UTF-8 {} \;
#### Android targets #####################################################

View File

@@ -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.

View File

@@ -13,41 +13,31 @@
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 = NSLocalizedStringFromTable(@"%@:00", @"Foundation", @"Clock position format, short style");
break;
case NSFormattingUnitStyleMedium:
format = NSLocalizedString(@"%@ o’clock", @"Clock position format, medium style");
format = NSLocalizedStringFromTable(@"%@ o’clock", @"Foundation", @"Clock position format, medium style");
break;
case NSFormattingUnitStyleLong:
format = NSLocalizedString(@"%@ o’clock", @"Clock position format, long style");
style = NSNumberFormatterSpellOutStyle;
format = NSLocalizedStringFromTable(@"%@ o’clock", @"Foundation", @"Clock position format, long style");
break;
default:
break;
}
_numberFormatter.numberStyle = style;
return [NSString stringWithFormat:format, [_numberFormatter stringFromNumber:@(hour)]];
}

View File

@@ -20,79 +20,79 @@
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"),
NSLocalizedStringFromTable(@"N", @"Foundation", @"North, short"),
NSLocalizedStringFromTable(@"N×E", @"Foundation", @"North by east, short"),
NSLocalizedStringFromTable(@"NNE", @"Foundation", @"North-northeast, short"),
NSLocalizedStringFromTable(@"NE×N", @"Foundation", @"Northeast by north, short"),
NSLocalizedStringFromTable(@"NE", @"Foundation", @"Northeast, short"),
NSLocalizedStringFromTable(@"NE×E", @"Foundation", @"Northeast by east, short"),
NSLocalizedStringFromTable(@"ENE", @"Foundation", @"East-northeast, short"),
NSLocalizedStringFromTable(@"E×N", @"Foundation", @"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"),
NSLocalizedStringFromTable(@"E", @"Foundation", @"East, short"),
NSLocalizedStringFromTable(@"E×S", @"Foundation", @"East by south, short"),
NSLocalizedStringFromTable(@"ESE", @"Foundation", @"East-southeast, short"),
NSLocalizedStringFromTable(@"SE×E", @"Foundation", @"Southeast by east, short"),
NSLocalizedStringFromTable(@"SE", @"Foundation", @"Southeast, short"),
NSLocalizedStringFromTable(@"SE×S", @"Foundation", @"Southeast by south, short"),
NSLocalizedStringFromTable(@"SSE", @"Foundation", @"South-southeast, short"),
NSLocalizedStringFromTable(@"S×E", @"Foundation", @"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"),
NSLocalizedStringFromTable(@"S", @"Foundation", @"South, short"),
NSLocalizedStringFromTable(@"S×W", @"Foundation", @"South by west, short"),
NSLocalizedStringFromTable(@"SSW", @"Foundation", @"South-southwest, short"),
NSLocalizedStringFromTable(@"SW×S", @"Foundation", @"Southwest by south, short"),
NSLocalizedStringFromTable(@"SW", @"Foundation", @"Southwest, short"),
NSLocalizedStringFromTable(@"SW×W", @"Foundation", @"Southwest by west, short"),
NSLocalizedStringFromTable(@"WSW", @"Foundation", @"West-southwest, short"),
NSLocalizedStringFromTable(@"W×S", @"Foundation", @"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"),
NSLocalizedStringFromTable(@"W", @"Foundation", @"West, short"),
NSLocalizedStringFromTable(@"W×N", @"Foundation", @"West by north, short"),
NSLocalizedStringFromTable(@"WNW", @"Foundation", @"West-northwest, short"),
NSLocalizedStringFromTable(@"NW×W", @"Foundation", @"Northwest by west, short"),
NSLocalizedStringFromTable(@"NW", @"Foundation", @"Northwest, short"),
NSLocalizedStringFromTable(@"NW×N", @"Foundation", @"Northwest by north, short"),
NSLocalizedStringFromTable(@"NNW", @"Foundation", @"North-northwest, short"),
NSLocalizedStringFromTable(@"N×W", @"Foundation", @"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"),
NSLocalizedStringFromTable(@"north", @"Foundation", @"North, long"),
NSLocalizedStringFromTable(@"north by east", @"Foundation", @"North by east, long"),
NSLocalizedStringFromTable(@"north-northeast", @"Foundation", @"North-northeast, long"),
NSLocalizedStringFromTable(@"northeast by north", @"Foundation", @"Northeast by north, long"),
NSLocalizedStringFromTable(@"northeast", @"Foundation", @"Northeast, long"),
NSLocalizedStringFromTable(@"northeast by east", @"Foundation", @"Northeast by east, long"),
NSLocalizedStringFromTable(@"east-northeast", @"Foundation", @"East-northeast, long"),
NSLocalizedStringFromTable(@"east by north", @"Foundation", @"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"),
NSLocalizedStringFromTable(@"east", @"Foundation", @"East, long"),
NSLocalizedStringFromTable(@"east by south", @"Foundation", @"East by south, long"),
NSLocalizedStringFromTable(@"east-southeast", @"Foundation", @"East-southeast, long"),
NSLocalizedStringFromTable(@"southeast by east", @"Foundation", @"Southeast by east, long"),
NSLocalizedStringFromTable(@"southeast", @"Foundation", @"Southeast, long"),
NSLocalizedStringFromTable(@"southeast by south", @"Foundation", @"Southeast by south, long"),
NSLocalizedStringFromTable(@"south-southeast", @"Foundation", @"South-southeast, long"),
NSLocalizedStringFromTable(@"south by east", @"Foundation", @"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"),
NSLocalizedStringFromTable(@"south", @"Foundation", @"South, long"),
NSLocalizedStringFromTable(@"south by west", @"Foundation", @"South by west, long"),
NSLocalizedStringFromTable(@"south-southwest", @"Foundation", @"South-southwest, long"),
NSLocalizedStringFromTable(@"southwest by south", @"Foundation", @"Southwest by south, long"),
NSLocalizedStringFromTable(@"southwest", @"Foundation", @"Southwest, long"),
NSLocalizedStringFromTable(@"southwest by west", @"Foundation", @"Southwest by west, long"),
NSLocalizedStringFromTable(@"west-southwest", @"Foundation", @"West-southwest, long"),
NSLocalizedStringFromTable(@"west by south", @"Foundation", @"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"),
NSLocalizedStringFromTable(@"west", @"Foundation", @"West, long"),
NSLocalizedStringFromTable(@"west by north", @"Foundation", @"West by north, long"),
NSLocalizedStringFromTable(@"west-northwest", @"Foundation", @"West-northwest, long"),
NSLocalizedStringFromTable(@"northwest by west", @"Foundation", @"Northwest by west, long"),
NSLocalizedStringFromTable(@"northwest", @"Foundation", @"Northwest, long"),
NSLocalizedStringFromTable(@"northwest by north", @"Foundation", @"Northwest by north, long"),
NSLocalizedStringFromTable(@"north-northwest", @"Foundation", @"North-northwest, long"),
NSLocalizedStringFromTable(@"north by west", @"Foundation", @"North by west, long"),
];
NSAssert(shortStrings.count == longStrings.count, @"Long and short compass direction string arrays must have the same size.");

View File

@@ -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.

View File

@@ -3,43 +3,108 @@
#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 = NSLocalizedStringFromTable(@"%@N", @"Foundation", @"North latitude format, short");
negativeLatitudeFormat = NSLocalizedStringFromTable(@"%@S", @"Foundation", @"South latitude format, short");
positiveLongitudeFormat = NSLocalizedStringFromTable(@"%@E", @"Foundation", @"East longitude format, short");
negativeLongitudeFormat = NSLocalizedStringFromTable(@"%@W", @"Foundation", @"West longitude format, short");
stringFormat = NSLocalizedStringFromTable(@"%@, %@", @"Foundation", @"Latitude-longitude format, short");
break;
case NSFormattingUnitStyleMedium:
positiveLatitudeFormat = NSLocalizedStringFromTable(@"%@ north", @"Foundation", @"North latitude format, medium");
negativeLatitudeFormat = NSLocalizedStringFromTable(@"%@ south", @"Foundation", @"South latitude format, medium");
positiveLongitudeFormat = NSLocalizedStringFromTable(@"%@ east", @"Foundation", @"East longitude format, medium");
negativeLongitudeFormat = NSLocalizedStringFromTable(@"%@ west", @"Foundation", @"West longitude format, medium");
stringFormat = NSLocalizedStringFromTable(@"%@, %@", @"Foundation", @"Latitude-longitude format, medium");
break;
case NSFormattingUnitStyleLong:
positiveLatitudeFormat = NSLocalizedStringFromTable(@"%@ north", @"Foundation", @"North latitude format, long");
negativeLatitudeFormat = NSLocalizedStringFromTable(@"%@ south", @"Foundation", @"South latitude format, long");
positiveLongitudeFormat = NSLocalizedStringFromTable(@"%@ east", @"Foundation", @"East longitude format, long");
negativeLongitudeFormat = NSLocalizedStringFromTable(@"%@ west", @"Foundation", @"West longitude format, long");
stringFormat = NSLocalizedStringFromTable(@"%@ by %@", @"Foundation", @"Latitude-longitude format, long");
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 = NSLocalizedStringFromTable(@"%d°", @"Foundation", @"Degrees format, short");
minutesFormat = NSLocalizedStringFromTable(@"%d′", @"Foundation", @"Minutes format, short");
secondsFormat = NSLocalizedStringFromTable(@"%d″", @"Foundation", @"Seconds format, short");
degreesMinutesFormat = NSLocalizedStringFromTable(@"%@%@", @"Foundation", @"Degrees-minutes format, short");
degreesMinutesSecondsFormat = NSLocalizedStringFromTable(@"%@%@%@", @"Foundation", @"Degrees-minutes-seconds format, short");
break;
case NSFormattingUnitStyleMedium:
degreesFormat = NSLocalizedStringFromTable(@"%d°", @"Foundation", @"Degrees format, medium");
minutesFormat = NSLocalizedStringFromTable(@"%d′", @"Foundation", @"Minutes format, medium");
secondsFormat = NSLocalizedStringFromTable(@"%d″", @"Foundation", @"Seconds format, medium");
degreesMinutesFormat = NSLocalizedStringFromTable(@"%@%@", @"Foundation", @"Degrees-minutes format, medium");
degreesMinutesSecondsFormat = NSLocalizedStringFromTable(@"%@%@%@", @"Foundation", @"Degrees-minutes-seconds format, medium");
break;
case NSFormattingUnitStyleLong:
degreesFormat = NSLocalizedStringFromTable(@"%d degree(s)", @"Foundation", @"Degrees format, long");
minutesFormat = NSLocalizedStringFromTable(@"%d minute(s)", @"Foundation", @"Minutes format, long");
secondsFormat = NSLocalizedStringFromTable(@"%d second(s)", @"Foundation", @"Seconds format, long");
degreesMinutesFormat = NSLocalizedStringFromTable(@"%@ and %@", @"Foundation", @"Degrees-minutes format, long");
degreesMinutesSecondsFormat = NSLocalizedStringFromTable(@"%@, %@, and %@", @"Foundation", @"Degrees-minutes-seconds format, long");
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;
}

View File

@@ -12,38 +12,43 @@ static NSString * const MGLTestLocaleIdentifier = @"en-US";
- (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]);
CLLocationDirection direction;
XCTAssertEqualObjects(@"12:00", [shortFormatter stringFromDirection:0]);
XCTAssertEqualObjects(@"12 o’clock", [mediumFormatter stringFromDirection:0]);
XCTAssertEqualObjects(@"twelve o’clock", [longFormatter stringFromDirection:0]);
direction = -90;
XCTAssertEqualObjects(@"9:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"9 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"9 o’clock", [longFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"2:00", [shortFormatter stringFromDirection:45]);
XCTAssertEqualObjects(@"2 o’clock", [mediumFormatter stringFromDirection:45]);
XCTAssertEqualObjects(@"two o’clock", [longFormatter stringFromDirection:45]);
direction = 0;
XCTAssertEqualObjects(@"12:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"12 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"12 o’clock", [longFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"3:00", [shortFormatter stringFromDirection:90]);
XCTAssertEqualObjects(@"3 o’clock", [mediumFormatter stringFromDirection:90]);
XCTAssertEqualObjects(@"three o’clock", [longFormatter stringFromDirection:90]);
direction = 45;
XCTAssertEqualObjects(@"2:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"2 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"2 o’clock", [longFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"6:00", [shortFormatter stringFromDirection:180]);
XCTAssertEqualObjects(@"6 o’clock", [mediumFormatter stringFromDirection:180]);
XCTAssertEqualObjects(@"six o’clock", [longFormatter stringFromDirection:180]);
direction = 90;
XCTAssertEqualObjects(@"3:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"3 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"3 o’clock", [longFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"9:00", [shortFormatter stringFromDirection:270]);
XCTAssertEqualObjects(@"9 o’clock", [mediumFormatter stringFromDirection:270]);
XCTAssertEqualObjects(@"nine o’clock", [longFormatter stringFromDirection:270]);
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

View File

@@ -17,49 +17,62 @@
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(@"N×E", [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

View File

@@ -8,8 +8,41 @@
@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

View File

@@ -201,6 +201,8 @@
DABFB8711CBE9A0F00D62B32 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848381CBAFB8500AB86E3 /* MGLMapView+MGLCustomStyleLayerAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
DABFB8721CBE9A0F00D62B32 /* MGLUserLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848391CBAFB8500AB86E3 /* MGLUserLocation.h */; settings = {ATTRIBUTES = (Public, ); }; };
DABFB8731CBE9A9900D62B32 /* Mapbox.h in Headers */ = {isa = PBXBuildFile; fileRef = DA88485E1CBAFC2E00AB86E3 /* Mapbox.h */; settings = {ATTRIBUTES = (Public, ); }; };
DAF9E8901CCBF7DC004C7E73 /* Foundation.strings in Resources */ = {isa = PBXBuildFile; fileRef = DAF9E88E1CCBF7DC004C7E73 /* Foundation.strings */; };
DAF9E8931CCBFA03004C7E73 /* Foundation.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DAF9E8911CCBFA03004C7E73 /* Foundation.stringsdict */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -413,6 +415,8 @@
DABCABBF1CB80717000A7C39 /* locations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = locations.cpp; sourceTree = "<group>"; };
DABCABC01CB80717000A7C39 /* locations.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = locations.hpp; sourceTree = "<group>"; };
DAC07C961CBB2CD6000CB309 /* mbgl.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = mbgl.xcconfig; path = ../../build/ios/mbgl.xcconfig; sourceTree = "<group>"; };
DAF9E88F1CCBF7DC004C7E73 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Foundation.strings; sourceTree = "<group>"; };
DAF9E8921CCBFA03004C7E73 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Foundation.stringsdict; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -660,7 +664,9 @@
DA8848621CBAFCC100AB86E3 /* Resources */ = {
isa = PBXGroup;
children = (
DAF9E88E1CCBF7DC004C7E73 /* Foundation.strings */,
DA89632C1CC4ECD300684375 /* Localizable.strings */,
DAF9E8911CCBFA03004C7E73 /* Foundation.stringsdict */,
DA8848771CBAFD5C00AB86E3 /* api_mapbox_com-digicert.der */,
DA8848781CBAFD5C00AB86E3 /* api_mapbox_com-geotrust.der */,
DA8848631CBAFCC100AB86E3 /* Compass.png */,
@@ -1027,10 +1033,12 @@
buildActionMask = 2147483647;
files = (
DA89632F1CC4EE3300684375 /* Localizable.strings in Resources */,
DAF9E8901CCBF7DC004C7E73 /* Foundation.strings in Resources */,
DA8848731CBAFCC100AB86E3 /* mapbox.png in Resources */,
DA8848741CBAFCC100AB86E3 /* mapbox@2x.png in Resources */,
DA88487A1CBAFD5C00AB86E3 /* api_mapbox_com-digicert.der in Resources */,
DA88486D1CBAFCC100AB86E3 /* Compass.png in Resources */,
DAF9E8931CCBFA03004C7E73 /* Foundation.stringsdict in Resources */,
DA8848721CBAFCC100AB86E3 /* default_marker@3x.png in Resources */,
DA88487C1CBAFD5C00AB86E3 /* star_tilestream_net.der in Resources */,
DA88486F1CBAFCC100AB86E3 /* Compass@3x.png in Resources */,
@@ -1231,6 +1239,22 @@
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
DAF9E88E1CCBF7DC004C7E73 /* Foundation.strings */ = {
isa = PBXVariantGroup;
children = (
DAF9E88F1CCBF7DC004C7E73 /* Base */,
);
name = Foundation.strings;
sourceTree = "<group>";
};
DAF9E8911CCBFA03004C7E73 /* Foundation.stringsdict */ = {
isa = PBXVariantGroup;
children = (
DAF9E8921CCBFA03004C7E73 /* en */,
);
name = Foundation.stringsdict;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */

View File

@@ -0,0 +1,269 @@
/* Degrees-minutes format, long */
"%@ and %@" = "%1$@ and %2$@";
/* Latitude-longitude format, long */
"%@ by %@" = "%1$@ by %2$@";
/* East longitude format, long
East longitude format, medium */
"%@ east" = "%@ east";
/* North latitude format, long
North latitude format, medium */
"%@ north" = "%@ north";
/* Clock position format, long style
Clock position format, medium style */
"%@ o’clock" = "%@ o’clock";
/* South latitude format, long
South latitude format, medium */
"%@ south" = "%@ south";
/* West longitude format, long
West longitude format, medium */
"%@ west" = "%@ west";
/* Degrees-minutes format, medium
Degrees-minutes format, short */
"%@%@" = "%1$@%2$@";
/* Degrees-minutes-seconds format, medium
Degrees-minutes-seconds format, short */
"%@%@%@" = "%1$@%2$@%3$@";
/* Latitude-longitude format, medium
Latitude-longitude format, short */
"%@, %@" = "%1$@, %2$@";
/* Degrees-minutes-seconds format, long */
"%@, %@, and %@" = "%1$@, %2$@, and %3$@";
/* Clock position format, short style */
"%@:00" = "%@:00";
/* East longitude format, short */
"%@E" = "%@E";
/* North latitude format, short */
"%@N" = "%@N";
/* South latitude format, short */
"%@S" = "%@S";
/* West longitude format, short */
"%@W" = "%@W";
/* Degrees format, long */
"%d degree(s)" = "%d degree(s)";
/* Minutes format, long */
"%d minute(s)" = "%d minute(s)";
/* Seconds format, long */
"%d second(s)" = "%d second(s)";
/* Degrees format, medium
Degrees format, short */
"%d°" = "%d°";
/* Minutes format, medium
Minutes format, short */
"%d′" = "%d′";
/* Seconds format, medium
Seconds format, short */
"%d″" = "%d″";
/* East, short */
"E" = "E";
/* East, long */
"east" = "east";
/* East by north, long */
"east by north" = "east by north";
/* East by south, long */
"east by south" = "east by south";
/* East-northeast, long */
"east-northeast" = "east-northeast";
/* East-southeast, long */
"east-southeast" = "east-southeast";
/* East-northeast, short */
"ENE" = "ENE";
/* East-southeast, short */
"ESE" = "ESE";
/* East by north, short */
"E×N" = "E×N";
/* East by south, short */
"E×S" = "E×S";
/* North, short */
"N" = "N";
/* Northeast, short */
"NE" = "NE";
/* Northeast by east, short */
"NE×E" = "NE×E";
/* Northeast by north, short */
"NE×N" = "NE×N";
/* North-northeast, short */
"NNE" = "NNE";
/* North-northwest, short */
"NNW" = "NNW";
/* North, long */
"north" = "north";
/* North by east, long */
"north by east" = "north by east";
/* North by west, long */
"north by west" = "north by west";
/* North-northeast, long */
"north-northeast" = "north-northeast";
/* North-northwest, long */
"north-northwest" = "north-northwest";
/* Northeast, long */
"northeast" = "northeast";
/* Northeast by east, long */
"northeast by east" = "northeast by east";
/* Northeast by north, long */
"northeast by north" = "northeast by north";
/* Northwest, long */
"northwest" = "northwest";
/* Northwest by north, long */
"northwest by north" = "northwest by north";
/* Northwest by west, long */
"northwest by west" = "northwest by west";
/* Northwest, short */
"NW" = "NW";
/* Northwest by north, short */
"NW×N" = "NW×N";
/* Northwest by west, short */
"NW×W" = "NW×W";
/* North by east, short */
"N×E" = "N×E";
/* North by west, short */
"N×W" = "N×W";
/* South, short */
"S" = "S";
/* Southeast, short */
"SE" = "SE";
/* Southeast by east, short */
"SE×E" = "SE×E";
/* Southeast by south, short */
"SE×S" = "SE×S";
/* South, long */
"south" = "south";
/* South by east, long */
"south by east" = "south by east";
/* South by west, long */
"south by west" = "south by west";
/* South-southeast, long */
"south-southeast" = "south-southeast";
/* South-southwest, long */
"south-southwest" = "south-southwest";
/* Southeast, long */
"southeast" = "southeast";
/* Southeast by east, long */
"southeast by east" = "southeast by east";
/* Southeast by south, long */
"southeast by south" = "southeast by south";
/* Southwest, long */
"southwest" = "southwest";
/* Southwest by south, long */
"southwest by south" = "southwest by south";
/* Southwest by west, long */
"southwest by west" = "southwest by west";
/* South-southeast, short */
"SSE" = "SSE";
/* South-southwest, short */
"SSW" = "SSW";
/* Southwest, short */
"SW" = "SW";
/* Southwest by south, short */
"SW×S" = "SW×S";
/* Southwest by west, short */
"SW×W" = "SW×W";
/* South by east, short */
"S×E" = "S×E";
/* South by west, short */
"S×W" = "S×W";
/* West, short */
"W" = "W";
/* West, long */
"west" = "west";
/* West by north, long */
"west by north" = "west by north";
/* West by south, long */
"west by south" = "west by south";
/* West-northwest, long */
"west-northwest" = "west-northwest";
/* West-southwest, long */
"west-southwest" = "west-southwest";
/* West-northwest, short */
"WNW" = "WNW";
/* West-southwest, short */
"WSW" = "WSW";
/* West by north, short */
"W×N" = "W×N";
/* West by south, short */
"W×S" = "W×S";

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>%d degree(s)</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@degrees@</string>
<key>degrees</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d degree</string>
<key>other</key>
<string>%d degrees</string>
</dict>
</dict>
<key>%d minute(s)</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@minutes@</string>
<key>minutes</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d minute</string>
<key>other</key>
<string>%d minutes</string>
</dict>
</dict>
<key>%d second(s)</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@seconds@</string>
<key>seconds</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d second</string>
<key>other</key>
<string>%d seconds</string>
</dict>
</dict>
</dict>
</plist>

View File

@@ -25,7 +25,7 @@
if (![value isKindOfClass:[NSValue class]]) {
return nil;
}
return [_coordinateFormatter stringForObjectValue:value];
return [_coordinateFormatter stringForObjectValue:value].localizedCapitalizedString;
}
@end