Localizing FATED in Unreal Engine 4 – Part 2

Michaël Dubé —  January 28, 2016 — 5 Comments

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:

Audio File Importer
Be sure to select “Localize languages” in Import Mode, and the desired language in “Destination language”.

Suite

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.

U4

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

5 responses to Localizing FATED in Unreal Engine 4 – Part 2

  1. 

    Hey Michael,

    First off, great posts, they have really helped me understand the loc process in ue4. We’re near the end of our project but have a strange issue that I can’t seem to be able to figure out at the moment… We have localized VO using Wwise, and we get the culture setting and turn that into a string (de, fr etc.). It works fine in standalone, but if I change my regional settings, our text loc is in the language, but the VO is always in english.. (we use blueprint for most everything except the custom loc library in wwise)I’m trying to figure out why. I’m not sure if it’s falling back to default each time or why it would be different in packaged build versus using standalone with launch params like -culture=de etc…. Maybe it’s related to this? :
    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.

    I tried finding ICUInternationlization.cpp but haven’t been able to…

    Any help would be appreciated, but thanks again for the great walkthrough!

    Like

    • 

      Hi!

      Thanks for the feedback! Your issue looks like what I described in my post, you can find the file I’m mentionning at this location:

      Engine\Source\Runtime\Core\Private\Internationalization\ICUInternationalization.cpp

      Let me know if you were able to solve your problem!

      Mick

      Like

      • 

        Thanks for the quick response! So it ended up being another issue for us, but I think I’m going to also implement that fix, as it should help so people won’t have to change their regional settings in windows unless they really need to to see loc stuff. 🙂
        Appreciate it and bets of luck to you, appreciate the dev posts!

        Liked by 1 person

  2. 

    Hey man,

    Thanks for the article! We are currently localizing our game and i’m stuck with getting the Steam App Language.
    How does your OnlineSubsystemSteam.h look like? I mean where exactly did you add your GetSteamAppLanguage() function?
    I added it underneath “FString GetAppId() const override;”, but when i try to acces the function a always get this mesage:
    ‘GetSteamAppLanguage’: is not a member of ‘IOnlineSubsystem’.
    Maybe you could help me out here 🙂

    Cheers,
    Tobi

    Like

    • 
      Aluminiumimmunity October 17, 2016 at 1:40 pm

      Ok, nvrmind my first question, i got it running. However, the function returns null when i play in standalone. Any idea how this could be possible? Steam overlay/achievements etc. are working fine, but somehow this line returns nothing:
      langFString = FString(ANSI_TO_TCHAR(steamApps->GetCurrentGameLanguage()));
      Any help would be greatly appreciated!

      Cheers,
      Tobi

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s