Xcode storyboards: Load localizable strings from different file - ios

I'm trying to build a library that will allow for dynamic loading of Localizable.strings files. If the views are being developed programmatically, then it's not a problem, as I could build a separate NSBundle, store the .strings files inside, and use NSLocalizedStringFromTableInBundle.
The problem I'm having lies with Storyboards. I haven't managed to find a way to specify which .strings file to load from (rather than using the default .strings that Apple uses).
Does anyone know of a solution for this? It doesn't even have to follow the same approach, as long as I can dynamically update the strings on a Storyboard. (The strings will be pulled down from an external source via API call upon app launch)

Loading strings from a separate bundle/strings source
In order to overcome the issue I had, I created IBOutlets for each object on the Storyboard's collection of views. Within each view's implementation file, I programmatically set the text/values of each object by using NSLocalizedStringFromTableInBundle, which allows me to specify a custom bundle, which can be populated with strings files.
In the event that a project has both programmatic and storyboard developed views, this approach also allows for the usage of only one Localizable.strings file, rather than mixing Storyboard-generated files, and files used only for programmatic views (if applicable).
Loading strings into an app via API call
Unfortunately, the above approach doesn't allow for strings to be downloaded from an external source via API call. The reason for this being, Apple doesn't allow for any files in the app bundle to be edited after being built.
Because of this, the solution would be to build out a data structure within the app's DocumentsDirectory, and edit this whenever necessary, then force the app to use this file/library in order to get localized strings. Not a pretty solution, but it's the best approach I can think of.

Related

Pre-load content into Documents or Library directories from XCode

I am building an iPhone app that requires preloaded content. This content is presented so that it tests the user's knowledge, but is not modified by the user. The content consists of proprietary image files and pdf files.
From what I understand, the best practice would be to store this in the app's Library or Documents directories (please inform if this assumption is not correct). In a future version of the app I might want to upload additional (not replacement) content via API, but this is not part of the initial version.
I have seen many posts and tutorials regarding obtaining paths to the Documents and Library directories of an app, and reading/writing to them. This is all good and useful, but not what I am looking for here.
I would like to preload the content into the Documents and/or Library directories, for the simulator initially, to test app in simulator; and ultimately to the release version. I would have thought this would be possible to do from XCode without writing code.
I have not been able to find a solution to this on Stack Overflow or other places on the net. Any pointers, links, solutions are welcome. I am using XCode 10.3 with Swift 4.2.
See the File System Programming Guide: File System Basics, which shows us:
The “data container” (including the Documents and the various Library folders) is for content generated/saved by the app. When, in Xcode, you mark resources as being part of the target, that becomes part of the bundle, and your app can retrieve it from there at runtime.
Theoretically, yes, you could copy data from the bundle to the Documents and/or Library folders, but, yes, you would have do that programmatically. It seems a bit wasteful to have two copies of these resources on the device, but you can do whatever you want. Generally, though, resources included in the bundle would just be be opened directly from there at runtime, not copying it to the data container (except for those cases where you would need to change it, because bundle contents are read-only).
FYI, for additional information regarding the file system, see the iOS Storage Best Practices video.

Loading Objective C code dynamically

I am looking for a possibility of loading Obj C based source dynamically and show the view in my iOS application. For example: I have a set of code written for showing a view, i want to dynamically load this code and show this view.
Some thing like,
I'll have a service running in the background of my iOS app.
It will get a set of Obj C code from my server in text format
This dynamic Obj C code should get executed dynamically and show the respective iOS view
From Comments Not released in the appstore.. its for internal
Is this possible?
Short answer: No
Not so short answer:
You could—in theory—include either the C, or C++ interface to the Clang compiler toolchain in your project, have that library compile the code you download, and then (through either NSBundle or direct interaction with dlopen) link that compiled code into your app.
In practice, if what you want to achieve is submitting to the App Store, this is explicitly prohibited by the Terms and Conditions.
You can't do this for deployment to the app store.
You wouldn't use plain text for this, you'd use a bundle (NSBundle). A bundle can contain both file (graphics, NIBs) resources and code so you can create your view classes and any associated NIBs, compile the bundle and then store it on your server. The app can then download the bundle and load it at runtime.
You can do it for non-app store apps. I have not tried this approach.
From Apple Docs:
The key to loading code from an external bundle is finding an
appropriate entry point into the bundle’s executable file. As with
other plug-in schemes, this requires some coordination between the
application developer and the plug-in developer. You can publish a
custom API for bundles to implement or define a formal plug-in
interface. In either case, once you have an appropriate bundle or
plug-in, you use the NSBundle class (or the CFBundleRef opaque type)
to access the functions or classes implemented by the external code.
Loading Objective-C Classes If you are writing a Cocoa application,
you can load the code for an entire class using the methods of
NSBundle. The NSBundle methods for loading a class are for use with
Objective-C classes only and cannot be used to load classes written in
C++ or other object-oriented languages.

