EMC Developer Network
 

EMC Developer Network - NLS Translator Tool for Documentum

NLS Translator Tool for Documentum

November 2007
Contributed by - Mitch Bird

Abstract

This program assists in the creation of localized NLS files not included in the Documentum Language Packs. In other words, NLS files for all of your custom applications and objects, so long as you used NLS files for their strings. The program also helps fix the Documentum Language Pack NLS files that have missing entries.


The Story

Recently, I was called on to implement a Spanish version of an installation of Webtop. This was for a relatively mature installation that included several types of custom applications and more than just a few actual modifications to the standard Documentum classes; the custom folder contained more than twenty folders most of which contained subfolders. Altogether they reflected the structures found within the standard Documentum folders like 'webcomponent', and 'wdk' with the addition of the custom application's folders.


The first step, of course, was to install the Spanish Language pack to the war folder which, it turned out, was very easy to do. The Language Pack file is a zip file. When it is unpacked it creates a folder structure that contains the same folder structure as the actual war folder. It is then just a simple matter to copy that expanded folder right on top of the war folder and the files all end up where they should go.


Another was to make a couple language config changes to an app.xml file. The language config settings are to be entered in VIRTUAL_ROOT/webtop/app.xml or if modified VIRTUAL_ROOT/custom/app.xml Those changes were as follows: add the reference to Spanish in the 'supported_locales' section and set the 'fallback_to_english_locale' flag to true. Your language section might look as follows:



<!-- language section -->
	<language>
		<supported_locales>
			<locale>en_US</locale>
			<locale lang="Spanish" version="5.3.0.308">es_ES</locale>
		</supported_locales>
		<default_locale>en_US</default_locale>
		<fallback_to_english_locale>True</fallback_to_english_locale>
	</language>

There were still a couple of small hurdles to deal with before I could start. The first was that several of our custom applications had not made full use of the NLS properties files for the storing and retrieval of strings. Fixing that was pretty straightforward.


The next was that several other of our applications were written in DocBasic and so could not take advantage of NLS properties files. Those applications were automation type apps without any real interface components. So be it, re- writing those applications was way outside of scope.


Another was that the headers in 'objectlist-type' components were not displaying the labels associated with custom fields but rather the field names themselves. I found an article on the EDN and followed the instructions to a T. While I was doing it I was thinking to myself ... that doesn't make a lot of sense. The way it was written every record would be examined to determine its custom field's params. Hmmm. The article wanted me to modify the 'custom_attribute_data_handlers' tag in app.xml, then create an implementation class based on ICustomAttributeDataHandler when really all I had to do was configure.


Some interesting information about how Documentum stores field information can be found by running the following DQL and then doing a dump on a couple of the object ids returned:


select * from dm_type where name = 'some_custom_object_type'
select * from dmi_type_info where r_type_name = 'some_custom_object_type'
select * from dm_aggr_domain where type_name = 'some_custom_object_type'

What really needs to be done is adding references to your custom fields in the following files. If your company uses the Streamline interface then I think you will also have to modify... a couple other components.


The XML sections go into
VIRTUAL_ROOT/webcomponent/config/navigation/homecabinet/homecabinet_list_component.xml
and
VIRTUAL_ROOT/webcomponent/config/navigation/doclist/doclist_component.xml


Here is a sample of how to edit those files. The first entry makes it so 'r_object_id' column headings say 'Object ID' the rest are for a custom application.



<!-- start missing from Documentum implementation -->             
		<column>
		    <attribute>r_object_id</attribute>
		    <label><nlsid>MSG_DDOC_OBJECT_ID</nlsid></label>
		    <visible>false</visible>
		</column> 
