Skip to content

File Translation Service

FileTranslationService submits batches of files to a translation provider asynchronously. When the run completes, Vault invokes a post-processing event handler that saves the translated output in Vault. For example, the translated output may be saved as a new document, a new version, a rendition, or an attachment.

FileTranslationService is typically invoked from a user action, entry action, workflow job step, or agent tool.

A translation run has three components:

  1. Initiation: Your code assembles a FileTranslationBatchRequest. This includes one FileTranslationInput per file, a connection name identifying the translation provider, an event handler API name, and an optional FileTranslationParameters instance to hold the context your handler will need. Calling batchTranslateFiles queues the job.
  2. Translation: The job runtime submits each file to the provider identified by the connection record and polls for results.
  3. Post-processing: When all files have completed or failed, Vault invokes the FileTranslationEventHandler you specified, which saves the translated output in Vault and has access to the original collection of parameters for any additional context it needs. For example, the translated output may be saved as a new document, a new version, a rendition, or an attachment.

The following example demonstrates locating FileTranslationService via ServiceLocator, building one FileTranslationInput per file, then building and executing the FileTranslationBatchRequest.

FileTranslationService translationService = ServiceLocator.locate(FileTranslationService.class);

// Build the input for a single file
FileTranslationInput input = translationService.newFileTranslationInputBuilder()
    .withSourceFile(sourceFileReference)
    .withSourceLanguageCode("en")          // optional; omit to let the provider detect it
    .withTargetLanguageCode("es")
    .build();

// Build the batch request
FileTranslationBatchRequest request = translationService.newFileTranslationBatchRequestBuilder()
    .withFileTranslationInputs(VaultCollections.asList(input))
    .withConnectionName("my_provider__c")  // api_name__sys of the Translation Provider connection record
    .withEventHandlerApiName("my_translation_handler__c")
    .build();

// Submit the batch
translationService.batchTranslateFiles(request)
    .onErrors(errors -> {
        for (FileTranslationSubmissionError error : errors) {
            // Log or handle error here
        }
    })
    .execute();

batchTranslateFiles returns a FileTranslationBatchOperation that exposes three strategies for pre-queue validation failures:

  • ignoreErrors(): Submit valid rows; skip invalid rows silently.
  • onErrors + ignoreErrors(): Handle row-level failures, then submit valid rows.
  • rollbackOnErrors(): Fail the entire batch if any row is invalid; nothing is queued.

FileTranslationErrorType describes the possible pre-queue validation failures:

  • SOURCE_FILE_NOT_READABLE
  • PROVIDER_NOT_FOUND
  • PROVIDER_NOT_ACTIVE
  • EVENT_HANDLER_NOT_FOUND
  • SOURCE_FORMAT_UNSUPPORTED
  • TARGET_LANGUAGE_UNSUPPORTED

FileTranslationParameters represents a keyed, serializable collection of parameters attached to the batch request. Vault carries it across the asynchronous boundary and makes it available to the event handler via FileTranslationEventHandlerContext. Use it to pass any context your handler needs, such as source document IDs, configuration names, or notification flags.

Set scalar values using FileTranslationParameterValueType constants:

FileTranslationParameters parameters = translationService.newFileTranslationParametersBuilder()
    .appendValue("config_name", "my_translation_config__c")
    .appendValue("send_notification", true)
    .build();

For structured data, implement FileTranslationParameterValue in a @UserDefinedClass. All fields must use scalars or collections of scalars to ensure serialization across the asynchronous boundary.

@UserDefinedClassInfo()
public class MyTranslationContext implements FileTranslationParameterValue {
    private String sourceDocumentVersionId;
    private String targetLanguageCode;
    // getters and setters
}

Retrieve values in the event handler using FileTranslationEventHandlerContext#getParameter:

// Scalar value
String configName = context.getParameter("config_name", FileTranslationParameterValueType.STRING);
// Custom type
MyTranslationContext ctx = context.getParameter("my_context", MyTranslationContext.class);

Implementing a File Translation Event Handler

Section link for Implementing a File Translation Event Handler

Vault invokes FileTranslationEventHandler when a translation run completes. It owns all post-processing: storing the translated files, updating records, and notifying users.