How to keep Storyboard strings up to date?

I have the Storyboard, Base language and translated all the app into another language, so far it's working fine.
I would like to know, when I add new elements in the Storyboard that needs to be localized, how do you keep the strings file up to date.
I tried a suggestion, which is to switch this: to Interface Builder Cocoa Storyboard and then back to Localizable Strings, however the results are not good, most of the translation is lost and switched back to the Base language.
Is there a handy tool to regenerate and merge the strings in Storyboard? I tried few scripts but they always ended up wiping everything.
I've modified a skript that i've found here on stackoverflow to be able to also handle the localized strings in storyboards.
The skript only adds new key-value pairs to the .strings file, but keeps the ones that you have already translated.
You can get it from my github, for more details about my localization workflow read my blogpost

Change localizable file

I'm currently developing an application for IOS and I have four Localizable.strings files, each representing a different language. The thing is, i want to be able change the file that is being used without having to restart the application.
You can't do it without restarting the App.
A work around is store the language and it's values in a database file or in a plist file. Then use the data from there. (Basically it is not a good idea)

How to localize a plist file

I appreciate your help in advance. I have searched high and low for an answer with no luck.
I have an app that uses very specialized sports terms which I store in a plist file. Those terms are then displayed in a UITableView. When the user taps on the skill, a video demo is played. The app works great, but I would very much like to localize it for other languages.
I have gotten the terms translated, and I was hoping I could localize the plist file by making a copy of it and just changing the sport-specific terms in each successive copy of the file, and then put it in its respective language folder. Is this possible and if so, can someone please point me to a good example or tutorial?
So far, I have I have tried to localize the plist file for Russian in Xcode and put it in its own ru.lproj folder, however, then when I run it in the simulator no data appears at all in the UITableView! Without the Russian file, it works fine. So my thought is that somehow Xcode is confusing the plist file because the name is the same, even though it is in a different directory (en.lproj and ru.lproj). The file is called Basic.plist in both directories. This process is totally confusing to me, and from what I gather it shouldn't be that difficult to figure out!
Again, thank you in advance. The localization concept is completely new to me and I am eager to learn it. I am quite sure I understand how the .strings files work with strings that are embedded in code, but I would like to know if it is possible to translate an entire pList file.
A lot of things could be wrong. One possibility is that the plist files don't get copied into the bundle (verify in your target's Build Phases page--it should say Basic.plist with "...in (localization).lproj" written next to it.
If you have manually created the ru.lproj, maybe you copied it in the wrong place, or left the original file in the wrong place (it should now be inside en.lproj). Rather than manually create the file, it's easiest to select the file Basic.plist in XCode and use the Localization control inside File Inspector to add localizations. As Kevin Grant mentions, if this doesn't show your file as having English and Russian, then something is wrong, and you could start again using the + control.
Finally, I'm not 100% sure about this but close enough: I believe your code probably needs to be updated to figure out where to load the plist file from. It it were a .xib or a .strings file, you wouldn't have to do this as this would be automatic and iOS knows to look inside the relevant .lproj folder first (when you load a .xib you only specify its name, not its exact location). But I assume you are loading the plist file through a specific path, therefore the path must now include the .proj folder.
If possible for you, I think a nicer approach to having different plist files per language would be to have just one plist, but instead of displaying the string from the plist you could use it as a key to your .strings file. You can retrieve the localization using the NSLocalizedString macro (which is defined as [[NSBundle mainBundle] localizedStringForKey:(key) value:#"" table:nil]) which will give you the corresponding value in the localized .strings file at run time. Of course this would mean that when you update your plist, you would also have to update your .strings files to match. The good thing is that you wouldn't need to determine the path of the plist for your active language -- with NSLocalizedString, you don't provide a path at all.

Resources