This is a community wiki. Feel free to add to it!
Please excuse the overly Americentric examples here.
Overriding Principals
Do not require the programmer to know the details of every language or locale that you plan to support.
Make the system flexible enough to allow an admin with fluency in the domain and any given locale* to provide a meaningful interface for users of that locale.
Custom Labels
- Use Custom Labels for all text that the system generates.
- If you have a complex piece of text that is generated in Apex including variables (e.g.,
'Please enter the first ' + numChars + ' characters'
) then use String.format
to allow translators to fill in details or <apex:outputText>
- Context matters, so name and categorize your labels as they will be used. For example, "Back" may mean "Go to the previous page" or "the opposite of front". If you use it in both senses, it is two different labels.
Dates and times
- Do not rely on a specific date or time format (e.g.,
MM/dd/yyyy
or dd/MM/yyyy
) anywhere.
- Never parse a string for date formats unless the string is generated by an external process. In that case, make the parsing format explicit.
- Do not use Strings as dates.
- Unless there is a reason to capture dates themselves (e.g., birthdays), use datetimes.
Picklists
- Be aware of the difference between
getValue
and getLabel
- Rely on
getValue
for internal processes, and getLabel
for presentation.
- You can use the
TOLABEL()
function in SOQL queries for presentation
Object Names and Field Labels
- Rely on "describe" information or,
$ObjectType
notation (e.g., {!$ObjectType.Account.Fields.Name.Label}
or {!$ObjectType.Account.Fields.Name.LabelPlural}
) for labels that are simply the name of the relevant field/object.
X-Localization SObjects
When you turn on Translation Workbench, you get new objects for the following objects all suffixed by "Localization":
They all have the same usable fields: Language, ParentId, Value. You should use these when providing the user with lists of these objects instead of using the original objects.
Record Types
- Use the DeveloperName, not the Name of the Record Type
Front-end
- If there are strings generated exclusively on the front-end, create a
global
service that you can call to translate appropriately within the Translation Workbench framework.
- If the String.format method as a service is too slow or awkward, check out sprintf-js for similar functionality.
ENCODE
- Since you have no control over what characters a translator will use, make sure to use
HTMLENCODE
, JSENCODE
and JSINHTMLENCODE
liberally in any literal HTML/JS your Visualforce pages.
Don't rely on literals
Ensure that you are not relying on literals whenever it is possible to avoid.
Testing
Test it all out with a fine-toothed comb and a native speaker.
* I am defining "locale" here in the general sense - A nebulous combination of language, datetime formats, currency, timezones, dialect and perhaps some cultural expectations.