Use Trados 2024 API to programmatically create a localization project for automation, but having errors. Please help check How I can fix it.

I use Trados 2024 API for project automation testing. My first step is to set up a project, I have activated Trados 2024. 

When I run the code, it displays the errors, my sample code:

using Sdl.Core.Globalization;
using Sdl.Core.Settings;
using Sdl.Core.Globalization.Async;
using Sdl.Desktop.Platform;
using Sdl.FileTypeSupport.Framework.Core;
using Sdl.FileTypeSupport.Framework.BilingualApi;
using Sdl.FileTypeSupport.Framework.IntegrationApi;
using Sdl.FileTypeSupport.Framework.NativeApi;
using Sdl.FileTypeSupport.Filters;
using Sdl.ProjectApi;
using Sdl.ProjectAutomation.Core;
using Sdl.ProjectAutomation.FileBased;
using Sdl.ProjectAutomation.Settings;
using Sdl.TranslationStudio.LanguageCloud;
using Sdl.LanguagePlatform.Core;
using Sdl.LanguagePlatform.TranslationMemory;
using Sdl.LanguagePlatform.TranslationMemoryApi;
using Sdl.LanguagePlatform.Core.Tokenization;
using System.Collections.Generic;
using Sdl.FileTypeSupport.Filters.Xml.Dita.Settings;
using Sdl.FileTypeSupport.Framework.Core.Settings;
using Sdl.ProjectAutomation.AutomaticTasks;
using System.IO;
using System;


namespace AutoTrados
{
class Program
{

static void Main(string[] args)
{
try
{
string projectName = "MySDLProject";
string projectPath = @"C:\Users\Felix\Documents\Studio 2024\Projects\";
string sourceLanguageCode = "en-US";
string[] targetLanguageCodes = { "fr-FR", "zh-CN" }; // target language array

// initialize language object
Language sourceLanguage = new Language(sourceLanguageCode);

// initialize target language array
Language[] targetLanguages = new Language[targetLanguageCodes.Length];
for (int i = 0; i < targetLanguageCodes.Length; i++)
{
targetLanguages[i] = new Language(targetLanguageCodes[i]);
}

string localProjectFolder = Path.Combine(projectPath, projectName);
if (!Directory.Exists(localProjectFolder))
{
Directory.CreateDirectory(localProjectFolder);
}

// Project Info
ProjectInfo info = new ProjectInfo
{
Name = projectName,
Description = "First trial project.",
SourceLanguage = sourceLanguage,
TargetLanguages = targetLanguages,
DueDate = DateTime.Now.AddDays(3),
LocalProjectFolder = localProjectFolder,

};

FileBasedProject newProject = new FileBasedProject(info);

Console.WriteLine("Project initialized successfully.");
}

catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine($"Stack Trace: {ex.StackTrace}");
}
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();

}
}
}

it shows the errors:

2024-12-12 21:00:45,001 ERROR Sdl.Desktop.Platform.Perpetual.PerpetualLicense - Error initializing perpetual license
Sdl.Core.PluginFramework.PluginFrameworkException: No Application specific plug-in directory found.
at Sdl.Core.PluginFramework.DefaultPluginLocator..ctor()
at Sdl.Core.PluginFramework.PluginManager.get_DefaultPluginRegistry()
at Sdl.Common.Licensing.Provider.Core.LicensingProviderManager.get_LicensingProviderFactories()
at Sdl.Common.Licensing.Provider.Core.LicensingProviderManager.CreateProvider(ILicensingProviderConfiguration config, String preferredProviderId, ILoggerFactory loggerFactory)
at Sdl.Common.Licensing.Provider.Core.ApplicationLicenseManager.GetCurrentLicensingProvider()
at Sdl.Desktop.Platform.Perpetual.PerpetualLicense.Initialize()
Error: No Application specific plug-in directory found.
Stack Trace: at Sdl.ProjectAutomation.FileBased.FileBasedProject.GetDefaultProjectTemplateReference()
at Sdl.ProjectAutomation.FileBased.FileBasedProject..ctor(ProjectInfo projectInfo)
at AutoTrados.Program.Main(String[] args) in C:\Users\FSun1\source\repos\AutoTrados\AutoTrados\Program.cs:line 71
Press Enter to exit.

