Localization not finding FTexts in UDataAsset

I have FText fields located in a USTRUCT that exists within a TArray of a UDataAsset class.

Here is a simplified example:

USTRUCT()
struct FCharacterClassData
{
	GENERATED_USTRUCT_BODY()

public:

	UPROPERTY(EditDefaultsOnly)
	FText Description;
}

UCLASS()
class  UClassLoadoutStaticData : public UDataAsset
{
	GENERATED_BODY()
	
public:

	UPROPERTY(EditDefaultsOnly)
	TArray<FCharacterClassData> CharacterClassList;
};

In the editor I’ve created a .uasset file from UClassLoadoutStaticData and filled out the array with a list of text that needs to be localized. However, when I run the GatherText commandlet it does not find these FText strings and add them to the manifest.

The gather Text step should be set up correctly:

;Gather text from assets in content.
[GatherTextStep1]
CommandletClass=GatherTextFromAssets
IncludePaths=./Content/DataAssets/
ExcludePaths=*/Content/Localization/*
PackageExtensions=*.umap
PackageExtensions=*.uasset

Is there something I am doing wrong or is the UDataAsset not supported for localization in the way I expect?

Any UObject’s directly or indirectly contained FText properties should be gathered. Only UDialogueWave and UDataTable require special localization support, as they aren’t simply UObjects with FText properties. UDataAsset should not need any explicit localization support. As far as I can tell, this should just work. I’ll test this locally and have more information or questions for you next week.

I looked into the GatherTextFromAssetsCommandlet.cpp and under UGatherTextFromAssetsCommandlet::ProcessPackages it looks like it only gather’s text from objects if they are of type UBlueprint, UDataTable or UDialogueWave.

This is the code for blueprint objects:

if ( Object->IsA( UBlueprint::StaticClass() ) )
			{
				UBlueprint* Blueprint = Cast<UBlueprint>( Object );

				if( Blueprint->GeneratedClass != NULL )
				{
					FGatherTextFromObject::Execute(this, Blueprint->GeneratedClass->GetDefaultObject(), Package, bFixBroken);
				}
				else
				{
					UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("%s - Invalid generated class!"), *Blueprint->GetFullName());
				}
			}

I took that to mean that the UDataAsset is not supported here without engine changes.

Not quite. The full excerpt is as such.

			UObject* Object = Objects[j];
			if ( Object->IsA( UBlueprint::StaticClass() ) )
			{
				UBlueprint* Blueprint = Cast<UBlueprint>( Object );

				if( Blueprint->GeneratedClass != NULL )
				{
					FGatherTextFromObject::Execute(this, Blueprint->GeneratedClass->GetDefaultObject(), Package, bFixBroken);
				}
				else
				{
					UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("%s - Invalid generated class!"), *Blueprint->GetFullName());
				}
			}
			else if ( Object->IsA( UDataTable::StaticClass() ) )
			{
				UDataTable* DataTable = Cast<UDataTable>(Object);
				FGatherTextFromDataTable::Execute(this, DataTable, Package, bFixBroken);
			}
			else if( Object->IsA( UDialogueWave::StaticClass() ) )
			{
				UDialogueWave* DialogueWave = Cast<UDialogueWave>(Object);
				ProcessDialogueWave(DialogueWave);
			}

			FGatherTextFromObject::Execute(this, Object, Package, bFixBroken);

There is specific additional gathering done for blueprints, data tables, and dialogue waves, but regardless, FGatherTextFromObject::Execute is called at the end of the object iterating loop.

I’m investigating today why it seems that data assets are not being gathered for you.

I’ve attempted to recreate the problem using the code you provided in a brand new project in the latest version of 4.7 and could not reproduce the issue. I made a data asset of the type you wrote, gave its array two elements, “Foo” and “Bar”, and did a gather, which yielded a manifest with both “Foo” and “Bar” in it.

This was my simple localization configuration script:

;Common settings to be used for all commandlets as needed.
[CommonSettings]
SourcePath=./Content/Localization/Game
DestinationPath=./Content/Localization/Game
ManifestName=Game.manifest
;English
SourceCulture=en
;English
CulturesToGenerate=en

;Gather text from source code and configuration files.
[GatherTextStep0]
CommandletClass=GatherTextFromSource
IncludePaths=./Source/
IncludePaths=./Config/
ExcludePaths=*/Config/Localization/*
SourceFileSearchFilters=*.h
SourceFileSearchFilters=*.cpp
SourceFileSearchFilters=*.ini

;Gather text from assets in content.
[GatherTextStep1]
CommandletClass=GatherTextFromAssets
IncludePaths=./Content/
ExcludePaths=*/Content/Localization/*
PackageExtensions=*.umap
PackageExtensions=*.uasset

;Create manifest with all gathered source text.
[GatherTextStep2]
CommandletClass=GenerateGatherManifest

Do you have any theories as to what might be different in your case, so that I can reproduce the issue and resolve it?

Thanks for your help Sheevok. I changed the data assets to data-only blueprints and the gather text worked for them so I’m still not sure what the problem is on my project.

I will return to this as soon as I have time to investigate further. I do have one question:

I’m running the GatherText commandlet like this:

call “UE4Editor.exe” “Z:\Project.uproject” -run=GatherText -config=“Z:\Project\Config\Localization\Game.ini” -log

but I can’t get the window to stay open to read the logs it provides. The window closes immediately as soon as it finishes the command and I could be missing errors that could tell us what is going on. Is there some way to keep the log window open after it completes?

Perhaps if you can create a very small project recreating the issue, compress it, and upload it here, I could take a look? At your leisure.

With 4.8, you may try the Localization Dashboard experimental feature, which effectively gives a safer, user-friendlier graphic interface to the localization workflow.

You should be able to find logs in the project’s /Saved/Logs directory. I’m not familiar with any appropriate mechanism to keep the log window open.

Any update on this? or a CL to grab?