Hosting Multi-Language IM Conversations in Lync 2010: Project Details (Part 2 of 3)

Summary:   This is the second in a series of three articles that describe how to build a Microsoft Lync 2010 Conversation Window Extension application that translates IM text between two languages. The ConversationTranslator application described in this article uses the Microsoft Translation web service.

Applies to:   Microsoft Lync 2010 SDK | Microsoft Lync 2010 | Microsoft Lync Server 2010

Published:   June 2011 | Provided by:   John Austin, Microsoft | About the Author


Part 1 introduced a Microsoft Lync 2010 application called ConversationTranslator and described two scenarios where ConversationTranslator is used.

Part 2 discusses the ConversationTranslator Visual Studio project, which includes project organization, Microsoft Lync 2010 API usage, and the Microsoft Translator web service logic.

The ConversationTranslator project is organized according to the Silverlight Model – View –ViewModel (MVVM) pattern with the addition of a category of classes that handle service interaction.

ConversationTranslator folder



Contains classes that encapsulate the data objects that are obtained from the Microsoft Translation web service (Language.cs) and Lync (MessageContext.cs). Each Translator-supported language is encapsulated by an instance of the Language class. Each individual IM that is sent or received is encapsulated by a MessageContext class instance.


Contains two classes. TranslationServices.cs encapsulates all of the capabilities of the Microsoft Translation service. ConversationService.cs encapsulates the IM conversation capabilities of the Lync 2010 API.


The MainViewModel.cs exposes observable collections of supported languages and conversation dialog. These public collection properties are bound to controls on the main view. The MessageLine.cs wraps the actual message text of an IM with sender, sent time, and background color properties. Each IM sent or received is encapsulated in a MessageLine class instance and is bound to a scrollable control on the main view. The languages collection is bound to two boxes on the view that give a user the option to select a preferred language to translate to and from.

Figure 1 shows an expanded view of the ConversationTranslator project. Two Lync 2010 API namespaces are added to the References folder and a reference to the Microsoft Translation service (BingTranslation) is added to the Service References folder.

The application view is defined by MainPage.xaml and MainPage.xaml.cs. Commanding is not used. Instead, the XAML control declarations define Click events and reference event handlers defined in MainPage.xaml.cs. The XAML also defines the bindings between the ComboBox and ScrollViewer controls and their associated observable collections from the view model classes.

Figure 1. Visual Studio Solution Explorer view of ConversationTranslator

Solution Explorer view of Conversation Translator.

Figure 2 shows the relationship between the elements of the ConversationTranslator project. The Microsoft Translator service and the Lync 2010 API platform provide the language list, translation services, and conversation events. The data obtained from the service level is wrapped by the classes of the model level. The view level interacts with the service level by handling events raised by service components and calling methods exposed by service component classes. The ViewModel classes provide observable lists of languages and conversation messages which are bound to controls in the main view.

Figure 2. ConversationTranslator MVVM project

Conversation Translator as MVVM project.

ConversationTranslator is started after a user has accepted an invitation to an IM conversation and the conversation window is open. The Lync 2010 conversation window More Options menu includes a ConversationTranslator extension option if ConversationTranslator is installed on the computer. If a user selects the ConversationTranslator option, the MainPage class instance performs the following tasks on startup.

  1. Initializes an IsolatedStorageSettings instance to the type IsolatedStorageSettings.ApplicationSettings. This isolation storage may hold a user’s previous language choices.

  2. Instantiates an instance of ObservableCollection<Language> and ObservableCollection<MessageLine>.

  3. Gets the active Microsoft.Lync.Model.Conversation.Conversation instance representing the IM conversation hosted by the parent Lync 2010 conversation window by calling LyncClientGetHostingConversation().

  4. Constructs an instance of the service helper classes, ConversationService and TranslationService.

  5. Registers for events on ConversationService and TranslationService as in the following example.

      conversationService.MessageError += new MessageError(conversationService_MessageError);
      conversationService.MessageReceived += new MessageReceived(conversationService_MessageReceived);
      conversationService.MessageSent += new MessageSent(conversationService_MessageSent);
      translationService.LanguagesReceived += new LanguagesReceived(translationService_LanguagesReceived);
      translationService.TranslationError += new TranslationError(translationService_TranslationError);
      translationService.TranslationReceived += new TranslationReceived(translationService_TranslationReceived);
  6. Calls ConversationService.Start() to register for Conversation.ParticipantAdded event and the InstantMessageModality.InstantMessageReceived event on each participant in the conversation.

  7. Gets the languages supported by Microsoft Translator by calling TranslationService.Start().

ConversationTranslator performs two important tasks. To fill the language Boxes on the main page, ConversationTranslator must query BingTranslation for the translation languages that it supports. The user selects one or more of these supported languages for incoming or outgoing message translation.

The second task that ConversationTranslator performs is to translate IM messages. The result of a translation depends on the language the user selected for incoming and outgoing messages. In the case of a conference, ConversationTranslator auto-detects the language of an incoming message and then translates the message into the user’s language.

Getting Supported Languages

ConversationTranslator uses the following procedure to obtain supported languages.

  1. MainPage calls the Start() method on TranslationService.

  2. TranslationService queries BingTranslation for supported translation languages. The query results are returned asynchronously as language codes.

  3. TranslationService queries BingTranslation for a set of language names that correspond to the language codes returned in the previous step.

  4. TranslationService creates an instance of the Language class for each code/name pair that represent Bing translation languages.

  5. TranslationService creates a IList<Language> object and passes it to MainPage as the argument of the LanguagesReceived event.

  6. MainPage.xaml binds the language list to the two ComboBox controls on the main page.

  7. MainPage reads the Languages property of the MainViewModel instance and adds the collection of languages that are returned in the LanguagesReceived event.

