Multi-Language/Translations in ABAP Cloud

kategorie
ABAP Cloud
Veröffentlicht
autor
Johannes

Internationale SAP-Anwendungen muessen Texte in verschiedenen Sprachen anzeigen. ABAP Cloud bietet mehrere Mechanismen fuer Mehrsprachigkeit: Message Classes fuer Meldungen, Text Elements fuer UI-Texte und CDS Text Associations fuer Datenbanktexte. Dieser Artikel zeigt, wie du mehrsprachige Anwendungen in ABAP Cloud entwickelst.

Uebersicht der Uebersetzungsmechanismen

In ABAP Cloud gibt es verschiedene Ansaetze fuer Mehrsprachigkeit:

MechanismusVerwendungSpeicherort
Message ClassesMeldungen (Fehler, Warnungen, Erfolg)Nachrichtenklasse
Text ElementsUI-Texte in ABAP-CodeTextelemente der Klasse
CDS Text AssociationsDatenbanktexte (z.B. Materialbezeichnungen)Texttabellen
Data ElementsFeldbezeichnungenDDIC Data Element
CDS AnnotationsMetadata-Texte fuer Fiori@EndUserText, @UI.*

Message Classes - Meldungen uebersetzen

Message Classes sind der Standard fuer Fehlermeldungen, Warnungen und Informationen. In ABAP Cloud erstellst du sie im ADT unter Other ABAP Repository Objects > Message Class.

Message Class erstellen

" Definition einer Message Class (in ADT)
" Message Class: ZTRAVEL_MSG
" Nachrichten:
" 001 - Reise & erfolgreich angelegt
" 002 - Reise & bereits gebucht
" 003 - Ungueltige Reisedaten: & bis &
" 004 - Maximale Reisedauer von & Tagen ueberschritten

Die Platzhalter & werden zur Laufzeit durch Parameter ersetzt:

CLASS zcl_travel_validation DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_abap_behavior_handler.
ENDCLASS.
CLASS zcl_travel_validation IMPLEMENTATION.
METHOD if_abap_behavior_handler~validate.
" Nachricht mit Parametern ausgeben
DATA(ls_travel) = <fs_travel>.
IF ls_travel-begin_date > ls_travel-end_date.
" Nachricht 003: Ungueltige Reisedaten: & bis &
APPEND VALUE #(
%tky = ls_travel-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = |Ungueltige Reisedaten: { ls_travel-begin_date } bis { ls_travel-end_date }|
)
) TO reported-travel.
ENDIF.
" Alternative: Message Class verwenden
APPEND VALUE #(
%tky = ls_travel-%tky
%msg = new_message(
id = 'ZTRAVEL_MSG'
number = '003'
severity = if_abap_behv_message=>severity-error
v1 = |{ ls_travel-begin_date }|
v2 = |{ ls_travel-end_date }|
)
) TO reported-travel.
ENDMETHOD.
ENDCLASS.

Nachrichten uebersetzen

Uebersetzungen werden in ADT ueber Properties > Translations gepflegt. Die Originalsprache ist typischerweise Englisch (EN), Uebersetzungen erfolgen in die Zielsprachen.

" ZTRAVEL_MSG - Nachricht 003
" EN: Invalid travel dates: & to &
" DE: Ungueltige Reisedaten: & bis &
" FR: Dates de voyage invalides: & a &
" ES: Fechas de viaje no validas: & a &

Text Elements - Programmtexte

Text Elements sind Texte, die direkt im ABAP-Code verwendet werden. In ABAP Cloud werden sie als Teil der ABAP-Klasse definiert.

Text Elements in Klassen

CLASS zcl_travel_report DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
" Text Symbols werden in der Klasse definiert
" TEXT-001: Reiseuebersicht
" TEXT-002: Keine Reisen gefunden
" TEXT-003: Reise erstellt am
METHODS generate_report
RETURNING VALUE(rv_html) TYPE string.
ENDCLASS.
CLASS zcl_travel_report IMPLEMENTATION.
METHOD generate_report.
" Text Symbols verwenden
DATA(lv_title) = TEXT-001. " Reiseuebersicht
" Alternativ: Inline-Text mit Uebersetzung
DATA(lv_no_data) = 'No travels found'(002).
" Text mit Variablen
rv_html = |<h1>{ lv_title }</h1>|.
IF lt_travels IS INITIAL.
rv_html = rv_html && |<p>{ lv_no_data }</p>|.
ENDIF.
ENDMETHOD.
ENDCLASS.

Text Pool pflegen

In ADT oeffnest du die Klasse und navigierst zu Text Elements im Outline-View. Dort werden die Texte gepflegt:

SymbolText (EN)Text (DE)
001Travel OverviewReiseuebersicht
002No travels foundKeine Reisen gefunden
003Travel created onReise erstellt am

CDS Text Associations - Datenbanktexte

Fuer sprachabhaengige Stammdaten (z.B. Materialbezeichnungen, Laendernamen) verwendet ABAP Cloud CDS Text Associations. Diese verknuepfen eine Haupttabelle mit einer Texttabelle.

