This is a test message to test the length of the message box.
Login
BTP Google Translate API
Erstellt von Software-Heroes

BTP - Google Translate Integration

170

Wie rufst du aus dem ABAP Environment eine externe API, wie Google Translate, auf und konsumierst diese in einer lokalen Klasse? Mehr dazu in diesem Artikel.

Werbung


Bereits in einem älteren Artikel haben wir uns die Provisionierung der Google Translate API angeschaut und wie du sie aufrufen kannst.

 

Einleitung

Die BTP stellt zahlreiche Services und Dienste zur Verfügung, doch wie sieht es mit der Integration von anderen Diensten aus? Die Einbindung von REST-basierten Diensten kann relativ leicht über die neuen HTTP Klassen im System erfolgen. Die Translate API benötigt dazu nur einen Aufruf und sendet uns die übersetzten Token zurück.

 

Implementierung

In diesem Abschnitt wollen wir den API Aufruf implementieren und erklären dir alles Schritt für Schritt.

 

URL

Im ersten Schritt benötigen wir die URL der API mit dem API Key, damit wir den Service ohne Authentifizierung verwenden können. Dazu legen wir uns Global zwei Konstanten an.

CONSTANTS c_api_endpoint TYPE string VALUE 'https://translation.googleapis.com/language/translate/v2'.
CONSTANTS c_api_key      TYPE string VALUE ''.

 

Per String-Template bauen wir uns dann die finale URL zusammen, nach dem Endpunkt kommt der Parameter mit dem API Schlüssel.

rd_url = |{ c_api_endpoint }?key={ c_api_key }|.

 

Payload

Im nächsten Schritt generieren wir die Payload, hierbei handelt es sich um die Anfrage an Google Translate. Dazu definieren wir einen Typen für die Struktur. Den Aufbau der Anfrage kannst du aus der API Dokumentation entnehmen.

TYPES: BEGIN OF ts_google_request,
         q      TYPE string_table,
         target TYPE string,
       END OF ts_google_request.

 

Dazu übergeben wir die zu übersetzenden Texte und die Zielsprache an die Struktur und erzeugen das JSON für die Anfrage. Wir rufen die SERIALIZE Methode auf und übergeben für die Felder ein Mapping, um die korrekten kleingeschriebenen Feldnamen zu erhalten.

DATA(ls_google_request) = VALUE ts_google_request( q      = it_text
                                                   target = id_target_language ).

rd_result = /ui2/cl_json=>serialize( data          = ls_google_request
                                     name_mappings = VALUE #( ( abap = 'Q' json = 'q' )
                                                              ( abap = 'TARGET' json = 'target' ) ) ).    

 

Die Payload sollte nun ungefähr so aussehen:

{
  "q": [
    "Test Artikel", 
    "Bitte diesen Text ins Englische übersetzen."
  ],
  "target": "en"
}

 

Anfrage

Nun wollen wir die Anfrage erzeugen, dazu müssen wir im ersten Schritt mit der URL eine Destination erzeugen und dann über den Client-Manager ein Client Objekt.

DATA(lo_destination) = cl_http_destination_provider=>create_by_url( ld_url ).
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).

 

Wir lassen uns vom Client eine Anfrage geben und konfigurieren diese, indem wir den ContentType setzen und die Payload mitgeben.

DATA(lo_request) = lo_client->get_http_request( ).
lo_request->set_content_type( 'application/json; charset=utf-8' ).
lo_request->set_text( ld_payload ).

 

Nun können wir die Anfrage ausführen. Der Endpunkt erwartet einen POST-Request, deshalb setzen wir beim Ausführen der EXECUTE Methode noch den POST.

DATA(lo_response) = lo_client->execute( i_method = if_web_http_client=>post ).

 

Antwort parsen

Nachdem wir die Anfrage ausgeführt haben, sollten wir eine Antwort erhalten haben. Diese ist im JSON Format und muss nun zurück nach ABAP geparst werden.

 

Dazu bauen wir uns eine Ergebnisstruktur auf, um das Ergebnis leicht parsen zu können.

TYPES: BEGIN OF ts_translation,
         translatedtext         TYPE string,
         detectedsourcelanguage TYPE string,
       END OF ts_translation.
TYPES tt_translation TYPE STANDARD TABLE OF ts_translation WITH EMPTY KEY.

TYPES: BEGIN OF ts_data,
         translations TYPE tt_translation,
       END OF ts_data.

TYPES: BEGIN OF ts_google_result,
         data TYPE ts_data,
       END OF ts_google_result.

 

Dazu definieren wir uns eine lokale Struktur mit dem Zieltypen. Im ersten Schritt prüfen wir, ob der Aufruf erfolgreich war und parsen dann das Ergebnis per DESERIALIZE.

DATA ls_google_result TYPE ts_google_result.

IF io_response->get_status( )-code = 200.
  /ui2/cl_json=>deserialize( EXPORTING json = io_response->get_text( )
                             CHANGING  data = ls_google_result ).
