Development Guides Home >> Guide to Locales

Guide to Locales - Best Practices


The locale system's functionality relies heavily on localization best practices. The system cannot translate phrases as code runs, and instead relies on pre-translated phrases in a lexicon. This document lists best practices and recommendations to ensure that you use easily-translated phrases. If you pay translators to localize your custom strings, these practices can significantly lower translation costs.

Whenever you localize a phrase, make certain to check whether a similar phrase already exists in the lexicon. If one does, use it. Reuse of phrases significantly lowers translation costs.

  • This document's examples use various languages to better illustrate likely use scenarios. For example, you are likely to localize error messages in a Perl script, which titles or headings will generally appear in a Template Toolkit file.
  • Most of the examples in this document use advanced bracket notation methods to illustrate likely use scenarios. For more information, read CPAN's Locale::Maketext::Utils documentation.

Make certain that phrases are complete sentences

Do not use partial phrases, or pass another phrase into the middle of a single phrase.

  • Do not confuse the ellipsis character ( ... ) with three consecutive periods ( . . . ).
  • We strongly recommend that you include a single space on each side of the ellipsis character, unless the ellipsis ends the phrase.

Two exceptions exist for this rule:

  • Labels or titles that use title case should not be complete sentences.
  • Partial phrases during a specific process may use an ellipsis character ( ... ) to convey their context.
Correct? Phrase Explanation
maketext('The system set up your email address “[_1]” on your domain.', $email) This example passes a single phrase that is a complete sentence to the locale system. It uses bracket notation to display the $email value.
No maketext('The system set up your email address') . $email . maketext('on your domain.') This example splits the sentence into two separate phrases:
  • The system set up your email address on
  • your domain.
Because neither of these phrases is a complete sentence, this method presents a translation problem.
maketext('The system set up your “[_1]” “[_2]” on your domain.', 'email address', $email) This example splits the sentence into two separate phrases:
  • The system set up your on your domain.
  • email address
Because email address is not an untranslated variable, it must remain with the remainder of the phrase.
Yes maketext('Starting the update process …') or maketext(' … Done!') This example is correct even though it is not a complete sentence. The ellipsis character conveys the sentence's context to translators.

Do not use bare variables

Do not use bare variables, unless the variable is clearly separated from the text. Whenever possible, we suggest that you surround bracket notation variables in phrases with double curly quotes (“”).

  • You are more likely to notice issues with partial phrases if curly quotes surround all of your variables.
  • Curly quotes help translators understand that a variable will appear in the phrase in a specific location.
    • For example, The new value is “”. will make more sense to translators than The new value is .
Correct? Phrase Explanation
Yes maketext('The system set up your email address “[_1]” on your domain.', $email) This example correctly uses a bracket notation variable in curly quotes.
No maketext('The system set up your [_1] [_2] on your domain.', 'email address', $email) Because this example includes bare variables, the partial phrase in the first variable is easier to miss:
The system set up your email address on your domain.
With curly quotes around the variables, the partial phrase becomes obvious:
The system set up your “email address” “” on your domain.
Yes maketext('The new value is “[_1]”.', $value) This example correctly uses a bracket notation variable in curly quotes.
No maketext('The new value is [_1].', $value) Because this example includes bare variables, it may confuse translators. Translators generally do not view code directly, and will only see the locale system's phrases, without their contexts. Phrases that include curly quotes show translators the specific locations in which variables will display.
  • In The new value is “”., the variable location is obvious.
  • The new value is . appears to be an incomplete sentence.
Yes maketext('The system received the following error message: [_1]', $error) This bare variable is correct, because the colon (:) clearly separates the variable from the phrase. When you use a colon to separate a phrase from a bare variable, make certain to include a single space between the colon and bare variable.

Labels and titles

Labels and titles should use title case.

  • Title case capitalizes the first letter of each word in a label or title. For example: This Is My Label .
  • Labels and titles should not include punctuation.
  • In general, labels and titles will only include a few words.
