2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
using System ;
using System.Collections.Generic ;
2014-09-09 19:26:11 -04:00
using System.Globalization ;
using System.Linq ;
2014-03-14 14:13:41 -04:00
using System.Text ;
using System.IO ;
using AutomationTool ;
using UnrealBuildTool ;
2014-09-09 19:26:11 -04:00
using OneSky ;
using EpicGames.OneSkyLocalization.Config ;
2014-03-14 14:13:41 -04:00
class Localise : BuildCommand
{
2014-09-09 19:26:11 -04:00
private void ExportProjectToDirectory ( OneSkyService oneSkyService , ProjectGroup projectGroup , string ProjectName )
{
var project = GetProject ( oneSkyService , projectGroup . Name , ProjectName ) ;
var file = project . UploadedFiles . FirstOrDefault ( f = > f . Filename = = ( ProjectName + ".po" ) ) ;
//Export
if ( file ! = null )
{
ExportFileToDirectory ( file , new DirectoryInfo ( CmdEnv . LocalRoot + "/Engine/Content/Localization/" + ProjectName ) , projectGroup . EnabledCultures ) ;
}
}
2014-08-18 13:29:39 -04:00
public override void ExecuteBuild ( )
{
var EditorExe = CombinePaths ( CmdEnv . LocalRoot , @"Engine/Binaries/Win64/UE4Editor-Cmd.exe" ) ;
2014-03-14 14:13:41 -04:00
2014-08-18 13:29:39 -04:00
if ( P4Enabled )
{
Log ( "Sync necessary content to head revision" ) ;
2014-04-02 18:09:23 -04:00
P4 . Sync ( P4Env . BuildRootP4 + "/Engine/Config/..." ) ;
P4 . Sync ( P4Env . BuildRootP4 + "/Engine/Content/..." ) ;
P4 . Sync ( P4Env . BuildRootP4 + "/Engine/Source/..." ) ;
2014-08-18 13:29:39 -04:00
Log ( "Localize from label {0}" , P4Env . LabelToSync ) ;
}
2014-03-14 14:13:41 -04:00
2014-09-09 19:26:11 -04:00
OneSkyConfigData OneSkyConfig = OneSkyConfigHelper . Find ( "OneSkyConfig_EpicGames" ) ;
var oneSkyService = new OneSkyService ( OneSkyConfig . ApiKey , OneSkyConfig . ApiSecret ) ;
var projectGroup = GetProjectGroup ( oneSkyService , "Unreal Engine" ) ;
// Export all text from OneSky
ExportProjectToDirectory ( oneSkyService , projectGroup , "Engine" ) ;
ExportProjectToDirectory ( oneSkyService , projectGroup , "Editor" ) ;
2014-09-17 15:42:19 -04:00
ExportProjectToDirectory ( oneSkyService , projectGroup , "EditorTutorials" ) ;
2014-09-09 19:26:11 -04:00
ExportProjectToDirectory ( oneSkyService , projectGroup , "PropertyNames" ) ;
ExportProjectToDirectory ( oneSkyService , projectGroup , "ToolTips" ) ;
2014-08-18 13:29:39 -04:00
// Setup editor arguments for SCC.
string EditorArguments = String . Empty ;
if ( P4Enabled )
{
2014-04-02 18:09:23 -04:00
EditorArguments = String . Format ( "-SCCProvider={0} -P4Port={1} -P4User={2} -P4Client={3} -P4Passwd={4}" , "Perforce" , P4Env . P4Port , P4Env . User , P4Env . Client , P4 . GetAuthenticationToken ( ) ) ;
2014-08-18 13:29:39 -04:00
}
else
{
EditorArguments = String . Format ( "-SCCProvider={0}" , "None" ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-18 13:29:39 -04:00
// Setup commandlet arguments for SCC.
string CommandletSCCArguments = String . Empty ;
if ( P4Enabled ) { CommandletSCCArguments + = ( string . IsNullOrEmpty ( CommandletSCCArguments ) ? "" : " " ) + "-EnableSCC" ; }
if ( ! AllowSubmit ) { CommandletSCCArguments + = ( string . IsNullOrEmpty ( CommandletSCCArguments ) ? "" : " " ) + "-DisableSCCSubmit" ; }
2014-03-14 14:13:41 -04:00
2014-08-18 13:29:39 -04:00
// Setup commandlet arguments with configurations.
var CommandletArgumentSets = new string [ ]
{
2014-08-28 17:35:37 -04:00
String . Format ( "-config={0}" , @"./Config/Localization/Engine.ini" ) + ( string . IsNullOrEmpty ( CommandletSCCArguments ) ? "" : " " + CommandletSCCArguments ) ,
String . Format ( "-config={0}" , @"./Config/Localization/Editor.ini" ) + ( string . IsNullOrEmpty ( CommandletSCCArguments ) ? "" : " " + CommandletSCCArguments ) ,
2014-09-17 15:42:19 -04:00
String . Format ( "-config={0}" , @"./Config/Localization/EditorTutorials.ini" ) + ( string . IsNullOrEmpty ( CommandletSCCArguments ) ? "" : " " + CommandletSCCArguments ) ,
2014-08-28 17:35:37 -04:00
String . Format ( "-config={0}" , @"./Config/Localization/PropertyNames.ini" ) + ( string . IsNullOrEmpty ( CommandletSCCArguments ) ? "" : " " + CommandletSCCArguments ) ,
String . Format ( "-config={0}" , @"./Config/Localization/ToolTips.ini" ) + ( string . IsNullOrEmpty ( CommandletSCCArguments ) ? "" : " " + CommandletSCCArguments ) ,
String . Format ( "-config={0}" , @"./Config/Localization/WordCount.ini" ) ,
2014-08-18 13:29:39 -04:00
} ;
2014-03-14 14:13:41 -04:00
2014-08-18 13:29:39 -04:00
// Execute commandlet for each set of arguments.
foreach ( var CommandletArguments in CommandletArgumentSets )
{
Log ( "Localization for {0} {1}" , EditorArguments , CommandletArguments ) ;
2014-03-14 14:13:41 -04:00
2014-09-09 19:26:11 -04:00
Log ( "Running UE4Editor to generate localization data" ) ;
2014-03-14 14:13:41 -04:00
2014-08-18 13:29:39 -04:00
string Arguments = String . Format ( "-run=GatherText {0} {1}" , EditorArguments , CommandletArguments ) ;
var RunResult = Run ( EditorExe , Arguments ) ;
2014-03-14 14:13:41 -04:00
2014-08-18 13:29:39 -04:00
if ( RunResult . ExitCode ! = 0 )
{
throw new AutomationException ( "Error while executing localization commandlet '{0}'" , Arguments ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-09-09 19:26:11 -04:00
// Upload all text to OneSky
UploadDirectoryToProject ( GetProject ( oneSkyService , "Unreal Engine" , "Engine" ) , new DirectoryInfo ( CmdEnv . LocalRoot + "/Engine/Content/Localization/Engine" ) , "*.po" ) ;
UploadDirectoryToProject ( GetProject ( oneSkyService , "Unreal Engine" , "Editor" ) , new DirectoryInfo ( CmdEnv . LocalRoot + "/Engine/Content/Localization/Editor" ) , "*.po" ) ;
2014-09-17 15:42:19 -04:00
UploadDirectoryToProject ( GetProject ( oneSkyService , "Unreal Engine" , "EditorTutorials" ) , new DirectoryInfo ( CmdEnv . LocalRoot + "/Engine/Content/Localization/EditorTutorials" ) , "*.po" ) ;
2014-09-09 19:26:11 -04:00
UploadDirectoryToProject ( GetProject ( oneSkyService , "Unreal Engine" , "PropertyNames" ) , new DirectoryInfo ( CmdEnv . LocalRoot + "/Engine/Content/Localization/PropertyNames" ) , "*.po" ) ;
UploadDirectoryToProject ( GetProject ( oneSkyService , "Unreal Engine" , "ToolTips" ) , new DirectoryInfo ( CmdEnv . LocalRoot + "/Engine/Content/Localization/ToolTips" ) , "*.po" ) ;
2014-08-18 13:29:39 -04:00
// Localisation statistics estimator.
if ( P4Enabled )
{
// Available only for P4
var EstimatorExePath = CombinePaths ( CmdEnv . LocalRoot , @"Engine/Binaries/DotNET/TranslatedWordsCountEstimator.exe" ) ;
var StatisticsFilePath = @"\\epicgames.net\root\UE3\Localization\WordCounts\udn.csv" ;
2014-03-14 14:13:41 -04:00
2014-08-18 13:29:39 -04:00
var Arguments = string . Format (
"{0} {1} {2} {3} {4}" ,
StatisticsFilePath ,
P4Env . P4Port ,
P4Env . User ,
P4Env . Client ,
Environment . GetEnvironmentVariable ( "P4PASSWD" ) ) ;
2014-03-14 14:13:41 -04:00
2014-08-18 13:29:39 -04:00
var RunResult = Run ( EstimatorExePath , Arguments ) ;
2014-03-14 14:13:41 -04:00
2014-08-18 13:29:39 -04:00
if ( RunResult . ExitCode ! = 0 )
{
throw new AutomationException ( "Error while executing TranslatedWordsCountEstimator with arguments '{0}'" , Arguments ) ;
}
}
}
2014-09-09 19:26:11 -04:00
private static ProjectGroup GetProjectGroup ( OneSkyService oneSkyService , string GroupName )
{
var launcherGroup = oneSkyService . ProjectGroups . FirstOrDefault ( g = > g . Name = = GroupName ) ;
if ( launcherGroup = = null )
{
launcherGroup = new ProjectGroup ( GroupName , new CultureInfo ( "en" ) ) ;
oneSkyService . ProjectGroups . Add ( launcherGroup ) ;
}
return launcherGroup ;
}
private static OneSky . Project GetProject ( OneSkyService oneSkyService , string GroupName , string ProjectName , string ProjectDescription = "" )
{
var launcherGroup = GetProjectGroup ( oneSkyService , GroupName ) ;
OneSky . Project appProject = launcherGroup . Projects . FirstOrDefault ( p = > p . Name = = ProjectName ) ;
if ( appProject = = null )
{
ProjectType projectType = oneSkyService . ProjectTypes . First ( pt = > pt . Code = = "website" ) ;
appProject = new OneSky . Project ( ProjectName , ProjectDescription , projectType ) ;
launcherGroup . Projects . Add ( appProject ) ;
}
return appProject ;
}
private static void ExportFileToDirectory ( UploadedFile file , DirectoryInfo destination , IEnumerable < CultureInfo > cultures )
{
foreach ( var culture in cultures )
{
var cultureDirectory = new DirectoryInfo ( Path . Combine ( destination . FullName , OneSky . LocaleCodeHelper . ConvertToLocaleCode ( culture . Name ) ) ) ;
if ( ! cultureDirectory . Exists )
{
cultureDirectory . Create ( ) ;
}
using ( var memoryStream = new MemoryStream ( ) )
{
var exportFile = new FileInfo ( Path . Combine ( cultureDirectory . FullName , file . Filename ) ) ;
var exportTranslationState = file . ExportTranslation ( culture , memoryStream ) . Result ;
if ( exportTranslationState = = UploadedFile . ExportTranslationState . Success )
{
memoryStream . Position = 0 ;
using ( Stream fileStream = File . OpenWrite ( exportFile . FullName ) )
{
memoryStream . CopyTo ( fileStream ) ;
Console . WriteLine ( "[SUCCESS] Exporting: " + exportFile . FullName + " Locale: " + OneSky . LocaleCodeHelper . ConvertToLocaleCode ( culture . Name ) ) ;
}
}
else if ( exportTranslationState = = UploadedFile . ExportTranslationState . NoContent )
{
Console . WriteLine ( "[WARNING] Exporting: " + exportFile . FullName + " Locale: " + OneSky . LocaleCodeHelper . ConvertToLocaleCode ( culture . Name ) + " has no translations!" ) ;
}
else
{
Console . WriteLine ( "[FAILED] Exporting: " + exportFile . FullName + " Locale: " + OneSky . LocaleCodeHelper . ConvertToLocaleCode ( culture . Name ) ) ;
}
}
}
}
static void UploadDirectoryToProject ( OneSky . Project project , DirectoryInfo directory , string fileExtension )
{
foreach ( var file in Directory . GetFiles ( directory . FullName , fileExtension , SearchOption . AllDirectories ) )
{
DirectoryInfo parentDirectory = Directory . GetParent ( file ) ;
string localeName = parentDirectory . Name ;
string currentFile = file ;
using ( var fileStream = File . OpenRead ( currentFile ) )
{
// Read the BOM
var bom = new byte [ 3 ] ;
fileStream . Read ( bom , 0 , 3 ) ;
//We want to ignore the utf8 BOM
if ( bom [ 0 ] ! = 0xef | | bom [ 1 ] ! = 0xbb | | bom [ 2 ] ! = 0xbf )
{
fileStream . Position = 0 ;
}
Console . WriteLine ( "Uploading: " + currentFile + " Locale: " + localeName ) ;
var uploadedFile = project . Upload ( Path . GetFileName ( currentFile ) , fileStream , new CultureInfo ( OneSky . LocaleCodeHelper . ConvertFromLocaleCode ( localeName ) ) ) . Result ;
if ( uploadedFile = = null )
{
Console . WriteLine ( "[FAILED] Uploading: " + currentFile + " Locale: " + localeName ) ;
}
else
{
Console . WriteLine ( "[SUCCESS] Uploading: " + currentFile + " Locale: " + localeName ) ;
}
}
}
}
2014-03-14 14:13:41 -04:00
}