Texttabelle anlegen

Zuerst erstellst du eine Texttabelle mit Sprachschluessel:

@EndUserText.label : 'Produkttexte'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
define table zproduct_text {
key client : abap.clnt not null;
key product_id: zproduct_id not null;
key language : abap.lang not null;
name : abap.char(60);
description : abap.char(255);
}

CDS View mit Text Association

Der CDS View verbindet Stammdaten mit Texten:

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Produkt mit Texten'
define view entity ZI_Product
as select from zproduct as Product
association [0..*] to zproduct_text as _Text
on _Text.product_id = Product.product_id
{
key Product.product_id as ProductId,
Product.product_type as ProductType,
Product.price as Price,
Product.currency as Currency,
" Text Association exponieren
_Text
}

Text Association in Projection View

In der Projection View nutzt du @ObjectModel.text.association:

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Produkt (Projektion)'
@Metadata.allowExtensions: true
define view entity ZC_Product
as projection on ZI_Product
{
key ProductId,
ProductType,
Price,
Currency,
" Text Association mit automatischer Sprachfilterung
@ObjectModel.text.association: '_Text'
_Text
}

Automatische Sprachfilterung

Mit @Semantics.language: true markierst du das Sprachfeld:

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Produkttext View'
define view entity ZI_ProductText
as select from zproduct_text
{
key product_id as ProductId,
@Semantics.language: true
key language as Language,
name as Name,
description as Description
}

Fiori Elements filtert automatisch auf die Anmeldesprache des Benutzers.

Text Element fuer Anzeigefeld

Fuer ein einzelnes Anzeigefeld mit automatischer Uebersetzung:

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Produkt mit Beschreibung'
define view entity ZI_ProductWithText
as select from zproduct as Product
left outer join zproduct_text as Text
on Text.product_id = Product.product_id
and Text.language = $session.system_language
{
key Product.product_id as ProductId,
Product.price as Price,
" Text in Benutzersprache
Text.name as ProductName,
Text.description as ProductDescription
}

Die Systemvariable $session.system_language liefert die Anmeldesprache.

Data Elements - Feldbezeichnungen

Data Elements definieren Feldbezeichnungen, die automatisch in Fiori und ALV angezeigt werden.

Data Element mit Uebersetzungen

@EndUserText.label : 'Produkt-ID'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
define type zproduct_id : abap.char(10);

Die Bezeichnungen werden in ADT unter Properties > Translations gepflegt:

SpracheKurztextMitteltextLangtext
ENProduct IDProduct IdentifierProduct Identification Number
DEProdukt-IDProduktkennungProduktidentifikationsnummer
FRID produitIdentifiant produitNumero d’identification du produit

Domain mit Festwerten

Fuer feste Wertebereiche (z.B. Status) eignen sich Domains mit uebersetzten Festwerten:

@EndUserText.label : 'Reisestatus'
define domain ztravel_status : abap.char(1) {
value 'N' : 'New'; " Neu
value 'O' : 'Open'; " Offen
value 'A' : 'Approved'; " Genehmigt
value 'X' : 'Rejected'; " Abgelehnt
}

CDS Annotations fuer UI-Texte

Fiori Elements verwendet CDS Annotations fuer UI-Texte. Diese koennen ebenfalls uebersetzt werden.

@EndUserText Annotation

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Travel Management'
@EndUserText.quickInfo: 'Manage business travels and expenses'
define view entity ZI_Travel
as select from ztravel
{
@EndUserText.label: 'Travel ID'
@EndUserText.quickInfo: 'Unique travel identifier'
key travel_id as TravelId,
@EndUserText.label: 'Agency'
agency_id as AgencyId,
@EndUserText.label: 'Customer'
customer_id as CustomerId,
@EndUserText.label: 'Begin Date'
begin_date as BeginDate,
@EndUserText.label: 'End Date'
end_date as EndDate,
@EndUserText.label: 'Total Price'
total_price as TotalPrice
}

@UI Annotations mit Texten

@UI.headerInfo: {
typeName: 'Travel',
typeNamePlural: 'Travels',
title: { value: 'TravelId' },
description: { value: 'Description' }
}
define view entity ZC_Travel
as projection on ZI_Travel
{
@UI.facet: [
{
id: 'GeneralInfo',
label: 'General Information',
type: #IDENTIFICATION_REFERENCE
},
{
id: 'Dates',
label: 'Travel Dates',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Dates'
}
]
@UI.identification: [{ position: 10 }]
@UI.lineItem: [{ position: 10, label: 'Travel' }]
key TravelId,
@UI.fieldGroup: [{ qualifier: 'Dates', position: 10, label: 'From' }]
BeginDate,
@UI.fieldGroup: [{ qualifier: 'Dates', position: 20, label: 'To' }]
EndDate
}

Translation Workflow

Der Uebersetzungsprozess in ABAP Cloud unterscheidet sich von klassischem ABAP (Transaktion SE63).

Uebersetzbare Objekte exportieren