Correct? Phrase Explanation
Yes <h3>[% locale.maketext('Reseller Center') %]</h3> or [% locale.maketext('Your Domain') %] <input type="text" name="domain"> These examples correctly uses title case for a heading and an interface label, respectively.
No <h3>[% locale.maketext('Reseller center') %]</h3> or [% locale.maketext('Your domain') %] <input type="text"name="domain"> These examples use sentence case. Because this causes the heading or label to appear similar to a partial phrase, it may cause difficulties for translators.
No [% locale.maketext('Enter The Name Of Your Domain.') %] This example incorrectly uses title case. Because the localized phrase is a complete sentence, you should not treat it as a label or title for localization purposes. Write complete sentences in sentence case, even if the phrase's position in the interface's layout is as a label or title.

Localized phrases should not include formatting

Do not include formatting in localized phrases (for example, extra whitespace, tabs, newlines, or other markup).

  • Formatting is almost always specific to a single usage of the phrase. This lessens the phrase's reusability, which often raises translation costs.
  • The locale system may experience errors with some formatting.
  • Formatting markup may confuse translators or other developers.

Use the output bracket notation method to add specific formatting or characters to localized phrases. For more information, read our Guide to Locals - Bracket Notation documentation.

Correct? Phrase Explanation
Yes <h3>[% locale.maketext('Reseller Center') %]</h3> In this example, formatting tags are correctly outside of the locale.maketext call.
No [% locale.maketext('<h3>Reseller Center</h3>') %] Because this example's formatting is included within the translated phrase, it may cause translation problems.

Avoid colloquialisms, jargon, and other dialect-specific words or phrasing

Many colloquialisms or "slang" terms do not translate well. Some normal phrases in one language may even be offensive when translated. For this reason, we strongly recommend that you avoid these words and phrases wherever possible. Precision that may seem unnecessary in one language could be vital in another language.

If you plan to add many new phrases to the locale system, an understanding of Global English will help you write easily translated phrases.

  • For more information, we suggest that you begin with TECHwhirl's Writing for Global Readiness article.
  • If you use a paid translation company, they may have additional resources to help you write easily-translated phrases.

Mark unlocalized text

Mark words or phrases that you do not wish to localize with the asis bracket notation method. This prevents localization of company names, trademarks, and other important terms.

Correct? Phrase Explanation
Yes <p>[% locale.maketext('The system installed [asis,Ruby On Rails] on the domain.') %] In this example, the asis method ensures that the term Ruby On Rails does not change.
No <p>[% locale.maketext('The system installed Ruby On Rails on the domain.') %] Your translation service might accidentally translate Ruby On Rails into something meaningless, such as Gems on Trains.

Create reusable phrases

The number of individual phrases in a lexicon correlates directly to the cost of translation.

  • For this reason, we strongly recommend that you reuse existing phrases whenever possible.
  • Whenever you add new phrases, write them to be as reusable as possible.
Correct? Phrase Explanation
Yes [% locale.maketext('List [numf,_1] of [numf,_2].',10,12) %] The numf bracket notation method will add the number (10) to the phrase when the localized text displays.
You can use this method to display the same phrase with many numbers:
  • List 10 of 12.
  • List 25 of 32.
  • List 100 of 400.
However, this method only adds a single phrase to the lexicon to translate:
  • List [numf,_1] of [numf,_2].
No [% locale.maketext('List 10 records.') %] This example incorrectly hardcodes the number (10) into the phrase. Each of the following similar phrases would require its own entry in the lexicon, and would be translated separately:
  • List 10 records.
  • List 25 records.
  • List 100 records.
Yes [% locale.maketext('Save') %] This example uses a simple phrase that you could use in many instances.
No [% locale.maketext('Save The Spreadsheet Changes') %] This example follows all of the requirements for the locale system, but is very specific to a single usage.

Unless there is a good reason for specific labels (for example, in an interface with several different Save options), we recommend that you generalize labels to minimize the number of lexicon strings to translate.