Can .strings resource files be added at runtime?
Asked Answered
Q

4

11

I know that in Mac apps one can add .strings files to the project folder to add localizations.

Is there any way that additional localizations can be added to an app (iOS or Mac OS) without loading them from the resources bundle at compile time. Say, downloading an additional localization and storing it in /Documents on iOS?

Quadrilateral answered 20/5, 2011 at 16:50 Comment(1)
5 years later there is a product for this. lokalise.co "No need to resubmit your app for review anymore. Use Lokalise iOS and Android SDK to update strings and translations with a few lines of code."Quadrilateral
J
20

Yes, but it's not what you think.

You can take a strings file and load it into an NSString, and then transform it into a dictionary using -[NSString propertyListFromStringsFileFormat].

This will provide you with a way to store your custom-translated strings in-memory.

As for actually using that, you'll have to define custom translation functions. IE, you can't use NSLocalizedString() and friends any more. Fortunately, genstrings (the utility used for generating strings files) lets you specify custom function names:

genstrings -s "JPLocalizedString" ...

This means that in code, you can define:

NSString* JPLocalizedString(NSString *key, NSString *comment) {
  return [myLoadedStrings objectForKey:key];
}

As well as JPLocalizedStringFromTable(), JPLocalizedStringFromTableInBundle(), JPLocalizedStringWithDefaultValue(). genstrings will pick up all of those. (In other words, just because NSLocalizedString is a macro doesn't mean your version has to be)

If you do this and use these JPLocalizedString variants, then genstrings will still generate your strings files for you (providing you use the -s flag).

Once these functions are called, you can use whatever lookup mechanism you want, defaulting back to the NSLocalizedString versions if you can't find anything.

Juniorjuniority answered 20/5, 2011 at 17:27 Comment(1)
Thanks, this was more of a theoretical question and I don't have plans to implement this.Quadrilateral
B
1

If you want to implement an alternate version of NSLocalizedString() inside your application, there are number of good strategies for that. That would allow you to modify the values used inside your application itself. But those won't work when it comes to Push Notifications.

Warning however : for iOS Push Notifications that use Localized Strings, there is no legal runtime method modify the built in strings resources that are used to translate the localized arguments sent from your server into the device's native language.

So if you want to use Localized Strings as part of Push Notifications, you must ship them in the app when you submit to the store. They can't be modified later by loading something from the server.

Bane answered 14/1, 2014 at 20:54 Comment(0)
M
0

You should be able to achieve this by overriding NSBundle’s various pathForResource:… methods in a category. (I would assume they all go through -pathForResource:ofType:inDirectory:forLocalization:, but this isn’t documented so you can’t rely on it even if it turns out to be the case now, so you should override all of them.)

I also suggest filing an enhancement request for a clean way of overriding the lookup mechanism.

Murky answered 20/5, 2011 at 17:25 Comment(2)
ooph, bad idea. the only way you'd get this to work is by swizzling out the -[NSBundle localizedStringForKey:value:table:] method, and that is a really really bad idea.Juniorjuniority
Well, I take that back. You could use a subclass of NSBundle, override the logic in the method, and invoke super when necessary, but you'd have to always use the NSLocalizedStringFromTableInBundle() or NSLocalizedStringWithDefaultValue() macros to specify your custom bundle.Juniorjuniority
B
0

I managed to do it and I created a small repo to show how I have done it:

https://github.com/multitudes/MyLocalisationTestApp

Create a custom bundle in the documents directory.

Looking at the Apple documentation for Text: https://developer.apple.com/documentation/swiftui/text

The SwiftUI text view initializer accepts a bundle parameter.

1 - I created a custom bundle in the Documents directory. 2 - I placed programmatically the language folders the strings files inside it. 3 - When using it I pass the custom bundle and the tableName (the name of the .strings file) to the Text initialiser together with the key.
Like in SwiftUI it will be: Text(localizedStringKey, tableName: tableName, bundle: bundle)

Butcher answered 4/11, 2021 at 10:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.