How to programmatically add Termbase to a project with optimal language mapping

Dear All

When attaching a termbase to a project, the languages of the termbase needs to be mapped to the source- and targetlanguage of the project. Often the mapping is not perfect, so French (FR) has to be mapped to French Switzerland (fr-CH) or French France (fr-FR).

http://producthelp.sdl.com/SDK/ProjectAutomationApi/2017/html/7a0aa922-1aa2-4976-afd3-7637104f2def.htm

string[] termbaseIndex = { "English", "German", "French" };

Language projSourceLang = new Language(CultureInfo.GetCultureInfo("en-US"));
Language projTargetLang1 = new Language(CultureInfo.GetCultureInfo("de-DE"));
Language projTargetLang2 = new Language(CultureInfo.GetCultureInfo("fr-FR"));

Here they only show a simple example, where the language is hardcoded, however, i am interested in a general approach for an arbitrary termbase where the languages are extracted from the termbase.

The final touch would be to programmatically add the language to the termbase if it does not contain the project language parent, so if the sourcelanguage is de-CH and the termbase only has FR and IT then add DE.

Best
Marco

  • Former Member
    0 Former Member 3 months ago

    I refer to two points.
    For SDL project file : "LanguageDirection" elements has two languages (a pair) information
    For SDL termbase file : "mtIndexes" table's "locale" column has all languages information
    I guess above two are good enough
    Regards

  • Hi 

    It really depends on the type of terminology provider that you are working with, as you would need to create an instance of the provider to recover a list of available languages (or add them). If this is a Multiterm provider, then you would need to first open the *.sdltb file, and then recover the language indexes from the definition.

    You can reference Sdl.MultiTerm.TMO.Interop.dll to access the multiterm api
    Example:

    using MultitermApplication = Sdl.MultiTerm.TMO.Interop.Application;
    
    var multiterm = new MultitermApplication();
    var repository = multiterm.LocalRepository;
    repository.Connect(string.Empty, string.Empty);
    var termbase = repository.Termbases[0];
    var languageIndexes = termbase.Definition.Indexes;
    



    Having said that, you could potentially create an instance of the provider factory by recovering the extension point from the plugin manager. This might be advantageous in the sense that it is reusing the existing implementation of the GetLanguages() method (overridden from AbstractTerminologyProvider). However, I can only see this working if you are casting the provider to a known interface that allows you to access it in this way.

    I will demonstrate here how you could get access to the provider factory, in case this is useful for you. However, I have never tested this type of scenario, so can't guarantee how reliable this is...

    Also, keep in mind that this type of solution probably won’t work with the integrated multiterm provider, as you would need to cast the provider to IMultiTermTerminologyProvider to first open a connection, which is not possible seeing as this interface is located in Sdl.MultiTerm.Client; not a public API.

    var currentProject = GetProjectController().CurrentProject;
    if (currentProject == null)
    {
    	return;
    }
    
    var termbaseConfiguration = currentProject.GetTermbaseConfiguration();
    var termbaseConfigurationLanguages = termbaseConfiguration.LanguageIndexes;
    
    // identify the termbase/s you are working with; for this example, I reference the default tb
    var defaultTermbase = termbaseConfiguration.Termbases.FirstOrDefault(a => a.Enabled);
    if (defaultTermbase == null)
    {
    	return;
    }
    
    // 1. the path associated with the provider
    var localPath = GetTermbasePath(defaultTermbase);
    if (string.IsNullOrEmpty(localPath))
    {
    	return;
    }
    
    // 2. get a list of the terminology factories from the plugin registry
    var extensionPoint = PluginManager.DefaultPluginRegistry.GetExtensionPoint<TerminologyProviderFactoryAttribute>();
    if (extensionPoint == null)
    {
    	return;
    }
    
    var providerLanguages = new List<ILanguage>();
    
    foreach (var extension in extensionPoint.Extensions)
    {				
    	// 3. identify if the provider is enabled
    	if (!extension.Enabled)
    	{
    		continue;
    	}
    
    	// 4. idetnify if the extension a provider of interest to you
    	// extension.ExtensionType == etc..
    	// extension.Plugin.Id == etc...
    
    	// 5. create an instance of the providers factory
    	var factory = (ITerminologyProviderFactory)extension.CreateInstance();
    	if (factory == null)
    	{
    		continue;
    	}
    				
    	// 6. create an instance of the terminology provider
    	var uri = new Uri("sdltb.file:///" + localPath);
    	var credentials = new TerminologyProviderCredentialStore();
    	var provider = factory.CreateTerminologyProvider(uri, credentials);
    
    	// 7. get a list of the languages from the AbstractTerminologyProvider implementation 
    	providerLanguages = provider.GetLanguages().ToList();							
    }
    
    // 8. check and assign the langauge index.
    foreach (var languageIndex in termbaseConfigurationLanguages)
    {
    	// if the selected index is not assigned, then attempt to assign it automatically, given
    	// that we already have a list of the termbase definition languages.
    	if (string.IsNullOrEmpty(languageIndex.TermbaseIndex))
    	{
    		var language = GuessLanguage(providerLanguages, languageIndex);
    		if (language != null)
    		{
    			languageIndex.TermbaseIndex = language.Name;
    		}
    	}
    }
    
    // 9. update the configuration
    currentProject.UpdateTermbaseConfiguration(termbaseConfiguration);
    
    private static string GetTermbasePath(Termbase defaultTermbase)
    {
    	var termbasePath = string.Empty;
    	if (defaultTermbase is LocalTermbase termbase)
    	{
    		termbasePath = termbase.FilePath;
    	}
    	else
    	{
    		// if server based provider, then parse the Path value from the SettingsXML
    	}
    
    	return termbasePath;
    }    
    
    private static ILanguage GuessLanguage(IEnumerable<ILanguage> definitionLanguages, TermbaseLanguageIndex languageIndex)
    {
    	foreach (var definitionLanguage in definitionLanguages)
    	{
    		if (definitionLanguage.Locale.Name == languageIndex.ProjectLanguage.CultureInfo.Name)
    		{
    			return definitionLanguage;
    		}
    
    		if (definitionLanguage.Locale.ThreeLetterISOLanguageName ==
    			languageIndex.ProjectLanguage.CultureInfo.ThreeLetterISOLanguageName)
    		{
    			return definitionLanguage;
    		}
    
    		if (definitionLanguage.Locale.TwoLetterISOLanguageName ==
    			languageIndex.ProjectLanguage.CultureInfo.TwoLetterISOLanguageName)
    		{
    			return definitionLanguage;
    		}
    	}
    
    	return null;
    }
    
    private static ProjectsController GetProjectController()
    {
    	return SdlTradosStudio.Application.GetController<ProjectsController>();
    }