private int translateArray(
            string appID,
            ITranslationEngine ti,
            DataTable table,
            string refLanguageCode,
            DataColumn column,
            int refValueIndex,
            string raw,
            BackgroundWorker bw,
            int delayMilliseconds,
            string prefixSuccess,
            bool useExistingTranslations,
            bool useExistingTranslationsOnly,
            InMemoryTranslationSnapshot imss,
            int translationSuccessCount,
            ref int translationErrorCount,
            bool continueOnErrors,
            string prefixError,
            ref int translationCount,
            ref int internallyExistingTranslationTranslatedSuccessCount)
        {
            var items = new List <TranslateItemInfo>();

            // --
            // From GUI to in-memory-list.

            if (column != null)
            {
                foreach (DataRow row in table.Rows)
                {
                    items.Clear();
                    if (row != null)
                    {
                        if (bw.CancellationPending)
                        {
                            throw new OperationCanceledException();
                        }

                        var text = row[column] as string;
                        if (!string.IsNullOrEmpty(text) && text.Trim().Length > 0)
                        {
                            continue;
                        }

                        // http://www.codeproject.com/KB/aspnet/ZetaResourceEditor.aspx?msg=3367544#xx3367544xx
                        if (FileGroup.IsInternalRow(row))
                        {
                            continue;
                        }

                        var sourceText = row[refValueIndex] as string;

                        if (string.IsNullOrEmpty(sourceText))
                        {
                            continue;
                        }

                        items.Add(new TranslateItemInfo {
                            Row = row, SourceText = sourceText
                        });
                    }

                    // --
                    // Pack into blocks.

                    var blocks = new List <List <TranslateItemInfo> >();

                    for (var index = 0; index < items.Count; index++)
                    {
                        if (index % ti.MaxArraySize == 0)
                        {
                            blocks.Add(new List <TranslateItemInfo>());
                        }

                        blocks[blocks.Count - 1].Add(items[index]);
                    }

                    // --
                    // Translate each block in batch.

                    foreach (var block in blocks)
                    {
                        if (block != null)
                        {
                            if (bw.CancellationPending)
                            {
                                throw new OperationCanceledException();
                            }

                            if (delayMilliseconds > 0)
                            {
                                Thread.Sleep(delayMilliseconds);
                            }

                            var sourceTexts = block.Select(itemInfo => itemInfo.SourceText).ToList();

                            try
                            {
                                var sourceLanguageCode = ti.MapCultureToSourceLanguageCode(
                                    appID,
                                    CultureHelper.CreateCultureErrorTolerant(refLanguageCode));
                                var destinationLanguageCode = ti.MapCultureToDestinationLanguageCode(
                                    appID,
                                    CultureHelper.CreateCultureErrorTolerant(raw));

                                if (useExistingTranslations)
                                {
                                    // Alle die nehmen, die schon übersetzt sind. Also quasi "aus Cache".
                                    for (var index = 0; index < sourceTexts.Count; ++index)
                                    {
                                        var dstText = imss?.GetTranslation(refLanguageCode, raw, sourceTexts[index]);
                                        if (dstText != null)
                                        {
                                            block[index].Row[column] = prefixSuccess + dstText;

                                            translationSuccessCount++;
                                            internallyExistingTranslationTranslatedSuccessCount++;

                                            sourceTexts[index] = string.Empty; // Markieren als "erledigt".
                                        }
                                    }
                                }

                                if (!useExistingTranslationsOnly && sourceTexts.Any(s => !string.IsNullOrEmpty(s)))
                                {
                                    var destinationTexts =
                                        ti.TranslateArray(
                                            appID,
                                            sourceTexts.ToArray(),
                                            sourceLanguageCode,
                                            destinationLanguageCode,
                                            _project.TranslationWordsToProtect,
                                            _project.TranslationWordsToRemove);

                                    for (var index = 0; index < block.Count; ++index)
                                    {
                                        if (destinationTexts[index] != null)
                                        {
                                            block[index].Row[column] = prefixSuccess + destinationTexts[index];

                                            // Merken für ggf. nächsten Durchlauf.
                                            if (useExistingTranslations)
                                            {
                                                imss?.AddTranslation(
                                                    refLanguageCode,
                                                    raw,
                                                    sourceTexts[index],
                                                    destinationTexts[index]);
                                            }

                                            translationSuccessCount++;
                                        }
                                    }
                                }
                            }
                            catch (Exception x)
                            {
                                translationErrorCount++;

                                if (continueOnErrors)
                                {
                                    var destinationText = prefixError + x.Message;

                                    foreach (var t in block)
                                    {
                                        if (t?.Row?[column] != null)
                                        {
                                            t.Row[column] = destinationText;
                                        }
                                    }
                                }
                                else
                                {
                                    throw;
                                }
                            }

                            translationCount++;
                        }
                    }
                }
            }

            return(translationSuccessCount);
        }
        private int translateSingle(
            string appID,
            ITranslationEngine ti,
            DataTable table,
            string refLanguageCode,
            DataColumn column,
            int refValueIndex,
            string raw,
            BackgroundWorker bw,
            int delayMilliseconds,
            string prefixSuccess,
            bool useExistingTranslations,
            bool useExistingTranslationsOnly,
            InMemoryTranslationSnapshot imss,
            int translationSuccessCount,
            ref int translationErrorCount,
            bool continueOnErrors,
            string prefixError,
            ref int translationCount,
            ref int internallyExistingTranslationTranslatedSuccessCount)
        {
            if (column != null)
            {
                foreach (DataRow row in table.Rows)
                {
                    if (row != null)
                    {
                        if (bw.CancellationPending)
                        {
                            throw new OperationCanceledException();
                        }

                        var text = row[column] as string;
                        if (!string.IsNullOrEmpty(text) && text.Trim().Length > 0)
                        {
                            continue;
                        }

                        // http://www.codeproject.com/KB/aspnet/ZetaResourceEditor.aspx?msg=3367544#xx3367544xx
                        if (FileGroup.IsInternalRow(row))
                        {
                            continue;
                        }

                        var sourceText = row[refValueIndex] as string;

                        if (string.IsNullOrEmpty(sourceText))
                        {
                            continue;
                        }

                        if (delayMilliseconds > 0)
                        {
                            Thread.Sleep(delayMilliseconds);
                        }

                        try
                        {
                            var sourceLanguageCode = ti.MapCultureToSourceLanguageCode(
                                appID,
                                CultureHelper.CreateCultureErrorTolerant(refLanguageCode));
                            var destinationLanguageCode = ti.MapCultureToDestinationLanguageCode(
                                appID,
                                CultureHelper.CreateCultureErrorTolerant(raw));

                            var doIt = true;

                            // Ggf. aus Cache holen.
                            if (useExistingTranslations)
                            {
                                var dstText = imss?.GetTranslation(refLanguageCode, raw, sourceText);
                                if (dstText != null)
                                {
                                    row[column] = dstText;

                                    translationSuccessCount++;
                                    internallyExistingTranslationTranslatedSuccessCount++;

                                    doIt = false;
                                }
                            }

                            if (!useExistingTranslationsOnly && doIt)
                            {
                                var destinationText =
                                    prefixSuccess +
                                    ti.Translate(
                                        appID,
                                        sourceText,
                                        sourceLanguageCode,
                                        destinationLanguageCode,
                                        _project.TranslationWordsToProtect,
                                        _project.TranslationWordsToRemove);

                                row[column] = destinationText;

                                // Merken für ggf. nächsten Durchlauf.
                                if (useExistingTranslations)
                                {
                                    imss?.AddTranslation(refLanguageCode, raw, sourceText, destinationText);
                                }

                                translationSuccessCount++;
                            }
                        }
                        catch (Exception x)
                        {
                            translationErrorCount++;

                            if (continueOnErrors)
                            {
                                var destinationText = prefixError + x.Message;

                                if (row[column] != null)
                                {
                                    row[column] = destinationText;
                                }
                            }
                            else
                            {
                                throw;
                            }
                        }

                        translationCount++;
                    }
                }
            }

            return(translationSuccessCount);
        }