I have a project that uses CocoaPods. As a result, I have a workspace which contains two projects: mine and Pods.
Pods contains code which I'd like to localize, and I've created .strings
files in Pod. However, NSLocalizedString
fails to load these strings. I suspect this happens because the .strings
file is not in the main bundle, but there's no Pod bundle, because it is compiled into a static library.
Is there a better way to localize code in a CocoaPods project than in my main project?
What is it and what does it do? Cocoapods is an application level dependency manager that runs on objective-c, swift, and any other programming languages that run on Objective-C. It focuses on source-based distribution of third party code and allows automatic integration to your Xcode projects.
What is CocoaPods. CocoaPods is a dependency manager for Swift and Objective-C Cocoa projects. It has over 92 thousand libraries and is used in over 3 million apps. CocoaPods can help you scale your projects elegantly. Install.
With the advent of Swift 3.0, Apple has released an official package manager called Swift Package Manager (AKA SPM or SwiftPM), that helps us manage dependencies. But there are two other package managers out there: CocoaPods and Carthage.
Ruby was a good choice to let users monkey-patch whatever they needed for their projects. Ruby is an excellent language for CLI tools that do a lot of string manipulation. They made an effort to make sure @CocoaPods would work with the Ruby that shipped with OS X, even when not having the Xcode CLI Tools installed.
NSLocalizedString
just invokes NSBundle's localizedStringForKey:value:table:
so I wrote a NSBundle category to enable looking into several bundles (which in iOS are just folders):
NSString * const kLocalizedStringNotFound = @"kLocalizedStringNotFound";
+ (NSString *)localizedStringForKey:(NSString *)key
value:(NSString *)value
table:(NSString *)tableName
backupBundle:(NSBundle *)bundle
{
// First try main bundle
NSString * string = [[NSBundle mainBundle] localizedStringForKey:key
value:kLocalizedStringNotFound
table:tableName];
// Then try the backup bundle
if ([string isEqualToString:kLocalizedStringNotFound])
{
string = [bundle localizedStringForKey:key
value:kLocalizedStringNotFound
table:tableName];
}
// Still not found?
if ([string isEqualToString:kLocalizedStringNotFound])
{
NSLog(@"No localized string for '%@' in '%@'", key, tableName);
string = value.length > 0 ? value : key;
}
return string;
}
Then redefined NSLocalizedString
macro in my prefix file:
#undef NSLocalizedString
#define NSLocalizedString(key, comment) \
[NSBundle localizedStringForKey:key value:nil table:@"MyStringsFile" backupBundle:AlternativeBundleInsideMain]
The same for other macros if needed (i.e. NSLocalizedStringWithDefaultValue
)
@Rivera Swift 2.0 version:
static let kLocalizedStringNotFound = "kLocalizedStringNotFound"
static func localizedStringForKey(key:String,
value:String?,
table:String?,
bundle:NSBundle?) -> String {
// First try main bundle
var string:String = NSBundle.mainBundle().localizedStringForKey(key, value: kLocalizedStringNotFound, table: table)
// Then try the backup bundle
if string == kLocalizedStringNotFound {
string = bundle!.localizedStringForKey(key, value: kLocalizedStringNotFound, table: table)
}
// Still not found?
if string == kLocalizedStringNotFound {
print("No localized string for '\(key)' in '\(table)'")
if let value = value {
string = value.characters.count > 0 ? value : key
} else {
string = key
}
}
return string;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With