Loading
Salesforce Document Generation
Table of Contents
Select Filters

          No results
          No results
          Here are some search tips

          Check the spelling of your keywords.
          Use more general search terms.
          Select fewer filters to broaden your search.

          Search all of Salesforce Help
          Render Seamless Multi-Language Fonts in Generated PDFs

          Render Seamless Multi-Language Fonts in Generated PDFs

          By enabling advanced text shaping for specific document processes, you can correct rendering issues for complex scripts in generated PDFs. Use the text shaper flag when you have documents containing non-English text that requires advanced text shaping settings. Doing so prevents unnecessary performance degradation for documents that contain standard English text.

          Required Editions

          Note
          Note Text shaping is a performance-intensive operation, so use it sparingly. Limit text shaping to the document templates that you need, as it increases document generation time during both automatic and manual setup.
          Available in: Lightning Experience
          Available in: Professional, Enterprise, Unlimited, and Developer Editions
          User Permissions Needed
          To generate a document: DocGen User Permission Set

          Turn On Text Shaping Manually

          Add the text shaper flag directly to the document generation process record to resolve font sequencing issues.

          1. Prepare your JSON payload for a new Document Generation Process record.
          2. In the Request Text field, add the "useTextShaper": true parameter into the JSON payload.
          Example
          Example Sample JSON input value:
          {
            "EmailNotificationOnDocumentGeneration": "False",
            "keepIntermediate": true,
            "title": "SampleDocTitle",
            "useTextShaper": true
          }
          

          Automate Text Shaping with a Trigger

          Use an Apex trigger to programmatically add the text shaper flag into document requests based on your specific template requirements.

          1. From Setup, in the Quick Find box, enter Object Manager, and then select Object Manager.
          2. Select Document Generation Process, and then click Triggers.
          3. Click New and enter your trigger logic.
          Example
          Example Use this sample trigger logic after adding your specific template IDs. We recommend customizing the logic to target only the specific templates that require advanced text shaping to avoid unnecessary performance overhead.
          trigger DocumentGenerationProcessTrigger on DocumentGenerationProcess (before insert) {
                // Define the list of applicable template IDs (Content Version IDs or Document Template IDs)                                                                                                                                                                                                                        
                // Update this list with their specific template IDs where useTextShaper should be enabled                                                                                                                                                                                                         
                Set<String> applicableTemplates = new Set<String>();                                                                                                                                                                                                                                                                
                applicableTemplates.add('068VW000000FsGDYA1'); // Example ContentVersion ID - replace with actual IDs                                                                                                                                                                                                               
                applicableTemplates.add('2dtVW000000EcgXYAS'); // Example DocumentTemplate ID - replace with actual IDs                                                                                                                                                                                                          
                // Add more Content Version IDs or Document Template IDs here as needed                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
                for (DocumentGenerationProcess dgp : Trigger.new) {                                                                                                                                                                                                                                                                 
                    Boolean shouldApplyTextShaper = false;
                    String templateContentVersionId = null;                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                    
                    // Check requestText for templateContentVersionId                                                                                                                                                                                                                                                               
                    if (String.isNotBlank(dgp.requestText)) {                                                                                                                                                                                                                                                                       
                        try {                                                                                                                                                                                                                                                                                                       
                            // 1. Deserialize the existing JSON string into a Map
                            Map<String, Object> requestMap = (Map<String, Object>) JSON.deserializeUntyped(dgp.requestText);                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                    
                            // 2. Extract templateContentVersionId from requestText JSON                                                                                                                                                                                                                                            
                            if (requestMap.containsKey('templateContentVersionId')) {                                                                                                                                                                                                                                               
                                templateContentVersionId = (String) requestMap.get('templateContentVersionId');                                                                                                                                                                                                                     
                            }                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                    
                            // 3. Check if templateContentVersionId is in the applicable list                                                                                                                                                                                                                                       
                            if (String.isNotBlank(templateContentVersionId) && applicableTemplates.contains(templateContentVersionId)) {                                                                                                                                                                                            
                                shouldApplyTextShaper = true;                                                                                                                                                                                                                                                                       
                            }                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                    
                            // 4. If not found via templateContentVersionId, check DocumentTemplate field                                                                                                                                                                                                                           
                            if (!shouldApplyTextShaper && String.isNotBlank(dgp.DocumentTemplateId)) {                                                                                                                                                                                                                                
                                if (applicableTemplates.contains(dgp.DocumentTemplateId)) {                                                                                                                                                                                                                                           
                                    shouldApplyTextShaper = true;                                                                                                                                                                                                                                                                   
                                }                                                                                                                                                                                                                                                                                                   
                            }                                                                                                                                                                                                                                                                                                       
                            
                            // 5. Apply useTextShaper only if template is in the applicable list
                            if (shouldApplyTextShaper) {
                                requestMap.put('useTextShaper', true);
                                dgp.requestText = JSON.serialize(requestMap);
                            }
                        } catch (Exception e) {
                            System.debug('Error parsing requestText JSON: ' + e.getMessage());
                            // Optional: Handle malformed JSON here (e.g., dgp.addError('Invalid JSON format'));                                                                                                                                                                                                                    
                        }                                                                                                                                                                                                                                                                                                           
                    } else {                                                                                                                                                                                                                                                                                                        
                        // If requestText is empty, check DocumentTemplate field                                                                                                                                                                                                                                                    
                        if (String.isNotBlank(dgp.DocumentTemplateId) && applicableTemplates.contains(dgp.DocumentTemplateId)) {
                            dgp.requestText = '{"useTextShaper": true}';                                                                                                                                                                                                                                                            
                        }                                                                                                                                                                                                                                                                                                           
                    }                                                                                                                                                                                                                                                                                                               
                }                                                                                                                                                                                                                                                                                                                   
            }
          
          
           
          Loading
          Salesforce Help | Article