Posts in Category "Libraries"

The Problem with Localizing Software for Multiple Platforms

Adobe has a long history of developing products for multiple platforms, be it desktop applications like our flagship Creative Suite applications or newer touch applications like Photoshop Touch. Most of our desktop apps have been built for both Windows and Mac and newer applications continue on this trend with support for iOS and Android including Tablet and Phone form factors for both.

Of course this would not have been possible without the careful efforts of the engineering team to largely maintain a single code base for all platforms.

While having a single code base has obvious benefits, in the UI layer it is often important to have platform specific variations for better usability. Each platform usually has a specific convention for referring to system menus, short cut keys and UI elements. For example on a windows platform a UI String could be – “Select a media file via the Browse button or enter a valid pathname.” and the same string for the Mac Platform could be – “Select a media file via the Choose button or enter a valid pathname.”

This means that translatable UI strings may have many variations in the source language depending upon which platform they are intended for. This is what our globalization group usually refers to as ‘Platform Variance’. Localizable strings are essentially multivalued entities. Each localizable string has an identifier and multiple associated values each of which can be selected based on certain criteria. The most obvious and commonly used criteria is the UI locale of the application but it need not be the only one. Platform too can decide the value of a string.

Platform variance support is not just useful for handling terminology differences for referring to system UI elements, it also helps adapt strings for different screen sizes. Modern application are designed for supporting multiple device form factors like tablet and phone with the UI being tweaked for each platform for best user experience. Platform variance in this case can be used to support longer strings for the Tablet view and shorter strings for the Phone view.

Yet another area where platform variance support could potentially be useful is in having different localizable values for a Pro version versus a Consumer version of the application.

However, localizing strings with platform variant data is a problem. The problem is two fold, one is in managing the processes and project schedule to allow for agile localization and simultaneous release for all target platforms. The second aspect is technically supporting the platform variance in both programming libraries and translation tools. Many tools and libraries assume a single value for a source and a target string, but in case of platform variance not only can there be multiple source and target values for a string there need not be a one-to-one correspondence between source and target values. There may be multiple platform variants for a source string that map to the same translated/target value or a single source string may need to be translated differently based on platform for the target locale. For example:

  • en_US: “Please close the dialog and start over.”
  • default fr_FR: “Fermez la zone de dialogue et recommencez.”
  • Windows fr_FR: “Fermez la boîte de dialogue et recommencez.”

Since I am part of the globalization tools team here at Adobe, the remainder of this post I describe the problem more from a technical tools and libraries perspective, drawing from my experience. The process problem is also pretty complex and would probably take a much longer blog post to discuss. In fact there’s a related one already on this blog, see – link.

Platform Variance Support in Libraries

Ideally the globalization libraries/APIs used in the code to manage externalized strings and the corresponding storage formats for the externalized data should have a notion of a platform variant value for each string. There should be a way to request a string value for a specific locale and platform along with a provision to fall back to a default value in case a platform specific value is not specified.

As an example, the Java ResourceBundle API supports selecting a bundle by ‘Locale’, there is no explicit mention of a ‘Platform’, but the ‘Locale’ itself is extensible to support variants. The variant mechanism in the ‘Locale’ can be used for supporting different platforms and there is also a fall back mechanism. At Adobe we have a custom developed cross platform library called ZString for managing externalized strings with explicit support for platform variance.

Platform Variance Support in Translation Tools

Most translation management systems (TMSs) have a one-to-one model of source strings with matching translated strings for each locale. This assumption is behind the architecture of the TM matching algorithms as well as the design of the translation workbench. A typical translation workbench usually offers a side by side view of source and target strings, but only supporting a single source string corresponding to a single translated value.

Typical Translation Workbench

A typical side by side view of Source and Target content in a translation tool

We are still searching for the ideal solution to this problem. For managing the TMs a possible workaround using existing systems is to have duplicate entries in the Translation Memory (TM) or a separate TM for each platform.

However, translators are still constrained by the view presented by their translation workbench. A possible solution to allow translation vendors to provide platform specific translations is to duplicate all the source strings for each possible target platform. The source value for the default platform can be used as the source value for all other platform unless the application UI already specifies a value for a specific platform in which case that is used. Now the translator can provide different translations for each platform if required. This workaround however seems to be a significant amount of additional work for the translators. Some optimization is possible by translating a single platform first and leveraging translations for all the other platforms.

In an ideal scenario the translation workbench would provide a side by side view of all platform variants for the source string and the target strings. With the ability for the translator to remove variants from the translated string where they are not required and propose variants for the translated string even if the source string does not have any. This would allow translators to work through the source content in a single pass, editing leveraged translations, providing new translations where required and proposing platform specific translated values as appropriate.

