2018-12-14 14:49:12 -05:00
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
2016-01-14 08:11:47 -05:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using AutomationTool ;
using UnrealBuildTool ;
2019-02-01 11:34:13 -05:00
using Tools.DotNETCommon ;
2016-01-14 08:11:47 -05:00
namespace EpicGames.Localization
{
2019-02-01 11:34:13 -05:00
public class ProjectImportExportInfo
2016-07-14 19:07:16 -04:00
{
2019-02-01 11:34:13 -05:00
public ProjectImportExportInfo ( string InDestinationPath , string InManifestName , string InArchiveName , string InPortableObjectName , string InNativeCulture , IReadOnlyList < string > InCulturesToGenerate , bool InUseCultureDirectory )
2017-05-10 11:49:32 -04:00
{
2019-02-01 11:34:13 -05:00
DestinationPath = InDestinationPath ;
ManifestName = InManifestName ;
ArchiveName = InArchiveName ;
PortableObjectName = InPortableObjectName ;
NativeCulture = InNativeCulture ;
CulturesToGenerate = InCulturesToGenerate ;
bUseCultureDirectory = InUseCultureDirectory ;
2017-05-10 11:49:32 -04:00
}
2019-02-01 11:34:13 -05:00
/** The destination path for the files containing the gathered data for this project (extracted from its config file - relative to the root working directory for the commandlet) */
public string DestinationPath { get ; private set ; }
/** The name to use for this projects manifest file (extracted from its config file) */
public string ManifestName { get ; private set ; }
/** The name to use for this projects archive file (extracted from its config file) */
public string ArchiveName { get ; private set ; }
/** The name to use for this projects portable object file (extracted from its config file) */
public string PortableObjectName { get ; private set ; }
/** The native culture for this project (extracted from its config file) */
public string NativeCulture { get ; private set ; }
/** The cultures to generate for this project (extracted from its config file) */
public IReadOnlyList < string > CulturesToGenerate { get ; private set ; }
/** True if we should use a per-culture directly when importing/exporting */
public bool bUseCultureDirectory { get ; private set ; }
/** The platform names that we have split into sub-folders */
public IReadOnlyList < string > SplitPlatformNames { get ; private set ; }
/** The platforms sub-folder */
public const string PlatformLocalizationFolderName = "Platforms" ;
public void CalculateSplitPlatformNames ( string RootWorkingDirectory )
2016-01-14 08:11:47 -05:00
{
2019-02-01 11:34:13 -05:00
// Is this isn't a single culture import/export, then also check for split platform sub-folders
var NewSplitPlatformNames = new List < string > ( ) ;
if ( bUseCultureDirectory )
2016-01-14 08:11:47 -05:00
{
2019-02-01 11:34:13 -05:00
var PlatformSourceDirectory = new DirectoryReference ( CommandUtils . CombinePaths ( RootWorkingDirectory , DestinationPath , PlatformLocalizationFolderName ) ) ;
if ( DirectoryReference . Exists ( PlatformSourceDirectory ) )
2016-01-14 08:11:47 -05:00
{
2019-02-01 11:34:13 -05:00
foreach ( DirectoryReference FoundDirectory in DirectoryReference . EnumerateDirectories ( PlatformSourceDirectory , "*" , SearchOption . TopDirectoryOnly ) )
2016-01-14 08:11:47 -05:00
{
2019-02-01 11:34:13 -05:00
string SplitPlatformName = CommandUtils . GetLastDirectoryName ( FoundDirectory . FullName ) ;
NewSplitPlatformNames . Add ( SplitPlatformName ) ;
}
}
}
SplitPlatformNames = NewSplitPlatformNames ;
}
} ;
public class ProjectStepInfo
{
public ProjectStepInfo ( string InName , string InLocalizationConfigFile )
{
Name = InName ;
LocalizationConfigFile = InLocalizationConfigFile ;
}
/** The name of this localization step */
public string Name { get ; private set ; }
/** Absolute path to this steps localization config file */
public string LocalizationConfigFile { get ; private set ; }
} ;
public class ProjectInfo
{
public ProjectInfo ( string InProjectName , IReadOnlyList < ProjectStepInfo > InLocalizationSteps , ProjectImportExportInfo InImportInfo , ProjectImportExportInfo InExportInfo )
{
ProjectName = InProjectName ;
LocalizationSteps = InLocalizationSteps ;
ImportInfo = InImportInfo ;
ExportInfo = InExportInfo ;
}
/** The name of this project */
public string ProjectName { get ; private set ; }
/** Path to this projects localization step data - ordered so that iterating them runs in the correct order */
public IReadOnlyList < ProjectStepInfo > LocalizationSteps { get ; private set ; }
/** Config data used by the PO file import process */
public ProjectImportExportInfo ImportInfo { get ; private set ; }
/** Config data used by the PO file export process */
public ProjectImportExportInfo ExportInfo { get ; private set ; }
} ;
public abstract class LocalizationProvider
{
public struct LocalizationProviderArgs
{
public string RootWorkingDirectory ;
public string RootLocalizationTargetDirectory ;
public string RemoteFilenamePrefix ;
public BuildCommand Command ;
public int PendingChangeList ;
} ;
public LocalizationProvider ( LocalizationProviderArgs InArgs )
{
RootWorkingDirectory = InArgs . RootWorkingDirectory ;
RemoteFilenamePrefix = InArgs . RemoteFilenamePrefix ;
Command = InArgs . Command ;
PendingChangeList = InArgs . PendingChangeList ;
LocalizationBranchName = Command . ParseParamValue ( "LocalizationBranch" ) ;
bUploadAllCultures = Command . ParseParam ( "UploadAllCultures" ) ;
}
public virtual string GetLocalizationProviderId ( )
{
throw new AutomationException ( "Unimplemented GetLocalizationProviderId." ) ;
}
public virtual void DownloadProjectFromLocalizationProvider ( string ProjectName , ProjectImportExportInfo ProjectImportInfo )
{
throw new AutomationException ( "Unimplemented DownloadProjectFromLocalizationProvider." ) ;
}
public virtual void UploadProjectToLocalizationProvider ( string ProjectName , ProjectImportExportInfo ProjectExportInfo )
{
throw new AutomationException ( "Unimplemented UploadProjectToLocalizationProvider." ) ;
}
public static LocalizationProvider GetLocalizationProvider ( string InLocalizationProviderId , LocalizationProvider . LocalizationProviderArgs InLocalizationProviderArgs )
{
if ( String . IsNullOrEmpty ( InLocalizationProviderId ) )
{
return null ;
}
if ( CachedLocalizationProviderTypes = = null )
{
// Find all types that derive from LocalizationProvider in any of our DLLs
CachedLocalizationProviderTypes = new Dictionary < string , Type > ( ) ;
var LoadedAssemblies = AppDomain . CurrentDomain . GetAssemblies ( ) ;
foreach ( var Dll in LoadedAssemblies )
{
var AllTypes = Dll . GetTypes ( ) ;
foreach ( var PotentialLocalizationNodeType in AllTypes )
{
if ( PotentialLocalizationNodeType ! = typeof ( LocalizationProvider ) & & ! PotentialLocalizationNodeType . IsAbstract & & ! PotentialLocalizationNodeType . IsInterface & & typeof ( LocalizationProvider ) . IsAssignableFrom ( PotentialLocalizationNodeType ) )
2016-01-14 08:11:47 -05:00
{
2019-02-01 11:34:13 -05:00
// Types should implement a static StaticGetLocalizationProviderId method
var Method = PotentialLocalizationNodeType . GetMethod ( "StaticGetLocalizationProviderId" ) ;
if ( Method ! = null )
2016-01-14 08:11:47 -05:00
{
2019-02-01 11:34:13 -05:00
try
{
var LocalizationProviderId = Method . Invoke ( null , null ) as string ;
CachedLocalizationProviderTypes . Add ( LocalizationProviderId , PotentialLocalizationNodeType ) ;
}
catch
{
BuildCommand . LogWarning ( "Type '{0}' threw when calling its StaticGetLocalizationProviderId method." , PotentialLocalizationNodeType . FullName ) ;
}
2016-01-14 08:11:47 -05:00
}
2019-02-01 11:34:13 -05:00
else
2016-01-14 08:11:47 -05:00
{
2019-02-01 11:34:13 -05:00
BuildCommand . LogWarning ( "Type '{0}' derives from LocalizationProvider but is missing its StaticGetLocalizationProviderId method." , PotentialLocalizationNodeType . FullName ) ;
2016-01-14 08:11:47 -05:00
}
}
}
}
}
2019-02-01 11:34:13 -05:00
Type LocalizationNodeType ;
CachedLocalizationProviderTypes . TryGetValue ( InLocalizationProviderId , out LocalizationNodeType ) ;
if ( LocalizationNodeType ! = null )
2016-01-14 08:11:47 -05:00
{
2019-02-01 11:34:13 -05:00
try
{
return Activator . CreateInstance ( LocalizationNodeType , new object [ ] { InLocalizationProviderArgs } ) as LocalizationProvider ;
}
catch ( Exception e )
{
BuildCommand . LogWarning ( "Unable to create an instance of the type '{0}'. {1}" , LocalizationNodeType . FullName , e . ToString ( ) ) ;
}
2016-01-14 08:11:47 -05:00
}
2019-02-01 11:34:13 -05:00
else
2016-01-14 08:11:47 -05:00
{
2019-02-01 11:34:13 -05:00
BuildCommand . LogWarning ( "Could not find a localization provider for '{0}'" , InLocalizationProviderId ) ;
2016-01-14 08:11:47 -05:00
}
2019-02-01 11:34:13 -05:00
return null ;
2016-01-14 08:11:47 -05:00
}
2019-02-01 11:34:13 -05:00
protected string RootWorkingDirectory ;
protected string LocalizationBranchName ;
protected string RemoteFilenamePrefix ;
protected bool bUploadAllCultures ;
protected BuildCommand Command ;
protected int PendingChangeList ;
2016-01-14 08:11:47 -05:00
2019-02-01 11:34:13 -05:00
private static Dictionary < string , Type > CachedLocalizationProviderTypes ;
} ;
2016-01-14 08:11:47 -05:00
}