Hello again folks!
This week, I pick up where I left off last week with Localizing FATED in Unreal Engine 4 – Part 1. I already covered the basis of text localization, i’ll follow up with Voice-Over localization using Wwise as well as other things to consider when localizing in Unreal Engine 4.
Localizing Voice-Over Using Wwise
Wwise is a really great tool, and I can’t imagine doing audio work without it ever again. The Unreal Engine integration is great, even if some stuff is missing, namely localization support. Fortunately, all the ground work is pretty much done, meaning there are only a couple of things you need to modify to make it all work.
Adding localized audio files in your Wwise project
The first thing you want to do is actually setup your localized audio files in your Wwise project using the Wwise authoring tool. This is very easy to do, and requires no additional step in the UE4 editor, since what you import in Unreal (Events and Banks) is language-agnostic. Basically, the event stays the same, but the audio files played will differ. The only thing you have to do is import the new localized audio file over the already existing audio files in Wwise. Right-click on an audio file (or folder) and select “Import Audio Files…”.
This screen will show up:
Be sure to select “Localize languages” in Import Mode, and the desired language in “Destination language”.
Select the preview language in theWwise authoring tool
Now, you do this for every VO of your game. It is important that every VO file name match your original VO file name. You can import by folder to go faster. You can also set your project in the desired language; that way Wwise recognizes which audio files have a counterpart file for the selected language. This makes it easy to know which audio does not have a valid localization yet. Once this is done, everything you had to do on the Wwise side is done! Let’s return to Unreal!
Generating banks for all supported languages
In AkAudioBankGenerationHelpers.cpp you will find the GenerateSoundBanks() function. In there, the following line specifies which bank language will be generated:
CommandLineParams += TEXT(" -Language English(US)");
For some reason, by default it only generates English banks; basically you have to add each language you want to generate. Even simpler, just comment out the line. This will make it so that it generates all languages specified in your Wwise project.
Specifying Culture in the Game
Now that the text and voice-overs have been generated in every supported language, you actually need to specify which language you want the game to show. In general, you’ll want to do this operation at the very start of the game. Unreal offers a simple way to launch the game in the desired culture using a launch argument: -culture=“fr”.
This will effectively call for the change in culture on the text side; unfortunately, it does not do anything regarding the Wwise banks. Instead of using the -culture argument, let’s dive in and see the actual calls we need to make the switch of culture happen.
For the text, the FInternationalization class is used to set different cultures. Here is an example of how to set the game in French:
FInternationalization::Get().SetCurrentCulture(TEXT("fr"));
This will only change the text, however. For the Wwise content, you need to do yet another small change. For that purpose, I added a function to the UAkGameplayStatics class that I called void SetLanguageToCurrentCulture().
In this function, the first step is to get the current culture:
FString currentCulture = FInternationalization::Get().GetCurrentCulture()->GetName();
After that, you can assign the Wwise current language this way:
AK::StreamMgr::SetCurrentLanguage(AKTEXT("French(Canada)"));
The name of the language is a string equivalent of how the language is called inside the Wwise authoring tool.
Optionally, you can also get the current Wwise language and unload the VO bank if the new language is not the same as what was loaded.
AK::StreamMgr::GetCurrentLanguage(); UnloadBankByName(TEXT("Act01_VO"));
Now you should have everything you need to have your game’s text and voice-overs localized.
IMPORTANT NOTE: For some reason, Unreal does not allow the culture to be changed directly in the editor. This can be frustrating if you want to see the content in another culture directly in the editor. Fortunately, there is a way to remedy the situation quite easily.
In TextLocalizationManager.cpp, you can find the OnCultureChanged() function. What you want to do is remove the FApp::IsGame() from the ShouldLoadGame initialization.
//const bool ShouldLoadGame = bIsInitialized && FApp::IsGame(); //Before const bool ShouldLoadGame = bIsInitialized; //After
IMPORTANT NOTE 2: Yet another “annoying” default behavior is that a packaged game will not fallback to “root” culture when the culture specified is more specific. For example, if your game is in “fr-CA”, it will not default back to “fr” but rather to the default culture, which is “en”. Yet again, a small change will fix that.
In ICUInternalization.cpp, you can find the SetCurrentCulture(const FString&) function. You simply want to allow fallback, which is something already done in Unreal, just not set by default.
// Allow Fallback, this make it so that we can use “root” language like “en” and “fr” and not need to specify “en-US”,”fr-CA”, “fr-CD”, “fr-CF”…
FCulturePtr NewCurrentCulture = FindOrMakeCulture(Name, true /*Allow Fallback*/);
Getting the Steam App Language
I won’t go over how to setup your game for Steam (there are already a few good tutorials out there for that), but I’ll talk about the snippet of code needed to use the language currently selected in Steam.
First, I added FString GetSteamAppLanguage(); in OnlineSubsystemSteam. You can add it to your custom version of OnlineSubsystemSteam, but I felt it was enough of a “core” feature to be added directly to OnlineSubsystemSteam.
Here is the function in its entirety:
FString FOnlineSubsystemSteam::GetSteamAppLanguage() { FString langFString = TEXT("english");//Default
ISteamApps* steamApps = SteamApps(); if (steamApps) { langFString = FString(ANSI_TO_TCHAR(steamApps->GetCurrentGameLanguage())); } return langFString; }
SteamApps() won’t always be valid, depending on some factors (like if the game was launched from Steam or not), so be sure to have a default value to fallback to.
Unreal is certainly going to add a lot to its Localization toolset; in fact, it’s already happening in 4.10.1 with the OneSky localization service plugin. This will certainly come in handy if you’re thinking about using that service for your game. There is also the experimental “Localization Dashboard” that can be activated in the “Experimental” section of Editor Preferences.
I did not use the Dashboard extensively, but it promises to one day remove all that “.ini” manipulation (which is not that user-friendly…) and make it all transparent through a nice visual tool. It seems to work well enough, but all it will do is manipulate all the files we talked about earlier, so it is still relevant to know how these files work.
This is it for localization in UE4. Obviously, there is more to it than what I addressed in this post, but you should be well on your way to making it work in your own game. Hope this was helpful, and don’t hesitate to ask questions in the comments section. Stay tuned for more on FATED, as we quickly approach the release date!
Mick / Lead Programmer / @Mickd777
www.fatedgame.com