From e5aa4413a8e6b2d2b9dfe47e2832e4b7e8f26936 Mon Sep 17 00:00:00 2001 From: Ryan Lim Date: Sat, 16 May 2026 02:42:43 +0800 Subject: [PATCH 1/9] - Implemented functionality to Generate String Table filled with Key References. --- Content/ELTEditorWidget_BP.uasset | Bin 391691 -> 534575 bytes .../Private/ELTEditor.cpp | 94 ++++++++++++++++++ .../Private/ELTEditorSettings.cpp | 10 ++ .../Private/ELTEditorWidget.cpp | 17 ++++ .../Private/SELTEditorWidget.cpp | 42 ++++++++ .../Public/ELTEditor.h | 5 + .../Public/ELTEditorSettings.h | 8 +- .../Public/ELTEditorWidget.h | 16 +++ .../Public/SELTEditorWidget.h | 2 + 9 files changed, 193 insertions(+), 1 deletion(-) diff --git a/Content/ELTEditorWidget_BP.uasset b/Content/ELTEditorWidget_BP.uasset index 938762f151f94885f26b5a8f3a9890ddaca42ca1..7beb0a8b8d1ebbb3c405ba4fc93a3fde86206890 100644 GIT binary patch literal 534575 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

u_Q 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 literal 391691 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 ZL3{_!v5}Dou_L6>e5{c>IHt|Q{{vJDtLp#& diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp index e4dfc65..785774c 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp @@ -1,14 +1,18 @@ // Copyright (c) 2026 Damian Nowakowski. All rights reserved. #include "ELTEditor.h" +#include "AssetToolsModule.h" #include "Internationalization/TextLocalizationResource.h" #include "Internationalization/TextLocalizationManager.h" +#include "Internationalization/StringTableCore.h" +#include "Internationalization/StringTable.h" #include "Misc/FileHelper.h" #include "Misc/Paths.h" #include "Misc/MessageDialog.h" #include "ELTEditorSettings.h" #include "ELTEditorWidget.h" #include "ELTSettings.h" +#include "UObject/SavePackage.h" #if ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 1)) #include "AssetRegistry/AssetRegistryModule.h" @@ -162,6 +166,7 @@ void UELTEditor::InitializeTheWidget() EditorWidget->OnGlobalNamespaceChangedDelegate.BindUObject(this, &UELTEditor::OnGlobalNamespaceChanged); EditorWidget->OnSeparatorChangedDelegate.BindUObject(this, &UELTEditor::OnSeparatorChanged); EditorWidget->OnFallbackWhenEmptyChangedDelegate.BindUObject(this, &UELTEditor::OnFallbackWhenEmptyChanged); + EditorWidget->OnGenerateKeyReferenceStringTableChangedDelegate.BindUObject(this, &UELTEditor::OnGenerateKeyReferenceStringTableChanged); EditorWidget->OnLogDebugChangedDelegate.BindUObject(this, &UELTEditor::OnLogDebugChanged); EditorWidget->OnPreviewInUIChangedDelegate.BindUObject(this, &UELTEditor::OnPreviewInUIChanged); @@ -198,6 +203,9 @@ void UELTEditor::InitializeTheWidget() EditorWidget->CallSetLocalizationOnFirstRun(UELTSettings::GetOverrideLanguageAtFirstLaunch()); EditorWidget->CallSetLocalizationOnFirstRunLang(UELTSettings::GetLanguageToOverrideAtFirstLaunch()); + // Set the Generate Key Reference String Table current value to the Widget. + EditorWidget->CallSetGenerateKeyReferenceStringTable(UELTEditorSettings::GetGenerateKeyReferenceStringTable()); + // Set LogDebug value to the Widget. EditorWidget->CallSetLogDebug(UELTEditorSettings::GetLogDebug()); @@ -357,6 +365,11 @@ void UELTEditor::OnFallbackWhenEmptyChanged(const FString& NewFallback) UELTEditorSettings::SetFallbackWhenEmpty(NewFallback); } +void UELTEditor::OnGenerateKeyReferenceStringTableChanged(bool bNewGenerateKeyReferenceStringTable) +{ + UELTEditorSettings::SetGenerateKeyReferenceStringTable(bNewGenerateKeyReferenceStringTable); +} + void UELTEditor::OnLogDebugChanged(bool bNewLogDebug) { // "Log Debug" flag has been changed in the Widget. Save this setting. @@ -502,8 +515,12 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt const FString MetaFileName = LocPath / LocName + TEXT(".locmeta"); const bool bLogDebug = UELTEditorSettings::GetLogDebug(); + const bool bGenerateStringTable = UELTEditorSettings::GetGenerateKeyReferenceStringTable(); + bool bFirstCSV = true; TMap LocReses; + TMap> NamespaceToKeysMap; + for (const FString& CSVPath : CSVPaths) { const FString CSVFilePath = FPaths::ConvertRelativePathToFull(CSVPath); @@ -636,6 +653,11 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt Keys.Values[Key], LocalizedString, 0); + + if (bGenerateStringTable && !Keys.Values[Key].IsEmpty()) + { + NamespaceToKeysMap.FindOrAdd(Namespace).Add(Keys.Values[Key]); + } } } } @@ -674,6 +696,78 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt LocRes.Value.SaveToFile(LocFileName); } + // Generate Key Reference String Table + if (bGenerateStringTable && NamespaceToKeysMap.Num() > 0) + { + FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked("AssetTools"); + + for (const auto& KVP : NamespaceToKeysMap) + { + const FString& Namespace = KVP.Key; + const TSet& Keys = KVP.Value; + + FString AssetName = FString::Printf(TEXT("ELT_KeyReferences_%s_%s"), *LocName, *Namespace); + FString VirtualPath = LocPath.StartsWith(TEXT("/Game")) ? LocPath : FPackageName::FilenameToLongPackageName(LocPath); + FString PackagePath = FPaths::Combine(VirtualPath, AssetName); + FPaths::NormalizeFilename(PackagePath); + + if (!PackagePath.StartsWith(TEXT("/"))) + { + PackagePath = TEXT("/") + PackagePath; + } + + UPackage* Package = CreatePackage(*PackagePath); + if (!Package) + { + OutMessage = FString::Printf(TEXT("ERROR: Failed to create package path for StringTable: %s"), *PackagePath); + return false; + } + + UStringTable* StringTableAsset = Cast(StaticFindObject(UStringTable::StaticClass(), Package, *AssetName)); + if (!StringTableAsset) + { + StringTableAsset = Cast(AssetToolsModule.Get().CreateAsset( + AssetName, + VirtualPath, + UStringTable::StaticClass(), + nullptr + )); + } + + if (!StringTableAsset) + { + OutMessage = FString::Printf(TEXT("ERROR: Failed to create StringTable asset: %s"), *AssetName); + return false; + } + + FStringTableRef StringTableRef = StringTableAsset->GetMutableStringTable(); + StringTableRef->SetNamespace(Namespace); + + for (const FString& Key : Keys) + { + StringTableRef->SetSourceString(FTextKey(Key), Key); + } + + Package->MarkPackageDirty(); + + FString PackageFileName = FPackageName::LongPackageNameToFilename(PackagePath, FPackageName::GetAssetPackageExtension()); + FSavePackageArgs SaveArgs; + SaveArgs.TopLevelFlags = RF_Public | RF_Standalone; + SaveArgs.Error = GError; + + if (!UPackage::SavePackage(Package, StringTableAsset, *PackageFileName, SaveArgs)) + { + OutMessage = FString::Printf(TEXT("ERROR: Failed to save StringTable package file to disk path: %s"), *PackageFileName); + return false; + } + + if (bLogDebug) + { + UE_LOG(ELTEditorLog, Log, TEXT("Saved String Table Asset: %s"), *PackageFileName); + } + } + } + OutMessage = TEXT("SUCCESS: Localization import complete!"); return true; } diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditorSettings.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditorSettings.cpp index 6a74ded..c7b1704 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTEditorSettings.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditorSettings.cpp @@ -72,6 +72,16 @@ void UELTEditorSettings::SetReimportAtEditorStartup(bool bNewReimportAtEditorSta ELTE_SET_SETTING(bReimportAtEditorStartup, bNewReimportAtEditorStartup); } +bool UELTEditorSettings::GetGenerateKeyReferenceStringTable() +{ + ELTE_GET_SETTING(bGenerateKeyReferenceStringTable); +} + +void UELTEditorSettings::SetGenerateKeyReferenceStringTable(bool bNewGenerateKeyReferenceStringTable) +{ + ELTE_SET_SETTING(bGenerateKeyReferenceStringTable, bNewGenerateKeyReferenceStringTable); +} + bool UELTEditorSettings::GetPreviewInUIEnabled() { ELTE_GET_SETTING(bPreviewInUI); diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditorWidget.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditorWidget.cpp index c3d0b07..dbe5394 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTEditorWidget.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditorWidget.cpp @@ -153,6 +153,18 @@ void UELTEditorWidget::CallSetLocalizationOnFirstRun(bool LocalizationOnFirstRun #endif } +void UELTEditorWidget::CallSetGenerateKeyReferenceStringTable(bool bGenerateKeyReferenceStringTable) +{ +#if ELTEDITOR_USE_SLATE_EDITOR_UI + if (MyWidget.IsValid()) + { + MyWidget->SetGenerateKeyReferenceStringTable(bGenerateKeyReferenceStringTable); + } +#else + SetReimportAtEditorStartup(bReimportAtEditorStartup); +#endif +} + void UELTEditorWidget::CallSetLocalizationOnFirstRunLang(const FString& OnFirstRunLang) { #if ELTEDITOR_USE_SLATE_EDITOR_UI @@ -281,6 +293,11 @@ void UELTEditorWidget::OnLocalizationOnFirstRunLangChanged(const FString& OnFirs OnLocalizationOnFirstRunLangChangedDelegate.ExecuteIfBound(OnFirstRunLang); } +void UELTEditorWidget::OnGenerateKeyReferenceStringTableChanged(bool bGenerateKeyReferenceStringTable) +{ + OnGenerateKeyReferenceStringTableChangedDelegate.ExecuteIfBound(bGenerateKeyReferenceStringTable); +} + void UELTEditorWidget::OnGlobalNamespaceChanged(const FString& NewGlobalNamespace) { OnGlobalNamespaceChangedDelegate.ExecuteIfBound(NewGlobalNamespace); diff --git a/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp b/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp index 5f59a13..47cd258 100644 --- a/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp +++ b/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp @@ -476,6 +476,43 @@ KEY - use the key of this entry")) ] ] ] + // > Generate Key Reference String Table on Import Box ================ + +SVerticalBox::Slot() + .AutoHeight() + .Padding(FMargin(0.f, 4.f, 0.f, 0.f)) + [ + SNew(SHorizontalBox) + .ToolTipText(INVTEXT("\ +On CSV Import, a String Table filled with Key References will be generated PER namespace.\n\ +These String Table can be used to easily assign keys to FText properties.\n\n\ +The String Table will be generated in the Localization Folder path and IS OVERRIDDEN if it already exists.")) + // >>>> Generate Key Reference String Table CSV Import Label + +SHorizontalBox::Slot() + .AutoWidth() + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Text(INVTEXT("Generate Key Reference String Table on Import:")) + ] + // >>>> Generate Key Reference String Table on Import checkbox + +SHorizontalBox::Slot() + .AutoWidth() + [ + SNew(SCheckBox) + .IsChecked_Lambda([this]() -> ECheckBoxState + { + return bGenerateKeyReferenceStringTable_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void + { + bGenerateKeyReferenceStringTable_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); + if (WidgetController.IsValid()) + { + WidgetController->OnGenerateKeyReferenceStringTableChanged(bGenerateKeyReferenceStringTable_Chkbox); + } + }) + ] + ] // > Spacer ================ +SVerticalBox::Slot() .AutoHeight() @@ -819,6 +856,11 @@ void SELTEditorWidget::SetFallbackWhenEmpty(const FString& FallbackWhenEmpty) } } +void SELTEditorWidget::SetGenerateKeyReferenceStringTable(bool bGenerateKeyReferenceStringTable) +{ + bGenerateKeyReferenceStringTable_Chkbox = bGenerateKeyReferenceStringTable; +} + void SELTEditorWidget::SetLogDebug(bool bLogDebug) { bLogDebug_Chkbox = bLogDebug; diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditor.h b/Source/EasyLocalizationToolEditor/Public/ELTEditor.h index 9e2668b..25fac18 100644 --- a/Source/EasyLocalizationToolEditor/Public/ELTEditor.h +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditor.h @@ -144,6 +144,11 @@ class EASYLOCALIZATIONTOOLEDITOR_API UELTEditor : public UObject */ void OnFallbackWhenEmptyChanged(const FString& NewFallback); + /** + * Called when "GenerateKeyReferenceStringTable" option has been changed in the Widget. + */ + void OnGenerateKeyReferenceStringTableChanged(bool bNewGenerateKeyReferenceStringTable); + /** * Called when "LogDebug" option has been changed in the Widget. */ diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditorSettings.h b/Source/EasyLocalizationToolEditor/Public/ELTEditorSettings.h index dcd8da2..e748c96 100644 --- a/Source/EasyLocalizationToolEditor/Public/ELTEditorSettings.h +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditorSettings.h @@ -59,6 +59,9 @@ class EASYLOCALIZATIONTOOLEDITOR_API UELTEditorSettings : public UObject static bool GetReimportAtEditorStartup(); static void SetReimportAtEditorStartup(bool bNewReimportAtEditorStartup); + static bool GetGenerateKeyReferenceStringTable(); + static void SetGenerateKeyReferenceStringTable(bool bNewGenerateKeyReferenceStringTable); + /** * Get/Set if the preview should be displayed on UI. */ @@ -99,7 +102,10 @@ class EASYLOCALIZATIONTOOLEDITOR_API UELTEditorSettings : public UObject UPROPERTY(config) bool bReimportAtEditorStartup = false; - + + UPROPERTY(config) + bool bGenerateKeyReferenceStringTable = false; + UPROPERTY(config) bool bPreviewInUI = true; diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditorWidget.h b/Source/EasyLocalizationToolEditor/Public/ELTEditorWidget.h index 3853c5a..b4060c5 100644 --- a/Source/EasyLocalizationToolEditor/Public/ELTEditorWidget.h +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditorWidget.h @@ -23,6 +23,7 @@ DECLARE_DELEGATE_OneParam(FOnLocalizationPreviewLangChanged, const FString&); DECLARE_DELEGATE_OneParam(FManuallySetLastLanguageChanged, bool); DECLARE_DELEGATE_OneParam(FOnLocalizationOnFirstRunChanged, bool); DECLARE_DELEGATE_OneParam(FOnLocalizationOnFirstRunLangChanged, const FString&); +DECLARE_DELEGATE_OneParam(FOnGenerateKeyReferenceStringTableChanged, bool); DECLARE_DELEGATE_OneParam(FOnGlobalNamespaceChanged, const FString&); DECLARE_DELEGATE_OneParam(FOnSeparatorChanged, const FString&); DECLARE_DELEGATE_OneParam(FOnFallbackWhenEmptyChanged, const FString&); @@ -196,6 +197,20 @@ class EASYLOCALIZATIONTOOLEDITOR_API UELTEditorWidget : public UEditorUtilityWid + /** + * Set "Generate Key Reference String Table On CSV Import" to the Widget. + */ + UFUNCTION(BlueprintImplementableEvent, Category = "Easy Localization Tool Editor") + void SetGenerateKeyReferenceStringTable(bool bGenerateKeyReferenceStringTable); + void CallSetGenerateKeyReferenceStringTable(bool bGenerateKeyReferenceStringTable); + + /** + * "Generate Key Reference String Table On CSV Import" option has been changed on the Widget. + */ + UFUNCTION(BlueprintCallable, Category = "Easy Localization Tool Editor") + void OnGenerateKeyReferenceStringTableChanged(bool bGenerateKeyReferenceStringTable); + + /** * Set "Global Namespace" option to the Widget. */ @@ -287,6 +302,7 @@ class EASYLOCALIZATIONTOOLEDITOR_API UELTEditorWidget : public UEditorUtilityWid FManuallySetLastLanguageChanged OnManuallySetLastLanguageChangedDelegate; FOnLocalizationOnFirstRunChanged OnLocalizationOnFirstRunChangedDelegate; FOnLocalizationOnFirstRunLangChanged OnLocalizationOnFirstRunLangChangedDelegate; + FOnGenerateKeyReferenceStringTableChanged OnGenerateKeyReferenceStringTableChangedDelegate; FOnGlobalNamespaceChanged OnGlobalNamespaceChangedDelegate; FOnSeparatorChanged OnSeparatorChangedDelegate; FOnFallbackWhenEmptyChanged OnFallbackWhenEmptyChangedDelegate; diff --git a/Source/EasyLocalizationToolEditor/Public/SELTEditorWidget.h b/Source/EasyLocalizationToolEditor/Public/SELTEditorWidget.h index 58f6487..cdcf909 100644 --- a/Source/EasyLocalizationToolEditor/Public/SELTEditorWidget.h +++ b/Source/EasyLocalizationToolEditor/Public/SELTEditorWidget.h @@ -33,6 +33,7 @@ class EASYLOCALIZATIONTOOLEDITOR_API SELTEditorWidget : public SUserWidget void SetGlobalNamespace(const FString& GlobalNamespace); void SetSeparator(const FString& Separator); void SetFallbackWhenEmpty(const FString& FallbackWhenEmpty); + void SetGenerateKeyReferenceStringTable(bool bGenerateKeyReferenceStringTable); void SetLogDebug(bool bLogDebug); void SetPreviewInUI(bool bPreviewInUI); @@ -54,6 +55,7 @@ class EASYLOCALIZATIONTOOLEDITOR_API SELTEditorWidget : public SUserWidget bool bIsLocalisationPreviewEnabled_Chkbox = false; bool bManuallySetLastLanguage_Chkbox = false; bool bOverrideLanguageOnStartup_Chkbox = false; + bool bGenerateKeyReferenceStringTable_Chkbox = false; bool bLogDebug_Chkbox = false; bool bPreviewInUI_Chkbox = false; From a9ec6f0c1e5004d18f11b14b02438289c8335531 Mon Sep 17 00:00:00 2001 From: Ryan Lim Date: Sat, 16 May 2026 00:01:40 +0800 Subject: [PATCH 2/9] - Layout formatting pass. --- .../Private/SELTEditorWidget.cpp | 182 +++++++++++------- 1 file changed, 110 insertions(+), 72 deletions(-) diff --git a/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp b/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp index 47cd258..7549005 100644 --- a/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp +++ b/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp @@ -16,7 +16,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) FallbackWhenEmptyAvailable.Add(MakeShareable(new FString(TEXT("KEY")))); SelectedFallbackWhenEmpty = FallbackWhenEmptyAvailable[0]; - SpacerBrush.SetImageSize(FVector2D(350.f, 1.f)); + SpacerBrush.SetImageSize(FVector2D(450.f, 1.f)); SpacerBrush.TintColor = FSlateColor(FLinearColor(.62f,.62f,.62f,1.f)); SUserWidget::Construct(SUserWidget::FArguments() @@ -53,7 +53,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // > Spacer ================ +SVerticalBox::Slot() .AutoHeight() - .Padding(FMargin(0.f, 4.f, 0.f, 4.f)) + .Padding(FMargin(0.f, 15.f, 0.f, 15.f)) .HAlign(EHorizontalAlignment::HAlign_Left) .VAlign(EVerticalAlignment::VAlign_Center) [ @@ -65,8 +65,36 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) [ SNew(SVerticalBox) .ToolTipText(INVTEXT("Name of currently selected Localization. The game can have multiple localization directories.")) + // >>>> Localization Name box + +SVerticalBox::Slot() + .AutoHeight() + [ + SNew(SHorizontalBox) + // >>>>>>>> Localization Name label + +SHorizontalBox::Slot() + .AutoWidth() + .Padding(FMargin(0.f, 5.f, 20.f, 0.f)) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) + .Text(INVTEXT("Localization name:")) + ] + // >>>>>>>> Localization Name value + +SHorizontalBox::Slot() + .AutoWidth() + .Padding(FMargin(0.f, 5.f, 20.f, 0.f)) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Bold", 11)) + .Text_Lambda([this]() -> FText + { + return FText::FromString(CurrentLocName); + }) + ] + ] // >>>> Localization Path selection list +SVerticalBox::Slot() + .Padding(FMargin(0.f, 3.f, 0.f, 0.f)) .AutoHeight() .HAlign(EHorizontalAlignment::HAlign_Left) [ @@ -97,38 +125,11 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) }) ] ] - // >>>> Localization Name box - +SVerticalBox::Slot() - .AutoHeight() - [ - SNew(SHorizontalBox) - // >>>>>>>> Localization Name label - +SHorizontalBox::Slot() - .AutoWidth() - .Padding(FMargin(0.f, 0.f, 20.f, 0.f)) - [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) - .Text(INVTEXT("Localization name:")) - ] - // >>>>>>>> Localization Name value - +SHorizontalBox::Slot() - .AutoWidth() - .Padding(FMargin(0.f, 0.f, 20.f, 0.f)) - [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Bold", 12)) - .Text_Lambda([this]() -> FText - { - return FText::FromString(CurrentLocName); - }) - ] - ] ] // > Spacer ================ +SVerticalBox::Slot() .AutoHeight() - .Padding(FMargin(0.f, 4.f, 0.f, 4.f)) + .Padding(FMargin(0.f, 15.f, 0.f, 15.f)) .HAlign(EHorizontalAlignment::HAlign_Left) .VAlign(EVerticalAlignment::VAlign_Center) [ @@ -145,7 +146,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) .AutoHeight() [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Available Languages In Selected Localization:")) ] // >>>> Available Langs In Selected Localization Value @@ -153,7 +154,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) .AutoHeight() [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Bold", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Bold", 11)) .Text_Lambda([this]() -> FText { return FText::FromString(AvailableLangsInLocFile); @@ -168,10 +169,11 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) .ToolTipText(INVTEXT("List of language codes that are implemented by every localization directory.")) // >>>> Available Langs Label +SVerticalBox::Slot() + .Padding(FMargin(0.f, 10.f, 0.f, 0)) .AutoHeight() [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Available Languages:")) ] // >>>> Localization Names value @@ -179,7 +181,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) .AutoHeight() [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Bold", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Bold", 11)) .Text_Lambda([this]() -> FText { return FText::FromString(AvailableLangs); @@ -189,7 +191,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // > Spacer ================ +SVerticalBox::Slot() .AutoHeight() - .Padding(FMargin(0.f, 4.f, 0.f, 4.f)) + .Padding(FMargin(0.f, 15.f, 0.f, 15.f)) .HAlign(EHorizontalAlignment::HAlign_Left) .VAlign(EVerticalAlignment::VAlign_Center) [ @@ -198,20 +200,24 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // > Reimport on editor startup Box ================ +SVerticalBox::Slot() .AutoHeight() + .MinHeight(24.f) [ SNew(SHorizontalBox) .ToolTipText(INVTEXT("Reimports the lastly selected localization with the last used CSV file when editor starts.")) // >>>> Reimport on editor startup Label +SHorizontalBox::Slot() - .AutoWidth() + .FillContentWidth(1) + .MaxWidth(250.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Reimport on editor startup:")) ] // >>>> Reimport on editor startup checkbox +SHorizontalBox::Slot() .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SCheckBox) .IsChecked_Lambda([this]() -> ECheckBoxState @@ -231,20 +237,24 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // > Localization Preview Box ================ +SVerticalBox::Slot() .AutoHeight() + .MinHeight(24.f) [ SNew(SHorizontalBox) .ToolTipText(INVTEXT("Enabled the preview of the localization in the editor.")) // >>>> Localization Preview Label +SHorizontalBox::Slot() - .AutoWidth() + .FillContentWidth(1) + .MaxWidth(250.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Localization Preview:")) ] // >>>> Localization Preview Checkbox +SHorizontalBox::Slot() .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SCheckBox) .IsChecked_Lambda([this]() -> ECheckBoxState @@ -263,6 +273,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // >>>> Localization Preview List +SHorizontalBox::Slot() .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SComboBox>) .OptionsSource(&PreviewsAvailables) @@ -295,20 +306,24 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // > Manually Set Last Language Box ================ +SVerticalBox::Slot() .AutoHeight() + .MinHeight(24.f) [ SNew(SHorizontalBox) .ToolTipText(INVTEXT("If enabled it won't save and load lastly set language automatically.")) // >>>> Manually Set Last Language Label +SHorizontalBox::Slot() - .AutoWidth() + .FillContentWidth(1) + .MaxWidth(250.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Manually Set Last Language:")) ] // >>>> Manually Set Last Language checkbox +SHorizontalBox::Slot() .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SCheckBox) .IsChecked_Lambda([this]() -> ECheckBoxState @@ -328,20 +343,24 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // > Override Language on Startup Box ================ +SVerticalBox::Slot() .AutoHeight() + .MinHeight(24.f) [ SNew(SHorizontalBox) .ToolTipText(INVTEXT("If enabled, when the game starts for the very first time the selected language will be used.\nNormally, the system language will be used or it will fallback to \"en\".")) // >>>> Override Language on Startup Label +SHorizontalBox::Slot() - .AutoWidth() + .FillContentWidth(1) + .MaxWidth(250.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Override Language on Startup:")) ] // >>>> Override Language on Startup Checkbox +SHorizontalBox::Slot() .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SCheckBox) .IsChecked_Lambda([this]() -> ECheckBoxState @@ -360,6 +379,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // >>>> Override Language on Startup List +SHorizontalBox::Slot() .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SComboBox>) .OptionsSource(&LanguageOverridesAvailable) @@ -392,25 +412,28 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // > Separator Box ================ +SVerticalBox::Slot() .AutoHeight() + .MinHeight(24.f) [ - SNew(SVerticalBox) + SNew(SHorizontalBox) .ToolTipText(INVTEXT("A CSV column separator. It's \",\" by default, but it can be any other single character.")) // >>>> Separator Label - +SVerticalBox::Slot() - .AutoHeight() + +SHorizontalBox::Slot() + .FillContentWidth(1) + .MaxWidth(250.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Separator:")) ] // >>>> Separator Value - +SVerticalBox::Slot() - .AutoHeight() - .HAlign(EHorizontalAlignment::HAlign_Left) + +SHorizontalBox::Slot() + .FillContentWidth(1) + .MaxWidth(200.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SEditableTextBox) - .Font(FCoreStyle::GetDefaultFontStyle("Regular", 12)) - .MinDesiredWidth(256.f) + .Font(FCoreStyle::GetDefaultFontStyle("Regular", 11)) .Text_Lambda([this]() -> FText { return FText::FromString(SeparatorValue); @@ -428,7 +451,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // > Fallback when empty Box ================ +SVerticalBox::Slot() .AutoHeight() - .Padding(FMargin(0.f, 4.f, 0.f, 0.f)) + .MinHeight(24.f) [ SNew(SHorizontalBox) .ToolTipText(INVTEXT("\ @@ -438,15 +461,18 @@ FIRST_LANG - use value of the first language.If that value is empty use Key\n\ KEY - use the key of this entry")) // >>>> Fallback when empty Label +SHorizontalBox::Slot() - .AutoWidth() + .FillContentWidth(1) + .MaxWidth(250.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Fallback when empty:")) ] // >>>> Fallback when empty List +SHorizontalBox::Slot() .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SComboBox>) .OptionsSource(&FallbackWhenEmptyAvailable) @@ -516,7 +542,7 @@ The String Table will be generated in the Localization Folder path and IS OVERRI // > Spacer ================ +SVerticalBox::Slot() .AutoHeight() - .Padding(FMargin(0.f, 4.f, 0.f, 4.f)) + .Padding(FMargin(0.f, 15.f, 0.f, 15.f)) .HAlign(EHorizontalAlignment::HAlign_Left) .VAlign(EVerticalAlignment::VAlign_Center) [ @@ -527,7 +553,7 @@ The String Table will be generated in the Localization Folder path and IS OVERRI .AutoHeight() [ SNew(SVerticalBox) - .ToolTipText(INVTEXT("CSV files to import. You can import mutliple files at once to the same Localization.")) + .ToolTipText(INVTEXT("CSV files to import. You can import multiple files at once to the same Localization.")) // >>>> CSV files list box +SVerticalBox::Slot() .AutoHeight() @@ -538,7 +564,7 @@ The String Table will be generated in the Localization Folder path and IS OVERRI .AutoHeight() [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("CSV file:")) ] // >>>>>>> CSV files list value @@ -546,7 +572,7 @@ The String Table will be generated in the Localization Folder path and IS OVERRI .AutoHeight() [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Bold", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Bold", 11)) .Text_Lambda([this]() -> FText { return FText::FromString(CSVFiles); @@ -556,6 +582,7 @@ The String Table will be generated in the Localization Folder path and IS OVERRI +SVerticalBox::Slot() // >>>> CSV select files box .AutoHeight() + .Padding(FMargin(0.f, 5.f, 0.f, 0.f)) [ SNew(SHorizontalBox) // >>>>>>> CSV select files button @@ -593,24 +620,29 @@ The String Table will be generated in the Localization Folder path and IS OVERRI // > Global namespace box ================ +SVerticalBox::Slot() .AutoHeight() + .MinHeight(24.f) + .Padding(FMargin(0.f, 15.f, 0.f, 0.f)) [ - SNew(SVerticalBox) + SNew(SHorizontalBox) .ToolTipText(INVTEXT("This namespace will be assigned to every key in localization.")) // >>>> Global namespace label ================ - +SVerticalBox::Slot() - .AutoHeight() + +SHorizontalBox::Slot() + .FillContentWidth(1) + .MaxWidth(250.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Global namespace:")) ] // >>>> Global namespace value ================ - +SVerticalBox::Slot() - .AutoHeight() - .HAlign(EHorizontalAlignment::HAlign_Left) + +SHorizontalBox::Slot() + .FillContentWidth(1) + .MaxWidth(200.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SEditableTextBox) - .Font(FCoreStyle::GetDefaultFontStyle("Regular", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Regular", 11)) .MinDesiredWidth(256.f) .Text_Lambda([this]() -> FText { @@ -629,7 +661,7 @@ The String Table will be generated in the Localization Folder path and IS OVERRI // > Spacer ================ +SVerticalBox::Slot() .AutoHeight() - .Padding(FMargin(0.f, 4.f, 0.f, 4.f)) + .Padding(FMargin(0.f, 15.f, 0.f, 15.f)) .HAlign(EHorizontalAlignment::HAlign_Left) .VAlign(EVerticalAlignment::VAlign_Center) [ @@ -638,20 +670,23 @@ The String Table will be generated in the Localization Folder path and IS OVERRI // > Log Debug Box ================ +SVerticalBox::Slot() .AutoHeight() + .MinHeight(24.f) [ SNew(SHorizontalBox) .ToolTipText(INVTEXT("Select this option to see additional informations in Output Log.\nBe aware that big CSVs might generate a lot of logs.")) // >>>> Log Debug Label +SHorizontalBox::Slot() - .AutoWidth() + .MaxWidth(250.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Log Debug:")) ] // >>>> Log Debug checkbox +SHorizontalBox::Slot() .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SCheckBox) .IsChecked_Lambda([this]() -> ECheckBoxState @@ -671,6 +706,7 @@ The String Table will be generated in the Localization Folder path and IS OVERRI // > Preview In UI Box ================ +SVerticalBox::Slot() .AutoHeight() + .MinHeight(24.f) [ SNew(SHorizontalBox) .ToolTipText(INVTEXT("Select this option to show a localization preview under the Text fields in the Editor UI.")) @@ -687,15 +723,17 @@ The String Table will be generated in the Localization Folder path and IS OVERRI }) // >>>> Preview In UI Label +SHorizontalBox::Slot() - .AutoWidth() + .MaxWidth(250.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Show preview in UI:")) ] // >>>> Preview In UI checkbox +SHorizontalBox::Slot() .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SCheckBox) .IsChecked_Lambda([this]() -> ECheckBoxState From 6e6aa48be0af3b3c03e8c693a3343a584ef54a3b Mon Sep 17 00:00:00 2001 From: Ryan Lim Date: Sat, 16 May 2026 03:15:02 +0800 Subject: [PATCH 3/9] - Updated formatting for Key Reference String Table implementation. --- .../Private/SELTEditorWidget.cpp | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp b/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp index 7549005..59df77c 100644 --- a/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp +++ b/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp @@ -16,7 +16,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) FallbackWhenEmptyAvailable.Add(MakeShareable(new FString(TEXT("KEY")))); SelectedFallbackWhenEmpty = FallbackWhenEmptyAvailable[0]; - SpacerBrush.SetImageSize(FVector2D(450.f, 1.f)); + SpacerBrush.SetImageSize(FVector2D(600.f, 1.f)); SpacerBrush.TintColor = FSlateColor(FLinearColor(.62f,.62f,.62f,1.f)); SUserWidget::Construct(SUserWidget::FArguments() @@ -207,7 +207,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // >>>> Reimport on editor startup Label +SHorizontalBox::Slot() .FillContentWidth(1) - .MaxWidth(250.0f) + .MaxWidth(400.0f) .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) @@ -244,7 +244,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // >>>> Localization Preview Label +SHorizontalBox::Slot() .FillContentWidth(1) - .MaxWidth(250.0f) + .MaxWidth(400.0f) .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) @@ -313,7 +313,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // >>>> Manually Set Last Language Label +SHorizontalBox::Slot() .FillContentWidth(1) - .MaxWidth(250.0f) + .MaxWidth(400.0f) .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) @@ -350,7 +350,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // >>>> Override Language on Startup Label +SHorizontalBox::Slot() .FillContentWidth(1) - .MaxWidth(250.0f) + .MaxWidth(400.0f) .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) @@ -419,7 +419,7 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // >>>> Separator Label +SHorizontalBox::Slot() .FillContentWidth(1) - .MaxWidth(250.0f) + .MaxWidth(400.0f) .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) @@ -462,7 +462,7 @@ KEY - use the key of this entry")) // >>>> Fallback when empty Label +SHorizontalBox::Slot() .FillContentWidth(1) - .MaxWidth(250.0f) + .MaxWidth(400.0f) .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) @@ -505,7 +505,7 @@ KEY - use the key of this entry")) // > Generate Key Reference String Table on Import Box ================ +SVerticalBox::Slot() .AutoHeight() - .Padding(FMargin(0.f, 4.f, 0.f, 0.f)) + .MinHeight(24.f) [ SNew(SHorizontalBox) .ToolTipText(INVTEXT("\ @@ -514,15 +514,18 @@ These String Table can be used to easily assign keys to FText properties.\n\n\ The String Table will be generated in the Localization Folder path and IS OVERRIDDEN if it already exists.")) // >>>> Generate Key Reference String Table CSV Import Label +SHorizontalBox::Slot() - .AutoWidth() + .FillContentWidth(1) + .MaxWidth(400.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 12)) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) .Text(INVTEXT("Generate Key Reference String Table on Import:")) ] // >>>> Generate Key Reference String Table on Import checkbox +SHorizontalBox::Slot() .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(SCheckBox) .IsChecked_Lambda([this]() -> ECheckBoxState @@ -628,7 +631,7 @@ The String Table will be generated in the Localization Folder path and IS OVERRI // >>>> Global namespace label ================ +SHorizontalBox::Slot() .FillContentWidth(1) - .MaxWidth(250.0f) + .MaxWidth(400.0f) .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) @@ -676,7 +679,7 @@ The String Table will be generated in the Localization Folder path and IS OVERRI .ToolTipText(INVTEXT("Select this option to see additional informations in Output Log.\nBe aware that big CSVs might generate a lot of logs.")) // >>>> Log Debug Label +SHorizontalBox::Slot() - .MaxWidth(250.0f) + .MaxWidth(400.0f) .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) @@ -723,7 +726,7 @@ The String Table will be generated in the Localization Folder path and IS OVERRI }) // >>>> Preview In UI Label +SHorizontalBox::Slot() - .MaxWidth(250.0f) + .MaxWidth(400.0f) .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) From d97bdbc3627009fbf105b8dda8bf55da34426b39 Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Sun, 17 May 2026 11:55:30 +0200 Subject: [PATCH 4/9] Improvements to the gen string tables --- Content/ELTEditorWidget_BP.uasset | Bin 534575 -> 391691 bytes .../Private/ELTCommandlet.cpp | 4 +- .../Private/ELTEditor.cpp | 141 ++++++++++++------ .../Private/ELTEditorWidget.cpp | 4 - .../Public/ELTEditor.h | 4 +- .../Public/ELTEditorWidget.h | 2 - 6 files changed, 99 insertions(+), 56 deletions(-) diff --git a/Content/ELTEditorWidget_BP.uasset b/Content/ELTEditorWidget_BP.uasset index 7beb0a8b8d1ebbb3c405ba4fc93a3fde86206890..938762f151f94885f26b5a8f3a9890ddaca42ca1 100644 GIT binary patch literal 391691 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 ZL3{_!v5}Dou_L6>e5{c>IHt|Q{{vJDtLp#& literal 534575 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

u_Q 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 diff --git a/Source/EasyLocalizationToolEditor/Private/ELTCommandlet.cpp b/Source/EasyLocalizationToolEditor/Private/ELTCommandlet.cpp index 5a93910..6ab23e6 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTCommandlet.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTCommandlet.cpp @@ -37,11 +37,13 @@ int32 UELTCommandlet::Main(const FString& Params) FString Fallback = TEXT("NONE"); FParse::Value(*Params, TEXT("-Fallback="), Fallback); + bool bGenerateStringTables = FParse::Param(*Params, TEXT("-GenStringTables")); + const FString LocName = FPaths::GetBaseFilename(LocPath); // Run generation of loc files implementation. Get the output message and display it the localization fails. FString OutMessage; - if (UELTEditor::GenerateLocFilesImpl(CSVPath, LocPath, LocName, Namespace, Separator, Fallback, OutMessage) == false) + if (UELTEditor::GenerateLocFilesImpl(CSVPath, LocPath, LocName, Namespace, Separator, Fallback, bGenerateStringTables, OutMessage) == false) { UE_LOG(ELTCommandletLog, Log, TEXT("+++ Failed to generate Localization: %s"), *OutMessage); return 1; diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp index 785774c..205c288 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp @@ -478,12 +478,12 @@ bool UELTEditor::GenerateLocFiles(FString& OutMessage) } const TArray& CSVFilePaths = PathsStringToList(GetCurrentCSVPath()); const FString LocPath = FPaths::ConvertRelativePathToFull(CurrentLocPath); - return GenerateLocFilesImpl(CSVFilePaths, LocPath, GetCurrentLocName(), GetCurrentGlobalNamespace(), UELTEditorSettings::GetSeparator(), UELTEditorSettings::GetFallbackWhenEmpty(), OutMessage); + return GenerateLocFilesImpl(CSVFilePaths, LocPath, GetCurrentLocName(), GetCurrentGlobalNamespace(), UELTEditorSettings::GetSeparator(), UELTEditorSettings::GetFallbackWhenEmpty(), UELTEditorSettings::GetGenerateKeyReferenceStringTable(), OutMessage); } -bool UELTEditor::GenerateLocFilesImpl(const FString& CSVPaths, const FString& LocPath, const FString& LocName, const FString& GlobalNamespace, const FString& Separator, const FString& FallbackWhenEmpty, FString& OutMessage) +bool UELTEditor::GenerateLocFilesImpl(const FString& CSVPaths, const FString& LocPath, const FString& LocName, const FString& GlobalNamespace, const FString& Separator, const FString& FallbackWhenEmpty, bool bGenerateStringTables, FString& OutMessage) { - return GenerateLocFilesImpl(PathsStringToList(CSVPaths), LocPath, LocName, GlobalNamespace, Separator, FallbackWhenEmpty, OutMessage); + return GenerateLocFilesImpl(PathsStringToList(CSVPaths), LocPath, LocName, GlobalNamespace, Separator, FallbackWhenEmpty, bGenerateStringTables, OutMessage); } // Define the type of behavior when the localized string in CSV is empty and the fallback value should be used. @@ -494,7 +494,7 @@ enum class EFallbackWhenEmptyType : uint8 KEY }; -bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FString& LocPath, const FString& LocName, const FString& GlobalNamespace, const FString& Separator, const FString& FallbackWhenEmpty, FString& OutMessage) +bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FString& LocPath, const FString& LocName, const FString& GlobalNamespace, const FString& Separator, const FString& FallbackWhenEmpty, bool bGenerateStringTables, FString& OutMessage) { if (Separator.Len() != 1) { @@ -515,11 +515,13 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt const FString MetaFileName = LocPath / LocName + TEXT(".locmeta"); const bool bLogDebug = UELTEditorSettings::GetLogDebug(); - const bool bGenerateStringTable = UELTEditorSettings::GetGenerateKeyReferenceStringTable(); bool bFirstCSV = true; TMap LocReses; TMap> NamespaceToKeysMap; +#if ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 8)) + TMap> NamespaceToKeysToNotesMap; +#endif for (const FString& CSVPath : CSVPaths) { @@ -531,28 +533,46 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt FCSVReader Reader; if (Reader.LoadFromFile(CSVFilePath, (*Separator)[0], OutMessage)) { - int32 FirstColumn = 0; - bool bHasNamespaces = false; + int32 CurrentColumn = 0; + int32 FirstLangColumn = 0; + + int32 NamespaceColumn = INDEX_NONE; + int32 DevNotesColumn = INDEX_NONE; const TArray Columns = Reader.Columns; for (const FCSVColumn& Column : Columns) { if (Column.Values[0].Equals(TEXT("namespace"), ESearchCase::IgnoreCase)) { - bHasNamespaces=true; - break; + NamespaceColumn = CurrentColumn; + ++CurrentColumn; + ++FirstLangColumn; + continue; + } + if (Column.Values[0].Equals(TEXT("devnotes"), ESearchCase::IgnoreCase)) + { + DevNotesColumn = CurrentColumn; + ++CurrentColumn; + ++FirstLangColumn; + continue; } if (Column.Values[0].Equals(TEXT("key"), ESearchCase::IgnoreCase)) { + ++FirstLangColumn; break; } - ++FirstColumn; + if ((NamespaceColumn != INDEX_NONE) || (DevNotesColumn != INDEX_NONE)) + { + OutMessage = TEXT("ERROR: Invalid CSV! The 'namespace' and 'devnotes' columns must be before the 'key' column!"); + return false; + } + ++CurrentColumn; } - if (Columns.Num() > (FirstColumn + 1)) + if (Columns.Num() > (CurrentColumn + 1)) { - const int32 NumOfValues = Columns[FirstColumn].Values.Num(); - for (int32 CIdx = FirstColumn + 1; CIdx < Columns.Num(); CIdx++) + const int32 NumOfValues = Columns[CurrentColumn].Values.Num(); + for (int32 CIdx = CurrentColumn + 1; CIdx < Columns.Num(); CIdx++) { if (Columns[CIdx].Values.Num() != NumOfValues) { @@ -562,17 +582,20 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt } // Potential place for namespaces. - const FCSVColumn& Namespaces = Columns[FirstColumn]; + const FCSVColumn& Namespaces = (NamespaceColumn != INDEX_NONE) ? Columns[NamespaceColumn] : Columns[0]; // Check if we have namespaces defined for every key or to use global value. - const bool bUseGlobalNamespace = (bHasNamespaces == false) && (GlobalNamespace.IsEmpty() == false); + const bool bUseGlobalNamespace = (NamespaceColumn == INDEX_NONE) && (GlobalNamespace.IsEmpty() == false); - if (bUseGlobalNamespace == false && bHasNamespaces == false) + if (bUseGlobalNamespace == false && (NamespaceColumn == INDEX_NONE)) { OutMessage = TEXT("ERROR: Namespaces in CSV not found!"); return false; } + // Potential place for devnotes. + const FCSVColumn& DevNotes = (DevNotesColumn != INDEX_NONE) ? Columns[DevNotesColumn] : Columns[0]; + // Clear the localization directory first. if (bFirstCSV) { @@ -583,21 +606,48 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt } } - // Keys will be in first row if not having namespaces. - const FCSVColumn& Keys = Columns[bHasNamespaces ? FirstColumn+1 : FirstColumn]; + // Get the keys column and check if it is valid. + const FCSVColumn& Keys = Columns[FirstLangColumn]; if (Keys.Values[0].Equals(TEXT("key"), ESearchCase::IgnoreCase) == false) { OutMessage = TEXT("ERROR: Key column in CSV not found!"); return false; } +#if ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 8)) + // Gather Dev Notes if available + if (DevNotesColumn != INDEX_NONE) + { + if (DevNotes.Values[0].Equals(TEXT("devnotes"), ESearchCase::IgnoreCase) == false) + { + OutMessage = TEXT("ERROR: Dev Notes column in CSV not found!"); + return false; + } + + for (int32 Key = 1; Key < Keys.Values.Num(); Key++) + { + FString DevNote = DevNotes.Values[Key]; + if (DevNote.IsEmpty() == false) + { + const FString& Namespace = (bUseGlobalNamespace || Namespaces.Values[Key].IsEmpty()) ? GlobalNamespace : Namespaces.Values[Key]; + if (Namespace.IsEmpty()) + { + OutMessage = FString::Printf(TEXT("ERROR: Namespace in row %i (counting from 1) for dev note is empty!"), Key); + return false; + } + TMap& DevNotesList = NamespaceToKeysToNotesMap.FindOrAdd(Namespace); + DevNotesList.Add(Keys.Values[Key], DevNote); + } + } + } +#endif + if (bLogDebug) { UE_LOG(ELTEditorLog, Log, TEXT("Adding Entries")); UE_LOG(ELTEditorLog, Log, TEXT("[Lang] | [Namespace] | [Key] | [Value]")); } - const int32 FirstLangColumn = bHasNamespaces ? (FirstColumn + 2) : (FirstColumn + 1); for (int32 Column = FirstLangColumn; Column < Columns.Num(); Column++) { const FCSVColumn& Locs = Columns[Column]; @@ -654,7 +704,7 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt LocalizedString, 0); - if (bGenerateStringTable && !Keys.Values[Key].IsEmpty()) + if (bGenerateStringTables && (Keys.Values[Key].IsEmpty() == false)) { NamespaceToKeysMap.FindOrAdd(Namespace).Add(Keys.Values[Key]); } @@ -697,7 +747,7 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt } // Generate Key Reference String Table - if (bGenerateStringTable && NamespaceToKeysMap.Num() > 0) + if (bGenerateStringTables && NamespaceToKeysMap.Num() > 0) { FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked("AssetTools"); @@ -707,55 +757,52 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt const TSet& Keys = KVP.Value; FString AssetName = FString::Printf(TEXT("ELT_KeyReferences_%s_%s"), *LocName, *Namespace); - FString VirtualPath = LocPath.StartsWith(TEXT("/Game")) ? LocPath : FPackageName::FilenameToLongPackageName(LocPath); - FString PackagePath = FPaths::Combine(VirtualPath, AssetName); - FPaths::NormalizeFilename(PackagePath); + FString PackagePath = FPackageName::FilenameToLongPackageName(LocPath / AssetName); - if (!PackagePath.StartsWith(TEXT("/"))) - { - PackagePath = TEXT("/") + PackagePath; - } - - UPackage* Package = CreatePackage(*PackagePath); - if (!Package) + UPackage* Package = FPackageName::DoesPackageExist(*PackagePath) ? LoadPackage(nullptr, *PackagePath, LOAD_None) : CreatePackage(*PackagePath); + if (Package == nullptr) { OutMessage = FString::Printf(TEXT("ERROR: Failed to create package path for StringTable: %s"), *PackagePath); return false; } - UStringTable* StringTableAsset = Cast(StaticFindObject(UStringTable::StaticClass(), Package, *AssetName)); - if (!StringTableAsset) - { - StringTableAsset = Cast(AssetToolsModule.Get().CreateAsset( - AssetName, - VirtualPath, - UStringTable::StaticClass(), - nullptr - )); - } - - if (!StringTableAsset) + UStringTable* StringTableAsset = NewObject(Package, UStringTable::StaticClass(), FName(*AssetName), (RF_Public | RF_Standalone | RF_Transactional)); + if (StringTableAsset == nullptr) { OutMessage = FString::Printf(TEXT("ERROR: Failed to create StringTable asset: %s"), *AssetName); return false; } + FAssetRegistryModule::AssetCreated(StringTableAsset); + Package->MarkPackageDirty(); + FStringTableRef StringTableRef = StringTableAsset->GetMutableStringTable(); StringTableRef->SetNamespace(Namespace); +#if ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 8)) + TMap* KeysToNotes = NamespaceToKeysToNotesMap.Find(Namespace); + for (const FString& Key : Keys) + { + FString DevNotes = TEXT(""); + if (FString* Note = KeysToNotes ? KeysToNotes->Find(Key) : nullptr) + { + DevNotes = *Note; + } + + StringTableRef->SetSourceString(FTextKey(Key), Key, DevNotes); + } +#else for (const FString& Key : Keys) { StringTableRef->SetSourceString(FTextKey(Key), Key); } - - Package->MarkPackageDirty(); +#endif FString PackageFileName = FPackageName::LongPackageNameToFilename(PackagePath, FPackageName::GetAssetPackageExtension()); FSavePackageArgs SaveArgs; SaveArgs.TopLevelFlags = RF_Public | RF_Standalone; SaveArgs.Error = GError; - - if (!UPackage::SavePackage(Package, StringTableAsset, *PackageFileName, SaveArgs)) + if (UPackage::SavePackage(Package, StringTableAsset, *PackageFileName, SaveArgs) == false) { OutMessage = FString::Printf(TEXT("ERROR: Failed to save StringTable package file to disk path: %s"), *PackageFileName); return false; diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditorWidget.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditorWidget.cpp index dbe5394..af514c3 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTEditorWidget.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditorWidget.cpp @@ -155,14 +155,10 @@ void UELTEditorWidget::CallSetLocalizationOnFirstRun(bool LocalizationOnFirstRun void UELTEditorWidget::CallSetGenerateKeyReferenceStringTable(bool bGenerateKeyReferenceStringTable) { -#if ELTEDITOR_USE_SLATE_EDITOR_UI if (MyWidget.IsValid()) { MyWidget->SetGenerateKeyReferenceStringTable(bGenerateKeyReferenceStringTable); } -#else - SetReimportAtEditorStartup(bReimportAtEditorStartup); -#endif } void UELTEditorWidget::CallSetLocalizationOnFirstRunLang(const FString& OnFirstRunLang) diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditor.h b/Source/EasyLocalizationToolEditor/Public/ELTEditor.h index 25fac18..c8efd8c 100644 --- a/Source/EasyLocalizationToolEditor/Public/ELTEditor.h +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditor.h @@ -49,8 +49,8 @@ class EASYLOCALIZATIONTOOLEDITOR_API UELTEditor : public UObject * Implementation of generating Unreal localization files. It is statically exposed, * so other elements like Commandlet can run it. */ - static bool GenerateLocFilesImpl(const FString& CSVPaths, const FString& LocPath, const FString& LocName, const FString& GlobalNamespace, const FString& Separator, const FString& FallbackWhenEmpty, FString& OutMessage); - static bool GenerateLocFilesImpl(const TArray& CSVPaths, const FString& LocPath, const FString& LocName, const FString& GlobalNamespace, const FString& Separator, const FString& FallbackWhenEmpty, FString& OutMessage); + static bool GenerateLocFilesImpl(const FString& CSVPaths, const FString& LocPath, const FString& LocName, const FString& GlobalNamespace, const FString& Separator, const FString& FallbackWhenEmpty, bool bGenerateStringTables, FString& OutMessage); + static bool GenerateLocFilesImpl(const TArray& CSVPaths, const FString& LocPath, const FString& LocName, const FString& GlobalNamespace, const FString& Separator, const FString& FallbackWhenEmpty, bool bGenerateStringTables, FString& OutMessage); private: diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditorWidget.h b/Source/EasyLocalizationToolEditor/Public/ELTEditorWidget.h index b4060c5..dc5b79e 100644 --- a/Source/EasyLocalizationToolEditor/Public/ELTEditorWidget.h +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditorWidget.h @@ -200,8 +200,6 @@ class EASYLOCALIZATIONTOOLEDITOR_API UELTEditorWidget : public UEditorUtilityWid /** * Set "Generate Key Reference String Table On CSV Import" to the Widget. */ - UFUNCTION(BlueprintImplementableEvent, Category = "Easy Localization Tool Editor") - void SetGenerateKeyReferenceStringTable(bool bGenerateKeyReferenceStringTable); void CallSetGenerateKeyReferenceStringTable(bool bGenerateKeyReferenceStringTable); /** From 6bd9957eca529b548b4378a861071b87cd6a5238 Mon Sep 17 00:00:00 2001 From: Ryan Lim Date: Sun, 17 May 2026 20:45:35 +0800 Subject: [PATCH 5/9] - Fixed Build Compilation errors in SELTEditorWidget.cpp to support older versions of UE. - Replaced FillContentWidth() with .FillWidth(1.0f), as the former is not supported in older versions. - Nested various content in SBox as SVerticalBox and SHorizontalBox does not support .MinHeight() in older versions. --- .../Private/SELTEditorWidget.cpp | 774 +++++++++--------- 1 file changed, 402 insertions(+), 372 deletions(-) diff --git a/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp b/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp index 59df77c..d443a69 100644 --- a/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp +++ b/Source/EasyLocalizationToolEditor/Private/SELTEditorWidget.cpp @@ -200,346 +200,367 @@ void SELTEditorWidget::Construct(const FArguments& InArgs) // > Reimport on editor startup Box ================ +SVerticalBox::Slot() .AutoHeight() - .MinHeight(24.f) [ - SNew(SHorizontalBox) - .ToolTipText(INVTEXT("Reimports the lastly selected localization with the last used CSV file when editor starts.")) - // >>>> Reimport on editor startup Label - +SHorizontalBox::Slot() - .FillContentWidth(1) - .MaxWidth(400.0f) - .VAlign(EVerticalAlignment::VAlign_Center) + SNew(SBox) + .MinDesiredHeight(24.f) [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) - .Text(INVTEXT("Reimport on editor startup:")) - ] - // >>>> Reimport on editor startup checkbox - +SHorizontalBox::Slot() - .AutoWidth() - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(SCheckBox) - .IsChecked_Lambda([this]() -> ECheckBoxState - { - return bReimportAtEditorStartup_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; - }) - .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void - { - bReimportAtEditorStartup_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); - if (WidgetController.IsValid()) + SNew(SHorizontalBox) + .ToolTipText(INVTEXT("Reimports the lastly selected localization with the last used CSV file when editor starts.")) + // >>>> Reimport on editor startup Label + +SHorizontalBox::Slot() + .FillWidth(1.0f) + .MaxWidth(400.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) + .Text(INVTEXT("Reimport on editor startup:")) + ] + // >>>> Reimport on editor startup checkbox + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(SCheckBox) + .IsChecked_Lambda([this]() -> ECheckBoxState { - WidgetController->OnReimportAtEditorStartupChanged(bReimportAtEditorStartup_Chkbox); - } - }) + return bReimportAtEditorStartup_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void + { + bReimportAtEditorStartup_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); + if (WidgetController.IsValid()) + { + WidgetController->OnReimportAtEditorStartupChanged(bReimportAtEditorStartup_Chkbox); + } + }) + ] ] ] // > Localization Preview Box ================ +SVerticalBox::Slot() .AutoHeight() - .MinHeight(24.f) [ - SNew(SHorizontalBox) - .ToolTipText(INVTEXT("Enabled the preview of the localization in the editor.")) - // >>>> Localization Preview Label - +SHorizontalBox::Slot() - .FillContentWidth(1) - .MaxWidth(400.0f) - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) - .Text(INVTEXT("Localization Preview:")) - ] - // >>>> Localization Preview Checkbox - +SHorizontalBox::Slot() - .AutoWidth() - .VAlign(EVerticalAlignment::VAlign_Center) + SNew(SBox) + .MinDesiredHeight(24.f) [ - SNew(SCheckBox) - .IsChecked_Lambda([this]() -> ECheckBoxState - { - return bIsLocalisationPreviewEnabled_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; - }) - .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void - { - bIsLocalisationPreviewEnabled_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); - if (WidgetController.IsValid()) + SNew(SHorizontalBox) + .ToolTipText(INVTEXT("Enabled the preview of the localization in the editor.")) + // >>>> Localization Preview Label + +SHorizontalBox::Slot() + .FillWidth(1.0f) + .MaxWidth(400.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) + .Text(INVTEXT("Localization Preview:")) + ] + // >>>> Localization Preview Checkbox + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(SCheckBox) + .IsChecked_Lambda([this]() -> ECheckBoxState { - WidgetController->OnLocalizationPreviewChanged(bIsLocalisationPreviewEnabled_Chkbox); - } - }) - ] - // >>>> Localization Preview List - +SHorizontalBox::Slot() - .AutoWidth() - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(SComboBox>) - .OptionsSource(&PreviewsAvailables) - .OnGenerateWidget_Lambda([this](TSharedPtr InItem) -> TSharedRef - { - return SNew(STextBlock).Text(FText::FromString(*InItem)); - }) - .OnSelectionChanged_Lambda([this](TSharedPtr Item, ESelectInfo::Type SelectInfo) -> void - { - SelectedPreviewLang = Item; - if (WidgetController.IsValid()) + return bIsLocalisationPreviewEnabled_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void { - WidgetController->OnLocalizationPreviewLangChanged(*Item); - } - }) + bIsLocalisationPreviewEnabled_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); + if (WidgetController.IsValid()) + { + WidgetController->OnLocalizationPreviewChanged(bIsLocalisationPreviewEnabled_Chkbox); + } + }) + ] + // >>>> Localization Preview List + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Regular", 10)) - .Text_Lambda([this]() -> FText + SNew(SComboBox>) + .OptionsSource(&PreviewsAvailables) + .OnGenerateWidget_Lambda([this](TSharedPtr InItem) -> TSharedRef + { + return SNew(STextBlock).Text(FText::FromString(*InItem)); + }) + .OnSelectionChanged_Lambda([this](TSharedPtr Item, ESelectInfo::Type SelectInfo) -> void + { + SelectedPreviewLang = Item; + if (WidgetController.IsValid()) { - if (SelectedPreviewLang.IsValid()) + WidgetController->OnLocalizationPreviewLangChanged(*Item); + } + }) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Regular", 10)) + .Text_Lambda([this]() -> FText { - return FText::FromString(*SelectedPreviewLang); - } - return FText::GetEmpty(); - }) + if (SelectedPreviewLang.IsValid()) + { + return FText::FromString(*SelectedPreviewLang); + } + return FText::GetEmpty(); + }) + ] ] ] ] // > Manually Set Last Language Box ================ +SVerticalBox::Slot() .AutoHeight() - .MinHeight(24.f) [ - SNew(SHorizontalBox) - .ToolTipText(INVTEXT("If enabled it won't save and load lastly set language automatically.")) - // >>>> Manually Set Last Language Label - +SHorizontalBox::Slot() - .FillContentWidth(1) - .MaxWidth(400.0f) - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) - .Text(INVTEXT("Manually Set Last Language:")) - ] - // >>>> Manually Set Last Language checkbox - +SHorizontalBox::Slot() - .AutoWidth() - .VAlign(EVerticalAlignment::VAlign_Center) + SNew(SBox) + .MinDesiredHeight(24.f) [ - SNew(SCheckBox) - .IsChecked_Lambda([this]() -> ECheckBoxState - { - return bManuallySetLastLanguage_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; - }) - .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void - { - bManuallySetLastLanguage_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); - if (WidgetController.IsValid()) + SNew(SHorizontalBox) + .ToolTipText(INVTEXT("If enabled it won't save and load lastly set language automatically.")) + // >>>> Manually Set Last Language Label + +SHorizontalBox::Slot() + .FillWidth(1.0f) + .MaxWidth(400.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) + .Text(INVTEXT("Manually Set Last Language:")) + ] + // >>>> Manually Set Last Language checkbox + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(SCheckBox) + .IsChecked_Lambda([this]() -> ECheckBoxState { - WidgetController->OnManuallySetLastUsedLanguageChanged(bManuallySetLastLanguage_Chkbox); - } - }) + return bManuallySetLastLanguage_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void + { + bManuallySetLastLanguage_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); + if (WidgetController.IsValid()) + { + WidgetController->OnManuallySetLastUsedLanguageChanged(bManuallySetLastLanguage_Chkbox); + } + }) + ] ] ] // > Override Language on Startup Box ================ +SVerticalBox::Slot() .AutoHeight() - .MinHeight(24.f) [ - SNew(SHorizontalBox) - .ToolTipText(INVTEXT("If enabled, when the game starts for the very first time the selected language will be used.\nNormally, the system language will be used or it will fallback to \"en\".")) - // >>>> Override Language on Startup Label - +SHorizontalBox::Slot() - .FillContentWidth(1) - .MaxWidth(400.0f) - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) - .Text(INVTEXT("Override Language on Startup:")) - ] - // >>>> Override Language on Startup Checkbox - +SHorizontalBox::Slot() - .AutoWidth() - .VAlign(EVerticalAlignment::VAlign_Center) + SNew(SBox) + .MinDesiredHeight(24.f) [ - SNew(SCheckBox) - .IsChecked_Lambda([this]() -> ECheckBoxState - { - return bOverrideLanguageOnStartup_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; - }) - .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void - { - bOverrideLanguageOnStartup_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); - if (WidgetController.IsValid()) + SNew(SHorizontalBox) + .ToolTipText(INVTEXT("If enabled, when the game starts for the very first time the selected language will be used.\nNormally, the system language will be used or it will fallback to \"en\".")) + // >>>> Override Language on Startup Label + +SHorizontalBox::Slot() + .FillWidth(1.0f) + .MaxWidth(400.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) + .Text(INVTEXT("Override Language on Startup:")) + ] + // >>>> Override Language on Startup Checkbox + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(SCheckBox) + .IsChecked_Lambda([this]() -> ECheckBoxState { - WidgetController->OnLocalizationOnFirstRun(bOverrideLanguageOnStartup_Chkbox); - } - }) - ] - // >>>> Override Language on Startup List - +SHorizontalBox::Slot() - .AutoWidth() - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(SComboBox>) - .OptionsSource(&LanguageOverridesAvailable) - .OnGenerateWidget_Lambda([this](TSharedPtr InItem) -> TSharedRef - { - return SNew(STextBlock).Text(FText::FromString(*InItem)); - }) - .OnSelectionChanged_Lambda([this](TSharedPtr Item, ESelectInfo::Type SelectInfo) -> void - { - SelectedLanguageOverride = Item; - if (WidgetController.IsValid()) + return bOverrideLanguageOnStartup_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void { - WidgetController->OnLocalizationOnFirstRunLangChanged(*Item); - } - }) + bOverrideLanguageOnStartup_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); + if (WidgetController.IsValid()) + { + WidgetController->OnLocalizationOnFirstRun(bOverrideLanguageOnStartup_Chkbox); + } + }) + ] + // >>>> Override Language on Startup List + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Regular", 10)) - .Text_Lambda([this]() -> FText + SNew(SComboBox>) + .OptionsSource(&LanguageOverridesAvailable) + .OnGenerateWidget_Lambda([this](TSharedPtr InItem) -> TSharedRef + { + return SNew(STextBlock).Text(FText::FromString(*InItem)); + }) + .OnSelectionChanged_Lambda([this](TSharedPtr Item, ESelectInfo::Type SelectInfo) -> void + { + SelectedLanguageOverride = Item; + if (WidgetController.IsValid()) { - if (SelectedLanguageOverride.IsValid()) + WidgetController->OnLocalizationOnFirstRunLangChanged(*Item); + } + }) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Regular", 10)) + .Text_Lambda([this]() -> FText { - return FText::FromString(*SelectedLanguageOverride); - } - return FText::GetEmpty(); - }) + if (SelectedLanguageOverride.IsValid()) + { + return FText::FromString(*SelectedLanguageOverride); + } + return FText::GetEmpty(); + }) + ] ] ] ] // > Separator Box ================ +SVerticalBox::Slot() .AutoHeight() - .MinHeight(24.f) [ - SNew(SHorizontalBox) - .ToolTipText(INVTEXT("A CSV column separator. It's \",\" by default, but it can be any other single character.")) - // >>>> Separator Label - +SHorizontalBox::Slot() - .FillContentWidth(1) - .MaxWidth(400.0f) - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) - .Text(INVTEXT("Separator:")) - ] - // >>>> Separator Value - +SHorizontalBox::Slot() - .FillContentWidth(1) - .MaxWidth(200.0f) - .VAlign(EVerticalAlignment::VAlign_Center) + SNew(SBox) + .MinDesiredHeight(24.f) [ - SNew(SEditableTextBox) - .Font(FCoreStyle::GetDefaultFontStyle("Regular", 11)) - .Text_Lambda([this]() -> FText - { - return FText::FromString(SeparatorValue); - }) - .OnTextCommitted_Lambda([this](const FText& NewText, ETextCommit::Type CommitType) -> void - { - SeparatorValue = NewText.ToString(); - if (WidgetController.IsValid()) + SNew(SHorizontalBox) + .ToolTipText(INVTEXT("A CSV column separator. It's \",\" by default, but it can be any other single character.")) + // >>>> Separator Label + +SHorizontalBox::Slot() + .FillWidth(1.0f) + .MaxWidth(400.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) + .Text(INVTEXT("Separator:")) + ] + // >>>> Separator Value + +SHorizontalBox::Slot() + .FillWidth(1.0f) + .MaxWidth(200.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(SEditableTextBox) + .Font(FCoreStyle::GetDefaultFontStyle("Regular", 11)) + .Text_Lambda([this]() -> FText { - WidgetController->OnSeparatorChanged(SeparatorValue); - } - }) + return FText::FromString(SeparatorValue); + }) + .OnTextCommitted_Lambda([this](const FText& NewText, ETextCommit::Type CommitType) -> void + { + SeparatorValue = NewText.ToString(); + if (WidgetController.IsValid()) + { + WidgetController->OnSeparatorChanged(SeparatorValue); + } + }) + ] ] ] // > Fallback when empty Box ================ +SVerticalBox::Slot() .AutoHeight() - .MinHeight(24.f) [ - SNew(SHorizontalBox) - .ToolTipText(INVTEXT("\ -When the entry is empty should it fill it with a fallback value?\n\ -NONE - no fallback\n\ -FIRST_LANG - use value of the first language.If that value is empty use Key\n\ -KEY - use the key of this entry")) - // >>>> Fallback when empty Label - +SHorizontalBox::Slot() - .FillContentWidth(1) - .MaxWidth(400.0f) - .VAlign(EVerticalAlignment::VAlign_Center) + SNew(SBox) + .MinDesiredHeight(24.f) [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) - .Text(INVTEXT("Fallback when empty:")) - ] - // >>>> Fallback when empty List - +SHorizontalBox::Slot() - .AutoWidth() - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(SComboBox>) - .OptionsSource(&FallbackWhenEmptyAvailable) - .OnGenerateWidget_Lambda([this](TSharedPtr InItem) -> TSharedRef - { - return SNew(STextBlock).Text(FText::FromString(*InItem)); - }) - .OnSelectionChanged_Lambda([this](TSharedPtr Item, ESelectInfo::Type SelectInfo) -> void - { - SelectedFallbackWhenEmpty = Item; - if (SelectedFallbackWhenEmpty.IsValid()) - { - WidgetController->OnFallbackWhenEmptyChanged(*Item); - } - }) + SNew(SHorizontalBox) + .ToolTipText(INVTEXT("\ + When the entry is empty should it fill it with a fallback value?\n\ + NONE - no fallback\n\ + FIRST_LANG - use value of the first language.If that value is empty use Key\n\ + KEY - use the key of this entry")) + // >>>> Fallback when empty Label + +SHorizontalBox::Slot() + .FillWidth(1.0f) + .MaxWidth(400.0f) + .VAlign(EVerticalAlignment::VAlign_Center) [ SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Bold", 10)) - .Text_Lambda([this]() -> FText + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) + .Text(INVTEXT("Fallback when empty:")) + ] + // >>>> Fallback when empty List + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(SComboBox>) + .OptionsSource(&FallbackWhenEmptyAvailable) + .OnGenerateWidget_Lambda([this](TSharedPtr InItem) -> TSharedRef + { + return SNew(STextBlock).Text(FText::FromString(*InItem)); + }) + .OnSelectionChanged_Lambda([this](TSharedPtr Item, ESelectInfo::Type SelectInfo) -> void + { + SelectedFallbackWhenEmpty = Item; + if (SelectedFallbackWhenEmpty.IsValid()) { - if (SelectedFallbackWhenEmpty.IsValid()) + WidgetController->OnFallbackWhenEmptyChanged(*Item); + } + }) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Bold", 10)) + .Text_Lambda([this]() -> FText { - return FText::FromString(*SelectedFallbackWhenEmpty); - } - return FText::GetEmpty(); - }) + if (SelectedFallbackWhenEmpty.IsValid()) + { + return FText::FromString(*SelectedFallbackWhenEmpty); + } + return FText::GetEmpty(); + }) + ] ] ] ] // > Generate Key Reference String Table on Import Box ================ +SVerticalBox::Slot() .AutoHeight() - .MinHeight(24.f) [ - SNew(SHorizontalBox) - .ToolTipText(INVTEXT("\ -On CSV Import, a String Table filled with Key References will be generated PER namespace.\n\ -These String Table can be used to easily assign keys to FText properties.\n\n\ -The String Table will be generated in the Localization Folder path and IS OVERRIDDEN if it already exists.")) - // >>>> Generate Key Reference String Table CSV Import Label - +SHorizontalBox::Slot() - .FillContentWidth(1) - .MaxWidth(400.0f) - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) - .Text(INVTEXT("Generate Key Reference String Table on Import:")) - ] - // >>>> Generate Key Reference String Table on Import checkbox - +SHorizontalBox::Slot() - .AutoWidth() - .VAlign(EVerticalAlignment::VAlign_Center) + SNew(SBox) + .MinDesiredHeight(24.f) [ - SNew(SCheckBox) - .IsChecked_Lambda([this]() -> ECheckBoxState - { - return bGenerateKeyReferenceStringTable_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; - }) - .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void - { - bGenerateKeyReferenceStringTable_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); - if (WidgetController.IsValid()) + SNew(SHorizontalBox) + .ToolTipText(INVTEXT("\ + On CSV Import, a String Table filled with Key References will be generated PER namespace.\n\ + These String Table can be used to easily assign keys to FText properties.\n\n\ + The String Table will be generated in the Localization Folder path and IS OVERRIDDEN if it already exists.")) + // >>>> Generate Key Reference String Table CSV Import Label + +SHorizontalBox::Slot() + .FillWidth(1.0f) + .MaxWidth(400.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) + .Text(INVTEXT("Generate Key Reference String Table on Import:")) + ] + // >>>> Generate Key Reference String Table on Import checkbox + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(SCheckBox) + .IsChecked_Lambda([this]() -> ECheckBoxState { - WidgetController->OnGenerateKeyReferenceStringTableChanged(bGenerateKeyReferenceStringTable_Chkbox); - } - }) + return bGenerateKeyReferenceStringTable_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void + { + bGenerateKeyReferenceStringTable_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); + if (WidgetController.IsValid()) + { + WidgetController->OnGenerateKeyReferenceStringTableChanged(bGenerateKeyReferenceStringTable_Chkbox); + } + }) + ] ] ] // > Spacer ================ @@ -623,42 +644,45 @@ The String Table will be generated in the Localization Folder path and IS OVERRI // > Global namespace box ================ +SVerticalBox::Slot() .AutoHeight() - .MinHeight(24.f) .Padding(FMargin(0.f, 15.f, 0.f, 0.f)) [ - SNew(SHorizontalBox) - .ToolTipText(INVTEXT("This namespace will be assigned to every key in localization.")) - // >>>> Global namespace label ================ - +SHorizontalBox::Slot() - .FillContentWidth(1) - .MaxWidth(400.0f) - .VAlign(EVerticalAlignment::VAlign_Center) + SNew(SBox) + .MinDesiredHeight(24.f) [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) - .Text(INVTEXT("Global namespace:")) - ] - // >>>> Global namespace value ================ - +SHorizontalBox::Slot() - .FillContentWidth(1) - .MaxWidth(200.0f) - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(SEditableTextBox) - .Font(FCoreStyle::GetDefaultFontStyle("Regular", 11)) - .MinDesiredWidth(256.f) - .Text_Lambda([this]() -> FText - { - return FText::FromString(GlobalNamespaceValue); - }) - .OnTextCommitted_Lambda([this](const FText& NewText, ETextCommit::Type CommitType) -> void - { - GlobalNamespaceValue = NewText.ToString(); - if (WidgetController.IsValid()) + SNew(SHorizontalBox) + .ToolTipText(INVTEXT("This namespace will be assigned to every key in localization.")) + // >>>> Global namespace label ================ + +SHorizontalBox::Slot() + .FillWidth(1.0f) + .MaxWidth(400.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) + .Text(INVTEXT("Global namespace:")) + ] + // >>>> Global namespace value ================ + +SHorizontalBox::Slot() + .FillWidth(1.0f) + .MaxWidth(200.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(SEditableTextBox) + .Font(FCoreStyle::GetDefaultFontStyle("Regular", 11)) + .MinDesiredWidth(256.f) + .Text_Lambda([this]() -> FText { - WidgetController->OnGlobalNamespaceChanged(GlobalNamespaceValue); - } - }) + return FText::FromString(GlobalNamespaceValue); + }) + .OnTextCommitted_Lambda([this](const FText& NewText, ETextCommit::Type CommitType) -> void + { + GlobalNamespaceValue = NewText.ToString(); + if (WidgetController.IsValid()) + { + WidgetController->OnGlobalNamespaceChanged(GlobalNamespaceValue); + } + }) + ] ] ] // > Spacer ================ @@ -673,84 +697,90 @@ The String Table will be generated in the Localization Folder path and IS OVERRI // > Log Debug Box ================ +SVerticalBox::Slot() .AutoHeight() - .MinHeight(24.f) [ - SNew(SHorizontalBox) - .ToolTipText(INVTEXT("Select this option to see additional informations in Output Log.\nBe aware that big CSVs might generate a lot of logs.")) - // >>>> Log Debug Label - +SHorizontalBox::Slot() - .MaxWidth(400.0f) - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) - .Text(INVTEXT("Log Debug:")) - ] - // >>>> Log Debug checkbox - +SHorizontalBox::Slot() - .AutoWidth() - .VAlign(EVerticalAlignment::VAlign_Center) + SNew(SBox) + .MinDesiredHeight(24.f) [ - SNew(SCheckBox) - .IsChecked_Lambda([this]() -> ECheckBoxState - { - return bLogDebug_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; - }) - .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void - { - bLogDebug_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); - if (WidgetController.IsValid()) + SNew(SHorizontalBox) + .ToolTipText(INVTEXT("Select this option to see additional informations in Output Log.\nBe aware that big CSVs might generate a lot of logs.")) + // >>>> Log Debug Label + +SHorizontalBox::Slot() + .MaxWidth(400.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) + .Text(INVTEXT("Log Debug:")) + ] + // >>>> Log Debug checkbox + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(SCheckBox) + .IsChecked_Lambda([this]() -> ECheckBoxState { - WidgetController->OnLogDebugChanged(bLogDebug_Chkbox); - } - }) + return bLogDebug_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void + { + bLogDebug_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); + if (WidgetController.IsValid()) + { + WidgetController->OnLogDebugChanged(bLogDebug_Chkbox); + } + }) + ] ] ] // > Preview In UI Box ================ +SVerticalBox::Slot() .AutoHeight() - .MinHeight(24.f) [ - SNew(SHorizontalBox) - .ToolTipText(INVTEXT("Select this option to show a localization preview under the Text fields in the Editor UI.")) - .Visibility_Lambda([this]() -> EVisibility - { - if (WidgetController.IsValid()) - { - if (WidgetController->IsPreviewInUISupported()) - { - return EVisibility::Visible; - } - } - return EVisibility::Collapsed; - }) - // >>>> Preview In UI Label - +SHorizontalBox::Slot() - .MaxWidth(400.0f) - .VAlign(EVerticalAlignment::VAlign_Center) - [ - SNew(STextBlock) - .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) - .Text(INVTEXT("Show preview in UI:")) - ] - // >>>> Preview In UI checkbox - +SHorizontalBox::Slot() - .AutoWidth() - .VAlign(EVerticalAlignment::VAlign_Center) + SNew(SBox) + .MinDesiredHeight(24.f) [ - SNew(SCheckBox) - .IsChecked_Lambda([this]() -> ECheckBoxState - { - return bPreviewInUI_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; - }) - .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void + SNew(SHorizontalBox) + .ToolTipText(INVTEXT("Select this option to show a localization preview under the Text fields in the Editor UI.")) + .Visibility_Lambda([this]() -> EVisibility + { + if (WidgetController.IsValid()) { - bPreviewInUI_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); - if (WidgetController.IsValid()) + if (WidgetController->IsPreviewInUISupported()) { - WidgetController->OnPreviewInUIChanged(bPreviewInUI_Chkbox); + return EVisibility::Visible; } - }) + } + return EVisibility::Collapsed; + }) + // >>>> Preview In UI Label + +SHorizontalBox::Slot() + .MaxWidth(400.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(STextBlock) + .Font(FCoreStyle::GetDefaultFontStyle("Light", 11)) + .Text(INVTEXT("Show preview in UI:")) + ] + // >>>> Preview In UI checkbox + +SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(SCheckBox) + .IsChecked_Lambda([this]() -> ECheckBoxState + { + return bPreviewInUI_Chkbox ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([this](ECheckBoxState InCheckBoxState) -> void + { + bPreviewInUI_Chkbox = (InCheckBoxState == ECheckBoxState::Checked); + if (WidgetController.IsValid()) + { + WidgetController->OnPreviewInUIChanged(bPreviewInUI_Chkbox); + } + }) + ] ] ] ] From d4e6e78e6c8927b098741a4cf03b126892079d94 Mon Sep 17 00:00:00 2001 From: Damian Nowakowski Date: Tue, 19 May 2026 10:49:01 +0200 Subject: [PATCH 6/9] Update Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp Fixed message dialog call for older engine versions Co-authored-by: Ryan Lim --- Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp index 205c288..ee433ed 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp @@ -283,6 +283,10 @@ void UELTEditor::OnGenerateLocFiles() FMessageDialog::Open((bSuccess ? EAppMsgCategory::Success : EAppMsgCategory::Error), EAppMsgType::Ok, FText::FromString(ReturnMessage)); #else FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(ReturnMessage)); +#if (ENGINE_MAJOR_VERSION == 5) && ENGINE_MINOR_VERSION >= 3 +FMessageDialog::Open((bSuccess ? EAppMsgCategory::Success : EAppMsgCategory::Error), EAppMsgType::Ok, FText::FromString(ReturnMessage)); +#else +FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(ReturnMessage)); #endif } From b5f91abb9dc6d7f0db4403c4bc50e09a2e282dbf Mon Sep 17 00:00:00 2001 From: Ryan Lim Date: Tue, 19 May 2026 18:03:32 +0800 Subject: [PATCH 7/9] Crash and Bug fixes. - Fixed GitHub auto commit being incorrectly done. - Fixed Key Column index not correctly defined. - Fixed StringTable package load causing assertion. --- .../Private/ELTEditor.cpp | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp index ee433ed..74e2345 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp @@ -279,14 +279,10 @@ void UELTEditor::OnGenerateLocFiles() } // Display a Dialog Window to inform user that the localization generation has been finished. -#if (ENGINE_MAJOR_VERSION == 5) +#if (ENGINE_MAJOR_VERSION == 5) && ENGINE_MINOR_VERSION >= 3 FMessageDialog::Open((bSuccess ? EAppMsgCategory::Success : EAppMsgCategory::Error), EAppMsgType::Ok, FText::FromString(ReturnMessage)); #else FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(ReturnMessage)); -#if (ENGINE_MAJOR_VERSION == 5) && ENGINE_MINOR_VERSION >= 3 -FMessageDialog::Open((bSuccess ? EAppMsgCategory::Success : EAppMsgCategory::Error), EAppMsgType::Ok, FText::FromString(ReturnMessage)); -#else -FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(ReturnMessage)); #endif } @@ -600,18 +596,27 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt // Potential place for devnotes. const FCSVColumn& DevNotes = (DevNotesColumn != INDEX_NONE) ? Columns[DevNotesColumn] : Columns[0]; - // Clear the localization directory first. + // Clear the localization directory first, preserving any .uasset files (e.g. string table assets). + // Deleting .uasset files while the corresponding UPackage is still in memory invalidates the async loader's package tracking and causes an assertion on the next reimport. if (bFirstCSV) { // Ensure we are not deleting any important files by checking if we are in Content directory and the Meta file is there exists. if (LocPath.Contains("Content") && IFileManager::Get().FileExists(*MetaFileName)) { - IFileManager::Get().DeleteDirectory(*LocPath, false, true); + TArray FilesToDelete; + IFileManager::Get().FindFilesRecursive(FilesToDelete, *LocPath, TEXT("*"), true, false); + for (const FString& File : FilesToDelete) + { + if (File.EndsWith(TEXT(".uasset")) == false) + { + IFileManager::Get().Delete(*File); + } + } } } // Get the keys column and check if it is valid. - const FCSVColumn& Keys = Columns[FirstLangColumn]; + const FCSVColumn& Keys = Columns[FirstLangColumn-1]; if (Keys.Values[0].Equals(TEXT("key"), ESearchCase::IgnoreCase) == false) { OutMessage = TEXT("ERROR: Key column in CSV not found!"); @@ -763,13 +768,31 @@ bool UELTEditor::GenerateLocFilesImpl(const TArray& CSVPaths, const FSt FString AssetName = FString::Printf(TEXT("ELT_KeyReferences_%s_%s"), *LocName, *Namespace); FString PackagePath = FPackageName::FilenameToLongPackageName(LocPath / AssetName); - UPackage* Package = FPackageName::DoesPackageExist(*PackagePath) ? LoadPackage(nullptr, *PackagePath, LOAD_None) : CreatePackage(*PackagePath); + // If the package is already in memory (e.g. from a previous reimport), use it directly. + UPackage* Package = FindPackage(nullptr, *PackagePath); + if (Package == nullptr) + { + if (FPackageName::DoesPackageExist(*PackagePath)) + { + Package = LoadPackage(nullptr, *PackagePath, LOAD_None); + } else + { + Package = CreatePackage(*PackagePath); + } + } if (Package == nullptr) { OutMessage = FString::Printf(TEXT("ERROR: Failed to create package path for StringTable: %s"), *PackagePath); return false; } - + + // Clear any existing StringTable from the package before creating a new one. + if (UStringTable* Existing = FindObject(Package, *AssetName)) + { + Existing->ClearFlags(RF_Public | RF_Standalone); + Existing->MarkAsGarbage(); + } + UStringTable* StringTableAsset = NewObject(Package, UStringTable::StaticClass(), FName(*AssetName), (RF_Public | RF_Standalone | RF_Transactional)); if (StringTableAsset == nullptr) { From 0b20bbcdf0e7456d9e69e6d58ebbf3ef855417b7 Mon Sep 17 00:00:00 2001 From: Ryan Lim Date: Tue, 19 May 2026 21:41:24 +0800 Subject: [PATCH 8/9] - Implemented Localization Audit (squashed for publish) - Implemented Audit Main Class (ELTEditorAuditor) - Implemented Audit Widget (ELTEditorAuditWidget) - Implemented Audit Types (ELTEditorAuditTypes) - Updated ELTEditorCommands to include Audit commands. - Updated EasyLocalizationToolEditorModule to include Audit menu bar and context menu functionality. - Updated ELTEditor, RefreshAvailableLangs() was updated to support both ELT Tool and Audit Widgets. --- .../EasyLocalizationToolEditor.Build.cs | 6 +- .../Private/ELTEditor.cpp | 28 +- .../Private/ELTEditorAuditWidget.cpp | 918 ++++++++++++++++++ .../Private/ELTEditorAuditor.cpp | 484 +++++++++ .../Private/ELTEditorCommands.cpp | 1 + .../EasyLocalizationToolEditorModule.cpp | 239 ++++- .../Public/ELTEditor.h | 18 +- .../Public/ELTEditorAuditTypes.h | 150 +++ .../Public/ELTEditorAuditWidget.h | 130 +++ .../Public/ELTEditorAuditor.h | 43 + .../Public/ELTEditorCommands.h | 1 + .../Public/EasyLocalizationToolEditorModule.h | 10 +- 12 files changed, 2009 insertions(+), 19 deletions(-) create mode 100644 Source/EasyLocalizationToolEditor/Private/ELTEditorAuditWidget.cpp create mode 100644 Source/EasyLocalizationToolEditor/Private/ELTEditorAuditor.cpp create mode 100644 Source/EasyLocalizationToolEditor/Public/ELTEditorAuditTypes.h create mode 100644 Source/EasyLocalizationToolEditor/Public/ELTEditorAuditWidget.h create mode 100644 Source/EasyLocalizationToolEditor/Public/ELTEditorAuditor.h diff --git a/Source/EasyLocalizationToolEditor/EasyLocalizationToolEditor.Build.cs b/Source/EasyLocalizationToolEditor/EasyLocalizationToolEditor.Build.cs index 4f3d1f5..165912f 100644 --- a/Source/EasyLocalizationToolEditor/EasyLocalizationToolEditor.Build.cs +++ b/Source/EasyLocalizationToolEditor/EasyLocalizationToolEditor.Build.cs @@ -40,6 +40,10 @@ public EasyLocalizationToolEditor(ReadOnlyTargetRules Target) : base(Target) "EditorWidgets", "BlueprintGraph", "PropertyEditor", + "ContentBrowser", + "AssetRegistry", + "Kismet", + "ApplicationCore", } ); @@ -98,4 +102,4 @@ public EasyLocalizationToolEditor(ReadOnlyTargetRules Target) : base(Target) PublicDefinitions.Add("ELTEDITOR_USE_SLATE_EDITOR_UI=0"); } } -} +} \ No newline at end of file diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp index 74e2345..feb1bdd 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditor.cpp @@ -11,6 +11,7 @@ #include "Misc/MessageDialog.h" #include "ELTEditorSettings.h" #include "ELTEditorWidget.h" +#include "ELTEditorAuditWidget.h" #include "ELTSettings.h" #include "UObject/SavePackage.h" @@ -41,6 +42,10 @@ void UELTEditor::Init() CSVPaths = UELTEditorSettings::GetCSVPaths(); CurrentLocPath = UELTEditorSettings::GetLocalizationPath(); + // Bind the audit widget's Reimport CSV button to this editor's generate function. + // Done here rather than InitializeTheWidget, as that requires ELT tool widget opened. + UELTEditorAuditWidget::OnReimportCSVDelegate.BindUObject(this, &UELTEditor::OnGenerateLocFiles); + // Reimport localizations (if this option is enabled). if (UELTEditorSettings::GetReimportAtEditorStartup()) { @@ -49,7 +54,7 @@ void UELTEditor::Init() } // Refresh information about available localizations. - RefreshAvailableLangs(false); + RefreshAvailableLangs(ERefreshUIFlags::None); // Set preview language (if the option is enabled). SetLanguagePreview(); @@ -151,7 +156,7 @@ void UELTEditor::ChangeTabWorld(UWorld* World, EMapChangeType MapChangeType) void UELTEditor::InitializeTheWidget() { // Check available languages (based on files in Localization directory) - RefreshAvailableLangs(true); + RefreshAvailableLangs(ERefreshUIFlags::All); // Bind all required delegates to the Widget. EditorWidget->OnLocalizationPathSelectedDelegate.BindUObject(this, &UELTEditor::OnLocalizationPathChanged); @@ -244,7 +249,7 @@ void UELTEditor::OnLocalizationPathChanged(const FString& NewPath) EditorWidget->CallFillCSVPath(PathsStringToList(GetCurrentCSVPath())); // Refresh available languages for this Localization directory and set them to the Widget. - RefreshAvailableLangs(false); + RefreshAvailableLangs(ERefreshUIFlags::None); EditorWidget->CallFillAvailableLangsInLocFile(CurrentAvailableLangsForLocFile); // Set Global Namespace for this Localization directory to the Widget. @@ -274,10 +279,11 @@ void UELTEditor::OnGenerateLocFiles() const bool bSuccess = GenerateLocFiles(ReturnMessage); if (bSuccess) { - RefreshAvailableLangs(true); + const ERefreshUIFlags Flags = EditorWidget ? ERefreshUIFlags::All : ERefreshUIFlags::AuditWidget; + RefreshAvailableLangs(Flags); SetLanguagePreview(); } - + // Display a Dialog Window to inform user that the localization generation has been finished. #if (ENGINE_MAJOR_VERSION == 5) && ENGINE_MINOR_VERSION >= 3 FMessageDialog::Open((bSuccess ? EAppMsgCategory::Success : EAppMsgCategory::Error), EAppMsgType::Ok, FText::FromString(ReturnMessage)); @@ -398,7 +404,7 @@ void UELTEditor::SetLanguagePreview() } } -void UELTEditor::RefreshAvailableLangs(bool bRefreshUI) +void UELTEditor::RefreshAvailableLangs(ERefreshUIFlags UIFlags) { // Get all available languages by reading the localization directory. // Languages in current localization directory put into the separate array too. @@ -426,7 +432,10 @@ void UELTEditor::RefreshAvailableLangs(bool bRefreshUI) } } - if (bRefreshUI) + const bool bRefreshELTWidget = EnumHasAnyFlags(UIFlags, ERefreshUIFlags::ToolWidget); + const bool bRefreshAuditWidget = EnumHasAnyFlags(UIFlags, ERefreshUIFlags::AuditWidget); + + if (bRefreshELTWidget && EditorWidget) { // If the RefreshUI has been requested - set the available languages on the Widget. EditorWidget->CallFillAvailableLangs(CurrentAvailableLangs); @@ -457,6 +466,11 @@ void UELTEditor::RefreshAvailableLangs(bool bRefreshUI) } } + if (bRefreshAuditWidget) + { + UELTEditorAuditWidget::UpdateAvailableLanguages(CurrentAvailableLangs); + } + // Set available languages to the game settings. UELTSettings::SetAvailableLanguages(CurrentAvailableLangs); } diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditWidget.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditWidget.cpp new file mode 100644 index 0000000..13ede49 --- /dev/null +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditWidget.cpp @@ -0,0 +1,918 @@ +// Copyright (c) 2026 Damian Nowakowski. All rights reserved. + +#include "ELTEditorAuditWidget.h" +#include "ELTEditorAuditor.h" +#include "ELTSettings.h" + +#include "Framework/Docking/TabManager.h" +#include "Widgets/Docking/SDockTab.h" +#include "Widgets/Layout/SBorder.h" +#include "Widgets/Layout/SBox.h" +#include "Widgets/Text/STextBlock.h" +#include "Widgets/Input/SButton.h" +#include "Widgets/Input/SCheckBox.h" +#include "Widgets/Input/SComboBox.h" +#include "Widgets/Input/SHyperlink.h" +#include "Widgets/Views/SHeaderRow.h" +#include "Widgets/Views/STableRow.h" +#include "Widgets/SBoxPanel.h" + +#include "Engine/Blueprint.h" +#include "EdGraph/EdGraph.h" +#include "EdGraph/EdGraphNode.h" +#include "Kismet2/KismetEditorUtilities.h" +#include "Subsystems/AssetEditorSubsystem.h" +#include "Internationalization/Internationalization.h" +#include "Internationalization/Culture.h" +#include "HAL/PlatformApplicationMisc.h" +#include "Misc/MessageDialog.h" +#include "Editor.h" + +#if (ENGINE_MAJOR_VERSION >= 5) + #define ELT_APP_STYLE FAppStyle::Get() + #define ELT_GET_BRUSH(Name) FAppStyle::GetBrush(Name) +#else + #include "EditorStyleSet.h" + #define ELT_APP_STYLE FEditorStyle::Get() + #define ELT_GET_BRUSH(Name) FEditorStyle::GetBrush(Name) +#endif + +DEFINE_LOG_CATEGORY_STATIC(ELTAuditWidgetLog, Log, All); + +namespace ELTAuditCol +{ + static const FName AssetName = TEXT("AssetName"); + static const FName Type = TEXT("Type"); + static const FName VariableNode = TEXT("VariableNode"); + static const FName Issue = TEXT("Issue"); + static const FName QuickAction = TEXT("QuickAction"); + static const FName LocalizedString = TEXT("LocalizedString"); + static const FName Value = TEXT("Value"); + static const FName Key = TEXT("Key"); + static const FName Namespace = TEXT("Namespace"); + static const FName IsUsingStringTable = TEXT("IsUsingStringTable"); +} + +namespace ELTAuditColor +{ + // Cell text colours + static const FLinearColor Default = FLinearColor::White; + static const FLinearColor Muted = FLinearColor(0.5f, 0.5f, 0.5f); + + // Type column + static const FLinearColor TypeClassVariable = FLinearColor(.7f, 0.4f, 0.9f); + static const FLinearColor TypeFunctionVariable = FLinearColor(0.4f, 0.7f, 1.f); + static const FLinearColor TypeNodeParameter = FLinearColor(1.f, 0.8f, 0.2f); + static const FLinearColor TypeWidgetComponent = FLinearColor(0.4f, 0.9f, 0.4f); + + // Issue column + static const FLinearColor IssueNone = FLinearColor(0.5f, 0.5f, 0.5f); + static const FLinearColor IssueWarning = FLinearColor(1.f, 0.8f, 0.2f); + static const FLinearColor IssueError = FLinearColor(1.f, 0.4f, 0.4f); + + // IsUsingStringTable column + static const FLinearColor StringTableTrue = FLinearColor(0.4f, 0.9f, 0.4f); + static const FLinearColor StringTableFalse = FLinearColor(1.f, 0.4f, 0.4f); + + // Primary column background tint + static const FLinearColor PrimaryColumnTint = FLinearColor(1.f, 1.f, 1.f, 0.05f); + + // Tip text + static const FLinearColor TipText = FLinearColor::White; +} + +const FName UELTEditorAuditWidget::TabName = TEXT("ELTLocalizationAudit"); +TArray UELTEditorAuditWidget::PendingResults; +TWeakPtr UELTEditorAuditWidget::LiveWidget; +FOnAuditWidgetReimportCSV UELTEditorAuditWidget::OnReimportCSVDelegate; +bool UELTEditorAuditWidget::bPendingDialogOnSpawn = false; + +/*static*/ void UELTEditorAuditWidget::ShowCompletionDialog(const TArray& Results) +{ + int32 IssueCount = 0; + TSet AffectedAssets; + for (const FELTAssetAuditResult& Result : Results) + { + for (const FELTAuditIssue& Issue : Result.Issues) + { + if (Issue.HasIssue()) + { + ++IssueCount; + AffectedAssets.Add(Issue.AssetName); + } + } + } + + const FString Summary = (IssueCount == 0) + ? FString::Printf(TEXT("All %d asset(s) passed localization audit."), Results.Num()) + : FString::Printf(TEXT("%d issue(s) found across %d / %d asset(s)."), IssueCount, AffectedAssets.Num(), Results.Num()); + +#if (ENGINE_MAJOR_VERSION == 5) + FMessageDialog::Open(EAppMsgCategory::Success, EAppMsgType::Ok, FText::FromString(Summary), FText::FromString(TEXT("Audit Complete"))); +#else + FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(Summary)); +#endif +} + +/*static*/ void UELTEditorAuditWidget::ShowResults(const TArray& Results) +{ + PendingResults = Results; + + FGlobalTabmanager& TM = *FGlobalTabmanager::Get(); + + if (TM.HasTabSpawner(TabName) == false) + { + FTabSpawnerEntry& Entry = TM.RegisterNomadTabSpawner( + TabName, FOnSpawnTab::CreateStatic(&UELTEditorAuditWidget::SpawnTab)); + + Entry + .SetDisplayName(FText::FromString(TEXT("Localization Audit"))) + .SetTooltipText(FText::FromString(TEXT("Shows FText localization issues found in selected assets."))) + .SetMenuType(ETabSpawnerMenuType::Hidden); + } + + if (TSharedPtr Pinned = LiveWidget.Pin()) + { + Pinned->SetPendingCompletionDialog(true); + Pinned->Refresh(Results); + TM.TryInvokeTab(TabName); + return; + } + + // Mark that a completion dialog should show when the widget is constructed. + bPendingDialogOnSpawn = true; + TM.TryInvokeTab(TabName); +} + +/*static*/ void UELTEditorAuditWidget::UpdateAvailableLanguages(const TArray& Languages) +{ + if (TSharedPtr Pinned = LiveWidget.Pin()) + { + Pinned->RefreshLanguages(Languages); + } +} + +/*static*/ TSharedRef UELTEditorAuditWidget::SpawnTab(const FSpawnTabArgs& Args) +{ + TSharedPtr Widget; + + TSharedRef Tab = SNew(SDockTab) + .TabRole(ETabRole::NomadTab) + .Label(FText::FromString(TEXT("Localization Audit"))) + [ + SAssignNew(Widget, SELTEditorAuditWidget) + .AuditResults(PendingResults) + ]; + + LiveWidget = Widget; + return Tab; +} + +class SELTAuditIssueRow : public SMultiColumnTableRow> +{ +public: + SLATE_BEGIN_ARGS(SELTAuditIssueRow) {} + SLATE_ARGUMENT(TSharedPtr, Issue) + SLATE_ARGUMENT(FAssetData,AssetData) + SLATE_END_ARGS() + + void Construct(const FArguments& InArgs, const TSharedRef& OwnerTable) + { + Issue = InArgs._Issue; + AssetData = InArgs._AssetData; + + // Initialised here so it has the same lifetime as the row widget — safe to take &. + CopyButtonStyle = FCoreStyle::Get().GetWidgetStyle("NoBorder"); + CopyButtonStyle.Normal = FSlateNoResource(); + CopyButtonStyle.Hovered = FSlateNoResource(); + CopyButtonStyle.Pressed = FSlateNoResource(); + + SMultiColumnTableRow>::Construct( + SMultiColumnTableRow::FArguments().Padding(FMargin(2.f, 1.f)), OwnerTable); + } + + virtual TSharedRef GenerateWidgetForColumn(const FName& ColumnId) override + { + if (Issue.IsValid() == false) + { + return SNullWidget::NullWidget; + } + + const FELTAuditIssue& Row = *Issue; + + // Detail columns have no background tint; primary columns (first five) get a subtle lighter shade. + auto Cell = [this](const FString& Str, FLinearColor Col = ELTAuditColor::Default) -> TSharedRef + { + return SNew(SButton) + .ButtonStyle(&CopyButtonStyle) + .ContentPadding(FMargin(6.f, 2.f)) + .Cursor(EMouseCursor::Hand) + .ToolTipText(FText::FromString(TEXT("Left-click to copy"))) + .OnClicked_Lambda([Str]() -> FReply + { + FPlatformApplicationMisc::ClipboardCopy(*Str); + return FReply::Handled(); + }) + [ + SNew(STextBlock) + .Text(FText::FromString(Str)) + .ColorAndOpacity(Col) + ]; + }; + + auto PrimaryCell = [this](const FString& Str, FLinearColor Col = ELTAuditColor::Default) -> TSharedRef + { + return SNew(SBorder) + .BorderImage(ELT_GET_BRUSH("WhiteTexture")) + .BorderBackgroundColor(ELTAuditColor::PrimaryColumnTint) + .Padding(0.f) + [ + SNew(SButton) + .ButtonStyle(&CopyButtonStyle) + .ContentPadding(FMargin(6.f, 2.f)) + .Cursor(EMouseCursor::Hand) + .ToolTipText(FText::FromString(TEXT("Left-click to copy"))) + .OnClicked_Lambda([Str]() -> FReply + { + FPlatformApplicationMisc::ClipboardCopy(*Str); + return FReply::Handled(); + }) + [ + SNew(STextBlock) + .Text(FText::FromString(Str)) + .ColorAndOpacity(Col) + ] + ]; + }; + + if (ColumnId == ELTAuditCol::AssetName) + { + return PrimaryCell(Row.AssetName, ELTAuditColor::Default); + } + + if (ColumnId == ELTAuditCol::QuickAction) + { + const FAssetData CapturedAsset = AssetData; + const FELTAuditIssue CapturedRow = Row; + + FString ActionLabel; + FString ActionTooltip; + + switch (Row.Type) + { + case EELTAuditParameterType::ClassVariable: + ActionLabel = TEXT("Open Asset"); + ActionTooltip = TEXT("Open this asset in its default editor"); + break; + case EELTAuditParameterType::FunctionVariable: + ActionLabel = TEXT("Jump to Function"); + ActionTooltip = FString::Printf(TEXT("Navigate to function '%s'"), *Row.GraphName); + break; + case EELTAuditParameterType::NodeParameter: + ActionLabel = TEXT("Jump to Node"); + ActionTooltip = FString::Printf(TEXT("Focus the node in graph '%s'"), *Row.GraphName); + break; + case EELTAuditParameterType::WidgetComponent: + ActionLabel = TEXT("Open Asset"); + ActionTooltip = TEXT("Open this Widget Blueprint in the designer"); + break; + } + + return SNew(SBorder) + .BorderImage(ELT_GET_BRUSH("WhiteTexture")) + .BorderBackgroundColor(ELTAuditColor::PrimaryColumnTint) + .Padding(FMargin(6.f, 1.f)) + [ + SNew(SHyperlink) + .Text(FText::FromString(ActionLabel)) + .ToolTipText(FText::FromString(ActionTooltip)) + .OnNavigate_Lambda([CapturedAsset, CapturedRow]() + { + SELTEditorAuditWidget::JumpToIssue(CapturedAsset, CapturedRow); + }) + ]; + } + + if (ColumnId == ELTAuditCol::Type) + { + FLinearColor TypeCol = ELTAuditColor::TypeClassVariable; + if (Row.Type == EELTAuditParameterType::FunctionVariable) { TypeCol = ELTAuditColor::TypeFunctionVariable; } + else if (Row.Type == EELTAuditParameterType::NodeParameter) { TypeCol = ELTAuditColor::TypeNodeParameter; } + else if (Row.Type == EELTAuditParameterType::WidgetComponent) { TypeCol = ELTAuditColor::TypeWidgetComponent; } + return PrimaryCell(Row.TypeDisplayString(), TypeCol); + } + + if (ColumnId == ELTAuditCol::VariableNode) { return PrimaryCell(Row.VariableNodeName, ELTAuditColor::Default); } + + if (ColumnId == ELTAuditCol::Issue) + { + FLinearColor IssueCol; + if (Row.Issue == EELTAuditIssueType::None) { IssueCol = ELTAuditColor::IssueNone; } + else if (Row.Issue == EELTAuditIssueType::EmptyValue) { IssueCol = ELTAuditColor::IssueWarning; } + else { IssueCol = ELTAuditColor::IssueError; } + + return SNew(SBorder) + .BorderImage(ELT_GET_BRUSH("WhiteTexture")) + .BorderBackgroundColor(ELTAuditColor::PrimaryColumnTint) + .Padding(FMargin(6.f, 2.f)) + [ + SNew(STextBlock) + .Text(FText::FromString(Row.IssueDisplayString())) + .ColorAndOpacity(IssueCol) + .ToolTipText(FText::FromString(Row.IssueTooltipString())) + ]; + } + + if (ColumnId == ELTAuditCol::LocalizedString) { return Cell(Row.LocalizedString, ELTAuditColor::Muted); } + if (ColumnId == ELTAuditCol::Value) { return Cell(Row.Value, ELTAuditColor::Muted); } + if (ColumnId == ELTAuditCol::Key) { return Cell(Row.Key, ELTAuditColor::Muted); } + if (ColumnId == ELTAuditCol::Namespace) { return Cell(Row.Namespace, ELTAuditColor::Muted); } + + if (ColumnId == ELTAuditCol::IsUsingStringTable) + { + const bool bUsing = Row.bIsUsingStringTable; + return Cell(bUsing ? TEXT("true") : TEXT("false"), + bUsing ? ELTAuditColor::StringTableTrue : ELTAuditColor::StringTableFalse); + } + + return SNullWidget::NullWidget; + } + +private: + TSharedPtr Issue; + FAssetData AssetData; + FButtonStyle CopyButtonStyle; +}; + +void SELTEditorAuditWidget::RebuildAuditData(const TArray& InResults) +{ + AllIssues.Reset(); + FlatIssues.Reset(); + AssetDataMap.Reset(); + LastAuditedAssets.Reset(); + + for (const FELTAssetAuditResult& Result : InResults) + { + AssetDataMap.Emplace(Result.AssetData.AssetName.ToString(), Result.AssetData); + LastAuditedAssets.Add(Result.AssetData); + + for (const FELTAuditIssue& Issue : Result.Issues) + { + AllIssues.Add(MakeShared(Issue)); + } + } +} + +FText SELTEditorAuditWidget::BuildSummaryText() const +{ + const int32 TotalAssets = AssetDataMap.Num(); + + int32 IssueCount = 0; + TSet AffectedAssets; + for (const FIssuePtr& Ptr : AllIssues) + { + if (Ptr.IsValid() && Ptr->HasIssue()) + { + ++IssueCount; + AffectedAssets.Add(Ptr->AssetName); + } + } + + if (IssueCount == 0) + { + return FText::FromString(FString::Printf(TEXT("✔ All %d asset(s) passed localization audit."), TotalAssets)); + } + + return FText::FromString(FString::Printf(TEXT("⚠ %d issue(s) across %d / %d asset(s)."), IssueCount, AffectedAssets.Num(), TotalAssets)); +} + +EColumnSortMode::Type SELTEditorAuditWidget::GetSortModeForColumn(FName Column) const +{ + return (SortColumn == Column) ? SortMode : EColumnSortMode::None; +} + +void SELTEditorAuditWidget::OnSortColumn(EColumnSortPriority::Type /*Priority*/, const FName& Column, EColumnSortMode::Type Mode) +{ + SortColumn = Column; + SortMode = Mode; + ApplySort(); + + if (ListView.IsValid()) { ListView->RequestListRefresh(); } +} + +void SELTEditorAuditWidget::ApplySort() +{ + if (SortMode == EColumnSortMode::None || SortColumn.IsNone()) + { + return; + } + + auto GetSortKey = [](const FIssuePtr& Ptr, const FName& Col) -> FString + { + if (Ptr.IsValid() == false) { return TEXT(""); } + const FELTAuditIssue& I = *Ptr; + if (Col == ELTAuditCol::AssetName) { return I.AssetName; } + if (Col == ELTAuditCol::Type) { return I.TypeDisplayString(); } + if (Col == ELTAuditCol::VariableNode) { return I.VariableNodeName; } + if (Col == ELTAuditCol::Issue) { return I.IssueDisplayString(); } + if (Col == ELTAuditCol::LocalizedString) { return I.LocalizedString; } + if (Col == ELTAuditCol::Value) { return I.Value; } + if (Col == ELTAuditCol::Key) { return I.Key; } + if (Col == ELTAuditCol::Namespace) { return I.Namespace; } + if (Col == ELTAuditCol::IsUsingStringTable) { return I.bIsUsingStringTable ? TEXT("true") : TEXT("false"); } + return TEXT(""); + }; + + const FName Col = SortColumn; + const bool bAscend = (SortMode == EColumnSortMode::Ascending); + + FlatIssues.Sort([&](const FIssuePtr& A, const FIssuePtr& B) + { + const int32 Cmp = GetSortKey(A, Col).Compare(GetSortKey(B, Col), ESearchCase::IgnoreCase); + return bAscend ? Cmp < 0 : Cmp > 0; + }); +} + +void SELTEditorAuditWidget::ApplyFilter() +{ + FlatIssues.Reset(); + for (const FIssuePtr& Ptr : AllIssues) + { + if (Ptr.IsValid() == false) { continue; } + + if (Ptr->Issue == EELTAuditIssueType::None) + { + if (bFilterIssues == false) { FlatIssues.Add(Ptr); } + } + else if (Ptr->Issue == EELTAuditIssueType::EmptyValue) + { + if (bHideEmpty == false) { FlatIssues.Add(Ptr); } + } + else + { + FlatIssues.Add(Ptr); + } + } +} + +void SELTEditorAuditWidget::OnFilterIssuesChanged(ECheckBoxState NewState) +{ + bFilterIssues = (NewState == ECheckBoxState::Checked); + ApplyFilter(); + ApplySort(); + if (ListView.IsValid()) { ListView->RequestListRefresh(); } + if (SummaryText.IsValid()) { SummaryText->SetText(BuildSummaryText()); } +} + +void SELTEditorAuditWidget::OnHideEmptyChanged(ECheckBoxState NewState) +{ + bHideEmpty = (NewState == ECheckBoxState::Checked); + ApplyFilter(); + ApplySort(); + if (ListView.IsValid()) { ListView->RequestListRefresh(); } + if (SummaryText.IsValid()) { SummaryText->SetText(BuildSummaryText()); } +} + +void SELTEditorAuditWidget::OnLanguageSelected(FLanguagePtr Item, ESelectInfo::Type SelectInfo) +{ + if (Item.IsValid() == false) { return; } + + SelectedLanguage = Item; + FInternationalization::Get().SetCurrentLanguage(*Item); + + // Reaudit the same assets so LocalizedString values reflect the new language. + const TArray Results = UELTEditorAuditor::RunAudit(LastAuditedAssets); + Refresh(Results); +} + +TSharedRef SELTEditorAuditWidget::OnGenerateLanguageComboRow(FLanguagePtr Item) +{ + return SNew(STextBlock) + .Text(FText::FromString(Item.IsValid() ? *Item : TEXT(""))) + .Margin(FMargin(4.f, 2.f)); +} + +void SELTEditorAuditWidget::ApplyDetailColumnVisibility() +{ + if (AuditHeaderRow.IsValid() == false) { return; } + +#if (ENGINE_MAJOR_VERSION >= 5) + for (const FName& Col : GetDetailColumns()) + { + AuditHeaderRow->SetShowGeneratedColumn(Col, bShowMoreDetails); + } +#endif + // SetShowGeneratedColumn is not available in UE4 — detail columns are always visible there. +} + +void SELTEditorAuditWidget::OnShowMoreDetailsChanged(ECheckBoxState NewState) +{ + bShowMoreDetails = (NewState == ECheckBoxState::Checked); + ApplyDetailColumnVisibility(); +} + +FReply SELTEditorAuditWidget::OnRefreshAuditClicked() +{ + const TArray Results = UELTEditorAuditor::RunAudit(LastAuditedAssets); + bPendingCompletionDialog = true; + Refresh(Results); + return FReply::Handled(); +} + +FReply SELTEditorAuditWidget::OnReimportCSVClicked() +{ + // GenerateLocFilesImpl calls LoadPackage synchronously. If async loading is already in process, subsequent loads trigger an assertion. + if (IsAsyncLoading()) + { + UE_LOG(ELTAuditWidgetLog, Warning, TEXT("Reimport CSV skipped — async loading is in progress. Please wait a moment and try again.")); + return FReply::Handled(); + } + + UELTEditorAuditWidget::OnReimportCSVDelegate.ExecuteIfBound(); + return FReply::Handled(); +} + +FText SELTEditorAuditWidget::PickRandomTip() const +{ + static const TArray Tips = { + TEXT("Copy to Clipboard by Left-Clicking audit table cells. Useful for copying Values to input on a separate localization sheet."), + TEXT("Sort the audit table content by clicking the column headers."), + }; + + const int32 Index = FMath::RandRange(0, Tips.Num() - 1); + return FText::FromString(FString::Printf(TEXT("Tip: %s"), *Tips[Index])); +} + +void SELTEditorAuditWidget::Construct(const FArguments& InArgs) +{ + RebuildAuditData(InArgs._AuditResults); + + const TArray Langs = UELTSettings::GetAvailableLanguages(); + for (const FString& Lang : Langs) + { + AvailableLanguages.Add(MakeShared(Lang)); + } + + // Default current language, fallback to the first available. + const FString CurrentLang = FInternationalization::Get().GetCurrentLanguage()->GetName(); + for (const FLanguagePtr& LangPtr : AvailableLanguages) + { + if (LangPtr.IsValid() && *LangPtr == CurrentLang) + { + SelectedLanguage = LangPtr; + break; + } + } + if (SelectedLanguage.IsValid() == false && AvailableLanguages.Num() > 0) + { + SelectedLanguage = AvailableLanguages[0]; + } + + // Set sort state before building the header so the attribute delegate returns + SortColumn = ELTAuditCol::AssetName; + SortMode = EColumnSortMode::Ascending; + + SAssignNew(AuditHeaderRow, SHeaderRow) + + + SHeaderRow::Column(ELTAuditCol::AssetName) + .DefaultLabel(FText::FromString(TEXT("Asset Name"))) + .FillWidth(0.11f) + .SortMode(this, &SELTEditorAuditWidget::GetSortModeForColumn, ELTAuditCol::AssetName) + .OnSort(this, &SELTEditorAuditWidget::OnSortColumn) + + + SHeaderRow::Column(ELTAuditCol::Type) + .DefaultLabel(FText::FromString(TEXT("Type"))) + .FillWidth(0.10f) + .SortMode(this, &SELTEditorAuditWidget::GetSortModeForColumn, ELTAuditCol::Type) + .OnSort(this, &SELTEditorAuditWidget::OnSortColumn) + + + SHeaderRow::Column(ELTAuditCol::VariableNode) + .DefaultLabel(FText::FromString(TEXT("Variable/Node Name"))) + .FillWidth(0.13f) + .SortMode(this, &SELTEditorAuditWidget::GetSortModeForColumn, ELTAuditCol::VariableNode) + .OnSort(this, &SELTEditorAuditWidget::OnSortColumn) + + + SHeaderRow::Column(ELTAuditCol::Issue) + .DefaultLabel(FText::FromString(TEXT("Issue"))) + .FillWidth(0.12f) + .SortMode(this, &SELTEditorAuditWidget::GetSortModeForColumn, ELTAuditCol::Issue) + .OnSort(this, &SELTEditorAuditWidget::OnSortColumn) + + + SHeaderRow::Column(ELTAuditCol::QuickAction) + .DefaultLabel(FText::FromString(TEXT("Quick Action"))) + .FixedWidth(110.f) + + + SHeaderRow::Column(ELTAuditCol::LocalizedString) + .DefaultLabel(FText::FromString(TEXT("Localized String"))) + .FillWidth(0.13f) + .SortMode(this, &SELTEditorAuditWidget::GetSortModeForColumn, ELTAuditCol::LocalizedString) + .OnSort(this, &SELTEditorAuditWidget::OnSortColumn) + + + SHeaderRow::Column(ELTAuditCol::Value) + .DefaultLabel(FText::FromString(TEXT("Value"))) + .FillWidth(0.13f) + .SortMode(this, &SELTEditorAuditWidget::GetSortModeForColumn, ELTAuditCol::Value) + .OnSort(this, &SELTEditorAuditWidget::OnSortColumn) + + + SHeaderRow::Column(ELTAuditCol::Key) + .DefaultLabel(FText::FromString(TEXT("Key"))) + .FillWidth(0.09f) + .SortMode(this, &SELTEditorAuditWidget::GetSortModeForColumn, ELTAuditCol::Key) + .OnSort(this, &SELTEditorAuditWidget::OnSortColumn) + + + SHeaderRow::Column(ELTAuditCol::Namespace) + .DefaultLabel(FText::FromString(TEXT("Namespace"))) + .FillWidth(0.10f) + .SortMode(this, &SELTEditorAuditWidget::GetSortModeForColumn, ELTAuditCol::Namespace) + .OnSort(this, &SELTEditorAuditWidget::OnSortColumn) + + + SHeaderRow::Column(ELTAuditCol::IsUsingStringTable) + .DefaultLabel(FText::FromString(TEXT("Is Using String Table"))) + .FillWidth(0.09f) + .SortMode(this, &SELTEditorAuditWidget::GetSortModeForColumn, ELTAuditCol::IsUsingStringTable) + .OnSort(this, &SELTEditorAuditWidget::OnSortColumn); + + SAssignNew(ListView, SListView) + .ListItemsSource(&FlatIssues) + .OnGenerateRow(this, &SELTEditorAuditWidget::OnGenerateIssueRow) + .HeaderRow(AuditHeaderRow.ToSharedRef()) + .SelectionMode(ESelectionMode::Single); + + ApplyFilter(); + ApplySort(); + ApplyDetailColumnVisibility(); + + ChildSlot + [ + SNew(SVerticalBox) + + + SVerticalBox::Slot() + .AutoHeight() + .Padding(8.f, 8.f, 8.f, 4.f) + [ + SNew(SHorizontalBox) + + + SHorizontalBox::Slot() + .VAlign(VAlign_Center) + .FillWidth(1.f) + [ + SNew(STextBlock) + .Text(FText::FromString(TEXT("Localization Audit"))) + .TextStyle(ELT_APP_STYLE, "LargeText") + ] + + + SHorizontalBox::Slot() + .VAlign(VAlign_Center) + .AutoWidth() + .Padding(0.f, 0.f, 12.f, 0.f) + [ + SNew(SCheckBox) + .IsChecked(ECheckBoxState::Unchecked) + .OnCheckStateChanged(this, &SELTEditorAuditWidget::OnFilterIssuesChanged) + .ToolTipText(FText::FromString(TEXT("When checked, FText entries that passed the audit are hidden"))) + [ + SNew(STextBlock).Text(FText::FromString(TEXT("Hide Valid Localization"))) + ] + ] + + + SHorizontalBox::Slot() + .VAlign(VAlign_Center) + .AutoWidth() + .Padding(0.f, 0.f, 12.f, 0.f) + [ + SNew(SCheckBox) + .IsChecked(ECheckBoxState::Unchecked) + .OnCheckStateChanged(this, &SELTEditorAuditWidget::OnHideEmptyChanged) + .ToolTipText(FText::FromString(TEXT("When checked, FText fields with no value set are hidden"))) + [ + SNew(STextBlock).Text(FText::FromString(TEXT("Hide Empty"))) + ] + ] + + + SHorizontalBox::Slot() + .VAlign(VAlign_Center) + .AutoWidth() + .Padding(0.f, 0.f, 12.f, 0.f) + [ + SNew(SCheckBox) + .IsChecked(ECheckBoxState::Checked) + .OnCheckStateChanged(this, &SELTEditorAuditWidget::OnShowMoreDetailsChanged) + .ToolTipText(FText::FromString(TEXT("When checked, additional detail columns are shown (Localized String, Value, Key, Namespace, Is Using String Table)"))) + [ + SNew(STextBlock).Text(FText::FromString(TEXT("Show More Details"))) + ] + ] + + + SHorizontalBox::Slot() + .VAlign(VAlign_Center) + .AutoWidth() + .Padding(0.f, 0.f, 8.f, 0.f) + [ + SAssignNew(LanguageComboBox, SComboBox) + .OptionsSource(&AvailableLanguages) + .InitiallySelectedItem(SelectedLanguage) + .OnSelectionChanged(this, &SELTEditorAuditWidget::OnLanguageSelected) + .OnGenerateWidget(this, &SELTEditorAuditWidget::OnGenerateLanguageComboRow) + .ToolTipText(FText::FromString(TEXT("Preview language for Localized String column"))) + [ + SNew(STextBlock) + .Text_Lambda([this]() + { + return FText::FromString(SelectedLanguage.IsValid() ? *SelectedLanguage : TEXT("")); + }) + ] + ] + + + SHorizontalBox::Slot() + .VAlign(VAlign_Center) + .AutoWidth() + .Padding(0.f, 0.f, 8.f, 0.f) + [ + SNew(SButton) + .Text(FText::FromString(TEXT("Reaudit Assets"))) + .ToolTipText(FText::FromString(TEXT("Re-run the audit on all previously audited assets"))) + .OnClicked(this, &SELTEditorAuditWidget::OnRefreshAuditClicked) + ] + + + SHorizontalBox::Slot() + .VAlign(VAlign_Center) + .AutoWidth() + [ + SNew(SButton) + .Text(FText::FromString(TEXT("Reimport CSV"))) + .ToolTipText(FText::FromString(TEXT("Reimport CSVs defined within the Easy Localization Tool."))) + .OnClicked(this, &SELTEditorAuditWidget::OnReimportCSVClicked) + ] + ] + + + SVerticalBox::Slot() + .AutoHeight() + .Padding(8.f, 0.f, 8.f, 6.f) + [ + SNew(SBorder) + .BorderImage(ELT_GET_BRUSH("ToolPanel.GroupBorder")) + .Padding(FMargin(8.f, 4.f)) + [ + SAssignNew(SummaryText, STextBlock) + .Text(BuildSummaryText()) + .TextStyle(ELT_APP_STYLE, "NormalText.Important") + ] + ] + + + SVerticalBox::Slot() + .FillHeight(1.f) + .Padding(8.f, 0.f, 8.f, 4.f) + [ + SNew(SBorder) + .BorderImage(ELT_GET_BRUSH("ToolPanel.GroupBorder")) + [ + ListView.ToSharedRef() + ] + ] + + + SVerticalBox::Slot() + .AutoHeight() + .Padding(8.f, 0.f, 8.f, 8.f) + [ + SAssignNew(TipText, STextBlock) + .Text(PickRandomTip()) + .ColorAndOpacity(ELTAuditColor::TipText) + ] + ]; + + // Fire the completion dialog now that the widget is fully constructed. + if (UELTEditorAuditWidget::bPendingDialogOnSpawn) + { + UELTEditorAuditWidget::bPendingDialogOnSpawn = false; + UELTEditorAuditWidget::ShowCompletionDialog(InArgs._AuditResults); + } +} + +void SELTEditorAuditWidget::Refresh(const TArray& InResults) +{ + RebuildAuditData(InResults); + ApplyFilter(); + ApplySort(); + + if (ListView.IsValid()) { ListView->RequestListRefresh(); } + if (SummaryText.IsValid()) { SummaryText->SetText(BuildSummaryText()); } + if (TipText.IsValid()) { TipText->SetText(PickRandomTip()); } + + if (bPendingCompletionDialog) + { + bPendingCompletionDialog = false; + UELTEditorAuditWidget::ShowCompletionDialog(InResults); + } +} + +void SELTEditorAuditWidget::RefreshLanguages(const TArray& Languages) +{ + AvailableLanguages.Reset(); + for (const FString& Lang : Languages) + { + AvailableLanguages.Add(MakeShared(Lang)); + } + + // Preserve the current selection if it still exists in the new list, otherwise fall back to the first entry. + bool bSelectionStillValid = false; + if (SelectedLanguage.IsValid()) + { + for (const FLanguagePtr& LangPtr : AvailableLanguages) + { + if (LangPtr.IsValid() && *LangPtr == *SelectedLanguage) + { + SelectedLanguage = LangPtr; + bSelectionStillValid = true; + break; + } + } + } + + if (bSelectionStillValid == false && AvailableLanguages.Num() > 0) + { + SelectedLanguage = AvailableLanguages[0]; + } + + if (LanguageComboBox.IsValid()) + { + LanguageComboBox->RefreshOptions(); + LanguageComboBox->SetSelectedItem(SelectedLanguage); + } +} + +TSharedRef SELTEditorAuditWidget::OnGenerateIssueRow( + FIssuePtr Issue, + const TSharedRef& OwnerTable) +{ + FAssetData RowAsset; + if (Issue.IsValid()) + { + if (const FAssetData* Found = AssetDataMap.Find(Issue->AssetName)) + { + RowAsset = *Found; + } + } + + return SNew(SELTAuditIssueRow, OwnerTable) + .Issue(Issue) + .AssetData(RowAsset); +} + +/*static*/ void SELTEditorAuditWidget::JumpToIssue( + const FAssetData& AssetData, + const FELTAuditIssue& Issue) +{ + UObject* Asset = AssetData.GetAsset(); + if (Asset == nullptr) { return; } + + UAssetEditorSubsystem* AssetEditorSS = GEditor->GetEditorSubsystem(); + + if (Issue.Type == EELTAuditParameterType::ClassVariable || + Issue.Type == EELTAuditParameterType::WidgetComponent) + { + AssetEditorSS->OpenEditorForAsset(Asset); + return; + } + + UBlueprint* Blueprint = Cast(Asset); + if (Blueprint == nullptr) + { + AssetEditorSS->OpenEditorForAsset(Asset); + return; + } + + if (Issue.Type == EELTAuditParameterType::FunctionVariable && Issue.GraphName.IsEmpty() == false) + { + for (UEdGraph* Graph : Blueprint->FunctionGraphs) + { + if (Graph != nullptr && Graph->GetName() == Issue.GraphName) + { + FKismetEditorUtilities::BringKismetToFocusAttentionOnObject(Graph); + return; + } + } + FKismetEditorUtilities::BringKismetToFocusAttentionOnObject(Blueprint); + return; + } + + if (Issue.Type == EELTAuditParameterType::NodeParameter && Issue.NodeGuid.IsValid()) + { + TArray AllGraphs; + Blueprint->GetAllGraphs(AllGraphs); + + for (UEdGraph* Graph : AllGraphs) + { + if (Graph == nullptr) { continue; } + for (UEdGraphNode* Node : Graph->Nodes) + { + if (Node != nullptr && Node->NodeGuid == Issue.NodeGuid) + { + FKismetEditorUtilities::BringKismetToFocusAttentionOnObject(Node); + return; + } + } + } + + FKismetEditorUtilities::BringKismetToFocusAttentionOnObject(Blueprint); + } +} \ No newline at end of file diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditor.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditor.cpp new file mode 100644 index 0000000..de4078c --- /dev/null +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditor.cpp @@ -0,0 +1,484 @@ +// Copyright (c) 2026 Damian Nowakowski. All rights reserved. + +#include "ELTEditorAuditor.h" +#include "ELTBlueprintLibrary.h" +#include "ELTEditorAuditWidget.h" + +#include "EditorUtilityLibrary.h" + +#include "AssetRegistry/AssetRegistryModule.h" +#include "Engine/AssetManager.h" + +#include "Internationalization/StringTableCore.h" +#include "Internationalization/StringTableRegistry.h" +#include "Internationalization/TextKey.h" +#include "Runtime/Launch/Resources/Version.h" + +#include "Engine/Blueprint.h" +#include "StructUtils/UserDefinedStruct.h" +#include "EdGraph/EdGraph.h" +#include "EdGraph/EdGraphNode.h" +#include "EdGraph/EdGraphPin.h" +#include "K2Node_FunctionEntry.h" +#include "WidgetBlueprint.h" +#include "Blueprint/WidgetTree.h" +#include "Components/Widget.h" + +DEFINE_LOG_CATEGORY_STATIC(ELTAuditLog, Log, All); + +namespace ELTAuditInternal +{ + static FString NodeDisplayName(const UEdGraphNode* Node) + { + return Node->GetNodeTitle(ENodeTitleType::ListView).ToString(); + } +} + +/*static*/ void UELTEditorAuditor::AuditText( + const FText& InText, + EELTAuditParameterType ParameterType, + const FString& VariableNodeName, + const FGuid& NodeGuid, + const FString& GraphName, + FELTAssetAuditResult& OutResult) +{ + // Skip if localized is set to false + if (InText.IsCultureInvariant()) + { + return; + } + + FString Package, Namespace, Key, Source; + UELTBlueprintLibrary::GetTextData(InText, Package, Namespace, Key, Source); + + auto AddIssue = [&](EELTAuditIssueType IssueType, FString LocalizedString = TEXT(""), bool bIsUsingStringTable = false) + { + FELTAuditIssue& Row = OutResult.Issues.Emplace_GetRef(); + Row.AssetName = OutResult.AssetData.AssetName.ToString(); + Row.Type = ParameterType; + Row.VariableNodeName = VariableNodeName; + Row.Issue = IssueType; + Row.Value = Source; + Row.LocalizedString = MoveTemp(LocalizedString); + Row.Key = Key; + Row.Namespace = Namespace; + Row.bIsUsingStringTable = bIsUsingStringTable; + Row.NodeGuid = NodeGuid; + Row.GraphName = GraphName; + }; + + if (InText.IsEmpty()) + { + AddIssue(EELTAuditIssueType::EmptyValue); + return; + } + + // Check for a broken String Table reference before valid localization check + FName TableId; + FString TableKey; + if (FTextInspector::GetTableIdAndKey(InText, TableId, TableKey)) + { + Key = TableKey; + Namespace = TableId.ToString(); + + FStringTableConstPtr Table = FStringTableRegistry::Get().FindStringTable(TableId); + bool bKeyValid = Table.IsValid() && Table->FindEntry(TableKey).IsValid(); + if (bKeyValid == false) + { + AddIssue(EELTAuditIssueType::StringTableMissingKey, TEXT(""), true); + } + else + { + AddIssue(EELTAuditIssueType::None, InText.ToString(), true); + } + return; + } + + // We assume key missing or key-value mismatched means the text was never set up to fetch localization strings via ELT + if (Key.IsEmpty() || Key.Equals(Source, ESearchCase::CaseSensitive) == false) + { + AddIssue(EELTAuditIssueType::NotYetLocalized); + return; + } + + FText FoundText; + bool bFoundInTable; + +#if ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 5)) + bFoundInTable = FText::FindTextInLiveTable_Advanced(*Namespace, *Key, FoundText, &Source); +#else + bFoundInTable = FText::FindText(*Namespace, *Key, FoundText, &Source); +#endif + + if (bFoundInTable) + { + AddIssue(EELTAuditIssueType::None, FoundText.ToString()); + } + else + { + AddIssue(EELTAuditIssueType::InvalidLocalization); + } +} + +/*static*/ void UELTEditorAuditor::AuditClassProperties( + void* ContainerPtr, + UStruct* Struct, + const FString& PathPrefix, + FELTAssetAuditResult& OutResult) +{ + for (TFieldIterator It(Struct, EFieldIteratorFlags::IncludeSuper); It; ++It) + { + FProperty* Prop = *It; + + const FString PropName = Cast(Struct) + ? Prop->GetAuthoredName() + : Prop->GetName(); + + const FString CurrentPath = PathPrefix.IsEmpty() ? PropName : PathPrefix + TEXT(".") + PropName; + + if (const FTextProperty* TextProp = CastField(Prop)) + { + AuditText(TextProp->GetPropertyValue_InContainer(ContainerPtr), + EELTAuditParameterType::ClassVariable, CurrentPath, FGuid(), TEXT(""), OutResult); + } + else if (const FStructProperty* StructProp = CastField(Prop)) + { + AuditClassProperties(StructProp->ContainerPtrToValuePtr(ContainerPtr), StructProp->Struct, CurrentPath, OutResult); + } + else if (const FArrayProperty* ArrayProp = CastField(Prop)) + { + FScriptArrayHelper ArrayHelper(ArrayProp, ArrayProp->ContainerPtrToValuePtr(ContainerPtr)); + for (int32 i = 0; i < ArrayHelper.Num(); i++) + { + const FString ElemPath = FString::Printf(TEXT("%s[%d]"), *CurrentPath, i); + void* ElemPtr = ArrayHelper.GetRawPtr(i); + + if (const FTextProperty* InnerText = CastField(ArrayProp->Inner)) + { + AuditText(InnerText->GetPropertyValue(ElemPtr), + EELTAuditParameterType::ClassVariable, ElemPath, FGuid(), TEXT(""), OutResult); + } + else if (const FStructProperty* InnerStruct = CastField(ArrayProp->Inner)) + { + AuditClassProperties(ElemPtr, InnerStruct->Struct, ElemPath, OutResult); + } + } + } + else if (const FMapProperty* MapProp = CastField(Prop)) + { + FScriptMapHelper MapHelper(MapProp, MapProp->ContainerPtrToValuePtr(ContainerPtr)); + for (int32 i = 0; i < MapHelper.GetMaxIndex(); i++) + { + if (MapHelper.IsValidIndex(i) == false) { continue; } + + const FString ElemPath = FString::Printf(TEXT("%s[%d].Value"), *CurrentPath, i); + void* ValPtr = MapHelper.GetValuePtr(i); + + if (const FTextProperty* ValText = CastField(MapProp->ValueProp)) + { + AuditText(ValText->GetPropertyValue(ValPtr), + EELTAuditParameterType::ClassVariable, ElemPath, FGuid(), TEXT(""), OutResult); + } + else if (const FStructProperty* ValStruct = CastField(MapProp->ValueProp)) + { + AuditClassProperties(ValPtr, ValStruct->Struct, ElemPath, OutResult); + } + } + } + } +} + +/*static*/ void UELTEditorAuditor::AuditBlueprintTextSources( + UBlueprint* Blueprint, + FELTAssetAuditResult& OutResult) +{ + if (Blueprint == nullptr) + { + return; + } + + TArray AllGraphs; + Blueprint->GetAllGraphs(AllGraphs); + + for (UEdGraph* Graph : AllGraphs) + { + if (Graph == nullptr) { continue; } + + const FString GraphName = Graph->GetName(); + + for (UEdGraphNode* Node : Graph->Nodes) + { + if (Node == nullptr) { continue; } + + if (UK2Node_FunctionEntry* EntryNode = Cast(Node)) + { + // Local variables are stored on the entry node + for (const FBPVariableDescription& LocalVar : EntryNode->LocalVariables) + { + if (LocalVar.VarType.PinCategory != UEdGraphSchema_K2::PC_Text) { continue; } + + FText DefaultText; + if (FTextStringHelper::ReadFromBuffer(*LocalVar.DefaultValue, DefaultText) && DefaultText.IsEmpty() == false) + { + AuditText(DefaultText, EELTAuditParameterType::FunctionVariable, + FString::Printf(TEXT("%s::%s"), *GraphName, *LocalVar.VarName.ToString()), + EntryNode->NodeGuid, GraphName, OutResult); + } + } + + // Parameter pins default values + for (UEdGraphPin* Pin : EntryNode->Pins) + { + if (Pin == nullptr || Pin->PinType.PinCategory != UEdGraphSchema_K2::PC_Text) { continue; } + if (Pin->DefaultTextValue.IsEmpty()) { continue; } + + AuditText(Pin->DefaultTextValue, EELTAuditParameterType::FunctionVariable, + FString::Printf(TEXT("%s::%s"), *GraphName, *Pin->PinName.ToString()), + EntryNode->NodeGuid, GraphName, OutResult); + } + + continue; + } + + // All other nodes: unconnected literal FText input pins. + for (UEdGraphPin* Pin : Node->Pins) + { + if (Pin == nullptr) { continue; } + if (Pin->Direction != EGPD_Input) { continue; } + if (Pin->PinType.PinCategory != UEdGraphSchema_K2::PC_Text) { continue; } + if (Pin->LinkedTo.Num() > 0) { continue; } + if (Pin->DefaultTextValue.IsEmpty()) { continue; } + + AuditText(Pin->DefaultTextValue, EELTAuditParameterType::NodeParameter, + ELTAuditInternal::NodeDisplayName(Node), Node->NodeGuid, GraphName, OutResult); + } + } + } +} + +/*static*/ void UELTEditorAuditor::AuditSingleAsset( + UObject* Asset, + const FAssetData& AssetData, + FELTAssetAuditResult& OutResult) +{ + OutResult.AssetData = AssetData; + + if (UBlueprint* Blueprint = Cast(Asset)) + { + // Covers function locals, parameter pins, and nodes. + AuditBlueprintTextSources(Blueprint, OutResult); + + // Covers UMG components. + if (UWidgetBlueprint* WidgetBlueprint = Cast(Blueprint)) + { + AuditWidgetComponents(WidgetBlueprint, OutResult); + } + + // Covers CDO + // (Note: Class Properties will not suffice for Blueprint Assets) + UObject* CDO = Blueprint->GeneratedClass ? Blueprint->GeneratedClass->GetDefaultObject(false) : nullptr; + if (CDO != nullptr) + { + for (const FBPVariableDescription& Var : Blueprint->NewVariables) + { + if (Var.VarType.PinCategory != UEdGraphSchema_K2::PC_Text) { continue; } + + FProperty* Prop = Blueprint->GeneratedClass->FindPropertyByName(Var.VarName); + if (const FTextProperty* TextProp = CastField(Prop)) + { + const FText& Val = TextProp->GetPropertyValue_InContainer(CDO); + AuditText(Val, EELTAuditParameterType::ClassVariable, + Var.VarName.ToString(), FGuid(), TEXT(""), OutResult); + } + } + } + } + else if (UUserDefinedStruct* UserStruct = Cast(Asset)) + { + if (const uint8* DefaultInstance = UserStruct->GetDefaultInstance()) + { + AuditClassProperties( + const_cast(DefaultInstance), + UserStruct, + TEXT(""), + OutResult); + } + } + else + { + // Non-Blueprint Asset, Audit Class Defaults + AuditClassProperties(Asset, Asset->GetClass(), TEXT(""), OutResult); + } +} + +/*static*/ void UELTEditorAuditor::AuditWidgetComponents( + UWidgetBlueprint* WidgetBlueprint, + FELTAssetAuditResult& OutResult) +{ + if (WidgetBlueprint == nullptr || WidgetBlueprint->WidgetTree == nullptr) + { + return; + } + + WidgetBlueprint->WidgetTree->ForEachWidget([&](UWidget* Widget) + { + if (Widget == nullptr) { return; } + + const FString ComponentName = Widget->GetName(); + + for (TFieldIterator PropIt(Widget->GetClass(), EFieldIteratorFlags::IncludeSuper); PropIt; ++PropIt) + { + const FTextProperty* TextProp = *PropIt; + const FName PropName = TextProp->GetFName(); + + // ToolTipText is intentionally empty on most widgets, skip if unset. + if (PropName == FName("ToolTipText")) + { + const FText& Val = TextProp->GetPropertyValue_InContainer(Widget); + if (Val.IsEmpty() == false) + { + AuditText(Val, EELTAuditParameterType::WidgetComponent, + FString::Printf(TEXT("%s.ToolTipText"), *ComponentName), FGuid(), TEXT(""), OutResult); + } + continue; + } + + // Accessible text fields are only relevant if set to override them with custom accessibility. + if (PropName == FName("AccessibleText") || PropName == FName("AccessibleSummaryText")) + { +#if (ENGINE_MAJOR_VERSION >= 5) + if (Widget->bOverrideAccessibleDefaults == false) { continue; } + + const bool bIsAccessible = (PropName == FName("AccessibleText")) && (Widget->AccessibleBehavior == ESlateAccessibleBehavior::Custom); + const bool bIsSummaryAccessible = (PropName == FName("AccessibleSummaryText")) && (Widget->AccessibleSummaryBehavior == ESlateAccessibleBehavior::Custom); + + if (bIsAccessible == false && bIsSummaryAccessible == false) { continue; } +#else + // Accessible override fields not supported in UE4 — skip entirely. + continue; +#endif + } + + // CommonUI internal classification hidden field — not a localizable text value. + if (PropName == FName("PaletteCategory")) { continue; } + + const FText& Val = TextProp->GetPropertyValue_InContainer(Widget); + AuditText(Val, EELTAuditParameterType::WidgetComponent, + FString::Printf(TEXT("%s.%s"), *ComponentName, *PropName.ToString()), FGuid(), TEXT(""), OutResult); + } + }); +} + +TSharedPtr UELTEditorAuditor::PendingLoadHandle; + +/*static*/ TArray UELTEditorAuditor::RunAudit(const TArray& Assets) +{ + TArray Results; + + for (const FAssetData& AssetData : Assets) + { + UObject* Asset = AssetData.GetAsset(); + if (Asset == nullptr) { continue; } + + FELTAssetAuditResult& Result = Results.Emplace_GetRef(); + AuditSingleAsset(Asset, AssetData, Result); + } + + UE_LOG(ELTAuditLog, Log, TEXT("Localization audit complete. %d asset(s) scanned."), Assets.Num()); + return Results; +} + +static void RunAuditAndShow(const TArray& Assets) +{ + const TArray Results = UELTEditorAuditor::RunAudit(Assets); + UELTEditorAuditWidget::ShowResults(Results); +} + +static void RequestLoadThenAudit(const TArray& Assets) +{ + // Cancel any in-progress load — the new request supersedes it. + if (UELTEditorAuditor::PendingLoadHandle.IsValid()) + { + UELTEditorAuditor::PendingLoadHandle->CancelHandle(); + UELTEditorAuditor::PendingLoadHandle.Reset(); + } + + TArray Unloaded; + for (const FAssetData& AssetData : Assets) + { + if (AssetData.IsAssetLoaded() == false) + { + Unloaded.Add(AssetData); + } + } + + if (Unloaded.IsEmpty()) + { + RunAuditAndShow(Assets); + return; + } + + // Build soft object paths for all unloaded assets and request an async load. + // PendingLoadHandle keeps the request alive until the callback fires. + TArray PathsToLoad; + for (const FAssetData& AssetData : Unloaded) + { + PathsToLoad.Add(AssetData.ToSoftObjectPath()); + } + + UE_LOG(ELTAuditLog, Log, TEXT("Waiting for %d asset(s) to load before auditing..."), Unloaded.Num()); + + UELTEditorAuditor::PendingLoadHandle = UAssetManager::GetStreamableManager().RequestAsyncLoad( + PathsToLoad, + FStreamableDelegate::CreateLambda([Assets]() + { + UELTEditorAuditor::PendingLoadHandle.Reset(); + RunAuditAndShow(Assets); + }) + ); +} + +void UELTEditorAuditor::AuditSelectedAssets() +{ + TArray Assets = UEditorUtilityLibrary::GetSelectedAssetData(); + +#if (ENGINE_MAJOR_VERSION >= 5) + const TArray SelectedPaths = UEditorUtilityLibrary::GetSelectedFolderPaths(); + if (SelectedPaths.Num() > 0) + { + FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")); + IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); + + FARFilter Filter; + Filter.bRecursivePaths = true; + for (const FString& Path : SelectedPaths) + { + FString PackagePath = Path; + const FString AllPrefix = TEXT("/All"); + if (PackagePath.StartsWith(AllPrefix)) + { + PackagePath = PackagePath.RightChop(AllPrefix.Len()); + } + Filter.PackagePaths.Add(FName(*PackagePath)); + } + + TArray FolderAssets; + AssetRegistry.GetAssets(Filter, FolderAssets); + + for (const FAssetData& FolderAsset : FolderAssets) + { + Assets.AddUnique(FolderAsset); + } + } +#endif + + // Nothing selected — do nothing rather than opening an empty audit. + if (Assets.IsEmpty()) { return; } + + RequestLoadThenAudit(Assets); +} + +void UELTEditorAuditor::AuditAssets(const TArray& Assets) +{ + RequestLoadThenAudit(Assets); +} \ No newline at end of file diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditorCommands.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditorCommands.cpp index 0d71b8c..8f026e2 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTEditorCommands.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditorCommands.cpp @@ -22,6 +22,7 @@ void FELTEditorCommands::RegisterCommands() { #define LOCTEXT_NAMESPACE "ELTLoc" UI_COMMAND(OpenELTMenu, "Easy Localization Tool", "Opens Easy Localisation Tool Editor Window", EUserInterfaceActionType::Check, FInputChord(EModifierKey::Shift | EModifierKey::Alt, EKeys::L)); + UI_COMMAND(RunELTAudit, "Audit Localizations", "Audit selected assets if content browser is focused, otherwise audit focused editor window if it is an asset.", EUserInterfaceActionType::Check, FInputChord(EModifierKey::Control | EModifierKey::Alt, EKeys::L)); #undef LOCTEXT_NAMESPACE } diff --git a/Source/EasyLocalizationToolEditor/Private/EasyLocalizationToolEditorModule.cpp b/Source/EasyLocalizationToolEditor/Private/EasyLocalizationToolEditorModule.cpp index 134a5ef..d7b147f 100644 --- a/Source/EasyLocalizationToolEditor/Private/EasyLocalizationToolEditorModule.cpp +++ b/Source/EasyLocalizationToolEditor/Private/EasyLocalizationToolEditorModule.cpp @@ -14,10 +14,19 @@ #include "PropertyEditorModule.h" #include "LevelEditor.h" -#include "BlueprintEditorModule.h" +#include "ContentBrowserModule.h" +#include "ContentBrowserDelegates.h" +#include "IContentBrowserSingleton.h" +#include "AssetRegistry/AssetRegistryModule.h" +#include "ELTEditorAuditor.h" +#include "Subsystems/AssetEditorSubsystem.h" +#include "Toolkits/AssetEditorToolkit.h" +#include "Editor.h" #if ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 4)) #include "ToolMenu.h" +#include "Toolkits/AssetEditorToolkitMenuContext.h" +#include "Toolkits/AssetEditorToolkit.h" #endif IMPLEMENT_MODULE(FEasyLocalizationToolEditorModule, EasyLocalizationToolEditor) @@ -61,6 +70,105 @@ void FEasyLocalizationToolEditorModule::StartupModule() GraphPanelPinFactory = MakeShared(); FEdGraphUtilities::RegisterVisualPinFactory(GraphPanelPinFactory); #endif + + // Register the Localization Audit action in the Content Browser context menu. + FContentBrowserMenuExtender_SelectedAssets AuditExtender = FContentBrowserMenuExtender_SelectedAssets::CreateLambda( + [](const TArray& SelectedAssets) -> TSharedRef + { + TSharedRef Extender = MakeShared(); + Extender->AddMenuExtension( + "CommonAssetActions", + EExtensionHook::After, + nullptr, + FMenuExtensionDelegate::CreateLambda([](FMenuBuilder& MenuBuilder) + { + MenuBuilder.BeginSection("ELTLocalizationAudit", FText::FromString("Easy Localization Tool")); + MenuBuilder.AddMenuEntry( + FText::FromString("Localization Audit"), + FText::FromString("\ +Scans asset(s) for all FText properties marked to be localize, and returns them in a list.\n\n\ +They are tested for the following issues:\n\ +1. Empty Text Value\n\ +2. Invalid String Table Key Reference\n\ +3. Not Yet Localized (Value and Localization Key do not match)\n\ +4. Invalid Localization (Value and Localization Key matches, but does not return a valid localization string)"), + FSlateIcon(), + FUIAction(FExecuteAction::CreateLambda([]() + { + GetMutableDefault()->AuditSelectedAssets(); + })) + ); + MenuBuilder.EndSection(); + }) + ); + return Extender; + } + ); + ContentBrowserExtenderHandle = AuditExtender.GetHandle(); + FModuleManager::LoadModuleChecked(TEXT("ContentBrowser")) + .GetAllAssetViewContextMenuExtenders().Add(MoveTemp(AuditExtender)); + + FContentBrowserMenuExtender_SelectedPaths FolderAuditExtender = FContentBrowserMenuExtender_SelectedPaths::CreateLambda( + [](const TArray& SelectedPaths) -> TSharedRef + { + TSharedRef Extender = MakeShared(); + Extender->AddMenuExtension( + "PathViewFolderOptions", + EExtensionHook::After, + nullptr, + FMenuExtensionDelegate::CreateLambda([SelectedPaths](FMenuBuilder& MenuBuilder) + { + MenuBuilder.BeginSection("ELTLocalizationAudit", FText::FromString("Easy Localization Tool")); + MenuBuilder.AddMenuEntry( + FText::FromString("Localization Audit"), + FText::FromString("Scans all assets in the selected folder(s) for FText localization issues."), + FSlateIcon(), + FUIAction(FExecuteAction::CreateLambda([SelectedPaths]() + { + FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")); + IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); + + FARFilter Filter; + Filter.bRecursivePaths = true; + for (const FString& Path : SelectedPaths) + { + // GetAllPathViewContextMenuExtenders also returns /All-prefixed + // virtual paths — strip to get the real package path. + FString PackagePath = Path; + const FString AllPrefix = TEXT("/All"); + if (PackagePath.StartsWith(AllPrefix)) + { + PackagePath = PackagePath.RightChop(AllPrefix.Len()); + } + Filter.PackagePaths.Add(FName(*PackagePath)); + } + + TArray Assets; + AssetRegistry.GetAssets(Filter, Assets); + + // Also include any assets selected in the asset view — the path view + // extender fires when right-clicking a folder regardless of asset selection, + // so we need to merge both selections manually. + TArray SelectedAssets; + FModuleManager::LoadModuleChecked(TEXT("ContentBrowser")) + .Get().GetSelectedAssets(SelectedAssets); + for (const FAssetData& SelectedAsset : SelectedAssets) + { + Assets.AddUnique(SelectedAsset); + } + + GetMutableDefault()->AuditAssets(Assets); + })) + ); + MenuBuilder.EndSection(); + }) + ); + return Extender; + } + ); + PathViewExtenderHandle = FolderAuditExtender.GetHandle(); + FModuleManager::LoadModuleChecked(TEXT("ContentBrowser")) + .GetAllPathViewContextMenuExtenders().Add(MoveTemp(FolderAuditExtender)); } void FEasyLocalizationToolEditorModule::ShutdownModule() @@ -80,6 +188,23 @@ void FEasyLocalizationToolEditorModule::ShutdownModule() PropertyModule.UnregisterCustomClassLayout(UObject::StaticClass()->GetFName()); #endif + // Unregister the Localization Audit content browser extender. + if (FContentBrowserModule* CBModule = FModuleManager::GetModulePtr(TEXT("ContentBrowser"))) + { + CBModule->GetAllAssetViewContextMenuExtenders().RemoveAll( + [this](const FContentBrowserMenuExtender_SelectedAssets& Delegate) + { + return Delegate.GetHandle() == ContentBrowserExtenderHandle; + } + ); + CBModule->GetAllPathViewContextMenuExtenders().RemoveAll( + [this](const FContentBrowserMenuExtender_SelectedPaths& Delegate) + { + return Delegate.GetHandle() == PathViewExtenderHandle; + } + ); + } + // Unregister Tab Spawner FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(ELTTabId); @@ -100,6 +225,82 @@ void FEasyLocalizationToolEditorModule::ShutdownModule() FELTEditorStyle::Shutdown(); } +void FEasyLocalizationToolEditorModule::RunAuditCommand() +{ + if (!FSlateApplication::IsInitialized() || !GEditor) + { + return; + } + + TArray AssetsToAudit; + bool bContentBrowserHasFocus = false; + + // Check if the active window/widget is a Content Browser or Content Drawer + TSharedPtr FocusedWidget = FSlateApplication::Get().GetUserFocusedWidget(0); + if (FocusedWidget.IsValid()) + { + FWidgetPath FocusedWidgetPath; + if (FSlateApplication::Get().GeneratePathToWidgetUnchecked(FocusedWidget.ToSharedRef(), FocusedWidgetPath)) + { + for (int32 i = FocusedWidgetPath.Widgets.Num() - 1; i >= 0; --i) + { + FString WidgetType = FocusedWidgetPath.Widgets[i].Widget->GetTypeAsString(); + + // This catches active standalone content browsers and the pop-up content drawer + if (WidgetType.Contains("SContentBrowser") || WidgetType.Contains("SContentDrawer")) + { + bContentBrowserHasFocus = true; + break; + } + } + } + } + + // If bContentBrowserHasFocus is true, audit selected assets and folders. Does nothing if nothing is selected. + if (bContentBrowserHasFocus) + { + GetMutableDefault()->AuditSelectedAssets(); + return; + } + + // Check if the active window is an asset, audit it if true. + UAssetEditorSubsystem* AssetEditorSubsystem = GEditor->GetEditorSubsystem(); + if (AssetEditorSubsystem == nullptr) + { + return; + } + + // Loop through all opened assets and check if the asset window is current tab. + for (UObject* Asset : AssetEditorSubsystem->GetAllEditedAssets()) + { + IAssetEditorInstance* EditorInstance = AssetEditorSubsystem->FindEditorForAsset(Asset, false); + if (!EditorInstance) + { + continue; + } + + FAssetEditorToolkit* EditorToolkit = static_cast(EditorInstance); + if (!EditorToolkit) + { + continue; + } + + TSharedPtr TabManager = EditorToolkit->GetTabManager(); + if (!TabManager) + { + continue; + } + + TSharedPtr OwnerTab = TabManager->GetOwnerTab(); + if (OwnerTab.IsValid() && OwnerTab->IsForeground()) + { + AssetsToAudit.Add(FAssetData(Asset)); + GetMutableDefault()->AuditAssets(AssetsToAudit); + return; + } + } +} + void FEasyLocalizationToolEditorModule::OnPostEngineInit() { // This function is for registering UICommand to the engine, so it can be executed via keyboard shortcut. @@ -119,6 +320,12 @@ void FEasyLocalizationToolEditorModule::OnPostEngineInit() FIsActionChecked::CreateRaw(this, &FEasyLocalizationToolEditorModule::IsEditorSpawned) ); + // Map the audit shortcut to RunAuditCommand. + Commands->MapAction( + FELTEditorCommands::Get().RunELTAudit, + FExecuteAction::CreateRaw(this, &FEasyLocalizationToolEditorModule::RunAuditCommand) + ); + // Register this UICommandList to the MainFrame. // Otherwise nothing will handle the input to trigger this command. IMainFrameModule& MainFrame = FModuleManager::Get().LoadModuleChecked("MainFrame"); @@ -126,17 +333,35 @@ void FEasyLocalizationToolEditorModule::OnPostEngineInit() #if ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 4)) - // The Menu Extender doesn't work correctly for new menus in UE5.4 as they don't have proper Hook names as they should... - // Attempt to add menu entry with UICommandList of opening ELT Window to the Tools menu. - UToolMenu* Menu = UToolMenus::Get()->FindMenu("LevelEditor.MainMenu.Tools"); - if (Menu) + // Add both the ELT window opener and Localization Audit to the same named section + // under the Tools menu, so they appear grouped as "Easy Localization Tool" entries. + UToolMenu* ToolsMenu = UToolMenus::Get()->ExtendMenu(TEXT("MainFrame.MainMenu.Tools")); + if (ToolsMenu) { - Menu->AddMenuEntry(NAME_None, FToolMenuEntry::InitMenuEntryWithCommandList( - FELTEditorCommands::Get().OpenELTMenu, + FToolMenuSection& Section = ToolsMenu->FindOrAddSection( + "ELTLocalizationAudit", + FText::FromString(TEXT("Easy Localization Tool")) + ); + + Section.AddEntry(FToolMenuEntry::InitMenuEntryWithCommandList( + FELTEditorCommands::Get().OpenELTMenu, Commands, FText::FromString(TEXT("Easy Localization Tool")), FText::FromString(TEXT("Opens Easy Localization Tool Window")), FSlateIcon(FELTEditorStyle::GetStyleSetName(), "ELTEditorStyle.MenuIcon"))); + + Section.AddEntry(FToolMenuEntry::InitMenuEntryWithCommandList( + FELTEditorCommands::Get().RunELTAudit, + Commands, + FText::FromString(TEXT("Localization Audit")), + FText::FromString(TEXT("\ +Scans this asset for all FText properties marked to be localize, and returns them in a list.\n\n\ +They are tested for the following issues:\n\ +1. Empty Text Value\n\ +2. Invalid String Table Key Reference\n\ +3. Not Yet Localized (Value and Localization Key do not match)\n\ +4. Invalid Localization (Value and Localization Key matches, but does not return a valid localization string)")), + FSlateIcon(FELTEditorStyle::GetStyleSetName(), "ELTEditorStyle.MenuIcon"))); } #else // Create a Menu Extender, which adds a button that executes the UICommandList of opening ELT Window. diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditor.h b/Source/EasyLocalizationToolEditor/Public/ELTEditor.h index c8efd8c..ee6e9ae 100644 --- a/Source/EasyLocalizationToolEditor/Public/ELTEditor.h +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditor.h @@ -167,11 +167,23 @@ class EASYLOCALIZATIONTOOLEDITOR_API UELTEditor : public UObject */ void SetLanguagePreview(); + /** + * Controls which UI elements are updated when RefreshAvailableLangs is called. + */ + enum class ERefreshUIFlags : uint8 + { + None = 0, + ToolWidget = 1 << 0, + AuditWidget = 1 << 1, + All = ToolWidget | AuditWidget, + }; + FRIEND_ENUM_CLASS_FLAGS(ERefreshUIFlags); + /** * Refresh the list of available languages based on the files that exists in Localization directory. - * It can optionally RefreshUI. + * UIFlags controls which widgets are updated */ - void RefreshAvailableLangs(bool bRefreshUI); + void RefreshAvailableLangs(ERefreshUIFlags UIFlags); /** * Generates Localization Files based on the given CSV path and Global Namespace. @@ -230,4 +242,4 @@ class EASYLOCALIZATIONTOOLEDITOR_API UELTEditor : public UObject // Cache of the CSV Paths defined for each Localization directory. TMap CSVPaths; -}; +}; \ No newline at end of file diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditTypes.h b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditTypes.h new file mode 100644 index 0000000..f4b9857 --- /dev/null +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditTypes.h @@ -0,0 +1,150 @@ +// Copyright (c) 2026 Damian Nowakowski. All rights reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "ELTEditorAuditTypes.generated.h" + +UENUM(BlueprintType) +enum class EELTAuditParameterType : uint8 +{ + // CDO-level variable or Blueprint class variable. + ClassVariable UMETA(DisplayName = "Class Variable"), + + // Local variable or input/output parameter on a Blueprint function graph. + FunctionVariable UMETA(DisplayName = "Function Variable"), + + // Inline literal FText pin on a Blueprint graph node. + NodeParameter UMETA(DisplayName = "Node Parameter"), + + // FText property on a UMG widget component inside a Widget Blueprint's widget tree. + WidgetComponent UMETA(DisplayName = "Widget Component"), +}; + +UENUM(BlueprintType) +enum class EELTAuditIssueType : uint8 +{ + // FText passed the audit — no localization issue detected. + None UMETA(DisplayName = "-"), + + // FText field is empty. + EmptyValue UMETA(DisplayName = "Empty Value"), + + // String Table reference is broken — table missing from registry or key absent from it. + StringTableMissingKey UMETA(DisplayName = "String Table Missing Key"), + + // Key does not match the source value — text was never set up via ELT or was edited after. + NotYetLocalized UMETA(DisplayName = "Not Yet Localized"), + + // Key matches source but is absent from the live localization table. + InvalidLocalization UMETA(DisplayName = "Invalid Localization"), +}; + +// One row in the audit results table. +USTRUCT(BlueprintType) +struct FELTAuditIssue +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + FString AssetName; + + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + EELTAuditParameterType Type = EELTAuditParameterType::ClassVariable; + + // Variable name, pin name, or node display name depending on Type. + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + FString VariableNodeName; + + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + EELTAuditIssueType Issue = EELTAuditIssueType::None; + + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + FString Value; + + // The resolved localization string for the current language at the time of audit. + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + FString LocalizedString; + + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + FString Key; + + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + FString Namespace; + + // True when the FText is backed by a String Table reference. + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + bool bIsUsingStringTable = false; + + // Navigation data used by the Quick Action column — not displayed as table columns. + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + FGuid NodeGuid; + + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + FString GraphName; + + bool HasIssue() const { return Issue != EELTAuditIssueType::None; } + bool IsEmpty() const { return Issue == EELTAuditIssueType::EmptyValue; } + + FString TypeDisplayString() const + { + switch (Type) + { + case EELTAuditParameterType::ClassVariable: return TEXT("Class Variable"); + case EELTAuditParameterType::FunctionVariable: return TEXT("Function Variable"); + case EELTAuditParameterType::NodeParameter: return TEXT("Node Parameter"); + case EELTAuditParameterType::WidgetComponent: return TEXT("Widget Component"); + } + return TEXT(""); + } + + FString IssueDisplayString() const + { + switch (Issue) + { + case EELTAuditIssueType::None: return TEXT("-"); + case EELTAuditIssueType::EmptyValue: return TEXT("Empty Value"); + case EELTAuditIssueType::StringTableMissingKey: return TEXT("String Table Missing Key"); + case EELTAuditIssueType::NotYetLocalized: return TEXT("Not Yet Localized"); + case EELTAuditIssueType::InvalidLocalization: return TEXT("Invalid Localization"); + } + return TEXT(""); + } + + FString IssueTooltipString() const + { + switch (Issue) + { + case EELTAuditIssueType::None: return TEXT(""); + case EELTAuditIssueType::EmptyValue: return TEXT("This FText field has no value set. \n\nIf this is intentional for state or function processing purposes, it is recommended to toggle FText localize bool to false."); + case EELTAuditIssueType::StringTableMissingKey: return TEXT("String Table is set, but an invalid key is selected."); + case EELTAuditIssueType::NotYetLocalized: return TEXT("Unable to fetch a localization string. (Value and Key do not match)"); + case EELTAuditIssueType::InvalidLocalization: return TEXT("The localization key does not return a valid localization string."); + } + return TEXT(""); + } + + FString ToLogString() const + { + return FString::Printf(TEXT("[%s] [%s] %s Value='%s' NS='%s' Key='%s'"), + *TypeDisplayString(), *IssueDisplayString(), *VariableNodeName, *Value, *Namespace, *Key); + } +}; + +// Aggregates all issues found for a single asset. The widget flattens these into one list. +USTRUCT(BlueprintType) +struct FELTAssetAuditResult +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + FAssetData AssetData; + + UPROPERTY(BlueprintReadOnly, Category = "ELT Audit") + TArray Issues; + + bool HasIssues() const + { + return Issues.ContainsByPredicate([](const FELTAuditIssue& I){ return I.HasIssue(); }); + } +}; \ No newline at end of file diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditWidget.h b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditWidget.h new file mode 100644 index 0000000..82230f6 --- /dev/null +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditWidget.h @@ -0,0 +1,130 @@ +// Copyright (c) 2026 Damian Nowakowski. All rights reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "ELTEditorAuditTypes.h" +#include "Widgets/SCompoundWidget.h" +#include "Widgets/Views/SListView.h" + +class STableViewBase; +class ITableRow; +class SDockTab; + +class SELTEditorAuditWidget : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SELTEditorAuditWidget) {} + SLATE_ARGUMENT(TArray, AuditResults) + SLATE_END_ARGS() + + void Construct(const FArguments& InArgs); + + void Refresh(const TArray& InResults); + void RefreshLanguages(const TArray& Languages); + void SetPendingCompletionDialog(bool bPending) { bPendingCompletionDialog = bPending; } + + static void JumpToIssue(const FAssetData& AssetData, const FELTAuditIssue& Issue); + +private: + using FIssuePtr = TSharedPtr; + using FLanguagePtr = TSharedPtr; + + // Full unfiltered list + TArray AllIssues; + + // Filtered + Sorted view + TArray FlatIssues; + + // Key AssetName, OnGenerateIssueRow. + TMap AssetDataMap; + + // All asset data from the last audit run, used to reaudit via Refresh(). + TArray LastAuditedAssets; + + // Widget Pointers + TSharedPtr SummaryText; + TSharedPtr TipText; + TSharedPtr AuditHeaderRow; + TSharedPtr> ListView; + + // Language Dropdown + TArray AvailableLanguages; + TSharedPtr> LanguageComboBox; + FLanguagePtr SelectedLanguage; + + // Hide rows with no issue + bool bFilterIssues = false; + + // Hide rows with empty text values + bool bHideEmpty = false; + + // Shows more details in list + bool bShowMoreDetails = true; + + // When true, Refresh() will show the audit completion dialog after updating the widget. + bool bPendingCompletionDialog = false; + + // More Detail columns + static const TArray& GetDetailColumns() + { + static const TArray Cols = { + TEXT("LocalizedString"), + TEXT("Value"), + TEXT("Key"), + TEXT("Namespace"), + TEXT("IsUsingStringTable") + }; + return Cols; + } + + FName SortColumn; + EColumnSortMode::Type SortMode = EColumnSortMode::None; + + void RebuildAuditData(const TArray& InResults); + FText BuildSummaryText() const; + FText PickRandomTip() const; + + TSharedRef OnGenerateIssueRow(FIssuePtr Issue, const TSharedRef& OwnerTable); + void OnSortColumn(EColumnSortPriority::Type Priority, const FName& Column, EColumnSortMode::Type Mode); + void OnFilterIssuesChanged(ECheckBoxState NewState); + void OnHideEmptyChanged(ECheckBoxState NewState); + void OnShowMoreDetailsChanged(ECheckBoxState NewState); + void OnLanguageSelected(FLanguagePtr Item, ESelectInfo::Type SelectInfo); + TSharedRef OnGenerateLanguageComboRow(FLanguagePtr Item); + FReply OnRefreshAuditClicked(); + FReply OnReimportCSVClicked(); + + void ApplySort(); + void ApplyFilter(); + void ApplyDetailColumnVisibility(); + EColumnSortMode::Type GetSortModeForColumn(FName Column) const; +}; + +DECLARE_DELEGATE(FOnAuditWidgetReimportCSV); + +class EASYLOCALIZATIONTOOLEDITOR_API UELTEditorAuditWidget +{ +public: + static void ShowResults(const TArray& Results); + + // Called after a CSV reimport to refresh the language dropdown with newly available languages. + static void UpdateAvailableLanguages(const TArray& Languages); + + // Shows the audit complete dialog. Called from Refresh() once the widget is live. + static void ShowCompletionDialog(const TArray& Results); + + static const FName TabName; + + // Bound by UELTEditor to trigger CSV reimport when the Reimport CSV button is clicked. + static FOnAuditWidgetReimportCSV OnReimportCSVDelegate; + + // Set before SpawnTab is called so Construct can read it synchronously. + static bool bPendingDialogOnSpawn; + +private: + static TSharedRef SpawnTab(const FSpawnTabArgs& Args); + + static TArray PendingResults; + static TWeakPtr LiveWidget; +}; \ No newline at end of file diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditor.h b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditor.h new file mode 100644 index 0000000..56394a0 --- /dev/null +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditor.h @@ -0,0 +1,43 @@ +// Copyright (c) 2026 Damian Nowakowski. All rights reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "EditorUtilityObject.h" +#include "Engine/StreamableManager.h" +#include "ELTEditorAuditTypes.h" +#include "ELTEditorAuditor.generated.h" + +class UWidgetBlueprint; + +UCLASS() +class EASYLOCALIZATIONTOOLEDITOR_API UELTEditorAuditor : public UEditorUtilityObject +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, CallInEditor, Category = "ELT|Localization Audit") + void AuditSelectedAssets(); + + UFUNCTION(BlueprintCallable, Category = "ELT|Localization Audit") + void AuditAssets(const TArray& Assets); + + static TArray RunAudit(const TArray& Assets); + + // Held alive until async asset loading completes before running the audit. + static TSharedPtr PendingLoadHandle; + +private: + static void AuditSingleAsset(UObject* Asset, const FAssetData& AssetData, FELTAssetAuditResult& OutResult); + + // Audits every FText reachable through the CDO property tree. This will recursively run through base classes and relevant properties. + static void AuditClassProperties(void* ContainerPtr, UStruct* Struct, const FString& PathPrefix, FELTAssetAuditResult& OutResult); + + // Audits Blueprint class variables, function local variables, function parameter pins, and inline node pins. + static void AuditBlueprintTextSources(UBlueprint* Blueprint, FELTAssetAuditResult& OutResult); + + // Audits FText properties on UMG widget components inside a Widget Blueprint's widget tree. + static void AuditWidgetComponents(UWidgetBlueprint* WidgetBlueprint, FELTAssetAuditResult& OutResult); + + static void AuditText(const FText& InText, EELTAuditParameterType ParameterType, const FString& VariableNodeName, const FGuid& NodeGuid, const FString& GraphName, FELTAssetAuditResult& OutResult); +}; \ No newline at end of file diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditorCommands.h b/Source/EasyLocalizationToolEditor/Public/ELTEditorCommands.h index 18d558c..3c3c06f 100644 --- a/Source/EasyLocalizationToolEditor/Public/ELTEditorCommands.h +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditorCommands.h @@ -20,4 +20,5 @@ class EASYLOCALIZATIONTOOLEDITOR_API FELTEditorCommands : public TCommands OpenELTMenu; + TSharedPtr RunELTAudit; }; diff --git a/Source/EasyLocalizationToolEditor/Public/EasyLocalizationToolEditorModule.h b/Source/EasyLocalizationToolEditor/Public/EasyLocalizationToolEditorModule.h index 74771ba..c54dec0 100644 --- a/Source/EasyLocalizationToolEditor/Public/EasyLocalizationToolEditorModule.h +++ b/Source/EasyLocalizationToolEditor/Public/EasyLocalizationToolEditorModule.h @@ -54,6 +54,11 @@ class EASYLOCALIZATIONTOOLEDITOR_API FEasyLocalizationToolEditorModule : public * Invokes spawning editor from the command. */ void InvokeEditorSpawn(); + + /** + * Audit selected assets if content browser is focused, otherwise audit focused editor window if it is an asset. + */ + void RunAuditCommand(); // Editor object. #if (ENGINE_MAJOR_VERSION == 5) @@ -69,4 +74,7 @@ class EASYLOCALIZATIONTOOLEDITOR_API FEasyLocalizationToolEditorModule : public FDelegateHandle OnPostEngineInitDelegateHandle; TSharedPtr GraphPanelPinFactory; -}; + + FDelegateHandle ContentBrowserExtenderHandle; + FDelegateHandle PathViewExtenderHandle; +}; \ No newline at end of file From 7d03c3362deb894e724940bf5ab9776aa3ed1ded Mon Sep 17 00:00:00 2001 From: Ryan Lim Date: Wed, 20 May 2026 02:31:07 +0800 Subject: [PATCH 9/9] Updated copyright and audit completion message icon. - Updated Copyright for audit related files. - Updated audit completion message dialog to change icon depending on issue count. --- .../Private/ELTEditorAuditWidget.cpp | 5 +++-- .../EasyLocalizationToolEditor/Private/ELTEditorAuditor.cpp | 2 +- .../EasyLocalizationToolEditor/Public/ELTEditorAuditTypes.h | 2 +- .../EasyLocalizationToolEditor/Public/ELTEditorAuditWidget.h | 2 +- Source/EasyLocalizationToolEditor/Public/ELTEditorAuditor.h | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditWidget.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditWidget.cpp index 13ede49..009e3bd 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditWidget.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditWidget.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2026 Damian Nowakowski. All rights reserved. +// Copyright (c) 2026 Crezetique. All rights reserved. #include "ELTEditorAuditWidget.h" #include "ELTEditorAuditor.h" @@ -108,7 +108,8 @@ bool UELTEditorAuditWidget::bPendingDialogOnSpawn = false; : FString::Printf(TEXT("%d issue(s) found across %d / %d asset(s)."), IssueCount, AffectedAssets.Num(), Results.Num()); #if (ENGINE_MAJOR_VERSION == 5) - FMessageDialog::Open(EAppMsgCategory::Success, EAppMsgType::Ok, FText::FromString(Summary), FText::FromString(TEXT("Audit Complete"))); + const EAppMsgCategory Category = (IssueCount == 0) ? EAppMsgCategory::Success : EAppMsgCategory::Warning; + FMessageDialog::Open(Category, EAppMsgType::Ok, FText::FromString(Summary), FText::FromString(TEXT("Audit Complete"))); #else FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(Summary)); #endif diff --git a/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditor.cpp b/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditor.cpp index de4078c..c0fa93f 100644 --- a/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditor.cpp +++ b/Source/EasyLocalizationToolEditor/Private/ELTEditorAuditor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2026 Damian Nowakowski. All rights reserved. +// Copyright (c) 2026 Crezetique. All rights reserved. #include "ELTEditorAuditor.h" #include "ELTBlueprintLibrary.h" diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditTypes.h b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditTypes.h index f4b9857..6c8c47b 100644 --- a/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditTypes.h +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditTypes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2026 Damian Nowakowski. All rights reserved. +// Copyright (c) 2026 Crezetique. All rights reserved. #pragma once diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditWidget.h b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditWidget.h index 82230f6..05f9f38 100644 --- a/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditWidget.h +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditWidget.h @@ -1,4 +1,4 @@ -// Copyright (c) 2026 Damian Nowakowski. All rights reserved. +// Copyright (c) 2026 Crezetique. All rights reserved. #pragma once diff --git a/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditor.h b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditor.h index 56394a0..4540251 100644 --- a/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditor.h +++ b/Source/EasyLocalizationToolEditor/Public/ELTEditorAuditor.h @@ -1,4 +1,4 @@ -// Copyright (c) 2026 Damian Nowakowski. All rights reserved. +// Copyright (c) 2026 Crezetique. All rights reserved. #pragma once