Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Localization and CocoaPods

Tags:

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?

like image 440
user1071136 Avatar asked Oct 13 '12 15:10

user1071136


People also ask

What are CocoaPods used for?

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 Apple CocoaPods?

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.

Is CocoaPods a package manager?

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.

Why do CocoaPods use Ruby?

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.


2 Answers

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)

like image 55
Rivera Avatar answered Sep 21 '22 15:09

Rivera


@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;
}
like image 28
SwiftArchitect Avatar answered Sep 18 '22 15:09

SwiftArchitect