Using M3 language constants in JScript

Using M3 language constants in JScript is a requirement that has been received from several sources recently. In Mashups it has been possible to use M3 constants and messages for some time using the markup extension MForms.Mashup.ConstantExtension. JScript developers however have been out of luck and have had to use other means of translating texts in scripts that targets more than one language.

In Smart Office 10.0.4.1 we have added support for using M3 constants in JScript in two different ways. The first option is a class called PropertyTranslator with functionality that is similar to the Mashup markup extension. The PropertyTranslator is simple to use and it can translate single constants for use on buttons, labels or other controls. The second option is to use the TranslationService class directly. The TranslationService is used by both the ConstantExtension and the PropertyTranslator to translate batches of constants and messages. The TranslationService is a bit more complicated to use but you get more control if you need to translate many constants or if you need a notification when the translation is complete.

Translation requests and caching

Before we get into the interesting parts of how to use the new functionality I want to take some time to discuss how it works behind the scenes. The M3 constants are not actually on the client machine so they have to be downloaded using HTTP calls to a server. Since there are a lot of M3 constants it is not feasible to load them all, we only load the ones we actually use.

The TranslationService tries to batch as many constants as possible in a single request. In many cases there will just be a single request even if you use many constants in a script. The fact that the TranslationService makes server calls means that it cannot do this on the UI thread and therefore the translations are asynchronous. This means that there will be a slight delay before the translation is complete and the translated texts are available.

The TranslationService will cache all previously translated texts so subsequent requests for the same constants will be more or less instant.

PropertyTranslator

Using the PropertyTranslator is pretty straightforward. There is a static method called Translate with three mandatory parameters and one optional. The mandatory parameters are a dependency object such as a Button control, a dependency property such as ContentControl.ContentProperty for a button and the key for the constant or message. The last parameter is the language file and this is optional for constants in the MVXCON file. For all other files you must specify the name of the file such as MVXMSG.

One thing to be aware of is the translation delay the first time the script is executed during a session. Buttons and labels will be blank until the translation request is complete. Sometime the request is so fast that the user will barely notice it; other times there might be a longer delay and the user interface might look strange with missing texts. You need to decide how to handle this if at all. Perhaps you set some default texts to begin with. Another option is to not add controls until the translation is complete but then you would have to use the TranslationService described below.

The only thing that might be tricky when using the PropertyTranslator is what the dependency property parameter should be. Each dependency property is actually defined using two properties. One property is an instance property that you mostly use in code and the other is a static property that defines the dependency property. The static one should be used for the second parameter. What makes it tricky is that sometimes the static property is defined on a base class and not on the control itself.

For a Button control the Content property is defined on the ContentControl base class so in this case you should use ContentControl.ContentProperty. The same goes for other ContentControls such as Label. When using TextBlock controls the property is defined directly on the control so you use TextBlock.TextProperty. If it is unclear where the dependency property is defined check the MSDN documentation found here: .NET Framework Class Library

The method is defined like this:

/// <summary>
/// Translates a M3 BE constant or message and sets the translated text to a dependency object of
/// the specified target dependecy object.
/// </summary>
/// <param name="target">The target object.</param>
/// <param name="property">The dependency object of the target that will be updated with the translated text.</param>
/// <param name="key">The key for a language constant or message.</param>
/// <param name="file">Optional name of the language file. Only required if the file is not the default file MVXCON.</param>
public static void Translate(DependencyObject target, DependencyProperty property, string key, string file = null)

The following shows how to use the PropertyTranslator class. The example script first clears the entire panel and then adds a couple of controls with translated properties.

import System;
import System.Windows;
import System.Windows.Controls;
import MForms;

package MForms.JScript {
   class PropertyTranslatorTest {
      public function Init(element : Object, args : Object, controller : Object, debug : Object) {
         var content : Object = controller.RenderEngine.Content;
         content.Children.Clear();

         var stackPanel = new StackPanel();

         var label = new Label();
         PropertyTranslator.Translate(label, ContentControl.ContentProperty, "XDX0012");
         stackPanel.Children.Add(label);

         var textBlock = new TextBlock();
         PropertyTranslator.Translate(textBlock, TextBlock.TextProperty, "WCOE102", "MVXMSG");
         stackPanel.Children.Add(textBlock);

         var button = new Button();
         button.Width = 140;
         button.Margin = new Thickness(0, 8, 0, 0);
         PropertyTranslator.Translate(button, ContentControl.ContentProperty, "OI05612", "MVXCON");
         stackPanel.Children.Add(button);

         stackPanel.Orientation = Orientation.Vertical;
         stackPanel.VerticalAlignment = VerticalAlignment.Center;
         stackPanel.HorizontalAlignment = HorizontalAlignment.Center;
         SetPosition(stackPanel, 0, 0, Configuration.GridColumns, Configuration.GridRows);
         content.Children.Add(stackPanel);
      }

      private function SetPosition(element, left, top, width, height) {
         Grid.SetColumn(element, left);
         Grid.SetRow(element, top);
         Grid.SetColumnSpan(element, width);
         Grid.SetRowSpan(element, height);
      }
   }
}

TranslationService

First of all the TranslationService should only be used directly if you really need to. There are a couple of scenarios where this might be required. One example is that a lot of constants must be translated that are used in different parts of the script. Another example is loading messages that should be displayed to the end user or other cases where the texts are not used on a control on the panel. A third example is when you need to know exactly when the translation is complete.

The TranslationService has a Translate method that accepts a list of TranslationItem objects and a callback function that will be called when the translation is complete. The result is an enumeration of TranslationItem objects where the Key property contains the constant key and the Text property contains the translated text.

The following example translates two constants and one message and output the result in the Script Tool output pane.

import System;
import System.Windows;
import System.Windows.Controls;
import System.Collections;
import MForms;

package MForms.JScript {
   class TranslationBatchTest {
      var debug;
      public function Init(element : Object, args : Object, controller : Object, debug : Object) {
         this.debug = debug;

         var items = new ArrayList();
         items.Add(new TranslationItem("XDX0012"));
         items.Add(new TranslationItem("OI05612", "MVXCON"));
         items.Add(new TranslationItem("WCOE102", "MVXMSG"));

         TranslationService.Current.Translate(items, OnTranslate);
      }

      private function OnTranslate(items : IEnumerable) {
         for (var item in items) {
            debug.Debug(item.Key + " = " + item.Text);
         }
      }
   }
}

6 thoughts on “Using M3 language constants in JScript

  1. Gaston

    Norpe,

    I am not able to compile any of the two scripts for PropertyTransalator or TranslationService, the message indicates: error JS1135: Variable “PropertyTransalator has not been declare”. I am using LSO V 10.0.2..07, could this be causing this issue? what other way is available for translating CONGB variables? I will even consider overriding a constant with a value.

    Thank you,
    Gaston

    Reply
    1. norpe Post author

      This functionality was added in Smart Office version 10.0.4.1 so the script will not work in earlier versions of Smart Office. There is no other supported way to get translated BE constants in JScript in earlier versions.

      Reply
  2. Pingback: Rich HTML output from MEC | M3 ideas

  3. bm

    Hello,

    Is it possible to use Translationservice in order to translate a message with parameters ?
    Example following message id : XIN0101 in MVXMSG (Incorrect range for value &1 and &2)

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s