<!-- end missing from Documentum implementation --> 		
<!-- start CustomApp attributes -->
		<column>
		 <attribute>mb_customapp_number</attribute>
		 <label><nlsid>MSG_MBCA_NUMBER</nlsid></label>
		 <visible>false</visible>
		</column>
		<column>
		 <attribute>mb_customapp_fiscal_year</attribute>
		 <label><nlsid>MSG_MBCA_FISCAL_YEAR</nlsid></label>
		 <visible>false</visible>
		</column>
		<column>
		    <attribute>mb_customapp_responsible</attribute>
		    <label><nlsid>MSG_MBCA_RESPONSIBLE</nlsid></label>
		    <visible>false</visible>
		</column>
		<column>
		    <attribute>mb_customapp_routing_date</attribute>
		    <label><nlsid>MSG_MBCA_ROUTING_DATE</nlsid></label>
		    <visible>false</visible>
		</column>
		<column>
		    <attribute>mb_customapp_routing_node</attribute>
		    <label><nlsid>MSG_MBCA_ROUTING_NODE</nlsid></label>
		    <visible>false</visible>
		</column>
		<column>
		    <attribute>mb_customapp_routing_note</attribute>
		    <label><nlsid>MSG_MBCA_ROUTING_NOTE</nlsid></label>
		    <visible>false</visible>
		</column>
		<column>
		    <attribute>mb_customapp_status</attribute>
		    <label><nlsid>MSG_MBCA_STATUS</nlsid></label>
		    <visible>false</visible>
		</column>
		<column>
		    <attribute>mb_customapp_type</attribute>
		    <label><nlsid>MSG_MBCA_TYPE</nlsid></label>
		    <visible>false</visible>
		</column>
		<column>
		    <attribute>mb_customapp_completion_date</attribute>
		    <label><nlsid>MSG_MBCA_COMPLETION_DATE</nlsid></label>
		    <visible>false</visible>
		</column>
		<column>
		    <attribute>mb_customapp_workflow_id</attribute>
		    <label><nlsid>MSG_MBCA_WORKFLOW_ID</nlsid></label>
		    <visible>false</visible>
		</column>
<!-- end CustomApp attributes -->


Then, of course, the NLS'd key/value pairs go into the following files:
VIRTUAL_ROOT\custom\strings\com\documentum\custom\navigation\homecabinet\HomeCabinetListNlsProp.properties
and
VIRTUAL_ROOT\custom\strings\com\documentum\custom\navigation\doclist\DocListNlsProp.properties


A sample from those files follows:


#dm_document
MSG_DDOC_OBJECT_ID=Object ID

#CustomApp
MSG_MBCA_FISCAL_YEAR=Fiscal Year
MSG_MBCA_NUMBER=ID Number
MSG_MBCA_RESPONSIBLE=Responsible
MSG_MBCA_ROUTING_DATE=Routing Date
MSG_MBCA_ROUTING_NODE=Routing Node
MSG_MBCA_ROUTING_NOTE=Routing Note
MSG_MBCA_STATUS=Status
MSG_MBCA_TYPE=Type
MSG_MBCA_COMPLETION_DATE=Completion Date
MSG_MBCA_WORKFLOW_ID=Workflow ID

So with those things fixed I only had to create my NLS properties files for my custom classes ... or so I thought. I did some preliminary checking into how well the Language Pack had worked and found out there were quite a few translations missing. Basically, the Language Pack files hadn't been updated for about two years, and so, many new keys had never been translated. As I started looking for the missing references, I began to realize why those keys were missing.


Creating and tracking all of the key/value pairs and then verifying that each one had a matching foreign translation was going to be nothing less than a clerical nightmare.


The Need for a Tool

What I needed was a tool with a simple interface where all of the translations could be entered quickly and conveniently. It would automatically replicate values whose keys are actually aliases for the same string so, for example, one would only have to translate the word 'Cancel' once.


It would need a special way to handle the 'NLS_INCLUDES=' keys, which can have multiple comma separated references to other NLS files. Those values need to be automatically changed to reference the foreign language versions.


Because I don't actually speak Spanish and wouldn't be sitting there with the person doing the actual translating, the interface had to be easy to use and understand, and include the ability for the translator to flag any key/value pairs that he might have a question about. It should also automatically flag any values containing arguments, like {0}, {1} so that I (or some other programmer) could verify they are still syntactically correct before generating the new NLS files. Also, anomalies like empty values in the English properties files should be flagged.


I thought about creating a 'commented line' tracker to regenerate included comments but never got around to it. A nice report should be generated, too.


Another thing that my translator might thank me for would be a button that simply enters the English string into the translation for 'internationalized' English values like 'Microsoft Word'.


A way to verify the completeness of the NLS files that came in the Language Pack, is critical. The tool should make the incremental updating of sets of NLS files quick and painless so the form should be able to filter up only the untranslated key/value pairs at any time while the translator is entering data. In other words, when they get back from lunch and still have 250 k/v pairs left to translate. The tool should be able to quickly add the missing key/value pairs and re-generate the updated files. Those files should be created into a pseudo copy of the folder structure; just like the Language Packs themselves, in order to make installing them just as simple.


At the same time, the tool should quickly create all of the NLS files for my custom applications which should also follow the same folder structure rules as the standard files so that the final installation is one simple copy and paste ... piece of cake.


Lastly, it would be nice if the program could start from any folder so that only the custom apps might be worked or even an entire Documentum install including all of the applications and not just Webtop.


The Plan

