SAP itself has a report (and function modules) to import/export translations via XLIFF files. The transaction for the translation administration is LXE_MASTER
. In this transaction you are able to create Object Lists (via tab Evaluations) which hold all relevant reports/DDIC objects for a translation project.
With the report RS_LXE_TEXTEXT_EXPORT
you are able to export translations of such object lists into XLIFF files (which can be read by various localization tools - Weblate in our case). Exporting our pre-defined object lists with this report was just too laborious so we analyzed the code and developed a class which does basically the same - with the addition to be called from other ABAP code.
The core parts of this class are
- reading of the object list
- extracting the translations of every object into XLIFF
Reading the Object List
All relevant data about object lists is stored in the tables LXE_ATTOB
(attributes) and LXE_COLOB
(objects of the list). The first part is to get all relevant objects out of the list:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
DATA lt_objtypes TYPE TABLE OF lxeobjtype.
" check if there is at least one object list
IF gr_objlist IS INITIAL.
RAISE EXCEPTION TYPE cx_lxe_textext
EXPORTING
textid = cx_lxe_textext=>object_selection.
ENDIF.
" allow all types of short text
SELECT obj_type
FROM lxe_attob
INTO TABLE lt_objtypes
WHERE typeatt EQ cl_lxe_constants=>c_typeatt_short.
IF sy-subrc NE 0.
RAISE EXCEPTION TYPE cx_lxe_textext
EXPORTING
textid = cx_lxe_textext=>object_selection.
ENDIF.
" allow export of virtual objects
APPEND cl_lxe_constants=>c_objtype_dems
TO lt_objtypes.
" select all objects from the object lists
SELECT custmnr objtype objname orig_lang collnam domanam
FROM lxe_colob
INTO CORRESPONDING FIELDS OF TABLE gt_colob_st
FOR ALL ENTRIES IN lt_objtypes
WHERE objlist IN gr_objlist
AND objtype EQ lt_objtypes-table_line.
Using this code we managed to get all relevant object for extracting the localization data.
Extract Localization Data
With the relevant objects from the object list we’re now able to extract the localization data:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
METHOD create_xliff_for_lang.
DATA: lv_source_lang TYPE lxestring,
lv_destination_lang TYPE lxestring,
lv_reference_lang TYPE lxestring,
lv_tstamp_str TYPE lxestring.
DATA: lt_objects TYPE cl_lxe_textext_aux=>tt_lxe_object_full.
" prepare the texts
lt_objects = prepare_short_texts( iv_lang ).
" convert langs to xml
lv_source_lang = cl_lxe_textext_aux=>convert_lang_sap_to_xml( gv_source_lang ).
lv_destination_lang = cl_lxe_textext_aux=>convert_lang_sap_to_xml( iv_lang ).
lv_tstamp_str = create_xliff_date( ).
CALL TRANSFORMATION lxe_shorttext_to_xliff
SOURCE objects = lt_objects
src_lang = lv_source_lang
tgt_lang = lv_destination_lang
ref_lang = lv_reference_lang
timestamp = lv_tstamp_str
RESULT XML rv_result.
" Transform it to a nicely intended XML
TRY.
" read the XML file
DATA(lo_reader) = cl_sxml_string_reader=>create( rv_result ).
" set up the writer
DATA(lo_writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10
encoding = 'UTF-8' ) ).
lo_writer->set_option( if_sxml_writer=>co_opt_linebreaks ).
lo_writer->set_option( if_sxml_writer=>co_opt_indent ).
lo_reader->next_node( ).
lo_reader->skip_node( lo_writer ).
" and write it back to the xstring
rv_result = CAST cl_sxml_string_writer( lo_writer )->get_output( ).
CATCH cx_root INTO DATA(e_txt).
ENDTRY.
" validate the created xliff
cl_lxe_textext_aux=>validate_xliff(
EXPORTING
xliff = rv_result
EXCEPTIONS
invalid = 1 ).
IF sy-subrc NE 0.
RAISE EXCEPTION TYPE cx_lxe_textext
EXPORTING
textid = cx_lxe_textext=>xml_transform.
ENDIF.
ENDMETHOD.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
METHOD prepare_short_texts.
DATA: ls_object TYPE lxe_object_full,
ls_texts TYPE lxe_texts_export.
DATA: lt_pcx_s1 TYPE TABLE OF lxe_pcx_s1.
FIELD-SYMBOLS: <colob> TYPE t_colob,
<pcx> TYPE lxe_pcx_s1.
" get the objects
LOOP AT gt_colob_st ASSIGNING <colob>.
CLEAR: ls_object, lt_pcx_s1.
MOVE-CORRESPONDING <colob> TO ls_object.
IF ls_object-objname(3) = '---'.
ls_object-objname(3) = sy-mandt.
ENDIF.
CALL FUNCTION 'LXE_OBJ_TEXT_PAIR_READ'
EXPORTING
t_lang = iv_lang
s_lang = gv_source_lang
custmnr = ls_object-custmnr
objtype = ls_object-objtype
objname = ls_object-objname
TABLES
lt_pcx_s1 = lt_pcx_s1.
CHECK lt_pcx_s1 IS NOT INITIAL.
CALL FUNCTION 'LXE_OBJ_TRANSLATION_STATUS2'
EXPORTING
t_lang = iv_lang
s_lang = gv_source_lang
custmnr = ls_object-custmnr
objtype = ls_object-objtype
objname = ls_object-objname
IMPORTING
stattrn = ls_object-stattrn.
" cumulate
" (target text must by ignored as it would cause redundant translations)
SORT lt_pcx_s1 BY s_text unitmlt.
DELETE ADJACENT DUPLICATES FROM lt_pcx_s1 COMPARING s_text unitmlt.
LOOP AT lt_pcx_s1 ASSIGNING <pcx>.
MOVE-CORRESPONDING <pcx> TO ls_texts.
APPEND ls_texts TO ls_object-texts.
ENDLOOP.
prepare_short_texts_lines( EXPORTING iv_lang = iv_lang
CHANGING cs_object = ls_object ).
ls_object-path = |//{ sy-sysid }//{ sy-mandt }//{ ls_object-custmnr }//{ ls_object-objtype }//{ ls_object-objname }|.
APPEND ls_object
TO rt_objects.
ENDLOOP.
ENDMETHOD.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
METHOD prepare_short_texts_lines.
CONSTANTS: lc_approved_yes TYPE string VALUE 'yes',
lc_approved_no TYPE string VALUE 'no'.
DATA: lv_stattrn TYPE lxestattrn,
lt_ref_texts TYPE STANDARD TABLE OF lxe_pcx_s1,
wa_text TYPE lxe_pcx_s1.
FIELD-SYMBOLS <text> TYPE lxe_texts_export.
LOOP AT cs_object-texts ASSIGNING <text>.
CLEAR lv_stattrn. " lv_pstatus.
TRY.
cl_lxe_pp=>factory->getlib_eval( )->evaluate_get(
EXPORTING
i_src_lang = gv_source_lang
i_tgt_lang = iv_lang
i_domain = cs_object-domanam
i_src_text = <text>-s_text
i_tgt_text = <text>-t_text
i_max_length = <text>-unitmlt
IMPORTING
e_trl_status = lv_stattrn
e_best_p_text = <text>-best_pp
e_best_p_status = <text>-best_pp_status ).
CATCH cx_lxe_pp.
DELETE TABLE cs_object-texts FROM <text>.
CONTINUE.
ENDTRY.
IF lv_stattrn = cl_lxe_constants=>c_trl_status_translated.
<text>-state = lv_stattrn.
<text>-approved = lc_approved_yes.
ELSE.
<text>-state = lv_stattrn.
<text>-approved = lc_approved_no.
ENDIF.
ENDLOOP.
ENDMETHOD.
Using these methods we’re able to export existing localization data of our SAP system to a XLIFF file.