Figure 3 shows how the components in the ConversationTranslator interact to get the languages supported by the translation service and then display the languages in a set of Box controls in the main view.

Figure 3. The sequence of method calls to get a Bing Translator language set

Sequence of method calls to get Bing Languages

Translating Messages

Your application should always translate received IM text to the language of the local user. IM text to be sent should only be translated to another participant’s language if that participant’s IM client cannot translate IM text.

Translating IM Text Before IM is Sent

The next procedure shows how ConversationTranslator translates IM text before the IM is sent.

Note Note

The local user sends IM text to the other conversation participant. The other participant is not using ConversationTranslator and must receive IM text that is previously translated.

To translate IM text before IM is sent

  1. MainPage creates a new instance of MessageContext and then updates the OriginalMessage property with the IM text that will be translated.

  2. MainPage gets the name of the message sender by reading the Participant.Contact property of the local participant, calling the Contact.GetContactInformation method, and then passing the DisplayName enumerator.

  3. MainPage sets the source and target language properties of the new message context to the language combo box selections made by the user.

  4. MainPage calls TranslationService.Translate, passing the MessageContext instance as an argument to the method.

  5. TranslationService calls LanguageService.TranslationService.BeginTranslate on the Bing translation service, passing the original message text and desired translation language.

  6. With the translation response from LanguageService.TranslationService, TranslationService sets the MessageContext.TranslatedMessage property and raises the TranslationReceived event to MainPage.

  7. MainPage changes the Translate button text to “Send” and changes the IM text entry box text value to the translated message text.

  8. User clicks the Send button.

  9. MainPage calls ConversationService.SendMessage, passing the updated MessageContext as an argument.

  10. ConversationService calls InstantMessageModalityBeginSendMessage(string, AsyncCallback, object).

  11. In the BeginSendMessage callback method, ConversationService raises the MessageSent event to MainPage.

  12. MainPage creates a new instance of MessageLine and adds it to the ViewModel.MessageHistory collection. The conversation history list box is scrolled to the new entry.

Figure 4 shows how ConversationTranslator sends translated IM text to another conversation participant.

Figure 4. Translate and send IM text

Translate and send IM text.

Translating Received IM Text

The next procedure shows how ConversationTranslator translates an incoming IM message.

To translate received IM text

  1. A second user sends an IM to the local user.

  2. Lync 2010 raises the InstantMessageModality.InstantMessageReceived event that is handled by ConversationService.

  3. ConversationService gets the name of the message sender by reading the Participant.Contact property of the sender, calling the Contact.GetContactInformation method, and then passing the DisplayName enumerator.

  4. ConversationService raises the MessageReceived(string message, string participantName) event to MainPage.

  5. MainPage creates a new instance of MessageContext, sets message time, participant name, original message text, target translation language, and message direction properties on the new MessageContext instance.

  6. MainPage calls the Translate(MessageContext) method on TranslationService.

  7. TranslationService asks BingTranslation to detect the original language of the message and then asks BingTranslation to translate the IM from that language to the language of the local user.

  8. When the translation operation is complete, TranslationService sets the TranslatedMessage property of the MessageContext with the value of the translated message string.

  9. When the translation is received from BingTranslation, TranslationService raises the TranslationReceived(MessageContext) event for the MainPage.xaml.cs listener.

  10. MainPage creates a new instance of MessageLine, passing the message sender name, time, and translated message in the constructor.

  11. MainPage reads the MessageHistory property of MainViewModel and adds the new message line to the collection of previous MessageLine instances.

  12. The new message is displayed in a list called listBoxHistory, inside a scrollable view that MainPage.xaml has previously bound to the message history.

Figure 5 shows how the components in the ConversationTranslator interact to accept an incoming IM, detect the language of the message text, translate the text to the local participant’s language, and then display the message in the main view.

Figure 5. Translate text of a received IM

Translate text of a received IM.

ConversationTranslator uses the four methods, two properties, and two events that appear in the following tables to enable interaction with the Lync conversation model. Except otherwise noted, these API types are used in the ConversationService class.




Gets the Conversation instance that represents the IM conversation hosted by the Lync 2010 conversation window. The MainPage.xaml.UserControl_Loaded method calls GetHostingConversation.

Note Note
GetHostingConversation is available only in %ProgramFiles%\Microsoft Lync\SDK\Assemblies\Silverlight\Microsoft.Lync.Model.dll.


Called to get the display name of a conversation participant who sent a message.


Called to send a plain text IM. The method is called asynchronously.

Tip Tip
InstantMessageModality.EndSendMessage should be called to complete the IM send operation and obtain the results of the operation. The call is optional.


Sends one typing notification to all conversation participants with each keystroke typed in the message input text box.




Gets the IM modality from the local and remote participants in the conversation.


Read to avoid subscribing to IM events on the local participant.




Handles the event that is raised when a participant is added to the conversation. The event handler subscribes to IM events on the added participant if the participant is not the local participant.


Handles the event that is raised when a new IM is received by the conversation. This event is raised if the IM originated with the local participants or any of the remote participants.

Hosting Multi-Language IM Conversations in Lync 2010: Code Listing (Part 3 of 3) discusses how to use the ConversationTranslator application to obtain languages and translate messages.

John Austin, Microsoft, is a programmer/writer in the Lync client SDK documentation team. He has been writing Microsoft technical documentation for four years. Prior to working for Microsoft, John spent two decades as a software developer.