An approximation to this ideal view is an Excel sheet with each source string being represented in a row and having a separate column for each platform for both source and target strings. With blank values in a platform column signifying that the default translation is to be used for that platform and non-blank platform entries being used for the platform specific translations.

Ideal Translation Workbench

A proposed translation workbench view allowing simultaneous translations for multiple platforms

We are still experimenting to find the optimal solution for our needs, that offers flexibility to translators and yet leverages our investment in existing translation tools and processes. The goal is to be able to support faster agile release cycles with all platform releases happening simultaneously.

I think this is a good forum to ask our blog readers if they have faced similar problems and the solutions they have developed to deal with it.

Adobe Moses Tools now available for Windows

This article was originally written in English. Text in other languages is provided via machine translation.

We have an update on the [tp no_translate="y"]Adobe Moses Tools[/tp] which we announced on this blog on May 11.  The tools are now available in pre-built packages for [tp no_translate="y"]Windows[/tp]!  Check out the download section of the M4Loc site to get the [tp no_translate="y"]Windows[/tp] packages and for documentation and other information about the tools.

Please download the tools and let us know what you think!

–Raymond Flournoy
[tp no_translate="y"]Senior Program Manager[/tp]
[tp no_translate="y"]Translation Technology Team[/tp]

Invoking ICU from Adobe AIR Applications (Part 2): using Flash Builder 4.6

This article was originally written in English. Text in other languages was provided by machine translation.

In my previous blog article http://blogs.adobe.com/globalization/invoking-icu-from-adobe-air-applications-2, I demonstrated using the AIR3 ActionScript Native Extensions feature to invoke ICU from an AIR application. I used the AIR developer tools to compile and build various components. In this article, I demonstrate the same using the prerelease version of Adobe Flash Builder 4.6. It is much simpler to do this in Flash Builder avoiding the cumbersome command line.

The prerelease version of Adobe Flash Builder4.6 has a new Flex SDK version 4.5.2, which has AIR3 integrated. Please download the sample files as follows.

You will need the following software to build an ICU extension for AIR platform.

1         Building ICU extension for Adobe AIR

Adobe AIR t native extensions, also known as ‘ane’ or ‘ANE’ files are archived packages. These consist of

  • ActionScript wrapper classes calling into external DLLs
  • The external DLLs
  • XML file describing details of external DLLs

The archived ANE files are used just like SWC libraries in integrating into an AIR application. In other words, ANE file is a library and it has public ActionScript APIs.

Covering all details about the ActionScript extension is too much for this blog article, but I will explain the steps to build this sample and run. Below are the sequential steps and commands.

1.1       Building Windows AIR ICU Extension DLL

1)      The AirIcuExtensionWin folder has the Visual studio solution ‘AirIcuExtension.sln’. Open this in MS VS2010.

2)      The file AIRIcuExtension.cpp has the necessary code needed to interface with Adobe AIR 3. It also has the wrapper routines calling ICU C functions.

3)      This is a DLL project and the build output is AirIcuExtension.dll

1.2       Building ActionScript Library in FB 4.6

1.2.1       Building the ActionScript library

Create a new ActionScript Library project and name it AirIcuExtension. See the downloaded ActionScript FB4.6 library project.

1.2.2       Packaging ActionScript native extension

To package an ANE, you still need to do it in commandline. FB 4.6 does not have a feature yet to generate ANEs in the IDE.

Open the binAirIcuExtension.swc is a zipped archive. Open it using WinRAR or WinZip program and extract the library.swf file in the swc package into the AirIcuExtensionbin folder.

The folder srcresources contains file extension.xml, AirIcuExtension.dll and ICU dlls icudt48.dll, icuuc48.dll, icuio48.dll and icuin48.dll. The file external.xml defines the external library details to AIR runtime.

For simplicity, place the AirIcuExtension.dll, ICU dlls and extension.xml files in AirIcuExtensionbin folder. All these files are packaged into a zipped archive called AiricuExtension.ane using the following command.

C:FB4.6sdksbinadt -package -storetype pkcs12 -storepass <passwd> –keystore <AIR certificate> -tsa none -target ane AirIcuExtension.ane extension.xml -swc AirIcuExtension.swc -platform Windows-x86 library.swf AirIcuExtension.dll icudt48.dll icuin48.dll icuio48.dll icuuc48.dll

Using Adobe FlashBuilder4.6 or  C:FB4.6sdksbinadt program, one can generate an AIR certificate.

The output is an archive file AirIcuExtension.ane in the AirIcuExtensionbin folder.

1.3       Building the Test program AirIcuExtensionTest.mxml

Now that we built and packaged the native extension package AiricuExtension.ane, we are ready to use this and call ICU services in a test program.

The folder AirIcuExtensionTestsrc contains the test file AirIcuExtensionTest.mxml. The descriptor file AirIcuExtensionTest-app.xml has  the details of native extension.

