Skip to content

feat(i18n) + fix(install): XCO translation tools and InstallZADTVSP robustness#122

Open
ClementRingot wants to merge 24 commits into
oisee:mainfrom
ClementRingot:feat/i18n-and-install-fixes
Open

feat(i18n) + fix(install): XCO translation tools and InstallZADTVSP robustness#122
ClementRingot wants to merge 24 commits into
oisee:mainfrom
ClementRingot:feat/i18n-and-install-fixes

Conversation

@ClementRingot
Copy link
Copy Markdown

Summary

Adds comprehensive XCO-based i18n/translation tools and fixes multiple InstallZADTVSP deployment issues, particularly on load-balanced and non-HANA SAP systems.

Compatibility: On-premise and SAP Private Cloud only. Not available on BTP/Public Cloud (requires custom ABAP class deployment via InstallZADTVSP).


i18n / Translation Tools (new)

5 new MCP tools powered by the xco_i18n class over WebSocket (ZADT_VSP), available in all modes (hyperfocused, focused, expert):

Tool Purpose
GetTranslationXCO Read translated texts for any ABAP object
SetTranslationXCO Write translated texts (requires transport)
ListTranslatableTextsXCO Discover all translatable texts for an object
CompareTranslationsXCO Side-by-side comparison between two languages
ListLanguages List all SAP-installed languages (SAP code, ISO code, name)

Supported target types: data_element, domain, data_definition (CDS entity + field level), metadata_extension, message_class, text_pool, application_log_object, business_configuration_object.

Key features:

  • Uses xco_i18n class
  • ISO 639-1 language codes: accepts both SAP 1-char (E, D, S) and ISO 2-char (EN, DE, ES)
  • Auto-discover fields: CompareTranslationsXCO for data_definition/metadata_extension auto-discovers all CDS fields when fields param is omitted
  • Auto-detect ME annotation positions: reads DDLX source to count actual @UI.lineItem/@UI.identification/etc. positions
  • Entity-level CDS descriptions: data_definition supports entity-level texts (endusertext_label, UI.headerInfo title/description/typeName/typeNamePlural) alongside field-level texts
  • Original language detection: reads original language from TADIR
  • Fix & encoding: SetEscapeHTML(false) prevents &\u0026 in WebSocket JSON (was breaking SAP message placeholders &1, &2)
  • Embedded ABAP class ZCL_VSP_I18N_SERVICE (~1700 lines) auto-deployed via InstallZADTVSP

InstallZADTVSP Fixes

Fix Problem
Load-balanced SAP robustness Existence check and CreateObject can hit different backends → upsert fallback with AlreadyExists detection
Skip AMDP on non-HANA Detects DB system, skips AMDP debugger service on non-HANA (avoids syntax errors)
Skip I18N on old releases Skips ZCL_VSP_I18N_SERVICE on ABAP Platform < 2022 (release < 756) where XCO APIs are unavailable
Retry lock after create On load-balanced systems, lock may fail immediately after create → retry logic
Set Description + check Success Properly sets package/class descriptions and validates deployment result
Syntax check before lock Reorders to avoid holding locks during slow syntax checks; fixes POSIX regex deprecation

Infrastructure

  • Cookie passthrough for WebSocket: passes browser-auth cookies to all WebSocket clients (AMDP, Debug, I18N), enabling all WebSocket-based tools in browser-auth mode
  • Dynamic APC service discovery: discovers available ZADT_VSP services via SEOMETAREL instead of hardcoded list

Files Changed (28 files, +3563 / -109)

Area Key Files
i18n handlers handlers_i18n_xco.go (new), i18n_ws.go (new), zcl_vsp_i18n_service.clas.abap (new)
i18n tests handlers_i18n_xco_test.go (new), i18n_ws_test.go (new)
install fixes handlers_install.go, workflows.go, workflows_deploy.go, workflows_source.go
WebSocket infra websocket_base.go, websocket.go, amdp_websocket.go
tool registration tools_register.go, tools_focused.go, tools_groups.go
APC discovery zcl_vsp_apc_handler.clas.abap, embed.go

