It's possible. You can set the locale. However, I would not recommend that. We've tried it at early stages, it's basically fighting the system.
We have the same requirement for changing the language but decided to settle to the fact that UI should be same as phone UI. It was working via setting locale but was too buggy. And you have to set it every time you enter activity (each activity) from my experience. here is a code if you still need this (again, I don't recommend that)
Resources res = context.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.setLocale(new Locale(language_code.toLowerCase())); // API 17+ only.
// Use conf.locale = new Locale(...) if targeting lower versions
res.updateConfiguration(conf, dm);
If you have language specific content - you can change that base on the setting.
update on 26th of march 2020
public static void setLocale(Activity activity, String languageCode) {
Locale locale = new Locale(languageCode);
Locale.setDefault(locale);
Resources resources = activity.getResources();
Configuration config = resources.getConfiguration();
config.setLocale(locale);
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
- NOTES: Language code cannot got '-' & must be 2 small case letter only
Defaulting to a particular language is not what you should strive for. Suppose a japanese user living in France and fluently speaking French has his phone set to Japanese. Your App would default to German, despite it having a French translation; I guess that's not what you want and it's certainly not what the user wants.
For this reason I suggest to respect the language prioritization as set by the user.
Since you don't want to support English but have developed the App in English, the easiest thing you can do is to just get rid of en.lproj
right after compiling. This will leave the app with only the languages you plan to support, and the iPhone will chose the language best suited for the user, as set in iPhone's defaults.
There is a pretty straightforward solution to deleting a specific localization:
Let Xcode build the App with all the present localizations and just before code-signing kicks in delete the en.lproj
folder and all localized files for that language are gone. You can easily do this by adding a Run Script build phase to the target, containing this one line of code (it's a Bash Script):
rm -r "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/en.lproj"
Code Signing always kicks in after all build phases have completed, so just put that build phase at the end of your current phases.
Note that this increases the time to build because Xcode recreates all English files, so you might want to disable this step during testing.
I hope that's a viable solution for you.
Concerning "the app must fall back to German in the case that an appropriate localization doesn't exist":
Question is what is an appropriate localization? If the user's third choice is French (after 2 unsupported languages), this solution will make the app fall back to French, which is an appropriate localization. More appropriate than setting the user's fifth choice, German, by hand.
What happens when an app launches is simple: The OS descends the users language list, as set in Preferences, until it finds a matching localization, and uses this language. The reason many apps default to English and not German is simply because English appears on most user language lists above German. There is no inherent language preference to the system. If you delete the English translation, only the languages you want to support are there, and of these languages the one higher on a user's list is taken.
Best Answer
There are three issues here:
The last is almost certainly not fixable, so we will leave it be. They're going to show up in the device language.
The other two are solvable, but you will need to do more things by hand. For strings, instead of creating a single Localizable.strings and then localizing it, create completely separate tables (English.strings, French.strings, etc.) Then, use
NSLocalizedStringFromTable()
, passing the language as the table.For NIBs, there are two approaches. You can put each set of localized NIBs into its own Bundle and then pass that Bundle rather than
nil
to-initWithNibName:bundle:
. Alternately, you can hand-load the NIBs after finding them with[NSBundle -pathForResource:ofType:inDirectory:forLocalization:]
.