SOLVED

Re: Forms in Other Languages

Go to solution
Joseph_Moran2
Level 2

We are in the process of launching a new website. As we were reviewing our old forms, we began looking into how we would handle translations. Having 7 versions of the same form (Contact Us English, Contact Us French, Contact Us German, etc.) sounds aweful to us. I am curious, how have others handled translations of forms in Marketo?

Sanford Whiteman shared this wonderful method for handling translations, https://blog.teknkl.com/smoothing-embedded-marketo-form-loads/. Has anyone tried this approach? Any challenges we should anticipate?

Champion Program

Joseph Moran
1 ACCEPTED SOLUTION
SanfordWhiteman
Level 10 - Community Moderator

It’s PlaceholderText, not Placeholder.

View solution in original post

25 REPLIES 25
mhall70
Level 1

@SanfordWhiteman is it possible to modify the placeholder value of a field using this method? I've tried adding placeholder as part of the JSON but it does not change the placeholder value of the field I reference.  I've added it to the JSON like this:

 

{
Name: "FirstName",
Placeholder: "Séance B"
}
SanfordWhiteman
Level 10 - Community Moderator

It’s PlaceholderText, not Placeholder.

mhall70
Level 1

Thank you, I didn't know the correct nomenclature

SanfordWhiteman
Level 10 - Community Moderator

Has anyone tried this approach?

I have.

Good when paired with https://blog.teknkl.com/safely-embedding-json-in-a-rich-text-as-opposed-to-plain-text-my-token/

Todd_Sprinkel
Level 2

Where does this translate function get placed? I'm also confused because you've defined a translateMktoDescriptor function in the sample code, but then there's also a translateMktoForm function that doesn't seem to be defined. I'm also curious how to handle translating select list option labels. I'm guessing you'd need an additional conditional loop within the translate function, but I'm not sure where I'd put that in the JSON file.

Additionally, how do you determine which language to translate everything into?

Is there a working example of this approach out there in the wild?

SanfordWhiteman
Level 10 - Community Moderator
Additionally, how do you determine which language to translate everything into?

The language code could be previously stored in a cookie, put in the path/query string, wherever. How do you usually choose/store the lead's preferred language?

Is there a working example of this approach out there in the wild?

Right here:

   

   MktoForms2 :: Manual descriptor, localize <select> 

You're right that there was a mismatch between the function name and the function call in the blog post, changed that.

Todd_Sprinkel
Level 2

I've got this working on the initial page load, but I'm not sure how to re-render the form if a user changes their language preference (a dropdown field on the form). I tried attaching an event listener to the field, which runs the function, but the descriptor is undefined and I'm not sure how to access it outside the initial load.

MktoForms2.whenReady(function(form){
var formEl = form.getFormElem()[0];
var langField = "Language_Preference__c";
var langEl = formEl.querySelector("#"+langField);

langEl.onchange = function(e){
//console.log('Running');
session.lang = langEl.value();
translateMktoForm(formEl.descriptor, mktoFormLanguages, session);
}
});‍‍‍‍‍‍‍‍‍‍‍
SanfordWhiteman
Level 10 - Community Moderator

No, that won't work -- the descriptor is only parsed once.

It seems surprising that you would need to keep the person on the same page (including all the other potentially localized information on the page) after they change their language preference. Usually that's grounds for a page reload.

Todd_Sprinkel
Level 2

The language preference is a newly-introduced concept for this global company, so everything will default to English until users begin selecting their preferences. I'd like to be able to translate the whole page again if the user selects a new language preference, but I suppose I could force a page reload and re-render everything if it's not possible to do on the fly.

SanfordWhiteman
Level 10 - Community Moderator

To localize the entire page without a full document refresh requires some major front end engineering. If you look at the world's biggest sites, even those that otherwise operate as single-page apps still refresh the whole doc when you change the language.

Todd_Sprinkel
Level 2

Well, I thought I'd be clever and use a hash to override the language preference using this:

var supportedLangs = ["English","Chinese","Japanese","Korean","Spanish","Portuguese","French","German","Polish","Italian"];
var hash = location.hash.substring(1);
var langpref;
if(supportedLangs.includes(hash)){
langpref = hash;
}
else{
langpref = "{{lead.Language_Preference__c:default=English}}";
}
var session = {lang: langpref};‍‍‍‍‍‍‍‍‍‍

and then adding an event listener to the form to redirect with the new hash like this:

MktoForms2.whenReady(function(form) {
var formEl = form.getFormElem()[0];
var langField = "Language_Preference__c";
var langEl = formEl.querySelector("#" + langField);

langEl.onchange = function(e) {
window.location.assign(window.location.pathname + "#" + langEl.value);
}
});‍‍‍‍‍‍‍‍‍

