lunes, 21 de febrero de 2011

Traducción de Idiomas y Síntesis de Voz con Google API y Microsoft translator en Windows Phone 7

Es util hoy en día contar con herramientas para la traducción de idiomas, las cuales cada vez ofrecen mejores servicios, ejemplos claros son google translate y Microsoft Translator.


La siguiente clase utiliza los servicios de google translator API usando http, desde una app Windows Phone 7, pero puede ser utilizado en otros contextos, mediante una ligera modificación.







Traducción de idiomas con Google API


1. Definamos primero una interface para establecer un contrato de lo que un traductor básico debe hacer, sea google u otro



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace F.Phone.Translator
{

public class TranslatorEventArgs: System.EventArgs

    {
        public string TranslationResult { get; set; }
    }


    public interface ITranslator
    {
        string TranslationError { get; set; }
        string TranslationResult { get; set; }
        event EventHandler<F.Phone.Translator.TranslatorEventArgs> TextTranslated;
        void Translate(string expression, string originalLanguage, string targetLanguage);
    }
}

2. Implementamos una clase para utilizar la API de google para llevar acabo esta tarea, en este caso la clase consume un servicio de la API de google mediante HTTP de forma asíncrona (por ser para un dispositivo móvil y al terminar dispara un evento para que sea manejado en la aplicación).

Nota. para usar la google API es necesario registrarse como developer y registrar una app y generar una llave. http://code.google.com/intl/es-ES/apis/loader/signup.html

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace F.Phone.Translator.Google
{
    /// <summary>
    /// This class is a proxy to use GoogleAPI for translation purposes
    /// </summary>
    public class GoogleTranslator: ITranslator
    {

        #region Properties
        public const string TranslatorURI = "https://www.googleapis.com/language/translate/v2?key={0}&q={1}&source={2}&target={3}&callback=handleResponse";
        public const string KeyId = "COLOCA-TU-GOOGLE-API-KEY-AQUI";
        WebClient _proxy;
        /// <summary>
        /// Web Client to use google API through HTTP Protocol
        /// </summary>
        public WebClient Proxy {
            get {
                if (_proxy == null)
                    _proxy = new WebClient();
                return _proxy;
            }
        }
        /// <summary>
        ///
        /// </summary>       
        public string TranslationError {get;set;}
        /// <summary>
        ///
        /// </summary>
        public string TranslationResult {get;set;}
        public event EventHandler<F.Phone.Translator.TranslatorEventArgs> TextTranslated;

        #endregion
      
        #region Methods
        /// <summary>
        ///
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="originalLanguage"></param>
        /// <param name="targetLanguage"></param>
        public void  Translate(string expression, string originalLanguage, string targetLanguage) {
           TranslationResult = expression ;
           TranslationError = string.Empty ;

            try
            {

                Proxy.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Proxy_DownloadStringCompleted);  
                Proxy.DownloadStringAsync (new Uri (
                                                    String.Format (
                                                        TranslatorURI,
                                                        KeyId,
                                                        expression,
                                                        originalLanguage,
                                                        targetLanguage
                                                    )
                                            )
                    );
            }
            catch (Exception ex) {
                TranslationError = ex.Message;
            }


          
        }
        #endregion

        #region Event Handlers
        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Proxy_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            try
            {
                string text = System.Text.RegularExpressions.Regex.Match
                    (e.Result,
                     "\"translatedText\"\\s*:\\s*\"(?<expre>[\\w,\\W,\\s]+)\"\\s*}").Groups["expre"].Value;

                TranslationResult = text;

                if (TextTranslated != null) {
                    TextTranslated(sender, new TranslatorEventArgs() {  TranslationResult = text });
                }
            }
            catch (Exception ex) {
                TranslationError = ex.Message;
            }
        }
        #endregion

    }
}



Síntesis de Voz con Microsoft Translator (bing)

De igual manera como se hizo en la clase para la traducción en este caso se hace una clase para reproducir o sintetizar voz a partir de un texto, esta síntesis puede ser en varios idiomas, para lo cual es necesario mandar el identificador estándar de la cultura, como parámetro.

