Localization and CocoaPods
Asked Answered
G

5

21

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?

Gayl answered 13/10, 2012 at 15:45 Comment(4)
Nope; I just put the localized strings in the main project in a separate group/directory.Gayl
Localization is changed in newles Xcode. [look there][1] I think, mb it's solved your issue.. :-/ [1]: #5349566Gibbons
Not sure how that helps; my question was posted when Xcode was around 4.5. Can you point to something specific?Gayl
If you specify what your resources are in your Podfile, then they get copied to your App Bundle. That said, Localization STILL isn't working...Castroprauxel
P
12

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)

Perpetua answered 25/4, 2013 at 8:34 Comment(0)
H
5

@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;
}
Hadst answered 29/7, 2015 at 8:21 Comment(0)
C
3
  1. You should not put any file in the Pods project, because the pod command will recreate the project again and again.

    So put the string files in your own project.

  2. If you want to ship localized string files in your own Pod, you should include it in a bundle and make sure, the bundle will be installed in your Podspec file.

For example:

def s.post_install(target)
    puts "\nGenerating YOURPOD resources bundle\n".yellow if config.verbose?
    Dir.chdir File.join(config.project_pods_root, 'YOURPOD') do
        command = "xcodebuild -project YOURPOD.xcodeproj -target YOURPODResources CONFIGURATION_BUILD_DIR=../Resources"
        command << " 2>&1 > /dev/null" unless config.verbose?
        unless system(command)
            raise ::Pod::Informative, "Failed to generate YOURPOD resources bundle"
        end

        File.open(File.join(config.project_pods_root, target.target_definition.copy_resources_script_name), 'a') do |file|
            file.puts "install_resource 'Resources/YOURPODResources.bundle'"
        end
    end
end
Circumnavigate answered 27/2, 2013 at 14:51 Comment(3)
So, the problem is that strings that are in the Pods project are not being loaded using NSLocalizedString. Even if a Pod ships with localization files, I can't use them without copying there into my project.Gayl
Actually, I read your response too fast - you might be on the right track. I can't verify the answer at the moment, so I'll rely on upvotes instead.Gayl
Any success on above issue? I need to add new language support in existing sdkIrons
S
3

The best approach for localizing resources in a pod (public or private is indifferent) is to add the .strings localization files to the pod bundle.

The main app is very picky when comes to pick up the localization files from the pod frameworks, here the steps you must follow:

1 - Create the Localizable.strings and all the other *.strings files you need for your localization and put them in a folder, something like this:

strings folder structure

Some constraints to respect:

  • The folders name must be XX.lproj, where XX is your EXACT language name, note: en != en-GB != en-US
  • All the lproj folder need to be at the same level
  • Every lproj folder need to have the same number of .strings files and with the same names

2 - Configure your .podspec file so the pod can pick up the localization correctly and copy them in the .framework.

Example:

  s.resource = 'your_path/Localizations/**/*', '... possibly other resources'

after doing pod install the result in your Development Pods folder should be something like this:

enter image description here

One important thing to check is that created framework is that all the .lproj folder need to be on the root folder, otherwise are not picked up correctly by the main app.

3 - In your pod's code instead than the usual NSLocalizedString you must use NSLocalizedStringFromTableInBundle:

NSLocalizedStringFromTableInBundle(@"My string", nil, [NSBundle bundleForClass:[MCLoginContext class]], @"String context")

The entire process is very delicate and annoying, but that's should be all.

Suspicion answered 24/7, 2020 at 13:31 Comment(0)
T
-2

for swift you could use a Loc enum:

enum Loc : String{
case ok = "OK"
case cancel = "Cancel"

var localized: String {
    let s = self.rawValue
    let bundle = Bundle(for: <classname inside the bundle>.self)
    let result = NSLocalizedString(s, tableName: nil, bundle: bundle, value: "", comment: "")
    return result;
}

}

And use it so:

let s = Loc.ok.localized
print(s)
Tactic answered 9/9, 2020 at 13:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.