Developers

Salesforce Translation: A Step-by-Step Implementation Guide to XLIFF File Imports

By Sai Akshitha Gaddam

Organizations often struggle when processing large translation datasets in Salesforce. The traditional approach of loading all translation records at once and generating XLIFF files hits severe limitations at around 20,000 records, causing memory issues and system crashes. For enterprises dealing with 650,000+ records across multiple languages, this creates a significant bottleneck.

The techniques outlined in this guide transform translation processing from a technical challenge into a competitive advantage.

Understanding the Scale Challenge

When processing 650,000 translation records across five languages, you’re dealing with 3.25 million translation operations. The standard approach fails because:

  • Salesforce governor limits restrict memory usage per transaction.
  • Large XLIFF file generation consumes excessive heap memory.
  • Manual file downloading and importing becomes unmanageable.
  • Processing must be repeated for each language separately.

The Batch Processing Solution

Batch processing solves scale issues by breaking large datasets into manageable chunks. Instead of processing all 650,000 records simultaneously, the system processes 1,000-2,000 records per batch, allowing Salesforce to handle each batch with fresh memory allocation.

Implementation

public class TranslationBatch implements Database.Batchable<sObject> {
    private String targetLanguage;

    public TranslationBatch(String language) {
        this.targetLanguage = language;
    }

    public Database.QueryLocator start(Database.BatchableContext BC) {
        return Database.getQueryLocator([
            SELECT Id, Language_Key__c, Translation_Value__c, Source_Text__c, Processed__c, Batch_File_Id__c
            FROM Language_Translation__c
            WHERE Lanugage__c = :targetLanguage
            AND Processed__c = false
        ]);
    }

    public void execute(Database.BatchableContext BC, List<Language_Translation__c> scope) {
        if (scope.isEmpty()) return;

        String xliffContent = generateXLIFFContent(scope);
        String fileName = 'translations_' + targetLanguage + '_batch_' + BC.getJobId() + '.xliff';

        // Create ContentVersion (will appear in Files for the running user)
        ContentVersion file = new ContentVersion(
            Title = fileName,
            PathOnClient = fileName,
            VersionData = Blob.valueOf(xliffContent)
        );
        insert file;

        // Mark records as processed
        for (Language_Translation__c record : scope) {
            record.Processed__c = true;
            record.Batch_File_Id__c = file.Id; // stores ContentVersion Id
        }
        update scope;
    }

    public void finish(Database.BatchableContext BC) {
        System.debug('Translation batch completed for language: ' + targetLanguage);
    }

    private String generateXLIFFContent(List<Language_Translation__c> translations) {
        String xliff = '<?xml version="1.0" encoding="UTF-8"?>\n';
        xliff += '<xliff version="1.2">\n';
        xliff += '<file target-language="' + targetLanguage + '">\n';
        xliff += '<body>\n';

        for (Language_Translation__c trans : translations) {
            xliff += '  <trans-unit id="' + escapeXML(trans.Language_Key__c) + '">\n';
            xliff += '    <source>' + escapeXML(trans.Source_Text__c) + '</source>\n';
            xliff += '    <target>' + escapeXML(trans.Translation_Value__c) + '</target>\n';
            xliff += '  </trans-unit>\n';
        }

        xliff += '</body>\n</file>\n</xliff>';
        return xliff;
    }

    private String escapeXML(String input) {
        if (String.isBlank(input)) return '';
        return input.replace('&', '&amp;')
                    .replace('<', '&lt;')
                    .replace('>', '&gt;')
                    .replace('"', '&quot;')
                    .replace('\'', '&apos;');
    }
}

For processing multiple languages efficiently:

public class MultiLanguageProcessor {
    public static void processAllLanguages() {
        List<String> languages = new List<String>{'fr', 'es', 'de', 'it', 'pt'};

        for (String lang : languages) {
            TranslationBatch batch = new TranslationBatch(lang);
            Database.executeBatch(batch, 1500);
        }
    }
}

Step-by-Step Implementation Guide

1. Preparing the Data

• Identify Data for Translation: Collect all translation-relevant data. This includes translation keys, labels, and their corresponding values in different languages.

• Format Data According to Salesforce Requirements: Ensure the data aligns with the structure of the custom Language_Translation__c object. Each record should include:

  • Language Key.
  • Source Language Text.
  • Target Language(s).
  • Metadata fields (e.g., context, object/module reference).

2. Inserting Data into Salesforce

  • Use Workbench or Data Loader to insert the formatted data into the Language_Translation__c object in Salesforce.

3. Converting Data to XLF Format

  • Log in to Salesforce.
  • Execute the custom Apex code (XLIFFConverter) to generate XLF files.

This tool extracts translation records from Language_Translation__c and formats them into XLIFF-compliant XML.

4. Uploading to Translations Workbench

  • Download XLF File: After successful conversion, download the generated XLF file from Salesforce.
  • Access Translations Workbench: Navigate to: Setup > Translation Workbench > Import/Export
  • Upload & Process XLF File
    • Upload the XLF file.
    • Review the upload prompts to validate and apply translations.
    • Make any necessary adjustments if prompted during import.
  • Verify Translation Results: After import, validate within Salesforce UI that all translations appear correctly in their respective components (e.g., labels, custom fields, picklists).

Alternative Approaches

Queueable Job Chains

public class TranslationQueueable implements Queueable {
    private List<String> remainingLanguages;
    private String currentLanguage;

    public TranslationQueueable(List<String> languages) {
        this.remainingLanguages = languages;
        this.currentLanguage = languages.remove(0);
    }

    public void execute(QueueableContext context) {
        // Process current language
        TranslationBatch batch = new TranslationBatch(currentLanguage);
        Database.executeBatch(batch, 1500);

        // Chain next language if remaining
        if (!remainingLanguages.isEmpty()) {
            System.enqueueJob(new TranslationQueueable(remainingLanguages));
        }
    }
}

Requirements Skip File Generation

public class DirectTranslationUpdater implements Database.Batchable<sObject> {

    public void execute(Database.BatchableContext BC, List<Language_Translation__c> scope) {
        Map<String, List<Translation>> translationsByLanguage = groupByLanguage(scope);

        for (String language : translationsByLanguage.keySet()) {
            updateTranslationWorkbench(language, translationsByLanguage.get(language));
        }
    }

    private void updateTranslationWorkbench(String language, List<Translation> translations) {
        // Use Metadata API to directly update Translation Workbench
        // This requires custom implementation based on your specific setup
    }
}

Final Thoughts 

Mastering translation imports in Salesforce requires understanding both the platform’s capabilities and limitations. By implementing batch processing strategies, leveraging XLIFF files effectively, and following optimization best practices, organizations can successfully manage translations at any scale. 

The key to success lies in choosing the right approach for your organization’s specific needs. Whether implementing basic batch processing or advanced automation workflows, the goal remains consistent: efficient, reliable translation management that scales with your global growth. 

As Salesforce continues to evolve, staying current with new translation features and capabilities ensures your implementation remains optimal for years to come.

The Author

Sai Akshitha Gaddam

Sai is a 15x certified Salesforce Architect, and the Founder of AI TestGenie for Salesforce.

Leave a Reply