/// <summary>
        /// Attempt to translated the provided untranslated text. Will be used in a "coroutine",
        /// so it can be implemented in an asynchronous fashion.
        /// </summary>
        public IEnumerator Translate(ITranslationContext context)
        {
            EnsureInitialized();

            while (_initializing && !_failed)
            {
                yield return(new WaitForSeconds(0.2f));
            }

            if (_failed)
            {
                context.Fail("External process failed.");
            }

            var result = new ProtocolTransactionHandle();
            var id     = Guid.NewGuid();

            lock ( _sync )
            {
                _transactionHandles[id] = result;
            }

            try
            {
                var request = new TranslationRequest
                {
                    Id                  = id,
                    SourceLanguage      = context.SourceLanguage,
                    DestinationLanguage = context.DestinationLanguage,
                    UntranslatedTexts   = context.UntranslatedTexts
                };
                var payload = ExtProtocolConvert.Encode(request);

                _process.StandardInput.WriteLine(payload);
            }
            catch (Exception e)
            {
                result.SetCompleted(null, e.Message);
            }

            // yield-wait for completion
            var iterator = result.GetSupportedEnumerator();

            while (iterator.MoveNext())
            {
                yield return(iterator.Current);
            }

            if (!result.Succeeded)
            {
                context.Fail("Error occurred while retrieving translation. " + result.Error);
            }

            context.Complete(result.Results);
        }
        /// <summary>
        /// Attempt to translated the provided untranslated text. Will be used in a "coroutine",
        /// so it can be implemented in an asynchronous fashion.
        /// </summary>
        public IEnumerator Translate(ITranslationContext context)
        {
            EnsureInitialized();

            while (_initializing && !_failed)
            {
                var instruction = Features.GetWaitForSecondsRealtime(0.2f);
                if (instruction != null)
                {
                    yield return(instruction);
                }
                else
                {
                    yield return(null);
                }
            }

            if (_failed)
            {
                context.Fail("External process failed.");
            }

            var totalDelay    = (float)(Rng.Next((int)((MaxDelay - MinDelay) * 1000)) + (MinDelay * 1000)) / 1000;
            var timeSinceLast = TimeSupport.Time.realtimeSinceStartup - _lastRequestTimestamp;

            if (timeSinceLast < totalDelay)
            {
                var remainingDelay = totalDelay - timeSinceLast;

                var instruction = Features.GetWaitForSecondsRealtime(remainingDelay);
                if (instruction != null)
                {
                    yield return(instruction);
                }
                else
                {
                    float start = TimeSupport.Time.realtimeSinceStartup;
                    var   end   = start + remainingDelay;
                    while (TimeSupport.Time.realtimeSinceStartup < end)
                    {
                        yield return(null);
                    }
                }
            }
            _lastRequestTimestamp = TimeSupport.Time.realtimeSinceStartup;

            var result = new ProtocolTransactionHandle();
            var id     = Guid.NewGuid();

            lock ( _sync )
            {
                _transactionHandles[id] = result;
            }

            try
            {
                var request = new TranslationRequest
                {
                    Id                    = id,
                    SourceLanguage        = context.SourceLanguage,
                    DestinationLanguage   = context.DestinationLanguage,
                    UntranslatedTextInfos = context.UntranslatedTextInfos.Select(x => x.ToTransmittable()).ToArray()
                };
                var payload = ExtProtocolConvert.Encode(request);

                _process.StandardInput.WriteLine(payload);
            }
            catch (Exception e)
            {
                result.SetCompleted(null, e.Message, StatusCode.Unknown);
            }

            // yield-wait for completion
            var iterator = result.GetSupportedEnumerator();

            while (iterator.MoveNext())
            {
                yield return(iterator.Current);
            }

            if (!result.Succeeded)
            {
                context.Fail("Error occurred while retrieving translation. " + result.Error);
            }

            context.Complete(result.Results);
        }