Can variables be used in LOCTEXT? Or, how to handle grammar in localization

I have a bunch of actors with names. When the player comes near them, a UMG widget will pop up and say “Take the ___”, eg. “Take the chair”, “Take the box”, etc.

Because grammar could be different in other languages, I don’t want to just concatenate “Take the” and the actor’s name; I want to make a new key value pair in the localization list, something like LOCTEXT("take/" + actor.name, "Take the " + actor.name). Obviously this would mean re-translating things twice (eg. ‘box’ and ‘take the box’), but I can’t think of another way to handle grammar properly.

So how can I use variables in LOCTEXT, or is there a better way to go about this?

You never want to concatenate localizable text in code, nor in blueprints. You should use FText::Format() or “Format Text” in BPs, and replace the inputs with markers that can be moved by the translator. This assumes item.name and target.name are FText properties below.

E.g.

FText::Format(LOCTEXT("PlaceItem", "Take the {0} and put it on {1}"), item.name, target.name);

This way, the translator can move {0} and {1} around as he pleases and it’ll turn out correctly. Note that this doesn’t work if the grammar of the sentence changes with the item or target, or count of them, that’s just a limitation of the engine (and pretty messy to get right even if supported).

If the sentence is complex, you can use named arguments:

FFormatNamedArguments Arguments;
Arguments.Add(TEXT("item"), item.name);
Arguments.Add(TEXT("target"), target.name);
FText::Format(LOCTEXT( "PlaceItem", "Take the {item} and put it on {target}"), Arguments);
1 Like

Thanks for the ideas! Haven’t tried it yet but I think it might be possible to have both the argument and the formatter string as localized text. Then I can do something like FText::Format(LOCTEXT("TakeItem", "Take the {0}"), LOCTEXT("ItemToTake_Chair", "Chair")); So then if I translate it to say Japanese or something, “TakeItem” would be “{0}を取る”.

Yes, in my example above item.name and target.name would definitely be an FText defined either using LOCTEXT or via some data table associated with each item, understood by the localization tool. If you don’t have one of the texts as a parameter, there’s not that much reason to split them up in the first place.