Strings are provided to your application at runtime via the Android resource system. In this video, walk through the process of how the system selects a screen to be displayed in your app, including changes introduced in Android Nougat.
- [Instructor] Trying to find out exactly what string will be returned to a user in any given situation can be complicated. There's differences based on Android OS versions and based on the sets of strings available in your app. Let's go over how the whole process works so you can better understand how to set up your strings and troubleshoot when things go wrong. First let's consider a basic example. Our app has three strings files. The default strings file, a strings file just for Spanish, so it's just ES, and a string file for French, spoken in France.
All strings all translated in all files and the user's phone is set to Spanish, spoken in Spain. In the app a screen is loaded that contains a string. At runtime the resource looks at the user's locale and looks to the collection string resources to find the correct string. The locale is Spanish spoken in Spain so the system looks for a direct match. No match is found, just Spanish doesn't match exactly so the region is removed.
Now it's looking for a direct match with just the Spanish language by itself. Now it finds a match so the Spanish string file is selected. Then the system looks in the Spanish strings file for the string, finds the string resource, and uses it in the layout. Now let's consider the same setup, but this time the user's phone is set to French spoken in Canada. Again at runtime, the resource system looks for a direct match of French spoken in Canada and it can't find it so it removes the region and looks for just French.
You might think it would select French spoken in France, but it does not since it's not a direct match. Since no matches were found it defaults to the default strings file, which is English in this case. Now this is how the resolution system worked until Android Nougat. With Nougat they made a change to the resolution system for just this case. In the previous example when a direct match could not be found for just French, it makes one more check. It checks to see if there are any French language options with specific regions.
And in this case it finds French spoken in France so that strings file is selected. Now this is a much better experience. A French speaking Canadian user would probably prefer French strings even if they're specifically for French speakers in France rather than the default English strings. This means that now you can be more targeted with the languages you support. Prior to this change you had to decide if you wanted to ship specific translations like Spanish spoken in Spanish and Spanish spoken in Mexico, and potentially duplicate translations in the higher level ES locale.
Or only ship the ES locale and not be able to specifically support regional languages. And now you can ship those specific translations without worrying about leaving out support for sibling languages. Android Nougat also added support for setting the list of preferred languages rather than just one language. So let's see how that works for resource resolution. In this example our user has two language, French spoken in Switzerland and Italian spoken in Switzerland, and our example app only supports Italian.
So let's open the app in our emulator that's preconfigured with these languages, and take a look. I set up the app to have one Italian translation on the subscription screen. So let's go to that screen by clicking the light green line. But when we go to the screen, the text at the top, I would expect that to be Italian but it's still in English. So why is that? To investigate that let's look at the resources bundled in our Android APK file.
In recent of Android Studio an APK analyzer was added that lets us look into the APK file that's built. If we go to Android Studio we can access it through the build menu and then select Analyze APK. Here it will preselect the APK file that was built and loaded into our emulator so you can click okay to analyze that. And now we see everything that's bundled in that file like it's installed on the emulator. Here we want to look at the resources that are bundled so we'll click resources.arsc.
We'll expand the section at the bottom a little bit and select string as resource types. See we actually have a ton of resources here that we didn't explicitly add. It says there are 60 different string resources across 83 configurations. Now we only have six languages, so where did all these other languages come from? We didn't add Japanese, we didn't add all of these German strings. So these are actually all getting pulled in from the Android support library.
Since the support library is used in most Android apps but isn't part of the operating system, Google has to provide translations for a ton of languages that they want to support. But what that means for our app is that they're providing some French strings. So this makes the resource resolution system think our app supports French even though we don't have any explicit French translations for any of the strings in our app. So when the system tries to resolve the strings in our app, it looks at the user's primary language, which is French, and sees that our app does have some French strings in it, but it doesn't have the one we're looking for, the subscription text.
So instead it defaults to the default language, English. Unfortunately it doesn't fail over to the user's secondary language. Now to fix this we can use an option in our Gradle build file. So let's go to the project explorer Expand Gradle scripts, and open up the build.gradle file for our app module. In our default configuration on line 12 we can add a new option called resConfigs.
ResConfigs tells Gradle which resources to keep around when it's building. So we can provide it a list of all the languages we want to explicitly support, but then we'd have to keep that up to date as we add new languages. The resConfig property has an option called auto, which we can use instead. So auto will automatically strip out languages that are not explicitly provided by you in this application module. So instead of having to maintain a list it just looks at the strings files that you have in the module and strips out all other languages instead.
Now we can rerun the app. Go to the subscription screen, and now we can see that the Italian string shows up this time. So understanding how the resource resolution system works really helps you to understand the intricacies of how each string is selected for display to your users no matter what locale they're in.
- The localization process
- Basic internationalization
- Choosing target markets
- Preparing your app for internationalization
- Translating your app
- Testing and releasing your translated app