I thought a simple VB/ADO application with a Microsoft Access database as the back end would do the trick nicely. I am an old hand at that but in VB6 using classic ADO. I thought this would be an excellent opportunity to expand my horizons by doing it in .NET and with a few of those new fangled ADO data adapter thingies. The Access database would have a data entry form built right in. For the translator's convenience I would use the old 'autoexec' trick to make the form open by default and to hide my actual tables. The front end (the VB.NET part) would have a config screen for setting up the flowerbox contents, for locating the folder from which to get the data, and lastly, for creating and monitoring the creation of the new NLS properties files/folders.


The Answer

Download the install file and unzip it to your desktop. Inside the folder that will be created are both the install files and the Access file that will hold the data. Make a copy of the Access file somewhere and keep the it as your template. Run setup.exe and try it out.


If you are not actually doing a localization project right now but would like to try out the program anyway, you can easily do that by just creating a small folder heirarchy and copying some of your 'properties' files into the folders. In that way you can quickly walk through the whole process with a minimum of data entry.


During initial setup of a translation, the user enters information which will become the flowerbox - header section - of the generated NLS files.


Data entry is done in a streamlined interface that handles redundant values by requiring only a single entry. So, for example, if you have 50 Keys which are all aliases for the word 'false', your translator will only have to enter a translation for one them and all of the rest will be filled in automatically. There is also a checkbox which the translator can use to mark entries that he feels need clarification or special attention.


The program works for any of the single byte languages and may work for double byte languages, but in all honesty, it was just too much trouble to set up the testing.


How Does It Work?

It is recommended that the program be run against a copy of the actual war folder, just to be safe. Not that anything would go wrong, but it is a best practice to keep your original files secure.


The program recursively goes through a copy of an application's war folder, for example 'webtop.war', and finds all files that end in '.properties'. Files under the 'custom' folder are automatically processed and files under the other folders are checked for completeness/existence against the assumed localized version.


In other words, when the progarm gets to the ... 'webtop.war\webcomponent\strings\com\documentum\webcomponent\navigation\doclist' folder, if the program is working on a spanish translation i.e., _es_ES, then the program will be looking for a file called 'DocListNlsProp_es_ES.properties' that goes along with the 'DocListNlsProp.properties' file. If it finds the file it will compare the two and verify that there exists a matching entry for each of the entries in the original file. If it doesn't find the file it will treat the matter just like a 'custom' NLS file and process the data into the database for creation of a localized version. I found that many of the Documentum provided Language Pack NLS files were missing entries and also that quite a few of the standard OOTB NLS files did not have localized versions included in the Language Pack.


The program gathers all of the key/value pairs from the NLS files identified as to be included into an Access database along with their paths and file names. The program then identifies values that may need special treatment - containing arguments like {0}, {1} - and flags them for final review. It then marks duplicate values, so the translator only has to translate each unique value once. Finally, it applies special treatment to 'NLS_INCLUDES' tags.


At this point, the Access database is ready to hand off to the translator. When the translator opens the database, a form appears where she can enter the translations. This form automatically opens when the file is opened. In order to open a standard view of the database, the user must hold down the shift key from before double clicking the file icon until the file is completely open. This makes it so the average user will only see the 'Enter Translations' form.


Once all the translations have been entered, open the Access file with this program again and once opened, click the 'Create New Locale Files' button.


A dialog appears asking where the program should create the files. The program creates a folder structure which mirrors the original war folder's structure. The original war folder should not be used for this because the translation folders will be created in a root folder called 'NLSTranslations' and would therefore not end up in the original folders.


Once finished a report will also be in the root of that folder, identifying various entries that may require special attention. Review that report before moving the files into the war folder.


That's it. Instant - or at least relatively so - localization of your Documentum applications.


Note: If you are processing a very large extraction, the program may appear to lock up for a moment (but never really does), owing to the extraction process being a linear and processor intensive algorithm, but it will finish in a moment or two.


Screen Shots

Click on photos for larger images



Main screen



Configuration screen



Main screen after processing



Data entry screen


About the Author

Mitch Bird has over 10 years experience programming; with professional projects written in .Net, Java, PHP, COBOL, and several other languages. He wrote the MrDistrict CRM program (www.mrdistrict.com) used by many State and Local politicians. He is somewhat new to Documentum, though, and has been programming with DFC/WDK about a year. Mitch has written several Enterprise DocApps and created about a dozen utilities for such things as DocApp Creation automation, Index Agent Maintenance and Monitoring, InputAccel and Method server monitors, file migration tools and others. He can be reached at mitchbird@birdco.net. Mitch is willing to send the source code for this project to those who request it via email.


Discuss

Click here to discuss this article