Reputation: 15725
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?
Upvotes: 21
Views: 10802
Reputation: 188
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)
Upvotes: -2
Reputation: 9505
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:
Some constraints to respect:
XX.lproj
, where XX is your EXACT language name, note: en
!= en-GB
!= en-US
lproj
folder need to be at the same levellproj
folder need to have the same number of .strings
files and with the same names2 - 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:
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.
Upvotes: 3
Reputation: 48524
@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;
}
Upvotes: 5
Reputation: 10938
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
)
Upvotes: 12
Reputation: 325
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.
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
Upvotes: 3