A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
DlgLocalizationHelper.cpp
Go to the documentation of this file.
1// Copyright Csaba Molnar, Daniel Butum. All Rights Reserved.
3
4#include "DlgSystemSettings.h"
5#include "Internationalization/Text.h"
6#include "Internationalization/TextPackageNamespaceUtil.h"
7#include "Serialization/TextReferenceCollector.h"
8
9
11{
12 const auto* Settings = GetDefault<UDlgSystemSettings>();
13 return WillTextNamespaceBeUpdated(Text, *Settings);
14}
15
17{
18 // Means we can override it
20 Settings.IsIgnoredTextForLocalization(Text);
21}
22
24{
25 if (Settings.IsTextRemapped(OutText))
26 {
27 // Remapped
28 const FText& RemappedText = Settings.GetTextRemappedText(OutText);
29 OutText = RemappedText;
30 // Copy namespace and key
31 // NewNamespace = FTextInspector::GetNamespace(RemappedText).Get(DefaultValue);
32 // NewKey = FTextInspector::GetKey(RemappedText).Get(DefaultValue);
33 }
34}
35
36#if WITH_EDITOR
37
39{
40 static const FString DefaultValue = TEXT("");
41
42 // See if we can edit this
43 if (!IsValid(Object))
44 {
45 return;
46 }
47
48 // Text remapping takes precedence over everything
49 FString NewNamespace;
50 FString NewKey;
51 if (!GetNewNamespaceAndKey(Object, Settings, Text, NewNamespace, NewKey))
52 {
53 return;
54 }
55
56 // Change namespace
57 // Don't use this as this marks the text as immutable
58 // Text = FInternationalization::ForUseOnlyByLocMacroAndGraphNodeTextLiterals_CreateText(*Text.ToString(), *NewNamespace, *CurrentKey);
59 Text = FText::ChangeKey(NewNamespace, NewKey, Text);
60}
61
62bool FDlgLocalizationHelper::GetNewNamespaceAndKey(
63 const UObject* Object,
64 const UDlgSystemSettings& Settings,
65 const FText& Text,
66 FString& OutNewNamespace,
67 FString& OutNewKey
68)
69{
70 static const FString DefaultValue = TEXT("");
72 {
73 return false;
74 }
75 // Culture invariant, empty, from string table, can't update idk
76 if (!Text.ShouldGatherForLocalization())
77 {
78 return false;
79 }
80 if (!Settings.IsIgnoredTextForLocalization(Text))
81 {
82 return false;
83 }
84
85 bool bNamespaceChanged = false;
86 bool bKeyChanged = false;
87
88 const FString CurrentFullNamespace = FTextInspector::GetNamespace(Text).Get(DefaultValue);
89 const FString CurrentKey = FTextInspector::GetKey(Text).Get(DefaultValue);
90 FString NewKey = CurrentKey;
91
92 // Set new Namespace
93 FString NewNamespace = Settings.DialogueTextGlobalNamespaceName; // GlobalNamespace
95 {
96 NewNamespace = Object->GetName();
97 }
99 {
100 NewNamespace = Settings.DialogueTextPrefixNamespaceName + Object->GetName();
101 }
102
103 // Did namespace change?
104 // Only apply the change if the new namespace/package is different - we want to keep the keys stable where possible
105#if USE_STABLE_LOCALIZATION_KEYS
106 {
107 // Compare namespace + package
108 const UPackage* Package = Object ? Object->GetOutermost() : nullptr;
109 const FString PackageNamespace = TextNamespaceUtil::EnsurePackageNamespace(const_cast<UPackage*>(Package));
110 const FString NewFullNamespace = TextNamespaceUtil::BuildFullNamespace(NewNamespace, PackageNamespace, /*bAlwaysApplyPackageNamespace*/true);
111 bNamespaceChanged = !CurrentFullNamespace.Equals(NewFullNamespace, ESearchCase::CaseSensitive);
112 }
113#else
114 // Compare only namespaces without the package
115 const FString CurrentNamespace = TextNamespaceUtil::StripPackageNamespace(CurrentFullNamespace);
116 bNamespaceChanged = !CurrentNamespace.Equals(NewNamespace, ESearchCase::CaseSensitive);
117#endif // USE_STABLE_LOCALIZATION_KEYS
118
119 // Did key change?
120 //bKeyChanged = !CurrentKey.Equals(NewKey, ESearchCase::CaseSensitive);
121
122 // Get stabilized namespace and keys
123 // We must use the package to get a stabilized key
124#if USE_STABLE_LOCALIZATION_KEYS
125 if (bNamespaceChanged)
126 {
127 // NOTE: dereference should be legal because GetSourceString always return a valid pointer
128 const FString& TextSource = *FTextInspector::GetSourceString(Text);
129 FString NewStableNamespace;
130 FString NewStableKey;
131 StaticStableTextId(
132 Object,
133 IEditableTextProperty::ETextPropertyEditAction::EditedNamespace,
134 TextSource,
135 NewNamespace,
136 NewKey,
137 NewStableNamespace,
138 NewStableKey
139 );
140 NewNamespace = NewStableNamespace;
141 NewKey = NewStableKey;
142 }
143#endif // USE_STABLE_LOCALIZATION_KEYS
144
145 // Did key change?
146 bKeyChanged = !CurrentKey.Equals(NewKey, ESearchCase::CaseSensitive);
147
148 // Something changed
149 if (bNamespaceChanged || bKeyChanged)
150 {
151 OutNewNamespace = NewNamespace;
152 OutNewKey = NewKey;
153 return true;
154 }
155
156 return false;
157}
158
159
160#if USE_STABLE_LOCALIZATION_KEYS
161
162void FDlgLocalizationHelper::StaticStableTextId(const UObject* InObject, IEditableTextProperty::ETextPropertyEditAction InEditAction, const FString& InTextSource, const FString& InProposedNamespace, const FString& InProposedKey, FString& OutStableNamespace, FString& OutStableKey)
163{
164 const UPackage* Package = InObject ? InObject->GetOutermost() : nullptr;
165 StaticStableTextId(Package, InEditAction, InTextSource, InProposedNamespace, InProposedKey, OutStableNamespace, OutStableKey);
166}
167
168void FDlgLocalizationHelper::StaticStableTextId(const UPackage* InPackage, IEditableTextProperty::ETextPropertyEditAction InEditAction, const FString& InTextSource, const FString& InProposedNamespace, const FString& InProposedKey, FString& OutStableNamespace, FString& OutStableKey)
169{
170 bool bPersistKey = false;
171
172 const FString PackageNamespace = TextNamespaceUtil::EnsurePackageNamespace(const_cast<UPackage*>(InPackage));
173 if (!PackageNamespace.IsEmpty())
174 {
175 // Make sure the proposed namespace is using the correct namespace for this package
176 OutStableNamespace = TextNamespaceUtil::BuildFullNamespace(InProposedNamespace, PackageNamespace, /*bAlwaysApplyPackageNamespace*/true);
177
178 if (InProposedNamespace.Equals(OutStableNamespace, ESearchCase::CaseSensitive) || InEditAction == IEditableTextProperty::ETextPropertyEditAction::EditedNamespace)
179 {
180 // If the proposal was already using the correct namespace (or we just set the namespace), attempt to persist the proposed key too
181 if (!InProposedKey.IsEmpty())
182 {
183 // If we changed the source text, then we can persist the key if this text is the *only* reference using that ID
184 // If we changed the identifier, then we can persist the key only if doing so won't cause an identify conflict
185 const FTextReferenceCollector::EComparisonMode ReferenceComparisonMode = InEditAction == IEditableTextProperty::ETextPropertyEditAction::EditedSource ? FTextReferenceCollector::EComparisonMode::MatchId : FTextReferenceCollector::EComparisonMode::MismatchSource;
186 const int32 RequiredReferenceCount = InEditAction == IEditableTextProperty::ETextPropertyEditAction::EditedSource ? 1 : 0;
187
188 int32 ReferenceCount = 0;
189 FTextReferenceCollector(InPackage, ReferenceComparisonMode, OutStableNamespace, InProposedKey, InTextSource, ReferenceCount);
190
191 if (ReferenceCount == RequiredReferenceCount)
192 {
193 bPersistKey = true;
194 OutStableKey = InProposedKey;
195 }
196 }
197 }
198 else if (InEditAction != IEditableTextProperty::ETextPropertyEditAction::EditedNamespace)
199 {
200 // If our proposed namespace wasn't correct for our package, and we didn't just set it (which doesn't include the package namespace)
201 // then we should clear out any user specified part of it
202 OutStableNamespace = TextNamespaceUtil::BuildFullNamespace(FString(), PackageNamespace, /*bAlwaysApplyPackageNamespace*/true);
203 }
204 }
205
206 if (!bPersistKey)
207 {
208 OutStableKey = FGuid::NewGuid().ToString();
209 }
210}
211
212#endif // USE_STABLE_LOCALIZATION_KEYS
213
214#endif // WITH_EDITOR
static void UpdateTextFromRemapping(const UDlgSystemSettings &Settings, FText &OutText)
static bool WillTextNamespaceBeUpdated(const FText &Text)
static void UpdateTextNamespaceAndKey(const UObject *Object, const UDlgSystemSettings &Settings, FText &Text)
UCLASS(Config = Engine, DefaultConfig, meta = (DisplayName = "Dialogue System Settings"))
EDlgTextNamespaceLocalization DialogueTextNamespaceLocalization
UPROPERTY(Category = "Localization", Config, EditAnywhere, DisplayName = "Text Namespace")
FString DialogueTextPrefixNamespaceName
UPROPERTY(Category = "Localization", Config, EditAnywhere, DisplayName = "Text Namespace Name Prefix"...
FString DialogueTextGlobalNamespaceName
UPROPERTY(Category = "Localization", Config, EditAnywhere, DisplayName = "Text Global Namespace Name"...
bool IsIgnoredTextForLocalization(const FText &Text) const
FORCEINLINE const FText & GetTextRemappedText(const FText &Text) const
FORCEINLINE bool IsTextRemapped(const FText &Text) const