ENDIF.

 

Zum Abschluss verarbeiten wir die interne Tabelle der Struktur und übernehmen die Texte in unseren Returning Parameter. Gab es zuvor einen Fehler, ist die Tabelle leer und es wird nicht übernommen, damit benötigen wir keine weitere Fehlerbehandlung.

LOOP AT ls_google_result-data-translations INTO DATA(ls_translated).
  INSERT ls_translated-TranslatedText INTO TABLE rt_result.
ENDLOOP.

 

Übersetzen

Damit unsere Klasse nun einfach verwendet werden kann, implementieren wir zwei Methoden zum Übersetzen. Eine einfache Methode um einzelne Texte zu übersetzen (TRANSLATE_TEXT) und eine Methode um viele Texte auf einmal zu übersetzen (TRANSLATE_TEXTS).

METHODS translate_text
  IMPORTING id_text            TYPE string
            id_target_language TYPE string DEFAULT `en`
  RETURNING VALUE(rd_result)   TYPE string.

METHODS translate_texts
  IMPORTING it_text            TYPE string_table
            id_target_language TYPE string DEFAULT `en`
  RETURNING VALUE(rt_result)   TYPE string_table.

 

Die vollständige Implementierung der Methoden und des gesamten Beispiels findest du im Abschnitt unten.

 

Test

Um die API zu testen, schreiben wir entsprechende ABAP Unit Tests. Die Implementierung erfolgt als lokale Testklasse im Testklassen-Include unserer Klasse.

CLASS ltc_google_api DEFINITION FINAL
  FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.

  PRIVATE SECTION.
    METHODS translate_apple  FOR TESTING.
    METHODS translate_fruits FOR TESTING.
    METHODS dont_translate   FOR TESTING.
ENDCLASS.


CLASS ltc_google_api IMPLEMENTATION.
  METHOD translate_apple.
    DATA(lo_cut) = NEW zcl_bs_demo_google_integration( ).

    DATA(ld_result) = lo_cut->translate_text( `Apfel` ).

    cl_abap_unit_assert=>assert_equals( exp = `Apple`
                                        act = ld_result ).
  ENDMETHOD.


  METHOD translate_fruits.
    DATA(lo_cut) = NEW zcl_bs_demo_google_integration( ).

    DATA(lt_result) = lo_cut->translate_texts( VALUE #( ( `Apfel` ) ( `Birne` ) ) ).

    cl_abap_unit_assert=>assert_equals( exp = VALUE string_table( ( `Apple` ) ( `Pear` ) )
                                        act = lt_result ).
  ENDMETHOD.


  METHOD dont_translate.
    DATA(lo_cut) = NEW zcl_bs_demo_google_integration( ).

    DATA(ld_result) = lo_cut->translate_text( `Apple` ).

    cl_abap_unit_assert=>assert_equals( exp = `Apple`
                                        act = ld_result ).
  ENDMETHOD.
ENDCLASS.

 

Wir testen drei verschiedene Konstellationen, einmal die einfache Methode für einen Begriff, einmal übergeben wir mehrere Wörter und zum Abschluss übergeben wir einen bereits übersetzten Text. Im letzten Fall gehen wir davon aus, dass keine Änderung am Wort vorgenommen wird.

 

Vollständiges Beispiel

Hier findest du die vollständige Beispielklasse mit den beiden öffentlichen Methoden zum Übersetzen von Texten. Der Best Practices folgend, würden wir eigentlich noch ein globales Interface und eine Factory erzeugen, dies haben wir uns zur besseren Übersicht gespart.

CLASS zcl_bs_demo_google_integration DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    "! Translate a single text
    "! @parameter id_text            | Text to be translated
    "! @parameter id_target_language | Target language
    "! @parameter rd_result          | Translated text
    METHODS translate_text
      IMPORTING id_text            TYPE string
                id_target_language TYPE string DEFAULT `en`
      RETURNING VALUE(rd_result)   TYPE string.

    "! Translates a table of texts into the target language
    "! @parameter it_text            | Table of texts
    "! @parameter id_target_language | Target language
    "! @parameter rt_result          | Table of translated texts
    METHODS translate_texts
      IMPORTING it_text            TYPE string_table
                id_target_language TYPE string DEFAULT `en`
      RETURNING VALUE(rt_result)   TYPE string_table.

  PRIVATE SECTION.
    CONSTANTS c_api_endpoint TYPE string VALUE 'https://translation.googleapis.com/language/translate/v2'.
    CONSTANTS c_api_key      TYPE string VALUE ''.

    TYPES: BEGIN OF ts_google_request,
             q      TYPE string_table,
             target TYPE string,
           END OF ts_google_request.

    TYPES: BEGIN OF ts_translation,
             translatedtext         TYPE string,
             detectedsourcelanguage TYPE string,
           END OF ts_translation.
    TYPES tt_translation TYPE STANDARD TABLE OF ts_translation WITH EMPTY KEY.

    TYPES: BEGIN OF ts_data,
             translations TYPE tt_translation,
           END OF ts_data.

    TYPES: BEGIN OF ts_google_result,
             data TYPE ts_data,
           END OF ts_google_result.

    METHODS map_result
      IMPORTING io_response      TYPE REF TO if_web_http_response
      RETURNING VALUE(rt_result) TYPE string_table
      RAISING   cx_web_message_error.

    METHODS create_payload
      IMPORTING it_text            TYPE string_table
                id_target_language TYPE string
      RETURNING VALUE(rd_result)   TYPE string.

    METHODS create_url
      RETURNING VALUE(rd_url) TYPE string.
ENDCLASS.


CLASS zcl_bs_demo_google_integration IMPLEMENTATION.
  METHOD translate_text.
    DATA(lt_result) = translate_texts( it_text            = VALUE #( ( id_text ) )
                                       id_target_language = id_target_language ).

    IF line_exists( lt_result[ 1 ] ).
      rd_result = lt_result[ 1 ].
    ENDIF.
  ENDMETHOD.


  METHOD translate_texts.
    DATA(ld_url) = create_url( ).
    DATA(ld_payload) = create_payload( it_text            = it_text
                                       id_target_language = id_target_language ).

    TRY.
        DATA(lo_destination) = cl_http_destination_provider=>create_by_url( ld_url ).
        DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).

        DATA(lo_request) = lo_client->get_http_request( ).
        lo_request->set_content_type( 'application/json; charset=utf-8' ).
        lo_request->set_text( ld_payload ).
        DATA(lo_response) = lo_client->execute( i_method = if_web_http_client=>post ).

        rt_result = map_result( lo_response ).

      CATCH cx_root.
        CLEAR rt_result.
    ENDTRY.
  ENDMETHOD.


  METHOD create_url.
    rd_url = |{ c_api_endpoint }?key={ c_api_key }|.
  ENDMETHOD.


  METHOD create_payload.
    DATA(ls_google_request) = VALUE ts_google_request( q      = it_text
                                                       target = id_target_language ).

    rd_result = /ui2/cl_json=>serialize( data          = ls_google_request
                                         name_mappings = VALUE #( ( abap = 'Q' json = 'q' )
                                                                  ( abap = 'TARGET' json = 'target' ) ) ).
  ENDMETHOD.


  METHOD map_result.
    DATA ls_google_result TYPE ts_google_result.

    IF io_response->get_status( )-code = 200.
      /ui2/cl_json=>deserialize( EXPORTING json = io_response->get_text( )
                                 CHANGING  data = ls_google_result ).
    ENDIF.

    LOOP AT ls_google_result-data-translations INTO DATA(ls_translated).
      INSERT ls_translated-TranslatedText INTO TABLE rt_result.
    ENDLOOP.
  ENDMETHOD.
