GroupShare: Adding Translation Units directly via Trados API always results in Discard – expected behaviour?

Hello everyone,

I’m currently experimenting with the Trados APIs to programmatically populate a server-based GroupShare TM (GS 2020 / Studio 2021), and I’ve run into a behaviour that I’d like to better understand or confirm.

Context

  • GroupShare 2020

  • Trados Studio 2021

  • Server-based TM created specifically for testing

  • User has admin roles in GroupShare

  • Importing a TMX manually via Studio works

  • Importing a TMX programmatically via the API also works

However, when trying to add Translation Units directly via the API, nothing is persisted.

What I’m trying to do

I’m using ServerBasedTranslationMemoryLanguageDirection.AddTranslationUnit(...) to insert a simple TU (plain text, no tags).

Below is a simplified example of the code I’m using.
(It does not contain all variables/constants, but should give a clear idea of the approach.)

private static void Main()
{
  try
  {
    AssemblyResolver.Resolve();

    var server = new TranslationProviderServer(
      new Uri(GROUPSHARE_TM_ENDPOINT),
      useWindowsAuthentication: true,
      userName: null,
      password: null);

    var tms = server.GetTranslationMemories(TranslationMemoryProperties.None).ToList();
    Console.WriteLine($"Connection OK. Found {tms.Count} TM(s) on the server:");

    foreach (var t in tms)
    {
      Console.WriteLine($"- {t.Name} | {t.Id}");
    }

    var tmRef = tms.FirstOrDefault(t =>
    string.Equals(t.Name, TM_NAME, StringComparison.OrdinalIgnoreCase));

    if (tmRef == null)
    {
      return;
    }

    var tm = server.GetTranslationMemory(tmRef.Id, TranslationMemoryProperties.None);
    if (tm == null)
    {
      return;
    }

    var sourceCulture = new CultureInfo("en-GB");
    var targetCulture = new CultureInfo("fr-FR");

    var ld = tm.LanguageDirections.GetLanguageDirection("en-GB", "fr-FR");
    if (ld == null)
    {
      return;
    }

    var tu = new TranslationUnit
    {
      SourceSegment = BuildPlainTextSegment(sourceCulture, "Hello world!"),
      TargetSegment = BuildPlainTextSegment(targetCulture, "Bonjour le monde !")
    };

    var importSettings = new ImportSettings();
    var result = ld.AddTranslationUnit(tu, importSettings);

    Console.WriteLine($"Cached TU count: {tm.CachedTranslationUnitCount}");
    Console.WriteLine($"Actual TU count: {tm.GetTranslationUnitCount()}");
    Console.WriteLine($"TM IsReadOnly: {tm.IsReadOnly}");
    Console.WriteLine($"TM SupportsUpdate: {tm.SupportsUpdate}");
    Console.WriteLine($"Has Delete permission: {tm.HasPermission(TranslationMemoryPermissions.Delete)}");
    Console.WriteLine($"Has Add permission: {tm.HasPermission(TranslationMemoryPermissions.Add)}");
    Console.WriteLine($"Has Edit permission: {tm.HasPermission(TranslationMemoryPermissions.Edit)}");
    Console.WriteLine($"ImportResult: {result}");
  }
  catch (Exception ex)
  {
    Console.WriteLine("Error while inserting TU:");
    Console.WriteLine(ex);
  }
}

private static Segment BuildPlainTextSegment(CultureInfo culture, string text)
{
  var segment = new Segment(culture);
  segment.Add(new SdlText(text));
  return segment;
}

Output

After running this code, I consistently get the following output:

Cached TU count: 0
Actual TU count: 0
TM IsReadOnly: False
TM SupportsUpdate: True
Has Delete permission: True
Has Add permission: True
Has Edit permission: True
ImportResult: Discard-(0, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)-OK

So:

  • No exception is thrown

  • Permissions look fine

  • The TM is writable

  • But no TU is added

  • ImportResult always comes back as Discard

Additional observation / question

When switching to a TMX-based approach (i.e. generating a TMX file and importing it via the API), the import works correctly and the TUs are effectively added to the server-based TM.
In contrast, inserting TUs one by one via AddTranslationUnit consistently results in a Discard without any explicit error, even when using an admin account.
This makes me wonder whether direct TU insertion via the API is intentionally restricted in GroupShare, or if there is some server-side policy or design decision that silently discards such inserts.

Is this behaviour expected for server-based GroupShare TMs, and is the recommended or supported approach to populate them exclusively via batch TMX imports rather than direct TU insertion?

Thanks in advance!

Damien



Changed the style of code.
[edited by: Damien Morard at 3:48 PM (GMT 0) on 9 Feb 2026]