Test Plan

  • go build ./cmd/vsp compiles without errors
  • go test ./internal/mcp/ passes (including new i18n unit tests)
  • go test ./pkg/adt/ passes (including new i18n_ws tests)
  • All unrelated test suites pass (ctxcomp, abaplint, graph, dsl, config, etc.)
  • Integration test: InstallZADTVSP on a load-balanced SAP system
  • Integration test: ListTranslatableTextsXCOGetTranslationXCOSetTranslationXCO workflow
  • Integration test: browser-auth mode with cookie passthrough

Scope Note

Debug-related changes (WebSocket debugger migration, cross-tool terminal IDs, TERMINAL mode listener) were intentionally excluded from this PR to keep scope focused on i18n + install. They will be submitted separately.

🤖 Generated with Claude Code

ClementRingot and others added 24 commits April 23, 2026 22:38
Adds full i18n/translation coverage for ABAP objects not reachable via
ADT REST (CDS/DDLS fields, DDLX annotations, domains, data elements)
using the released C1 API XCO_CP_I18N (requires SAP_BASIS >= 7.57).

ABAP:
- New ZCL_VSP_I18N_SERVICE implementing ZIF_VSP_SERVICE for the "i18n"
  domain: get_translation, set_translation, list_languages, compare_translations
- Registered in ZCL_VSP_APC_HANDLER class_constructor
- Bundled via go:embed for InstallZADTVSP deployment

Go:
- pkg/adt/i18n_ws.go: 4 WebSocket client methods on AMDPWebSocketClient
- internal/mcp/handlers_i18n_xco.go: 4 MCP handlers
- tools_register.go: GetTranslationXCO, SetTranslationXCO, ListLanguages,
  CompareTranslationsXCO registered with full parameter definitions
- tools_focused.go: GetTranslationXCO + ListLanguages in focused mode
- tools_groups.go: all 4 tools added to group N (i18n)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When using --browser-auth or --cookie-file, the WebSocket client
(ZADT_VSP) was not receiving the session cookies, causing HTTP 302
redirects to the SAML IdP. Only Basic Auth credentials were sent
in the WebSocket handshake headers.

This change adds a cookies parameter to BaseWebSocketClient,
NewDebugWebSocketClient, and NewAMDPWebSocketClient, and sends
them as a Cookie header when user/password are empty.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add routeI18nAction to route i18n sub-actions through the unified SAP tool:
- GET_TRANSLATION: read translations via XCO
- SET_TRANSLATION: write translations via XCO
- LIST_LANGUAGES: list installed SAP languages
- COMPARE_TRANSLATIONS: compare translations between languages

Usage: SAP(action="i18n", target="GET_TRANSLATION", params={...})

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The CP (Cloud Platform) variant filters out custom Z* objects via
CL_XCO_CP_AR_OBJECT->is_hidden(), causing exists() to return false
for DDLXs, DDLSs and other custom objects not released for Cloud.

Changes to ZCL_VSP_I18N_SERVICE:
- Replace all xco_cp_i18n references with xco_i18n (16 occurrences)
- Replace xco_cp_metadata_extension with xco_metadata_extension
- Add get_me_field_attr helper supporting 8 ME text attribute types
- Rewrite GET metadata_extension: dynamic multi-attribute with TRY/CATCH
  (endusertext_label, ui_lineitem_label, ui_identification_label,
   ui_fieldgroup_label, ui_facet_label, consumption_valuehelpdef_label)
- Add SET metadata_extension handler (was missing)
- Add COMPARE metadata_extension handler with TRY/CATCH per attribute
- Add error tolerance: gracefully skip missing annotations per field

Root cause: CL_XCO_CP_AR_OBJECT overrides exists() with is_hidden()
check that uses CL_XCO_CP_AR_OBJECT_CLASS to verify cloud release
status. Custom Z* DDLXs are never released, so they are always hidden.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… fallback