Flash builder4.6 has a new feature to link Flash applications with ANE files. As you see from the FB4.6 project properties ‘Flex Build Path’ command, there is a new tab for Native Extensions. Using ‘Add ANE’ button, add the AirIcuExtension.ane file present in the AirIcuExtension/bin folder as shown below.

Also see the ‘Flex Building Package’ command in the project properties, there is a new tab for Native Extension. Please make sure that the check box for AiricuExtension is On.

The output swf file AirIcuExtensionTest.swf is placed in the bin-debug folder.

1.4       Building AIR package for executing AirIcuExtensionTest

The final step is to package the above AirIcuExtensionTest .swf and AirIcuExtension.ane files into an AIR executable folder.  We can do this in FB4.6 now instead of using tedious command line.

  • IN FB4.6, select AiricuExtensionProject and execute menu command Project->Export Release Build…
  • In the ensuing dialog, choose Signed native installer radio button. We can only create native installers as we are using OS specific ANE package.
  • In the Native Extensions tab, make sure that the AirIcuExtension.ane checkbox is On.
  • Finish creating the release build after entering the correct AIR certificate credentials.

The output of the above command is an installer AirIcuExtensionTest.exe. By executing it, you can install the test program.

2         Conclusion

The sample illustrated how to invoke ICU from ActionScript. The AIR ICU extension is easy to build using the upcoming AdobeFlash Builder 4.6 release. ANE is a great feature for AIR developers and AIR applications can make use of the platform or ICU provided globalization services.

A lightweight auto-complete ActionScript example with a trie

This article was originally written in English. Text in other languages was provided by machine translation.


Auto-complete functionality is used widely over the internet and mobile apps. A lot of websites and apps try to complete your input as soon as you start typing.  In this post, I would like to introduce a simple ActionScript auto-complete solution by using trie data structure.

A trie is an ordered tree data structure that is used to store an associative array. All the descendants of a node have a common prefix of the string associated with that node, and the root is associated with the empty string. Starting from the root node, you can check if a word exists in the trie easily by following pointers corresponding to the letters in the target word. Trie is a well-known data structure in computer science; you can find the detailed information about trie through Wikipedia.

Here is a simple trie implementation in ActionScript:

/**
* An simple data structure to store and look up words.
* @see http://en.wikipedia.org/wiki/Trie for additional details.
*/

public class Trie {
private var _rootKeys:Array;
public function Trie():void {
_rootKeys=[];
}

/**
* Return a list of words which have the given prefix.
*/

public function get(prefix:String):Array {
var results:Array=[];
var letter:String=prefix.substr(0,1);
var root:TrieNode=_rootKeys[letter];
if (root) {
getWordList(prefix, 1, root, results);
}
return results;
}

/**
* Add a word to the object which can be matched as a prefix.
*/

public function add(word:String):void {
var letter:String=word.substr(0,1);
var root:TrieNode=_rootKeys[letter];


if (!root) {
root=createNode(letter);
_rootKeys[letter]=root;
}
insertWord(word, 1, root);
}


private function traverse(root:TrieNode, results:Array, prefix:String):void {
if(root.children) {
for each( var c:TrieNode in root.children ) {
var node:TrieNode = c as TrieNode;
if( node.word ) {
results.push( prefix + node.value);
}
traverse(node, results, prefix+node.value );
}
}
}


private function getWordList(prefix:String,
position:uint,
root:TrieNode,
results:Array):void {
var letter:String=prefix.substr(position,1);
var child:TrieNode=root.children[letter];
if (!letter || !child) {
return;
}


if ( position<(prefix.length-1) ) {
getWordList(prefix, ++position, child, results);
}else {
if (!child.word) {
traverse( child, results, prefix);
}
}

}


private function insertWord(word:String,
position:uint,
root:TrieNode):void {
var letter:String=word.substr(position,1);
if (position==word.length || !letter) {
return;
}


var child:TrieNode=root.children[letter];
if (! child) {
child=createNode(letter);
root.children[letter]=child;
}


if (position==word.length-1) {
child.word=true;
} else {
insertWord(word, ++position, child);
}
}


private function createNode(letter:String):TrieNode {
return new TrieNode(letter,false);
}
}

Format date and time in non-Gregorian calendars

This article was originally written in English. Text in other languages was provided by machine translation.

Although the Gregorian calendar is the most used civil calendar, there are other calendars used in different countries and regions.

Islamic calendar is used in many Islamic countries and it has quite a few variances. Japan uses the imperial calendar which identify the year with an era name(年号, nengō) and a number. Thailand uses a calendar that counts in the Buddhist era.

With flash.globalization package, you can easier format a date in non-Gregorian calendars. See the code below.