Parents
  • Hi  , sorry to hear yr running into issues with your first attempts integrating the API.  Let's see if we can get you up and running.

    It looks like you're developing a standalone application that uses the Trados API, rather than a plugin that's loaded within the Trados Studio UI. When developing standalone applications with the Trados API, there are some additional considerations to ensure all dependencies and components are correctly resolved.

    Let's first try to understand the errors:

    ```Error initializing perpetual license Sdl.Core.PluginFramework.PluginFrameworkException: No Application specific plug-in directory found.```

    Note: This error indicates that the application cannot locate the necessary plug-in directory required for initializing certain components within the Trados API. Specifically, it's struggling to find the application-specific plugins and resources that are usually available when running within the Trados Studio environment.

    The stack trace points to the issue occurring when the API tries to get the default project template:

    ```at Sdl.ProjectAutomation.FileBased.FileBasedProject.GetDefaultProjectTemplateReference()```

    There are a couple of ways to resolve this issue, you could setup a Dependency Resolver to resolve the dependencies, which is a bit more involved, or you could simply set the Output Path of your project to the Trados Studio Installation Directory.  I would recommend the second option, as follows:

    Set the Output Path of Your Project to the Trados Studio Installation Directory

    By setting the output directory of your project to the Trados Studio installation folder, you ensure that your application can find all the necessary dependencies when it runs. This is because all the required DLLs for the API's and resources are located in that directory.

    Steps:

    Change Output Directory:

    - In your Visual Studio project, right-click on your project in the Solution Explorer and select Properties.

    - Go to the Build tab.

    - Set the Output path to the Trados Studio installation directory, for example:

    ```C:\Program Files (x86)\Trados\Trados Studio\Studio18\```

    Rebuild Your Project:

    - Build your project to output the executable into the Trados Studio directory.

    Run Your Application:

    - Navigate to the Trados Studio installation directory.

    - Run your executable from there.

    Let me know how it goes

  • Hi  , great thanks! I changed the Output path, it worked to create a project. My questions is, if using current solution, I need to run the application by Administrator, because only administrator has the access to Studio18 for writing; If I change to another Output Path, how could I configure? As I debug, if out path is original in source code path, It needs license, plug-in registry, initialization, etc.

    One more question, I use Trados API to do automatic tasks after creating project:

    LocalProjectSettings settings = new LocalProjectSettings
    {
    ProjectName = "MyTestProject",
    ProjectPath = @"C:\Users\FSun1\Documents\Studio 2024\project\",
    SourceLanguage = new Language(CultureInfo.GetCultureInfo("en-US").Name),
    TargetLanguages = new Language[] {
    new Language(CultureInfo.GetCultureInfo("de-DE").Name),
    new Language(CultureInfo.GetCultureInfo("zh-CN").Name) },
    InputFolder = @"C:\Users\FSun1\Desktop\New folder\test\release-notes\",
    TMPath = @"C:\Users\FSun1\Desktop\New folder\test\tm",
    };

    string ProjectFolderPath = Path.Combine(settings.ProjectPath, settings.ProjectName);
    if (!Directory.Exists(ProjectFolderPath))
    {
    Directory.CreateDirectory(ProjectFolderPath);
    }

    //create project
    FileBasedProject newProject = CreateProject(settings, ProjectFolderPath);

    // add folder of files
    newProject.AddFolderWithFiles(settings.InputFolder, true);

    //for perfect match use
    // newProject.AddBilingualReferenceFiles(GetBilingualFileMappings(info.TargetLanguages, files, @"c:\ProjectFiles\PreviousProjectFiles"));

    //scan files
    AutomaticTask scanFiles = newProject.RunAutomaticTask(newProject.GetSourceLanguageFiles().GetIds(), AutomaticTaskTemplateIds.Scan);

    // add TMs
    AddMasterTMs(newProject, settings.TMPath);

    // prepare workflow
    PrepareFiles(newProject);

    newProject.Save();
    }

    private static FileBasedProject CreateProject(LocalProjectSettings settings, string folderPath)
    {
    ProjectInfo info = new ProjectInfo
    {
    Name = settings.ProjectName,
    SourceLanguage = settings.SourceLanguage,
    TargetLanguages = settings.TargetLanguages,
    LocalProjectFolder = folderPath,
    DueDate = DateTime.Now.AddDays(3)
    };

    // Get project template
    ProjectTemplateReference templateReference = GetDefaultProjectTemplateReference();


    FileBasedProject createdProject = new FileBasedProject(info, templateReference);

    return createdProject;
    }

    public static void AddMasterTMs(FileBasedProject project, string path)
    {
    Language trgLangDe = new Language(CultureInfo.GetCultureInfo("de-DE").Name);
    Language trgLangZh = new Language(CultureInfo.GetCultureInfo("zh-CN").Name);

    TranslationProviderConfiguration tmConfigEnDe = project.GetTranslationProviderConfiguration(trgLangDe);
    TranslationProviderConfiguration tmConfigEnZh = project.GetTranslationProviderConfiguration(trgLangZh);

    TranslationProviderCascadeEntry[] tmEntriesEnDe =
    {
    new TranslationProviderCascadeEntry(path + "FTOptix_Doc_NonRef_DEU.sdltm", true, true, true, 0),
    // new TranslationProviderCascadeEntry(path + "General En-De.sdltm", true, true, true, 2),
    };

    TranslationProviderCascadeEntry[] tmEntriesEnZh =
    {
    new TranslationProviderCascadeEntry(path + "FTOptix_Doc_NonRef_CHS.sdltm", true, true, true, 0),
    //new TranslationProviderCascadeEntry(path + "General En-Fr.sdltm", true, true, true, 2)
    };


    for (int i = 0; i < tmEntriesEnDe.Length; i++)
    {
    tmConfigEnDe.Entries.Add(tmEntriesEnDe[i]);
    }

    for (int i = 0; i < tmEntriesEnZh.Length; i++)
    {
    tmConfigEnDe.Entries.Add(tmEntriesEnZh[i]);
    }

    project.UpdateTranslationProviderConfiguration(trgLangDe, tmConfigEnDe);
    project.UpdateTranslationProviderConfiguration(trgLangZh, tmConfigEnZh);

    }
    public static void PrepareFiles(FileBasedProject project)
    {
    List<TaskStatusEventArgs> taskStatusEventArgsList = new List<TaskStatusEventArgs>();
    List<MessageEventArgs> messageEventArgsList = new List<MessageEventArgs>();

    ProjectFile[] sourceFiles = project.GetSourceLanguageFiles();

    for (int i = 0; i < sourceFiles.Length; i++)
    {

    Guid[] fileId = { sourceFiles[i].Id };
    AutomaticTask convertTask = project.RunAutomaticTask(
    fileId,
    AutomaticTaskTemplateIds.ConvertToTranslatableFormat);

    AutomaticTask copyTask = project.RunAutomaticTask(
    fileId,
    AutomaticTaskTemplateIds.CopyToTargetLanguages);

    }

    ProcessTargetLanguageFilesExtended(project, "de-DE");
    ProcessTargetLanguageFilesExtended(project, "zh-CN");
    }

    public static void ProcessTargetLanguageFilesExtended(FileBasedProject project, string locale)
    {
    List<TaskStatusEventArgs> taskStatusEventArgsList = new List<TaskStatusEventArgs>();
    List<MessageEventArgs> messageEventArgsList = new List<MessageEventArgs>();

    ProjectFile[] targetFiles = project.GetTargetLanguageFiles(new Language(CultureInfo.GetCultureInfo(locale).Name));

    // project.AddBilingualReferenceFiles(GetBilingualFileMappings(new Language[] { targetLanguage }, targetFiles, @"c:\ProjectFiles\PreviousProjectFiles"));
    /*
    project.RunAutomaticTask(targetFiles.GetIds(),AutomaticTaskTemplateIds.PerfectMatch);
    */
    AutomaticTask analyzeTask = project.RunAutomaticTask(targetFiles.GetIds(), AutomaticTaskTemplateIds.AnalyzeFiles);
    CheckEvents(taskStatusEventArgsList, messageEventArgsList);

    // Save Analysis Report
    //Guid reportId = analyzeTask.Reports[0].Id;
    //project.SaveTaskReportAs(reportId, @"C:\Users\FSun1\Documents\Studio 2024\report\Analysis_report.xls", ReportFormat.Excel);

    //pre-translate files
    project.RunAutomaticTask(targetFiles.GetIds(), AutomaticTaskTemplateIds.PreTranslateFiles);
    CheckEvents(taskStatusEventArgsList, messageEventArgsList);

    //populate project TMs
    project.RunAutomaticTask(targetFiles.GetIds(), AutomaticTaskTemplateIds.PopulateProjectTranslationMemories);
    CheckEvents(taskStatusEventArgsList, messageEventArgsList);
    }
    private static void CheckEvents(List<TaskStatusEventArgs> taskStatusEventArgsList, List<MessageEventArgs> messageEventArgsList)
    {
    // loop through the available statuses and messages
    foreach (var item in taskStatusEventArgsList)
    {
    switch (item.Status)
    {
    case TaskStatus.Assigned:
    break;
    case TaskStatus.Cancelled:
    break;
    case TaskStatus.Cancelling:
    break;
    case TaskStatus.Completed:
    break;
    case TaskStatus.Created:
    break;
    case TaskStatus.Invalid:
    break;
    case TaskStatus.Rejected:
    break;
    case TaskStatus.Started:
    break;
    case TaskStatus.Failed:
    break;
    default:
    break;
    }
    }
    // at the end clear task statuses and messages
    taskStatusEventArgsList.Clear();
    messageEventArgsList.Clear();
    }

    private static ProjectTemplateReference GetDefaultProjectTemplateReference()
    {
    try
    {
    string defaultTemplatePath = @"C:\Program Files (x86)\Trados\Trados Studio\Studio18\ProjectTemplates\Default.sdltpl";
    if (!File.Exists(defaultTemplatePath))
    {
    throw new FileNotFoundException("Default project template not found: " + defaultTemplatePath);
    }
    return new ProjectTemplateReference(defaultTemplatePath);

    }
    catch (Exception exception)
    {
    throw new InvalidOperationException("Could not find the default project template. Run Trados Studio to initialize the default project template.", exception);
    }
    }

    }
    }

    It shows the error message:Screenshot of a debug log with multiple entries, highlighting an error message about a 'DirectoryNotFoundException' and a file path that could not be found.

    I opened the project, but in the project the source files have not been converted into Bilingual SDLXLIFF files: AutomaticTask convertTask = project.RunAutomaticTask(
    fileId,
    AutomaticTaskTemplateIds.ConvertToTranslatableFormat); it does not have effect. Do you know why or if my code has problem?
    Screenshot of a file explorer window showing a project directory with folders named 'de-DE', 'en-US', 'zh-CN', and a file 'MyTestProject.sdlproj'. The 'de-DE' folder is highlighted.



    Generated Image Alt-Text
    [edited by: RWS Community AI at 11:26 AM (GMT 0) on 18 Dec 2024]
  • Hi , great to see you making progress.

    Correct, you'd need to open Visual Studio as administrator to build the output in the Trados Studio installation directory.  However, I wouldn't expect you need to be an administrator to run your executable or application, right?

    Please make reference to this sample project to get a better undestanding of how to develop a solution to automate project creation, add tm, analyze etc...

    https://github.com/RWS/trados-studio-api-samples/blob/master/ProjectAutomation/Sdl.SDK.ProjectAutomation.Samples.BatchAnalyze/ProjectCreator.cs

    You can also find some useful information from our public API documentation here: https://developers.rws.com/studio-api-docs/apiconcepts/projectautomation/setting_the_project_information.html?tabs=tabid-1%2Ctabid-2%2Ctabid-3%2Ctabid-4%2Ctabid-5%2Ctabid-6%2Ctabid-7%2Ctabid-8%2Ctabid-9

    Note: There is an entire walkthough to creating the project and adding the resources, analyse, pretranslate, generation of reports etc...

  • Hi  , great thanks for your quick response.

    Yes, I don't want to run always by administrator, we need to deploy the app into our server, so do you have any solution for this?

    For example and API doc, yes, I am referring to them in recent API call, but still don't know why the source files cannot be converted into Bilingual SDL Xliff and don't know the reason.

    Could you help check the following error why object reference not set to an instance? Great thanks!

     Screenshot of a log file with multiple entries. Highlighted error states 'Sdl.ProjectApi.AutomaticTasks.Conversion.ConversionTask - Object reference not set to an instance of an object.'



    Generated Image Alt-Text
    [edited by: RWS Community AI at 6:45 AM (GMT 0) on 19 Dec 2024]
  • Moreover, although it works after I changed the Output path, but after that ,I never open Traods. In no way I can open a trados project including this software, it seems that the Trados software is broken or forbidden after I run the code. Do you know why?

Reply Children
No Data