Text is not updated when string tables are loaded asynchronously after the text element has already been shown

We observed the problem that UI text is not showing the localized text.

We are using string tables to localize text.

As far as we can see this happens when the UI element is initialize before the string table is loaded.

It looks like the UI element is not updated after the table is loaded.

The issue seems to be cased by

FVector2D FSlateTextBlockLayout::ComputeDesiredSize(const FWidgetDesiredSizeArgs& InWidgetArgs, const float InScale)when TextLastUpdate.IdenticalTo(TextToSet) returning false and TextLastUpdate.IsDisplayStringEqualTo(TextToSet) returns true.

`if (!TextLastUpdate.IdenticalTo(TextToSet))
{
// The pointer used by the bound text has changed, however the text may still be the same - check that now
if (!TextLastUpdate.IsDisplayStringEqualTo(TextToSet))
{
// The source text has changed, so update the internal text
bRequiresTextUpdate = true;
}

// Update this even if the text is lexically identical, as it will update the pointer compared by IdenticalTo for the next Tick
TextLastUpdate = FTextSnapshot(TextToSet);
}
LocalizedStringPtr is not used in the check for IsDisplayStringEqualTo`FTextSnapshot::IsDisplayStringEqualTo(const FText& InText) does not take LocalizedStringPtr into consideration

`bool FTextSnapshot::IsDisplayStringEqualTo(const FText& InText) const
{
// Make sure the string is up-to-date with the current culture
// (this usually happens when ToString() is called)
InText.Rebuild();

// We have to assume that the display string has changed if the history of the text has changed
// (due to a culture change), as we no longer have the old display string to compare against
return TextDataPtr
&& GlobalHistoryRevision == GetGlobalHistoryRevisionForText(InText)
&& LocalHistoryRevision == GetLocalHistoryRevisionForText(InText)
&& TextDataPtr->GetDisplayString().Equals(InText.TextData->GetDisplayString(), ESearchCase::CaseSensitive);
}`while IdenticalTo does.

What worked as a fix for us was extending the check to include LocalizedStringPtr in IsDisplayStringEqualTo.

`bool FTextSnapshot::IsDisplayStringEqualTo(const FText& InText) const
{
// Make sure the string is up-to-date with the current culture
// (this usually happens when ToString() is called)
InText.Rebuild();

// We have to assume that the display string has changed if the history of the text has changed
// (due to a culture change), as we no longer have the old display string to compare against
// add check to return false when the LocalizedStringPtr does not have the same validity state
return TextDataPtr
&& LocalizedStringPtr.IsValid() == InText.TextData->GetLocalizedString().IsValid()
&& GlobalHistoryRevision == GetGlobalHistoryRevisionForText(InText)
&& LocalHistoryRevision == GetLocalHistoryRevisionForText(InText)
&& TextDataPtr->GetDisplayString().Equals(InText.TextData->GetDisplayString(), ESearchCase::CaseSensitive);
}`

The question is, is there a specific reason why LocalizedStringPtr was not included in the check for IsDisplayStringEqualTo

Thanks for the answer.

LocalizedStringPtr.IsValid() == InText.TextData->GetLocalizedString().IsValid()is what I added to bool FTextSnapshot::IsDisplayStringEqualTo(const FText& InText) const and it solved the missing update after async load.

Sorry couldn’t figure out how to highlight a line in a code snipped.

Changed IsDisplayStringEqualTo to solve the specific case that the localized string changes from invalid to valid or the other way around:

`bool FTextSnapshot::IsDisplayStringEqualTo(const FText& InText) const
{
// Make sure the string is up-to-date with the current culture
// (this usually happens when ToString() is called)
InText.Rebuild();

// We have to assume that the display string has changed if the history of the text has changed
// (due to a culture change), as we no longer have the old display string to compare against
// add check to return false when the LocalizedStringPtr does not have the same validity state
return TextDataPtr`added line

&& LocalizedStringPtr.IsValid() == InText.TextData->GetLocalizedString().IsValid() && GlobalHistoryRevision == GetGlobalHistoryRevisionForText(InText) && LocalHistoryRevision == GetLocalHistoryRevisionForText(InText) && TextDataPtr->GetDisplayString().Equals(InText.TextData->GetDisplayString(), ESearchCase::CaseSensitive); }

Thanks for clarifying that culture invariant text changes the data pointer every time. I was afraid that there would be a way that this might happen.

Comparing the validity seems to solve the problem and hopefully does not lead to unnecessary updates even for culture invariant texts.