- Use xco_cp_i18n (released API) as primary for all target types
- Auto-detect on-premise via RTTI (XCO_I18N class existence)
- On on-premise: check CP visibility per object via xco_cp_abap_repository
- Fallback to xco_i18n for objects not in Cloud-configured SWCs
- Change xco_metadata_extension to xco_cp_metadata_extension (released)
- Add detect_system() and should_use_cp() methods
- Tested: Cloud SWC objects use CP path, \ objects use fallback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace hardcoded service instantiation with dynamic discovery
- Query SEOMETAREL for all ZIF_VSP_SERVICE implementors at startup
- Build domains list dynamically from registered services
- New services are auto-detected without modifying handler class

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove hardcoded service class expectations from APCHandler dependency
test since services are now discovered dynamically via SEOMETAREL.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ol documentation

- Add handle_list_texts to ABAP ZCL_VSP_I18N_SERVICE class (enumerates all
  translatable texts for data_element, domain, data_definition,
  metadata_extension, message_class, text_pool, application_log_object,
  business_configuration_object)
- Add ListTranslatableTextsXCO MCP tool with Go handler, WebSocket client,
  and tool registration
- Add subobject_name param for application_log_object support
- Add position param for metadata_extension UI annotations
- Rewrite all i18n tool descriptions with complete target type docs,
  valid attributes per type, required params, and workflow guidance
- Add metadata_extension support to CompareTranslationsXCO
- Add ListTranslatableTextsXCO to focused mode whitelist and tool group N
- Fix all references from XCO_CP_I18N to XCO I18N

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add comprehensive tests for the XCO-based i18n translation tools:

pkg/adt/i18n_ws_test.go:
- JSON serialization tests for I18NGetParams, I18NSetParams,
  I18NCompareParams, I18NListTextsParams structs
- Verify omitempty behavior for optional fields
- Test new SubobjectName/Position fields
- I18NText roundtrip serialization
- I18NListTextEntry serialization

internal/mcp/handlers_i18n_xco_test.go:
- Tool registration: verify all 5 XCO i18n tools are registered
  with correct required/optional parameters
- Handler param validation: test required param error messages
  for Get, Set, Compare, ListTexts handlers
- Set handler: test invalid JSON, empty array edge cases
- Fields parsing: test comma-separated and JSON array formats
- Focused mode: verify i18n tools in focused tool set
- Tool groups: verify all 5 tools in group N

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Use Mode='expert' in test config so all tools are registered
  (SetTranslationXCO and CompareTranslationsXCO are not in focused mode)
- Replace handler-level param validation tests with schema-level
  required param tests to avoid WebSocket connection attempts in CI
- Remove unused context import

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
InstallZADTVSP was silently failing: WriteSourceOptions had no Description
set, causing writeSourceCreate to return early with a nil error but
Success=false. The handler only checked err, not result.Success, so it
reported all objects as deployed when none were actually created.

Two fixes:
- Pass obj.Description into WriteSourceOptions
- Check wsResult.Success in addition to err

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ation

- DeployFromFile/CreateFromFile: move SyntaxCheck before LockObject
  to prevent lock handle invalidation on some SAP systems (matches
  WriteClass pattern: SyntaxCheck -> Lock -> Update -> Unlock -> Activate)
- Replace deprecated FIND REGEX (POSIX) with FIND PCRE in
  zcl_vsp_rfc_service and zcl_vsp_amdp_service
- Shorten I18N service description to fit SAP 60-char limit

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ackage exists msg

- Skip ZCL_VSP_AMDP_SERVICE deployment on non-HANA systems (like git skip)
- Add retry logic (3 attempts, 500ms backoff) in WriteClass lock step for
  newly created objects that may not be immediately lockable (404 race)
- Handle package 'already exists' gracefully instead of showing raw XML error
- Update features summary to reflect AMDP availability

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
XCO_CP_I18N APIs are only available from ABAP Platform 2022 (SAP_BASIS 756+).
Skip ZCL_VSP_I18N_SERVICE deployment on older systems using GetSystemInfo
release check, same pattern as AMDP/HANA and Git/abapGit skips.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add handler-level retry (3 attempts, 5s/8s/12s delays) in InstallZADTVSP
  for transient errors (404, activation failures) on load-balanced backends
- Add AlreadyExists fallback in WriteSource upsert mode: if create fails
  because object exists on another backend, fall back to update path
- Revert lower-level retry additions (lockWithRetry, isAlreadyExistsError,
  upsert reverse fallback) that were insufficient for all failure patterns
