Code writing standards for easier localization





This article describes code writing standards for easier localization. All of the listed recommendations are mandatory unless noted otherwise.

1. If configuration modules contain strings intended for displaying in the user interface (messages to users, form texts, command names, tooltips, and so on), take measures to facilitate future localization.

Use the NStr function instead of specifying string literals explicitly. Do not use strings intended for displaying in the user interface in any other way.

Incorrect:

DoMessageBox("This action requires installing a file extension.");

Correct:

DoMessageBox(NStr("en='This action requires installing a file extension.'"));

Also ensure that the NStr function is used correctly.
Incorrect:

MessageText = "en='This action requires installing a file extension.'";
DoMessageBox(NStr(MessageText));

Correct:

MessageText = NStr("en='This action requires installing a file extension.'");
DoMessageBox(MessageText);

2. If a string consists of multiple text segments and variables, we strongly recommend writing it as a complete sentence instead of assembling it from segments on the go. Use variable substitution as shown in the following example.

Incorrect:

MessageItemShortage = "Not enough " + ItemDescription + " items in " + WarehouseDescription + " warehouse.";

Correct:

MessageItemShortage = NStr("en='Not enough %Item% items in %Warehouse% warehouse.'") 
MessageItemShortage = StrReplace(MessageItemShortage, "%Item%", ItemDescription); 
MessageItemShortage = StrReplace(MessageItemShortage, "%Warehouse%", WarehouseDescription);

There are two reasons for this. First, parameters might have different positions in different languages. Therefore, localizing a concatenated string might require swapping positions of its segments. Second, incomplete segments are difficult to translate.

Note. In rare cases when substituted values are variables themselves or they include variables (such as %Warehouse%), the method described above that uses StrReplace might give incorrect results. If your configuration includes 1C:Subsystems Library, you can use the function StringFunctionsClientServer.SubstituteParametersInString to bypass the restriction:

MessageItemShortage = StringFunctionsClientServer.SubstituteParametersInString(
    NStr("en='Not enough %1 items in %2 warehouse.'"), ItemDescription,  WarehouseDescription); 

3.  In the NStr function, the string must be enclosed in single straight quotation marks, because string literals often include regular quotation marks.
Incorrect:

DoMessageBox(NStr("en=Variable of ""String"" type")); 
DoMessageBox(NStr("en=""Variable of ""String"" type"""));

Correct:

DoMessageBox(NStr("en='Variable of ""String"" type'"));

4. However, if you decide to use a concatenated string instead of a string with variable substitution, present characters that are not language-specific (spaces, tabs, and so on) as individual string literals, which do not require translation.

Incorrect:

MessageText = NStr("en = 'Balance of funds issued to person accountable: '")
  + QueryResultSelection.BalanceOfPersonAccountable;

Correct:

MessageText = NStr("en = 'Balance of funds issued to person accountable:'")
  + " " + QueryResultSelection.BalanceOfPersonAccountable;

5. Rarely string literals displayed in the user interface are defined in queries. Define such literals as parameters instead of defining them explicitly in the query text.
Incorrect:

QueryByVersions = New Query(" 
  |SELECT 
  |Versions.Ref, 
  |CASE WHEN Versions.Released = TRUE 
  | THEN ""(released)"" 
  | ELSE ""(in development)"" 
  |END AS TextAnnotation
  | FROM 
  | Catalog.Versions AS Versions");

Correct:

QueryByVersions = New Query("
  |SELECT 
  |Versions.Ref, 
  |CASE WHEN Versions.Released = TRUE 
  | THEN &TextReleasedVersion 
  | ELSE &TextNotReleasedVersion 
  |END AS TextAnnotation
  | FROM 
  | Catalog.Versions AS Versions");
QueryByVersions.SetParameter("&TextReleasedVersion", NStr("en='(released)'")); 
QueryByVersions.SetParameter("&TextNotReleasedVersion", NStr("en='(in development)'"));

6. When you use the Format function for displaying dates, remember that the date and time format varies between countries and regions. For example, you can write the same date as 12/20/2012 (US format) or 20.12.2012 (Russian format).

Therefore, instead of specifying dates explicitly

Format(Date, "DF=MM/dd/yyyy")

use the local date format:

Format(Date, "DLF=D")

Another incorrect usage example:

Format(ApprovalDate, "DF='MMMM dd, yyyy'")

Correct:

Format(ApprovalDate, "DLF=DD")

7.1. When you specify date format in form input fields or in data composition schema-based report fields, also use local date format.

7.2. In form fields with choice lists always set the ListChoiceMode property to True. Then the fields will display localized presentations (which is correct) instead of choice list values.

7.3. When you redefine standard field presentations in data composition schema-based reports, follow the same rules as when writing module script. For example, this is incorrect:

"No. " + Number + " from " + Format(Date, "DF=MM/dd/yyyy")

And this is the correct expression for calculating field presentation:

StringFunctionsClientServer.SubstituteParametersInString(
  NStr("en = 'No. %1 from %2'"),
  Number,
  Format(Date, "DLF=D"))

Note. The StringFunctionsClientServer.SubstituteParametersInString function is available if 1C:Subsystems Library is included in your configuration.

8. Exceptions from the listed rules are:

8.1. Strings generated by the script that are recorded to the infobase and displayed to users.
For example, an autogenerated comment to a posting operation, or the EventName parameter of the WriteLogEvent method.

Make such strings available for localization but explicitly specify the default configuration language for them. If you do not, you can encounter issues like this: a document is posted by a user with English interface and then reposted by a user with German interface, and the accounting register records change (which is incorrect).
We recommend that for each script fragment that generates such strings you add a comment explaining the exception from general localization rules: 

Comment = NStr("en = 'Comment to posting'", Metadata.DefaultLanguage.LanguageCode); // this string is recorded to the infobase

8.2. Do not localize string constants that store internal IDs and are never displayed to users. Do not apply the NStr function to these constants.
Examples: 

Type("Array")
Return "OperationCompletedSuccessfully";
Notify("Write_File", New Structure("Event", "VersionSaved"), FileRef);
OpenForm("Catalog.AdditionalAttributeAndDataSets.Form.EditSetsContent");

8.3. Do not localize query texts.


Comments
0
Add comment