Introduction
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.
Important:
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.
Notes:
- 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, while 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.
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.Notes:
- 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.
- Do not confuse the ellipsis character (
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. |
|
maketext('The system set up your email address') . $email . maketext('on your domain.') |
This example splits the sentence into two separate phrases:
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:
email address is not an untranslated variable, it must remain with the rest of the phrase. |
|
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 thanThe new value is .
- For example,
Correct? |
Phrase |
Explanation |
maketext('The system set up your email address “[_1]” on your domain.', $email) |
This example correctly uses a bracket notation variable in curly quotes. |
|
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 user@example.com on your domain. With curly quotes around the variables, the partial phrase becomes obvious: The system set up your “email address” “user@example.com” on your domain.
|
|
maketext('The new value is “[_1]”.', $value) |
This example correctly uses a bracket notation variable in curly quotes. |
|
maketext('The new value is [_1].', $value) |
Because this example includes bare variables, it may confuse translators. Phrases that include curly quotes show translators the specific locations in which variables will display.
Remember: Translators generally do not view code directly, and will only see the locale system's phrases, without their contexts. |
|
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. Note: 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 |
<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. |
|
<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. |
|
[% 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.
Note:
Use the output
bracket notation method to add specific formatting or characters to localized phrases. For more information, readCPAN's Locale::Maketext::Utils
documentation.
Correct? |
Phrase |
Explanation |
<h3>[% locale.maketext(' Reseller Center' ) %]</h3> |
In this example, formatting tags are correctly outside of the locale.maketextcall. |
|
[% 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. Many excellent books, articles, and other resources exist for this topic.
- 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. This prevents localization of company names, trademarks, and other important terms.
Correct? |
Phrase |
Explanation |
<p>[% locale.maketext('The system installed [asis,Ruby On Rails] on the domain.') %] |
In this example, the asis tag ensures that the term Ruby On Railsdoes not change. |
|
<p>[% locale.maketext('The system installed Ruby On Rails on the domain.') %] |
Your translation service might accidentally translate Ruby On Railsinto something meaningless, such as Gems on Trains. |
Numeration
You can use the numerate
function to properly localize singular and plural text. If you append the .size
suffix to the end of a variable, it returns the size of the variable.
In the following example, the reverse_dns_hostname
variable is a list of strings, and may contain multiple values:
[% locale.maketext( 'A reverse [output,abbr,DNS,Domain Name Service] lookup on the IP address returned the host[numerate,_1,name,names] [list_and_quoted,_2].' , reverse_dns_hostnames.size, reverse_dns_hostnames) %] |
In this example, the system determines the size of the reverse_dns_hostnames
variable. Then, the system passes it through the _1
identifier to the numerate
function, which determines whether to use the singular term name
or the plural term names
.
The system then passes the actual contents of the reverse_dns_hostnames
variable through the _2
identifier to the list_and_quoted
function, which makes a list out of the values and puts them in quotes.
In the interface, this template code could display the following results:
A reverse DNS lookup on the IP address returned the hostname "hostname.example.com". |
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 |
[% 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:
However, this method only adds a single phrase to the lexicon to translate:
|
|
[% 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:
|
|
[% locale.maketext('Save' ) %] |
This example uses a simple phrase that you could use in many instances. |
|
[% 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. |