IOS/iPhone: Nested Localizable.strings Files?
Asked Answered
A

5

6

I'm creating an app that will have a number of variants.

These variants will be controlled by a few strings in multiple Localizable.strings files.

However, 90% of the strings will remain the same.

I'd like to have it so that each of the unique Localizable.strings files imports the "master" one, so that I don't have to go through each of the app variant files when I want to change a common string.

Is this possible?

Aeriell answered 10/10, 2011 at 11:52 Comment(0)
S
7

Two alternatives:

  1. Use custom wrapper functions around NSLocalizedString that do your hierarchical lookup for you, and then fall back to the NSLocalizedString mechanism for the default case.

    I previously wrote an answer about how to do this: Can .strings resource files be added at runtime?

  2. Use multiple .strings files per language. By default things are looked up in "Localizable.strings", but the NSLocalizedStringFromTable() function allows you to specify a custom "table" name. So if you passed in "Configuration" as the table name, it would look things up in the "Configuration.strings" file.

    I worked on an app that did this. We had two different .strings files. One controlled the branding settings (what name to use, what images to use, what servers to use, etc), and the other contained all of the actual translated strings. There would only be a single copy of the branding information in the app bundle, and we chose the correct variant to use at compile time with some custom scripts. It worked really really well.

Seen answered 15/10, 2011 at 15:44 Comment(1)
Thanks. I appreciate that. I'd probably have to do a bit of research to do it correctly, but Option 2 makes a lot of sense. The Perl script did the trick for me, and I've already had it in place for a couple of days (and a number of variants), so I'll have to stick with that for this project.Aeriell
S
2

Unfortunately, Apple doesn't support that for its Localizable.strings files.

You could mimic that feature through a custom Ruby or Python script or just a Bash script using sed; the script could take the root .strings file and copy the contents into each variant's .strings file. It could even be a custom build step in Xcode.

Signature answered 12/10, 2011 at 15:27 Comment(1)
Thanks. That's pretty much what I thought.Aeriell
G
1

I'm not sure of what you want but if you just want to translate a few strings you could.

You can just translate a part of these strings, if there is no translation, ios will select the strings in the application language and display it. So the Localizable.strings in the application language could be consider like the master one.

Gannie answered 10/10, 2011 at 13:48 Comment(1)
Thanks. However, that's not really what I need. Every single string displayed comes from the Localized.strings file. However, only a very few change between app variants. The vast majority are the same. This means that I must make an entire copy of the file for each variant. Then, when I add or change strings, I need to go into every single variant, and change that string. It is easy to make a mistake. I'd far prefer having all of the shared strings in one file that was included into the variants' specific files. However, the .strings file appears to be a custom format.Aeriell
A
1

OK. Here's what I did to solve it.

I removed the various Localizable.strings file from the Git repository, but left them in their locations (one in each of the app variant directories).

I took just the few lines that varied between each variant, and broke them into a separate text file, called "MyLocalizable.strings". I added each of these to Git, and added them to the project WITHOUT ASSOCIATING THEM WITH A TARGET. I left the Localizable.strings file associated with each target.

So, what we have, is each target has a Localizable.strings file that is associated with a target, and will be copied into the bundle. Each target directory has a file called "MyLocalizable.strings", that contains only the few strings that vary from target to target.

I then took the vast majority of the strings -the ones that don't change- and put them into another file called "MyLocalizable.strings", and placed this within the central (common) directory. Again, I added this to Git and to the project, WITHOUT ASSOCIATING IT WITH A TARGET.

I then wrote a very small, pathetic Perl script to construct a Localizable.strings file in a given target, from the common file, with the target-specific file appended. This overwrites the existing Localizable.strings file. This means that the Localizable.strings file is new for each run of the script. This script was placed in the common area, and added to the project WITHOUT ASSOCIATING IT WITH A TARGET. The script has one argument, which is the name of the target (and its directory). The syntax of this script is:

#!/usr/bin/perl

use strict;         # I'm anal. What can I say?
use Cwd;            # We'll be operating on the working directory.
use File::Path;

my $input1File = cwd()."/BMLT/Supporting\ Files/en.lproj/MyLocalizable.strings";
my $input2File = cwd()."/".$ARGV[0]."/en.lproj/MyLocalizable.strings";
my $outputFile = cwd()."/".$ARGV[0]."/en.lproj/Localizable.strings";

open ( MAIN_FILE, $input1File ) || die ( "Could not open main file!" );

my @file_data = <MAIN_FILE>;

close ( MAIN_FILE );

open ( PRODUCT_FILE, $input2File ) || die ( "Could not open product file!" );

push ( @file_data, <PRODUCT_FILE> );

close ( PRODUCT_FILE );

open ( FINAL_FILE, ">$outputFile" ) || die ( "Could not open destination file!" );

foreach ( @file_data ) print FINAL_FILE $_;

close ( FINAL_FILE );

I then add a Run Script build step BEFORE the Copy Bundle Resources step. This script calls the Perl script with the following syntax:

${PROJECT_DIR}/BMLT/Supporting\ Files/buildLocalizationFile.pl ${PRODUCT_NAME}

When the build is made, the files are combined, and the combined file is put into the bundle.

Aeriell answered 15/10, 2011 at 1:50 Comment(1)
I think this is the perfect solution to this problem. Thanks i will try this today.Unshod
I
1

Create one Localizable.strings for all targets with common strings. Also create TargetSpecificLocalizable.strings for each target and put target specific strings in it. Then for common strings use

NSLocalizedString("sample string", comment: "")

and for target specific strings use

NSLocalizedString("sample string", tableName: "TargetSpecificLocalizable", bundle: Bundle.main, value: "", comment: "")
Intestine answered 30/1, 2020 at 7:29 Comment(1)
That's a very good practice, but in the case from the OP, it would not work, as the executing code wouldn't know to use the alternate strings file.Aeriell

© 2022 - 2024 — McMap. All rights reserved.