Multi-Language Email Templates Using Visualforce Components

In the previous post, I showed how to create basic email templates using custom labels. This works well for simple templates that don’t need a lot of merge fields. In this post, I’ll show an alternative using Visualforce components.

First a high level overview. Rather than create a single email template, we will create one template for each language. We will then create a Visualforce component that retrieves the appropriate template, performs the merge and then outputs the content into another email template. Kind of confusing, but bear with me.

  1. Create Email Templates

Create an HTML email template for each language you want to use.

English Template
German Template

2. Create a Custom Label

Create a custom label that will store the Ids of the email templates created in step 1. You’ll just add a “translation” for each label that will contain the Id for the appropriate language. I’m not a fan of hard coding Ids and you could get fancier by using the API name of the email templates instead, but for simplicity sake, I’m just using Id here.

3. Create Apex Controller 

Now we need an Apex Controller that can take an arbitrary email template Id, merge it with a record Id, and output the final result. The key here is we are going to use Messaging.renderStoredEmailTemplate that takes an email template Id, a what Id and  a who Id and creates a merged email. See the gist below for the code.

4. Create a Visualforce Component

This component will return the HTML or text body of the merge email template. See gist below for the code.

5. Create Final Email Template

For the final email template, you need to create a Visualforce template that uses the component created above.

  • For the subject, you have to use the Substitute function I used in the previous post because subject can’t use custom controllers.
  • Set the language so the custom labels pull in the correct email template Id.
  • Reference the component for both the html and plain text version.

Wrapping Up

In this post, I’ve introduced another way to dynamically translate your email templates. You can also use this technique to reduce the number of workflows and email alerts you create for other types of notifications. I’d love to hear other ideas you have on how to use the dynamic email component.

Multi-Language Email Templates Using Custom Labels

As you start expanding your Salesforce org, you may find you need to send notifications in multiple languages. In this post, I’ll show how you can do it using Custom Labels. The documentation alludes to using labels, but doesn’t really explain how to do it.

Before we get started, you’ll need to enable Translation Workbench and enable the languages you want to use.

In this example, I’m going to use a field on the record to determine the notification language. Create a picklist field on the object you want to send the notifications from.  Use the new feature available in Spring 17 so you can have a different API name than label as in the screenshot below.

Next, we need to setup some custom labels. In this example, I’m just going to create two custom labels: one for the subject and one for the body. Obviously, you might need many custom labels to support your real email templates. In the subject, you’ll notice I put in a placeholder ({0}). I’m going to use this in the email template to substitute in the record name.

Now that we have the custom field on the object and the custom labels setup, we can create an email template. We have to use a Visualforce email template to get it to work correctly.

Test it with a record with the language field set and you’ll see the template translated.

Implementing this in the real world gets complicated quickly when you want to merge in fields from the source record, combined with different language syntaxes. I attempted to show one technique using a placeholder, but it isn’t easy to use. In my next post, I’ll show another way to do it.

 

Updating Custom Report Types With All Available Fields

So, you’ve created a custom report type and have been using it for a while. One day you go to use it and realize it is missing all the new fields you’ve added to your org. You can go and edit the report type and drag in the new fields, but of all the interfaces in Salesforce, the Custom Report type one has to be one of the most maddening. (I reserve my anger at State and Country Picklists for the worst at being so damn slow.)

Rather than drag in individual fields, we can use the metadata API to solve the problem. Here are the steps I use:

  1. Create a new report type with the same relationships. Leave it in “In Development” status. This new report type will contain all the fields in your objects by default.
  2. Download the metadata for the report types. You can use MavensMate, workbench or other tools for this. If you use Workbench, here is a sample package.xml file you can use:
  3. Once you get the two metadata files, copy everything in the <sections> tag over from the new one to the old one and save.
  4. Use your preferred metadata tool to push the updated report type back to Salesforce.

Live Agent Sensitive Data Rules

After implementing Live Agent, you may find yourself scratching your head at how to write patterns to prevent sensitive data from being sent over chat. Sure you can just type in strings, but you’ll quickly realize that strings aren’t good enough. The documentation says it supports JavaScript Regex statements, but doesn’t provide much information beyond that. I found Mozilla’s documentation to be the best at helping me with the patterns.

Here are a few patterns that I think you might find helpful. They might not let you Make America Kittens Again, but you can still have some fun with it.

  1. Naughty words case insensitive: you might want to prevent certain bad words to be sent, but quickly realized that case is important in these patterns. for example, you can block “ass”, but what about “Ass” or “ASS” or even “AsS”? Use square brackets to group the two cases together like so:
  2. Naughty words with drawn out vowels. Sometimes people like to repeat vowel sounds in curse words. We can block those too using {n,} where n is a number and the comma means at least that many occurrences of the preceding letter. You can also use the square brackets like in the above example to use character substitutions.
  3. Credit card numbers or Social Security numbers: credit card numbers are either 15 or 16 characters long and are predictable with what number they start with (Amex starts with 3 and 15 long, Visa starts with 4 and is 16 long, etc). Use \d to look for any number and then {n} to tell it how many digits there are (replace n with a number). Use * for optional characters so you can look for strings such as the hyphen between the numbers.
  4. Match whole words only. Maybe you have a word you want blocked when it is used by itself, but it wouldn’t make sense to mask it when part of another word. Let’s say you are anti-fun. you can use \b for word boundaries. In this case I’m using it before and after the string so it has to stand alone, but you can also drop one of them so the match is at the end or beginning of a word only
  5. Blocking strings at the beginning or end only. I can’t think of a great use case, but you can use ^ for beginning and $ for end.
  6. Edit: after a silly back and forth on Twitter with @EvilN8, I had to add one more. This illustrates how complicated you can make things to try and prevent it from masking things you don’t mean to. And I didn’t even get all the possibilities with this one either.