but that doesn't actually re-load the form from the server. I also tried adding in a window.location.reload(true); somewhere and got stuck in an infinite redirect loop, but I can't remember how I did that exactly. I was thinking I could do something on the page to check if the hash was a supported language, and not equal to a non-blank value of the form field, but the page redirect doesn't trigger another whenReady() event on the form, so I couldn't get that to work right.

SanfordWhiteman
Level 10 - Community Moderator

Don't use Array#includes, it doesn't work in any version of IE.

Also don't overwrite the single onchange function, add a new listener.

Things like hash = document.location.hash.substring(1) give me the willies (use of the same var name and property name). Try using something semantically accurate, like runtimeLang = document.location.hash.substring(1).

Other than that, the general approach will work, but you must be able to call document.location.reload. I don't know what code you tried that was getting you into a redirect loop.

MktoForms2.whenReady(function(form){
var formEl = form.getFormElem()[0],
langField = "Language_Preference__c",
langEl = formEl.querySelector("[name='"+ langField + "']");

langEl.addEventListener("change", function(e){
document.location.hash = form.getValues()[langField];
document.location.reload();
});
});‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Todd_Sprinkel
Level 2

Thanks Sandy. Good heads up on the Array.includes. I ended up using Array.prototype.indexOf. While it isn't supported prior to IE9, they decided they didn't need to support older versions.

I also took your advice on the variable name--definitely likely to cause some headaches...

For anyone else looking to do this, I also added a condition to the event listener to make sure the new value of the Language_Preference__c field was different than the current session language. Not including this makes the form unsubmittable as it just reloads every time you change the language preference.

MktoForms2.whenReady(function(form) {
var formEl = form.getFormElem()[0],
langField = "Language_Preference__c",
langEl = formEl.querySelector("[name='" + langField + "']");

langEl.addEventListener("change", function(e) {
if (form.getValues()[langField] && form.getValues()[langField] != session.lang) {
document.location.hash = form.getValues()[langField];
document.location.reload();
}
});
});‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
SanfordWhiteman
Level 10 - Community Moderator

If you set the field value to the session language (programmatically using setValues) then it wouldn't be a change event.

Todd_Sprinkel
Level 2

Correct, but I'm only changing the value programmatically if it is already stored in a token or present in the hash, and the session language is set prior to the form load (in order to determine what language to load everything in)--in which case it would be equal to the value I'm setting, and I wouldn't want to reload the page because it's already in the correct language. 

The only time a reload should occur is if the user changes the form value to a new value that is not blank and is not the current session language.

What other scenarios might I want to set it programmatically and have that trigger a change event? I can't think of a reason I'd need to do this.

I may also get into using sessionStorage to restore previously filled out values if/when the page is reloaded due to changing the language preference (only potential PII is an email address) in order to prevent the user from having to fill them out again, but I haven't thought through all of the potential implications of that yet. I'd be interested in what, if any, thoughts you have on that potential approach.

SanfordWhiteman
Level 10 - Community Moderator

No, I'm saying you don't need to worry about the change if you set it programmatically. Hence there shouldn't be a situation where the person "changes the dropdown to be the same as the session language" because if the dropdown is already set to Language A, and they drop it down and select Language A, that won't be a change, hence won't reload the page.

Todd_Sprinkel
Level 2

@SanfordWhiteman Any ideas on how to scalably translate any rich text included in a form? It doesn't look it's possible to give those a name, and it comes through in the descriptor like this:

[
      {
        "Id": 29708,
        "Name": "HtmlText_2019-09-16T14:03:23.709Z",
        "Datatype": "htmltext",
        "InputInitialValue": "",
        "LabelWidth": 260,
        "ProfilingFieldNumber": 0,
        "Htmltext": "<p>Here is some text.</p>",
        "IsLabelToLeft": true
      }
    ],

If it's just one form, that's fine, but even if the form is cloned, I think the rich text gets a new Id and Name attribute. I suppose you could evaluate the Htmltext, but that seems messy and error-prone as well.

SanfordWhiteman
Level 10 - Community Moderator

I think you'd have to inject and parse the HTML. It shouldn't be too error-prone as long as you only look for the trimmed textContent.

Joseph_Moran2
Level 2

Thanks for your reply Sanford! In reading through the link, that is for Marketo LPs, but not embedded forms on the main site, correct?

Joseph Moran
SanfordWhiteman
Level 10 - Community Moderator

Either one!