The Simple Way to Create Multi-Language Account Engagement Forms

The Simple Way to Create Multi-Language Account Engagement Forms

min. reading

Handling multiple languages with Account Engagement (Pardot) forms has always been complex — especially when it comes to reporting. But there is a way to multi-language Account Engagement forms.

The traditional solution — one form per language — has its drawbacks. But it’s something that’s super important for companies that use Account Engagement on a global scale to do in a logical and user-friendly way. 

Today, we’ll explore a new, more efficient method that improves reporting and streamlines the translation process.

Challenges with traditional solutions for creating multi-language Account Engagement forms

There are a few ripple effects that we have to handle when we use multiple forms to realistically capture one set of data. 

First, we need a way of figuring out which form we want to display. Commonly this is done as a piece of dynamic content driven off a known Prospect field.

Next, we need to handle submissions for a single goal across multiple forms. The approach we take can vary depending on how complex our Automations and Reporting strategies are, and it all can add up.

A new solution for handling multiple languages

We can still work within the constraints of Account Engagement (Pardot) and leverage a common web development pattern of internationalization (or i18n for short). With the power of JavaScript, we can have one Account Engagement form and feel confident that our visitors will be able to have it in their language.

JavaScript and Handlebars.js

Before we dive into the actual code (honestly my favorite), it might be helpful to talk about what we are going to use.  We have a mix of a little bit of custom JavaScript with a common JavaScript library called HandlebarsJS, not to be confused with Account Engagement Handlebars Merge Language (HML).

The custom JavaScript takes the HTML that Account Engagement will render, look for the i18n placeholders and do a real-time replacement with the translations you have set up. This gives you full control over the wording and design in each language for every page.

Both HML and HandlebarsJS (by default) use double curly braces for wrapping placeholders. We’ve chosen to help differentiate between the two easily by specifying square brackets.  

Getting into the details

So as a super simple example, you can use the label [[i18n.firstname]] to have English, French, Spanish (or any other language you want) for the value {{Recipient.first_name}}.

Example of single Account Engagement form supporting 3 languages

Ok, let’s show what this can look like. Here we have a demo form that supports three languages.

Pre-work to do for your multi-language Account Engagement forms

If you’ve previously filled out the form, we will render the form in the language you specified. If you haven’t, we’ll try to use your browser’s language. Form error messages and thank you content are all translated.

Back in Account Engagement, there are a few things that need to be done.

Here’s what to do:

