void FEditorStyleSettingsDetails::RefreshAvailableCultures() { AvailableCultures.Empty(); IPlatformFile& PlatformFile = IPlatformFile::GetPlatformPhysical(); TArray<FString> AllCultureNames; FInternationalization::GetCultureNames(AllCultureNames); const TArray<FString> LocalizationPaths = FPaths::GetEditorLocalizationPaths(); for(const auto& LocalizationPath : LocalizationPaths) { /* Visitor class used to enumerate directories of culture */ class FCultureEnumeratorVistor : public IPlatformFile::FDirectoryVisitor { public: FCultureEnumeratorVistor( const TArray<FString>& InAllCultureNames, TArray< TSharedPtr<FCulture> >& InAvailableCultures ) : AllCultureNames(InAllCultureNames) , AvailableCultures(InAvailableCultures) { } virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory) OVERRIDE { if(bIsDirectory) { for( const auto& CultureName : AllCultureNames ) { TSharedPtr<FCulture> Culture = FInternationalization::GetCulture(CultureName); if(Culture.IsValid() && !AvailableCultures.Contains(Culture)) { // UE localization resource folders use "en-US" style while ICU uses "en_US" style so we replace underscores with dashes here. const FString UnrealCultureName = FString(TEXT("/")) + CultureName.Replace(TEXT("_"), TEXT("-")); if(FString(FilenameOrDirectory).EndsWith(UnrealCultureName)) { AvailableCultures.Add(Culture); } else { // If the full name doesn't match, see if the base language is present const FString CultureLanguageName = FString(TEXT("/")) + Culture->GetTwoLetterISOLanguageName(); if(FString(FilenameOrDirectory).EndsWith(CultureLanguageName)) { AvailableCultures.Add(Culture); } } } } } return true; } /** Array of all culture names we can use */ const TArray<FString>& AllCultureNames; /** Array of cultures that are available */ TArray< TSharedPtr<FCulture> >& AvailableCultures; }; FCultureEnumeratorVistor CultureEnumeratorVistor(AllCultureNames, AvailableCultures); PlatformFile.IterateDirectory(*LocalizationPath, CultureEnumeratorVistor); }
void FTextLocalizationManager::LoadResources(const bool ShouldLoadEditor, const bool ShouldLoadGame) { // Add one to the revision index, so all FText's refresh. ++HeadCultureRevisionIndex; FInternationalization& I18N = FInternationalization::Get(); #if ENABLE_LOC_TESTING { const FString& CultureName = I18N.GetCurrentCulture()->GetName(); if(CultureName == TEXT("LEET")) { for(auto NamespaceIterator = LiveTable.NamespaceTable.CreateIterator(); NamespaceIterator; ++NamespaceIterator) { const FString& Namespace = NamespaceIterator.Key(); FTextLookupTable::FKeyTable& LiveKeyTable = NamespaceIterator.Value(); for(auto KeyIterator = LiveKeyTable.CreateIterator(); KeyIterator; ++KeyIterator) { const FString& Key = KeyIterator.Key(); FStringEntry& LiveStringEntry = KeyIterator.Value(); LiveStringEntry.bIsLocalized = true; FInternationalization::Leetify( *LiveStringEntry.String ); } } return; } } #endif TArray<FString> LocalizationPaths; if(ShouldLoadGame) { LocalizationPaths += FPaths::GetGameLocalizationPaths(); } if(ShouldLoadEditor) { LocalizationPaths += FPaths::GetEditorLocalizationPaths(); LocalizationPaths += FPaths::GetToolTipLocalizationPaths(); bool bShouldLoadLocalizedPropertyNames = true; if( !GConfig->GetBool( TEXT("Internationalization"), TEXT("ShouldLoadLocalizedPropertyNames"), bShouldLoadLocalizedPropertyNames, GEditorGameAgnosticIni ) ) { GConfig->GetBool( TEXT("Internationalization"), TEXT("ShouldLoadLocalizedPropertyNames"), bShouldLoadLocalizedPropertyNames, GEngineIni ); } if(bShouldLoadLocalizedPropertyNames) { LocalizationPaths += FPaths::GetPropertyNameLocalizationPaths(); } } LocalizationPaths += FPaths::GetEngineLocalizationPaths(); // Prioritized array of localization entry trackers. TArray<FLocalizationEntryTracker> LocalizationEntryTrackers; const auto MapCulturesToDirectories = [](const FString& LocalizationPath) -> TMap<FString, FString> { TMap<FString, FString> CultureToDirectoryMap; IFileManager& FileManager = IFileManager::Get(); /* Visitor class used to enumerate directories of culture */ class FCultureDirectoryMapperVistor : public IPlatformFile::FDirectoryVisitor { public: FCultureDirectoryMapperVistor( TMap<FString, FString>& OutCultureToDirectoryMap ) : CultureToDirectoryMap(OutCultureToDirectoryMap) { } 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); CultureToDirectoryMap.Add(CanonicalName, LocalizationFolder); } return true; } /** Array to fill with the names of the UE localization folders available at the given path */ TMap<FString, FString>& CultureToDirectoryMap; }; FCultureDirectoryMapperVistor CultureEnumeratorVistor(CultureToDirectoryMap); FileManager.IterateDirectory(*LocalizationPath, CultureEnumeratorVistor); return CultureToDirectoryMap; }; TMap< FString, TMap<FString, FString> > LocalizationPathToCultureDirectoryMap; for (const FString& LocalizationPath : LocalizationPaths) { LocalizationPathToCultureDirectoryMap.Add(LocalizationPath, MapCulturesToDirectories(LocalizationPath)); } // Read culture localization resources. TArray<FString> PrioritizedParentCultureNames = I18N.GetCurrentCulture()->GetPrioritizedParentCultureNames(); for (const FString& CultureName : PrioritizedParentCultureNames) { FLocalizationEntryTracker& CultureTracker = LocalizationEntryTrackers[LocalizationEntryTrackers.Add(FLocalizationEntryTracker())]; for (const FString& LocalizationPath : LocalizationPaths) { const FString* const Entry = LocalizationPathToCultureDirectoryMap[LocalizationPath].Find(FCulture::GetCanonicalName(CultureName)); if (Entry) { const FString CulturePath = LocalizationPath / (*Entry); CultureTracker.ReadFromDirectory(CulturePath); } } CultureTracker.ReportCollisions(); } UpdateLiveTable(LocalizationEntryTrackers); }
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()); }); }