This is a reposting of an article I originally wrote on my Developing for Dynamics GP blog.
After a chat with Mariano Gomez, who was directly responsible for the creation of the first Spanish version of Microsoft Dynamics GP, I realized that I had not yet covered some additional areas that will need translation. This post will try to cover the other areas you need to consider.
For many of the topics covered in the following sections, you will need to have a ‘Language ID’ of globals value for your language. The Language ID is assigned when Microsoft Dynamics GP launches. The system looks at the value in the message 9999 (eg. “English-US”) and compares it to a number of constants to identify the language being used. In the case of “English-US” the constant value is 0.
The integers for the Language ID values can be found in the LanguageID() global function. For more information on the Language ID and a list of values for the various languages, please see the following Knowledge Base (KB) article:
You will probably have noticed when launch Microsoft Dynamics GP for the first time after installation that it will run through a process of building SQL messages. This process copies all messages from the core Dynamics.dic dictionary into a SQL table for the current Language ID. The messages in the MESSAGES (MESSAGES) table are then used by Stored Procedures when they need to return error messages. To make sure that the messages from your translated dictionary are updated into the table for your Language ID, you will need to change the Dex.ini setting below to true:
Error and Warning Dialogs
Within Microsoft Dynamics GP there are two types of error or warning dialogs:
Those created from messages using getmsg() (and substitute) commands and the error or warning system dialogs. i.e. warning getmsg(10007);
Those created using the SY_Error_Message form and the Warning_Dialog global procedure.
The first type will have already been translated when we updated the strings and messages in the dictionary. It is the second type which need further work as they read their error description and more information text from tables.
The Warning_Dialog global procedure will read data from the following tables:
SY_Error_Messages_MSTR (SY01700) for core messages
SY_Error_Messages_MSTR_3rd (ALERT3RD) for 3rd party messages (numbered >= 100000)
GPS_SQL_Error_Codes (GPS_SQL_Error_Codes) for errors from stored procedures
In all cases the code will look for a record using the current Language ID. If no record can be found, it will look again using a Language ID of 0 for the English-US record.
You will need to add records into these tables for your Language ID.
The system also has another table which stores translated terms for various Language IDs. This is primarily used from report via the RW_GetTranslatedStringValue() report writer function. This function calls the function GetTranslatedStringValue() of form syLanguage which reads the SY_Language_MSTR (SY05300) table. You will also need to add translated values into this table.
Some other tables that also use Language ID and might need to be looked at are:
coProcess (SY01300) Process Monitor Information
syReportingToolsReport (SY10900) Reporting Tools Report
syReportingToolsData (SY10990) Reporting Tools Data
syReportingToolsXMLData (SY10995) Reporting Tools XML Data
syReportingToolsBIMessages (SY10996) Business Intelligence Messages
syReportingToolsBIEnum (SY10997) Business Intelligence Enumerations
There are other tables in the system which do not use a Language ID, but have text which can be translated. For example:
sySecurityMSTRRole (SY09100) Security Roles Master (v10.00 and above)
sySecurityMSTRTask (SY09000) Security Task Master (v10.00 and above)
syCurrentResources (SY09400) Security Resource Descriptions (v10.00 and above) *
* Running Clear Data on this table will rebuild the resource descriptions from the translated dictionary.
Re-using Strings and Messages
If developing your own third party add-on customizations, be sure to enter the same strings as used in the core Dynamics.dic dictionary where possible. Dexterity will re-use an existing string if it can. This means if your dictionary uses “Customer ID” or “Vendor ID” as a string, it will be associated with the string in the core dictionary. When the string in the core dictionary is translated, it will also be translated for your dictionary. If you create a new string by using “Customer id” for example, it will not be translated automatically as it will now be a new string in your dictionary.
Where possible you can also re-use messages from the core dictionary rather than creating new messages. This will decrease the number of message resources needed to be translated in your dictionary, thereby decreasing the cost of translation. It also ensures your product’s consistency with the core product.
A final point about strings, don’t use multiple terms for the same object. For example: Don’t use “Account ID” to refer to an “Account Number” when “Account Number” is used every else. This can confuse the person performing the translation as they will be unsure if this is referring to a single object or not.
I am not going to go into details on this post, but you can use Dexterity Utilities to create a chunk file which includes all the core messages and strings for each series. This is how the language chunks such as AUERR.CNK, NZERR.CNK, SGERR.CNK are created and used to change the language of the core Dynamics.dic dictionary. For a translation like Arabic or Hebrew where many of the windows have been altered, it might be simpler to provide the translated Dynamics.dic rather than using a language chunk file.
For a third party add-on dictionary you would normally just use a translated chunk.
I am sure that this is not an exhaustive list, but it hopefully will cover most of the additional areas you need to look at.
This article was originally posted on the Developing for Dynamics GP Blog and has been reposted on http://www.winthropdc.com/blog.