Step 1: Edit form fields – Each Form Field needs to be edited to use a label in the format [[i18n.TOKEN]] (where the TOKEN can be a field name or anything you like

Step 2: Edit dropdown field values – Each Dropdown field value needs to be edited to use a label in a similar format

Step 3: Ensure dropdown fields store language code – The Form should have a Language dropdown field that stores the language code. Language choice labels should use a label in a slightly different format. It should use [[lang.CODE]].

You’ll also need to add the CSS Class langChoice to this field:

Step 4: Update the submit button text – Submit button text should be edited to use [[i18n.submit]].

Step 5: Check thank you content – Thank you content should be edited to use [[i18n.thankyou]].

    Add JavaScript to the form

    Once you have all your labels set up, we need to actually add the JavaScript to the form.  There are a few ways you can do this and the approach will depend on just how reusable (and large) you want your JavaScript to be.

    In our example, we’ve placed the JavaScript in the Layout Template, which provides a balance of re-usability (can be used by multiple forms) and maintenance (common, but not all translations for the entire site).

    Ok, time for the code. I’ve split this JavaScript into three sections, but it can all be copy and pasted into a single <script> block in your Layout Template.

    Define languages the form will support

    First, we have a JavaScript object that defines the languages that we will be supporting, as well as the label of that language. Feel free to adjust this as necessary, just keep the structure intact.

    <script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
    <script>
    // the supported languages by this script
    const languages = {
        lang: {
            en: 'English',
            fr: 'Français',
            es: 'Español'
        }
    };

    Add the translations

    Next, we have all of the translations

    // the translations for each language
    const translations = {
      'en': {
        i18n: {
          firstname: "First Name",
          lastname: "Last Name",
          company: "Company",
          email: "Email",
          industry: "Industry",
          hospitality: "Hospitality",
          tech: "Tech",
          submit: "Save now",
          language: "Language",
          formErrors: "Please correct the errors below:",
          fieldError: "This field is required",
          thankyou: "Thanks for submitting!"
        }
      },
      'fr': {
        i18n: {
          firstname: "Prénom",
          lastname: "Nom de famille",
          company: "Société",
          email: "Email",
          industry: "Secteur d'activité",
          hospitality: "Hospitality",
          tech: "Technologie",
          submit: "Enregistrer",
          language: "Langue",
          formErrors: "Corrigez les erreurs ci-dessous:",
          fieldError: "Ce champ est obligatoire",
          thankyou: "Merci d'avoir soumis"
        }
      },
      'es': {
        i18n: {
          firstname: "Primer nombre",
          lastname: "Apellido",
          company: "Compañía",
          email: "Correo electrónico",
          industry: "Industria",
          hospitality: "Hospitalidad",
          tech: "Tecnología",
          submit: "Guardar ahora",
          language: "Idioma",
          formErrors: "Por favor corrija los siguientes errores:",
          fieldError: "Este campo es obligatorio",
          thankyou: "Gracias por enviar"
        }
      }

    For each token you want to be translated, you will need to add a translation for each language. Like how languages are set up, you can make any adjustments/additions you want… just keep the structure intact.

    Add the main functionality to apply the translations you defined

    Next, we have the main functionality. This handles the actual work of applying the translations we have defined already.

    function i18nForm(prospectLang) {
        document.addEventListener("DOMContentLoaded", function(event) {
            const brO = '{', brC = '}';
            let formErrors = document.querySelector('#pardot-form p.errors');
            if (formErrors != null) {
                document.querySelector('#pardot-form p.errors').innerHTML = `[[i18n.formErrors]]`;
                [...document.querySelectorAll('#pardot-form p.error.no-label')].forEach(node => {
                    node.innerHTML = `[[i18n.fieldError]]`;
                });
            }
            let notYou = document.querySelector('.email span.description');
            if (notYou != null) {
                let origHtml = notYou.innerHTML;
                notYou.innerHTML = origHtml.replace('Not', '[[i18n.notYou]]').replace('Click Here', '[[i18n.notYouClickHere]]');
            }
    
            // Get the original HTML of the form, replacing [[ with {{ and ]] with }}
            const originalHtml = document.querySelector('#pardot-form').innerHTML
                .replace(/\[\[/g, `${brO + brO}`).replace(/\]\]/g, `${brC + brC}`);
            // Compile the template with Handlebars
            const processTemplate = Handlebars.compile(originalHtml);
    
            // Get the browser language
            const browserLang = window.navigator.language.substr(0, 2);
            let formLangCode = '';
            let currentLangVal = '';
    
            // Dynamically map Pardot option values to language codes using innerHTML
            const pardotLanguages = {};
            const langNodes = document.querySelectorAll('.langChoice select option');
            langNodes.forEach(option => {
                let langKey = option.innerHTML.replace(/\[\[lang\.(.*?)\]\]/, '$1');
                pardotLanguages[option.value] = langKey;
            });
    
            // Determine the selected language in the dropdown
            langNodes.forEach(option => {
                if (option.selected && option.value !== '') {
                    currentLangVal = option.value;
                    formLangCode = pardotLanguages[option.value];
                }
            });
    
            // Determine the language to use
            let currentLangCode = formLangCode || prospectLang || browserLang;
    
            // Function to apply translations
            function applyTranslations() {
                let translatedHtml = processTemplate({ ...translations[currentLangCode], ...languages });
                document.querySelector("#pardot-form").innerHTML = translatedHtml;
                document.querySelector('.langChoice select').value = currentLangVal;
    
                // Handle language dropdown change event
                document.querySelector('.langChoice select').onchange = function () {
                    let selectedLang = pardotLanguages[this.value];
                    if (selectedLang in languages.lang) {
                        currentLangCode = selectedLang;
                        currentLangVal = this.value;
                        applyTranslations();
                    }
                };
            }
            applyTranslations();
        });
    }
    i18nForm();
    </script>

    Test and revise

    All that’s left to do is test it out, and then mold this example into what you need.

    Considerations

    Like any JavaScript examples you might find online, they are opinionated in approach. Making minor changes can sometimes break the code due to assumptions that might not be well documented/understood. I’ve left a bunch of console.log statements commented throughout the code to hopefully help you troubleshoot when things go wrong.

    One of those opinions is using the “i18n” and “lang” prefixes. We think this makes the placeholders easier to read, even if it slightly complicates the JavaScript object itself. Feel free to remove this if you want, just know to make the various adjustments.

    One Account Engagement form can handle all the languages you need

    If your company works with audiences who speak a variety of languages, then this is the perfect solution for you to simplify the way you build forms in Account Engagement. Our new approach simplifies translating Pardot Forms, improves reporting, and offers a better user experience for a multilingual audience.

    Still not sure how to approach your global marketing strategy? Then reach out to the team at Sercante for guidance along the way.

    Post updated: June 2024

    Subscribe to The Spot

    This field is hidden when viewing the form
    This field is hidden when viewing the form
    This field is hidden when viewing the form
    This field is hidden when viewing the form
    This field is for validation purposes and should be left unchanged.

    Upcoming Salesforce Events

    Salesforce Training Courses

    Categories

    Top 5 Recent Posts

    • Adam Erstelle is a Developer with Sercante. He loves learning about and solving really interesting challenges with Pardot and Salesforce often by building some cool tools.

    Leave Your Comment

    Related Articles

    Bot Single Post