Implement the FileTranslationEventHandler interface and annotate the class with @FileTranslationEventHandlerInfo. The apiName attribute must be unique within your Vault and follow standard naming conventions (__c for custom handlers).

The interface requires two methods, both receiving a FileTranslationEventHandlerContext:

  • onCompleteWithSuccess: Vault calls this method only when every input in the batch succeeded. Use context.getResults() to retrieve each FileTranslationResultSuccess.
  • onCompleteWithError: Vault calls this method when any input failed, even if other inputs in the same batch succeeded. Use both context.getResults() for successes and context.getErrors() for failures.
import com.veeva.vault.sdk.api.translation.*;

@FileTranslationEventHandlerInfo(apiName = "my_translation_handler__c")
public class MyTranslationHandler implements FileTranslationEventHandler {

    @Override
    public void onCompleteWithSuccess(FileTranslationEventHandlerContext context) {
        for (FileTranslationResultSuccess result : context.getResults()) {
            // Retrieve the successfully translated file
            FileReference translatedFile = result.getFileReference();
        }
    }

    @Override
    public void onCompleteWithError(FileTranslationEventHandlerContext context) {
        for (FileTranslationResultSuccess result : context.getResults()) {
            // Retrieve the successfully translated file
            FileReference translatedFile = result.getFileReference();
        }
        for (FileTranslationResultError result : context.getErrors()) {
            // Log or handle provider-level error here
        }
    }
}

FileTranslationProviderErrorType describes possible provider-side failures on a FileTranslationResultError:

  • INVALID_REQUEST
  • AUTHENTICATION_FAILED
  • PROVIDER_UNAVAILABLE
  • PROVIDER_ERROR
  • UNEXPECTED_ERROR

Document Translation Event Handlers

Section link for Document Translation Event Handlers

Instead of implementing your own FileTranslationEventHandler, you can use one of the two document translation event handlers by passing its API name constant to withEventHandlerApiName:

  • DocumentCreationHandlerParameters.API_NAME (document_creation__sys): Creates a new translated document per successfully translated file, copying fields from a source document version and linking each translation back to it.
  • DocumentUpdateHandlerParameters.API_NAME (document_update__sys): Creates a new version of an existing target document from the translated content. Only appropriate when a single target language is selected and the batch has exactly one input.

Each platform handler requires its own collection of parameters, built via FileTranslationService and attached to FileTranslationParameters under the handler's PARAMETER_NAME. See the Doctranslationsconfig component type for information about how to configure field copy and relationship behavior.

Example: Using a Document Translation Event Handler

Section link for Example: Using a Document Translation Event Handler

The following example builds a translation request using the document_creation__sys platform handler, which creates a new translated document for each successfully translated file.

FileTranslationService translationService = ServiceLocator.locate(FileTranslationService.class);

// Build the platform handler parameters
DocumentCreationHandlerParameters handlerParameters = translationService
    .newDocumentCreationHandlerParametersBuilder()
    .withInstanceId("1000443")
    .withSourceDocumentId("1502")
    .withSourceMajorVersion("1")
    .withSourceMinorVersion("0")
    .withTargetLanguageCodes(VaultCollections.asList("fr", "de"))
    .withNotifyOnCompletion(true)
    .build();

// Attach the handler parameters to the batch parameters collection
FileTranslationParameters parameters = translationService.newFileTranslationParametersBuilder()
    .appendValue(DocumentCreationHandlerParameters.PARAMETER_NAME, handlerParameters)
    .build();

// Build the input
FileTranslationInput input = translationService.newFileTranslationInputBuilder()
    .withSourceFile(sourceFileReference)
    .withTargetLanguageCode("es")
    .build();

// Build and submit the batch
FileTranslationBatchRequest request = translationService.newFileTranslationBatchRequestBuilder()
    .withFileTranslationInputs(VaultCollections.asList(input))
    .withConnectionName("deepl")
    .withEventHandlerApiName(DocumentCreationHandlerParameters.API_NAME)
    .withParameters(parameters)
    .build();

translationService.batchTranslateFiles(request)
    .onErrors(errors -> {
        for (FileTranslationSubmissionError error : errors) {
            // Log or handle error here
        }
    })
    .execute();

See DocumentCreationHandlerParameters and DocumentUpdateHandlerParameters in the Javadocs for the full set of parameters each platform handler requires.