ENDCLASS.

 

Fazit

Die Translate API ist eine recht einfache API und benötigt keinen Autentifizierungsflow, wodurch wir sie sehr leicht konsumieren können. Die Klasse können wir nun überall im System verwenden, um Texte zu übersetzen.


Enthaltene Themen:
BTPABAP EnvironmentGoogle TranslateHTTP
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Dienstag und Freitag neuen Content im Bereich ABAP und unregelmäßig in allen anderen Bereichen. Schaue bei unseren Tools und Apps vorbei, diese stellen wir kostenlos zur Verfügung.


BTP - Testen mit Swagger

Kategorie - ABAP

Du hast gerade dein Service Binding in ABAP vom Typ Web API erstellt und willst nicht mit dem Postman testen? Hast du dir schon Swagger angeschaut, was nun Out-of-the-Box funktioniert?

30.09.2025

RAP - EML Varianten

Kategorie - ABAP

Wenn du EML verwendest, um mit dem ABAP RESTful Application Programming Model zu interagieren, stehen dir aktuell mehrere Varianten zur Verfürgung. Schauen wir sie uns einmal im Detail an.

16.09.2025

BTP - ATC Automatisierung

Kategorie - ABAP

Wie kannst du dein ABAP Test Cockpit in der BTP automatisieren und dir die Ergebnisse zuschicken lassen, wenn es einmal Probleme gibt? In diesem Artikel gehen wir auf die Details ein.

12.09.2025

BTP - ATC Genehmigung in Steampunk

Kategorie - ABAP

Wie kannst du eigentlich eine ATC Befreiung im SAP BTP ABAP Environment durchführen? Wir führen dich einmal Schritt für Schritt durch den Prozess.

09.09.2025

BTP - Pages und Spaces (ADT)

Kategorie - ABAP

Kannst du eigentlich auch das Launchpad mit den Pages und Spaces über die ABAP Development Tools konfigurieren? In diesem Artikel schauen wir uns die aktuellen Möglichkeiten an.

08.08.2025