void FInternationalizationSettingsModelDetails::RefreshAvailableRegions() { AvailableRegions.Empty(); FCulturePtr DefaultCulture; if ( SelectedLanguage.IsValid() ) { const FString SelectedLanguageName = SelectedLanguage->GetTwoLetterISOLanguageName(); // Setup the region list for( const auto& Culture : AvailableCultures ) { const FString CultureLanguageName = Culture->GetTwoLetterISOLanguageName(); if ( SelectedLanguageName == CultureLanguageName) { AvailableRegions.Add( Culture ); // If this doesn't have a valid region... assume it's the default const FString CultureRegionName = Culture->GetNativeRegion(); if ( CultureRegionName.IsEmpty() ) { DefaultCulture = Culture; } } } AvailableRegions.Sort( FCompareCultureByNativeRegion() ); } // If we have a preferred default (or there's only one in the list), select that now if ( !DefaultCulture.IsValid() ) { if(AvailableRegions.Num() == 1) { DefaultCulture = AvailableRegions.Last(); } } if ( DefaultCulture.IsValid() ) { // Set it as our default region, if one hasn't already been chosen if ( !SelectedCulture.IsValid() && RegionComboBox.IsValid() ) { // We have to update the combo box like this, otherwise it'll do a null selection when we next click on it RegionComboBox->SetSelectedItem( DefaultCulture ); } } if ( RegionComboBox.IsValid() ) { RegionComboBox->RefreshOptions(); } }
bool LocalizationCommandletTasks::ImportTextForCulture(const TSharedRef<SWindow>& ParentWindow, ULocalizationTarget* const Target, const FString& CultureName, const TOptional<FString> FilePath) { FCulturePtr Culture = FInternationalization::Get().GetCulture(CultureName); if (!Culture.IsValid()) { return false; } TArray<LocalizationCommandletExecution::FTask> Tasks; const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet(); const FString DefaultImportScriptPath = LocalizationConfigurationScript::GetImportTextConfigPath(Target, TOptional<FString>(CultureName)); const FString ImportScriptPath = FPaths::CreateTempFilename(*FPaths::GetPath(DefaultImportScriptPath), *FPaths::GetBaseFilename(DefaultImportScriptPath), *FPaths::GetExtension(DefaultImportScriptPath, true)); LocalizationConfigurationScript::GenerateImportTextConfigFile(Target, TOptional<FString>(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 = LocalizationCommandletExecution::Execute(ParentWindow, WindowTitle, Tasks); IFileManager::Get().Delete(*ImportScriptPath); // Don't clutter up the loc config directory with scripts for individual cultures. return HasSucceeeded; }
void FInternationalizationSettingsModelDetails::RefreshAvailableLanguages() { AvailableLanguages.Empty(); FString SelectedLanguageName; if ( SelectedCulture.IsValid() ) { SelectedLanguageName = SelectedCulture->GetNativeLanguage(); } // Setup the language list for( const auto& Culture : AvailableCultures ) { FCulturePtr LanguageCulture = FInternationalization::Get().GetCulture(Culture->GetTwoLetterISOLanguageName()); if (LanguageCulture.IsValid() && AvailableLanguages.Find(LanguageCulture) == INDEX_NONE) { AvailableLanguages.Add(LanguageCulture); // Do we have a match for the base language const FString CultureLanguageName = Culture->GetNativeLanguage(); if ( SelectedLanguageName == CultureLanguageName) { SelectedLanguage = Culture; } } } AvailableLanguages.Sort( FCompareCultureByNativeLanguage() ); RefreshAvailableRegions(); }
FText SLocalizationDashboardTargetRow::GetCulturesText() const { FLocalizationTargetSettings* const TargetSettings = GetTargetSettings(); if (TargetSettings) { TArray<FString> OrderedCultureNames; OrderedCultureNames.Add(TargetSettings->NativeCultureStatistics.CultureName); for (auto& ForeignCultureStatistics : TargetSettings->SupportedCulturesStatistics) { OrderedCultureNames.Add(ForeignCultureStatistics.CultureName); } FString Result; for (FString& CultureName : OrderedCultureNames) { const FCulturePtr Culture = FInternationalization::Get().GetCulture(CultureName); if (Culture.IsValid()) { const FString CultureDisplayName = Culture->GetDisplayName(); if (!Result.IsEmpty()) { Result.Append(TEXT(", ")); } Result.Append(CultureDisplayName); } } return FText::FromString(Result); } return FText::GetEmpty(); }
FORCEINLINE bool operator()( const FCulturePtr A, const FCulturePtr B ) const { check( A.IsValid() ); check( B.IsValid() ); // Non-Specific Region should appear before all else. if(A->GetNativeRegion().IsEmpty()) { return true; } // Non-Specific Region should appear before all else. if(B->GetNativeRegion().IsEmpty()) { return false; } // Compare native region strings. return( GetCultureNativeRegionText( A ).CompareToCaseIgnored( GetCultureNativeRegionText( B ) ) ) < 0; }
static FText GetCultureNativeRegionText( const FCulturePtr Culture ) { check( Culture.IsValid() ); FString Region = Culture->GetNativeRegion(); if ( Region.IsEmpty() ) { // Fallback to displaying the language, if no region is available return LOCTEXT("NoSpecificRegionOption", "Non-Specific Region"); } return FText::FromString(Region); }
static FText GetCultureNativeLanguageText( const FCulturePtr Culture ) { check( Culture.IsValid() ); const FString Language = Culture->GetNativeLanguage(); return FText::FromString(Language); }
FORCEINLINE bool operator()( const FCulturePtr A, const FCulturePtr B ) const { check( A.IsValid() ); check( B.IsValid() ); return( GetCultureNativeLanguageText( A ).CompareToCaseIgnored( GetCultureNativeLanguageText( B ) ) ) < 0; }
void EndInitTextLocalization() { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("EndInitTextLocalization"), STAT_EndInitTextLocalization, STATGROUP_LoadTime); const bool ShouldLoadEditor = WITH_EDITOR; const bool ShouldLoadGame = FApp::IsGame(); FInternationalization& I18N = FInternationalization::Get(); // Set culture according to configuration now that configs are available. #if ENABLE_LOC_TESTING if( FCommandLine::IsInitialized() && FParse::Param(FCommandLine::Get(), TEXT("LEET")) ) { I18N.SetCurrentCulture(TEXT("LEET")); } else #endif { FString RequestedCultureName; if (FParse::Value(FCommandLine::Get(), TEXT("CULTUREFORCOOKING="), RequestedCultureName)) { // Write the culture passed in if first install... if (FParse::Param(FCommandLine::Get(), TEXT("firstinstall"))) { GConfig->SetString(TEXT("Internationalization"), TEXT("Culture"), *RequestedCultureName, GEngineIni); } } else #if !UE_BUILD_SHIPPING // Use culture override specified on commandline. if (FParse::Value(FCommandLine::Get(), TEXT("CULTURE="), RequestedCultureName)) { //UE_LOG(LogInit, Log, TEXT("Overriding culture %s w/ command-line option".), *CultureName); } else #endif // !UE_BUILD_SHIPPING #if WITH_EDITOR // See if we've been provided a culture override in the editor if(GConfig->GetString( TEXT("Internationalization"), TEXT("Culture"), RequestedCultureName, GEditorGameAgnosticIni )) { //UE_LOG(LogInit, Log, TEXT("Overriding culture %s w/ editor configuration."), *CultureName); } else #endif // WITH_EDITOR // Use culture specified in engine configuration. if(GConfig->GetString( TEXT("Internationalization"), TEXT("Culture"), RequestedCultureName, GEngineIni )) { //UE_LOG(LogInit, Log, TEXT("Overriding culture %s w/ engine configuration."), *CultureName); } else { RequestedCultureName = I18N.GetDefaultCulture()->GetName(); } FString TargetCultureName = RequestedCultureName; { TArray<FString> LocalizationPaths; if(ShouldLoadEditor) { LocalizationPaths += FPaths::GetEditorLocalizationPaths(); } if(ShouldLoadGame) { LocalizationPaths += FPaths::GetGameLocalizationPaths(); } LocalizationPaths += FPaths::GetEngineLocalizationPaths(); // Validate the locale has data or fallback to one that does. TArray< FCultureRef > AvailableCultures; I18N.GetCulturesWithAvailableLocalization(LocalizationPaths, AvailableCultures, false); TArray<FString> PrioritizedParentCultureNames = I18N.GetCurrentCulture()->GetPrioritizedParentCultureNames(); FString ValidCultureName; for (const FString& CultureName : PrioritizedParentCultureNames) { FCulturePtr ValidCulture = I18N.GetCulture(CultureName); if (ValidCulture.IsValid() && AvailableCultures.Contains(ValidCulture.ToSharedRef())) { ValidCultureName = CultureName; break; } } if(!ValidCultureName.IsEmpty()) { if(RequestedCultureName != ValidCultureName) { // Make the user aware that the localization data belongs to a parent culture. UE_LOG(LogTextLocalizationManager, Log, TEXT("The requested culture ('%s') has no localization data; parent culture's ('%s') localization data will be used."), *RequestedCultureName, *ValidCultureName); } } else { // Fallback to English. UE_LOG(LogTextLocalizationManager, Log, TEXT("The requested culture ('%s') has no localization data; falling back to 'en' for localization and internationalization data."), *RequestedCultureName); TargetCultureName = "en"; } } I18N.SetCurrentCulture(TargetCultureName); } FTextLocalizationManager::Get().LoadResources(ShouldLoadEditor, ShouldLoadGame); FTextLocalizationManager::Get().bIsInitialized = true; }
void FOneSkyLocalizationServiceProvider::ExportCultureForTargetToOneSky_Callback(const FLocalizationServiceOperationRef& Operation, ELocalizationServiceOperationCommandResult::Type Result, bool bIsTargetSet) { TSharedPtr<FUploadLocalizationTargetFile, ESPMode::ThreadSafe> UploadLocalizationTargetOp = StaticCastSharedRef<FUploadLocalizationTargetFile>(Operation); bool bError = !(Result == ELocalizationServiceOperationCommandResult::Succeeded); FText ErrorText = FText::GetEmpty(); FGuid InTargetGuid; FString InRelativeInputFilePathAndName; FString TargetName = ""; FString CultureName = ""; ULocalizationTarget* Target = nullptr; if (UploadLocalizationTargetOp.IsValid()) { InTargetGuid = UploadLocalizationTargetOp->GetInTargetGuid(); CultureName = UploadLocalizationTargetOp->GetInLocale(); InRelativeInputFilePathAndName = UploadLocalizationTargetOp->GetInRelativeInputFilePathAndName(); TargetName = FPaths::GetBaseFilename(InRelativeInputFilePathAndName); FString EngineOrGamePath = FPaths::GetBaseFilename(FPaths::GetPath(FPaths::GetPath(FPaths::GetPath(InRelativeInputFilePathAndName)))); bool bIsEngineTarget = EngineOrGamePath == "Engine"; Target = ILocalizationModule::Get().GetLocalizationTargetByName(TargetName, bIsEngineTarget); // Remove each file we get a callback for so we know when we've gotten a callback for all of them FilesDownloadingForImportFromOneSky.Remove(InRelativeInputFilePathAndName); ErrorText = UploadLocalizationTargetOp->GetOutErrorText(); FilesUploadingForExportToOneSky.Remove(InRelativeInputFilePathAndName); int32 TotalNumber = 0; if (bIsTargetSet) { for (ULocalizationTarget* LocalizationTarget : Target->GetOuterULocalizationTargetSet()->TargetObjects) { TotalNumber += LocalizationTarget->Settings.SupportedCulturesStatistics.Num(); } } else { TotalNumber = Target->Settings.SupportedCulturesStatistics.Num(); } // Update progress bar GWarn->StatusUpdate(TotalNumber - FilesUploadingForExportToOneSky.Num(), TotalNumber, LOCTEXT("UploadingFilestoLocalizationService", "Uploading Files to Localization Service...")); if (FilesUploadingForExportToOneSky.Num() == 0) { GWarn->EndSlowTask(); } } // Try to get display name FInternationalization& I18N = FInternationalization::Get(); FCulturePtr CulturePtr = I18N.GetCulture(CultureName); FString CultureDisplayName = CultureName; if (CulturePtr.IsValid()) { CultureName = CulturePtr->GetDisplayName(); } if (!bError && ErrorText.IsEmpty()) { FText SuccessText = FText::Format(LOCTEXT("ExportTranslationsToTranslationServiceSuccess", "{0} translations for {1} target uploaded for processing to Translation Service."), FText::FromString(CultureDisplayName), FText::FromString(TargetName)); FMessageLog TranslationEditorMessageLog("TranslationEditor"); TranslationEditorMessageLog.Info(SuccessText); TranslationEditorMessageLog.Notify(SuccessText, EMessageSeverity::Info, true); } else { if (ErrorText.IsEmpty()) { ErrorText = LOCTEXT("ExportToLocalizationServiceUnspecifiedError", "An unspecified error occured when trying to export to the Localization Service."); } FText ErrorNotify = FText::Format(LOCTEXT("SaveSelectedTranslationsToTranslationServiceFail", "{0} translations for {1} target failed to export to Translation Service!"), FText::FromString(CultureDisplayName), FText::FromString(TargetName)); FMessageLog TranslationEditorMessageLog("TranslationEditor"); TranslationEditorMessageLog.Error(ErrorNotify); TranslationEditorMessageLog.Error(ErrorText); TranslationEditorMessageLog.Notify(ErrorNotify); } }
void FInternationalization::GetCulturesWithAvailableLocalization(const TArray<FString>& InLocalizationPaths, TArray< FCultureRef >& OutAvailableCultures, const bool bIncludeDerivedCultures) { OutAvailableCultures.Reset(); TArray<FString> AllLocalizationFolders; IFileManager& FileManager = IFileManager::Get(); for(const auto& LocalizationPath : InLocalizationPaths) { /* Visitor class used to enumerate directories of culture */ class FCultureEnumeratorVistor : public IPlatformFile::FDirectoryVisitor { public: FCultureEnumeratorVistor( TArray<FString>& OutLocalizationFolders ) : LocalizationFolders(OutLocalizationFolders) { } virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory) override { if(bIsDirectory) { // UE localization resource folders use "en-US" style while ICU uses "en_US" const FString LocalizationFolder = FPaths::GetCleanFilename(FilenameOrDirectory); const FString CanonicalName = FCulture::GetCanonicalName(LocalizationFolder); LocalizationFolders.AddUnique(CanonicalName); } return true; } /** Array to fill with the names of the UE localization folders available at the given path */ TArray<FString>& LocalizationFolders; }; FCultureEnumeratorVistor CultureEnumeratorVistor(AllLocalizationFolders); FileManager.IterateDirectory(*LocalizationPath, CultureEnumeratorVistor); } // Find any cultures that are a partial match for those we have translations for. if(bIncludeDerivedCultures) { TArray<FString> CultureNames; GetCultureNames(CultureNames); for(const FString& CultureName : CultureNames) { FCulturePtr Culture = GetCulture(CultureName); if (Culture.IsValid()) { TArray<FString> PrioritizedParentCultureNames = Culture->GetPrioritizedParentCultureNames(); for (const FString& PrioritizedParentCultureName : PrioritizedParentCultureNames) { if(AllLocalizationFolders.Contains(PrioritizedParentCultureName)) { OutAvailableCultures.AddUnique(Culture.ToSharedRef()); break; } } } } } // Find any cultures that are a complete match for those we have translations for. else { for(const FString& LocalizationFolder : AllLocalizationFolders) { FCulturePtr Culture = GetCulture(LocalizationFolder); if(Culture.IsValid()) { OutAvailableCultures.AddUnique(Culture.ToSharedRef()); } } } // Remove any cultures that were explicitly disabled OutAvailableCultures.RemoveAll([&](const FCultureRef& InCulture) -> bool { return Implementation->IsCultureDisabled(InCulture->GetName()); }); }