This commit is contained in:
Dale Myers 2021-01-05 13:57:45 +00:00
Родитель abe80a46f9
Коммит 50c26a2c9a
5 изменённых файлов: 168 добавлений и 312 удалений

Просмотреть файл

@ -21,8 +21,7 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
OBJ_32 /* LocalizedStringKit.m in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* LocalizedStringKit.m */; };
OBJ_34 /* LocalizedStringKit.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_11 /* LocalizedStringKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
DD90F1BF25A47E1C006C2ED8 /* LocalizedStringKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD90F1BE25A47E1C006C2ED8 /* LocalizedStringKit.swift */; };
OBJ_41 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; };
OBJ_52 /* LocalizedStringKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_14 /* LocalizedStringKitTests.swift */; };
OBJ_53 /* XCTestManifests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_15 /* XCTestManifests.swift */; };
@ -47,14 +46,13 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
DD90F1BE25A47E1C006C2ED8 /* LocalizedStringKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizedStringKit.swift; sourceTree = "<group>"; };
"LocalizedStringKit::LocalizedStringKit::Product" /* LocalizedStringKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LocalizedStringKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
"LocalizedStringKit::LocalizedStringKitTests::Product" /* LocalizedStringKitTests.xctest */ = {isa = PBXFileReference; lastKnownFileType = file; path = LocalizedStringKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
OBJ_11 /* LocalizedStringKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalizedStringKit.h; sourceTree = "<group>"; };
OBJ_14 /* LocalizedStringKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizedStringKitTests.swift; sourceTree = "<group>"; };
"LocalizedStringKit::LocalizedStringKitTests::Product" /* LocalizedStringKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; path = LocalizedStringKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
OBJ_14 /* LocalizedStringKitTests.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = LocalizedStringKitTests.swift; sourceTree = "<group>"; tabWidth = 2; };
OBJ_15 /* XCTestManifests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestManifests.swift; sourceTree = "<group>"; };
OBJ_25 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
OBJ_9 /* LocalizedStringKit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LocalizedStringKit.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -76,14 +74,6 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
OBJ_10 /* include */ = {
isa = PBXGroup;
children = (
OBJ_11 /* LocalizedStringKit.h */,
);
path = include;
sourceTree = "<group>";
};
OBJ_12 /* Tests */ = {
isa = PBXGroup;
children = (
@ -133,8 +123,7 @@
OBJ_8 /* LocalizedStringKit */ = {
isa = PBXGroup;
children = (
OBJ_9 /* LocalizedStringKit.m */,
OBJ_10 /* include */,
DD90F1BE25A47E1C006C2ED8 /* LocalizedStringKit.swift */,
);
name = LocalizedStringKit;
path = Sources/LocalizedStringKit;
@ -147,7 +136,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 0;
files = (
OBJ_34 /* LocalizedStringKit.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -210,6 +198,11 @@
attributes = {
LastSwiftMigration = 9999;
LastUpgradeCheck = 9999;
TargetAttributes = {
"LocalizedStringKit::LocalizedStringKit" = {
LastSwiftMigration = 1220;
};
};
};
buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "LocalizedStringKit" */;
compatibilityVersion = "Xcode 3.2";
@ -236,7 +229,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 0;
files = (
OBJ_32 /* LocalizedStringKit.m in Sources */,
DD90F1BF25A47E1C006C2ED8 /* LocalizedStringKit.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -289,9 +282,9 @@
"$(SRCROOT)/Sources/LocalizedStringKit/include",
);
INFOPLIST_FILE = LocalizedStringKit.xcodeproj/LocalizedStringKit_Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx";
MACOSX_DEPLOYMENT_TARGET = 10.10;
MACOSX_DEPLOYMENT_TARGET = 10.15;
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
@ -300,9 +293,11 @@
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGET_NAME = LocalizedStringKit;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
TVOS_DEPLOYMENT_TARGET = 13.0;
WATCHOS_DEPLOYMENT_TARGET = 6.0;
};
name = Debug;
};
@ -351,9 +346,9 @@
"$(SRCROOT)/Sources/LocalizedStringKit/include",
);
INFOPLIST_FILE = LocalizedStringKit.xcodeproj/LocalizedStringKit_Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx";
MACOSX_DEPLOYMENT_TARGET = 10.10;
MACOSX_DEPLOYMENT_TARGET = 10.15;
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
@ -362,9 +357,10 @@
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)";
SWIFT_VERSION = 5.0;
TARGET_NAME = LocalizedStringKit;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
TVOS_DEPLOYMENT_TARGET = 13.0;
WATCHOS_DEPLOYMENT_TARGET = 6.0;
};
name = Release;
};
@ -429,6 +425,7 @@
OBJ_49 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ENABLE_MODULES = YES;
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
FRAMEWORK_SEARCH_PATHS = (
@ -440,23 +437,24 @@
"$(SRCROOT)/Sources/LocalizedStringKit/include",
);
INFOPLIST_FILE = LocalizedStringKit.xcodeproj/LocalizedStringKitTests_Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
MACOSX_DEPLOYMENT_TARGET = 10.15;
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)";
SWIFT_VERSION = 5.0;
TARGET_NAME = LocalizedStringKitTests;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
TVOS_DEPLOYMENT_TARGET = 13.0;
WATCHOS_DEPLOYMENT_TARGET = 6.0;
};
name = Debug;
};
OBJ_50 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ENABLE_MODULES = YES;
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
FRAMEWORK_SEARCH_PATHS = (
@ -468,17 +466,17 @@
"$(SRCROOT)/Sources/LocalizedStringKit/include",
);
INFOPLIST_FILE = LocalizedStringKit.xcodeproj/LocalizedStringKitTests_Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
MACOSX_DEPLOYMENT_TARGET = 10.15;
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)";
SWIFT_VERSION = 5.0;
TARGET_NAME = LocalizedStringKitTests;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
TVOS_DEPLOYMENT_TARGET = 13.0;
WATCHOS_DEPLOYMENT_TARGET = 6.0;
};
name = Release;
};

Просмотреть файл

@ -1,180 +0,0 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
@import CommonCrypto;
#import "LocalizedStringKit.h"
@interface LocalizedStringKit : NSObject
@end
@implementation LocalizedStringKit
static NSMutableDictionary *bundleMap = nil;
#pragma mark - Public
NSString *_Nonnull LSKPrimaryBundleName = @"LocalizedStringKit.bundle";
NSURL *_Nullable LSKAlternateBundleSearchPath = nil;
NSString *Localized(NSString *_Nonnull value, NSString *_Nonnull comment) {
return [LocalizedStringKit localizeWithValue:value comment:comment keyExtension:nil bundleName:nil];
}
NSString *LocalizedWithBundle(NSString *_Nonnull value, NSString *_Nonnull comment, NSString *_Nonnull bundleName) {
return [LocalizedStringKit localizeWithValue:value comment:comment keyExtension:nil bundleName:bundleName];
}
NSString *LocalizedWithKeyExtension(NSString *_Nonnull value, NSString *_Nonnull comment, NSString *_Nonnull keyExtension) {
return [LocalizedStringKit localizeWithValue:value comment:comment keyExtension:keyExtension bundleName:nil];
}
NSString *LocalizedWithKeyExtensionAndBundle(NSString *_Nonnull value, NSString *_Nonnull comment, NSString *_Nonnull keyExtension, NSString *_Nullable bundleName) {
return [LocalizedStringKit localizeWithValue:value comment:comment keyExtension:keyExtension bundleName:bundleName];
}
__attribute__((annotate("returns_localized_nsstring")))
NSString *LocalizationUnnecessary(NSString *value) {
return value;
}
NSBundle * _Nullable getLocalizedStringKitBundle(NSString *_Nullable bundleName) {
return [LocalizedStringKit getLocalizedStringKitBundle:bundleName];
}
#pragma mark - Private / Static
+ (NSString *)localizeWithValue:(NSString *_Nonnull)value comment:(NSString *_Nonnull)comment keyExtension:(NSString *_Nullable)keyExtension bundleName:(NSString *_Nullable)bundleName
{
// Key
NSString *key = [self keyWithValue:value keyExtension:keyExtension];
// Table: This does not change between bundles
NSString *table = @"LocalizedStringKit";
// Bundle Map: [bundleName String: NSBundle]
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
bundleMap = [[NSMutableDictionary alloc] init];
});
if (bundleName == nil)
{
// Default to primary strings bundle
bundleName = @"LocalizedStringKit.bundle";
}
NSBundle *bundle = [bundleMap objectForKey:bundleName];
if (bundle == nil)
{
// Load and cache bundle
bundle = [LocalizedStringKit getLocalizedStringKitBundle:bundleName];
if (bundle == nil)
{
[bundleMap setObject:[NSNull null] forKey:bundleName];
// Unable to load `LocalizedStringKit` bundle
return value;
}
[bundleMap setObject:bundle forKey:bundleName];
}
if ([bundle isKindOfClass:[NSNull class]]) {
// Resolved NSNull for bundle
return value;
}
// Forward to `NSLocalizedString`
return NSLocalizedStringWithDefaultValue(key, table, bundle, value, comment);
}
+ (NSString *)keyWithValue:(NSString *_Nonnull)value keyExtension:(NSString *)keyExtension
{
// Generate the `key` which is equal to the `MD5(<value>)` or `MD5(<value>:<keyExtension>)`. This logic must stay in sync with `localize.py`.
NSString *hashInput = value;
if (keyExtension.length > 0)
{
hashInput = [hashInput stringByAppendingFormat:@":%@", keyExtension];
}
const char *inputCharacterArray = [hashInput UTF8String];
unsigned char outputCharacterArray[CC_MD5_DIGEST_LENGTH];
CC_MD5(inputCharacterArray, (CC_LONG)strlen(inputCharacterArray), outputCharacterArray);
NSMutableString *key = [[NSMutableString alloc] init];
for (NSInteger idx = 0; idx < CC_MD5_DIGEST_LENGTH; idx++) {
[key appendFormat:@"%02x", outputCharacterArray[idx]];
}
return key;
}
+ (NSBundle *_Nullable)getLocalizedStringKitBundle:(NSString *_Nullable)bundleName
{
// Search Paths
NSURL *searchPath = [[NSBundle mainBundle] bundleURL];
// Determine target bundleName
if (bundleName == nil) {
// Defaults to primary bundle if bundleName not specified
bundleName = LSKPrimaryBundleName;
}
else if (![bundleName hasSuffix:@".bundle"])
{
// Append suffix
bundleName = [bundleName stringByAppendingFormat:@".bundle"];
}
// Alternate path check, if url specified
if (LSKAlternateBundleSearchPath != nil) {
NSURL *alternateBundleURL = [LSKAlternateBundleSearchPath URLByAppendingPathComponent:bundleName];
NSBundle *bundle = [NSBundle bundleWithURL:alternateBundleURL];
if (bundle) {
return bundle;
}
}
// Primary searchPath check
while(YES)
{
NSURL *bundleURL = [searchPath URLByAppendingPathComponent:bundleName];
NSBundle *bundle = [NSBundle bundleWithURL:bundleURL];
if (bundle != nil)
{
if ([bundle.bundleURL.lastPathComponent isEqualToString:bundleName]) {
return bundle;
}
else {
break;
}
}
NSURL *newPath = [[searchPath URLByAppendingPathComponent:@".."] absoluteURL];
if ([newPath isEqual:searchPath])
{
break;
}
searchPath = newPath;
}
return nil;
}
void LSKSetPrimaryBundleName(NSString *_Nonnull bundleName) {
LSKPrimaryBundleName = bundleName;
}
void LSKSetAlternateBundleSearchPath(NSURL *_Nonnull url) {
LSKAlternateBundleSearchPath = url;
[bundleMap removeAllObjects];
}
@end

Просмотреть файл

@ -0,0 +1,129 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
import Foundation
import CryptoKit
public func Localized(_ value: String, _ comment: String, keyExtension: String? = nil, bundleName: String? = nil) -> String {
return Localizer.localize(value, comment, keyExtension: keyExtension, bundleName: bundleName)
}
/// Soft deprecated. Use `Localized(value, comment, keyExtension: keyExtension)` instead
public func LocalizedWithKeyExtension(_ value: String, _ comment: String, _ keyExtension: String) -> String {
return Localizer.localize(value, comment, keyExtension: keyExtension, bundleName: nil)
}
/// Soft deprecated. Use `Localized(value, comment, bundleName: bundleName)` instead
public func LocalizedWithBundle(_ value: String, _ comment: String, _ bundleName: String) -> String {
return Localizer.localize(value, comment, keyExtension: nil, bundleName: bundleName)
}
/// Soft deprecated. Use `Localized(value, comment, keyExtension: keyExtension, bundleName: bundleName)` instead
public func LocalizedWithKeyExtensionAndBundle(_ value: String, _ comment: String, _ keyExtension: String, _ bundleName: String) -> String {
return Localizer.localize(value, comment, keyExtension: keyExtension, bundleName: bundleName)
}
public class Localizer {
private static var bundleMap = [String: Bundle]()
private static var missingBundles: Set<String> = Set()
public static var primaryBundleName = "LocalizedStringKit.bundle"
public static var alternateBundleSearchPath: URL? {
didSet {
bundleMap.removeAll()
}
}
static func md5(string: String) -> String? {
guard let data = string.data(using: .utf8) else {
return nil
}
let digest = Insecure.MD5.hash(data: data)
return digest.map { String(format: "%02hhx", $0) }.joined()
}
static func key(_ value: String, keyExtension: String?) -> String? {
// Generate the `key` which is equal to the `MD5(<value>)` or `MD5(<value>:<keyExtension>)`. This logic must stay in sync with `localize.py`.
var hashInput = value
if let ke = keyExtension, ke.isEmpty {
hashInput = hashInput.appendingFormat(":%@", ke)
}
return md5(string: hashInput)
}
static func getBundle(_ bundleName: String?) -> Bundle? {
// Search Paths
var searchPath = Bundle.main.bundleURL
// Determine target bundleName
var bundleName = bundleName ?? primaryBundleName
// Append suffix
if !bundleName.hasSuffix(".bundle") {
bundleName += ".bundle"
}
// Alternate path check, if url specified
if let alernateSearchPath = alternateBundleSearchPath,
let bundle = Bundle(url: alernateSearchPath.appendingPathComponent(bundleName)) {
return bundle
}
// Primary searchPath check
while true {
let bundleURL = searchPath.appendingPathComponent(bundleName)
if let bundle = Bundle(url: bundleURL) {
if bundle.bundleURL.lastPathComponent == bundleName {
return bundle
} else {
break
}
}
let newPath = searchPath.appendingPathComponent("..").absoluteURL
if newPath == searchPath {
break
}
searchPath = newPath
}
return nil
}
@objc static func localize(_ value: String, _ comment: String, keyExtension: String?, bundleName: String?) -> String {
let bundleName = bundleName ?? "LocalizedStringKit.bundle"
let table = "LocalizedStringKit" // This does not change between bundles
guard let key = self.key(value, keyExtension: keyExtension) else {
return value
}
if let cachedBundle = bundleMap[bundleName] {
return NSLocalizedString(key, tableName: table, bundle: cachedBundle, value: value, comment: comment)
}
// We can't find it, so don't bother searching again
guard !missingBundles.contains(bundleName) else {
return value
}
// Bundle wasn't cached so fetch and cache
guard let bundle = getBundle(bundleName) else {
missingBundles.insert(bundleName)
return value
}
bundleMap[bundleName] = bundle
// Forward to `NSLocalizedString`
return NSLocalizedString(key, tableName: table, bundle: bundle, value: value, comment: comment)
}
}

Просмотреть файл

@ -1,89 +0,0 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
@import Foundation;
NS_ASSUME_NONNULL_BEGIN
//! Project version number for LocalizedStringKit.
FOUNDATION_EXPORT double LocalizedStringKitVersionNumber;
//! Project version string for LocalizedStringKit.
FOUNDATION_EXPORT const unsigned char LocalizedStringKitVersionString[];
/// The name to be used for the primary strings bundle
/// Example:
/// "Localizable" (do not include the extension suffix)
FOUNDATION_EXPORT NSString *_Nonnull LSKPrimaryBundleName;
/// URL for alternate string bundle search (the root from where search will begin)
FOUNDATION_EXPORT NSURL *_Nullable LSKAlternateBundleSearchPath;
/// Primary localization function used to localize strings (excluding bundleName)
///
/// @param value: The English string
/// @param comment: String to give context where the value string is used
///
/// Examples
/// Localized("Cancel", "Action sheet action title")
NSString *Localized(NSString *_Nonnull value, NSString *_Nonnull comment);
/// Primary localization function used to localize strings
///
/// @param value: The English string
/// @param comment: String to give context where the value string is used
/// @param bundleName: String to provide additional classification of the value string. Can be used to segment groups of strings in multiple bundles.
///
/// Examples
/// Localized("Cancel", "Action sheet action title", nil)
/// Localized("Cancel", "Action sheet action title", "primary")
/// Localized("Cancel", "Action sheet action title", "primary")
NSString *LocalizedWithBundle(NSString *_Nonnull value, NSString *_Nonnull comment, NSString *_Nonnull bundleName);
/// Additional localization function used to localize strings
///
/// @param value: The English string
/// @param comment: String to give context where the value string is used
/// @param keyExtension: String to be used to provide additional differentiation between contexts. The `keyExtension` is included when generating the string `key` so two calls with the same `value` but different `keyExtension` values will result in two different strings in the localization dictionary
///
/// Ex: `LocalizedWithKeyExtension("Archive", "Button title", "Verb")
/// Ex: `LocalizedWithKeyExtension("Archive", "Folder title", "Noun")
NSString *LocalizedWithKeyExtension(NSString *_Nonnull value, NSString *_Nonnull scomment, NSString *_Nonnull keyExtension);
/// Additional localization function used to localize strings
///
/// @param value: The English string
/// @param comment: String to give context where the value string is used
/// @param keyExtension: String to be used to provide additional differentiation between contexts. The `keyExtension` is included when generating the string `key` so two calls with the same `value` but different `keyExtension` values will result in two different strings in the localization dictionary
/// @param bundleName: Optional string to provide additional classification of the string. Can be used to segment groups of strings in multiple bundles.
///
/// Ex: `LocalizedWithKeyExtensionAndBundle("Archive", "Button title", "Verb", "primary")
/// Ex: `LocalizedWithKeyExtensionAndBundle("Archive", "Folder title", "Noun", "primary")
NSString *LocalizedWithKeyExtensionAndBundle(NSString *_Nonnull value, NSString *_Nonnull scomment, NSString *_Nonnull keyExtension, NSString *_Nullable bundleName);
/// Marks a string as not needing localization (to avoid false positives from
/// the static analyzer
NSString *LocalizationUnnecessary(NSString *value);
/// Load the bundle which contains the localized strings
///
/// @param bundleName: Optional bundleName to find related bundle for strings. bundleNames can be used to segment localized string bundles. If nil, default bundle will be returned.
NSBundle * _Nullable LSKLocalizedStringKitBundle(NSString *_Nullable bundleName);
/// Set the primary bundle name
///
/// @param bundleName: Nonnull bundle name to set as a String
void LSKSetPrimaryBundleName(NSString *_Nonnull bundleName);
/// Set the alternate bundle search path
///
/// @param url: URL to search
void LSKSetAlternateBundleSearchPath(NSURL *_Nonnull url);
/// Get a strings bundle
///
/// @param bundleName: Name of bundle to search for
NSBundle * _Nullable getLocalizedStringKitBundle(NSString *_Nullable bundleName);
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -20,13 +20,11 @@ final class LocalizedStringKitTests: XCTestCase {
if Locale.current.languageCode == "en" {
XCTAssertEqual(Localized("Done", "Done"), "Done")
XCTAssertEqual(Localized("Not a Localized String", "Done"), "Not a Localized String")
XCTAssertEqual(LocalizationUnnecessary("Not Needed"), "Not Needed")
}
else {
XCTFail("Please add other development language localization tests")
XCTAssertEqual(Localized("Done", "Done"), "Done")
XCTAssertEqual(LocalizedWithBundle("Not a Localized String", "Done", "primary"), "Not a Localized String")
XCTAssertEqual(LocalizationUnnecessary("Not Needed"), "Not Needed")
}
}
@ -56,19 +54,19 @@ final class LocalizedStringKitTests: XCTestCase {
}
func testGetLocalizedStringKitBundle() {
XCTAssertNil(getLocalizedStringKitBundle("unknown_bundle"))
XCTAssertNil(LocalizedStringKit.getBundle("unknown_bundle"))
}
func testPrimaryBundleName() {
XCTAssertEqual(LSKPrimaryBundleName, "LocalizedStringKit.bundle")
LSKSetPrimaryBundleName("Other.bundle")
XCTAssertEqual(LSKPrimaryBundleName, "Other.bundle")
XCTAssertEqual(LocalizedStringKit.primaryBundleName, "LocalizedStringKit.bundle")
LocalizedStringKit.primaryBundleName = "Other.bundle"
XCTAssertEqual(LocalizedStringKit.primaryBundleName, "Other.bundle")
}
func testAlternateBundleSearchPath() {
XCTAssertNil(LSKAlternateBundleSearchPath)
LSKAlternateBundleSearchPath = NSURL(string: "file://path")
XCTAssertEqual(LSKAlternateBundleSearchPath, NSURL(string: "file://path"))
XCTAssertNil(LocalizedStringKit.alternateBundleSearchPath)
LocalizedStringKit.alternateBundleSearchPath = URL(string: "file://path")
XCTAssertEqual(LocalizedStringKit.alternateBundleSearchPath, URL(string: "file://path"))
}
// TODO: LocalizedStringKit statically binds the Locale bundle so we cannot swap locale at runtime, if we need to