Google Cloud Translation sobre gRPC en Delphi

· Componentes

Google Cloud Translation v3 traduce texto entre más de cien idiomas y puede detectar el idioma de un fragmento de texto por ti. El servicio se expone sobre gRPC, y sgcWebSockets Enterprise incluye un cliente gRPC de Translation tipado construido sobre TsgcGRPCClient. En lugar de ensamblar Protocol Buffers a mano, rellenas un objeto de petición, llamas a un método, y lees el texto traducido directamente de una respuesta tipada. Este artículo recorre cómo funciona y muestra el código Delphi real de la demo incluida.

Cómo funciona

gRPC son Protocol Buffers enmarcados sobre HTTP/2, así que el cliente de Translation se apoya sobre la pila HTTP/2 de sgcWebSockets. Creas un TsgcHTTP2Client apuntando a translate.googleapis.com en el puerto 443 con TLS, lo asignas a un TsgcGRPCClient, y el componente gRPC hace el enmarcado de mensajes, las cabeceras y la gestión de streams por ti.

La unidad de Translation sgcGRPC_Google_Translation añade las clases de mensaje tipadas que reflejan la API v3: TsgcGRPCTranslationTranslateTextRequest y ...TranslateTextResponse para la traducción, el par DetectLanguage para la detección de idioma, y el par GetSupportedLanguages para listar idiomas. Cada petición expone un método ToBytes que la serializa a protobuf, y cada respuesta expone un método LoadFromBytes que analiza la respuesta. Pasas esos bytes al método Call del cliente gRPC y lees el resultado de vuelta.

Autenticación

Cloud Translation requiere un token de cuenta de servicio de Google. La demo se autentica con una clave JSON de cuenta de servicio (email de cliente, id de clave privada, clave privada e id de proyecto) y obtiene un Bearer token, que luego se añade como metadata gRPC para que viaje en cada llamada.

GetGRPCClient.DefaultMetadata.Clear;
GetGRPCClient.DefaultMetadata.Add('authorization', 'Bearer ' + FToken);

Un detalle que conviene señalar: un JWT de cuenta de servicio autofirmado está vinculado a la audiencia, así que el token tiene que apuntar al endpoint de Translation para ser aceptado por translate.googleapis.com. La demo establece JWT.API_Endpoint a https://translate.googleapis.com/ antes de solicitar el token.

Configurar el cliente

El transporte HTTP/2 y el cliente gRPC se conectan una sola vez. El servicio de Translation espera protobuf en el cable, así que el content type del canal es grpcProto.

uses
  sgcHTTP2_Client, sgcGRPC_Types, sgcGRPC_Client,
  sgcGRPC_Google_Translation;

FHTTP2Client := TsgcHTTP2Client.Create(nil);
FHTTP2Client.Host := 'translate.googleapis.com';
FHTTP2Client.Port := 443;
FHTTP2Client.TLS  := True;

FGRPCClient := TsgcGRPCClient.Create(nil);
FGRPCClient.Client := FHTTP2Client;
FGRPCClient.ChannelOptions.ContentType  := grpcProto;
FGRPCClient.ChannelOptions.Compression  := grpcNoCompression;

Traducir texto

Para traducir, rellena un TsgcGRPCTranslationTranslateTextRequest: establece la ruta de recurso Parent, añade uno o más strings a Contents, establece los códigos de idioma de origen y destino y el tipo MIME. Serialízalo con ToBytes y pásalo a Call con el nombre completo del servicio y el método. La ruta parent sigue la forma v3 projects/<project-id>/locations/global.

var
  oRequest: TsgcGRPCTranslationTranslateTextRequest;
  oResponse: TsgcGRPCResponse;
begin
  oRequest := TsgcGRPCTranslationTranslateTextRequest.Create;
  try
    oRequest.Parent := 'projects/' + txtProjectId.Text + '/locations/global';
    oRequest.Contents.Add(txtSourceText.Text);
    oRequest.SourceLanguageCode := txtSourceLang.Text;   // e.g. 'en'
    oRequest.TargetLanguageCode := txtTargetLang.Text;   // e.g. 'es'
    oRequest.MimeType := 'text/plain';

    oResponse := GetGRPCClient.Call
      ('google.cloud.translation.v3.TranslationService', 'TranslateText',
      oRequest.ToBytes);
  finally
    oRequest.Free;
  end;
end;

La respuesta vuelve como un TsgcGRPCResponse. Cuando StatusCode es grpcOK, carga los bytes Data en bruto en una respuesta tipada y lee cada traducción. Cada Translation lleva el TranslatedText y, cuando el idioma de origen se autodetectó, el DetectedLanguageCode.

var
  oResponse: TsgcGRPCTranslationTranslateTextResponse;
  i: Integer;
begin
  oResponse := TsgcGRPCTranslationTranslateTextResponse.Create;
  try
    oResponse.LoadFromBytes(aData);
    for i := 0 to oResponse.TranslationCount - 1 do
    begin
      DoLog('Translated: ' + oResponse.Translation(i).TranslatedText);
      if oResponse.Translation(i).DetectedLanguageCode <> '' then
        DoLog('Detected: ' + oResponse.Translation(i).DetectedLanguageCode);
    end;
  finally
    oResponse.Free;
  end;
end;

Detectar el idioma

Cuando no conoces el idioma de origen, deja la traducción a un lado y llama a DetectLanguage. Construye un TsgcGRPCTranslationDetectLanguageRequest con la ruta parent y el Content a inspeccionar, luego lee de vuelta los idiomas candidatos, cada uno con un LanguageCode y un valor de Confidence.

oRequest := TsgcGRPCTranslationDetectLanguageRequest.Create;
try
  oRequest.Parent := GetParentPath;
  oRequest.Content := txtSourceText.Text;
  oRequest.MimeType := 'text/plain';

  oResponse := GetGRPCClient.Call
    ('google.cloud.translation.v3.TranslationService', 'DetectLanguage',
    oRequest.ToBytes);
finally
  oRequest.Free;
end;

Analizar la respuesta de detección te da el código de idioma y una puntuación de confianza para cada candidato.

oResponse := TsgcGRPCTranslationDetectLanguageResponse.Create;
try
  oResponse.LoadFromBytes(aData);
  for i := 0 to oResponse.LanguageCount - 1 do
    DoLog('Language: ' + oResponse.Language(i).LanguageCode +
      ' (confidence: ' + FloatToStr(oResponse.Language(i).Confidence) + ')');
finally
  oResponse.Free;
end;

Listar los idiomas soportados

La tercera operación, GetSupportedLanguages, devuelve todos los idiomas que el servicio soporta. Establece DisplayLanguageCode al idioma en el que quieres los nombres a mostrar, y cada entrada vuelve con un LanguageCode y un DisplayName legible, junto con indicadores de si puede usarse como origen o destino.

oRequest := TsgcGRPCTranslationGetSupportedLanguagesRequest.Create;
try
  oRequest.Parent := GetParentPath;
  oRequest.DisplayLanguageCode := 'en';

  oResponse := GetGRPCClient.Call
    ('google.cloud.translation.v3.TranslationService',
    'GetSupportedLanguages', oRequest.ToBytes);
finally
  oRequest.Free;
end;

Disponibilidad

El cliente gRPC de Translation forma parte de la edición Enterprise de sgcWebSockets y se ejecuta en Windows, macOS, Linux, iOS y Android, en Delphi y C++Builder. Un ejemplo completo y listo para ejecutar con la carga de la cuenta de servicio y las tres operaciones está en Demos\21.GRPC\12.Translation, y el cliente gRPC subyacente está documentado en la página de producto del Cliente gRPC.

¿Preguntas o comentarios? Ponte en contacto. Recibirás respuesta de las personas que escribieron el código.