private ProjectImportExportInfo GenerateProjectImportExportInfo(string RootWorkingDirectory, string LocalizationConfigFile) { ConfigFile File = new ConfigFile(new FileReference(LocalizationConfigFile), ConfigLineAction.Add); var LocalizationConfig = new ConfigHierarchy(new ConfigFile[] { File }); string DestinationPath; if (!LocalizationConfig.GetString("CommonSettings", "DestinationPath", out DestinationPath)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'DestinationPath', File: '{0}'", LocalizationConfigFile); } string ManifestName; if (!LocalizationConfig.GetString("CommonSettings", "ManifestName", out ManifestName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'ManifestName', File: '{0}'", LocalizationConfigFile); } string ArchiveName; if (!LocalizationConfig.GetString("CommonSettings", "ArchiveName", out ArchiveName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'ArchiveName', File: '{0}'", LocalizationConfigFile); } string PortableObjectName; if (!LocalizationConfig.GetString("CommonSettings", "PortableObjectName", out PortableObjectName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'PortableObjectName', File: '{0}'", LocalizationConfigFile); } string NativeCulture; if (!LocalizationConfig.GetString("CommonSettings", "NativeCulture", out NativeCulture)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'NativeCulture', File: '{0}'", LocalizationConfigFile); } List <string> CulturesToGenerate; if (!LocalizationConfig.GetArray("CommonSettings", "CulturesToGenerate", out CulturesToGenerate)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'CulturesToGenerate', File: '{0}'", LocalizationConfigFile); } bool bUseCultureDirectory; if (!LocalizationConfig.GetBool("CommonSettings", "bUseCultureDirectory", out bUseCultureDirectory)) { // bUseCultureDirectory is optional, default is true bUseCultureDirectory = true; } var ProjectImportExportInfo = new ProjectImportExportInfo(DestinationPath, ManifestName, ArchiveName, PortableObjectName, NativeCulture, CulturesToGenerate, bUseCultureDirectory); ProjectImportExportInfo.CalculateSplitPlatformNames(RootWorkingDirectory); return(ProjectImportExportInfo); }
public override void UploadProjectToLocalizationProvider(string ProjectName, ProjectImportExportInfo ProjectExportInfo) { var XLocApiClient = CreateXLocApiClient(); var TransferServiceClient = CreateTransferServiceClient(); try { var AuthToken = RequestAuthTokenWithRetry(XLocApiClient); // Upload the .po file for the native culture first UploadLatestPOFile(TransferServiceClient, AuthToken, ProjectExportInfo.NativeCulture, ProjectExportInfo); if (bUploadAllCultures) { // Upload the remaining .po files for the other cultures foreach (var Culture in ProjectExportInfo.CulturesToGenerate) { // Skip native culture as we uploaded it above if (Culture != ProjectExportInfo.NativeCulture) { UploadLatestPOFile(TransferServiceClient, AuthToken, Culture, ProjectExportInfo); } } } } finally { XLocApiClient.Close(); TransferServiceClient.Close(); } }
private void DownloadLatestPOFiles(Project OneSkyProject, string Platform, ProjectImportExportInfo ProjectImportInfo) { var OneSkyFileName = GetOneSkyFilename(ProjectImportInfo.PortableObjectName, Platform); var OneSkyFile = OneSkyProject.UploadedFiles.FirstOrDefault(f => f.Filename == OneSkyFileName); // Export if (OneSkyFile != null) { var CulturesToExport = new List <string>(); foreach (var OneSkyCulture in OneSkyProject.EnabledCultures) { // Skip the native culture, as OneSky has mangled it if (OneSkyCulture == ProjectImportInfo.NativeCulture) { continue; } // Only export the OneSky cultures that we care about for this project if (ProjectImportInfo.CulturesToGenerate.Contains(OneSkyCulture)) { CulturesToExport.Add(OneSkyCulture); } } var DestinationDirectory = String.IsNullOrEmpty(Platform) ? new DirectoryInfo(CommandUtils.CombinePaths(RootWorkingDirectory, ProjectImportInfo.DestinationPath)) : new DirectoryInfo(CommandUtils.CombinePaths(RootWorkingDirectory, ProjectImportInfo.DestinationPath, ProjectImportExportInfo.PlatformLocalizationFolderName, Platform)); ExportOneSkyFileToDirectory(OneSkyFile, DestinationDirectory, ProjectImportInfo.PortableObjectName, CulturesToExport, ProjectImportInfo.bUseCultureDirectory); } }
public override void UploadProjectToLocalizationProvider(string ProjectName, ProjectImportExportInfo ProjectExportInfo) { var OneSkyProject = GetOneSkyProject(ProjectName); Func <string, FileInfo> GetPathForCulture = (string Culture) => { if (ProjectExportInfo.bUseCultureDirectory) { return(new FileInfo(Path.Combine(RootWorkingDirectory, ProjectExportInfo.DestinationPath, Culture, ProjectExportInfo.PortableObjectName))); } else { return(new FileInfo(Path.Combine(RootWorkingDirectory, ProjectExportInfo.DestinationPath, ProjectExportInfo.PortableObjectName))); } }; // Upload the .po file for the native culture first UploadFileToOneSky(OneSkyProject, GetPathForCulture(ProjectExportInfo.NativeCulture), ProjectExportInfo.NativeCulture); if (bUploadAllCultures) { // Upload the remaining .po files for the other cultures foreach (var Culture in ProjectExportInfo.CulturesToGenerate) { // Skip native culture as we uploaded it above if (Culture != ProjectExportInfo.NativeCulture) { UploadFileToOneSky(OneSkyProject, GetPathForCulture(Culture), Culture); } } } }
public override void UploadProjectToLocalizationProvider(string ProjectName, ProjectImportExportInfo ProjectExportInfo) { var OneSkyProject = GetOneSkyProject(ProjectName); // Upload the .po file for the native culture first UploadFileToOneSky(OneSkyProject, ProjectExportInfo.NativeCulture, null, ProjectExportInfo); foreach (var Platform in ProjectExportInfo.SplitPlatformNames) { UploadFileToOneSky(OneSkyProject, ProjectExportInfo.NativeCulture, Platform, ProjectExportInfo); } if (bUploadAllCultures) { // Upload the remaining .po files for the other cultures foreach (var Culture in ProjectExportInfo.CulturesToGenerate) { // Skip native culture as we uploaded it above if (Culture != ProjectExportInfo.NativeCulture) { UploadFileToOneSky(OneSkyProject, Culture, null, ProjectExportInfo); foreach (var Platform in ProjectExportInfo.SplitPlatformNames) { UploadFileToOneSky(OneSkyProject, Culture, Platform, ProjectExportInfo); } } } } }
private ProjectInfo GenerateProjectInfo(string RootWorkingDirectory, string ProjectName, IReadOnlyList <string> LocalizationStepNames) { var LocalizationSteps = new List <ProjectStepInfo>(); ProjectImportExportInfo ImportInfo = null; ProjectImportExportInfo ExportInfo = null; // Projects generated by the localization dashboard will use multiple config files that must be run in a specific order // Older projects (such as the Engine) would use a single config file containing all the steps // Work out which kind of project we're dealing with... var MonolithicConfigFile = CombinePaths(RootWorkingDirectory, String.Format(@"Config/Localization/{0}.ini", ProjectName)); if (File.Exists(MonolithicConfigFile)) { LocalizationSteps.Add(new ProjectStepInfo("Monolithic", MonolithicConfigFile)); ImportInfo = GenerateProjectImportExportInfo(RootWorkingDirectory, MonolithicConfigFile); ExportInfo = ImportInfo; } else { var FileSuffixes = new[] { new { Suffix = "Gather", Required = LocalizationStepNames.Contains("Gather") }, new { Suffix = "Import", Required = LocalizationStepNames.Contains("Import") || LocalizationStepNames.Contains("Download") }, // Downloading needs the parsed ImportInfo new { Suffix = "Export", Required = LocalizationStepNames.Contains("Gather") || LocalizationStepNames.Contains("Upload") }, // Uploading needs the parsed ExportInfo new { Suffix = "Compile", Required = LocalizationStepNames.Contains("Compile") }, new { Suffix = "GenerateReports", Required = false } }; foreach (var FileSuffix in FileSuffixes) { var ModularConfigFile = CombinePaths(RootWorkingDirectory, String.Format(@"Config/Localization/{0}_{1}.ini", ProjectName, FileSuffix.Suffix)); if (File.Exists(ModularConfigFile)) { LocalizationSteps.Add(new ProjectStepInfo(FileSuffix.Suffix, ModularConfigFile)); if (FileSuffix.Suffix == "Import") { ImportInfo = GenerateProjectImportExportInfo(RootWorkingDirectory, ModularConfigFile); } else if (FileSuffix.Suffix == "Export") { ExportInfo = GenerateProjectImportExportInfo(RootWorkingDirectory, ModularConfigFile); } } else if (FileSuffix.Required) { throw new AutomationException("Failed to find a required config file! '{0}'", ModularConfigFile); } } } return(new ProjectInfo(ProjectName, LocalizationSteps, ImportInfo, ExportInfo)); }
private ProjectImportExportInfo GenerateProjectImportExportInfo(string LocalizationConfigFile) { var ProjectImportExportInfo = new ProjectImportExportInfo(); ConfigFile File = new ConfigFile(new FileReference(LocalizationConfigFile), ConfigLineAction.Add); var LocalizationConfig = new ConfigHierarchy(new ConfigFile[] { File }); if (!LocalizationConfig.GetString("CommonSettings", "DestinationPath", out ProjectImportExportInfo.DestinationPath)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'DestinationPath', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetString("CommonSettings", "ManifestName", out ProjectImportExportInfo.ManifestName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'ManifestName', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetString("CommonSettings", "ArchiveName", out ProjectImportExportInfo.ArchiveName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'ArchiveName', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetString("CommonSettings", "PortableObjectName", out ProjectImportExportInfo.PortableObjectName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'PortableObjectName', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetString("CommonSettings", "NativeCulture", out ProjectImportExportInfo.NativeCulture)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'NativeCulture', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetArray("CommonSettings", "CulturesToGenerate", out ProjectImportExportInfo.CulturesToGenerate)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'CulturesToGenerate', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetBool("CommonSettings", "bUseCultureDirectory", out ProjectImportExportInfo.bUseCultureDirectory)) { // bUseCultureDirectory is optional, default is true ProjectImportExportInfo.bUseCultureDirectory = true; } return(ProjectImportExportInfo); }
public override void DownloadProjectFromLocalizationProvider(string ProjectName, ProjectImportExportInfo ProjectImportInfo) { var XLocApiClient = CreateXLocApiClient(); try { var AuthToken = RequestAuthTokenWithRetry(XLocApiClient); // Create changelist for backed up POs from XLoc. int XLocDownloadedPOChangeList = 0; if (CommandUtils.P4Enabled) { XLocDownloadedPOChangeList = CommandUtils.P4.CreateChange(CommandUtils.P4Env.Client, "XLoc downloaded PO backup."); } // Get the latest files for each culture. foreach (var Culture in ProjectImportInfo.CulturesToGenerate) { // Skip the native culture, as XLoc doesn't have an entry for it if (Culture == ProjectImportInfo.NativeCulture) { continue; } DownloadLatestPOFile(XLocApiClient, AuthToken, Culture, ProjectImportInfo, XLocDownloadedPOChangeList); } // Submit changelist for backed up POs from OneSky. if (CommandUtils.P4Enabled) { int SubmittedChangeList; CommandUtils.P4.Submit(XLocDownloadedPOChangeList, out SubmittedChangeList); } } finally { XLocApiClient.Close(); } }
private void UploadLatestPOFile(TransferServiceClient TransferServiceClient, string AuthToken, string Culture, ProjectImportExportInfo ProjectExportInfo) { var SourceDirectory = new DirectoryInfo(CommandUtils.CombinePaths(RootWorkingDirectory, ProjectExportInfo.DestinationPath)); var CultureDirectory = (ProjectExportInfo.bUseCultureDirectory) ? new DirectoryInfo(Path.Combine(SourceDirectory.FullName, Culture)) : SourceDirectory; var FileToUpload = new FileInfo(Path.Combine(CultureDirectory.FullName, ProjectExportInfo.PortableObjectName)); var XLocFilename = GetXLocFilename(ProjectExportInfo.PortableObjectName); using (var FileStream = FileToUpload.OpenRead()) { // We need to leave the language ID field blank for the native culture to avoid XLoc trying to process it as translated source, rather than raw source text var EpicCultureToXLocLanguageId = GetEpicCultureToXLocLanguageId(); var LanguageId = (Culture == ProjectExportInfo.NativeCulture) ? "" : EpicCultureToXLocLanguageId[Culture]; var FileUploadMetaData = new XLoc.Contracts.GameFileUploadInfo(); FileUploadMetaData.CaseSensitive = false; FileUploadMetaData.FileName = XLocFilename; FileUploadMetaData.HistoricalTranslation = false; FileUploadMetaData.LanguageId = LanguageId; FileUploadMetaData.LocalizationId = Config.LocalizationId; FileUploadMetaData.PlatformId = "!"; Console.WriteLine("Uploading: '{0}' as '{1}' ({2})", FileToUpload.FullName, XLocFilename, Culture); try { TransferServiceClient.UploadGameFile(Config.APIKey, AuthToken, FileUploadMetaData, FileToUpload.Length, FileStream); Console.WriteLine("[SUCCESS] Uploading: '{0}' ({1})", FileToUpload.FullName, Culture); } catch (Exception Ex) { Console.WriteLine("[FAILED] Uploading: '{0}' ({1}) - {2}", FileToUpload.FullName, Culture, Ex); } } }
private void DownloadLatestPOFile(XLocApiClient XLocApiClient, string AuthToken, string Culture, ProjectImportExportInfo ProjectImportInfo, int XLocDownloadedPOChangeList) { var XLocFilename = GetXLocFilename(ProjectImportInfo.PortableObjectName); // This will throw if the requested culture is invalid, but we don't want to let that kill the whole gather var LatestBuildXml = ""; try { var EpicCultureToXLocLanguageId = GetEpicCultureToXLocLanguageId(); LatestBuildXml = RequestLatestBuild(XLocApiClient, AuthToken, EpicCultureToXLocLanguageId[Culture]); } catch (Exception Ex) { BuildCommand.LogWarning("RequestLatestBuild failed for {0}. {1}", Culture, Ex); return; } var POFileUri = ""; var BuildsXmlDoc = new XmlDocument(); BuildsXmlDoc.LoadXml(LatestBuildXml); var BuildElem = BuildsXmlDoc["Build"]; if (BuildElem != null) { var BuildFilesElem = BuildElem["BuildFiles"]; if (BuildFilesElem != null) { foreach (XmlNode BuildFile in BuildFilesElem) { bool IsCorrectFile = false; // Is this the file we want? var GameFileElem = BuildFile["GameFile"]; if (GameFileElem != null) { var GameFileNameElem = GameFileElem["Name"]; if (GameFileNameElem != null && GameFileNameElem.InnerText == XLocFilename) { IsCorrectFile = true; } } if (IsCorrectFile) { var BuildFileDownloadUriElem = BuildFile["DownloadUri"]; if (BuildFileDownloadUriElem != null) { POFileUri = BuildFileDownloadUriElem.InnerText; break; } } } } } if (!String.IsNullOrEmpty(POFileUri)) { var DestinationDirectory = new DirectoryInfo(CommandUtils.CombinePaths(RootWorkingDirectory, ProjectImportInfo.DestinationPath)); var CultureDirectory = (ProjectImportInfo.bUseCultureDirectory) ? new DirectoryInfo(Path.Combine(DestinationDirectory.FullName, Culture)) : DestinationDirectory; if (!CultureDirectory.Exists) { CultureDirectory.Create(); } var HTTPRequest = WebRequest.Create(POFileUri); HTTPRequest.Method = "GET"; using (var Response = (HttpWebResponse)XLocUtils.GetWebResponse(HTTPRequest)) { if (Response.StatusCode != HttpStatusCode.OK) { BuildCommand.LogWarning("HTTP Request to '{0}' failed. {1}", POFileUri, Response.StatusDescription); return; } using (var ResponseStream = Response.GetResponseStream()) { var ExportFile = new FileInfo(Path.Combine(CultureDirectory.FullName, ProjectImportInfo.PortableObjectName)); // Write out the updated PO file so that the gather commandlet will import the new data from it { var ExportFileWasReadOnly = false; if (ExportFile.Exists) { // We're going to clobber the existing PO file, so make sure it's writable (it may be read-only if in Perforce) ExportFileWasReadOnly = ExportFile.IsReadOnly; ExportFile.IsReadOnly = false; } using (var FileStream = ExportFile.Open(FileMode.Create)) { ResponseStream.CopyTo(FileStream); Console.WriteLine("[SUCCESS] Exporting: '{0}' as '{1}' ({2})", XLocFilename, ExportFile.FullName, Culture); } if (ExportFileWasReadOnly) { ExportFile.IsReadOnly = true; } } // Also update the back-up copy so we can diff against what we got from XLoc, and what the gather commandlet produced { var ExportFileCopy = new FileInfo(Path.Combine(ExportFile.DirectoryName, String.Format("{0}_FromXLoc{1}", Path.GetFileNameWithoutExtension(ExportFile.Name), ExportFile.Extension))); var ExportFileCopyWasReadOnly = false; if (ExportFileCopy.Exists) { // We're going to clobber the existing PO file, so make sure it's writable (it may be read-only if in Perforce) ExportFileCopyWasReadOnly = ExportFileCopy.IsReadOnly; ExportFileCopy.IsReadOnly = false; } ExportFile.CopyTo(ExportFileCopy.FullName, true); if (ExportFileCopyWasReadOnly) { ExportFileCopy.IsReadOnly = true; } // Add/check out backed up POs from OneSky. if (CommandUtils.P4Enabled) { UE4Build.AddBuildProductsToChangelist(XLocDownloadedPOChangeList, new List <string>() { ExportFileCopy.FullName }); } } } } } }
public override void DownloadProjectFromLocalizationProvider(string ProjectName, ProjectImportExportInfo ProjectImportInfo) { var OneSkyFileName = GetOneSkyFilename(ProjectImportInfo.PortableObjectName); var OneSkyProject = GetOneSkyProject(ProjectName); var OneSkyFile = OneSkyProject.UploadedFiles.FirstOrDefault(f => f.Filename == OneSkyFileName); // Create changelist for backed up POs from OneSky. int OneSkyDownloadedPOChangeList = 0; if (CommandUtils.P4Enabled) { OneSkyDownloadedPOChangeList = CommandUtils.P4.CreateChange(CommandUtils.P4Env.Client, "OneSky downloaded PO backup."); } //Export if (OneSkyFile != null) { var CulturesToExport = new List <string>(); foreach (var OneSkyCulture in OneSkyProject.EnabledCultures) { // Only export the OneSky cultures that we care about for this project if (ProjectImportInfo.CulturesToGenerate.Contains(OneSkyCulture)) { CulturesToExport.Add(OneSkyCulture); } } ExportOneSkyFileToDirectory(OneSkyFile, new DirectoryInfo(CommandUtils.CombinePaths(RootWorkingDirectory, ProjectImportInfo.DestinationPath)), ProjectImportInfo.PortableObjectName, CulturesToExport, ProjectImportInfo.bUseCultureDirectory, OneSkyDownloadedPOChangeList); } // Submit changelist for backed up POs from OneSky. if (CommandUtils.P4Enabled) { int SubmittedChangeList; CommandUtils.P4.Submit(OneSkyDownloadedPOChangeList, out SubmittedChangeList); } }
public override void DownloadProjectFromLocalizationProvider(string ProjectName, ProjectImportExportInfo ProjectImportInfo) { var OneSkyFileName = GetOneSkyFilename(ProjectImportInfo.PortableObjectName); var OneSkyProject = GetOneSkyProject(ProjectName); var OneSkyFile = OneSkyProject.UploadedFiles.FirstOrDefault(f => f.Filename == OneSkyFileName); // Export if (OneSkyFile != null) { var CulturesToExport = new List <string>(); foreach (var OneSkyCulture in OneSkyProject.EnabledCultures) { // Skip the native culture, as OneSky has mangled it if (OneSkyCulture == ProjectImportInfo.NativeCulture) { continue; } // Only export the OneSky cultures that we care about for this project if (ProjectImportInfo.CulturesToGenerate.Contains(OneSkyCulture)) { CulturesToExport.Add(OneSkyCulture); } } ExportOneSkyFileToDirectory(OneSkyFile, new DirectoryInfo(CommandUtils.CombinePaths(RootWorkingDirectory, ProjectImportInfo.DestinationPath)), ProjectImportInfo.PortableObjectName, CulturesToExport, ProjectImportInfo.bUseCultureDirectory); } }
public override void DownloadProjectFromLocalizationProvider(string ProjectName, ProjectImportExportInfo ProjectImportInfo) { var XLocApiClient = CreateXLocApiClient(); try { var AuthToken = RequestAuthTokenWithRetry(XLocApiClient); // Get the latest files for each culture. foreach (var Culture in ProjectImportInfo.CulturesToGenerate) { // Skip the native culture, as XLoc doesn't have an entry for it if (Culture == ProjectImportInfo.NativeCulture) { continue; } DownloadLatestPOFile(XLocApiClient, AuthToken, Culture, ProjectImportInfo); } } finally { XLocApiClient.Close(); } }
public override void DownloadProjectFromLocalizationProvider(string ProjectName, ProjectImportExportInfo ProjectImportInfo) { var OneSkyProject = GetOneSkyProject(ProjectName); DownloadLatestPOFiles(OneSkyProject, null, ProjectImportInfo); foreach (var Platform in ProjectImportInfo.SplitPlatformNames) { DownloadLatestPOFiles(OneSkyProject, Platform, ProjectImportInfo); } }
private void UploadFileToOneSky(OneSky.Project OneSkyProject, string Culture, string Platform, ProjectImportExportInfo ProjectExportInfo) { var SourceDirectory = String.IsNullOrEmpty(Platform) ? new DirectoryInfo(CommandUtils.CombinePaths(RootWorkingDirectory, ProjectExportInfo.DestinationPath)) : new DirectoryInfo(CommandUtils.CombinePaths(RootWorkingDirectory, ProjectExportInfo.DestinationPath, ProjectImportExportInfo.PlatformLocalizationFolderName, Platform)); var CultureDirectory = (ProjectExportInfo.bUseCultureDirectory) ? new DirectoryInfo(Path.Combine(SourceDirectory.FullName, Culture)) : SourceDirectory; var FileToUpload = new FileInfo(Path.Combine(CultureDirectory.FullName, ProjectExportInfo.PortableObjectName)); using (var FileStream = FileToUpload.OpenRead()) { // Read the BOM var UTF8BOM = new byte[3]; FileStream.Read(UTF8BOM, 0, 3); // We want to ignore the utf8 BOM if (UTF8BOM[0] != 0xef || UTF8BOM[1] != 0xbb || UTF8BOM[2] != 0xbf) { FileStream.Position = 0; } var OneSkyFileName = GetOneSkyFilename(ProjectExportInfo.PortableObjectName, Platform); Console.WriteLine("Uploading: '{0}' as '{1}' ({2})", FileToUpload.FullName, OneSkyFileName, Culture); var UploadedFile = UploadOneSkyTranslationWithRetry(OneSkyProject, OneSkyFileName, Culture, FileStream); if (UploadedFile == null) { Console.WriteLine("[FAILED] Uploading: '{0}' ({1})", FileToUpload.FullName, Culture); } else { Console.WriteLine("[SUCCESS] Uploading: '{0}' ({1})", FileToUpload.FullName, Culture); } } }