Searching Terms
Searching the terminology source through your term provider is arguably the most important function of your implementation. A term provider can still be useful without the editing function, but is of no use if no term look-up and term recognition functionality is available.
How to search and recognize terms
When you click inside a segment in Trados Studio, the segment is scanned for any terminology contained in the term resource. If terms are recognized, they are highlighted with a red line and displayed in the Term Recognition window:
You can also manually look up terms in the Termbase Search window:
How to implement the search functionality
Open the MyTerminologyProvider.cs class and go to the Search() function (which is implemented by the AbstractTerminologyProvider interface). This function is called when you click inside a segment or launch a search in the Termbase Search window. Note that Trados Studio passes a number of useful parameters:
- text: the search string. When the user selects a segment in Trados Studio, this will be the source segment text. When you launch a search manually, this will be the search string entered by you.
- maxResultsCount: the maximum number of hits to show, i.e. the search depth.
- mode: the search mode, i.e. fuzzy or normal. When selecting a segment in Trados Studio, the mode is 'fuzzy' by default. When you do a manual lookup, the search mode is 'normal' by default (unless you clicked the Fuzzy Search button in the Termbase Search) window.
- targetRequired: boolean parameter that decides whether source terms without any target term should be shown or not. This parameter is controlled by you through the Trados Studio UI. Depending on the value returned, your implementation needs to decide whether an entry without a target term should be displayed or not.
Below is the page of the Trados Studio UI where the user can, for example, determine the search depth or whether to display entries without a target term:
The Search function returns a list of results to be displayed in Trados Studio. In our simplified implementation, we loop through the glossary text file and look for any matching source terms. We assume that when the search mode is 'normal', we just check whether there are any source terms in the glossary that start with the search string. If the search string is fuzzy, we check whether there are any source terms in the glossary that are contained in the search string (i.e. in the segment). Of course, your 'real-life' implementation might have a much more sophisticated way of performing fuzzy searches than the StartsWith() or Contains() methods. For each search result object, you set the following properties:
- Text: the source term, this will also be the term that is going to be highlighted with a red line in Trados Studio.
- Score: the fuzzy score. In our simple implementation, we will simply set it to 100%. Depending on how you implement your fuzzy logic, you may assign different values.
- Id: the id of the entry that the search result needs to be associated with. Note that in Trados Studio, you do not output the search result list, but rather the entries that you need to construct in a different function (see below). The search result objects are linked to the entries using the unique ID. This is also the reason why, in our implementation, every line in the glossary file is preceded with a unique number.
The Search() function of our implementation would look as shown below:
//Is executed when the user launches a lookup operation in the Termbase Search window,
//or when the user moves to a segment in the Editor of Studio. Moving to a segment
//automatically launches a fuzzy search to retrieve any known terminology.
public IList<SearchResult> Search(string text, ILanguage source, ILanguage destination, int maxResultsCount, SearchMode mode, bool targetRequired)
{
string[] chunks;
List<string> hits = new List<string>();
// open the glossary text file
using (StreamReader glossary = new StreamReader(fileName.Replace("file:///", "")))
{
// skip the first line, as it contains only the language settings
glossary.ReadLine();
while (!glossary.EndOfStream)
{
string thisLine = glossary.ReadLine();
if (thisLine.Trim() == "")
continue;
chunks = thisLine.Split(';');
string sourceTerm = chunks[1].ToLower();
// normal search (triggered from the Termbase Search window)
if (mode.ToString() == "Normal" && sourceTerm.StartsWith(text.ToLower()))
hits.Add(thisLine);
// fuzzy search (corresponds to the Terminology Eecognition)
if (mode.ToString() == "Fuzzy" && text.ToLower().Contains(sourceTerm))
hits.Add(thisLine);
}
}
// Create search results object (hitlist)
var results = new List<SearchResult>();
for (int i = 0; i < hits.Count; i++)
{
chunks = hits[i].Split(';');
// We create the search result object based on the source term
// found in the glossary, we assign the id, which associates the search
// result to the correspoinding entry, and we assume that the search score
// is always 100%.
SearchResult result = new SearchResult
{
Text = chunks[1], // source term
Score = 100,
Id = Convert.ToInt32(chunks[0]) // entry id
};
// Construct the entry object for the current search result
_entry.Add(CreateEntry(chunks[0], chunks[1], chunks[2], chunks[3], destination.Name));
results.Add(result);
}
return results;
}
As mentioned above, the results list needs to be associated with the corresponding entry that you construct in the following helper function:
// This helper function is used to construct the entry content with entry id, source and target term, and
// definition (if applicable)
private Entry CreateEntry(string id, string sourceTerm, string targetTerm, string definitionText, string targetLanguage)
{
// Assign the entry id
Entry thisEntry = new Entry
{
Id = Convert.ToInt32(id)
};
// Add the target language
EntryLanguage trgLanguage = new EntryLanguage
{
Name = targetLanguage
};
// Create the target term
EntryTerm _term = new EntryTerm
{
Value = targetTerm
};
trgLanguage.Terms.Add(_term);
thisEntry.Languages.Add(trgLanguage);
// Also add the definition (if available)
if (definitionText != "")
{
EntryField _definition = new EntryField
{
Name = "Definition",
Value = definitionText
};
thisEntry.Fields.Add(_definition);
}
return thisEntry;
}
Make sure that you add the following entry list object to the terminology provider class:
private List<Entry> _entry = new List<Entry>();
Besides the Search() method, the term provider interface also calls the GetEntry() method, which then outputs the entry with the corresponding entry based on the id parameter:
// Returns the entry for a search result. The entries are associated with the search results
// through the entry id.
public Entry GetEntry(int id)
{
return _entry.FirstOrDefault(_entry => _entry.Id == id);
}