- Restore workflows.go and workflows_source.go to v2.40.4 baseline

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ABAP changes (XCO I18N service):
- list_texts: now returns entity-level short_description (level=entity) before field list
- set_translation: supports entity-level when field_name is omitted (uses xco_i18n=>target->data_definition->entity)
- get_translation: supports entity-level when field_name is omitted (reads endusertext_label, ui_headerinfo_* attributes)
- New method get_dd_entity_attr mapping 5 entity text attributes
- RTTS fallback for field enumeration in list_texts

Go changes (MCP tool descriptions):
- GetTranslationXCO: field_name now optional for data_definition (entity-level when omitted)
- SetTranslationXCO: field_name now optional for data_definition (entity-level when omitted)
- ListTranslatableTextsXCO: description updated to mention entity-level texts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…English

The list_texts handler was hardcoding 'E' (English) as the original language
for all objects. This caused incorrect behavior when an object was created
in a different language (e.g., German or French).

Now reads masterlang from TADIR based on the target_type mapping:
- data_element -> DTEL, domain -> DOMA, data_definition -> DDLS
- metadata_extension -> DDLX, message_class -> MSAG
- text_pool -> CLAS/FUGR (based on owner type)

Falls back to sy-langu (session language) if TADIR entry not found.
Also changed default language fallback from 'E' to sy-langu.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Extract 3 helper methods: get_cds_field_names, resolve_original_language, build_text_json_entry
- Fix Bug oisee#1: entity description now uses XCO i18n (correct language)
- Fix Bug oisee#2: message_class filter uses SELECT DISTINCT (all messages)
- Eliminate CDS type-switch duplication (3 occurrences -> 1 helper)
- Extract TADIR original language lookup to reusable method
- Add domain and message_class support to compare_translations
- Add APLO/BCO WHEN branches to list_texts
- Add entity-level comparison to data_definition compare
- Update WHEN OTHERS error message with all supported types

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace hardcoded WHILE <= 10 loops with dynamic position counting by
parsing DDLX source from DDLXSRC_SRC table. For each field and positional
annotation (UI.lineItem, UI.identification, UI.fieldGroup, UI.facet, etc.),
the actual array size is determined by counting top-level { entries in the
annotation's [...] array.

New helper methods:
- map_me_attr_to_anno: maps i18n attribute names to CDS annotation names
- count_ddlx_positions: parses DDLX source to count annotation array entries

This fixes the issue where objects with >10 annotation entries per field
(e.g., UI.facet with 12 entries) would be silently truncated.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…er fields, debugger cross-tool support

i18n improvements:
- Fix double-encoding of & as \u0026 in WebSocket JSON (SetEscapeHTML=false)
- Fix & HTML-escaping in all i18n handler JSON responses
- Add ISO 639-1 to SAP SPRAS language code mapping (ES→S, EN→E, DE→D, etc.)
- Auto-discover CDS fields in compare_translations for data_definition/metadata_extension
- Add CompareTranslationsXCO to focused mode tool whitelist
- Update tool descriptions for optional fields and ISO language codes

Debugger cross-tool support:
- Add --ide-id and --debug-user CLI flags with env vars (SAP_IDE_ID, SAP_USER_DEBUG)
- Add WebSocket-based DebuggerListen handler (handleDebuggerListenWS)
- Inject terminalId/ideId into all debug WebSocket requests
- Switch legacy handler to TERMINAL mode for cross-tool breakpoint sharing
- Sync ABAP source ZCL_VSP_DEBUG_SERVICE with SAP (terminal IDs, init, cleanup)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restore debug files (main.go, handlers_debugger.go, handlers_debugger_legacy.go,
websocket_debug.go, zcl_vsp_debug_service.clas.abap) to upstream state.
Keep only cookie passthrough in WebSocket constructors (needed for browser-auth
used by i18n tools). Revert DebuggerListen handler back to REST version.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All XCO i18n tools (Get, Set, Compare, List, ListLanguages) are now
available in focused mode. SetTranslationXCO was previously excluded
as write-only but is needed for the full translation workflow.

Hyperfocused mode already routes all XCO tools via routeI18nAction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant