Google Cloud Translation sobre gRPC no Delphi

· Componentes

O Google Cloud Translation v3 traduz texto entre mais de cem idiomas e pode detectar o idioma de um trecho de texto para você. O serviço é exposto sobre gRPC, e o sgcWebSockets Enterprise inclui um cliente Translation gRPC tipado construído sobre o TsgcGRPCClient. Em vez de montar Protocol Buffers à mão, você preenche um objeto de requisição, chama um método e lê o texto traduzido diretamente de uma resposta tipada. Este post percorre como funciona e mostra o código Delphi real da demo incluída.

Como funciona

O gRPC são Protocol Buffers encapsulados sobre HTTP/2, então o cliente Translation se apoia na pilha HTTP/2 do sgcWebSockets. Você cria um TsgcHTTP2Client apontado para translate.googleapis.com na porta 443 com TLS, atribui-o a um TsgcGRPCClient, e o componente gRPC faz o enquadramento de mensagens, os cabeçalhos e o tratamento de streams para você.

A unidade Translation sgcGRPC_Google_Translation adiciona as classes de mensagem tipadas que espelham a API v3: TsgcGRPCTranslationTranslateTextRequest e ...TranslateTextResponse para tradução, o par DetectLanguage para detecção de idioma e o par GetSupportedLanguages para listar idiomas. Cada requisição expõe um método ToBytes que a serializa para protobuf, e cada resposta expõe um método LoadFromBytes que analisa a resposta. Você passa esses bytes para o método Call do cliente gRPC e lê o resultado de volta.

Autenticação

O Cloud Translation requer um token de conta de serviço do Google. A demo se autentica com uma chave JSON de conta de serviço (client email, private key id, private key e project id) e obtém um token Bearer, que é então adicionado como metadado gRPC para que acompanhe cada chamada.

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

Um detalhe que vale notar: um JWT autoassinado de conta de serviço é vinculado à audiência, então o token precisa ter como alvo o endpoint do Translation para ser aceito por translate.googleapis.com. A demo define JWT.API_Endpoint como https://translate.googleapis.com/ antes de solicitar o token.

Configurando o cliente

O transporte HTTP/2 e o cliente gRPC são conectados uma única vez. O serviço Translation espera protobuf no protocolo, então o tipo de conteúdo do canal é 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;

Traduzindo texto

Para traduzir, preencha um TsgcGRPCTranslationTranslateTextRequest: defina o caminho do recurso Parent, adicione uma ou mais strings a Contents, defina os códigos de idioma de origem e destino e o tipo MIME. Serialize-o com ToBytes e passe-o para Call com o nome totalmente qualificado do serviço e do método. O caminho parent segue a 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;

A resposta volta como um TsgcGRPCResponse. Quando StatusCode é grpcOK, carregue os bytes brutos de Data em uma resposta tipada e leia cada tradução. Cada Translation carrega o TranslatedText e, quando o idioma de origem foi autodetectado, o 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;

Detectando o idioma

Quando você não conhece o idioma de origem, deixe a tradução de lado e chame DetectLanguage. Monte um TsgcGRPCTranslationDetectLanguageRequest com o caminho parent e o Content a inspecionar, então leia os idiomas candidatos de volta, cada um com um LanguageCode e um 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;

Analisar a resposta de detecção fornece o código de idioma e uma pontuação de confiança 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;

Listando os idiomas suportados

A terceira operação, GetSupportedLanguages, retorna todos os idiomas que o serviço suporta. Defina DisplayLanguageCode com o idioma em que você quer os nomes de exibição, e cada entrada volta com um LanguageCode e um DisplayName legível, junto com flags indicando se ele pode ser usado como origem ou 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;

Disponibilidade

O cliente Translation gRPC faz parte da edição Enterprise do sgcWebSockets e roda em Windows, macOS, Linux, iOS e Android, em Delphi e C++Builder. Um exemplo completo e pronto para executar, com carregamento de conta de serviço e as três operações, está em Demos\21.GRPC\12.Translation, e o cliente gRPC subjacente está documentado na página do produto gRPC Client.

Dúvidas ou comentários? Entre em contato. Você receberá uma resposta das pessoas que escreveram o código.