// Copyright Epic Games, Inc. All Rights Reserved. #include "LocalizationCommandletTasks.h" #include "Misc/MessageDialog.h" #include "Misc/Paths.h" #include "Internationalization/Culture.h" #include "UObject/UObjectHash.h" #include "Sound/SoundWave.h" #include "Sound/DialogueWave.h" #include "LocalizationCommandletExecution.h" #include "LocalizationConfigurationScript.h" #include "LocalizationDelegates.h" #include "LocalizationTargetTypes.h" #include "HAL/FileManager.h" #define LOCTEXT_NAMESPACE "LocalizationCommandletTasks" namespace LocalizationCommandletTasks { void BroadcastLocalizationTargetsDataUpdated(TArrayView Targets) { for (ULocalizationTarget* Target : Targets) { const FString TargetContentPath = FPaths::Combine(Target->IsMemberOfEngineTargetSet() ? FPaths::EngineContentDir() : FPaths::ProjectContentDir(), TEXT("Localization"), Target->Settings.Name); LocalizationDelegates::OnLocalizationTargetDataUpdated.Broadcast(TargetContentPath); } } bool ExecuteTasksAndBroadcastLocalizationTargetsDataUpdated(const TSharedRef& ParentWindow, const FText& Title, const TArray& Tasks, TArrayView Targets) { if (LocalizationCommandletExecution::Execute(ParentWindow, Title, Tasks)) { BroadcastLocalizationTargetsDataUpdated(Targets); return true; } return false; } bool ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(const TSharedRef& ParentWindow, const FText& Title, const TArray& Tasks, ULocalizationTarget* const Target) { if (LocalizationCommandletExecution::Execute(ParentWindow, Title, Tasks)) { BroadcastLocalizationTargetsDataUpdated(MakeArrayView(&Target, 1)); return true; } return false; } } bool LocalizationCommandletTasks::GatherTextForTargets(const TSharedRef& ParentWindow, const TArray& Targets) { TArray Tasks; for (ULocalizationTarget* Target : Targets) { const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText GatherTaskName = FText::Format(LOCTEXT("GatherTaskNameFormat", "Gather Text for {TargetName}"), Arguments); const FString GatherScriptPath = LocalizationConfigurationScript::GetGatherTextConfigPath(Target); LocalizationConfigurationScript::GenerateGatherTextConfigFile(Target).WriteWithSCC(GatherScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(GatherTaskName, GatherScriptPath, ShouldUseProjectFile)); } return ExecuteTasksAndBroadcastLocalizationTargetsDataUpdated(ParentWindow, LOCTEXT("GatherAllTargetsWindowTitle", "Gather Text for All Targets"), Tasks, Targets); } bool LocalizationCommandletTasks::GatherTextForTarget(const TSharedRef& ParentWindow, ULocalizationTarget* const Target) { TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString GatherScriptPath = LocalizationConfigurationScript::GetGatherTextConfigPath(Target); LocalizationConfigurationScript::GenerateGatherTextConfigFile(Target).WriteWithSCC(GatherScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("GatherTaskName", "Gather Text"), GatherScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("GatherTargetWindowTitle", "Gather Text for Target {TargetName}"), Arguments); return ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); } bool LocalizationCommandletTasks::ImportTextForTargets(const TSharedRef& ParentWindow, const TArray& Targets, const TOptional DirectoryPath) { TArray Tasks; for (ULocalizationTarget* Target : Targets) { const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText ImportTaskName = FText::Format(LOCTEXT("ImportTaskNameFormat", "Import Translations for {TargetName}"), Arguments); const FString ImportScriptPath = LocalizationConfigurationScript::GetImportTextConfigPath(Target, TOptional()); const TOptional DirectoryPathForTarget = DirectoryPath.IsSet() ? DirectoryPath.GetValue() / Target->Settings.Name : TOptional(); LocalizationConfigurationScript::GenerateImportTextConfigFile(Target, TOptional(), DirectoryPathForTarget).WriteWithSCC(ImportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(ImportTaskName, ImportScriptPath, ShouldUseProjectFile)); const FText ReportTaskName = FText::Format(LOCTEXT("ReportTaskNameFormat", "Generate Reports for {TargetName}"), Arguments); const FString ReportScriptPath = LocalizationConfigurationScript::GetWordCountReportConfigPath(Target); LocalizationConfigurationScript::GenerateWordCountReportConfigFile(Target).WriteWithSCC(ReportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(ReportTaskName, ReportScriptPath, ShouldUseProjectFile)); } return ExecuteTasksAndBroadcastLocalizationTargetsDataUpdated(ParentWindow, LOCTEXT("ImportForAllTargetsWindowTitle", "Import Translations for All Targets"), Tasks, Targets); } bool LocalizationCommandletTasks::ImportTextForTarget(const TSharedRef& ParentWindow, ULocalizationTarget* const Target, const TOptional DirectoryPath) { TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString ImportScriptPath = LocalizationConfigurationScript::GetImportTextConfigPath(Target, TOptional()); LocalizationConfigurationScript::GenerateImportTextConfigFile(Target, TOptional(), DirectoryPath).WriteWithSCC(ImportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ImportTaskName", "Import Translations"), ImportScriptPath, ShouldUseProjectFile)); const FString ReportScriptPath = LocalizationConfigurationScript::GetWordCountReportConfigPath(Target); LocalizationConfigurationScript::GenerateWordCountReportConfigFile(Target).WriteWithSCC(ReportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ReportTaskName", "Generate Reports"), ReportScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("ImportForTargetWindowTitle", "Import Translations for Target {TargetName}"), Arguments); return ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); } bool LocalizationCommandletTasks::ImportTextForCulture(const TSharedRef& ParentWindow, ULocalizationTarget* const Target, const FString& CultureName, const TOptional FilePath) { FCulturePtr Culture = FInternationalization::Get().GetCulture(CultureName); if (!Culture.IsValid()) { return false; } TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString DefaultImportScriptPath = LocalizationConfigurationScript::GetImportTextConfigPath(Target, TOptional(CultureName)); const FString ImportScriptPath = FPaths::CreateTempFilename(*FPaths::GetPath(DefaultImportScriptPath), *FPaths::GetBaseFilename(DefaultImportScriptPath), *FPaths::GetExtension(DefaultImportScriptPath, true)); LocalizationConfigurationScript::GenerateImportTextConfigFile(Target, TOptional(CultureName), FilePath).Write(ImportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ImportTaskName", "Import Translations"), ImportScriptPath, ShouldUseProjectFile)); const FString ReportScriptPath = LocalizationConfigurationScript::GetWordCountReportConfigPath(Target); LocalizationConfigurationScript::GenerateWordCountReportConfigFile(Target).Write(ReportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ReportTaskName", "Generate Reports"), ReportScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("CultureName"), FText::FromString(Culture->GetDisplayName())); Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("ImportCultureForTargetWindowTitle", "Import {CultureName} Translations for Target {TargetName}"), Arguments); bool HasSucceeeded = ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); IFileManager::Get().Delete(*ImportScriptPath); // Don't clutter up the loc config directory with scripts for individual cultures. return HasSucceeeded; } bool LocalizationCommandletTasks::ExportTextForTargets(const TSharedRef& ParentWindow, const TArray& Targets, const TOptional DirectoryPath) { TArray Tasks; for (ULocalizationTarget* Target : Targets) { const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText ExportTaskName = FText::Format(LOCTEXT("ExportTaskNameFormat", "Export Translations for {TargetName}"), Arguments); const FString ExportScriptPath = LocalizationConfigurationScript::GetExportTextConfigPath(Target, TOptional()); const TOptional DirectoryPathForTarget = DirectoryPath.IsSet() ? DirectoryPath.GetValue() / Target->Settings.Name : TOptional(); LocalizationConfigurationScript::GenerateExportTextConfigFile(Target, TOptional(), DirectoryPathForTarget).WriteWithSCC(ExportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(ExportTaskName, ExportScriptPath, ShouldUseProjectFile)); } return ExecuteTasksAndBroadcastLocalizationTargetsDataUpdated(ParentWindow, LOCTEXT("ExportForAllTargetsWindowTitle", "Export Translations for All Targets"), Tasks, Targets); } bool LocalizationCommandletTasks::ExportTextForTarget(const TSharedRef& ParentWindow, ULocalizationTarget* const Target, const TOptional DirectoryPath) { TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString ExportScriptPath = LocalizationConfigurationScript::GetExportTextConfigPath(Target, TOptional()); LocalizationConfigurationScript::GenerateExportTextConfigFile(Target, TOptional(), DirectoryPath).WriteWithSCC(ExportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ExportTaskName", "Export Translations"), ExportScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("ExportForTargetWindowTitle", "Export Translations for Target {TargetName}"), Arguments); return ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); } bool LocalizationCommandletTasks::ExportTextForCulture(const TSharedRef& ParentWindow, ULocalizationTarget* const Target, const FString& CultureName, const TOptional FilePath) { FCulturePtr Culture = FInternationalization::Get().GetCulture(CultureName); if (!Culture.IsValid()) { return false; } TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString DefaultExportScriptPath = LocalizationConfigurationScript::GetExportTextConfigPath(Target, TOptional(CultureName)); const FString ExportScriptPath = FPaths::CreateTempFilename(*FPaths::GetPath(DefaultExportScriptPath), *FPaths::GetBaseFilename(DefaultExportScriptPath), *FPaths::GetExtension(DefaultExportScriptPath, true)); LocalizationConfigurationScript::GenerateExportTextConfigFile(Target, TOptional(CultureName), FilePath).Write(ExportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ExportTaskName", "Export Translations"), ExportScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("CultureName"), FText::FromString(Culture->GetDisplayName())); Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("ExportCultureForTargetWindowTitle", "Export {CultureName} Translations for Target {TargetName}"), Arguments); bool HasSucceeeded = ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); IFileManager::Get().Delete(*ExportScriptPath); // Don't clutter up the loc config directory with scripts for individual cultures. return HasSucceeeded; } bool LocalizationCommandletTasks::ImportDialogueScriptForTargets(const TSharedRef& ParentWindow, const TArray& Targets, const TOptional DirectoryPath) { TArray Tasks; for (ULocalizationTarget* Target : Targets) { const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText ImportTaskName = FText::Format(LOCTEXT("ImportDialogueScriptsTaskNameFormat", "Import Dialogue Scripts for {TargetName}"), Arguments); const FString ImportScriptPath = LocalizationConfigurationScript::GetImportDialogueScriptConfigPath(Target, TOptional()); const TOptional DirectoryPathForTarget = DirectoryPath.IsSet() ? DirectoryPath.GetValue() / Target->Settings.Name : TOptional(); LocalizationConfigurationScript::GenerateImportDialogueScriptConfigFile(Target, TOptional(), DirectoryPathForTarget).WriteWithSCC(ImportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(ImportTaskName, ImportScriptPath, ShouldUseProjectFile)); const FText ReportTaskName = FText::Format(LOCTEXT("ReportTaskNameFormat", "Generate Reports for {TargetName}"), Arguments); const FString ReportScriptPath = LocalizationConfigurationScript::GetWordCountReportConfigPath(Target); LocalizationConfigurationScript::GenerateWordCountReportConfigFile(Target).WriteWithSCC(ReportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(ReportTaskName, ReportScriptPath, ShouldUseProjectFile)); } return ExecuteTasksAndBroadcastLocalizationTargetsDataUpdated(ParentWindow, LOCTEXT("ImportDialogueScriptsForAllTargetsWindowTitle", "Import Dialogue Scripts for All Targets"), Tasks, Targets); } bool LocalizationCommandletTasks::ImportDialogueScriptForTarget(const TSharedRef& ParentWindow, ULocalizationTarget* const Target, const TOptional DirectoryPath) { TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString ImportScriptPath = LocalizationConfigurationScript::GetImportDialogueScriptConfigPath(Target, TOptional()); LocalizationConfigurationScript::GenerateImportDialogueScriptConfigFile(Target, TOptional(), DirectoryPath).WriteWithSCC(ImportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ImportDialogueScriptsTaskName", "Import Dialogue Scripts"), ImportScriptPath, ShouldUseProjectFile)); const FString ReportScriptPath = LocalizationConfigurationScript::GetWordCountReportConfigPath(Target); LocalizationConfigurationScript::GenerateWordCountReportConfigFile(Target).WriteWithSCC(ReportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ReportTaskName", "Generate Reports"), ReportScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("ImportDialogueScriptsForTargetWindowTitle", "Import Dialogue Scripts for Target {TargetName}"), Arguments); return ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); } bool LocalizationCommandletTasks::ImportDialogueScriptForCulture(const TSharedRef& ParentWindow, ULocalizationTarget* const Target, const FString& CultureName, const TOptional FilePath) { FCulturePtr Culture = FInternationalization::Get().GetCulture(CultureName); if (!Culture.IsValid()) { return false; } TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString DefaultImportScriptPath = LocalizationConfigurationScript::GetImportDialogueScriptConfigPath(Target, TOptional(CultureName)); const FString ImportScriptPath = FPaths::CreateTempFilename(*FPaths::GetPath(DefaultImportScriptPath), *FPaths::GetBaseFilename(DefaultImportScriptPath), *FPaths::GetExtension(DefaultImportScriptPath, true)); LocalizationConfigurationScript::GenerateImportDialogueScriptConfigFile(Target, TOptional(CultureName), FilePath).Write(ImportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ImportDialogueScriptsTaskName", "Import Dialogue Scripts"), ImportScriptPath, ShouldUseProjectFile)); const FString ReportScriptPath = LocalizationConfigurationScript::GetWordCountReportConfigPath(Target); LocalizationConfigurationScript::GenerateWordCountReportConfigFile(Target).Write(ReportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ReportTaskName", "Generate Reports"), ReportScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("CultureName"), FText::FromString(Culture->GetDisplayName())); Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("ImportDialogueScriptsForCultureForTargetWindowTitle", "Import {CultureName} Dialogue Scripts for Target {TargetName}"), Arguments); bool HasSucceeeded = ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); IFileManager::Get().Delete(*ImportScriptPath); // Don't clutter up the loc config directory with scripts for individual cultures. return HasSucceeeded; } bool LocalizationCommandletTasks::ExportDialogueScriptForTargets(const TSharedRef& ParentWindow, const TArray& Targets, const TOptional DirectoryPath) { TArray Tasks; for (ULocalizationTarget* Target : Targets) { const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText ExportTaskName = FText::Format(LOCTEXT("ExportDialogueScriptsTaskNameFormat", "Export Dialogue Scripts for {TargetName}"), Arguments); const FString ExportScriptPath = LocalizationConfigurationScript::GetExportDialogueScriptConfigPath(Target, TOptional()); const TOptional DirectoryPathForTarget = DirectoryPath.IsSet() ? DirectoryPath.GetValue() / Target->Settings.Name : TOptional(); LocalizationConfigurationScript::GenerateExportDialogueScriptConfigFile(Target, TOptional(), DirectoryPathForTarget).WriteWithSCC(ExportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(ExportTaskName, ExportScriptPath, ShouldUseProjectFile)); } return ExecuteTasksAndBroadcastLocalizationTargetsDataUpdated(ParentWindow, LOCTEXT("ExportDialogueScriptsForAllTargetsWindowTitle", "Export Dialogue Scripts for All Targets"), Tasks, Targets); } bool LocalizationCommandletTasks::ExportDialogueScriptForTarget(const TSharedRef& ParentWindow, ULocalizationTarget* const Target, const TOptional DirectoryPath) { TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString ExportScriptPath = LocalizationConfigurationScript::GetExportDialogueScriptConfigPath(Target, TOptional()); LocalizationConfigurationScript::GenerateExportDialogueScriptConfigFile(Target, TOptional(), DirectoryPath).WriteWithSCC(ExportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ExportDialogueScriptsTaskName", "Export Dialogue Scripts"), ExportScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("ExportDialogueScriptsForTargetWindowTitle", "Export Dialogue Scripts for Target {TargetName}"), Arguments); return ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); } bool LocalizationCommandletTasks::ExportDialogueScriptForCulture(const TSharedRef& ParentWindow, ULocalizationTarget* const Target, const FString& CultureName, const TOptional FilePath) { FCulturePtr Culture = FInternationalization::Get().GetCulture(CultureName); if (!Culture.IsValid()) { return false; } TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString DefaultExportScriptPath = LocalizationConfigurationScript::GetExportDialogueScriptConfigPath(Target, TOptional(CultureName)); const FString ExportScriptPath = FPaths::CreateTempFilename(*FPaths::GetPath(DefaultExportScriptPath), *FPaths::GetBaseFilename(DefaultExportScriptPath), *FPaths::GetExtension(DefaultExportScriptPath, true)); LocalizationConfigurationScript::GenerateExportDialogueScriptConfigFile(Target, TOptional(CultureName), FilePath).Write(ExportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ExportDialogueScriptsTaskName", "Export Dialogue Scripts"), ExportScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("CultureName"), FText::FromString(Culture->GetDisplayName())); Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("ExportDialogueScriptsForCultureForTargetWindowTitle", "Export {CultureName} Dialogue Scripts for Target {TargetName}"), Arguments); bool HasSucceeeded = ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); IFileManager::Get().Delete(*ExportScriptPath); // Don't clutter up the loc config directory with scripts for individual cultures. return HasSucceeeded; } bool LocalizationCommandletTasks::ImportDialogueForTargets(const TSharedRef& ParentWindow, const TArray& Targets) { TArray Tasks; for (ULocalizationTarget* Target : Targets) { const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText ImportDialogueTaskName = FText::Format(LOCTEXT("ImportDialogueTaskNameFormat", "Import Dialogue for {TargetName}"), Arguments); const FString ImportDialogueScriptPath = LocalizationConfigurationScript::GetImportDialogueConfigPath(Target); LocalizationConfigurationScript::GenerateImportDialogueConfigFile(Target).WriteWithSCC(ImportDialogueScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(ImportDialogueTaskName, ImportDialogueScriptPath, ShouldUseProjectFile)); } return ExecuteTasksAndBroadcastLocalizationTargetsDataUpdated(ParentWindow, LOCTEXT("ImportDialogueForAllTargetsWindowTitle", "Import Dialogue for All Targets"), Tasks, Targets); } bool LocalizationCommandletTasks::ImportDialogueForTarget(const TSharedRef& ParentWindow, ULocalizationTarget* const Target) { TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString ImportDialogueScriptPath = LocalizationConfigurationScript::GetImportDialogueConfigPath(Target); LocalizationConfigurationScript::GenerateImportDialogueConfigFile(Target).WriteWithSCC(ImportDialogueScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ImportDialogueTaskName", "Import Dialogue"), ImportDialogueScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("ImportDialogueForTargetWindowTitle", "Import Dialogue for Target {TargetName}"), Arguments); return ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); } bool LocalizationCommandletTasks::ImportDialogueForCulture(const TSharedRef& ParentWindow, ULocalizationTarget* const Target, const FString& CultureName) { FCulturePtr Culture = FInternationalization::Get().GetCulture(CultureName); if (!Culture.IsValid()) { return false; } TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString DefaultImportDialogueScriptPath = LocalizationConfigurationScript::GetImportDialogueConfigPath(Target, TOptional(CultureName)); const FString ImportDialogueScriptPath = FPaths::CreateTempFilename(*FPaths::GetPath(DefaultImportDialogueScriptPath), *FPaths::GetBaseFilename(DefaultImportDialogueScriptPath), *FPaths::GetExtension(DefaultImportDialogueScriptPath, true)); LocalizationConfigurationScript::GenerateImportDialogueConfigFile(Target, TOptional(CultureName)).Write(ImportDialogueScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("ImportDialogueTaskName", "Import Dialogue"), ImportDialogueScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("CultureName"), FText::FromString(Culture->GetDisplayName())); Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("ImportCultureDialogueForTargetWindowTitle", "Import {CultureName} Dialogue for Target {TargetName}"), Arguments); bool HasSucceeeded = ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); IFileManager::Get().Delete(*ImportDialogueScriptPath); // Don't clutter up the loc config directory with scripts for individual cultures. return HasSucceeeded; } bool LocalizationCommandletTasks::GenerateWordCountReportsForTargets(const TSharedRef& ParentWindow, const TArray& Targets) { TArray Tasks; for (ULocalizationTarget* Target : Targets) { const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText ReportTaskName = FText::Format(LOCTEXT("WordCountReportTaskNameFormat", "Generate Word Count Report for {TargetName}"), Arguments); const FString ReportScriptPath = LocalizationConfigurationScript::GetWordCountReportConfigPath(Target); LocalizationConfigurationScript::GenerateWordCountReportConfigFile(Target).WriteWithSCC(ReportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(ReportTaskName, ReportScriptPath, ShouldUseProjectFile)); } return ExecuteTasksAndBroadcastLocalizationTargetsDataUpdated(ParentWindow, LOCTEXT("GenerateReportsForAllTargetsWindowTitle", "Generate Word Count Reports for All Targets"), Tasks, Targets); } bool LocalizationCommandletTasks::GenerateWordCountReportForTarget(const TSharedRef& ParentWindow, ULocalizationTarget* const Target) { TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString ReportScriptPath = LocalizationConfigurationScript::GetWordCountReportConfigPath(Target); LocalizationConfigurationScript::GenerateWordCountReportConfigFile(Target).WriteWithSCC(ReportScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("WordCountReportTaskName_NoTarget", "Generate Word Count Report"), ReportScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("GenerateReportForTargetWindowTitle", "Generate Word Count Report for Target {TargetName}"), Arguments); return ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); } bool LocalizationCommandletTasks::CompileTextForTargets(const TSharedRef& ParentWindow, const TArray& Targets) { TArray Tasks; for (ULocalizationTarget* Target : Targets) { const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText CompileTaskName = FText::Format(LOCTEXT("CompileTaskNameFormat", "Compile Translations for {TargetName}"), Arguments); const FString CompileScriptPath = LocalizationConfigurationScript::GetCompileTextConfigPath(Target); LocalizationConfigurationScript::GenerateCompileTextConfigFile(Target).WriteWithSCC(CompileScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(CompileTaskName, CompileScriptPath, ShouldUseProjectFile)); } return ExecuteTasksAndBroadcastLocalizationTargetsDataUpdated(ParentWindow, LOCTEXT("GenerateLocResForAllTargetsWindowTitle", "Compile Translations for All Targets"), Tasks, Targets); } bool LocalizationCommandletTasks::CompileTextForTarget(const TSharedRef& ParentWindow, ULocalizationTarget* const Target) { TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString CompileScriptPath = LocalizationConfigurationScript::GetCompileTextConfigPath(Target); LocalizationConfigurationScript::GenerateCompileTextConfigFile(Target).WriteWithSCC(CompileScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("CompileTaskName", "Compile Translations"), CompileScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("GenerateLocResForTargetWindowTitle", "Compile Translations for Target {TargetName}"), Arguments); return ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); } bool LocalizationCommandletTasks::CompileTextForCulture(const TSharedRef& ParentWindow, ULocalizationTarget* const Target, const FString& CultureName) { FCulturePtr Culture = FInternationalization::Get().GetCulture(CultureName); if (!Culture.IsValid()) { return false; } TArray Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString DefaultCompileScriptPath = LocalizationConfigurationScript::GetCompileTextConfigPath(Target, TOptional(CultureName)); const FString CompileScriptPath = FPaths::CreateTempFilename(*FPaths::GetPath(DefaultCompileScriptPath), *FPaths::GetBaseFilename(DefaultCompileScriptPath), *FPaths::GetExtension(DefaultCompileScriptPath, true)); LocalizationConfigurationScript::GenerateCompileTextConfigFile(Target, TOptional(CultureName)).Write(CompileScriptPath); Tasks.Add(LocalizationCommandletExecution::FTask(LOCTEXT("CompileTaskName", "Compile Translations"), CompileScriptPath, ShouldUseProjectFile)); FFormatNamedArguments Arguments; Arguments.Add(TEXT("CultureName"), FText::FromString(Culture->GetDisplayName())); Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name)); const FText WindowTitle = FText::Format(LOCTEXT("CompileCultureForTargetWindowTitle", "Compile {CultureName} Translations for Target {TargetName}"), Arguments); bool HasSucceeeded = ExecuteTasksAndBroadcastLocalizationTargetDataUpdated(ParentWindow, WindowTitle, Tasks, Target); IFileManager::Get().Delete(*CompileScriptPath); // Don't clutter up the loc config directory with scripts for individual cultures. return HasSucceeeded; } bool LocalizationCommandletTasks::ReportLoadedAudioAssets(const TArray& Targets, const TOptional& CultureName) { TSet LoadedDialogueWaveAssets; TSet LoadedSoundWaveAssets; for (const ULocalizationTarget* Target : Targets) { const FString RootAssetPath = Target->IsMemberOfEngineTargetSet() ? TEXT("/Engine") : TEXT("/Game"); TArray CulturesToTest; { if (CultureName.IsSet()) { CulturesToTest.Add(CultureName.GetValue()); } else { CulturesToTest.Reserve(Target->Settings.SupportedCulturesStatistics.Num()); for (const FCultureStatistics& CultureData : Target->Settings.SupportedCulturesStatistics) { CulturesToTest.Add(CultureData.CultureName); } } } TArray DialogueWavePathsToTest; TArray SoundWavePathsToTest; { const FString NativeCulture = Target->Settings.SupportedCulturesStatistics.IsValidIndex(Target->Settings.NativeCultureIndex) ? Target->Settings.SupportedCulturesStatistics[Target->Settings.NativeCultureIndex].CultureName : FString(); const bool bImportNativeAsSource = Target->Settings.ImportDialogueSettings.bImportNativeAsSource && !NativeCulture.IsEmpty(); if (bImportNativeAsSource) { DialogueWavePathsToTest.Add(RootAssetPath); SoundWavePathsToTest.Add(RootAssetPath / Target->Settings.ImportDialogueSettings.ImportedDialogueFolder); } for (const FString& Culture : CulturesToTest) { if (bImportNativeAsSource && Culture == NativeCulture) { continue; } DialogueWavePathsToTest.Add(RootAssetPath / TEXT("L10N") / Culture); SoundWavePathsToTest.Add(RootAssetPath / TEXT("L10N") / Culture / Target->Settings.ImportDialogueSettings.ImportedDialogueFolder); } } ForEachObjectOfClass(UDialogueWave::StaticClass(), [&](UObject* InObject) { const FString ObjectPath = InObject->GetPathName(); auto FindAssetPathPredicate = [&](const FString& InAssetPath) -> bool { return ObjectPath.StartsWith(InAssetPath, ESearchCase::IgnoreCase); }; if (DialogueWavePathsToTest.ContainsByPredicate(FindAssetPathPredicate)) { LoadedDialogueWaveAssets.Add(ObjectPath); } }); ForEachObjectOfClass(USoundWave::StaticClass(), [&](UObject* InObject) { const FString ObjectPath = InObject->GetPathName(); auto FindAssetPathPredicate = [&](const FString& InAssetPath) -> bool { return ObjectPath.StartsWith(InAssetPath, ESearchCase::IgnoreCase); }; if (SoundWavePathsToTest.ContainsByPredicate(FindAssetPathPredicate)) { LoadedSoundWaveAssets.Add(ObjectPath); } }); } if (LoadedDialogueWaveAssets.Num() > 0 || LoadedSoundWaveAssets.Num() > 0) { FTextBuilder MsgBuilder; MsgBuilder.AppendLine(LOCTEXT("Warning_LoadedAudioAssetsMsg", "The following audio assets have been loaded by the editor and may cause the dialogue import to fail as their files will be read-only.")); MsgBuilder.AppendLine(FText::GetEmpty()); MsgBuilder.AppendLine(LOCTEXT("Warning_LoadedAudioAssetsMsg_Continue", "Do you want to continue?")); if (LoadedDialogueWaveAssets.Num() > 0) { MsgBuilder.AppendLine(FText::GetEmpty()); MsgBuilder.AppendLine(LOCTEXT("Warning_LoadedAudioAssetsMsg_DialogueWaves", "Dialogue Waves:")); MsgBuilder.Indent(); for (const FString& LoadedDialogueWaveAsset : LoadedDialogueWaveAssets) { MsgBuilder.AppendLine(LoadedDialogueWaveAsset); } MsgBuilder.Unindent(); } if (LoadedSoundWaveAssets.Num() > 0) { MsgBuilder.AppendLine(FText::GetEmpty()); MsgBuilder.AppendLine(LOCTEXT("Warning_LoadedAudioAssetsMsg_SoundWaves", "Sound Waves:")); MsgBuilder.Indent(); for (const FString& LoadedSoundWaveAsset : LoadedSoundWaveAssets) { MsgBuilder.AppendLine(LoadedSoundWaveAsset); } MsgBuilder.Unindent(); } return FMessageDialog::Open(EAppMsgType::YesNo, MsgBuilder.ToText(), LOCTEXT("Warning_LoadedAudioAssetsTitle", "Warning - Loaded Audio Assets")) == EAppReturnType::Yes; } return true; } #undef LOCTEXT_NAMESPACE