In ADT kannst du uebersetzbare Objekte exportieren:

  1. Package > Export Translations waehlen
  2. Zielsprachen auswaehlen
  3. XLIFF-Datei wird generiert
<!-- Beispiel XLIFF-Export -->
<xliff version="1.2">
<file source-language="en" target-language="de">
<body>
<trans-unit id="ZTRAVEL_MSG.001">
<source>Travel & successfully created</source>
<target>Reise & erfolgreich angelegt</target>
</trans-unit>
<trans-unit id="ZTRAVEL_MSG.002">
<source>Travel & already booked</source>
<target>Reise & bereits gebucht</target>
</trans-unit>
</body>
</file>
</xliff>

Uebersetzungen importieren

Nach der Uebersetzung (durch Uebersetzer oder Uebersetzungsbuero):

  1. Package > Import Translations waehlen
  2. Uebersetzte XLIFF-Datei auswaehlen
  3. Uebersetzungen werden ins System importiert

Fiori App: Maintain Translations

Fuer BTP-Umgebungen steht die Fiori App Maintain Translations zur Verfuegung:

  1. App im Launchpad starten
  2. Software Component und Sprache waehlen
  3. Texte direkt in der Oberflaeche uebersetzen
  4. Aenderungen speichern und aktivieren

Namenskonventionen fuer Uebersetzungen

ObjekttypNamenskonventionBeispiel
Message ClassZ{PROJEKT}_MSGZTRAVEL_MSG
Data Elementz{bereich}_{feld}ztravel_status
Domainz{bereich}_{domain}ztravel_status
Text Tablez{stamm}_textzproduct_text

Best Practices

1. Originalsprache festlegen

Definiere eine einheitliche Originalsprache (typischerweise EN):

" Immer englische Originaltexte verwenden
" ZTRAVEL_MSG
" 001 - EN: Travel & successfully created
" 001 - DE: Reise & erfolgreich angelegt

2. Konsistente Terminologie

Verwende ein Glossar fuer konsistente Uebersetzungen:

Begriff (EN)Begriff (DE)
TravelReise
BookingBuchung
CustomerKunde
AgencyAgentur
StatusStatus

3. Platzhalter sinnvoll einsetzen

" Gut: Flexibler Text mit Platzhaltern
" & records were processed successfully.
" Es wurden & Datensaetze erfolgreich verarbeitet.
" Schlecht: Grammatik funktioniert nicht in allen Sprachen
" & record(s) processed.

4. Texttabellen effizient abfragen

" Performant: Join mit Fallback
define view entity ZI_ProductWithText
as select from zproduct as Product
left outer join zproduct_text as UserText
on UserText.product_id = Product.product_id
and UserText.language = $session.system_language
left outer join zproduct_text as FallbackText
on FallbackText.product_id = Product.product_id
and FallbackText.language = 'E' " Englisch als Fallback
{
key Product.product_id,
" Benutzersprache bevorzugen, sonst Fallback
coalesce( UserText.name, FallbackText.name ) as Name
}

5. Uebersetzungsstatus pruefen

Vor einem Release sollten alle Texte uebersetzt sein:

" CDS View fuer fehlende Uebersetzungen
define view entity ZI_MissingTranslations
as select from zproduct as Product
left outer join zproduct_text as Text
on Text.product_id = Product.product_id
and Text.language = 'D' " Deutsche Uebersetzung
{
key Product.product_id,
case when Text.product_id is null then 'X' else '' end as MissingDE
}
where Text.product_id is null

Haeufige Probleme und Loesungen

Problem: Texte werden nicht angezeigt

Ursache: Texttabelle hat keinen Eintrag fuer die Benutzersprache.

Loesung: Fallback-Logik implementieren:

coalesce(
UserText.name,
FallbackText.name,
cast( Product.product_id as abap.char(60) )
) as DisplayName

Problem: Annotation-Texte nicht uebersetzt

Ursache: @EndUserText-Annotations werden nicht automatisch uebersetzt.

Loesung: Texte aus Data Elements verwenden oder manuelle Uebersetzung pflegen.

Problem: Dynamische Texte

Ursache: Texte werden zur Laufzeit zusammengesetzt.

Loesung: Message Class mit Platzhaltern verwenden:

" Message Class statt String-Konkatenation
MESSAGE e001(ztravel_msg) WITH lv_travel_id INTO DATA(lv_msg).

Zusammenfassung

Mehrsprachige ABAP Cloud Anwendungen erfordern die richtige Kombination der verfuegbaren Mechanismen:

  • Message Classes fuer alle Meldungen (Fehler, Warnungen, Informationen)
  • Text Elements fuer statische Programmtexte
  • CDS Text Associations fuer sprachabhaengige Stammdaten
  • Data Elements fuer Feldbezeichnungen
  • CDS Annotations fuer UI-Metadaten in Fiori

Der Uebersetzungsworkflow in ABAP Cloud nutzt XLIFF-Export/Import oder die Fiori App “Maintain Translations”. Eine konsistente Originalsprache und ein Glossar erleichtern die Uebersetzung erheblich.

Weiterführende Artikel