Para esto utilizaremos Microsoft Translator (Bing




using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;

namespace F.Phone.Translator.Microsoft
{
    public class MSSpeech
    {
        public const string SpeakURI = "http://api.microsofttranslator.com/V2/Http.svc/Speak?appId={0}&text={1}&language={2}";
        public const string AppID = "TU_LLAVE_DE_APP_BING";
        public const string DefaultLanguage = "en";

        WebClient _proxy;
        public WebClient Proxy
        {
            get
            {
                if (_proxy == null)
                    _proxy = new WebClient();
                return _proxy;
            }
        }

        public event EventHandler<OpenReadCompletedEventArgs > OnSpeech;
        /// <summary>
        ///
        /// </summary>
        public MSSpeech() {
            Proxy.OpenReadCompleted += new OpenReadCompletedEventHandler(Proxy_OpenReadCompleted);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Proxy_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            try
            {
                SoundEffect sound = SoundEffect.FromStream(e.Result);
                sound.Play();
                if (OnSpeech != null)
                {
                    OnSpeech(sender, e);
                }
            }
            catch (Exception ex) {
                MessageBox.Show(ex.Message);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="phrase"></param>
        /// <param name="language"></param>
        /// <param name="appID"></param>
        public void Speak(string phrase, string language, string appID) {
            try
            {
                string uri = string.Format(SpeakURI, appID, phrase, language);
                Proxy.OpenReadAsync(new Uri(uri));
            }
            catch (Exception ex) {
                MessageBox.Show(ex.Message);
            }
        }
    }
}




Despachador de servicios XNA

Cabe señalar que para efectos de reproducción del stream que es un WAV file se recurre al uso de XNA en el Windows Phone 7 que utiliza el esquema de brokers o despachadores de servicios para accionar hardware, en el cual se require implementar un despachador de servicios así como su respectiva configuración en el XAML de la aplicación que utilice la reproducción o síntesis de voz.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;

namespace F.Phone.Translator.Microsoft
{
    public class XNAFrameworkDispatcherService : IApplicationService
    {
        private DispatcherTimer frameworkDispatcherTimer;

        public XNAFrameworkDispatcherService()
        {
            this.frameworkDispatcherTimer = new DispatcherTimer();
            this.frameworkDispatcherTimer.Interval = TimeSpan.FromTicks(333333);
            this.frameworkDispatcherTimer.Tick += frameworkDispatcherTimer_Tick;
            FrameworkDispatcher.Update();
        }

        void frameworkDispatcherTimer_Tick(object sender, EventArgs e) { FrameworkDispatcher.Update(); }

        void IApplicationService.StopService() { this.frameworkDispatcherTimer.Stop(); }

        void IApplicationService.StartService(ApplicationServiceContext context) { this.frameworkDispatcherTimer.Start(); }

    }
}


XMAL

Los despachadores de servicios requieren de una instancia del despachador que se encuentra dentro de la sección de los objetos que viven durante el tiempo de vida de la ejecución de la aplicación.

<Application
    x:Class="LanguageTranslator.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"      
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:s="clr-namespace:F.Phone.Translator.Microsoft;assembly=F.Phone.Translator"
    >
   
    <!--Recursos de la aplicación-->
    <Application.Resources>
    </Application.Resources>

    <Application.ApplicationLifetimeObjects>
        <!--Objeto requerido que controla los eventos de duración de la aplicación-->
        <shell:PhoneApplicationService
            Launching="Application_Launching" Closing="Application_Closing"
            Activated="Application_Activated" Deactivated="Application_Deactivated"/>
        <s:XNAFrameworkDispatcherService/>
    </Application.ApplicationLifetimeObjects>

</Application>



Transacciones Fiori

  /UI2/CACHE Register service for UI2 cache use /UI2/CACHE_DEL Delete cache entries /UI2/CHIP Chip Registration /UI2/CUST Customizing of UI ...