Saltar al contenido

Caso práctico: textos multilingües con fallback en Datasphere

Paso a paso para traducir atributos en SAP Datasphere: text entity, texto de reserva (fallback), reglas de validación de traducciones y prueba por idioma.

Por 15 min de lectura
Diagrama de una dimensión de SAP Datasphere con una asociación de texto a una text entity validada y un texto de reserva, consumida en un Analytic Model en varios idiomas
Índice del artículo

En cualquier grupo con negocio internacional, los informes se leen en varios idiomas. En SAP Datasphere eso se resuelve desde hace años con una text entity, pero tenía dos pegas que en proyecto dolían: si faltaba la traducción de un miembro en el idioma del usuario, el atributo salía vacío, y no había ninguna forma integrada de saber qué faltaba por traducir. En septiembre de 2026 SAP añadió las dos piezas que faltaban: un texto de reserva (fallback) en la asociación de texto y reglas de validación específicas para text entities. En este caso práctico montamos el modelo completo y lo probamos idioma a idioma.

Qué vamos a construir

Usaremos un ejemplo típico de un grupo hotelero: el régimen de alojamiento (solo alojamiento, desayuno, media pensión…), que aparece en todas las reservas y que cada mercado quiere ver en su idioma. Al acabar tendrás:

  1. Una text entity V_BOARD_TYPE_TEXT con las traducciones en español, inglés, alemán y francés, validada con las nuevas reglas de text entities.
  2. Una dimensión V_BOARD_TYPE con una asociación de texto a esa text entity y la descripción corporativa como Fallback Text.
  3. Una vista fact V_BOOKINGS y un Analytic Model AM_BOOKINGS que la consume.
  4. Una prueba por idioma con la petición OData del propio editor (sap-language) y, si tienes SAC, con el idioma de acceso a datos del perfil.

La portada resume la arquitectura. Todos los nombres técnicos (T_BOARD_TYPE, V_BOARD_TYPE, AM_BOOKINGS…) son de ejemplo: usa los de tu convención.

Por qué merece la pena

El fallo clásico lo he visto en más de un proyecto: el modelo se prueba en español e inglés y, semanas después, un usuario de otro mercado abre la story en su idioma y ve la mitad de los regímenes en blanco. El fallback ataca el síntoma: mejor ver “All inclusive” que una celda vacía. La validación ataca la causa: te dice qué falta por traducir antes de que lo descubra el usuario.

Paso a paso

  1. Paso:Sube los datos de ejemplo

    Necesitas tres CSV pequeños con datos ficticios. Puedes descargarlos tal cual: board_type.csv, board_type_text.csv y bookings.csv.

    El maestro tiene la descripción corporativa (en inglés, que será nuestro idioma de reserva):

    board_type.csv
    BOARD_ID,BOARD_DESC
    RO,Room only
    BB,Bed and breakfast
    HB,Half board
    FB,Full board
    AI,All inclusive

    La tabla de textos lleva un registro por régimen e idioma. He dejado dos errores a propósito: falta el alemán de AI y HB tiene el español duplicado con distinta capitalización.

    board_type_text.csv
    BOARD_ID,LANGU,BOARD_TEXT
    RO,es,Solo alojamiento
    BB,es,Alojamiento y desayuno
    HB,es,Media pensión
    HB,ES,Media pension
    FB,es,Pensión completa
    AI,es,Todo incluido
    RO,en,Room only
    BB,en,Bed and breakfast
    HB,en,Half board
    FB,en,Full board
    AI,en,All inclusive
    RO,de,Nur Übernachtung
    BB,de,Übernachtung mit Frühstück
    HB,de,Halbpension
    FB,de,Vollpension
    RO,fr,Logement seul
    BB,fr,Chambre et petit-déjeuner
    HB,fr,Demi-pension
    FB,fr,Pension complète
    AI,fr,Tout compris

    Y bookings.csv, con 20 reservas (BOOKING_ID, BOOKING_DATE, BOARD_ID y ROOM_NIGHTS) que suman 82 noches: 6 de RO, 13 de BB, 14 de HB, 13 de FB y 36 de AI.

    En el Data Builder del espacio, usa Import > Import CSV File para crear T_BOARD_TYPE, T_BOARD_TYPE_TEXT y T_BOOKINGS. En el editor de importación, selecciona cada columna y abre la pestaña Details: ahí cambias el tipo y marcas la clave. Para la tabla de textos:

    • LANGU debe ser String(2). Es lo que corresponde a identificadores tipo es o de, y una de las reglas que veremos después lo comprueba.
    • Marca Set as Key en BOARD_ID y en LANGU. En el maestro, la clave es BOARD_ID.

    Hazlo antes de desplegar. Si creas la tabla sin clave y la añades después, Datasphere no te deja: una tabla con datos no admite cambios de clave primaria. En ese caso, la alternativa es crear la tabla vacía con sus claves y cargarla con Upload Data from CSV File.

    Con la clave puesta, un BOARD_ID repetido con el mismo idioma no entra en la tabla. Pero fíjate en que HB/es y HB/ES no chocan: son cadenas distintas. Ese es justo el tipo de error que solo se ve más tarde.

  2. Paso:Crea la text entity como vista

    Podrías marcar directamente la tabla local como text entity, pero yo prefiero una vista: la validación de datos solo está disponible en vistas, y además me permite normalizar el idioma. Crea una SQL View V_BOARD_TYPE_TEXT:

    V_BOARD_TYPE_TEXT.sql
    SELECT
    "BOARD_ID",
    LOWER("LANGU") AS "LANGU",
    "BOARD_TEXT"
    FROM "T_BOARD_TYPE_TEXT"

    En el panel de propiedades:

    Propiedad Valor
    Semantic Usage Text
    Clave BOARD_ID y LANGU
    BOARD_ID Identificador. Semantic type: None. Text / Association: BOARD_TEXT
    LANGU Semantic type Language
    BOARD_TEXT Semantic type Text

    Lo de la tercera fila no es opcional: si BOARD_ID no tiene BOARD_TEXT como texto, la vista avisa de que la text entity no tiene exactamente una clave con Text / Association.

    El LOWER tiene su porqué: SAP admite identificadores fr, FR, fr-FR o F, pero mezclar formatos dentro de la misma entidad es buscarse problemas. Normalizar en la vista hace que el duplicado HB/ES se convierta en un duplicado real, que la validación sí detecta.

    Si tu origen es S/4HANA o BW, el idioma suele venir en 1 carácter (S, E, D) con tipo abap.lang. Es válido, pero no lo mezcles con identificadores de dos letras.

    Guarda y despliega.

    Diálogo de atributos de la vista V_BOARD_TYPE_TEXT con BOARD_ID y LANGU como clave, LANGU String(2) con semantic type Language, BOARD_TEXT con semantic type Text y BOARD_TEXT como texto de BOARD_ID
    Atributos de la text entity: clave BOARD_ID + LANGU, LANGU como Language y BOARD_TEXT como texto de BOARD_ID.
  3. Paso:Valida las traducciones

    Pulsa Data Validation Status en el panel de propiedades de la vista y después Validate. Desde septiembre aparece la categoría Text Entities, con cuatro reglas:

    Regla Qué comprueba Severidad
    Language Identifier Length Que los identificadores encajen con la longitud del tipo (1 → E; 2 → en; 3 o más → en o en-US) Error
    Language Identifier Data Type Que el tipo encaje con los valores (abap.lang solo con 1 carácter; avisa si el tipo es más largo de lo necesario) Aviso o error
    Unique Language Identifiers Un único texto por miembro e idioma. No distingue mayúsculas, y trata - y _ como iguales Error
    Completeness of Translations Que todo esté traducido en todos los idiomas usados Aviso

    Con nuestros datos tienes que ver tres reglas con incidencias:

    • Unique Key Values (categoría Keys) da un registro no válido: tras el LOWER, la clave HB/es se repite.
    • Unique Language Identifiers da dos registros no válidos: las dos filas de HB en español.
    • Completeness of Translations avisa de que falta un registro: AI en de.
    Pestaña Data Validation de V_BOARD_TYPE_TEXT con Unique Key Values y Unique Language Identifiers en error, Completeness of Translations en aviso y el estado de validación 3 en el panel de propiedades
    Resultado de la validación: dos errores por el duplicado HB/ES y un aviso por la traducción que falta.

    En cada regla con incidencias, Details ofrece Copy SQL: pégalo en una SQL view nueva y tendrás la lista exacta de registros que fallan, lista para el responsable de las traducciones.

    Corrige el duplicado: borra la fila HB,ES de T_BOARD_TYPE_TEXT (desde el Data Editor de la tabla o volviendo a cargar el CSV) y vuelve a validar. Solo debe quedar el aviso de Completeness of Translations. El alemán de AI déjalo sin traducir: lo usaremos para probar el fallback.

    Algunas reglas no se ejecutan si hay data access control, parámetros de entrada o fuentes no replicadas: valida antes de añadir la seguridad.

  4. Paso:Crea la dimensión con su texto de reserva

    Crea la vista V_BOARD_TYPE sobre T_BOARD_TYPE. Vale una vista gráfica con una proyección o una SQL view con SELECT "BOARD_ID", "BOARD_DESC" FROM "T_BOARD_TYPE", que es la que usé yo:

    • Semantic Usage: Dimension.
    • Clave: BOARD_ID.
    • BOARD_DESC: semantic type Text. Este es el requisito para poder usarla como fallback.

    En la sección Associations, abre el menú + y elige Text Association; como destino, V_BOARD_TYPE_TEXT. En Mappings, BOARD_ID de la dimensión debe quedar enlazado con el identificador BOARD_ID de la text entity. Datasphere lo propone solo porque las columnas se llaman igual.

    Y aquí está la novedad: en el campo opcional Fallback Text, selecciona BOARD_DESC. A partir de ahora, si un usuario consulta en un idioma que no tiene traducción para un miembro, verá la descripción corporativa en lugar de nada.

    Vuelve a la lista de atributos y comprueba que el Text / Association de BOARD_ID apunta a la asociación de texto. Si en algún momento habías puesto BOARD_DESC como texto directo de BOARD_ID, quítalo: SAP solo permite usar cada columna de tipo Text una vez, o como texto de otra columna o como fallback de una asociación de texto.

    Despliega.

    Panel de la asociación de texto de V_BOARD_TYPE hacia V_BOARD_TYPE_TEXT con el campo Fallback Text = BOARD_DESC
    Asociación de texto de V_BOARD_TYPE a V_BOARD_TYPE_TEXT con BOARD_DESC como Fallback Text.

    Un aviso de lo que me encontré al probarlo: al volver a abrir la vista, el desplegable Fallback Text aparecía vacío, aunque el fallback estaba guardado y funcionaba. No te fíes del desplegable: compruébalo con la prueba de la sección de validación.

  5. Paso:Monta la fact y el Analytic Model

    Crea V_BOOKINGS sobre T_BOOKINGS con Semantic Usage = Fact, ROOM_NIGHTS como medida y una asociación de BOARD_ID a la dimensión V_BOARD_TYPE. Despliega y lanza también aquí la validación: la regla Referential Integrity te dirá si hay reservas con un régimen que no existe en el maestro. Un régimen huérfano no tiene texto en ningún idioma, y eso el fallback no lo arregla.

    Después crea el Analytic Model AM_BOOKINGS a partir de V_BOOKINGS, incluye la dimensión de régimen al añadir la fuente y despliega. No necesitas configurar nada de idiomas en el modelo: el texto viaja por la asociación. En la pestaña Preview, con BOARD_ID en filas, tienes que ver las 82 noches repartidas por régimen.

    Si cambias el fallback de la dimensión después de desplegar el Analytic Model, el modelo pasa a Changes to Deploy. Hasta que no lo redespliegas, sigue sin aplicar el texto de reserva.

Validación

La prueba importante es ver el mismo dato en varios idiomas. La más rápida no necesita SAC.

En el editor de AM_BOOKINGS (vista Model), pulsa Generate OData Request en la sección Tools. Deja Request = Data y añade dos filas en Query Parameters:

  • sap-language: el desplegable muestra los idiomas por su nombre nativo; elige Deutsch y en la URL aparece de.
  • $select: BOARD_ID, la columna de texto y ROOM_NIGHTS, para que salga una fila por régimen.

La columna de texto no se devuelve si no la pides en $select, y su nombre lo genera Datasphere a partir del atributo: en mi tenant era BOARD_ID_T y, tras redesplegar el modelo, pasó a BOARD_ID_T2. Lanza primero un Preview sin $select para ver el nombre real. La URL tendrá esta forma:

Petición OData de prueba
https://<tenant>/api/v1/datasphere/consumption/analytical/<espacio>/AM_BOOKINGS/AM_BOOKINGS?sap-language=de&$select=BOARD_ID,BOARD_ID_T2,ROOM_NIGHTS

Lo que debes ver:

Idioma RO HB AI
es Solo alojamiento Media pensión Todo incluido
de Nur Übernachtung Halbpension All inclusive (fallback)
fr Logement seul Demi-pension Tout compris
it Room only Half board All inclusive

Fíjate en las dos últimas filas: en alemán solo AI cae al texto de reserva; en italiano, que no existe en la text entity, caen todos. Esa es la diferencia con el comportamiento anterior, en el que esas celdas salían vacías. Los totales no cambian con el idioma: 36 noches en AI, 82 en total.

Vista previa de Generate OData Request de AM_BOOKINGS con sap-language=de: AI muestra el texto de reserva All inclusive y el resto de regímenes su texto en alemán
Petición OData en alemán: AI no tiene traducción y muestra la descripción corporativa.

Lo comprobé también por la vía mala: con el Analytic Model desplegado antes de fijar el fallback, la misma petición devolvía AI vacío en alemán y todos los regímenes vacíos en italiano. Si ves celdas vacías con el fallback configurado, redespliega el Analytic Model antes de abrir incidencia.

En SAP Analytics Cloud la prueba equivalente es cambiar el idioma de acceso a datos (Data Access Language) en la configuración del perfil y abrir una story sobre AM_BOOKINGS.

Para el día a día, no me fiaría solo de la validación manual. Esta vista de control da la misma foto que Completeness of Translations, y la puedes programar o mostrar en un panel de calidad del dato:

V_BOARD_TYPE_TEXT_GAPS.sql
SELECT b."BOARD_ID", l."LANGU"
FROM "T_BOARD_TYPE" AS b
CROSS JOIN (
SELECT DISTINCT LOWER("LANGU") AS "LANGU"
FROM "T_BOARD_TYPE_TEXT"
) AS l
LEFT JOIN "T_BOARD_TYPE_TEXT" AS t
ON t."BOARD_ID" = b."BOARD_ID"
AND LOWER(t."LANGU") = l."LANGU"
WHERE t."BOARD_ID" IS NULL

Con los datos de ejemplo devuelve una sola fila: AI / de. Un detalle: compara contra el maestro y no contra la propia text entity, así detecta también miembros sin ningún texto. La regla estándar solo ve los idiomas que ya existen en la entidad.

Errores habituales

Síntoma Causa Solución
El campo Fallback Text no ofrece ninguna columna La columna de descripción de la dimensión no tiene semantic type Text, o ya está usada como texto de otro atributo Ponle semantic type Text y quítala del Text / Association de cualquier otra columna
Al marcar la clave en la tabla de textos: Cannot convert primary key column La tabla ya tiene datos y no admite cambios de clave primaria Marca Set as Key en el editor de importación, o crea la tabla vacía con la clave y cárgala con Upload Data from CSV File
Aviso en la text entity: no tiene exactamente una clave con Text / Association BOARD_ID no tiene asignado el texto Pon BOARD_TEXT en el Text / Association de BOARD_ID
Celdas vacías en un idioma sin traducción, con el fallback configurado El Analytic Model se desplegó antes de fijar el fallback (está en Changes to Deploy) Redespliega el Analytic Model
La petición OData falla con Property ‘BOARD_ID_T’ does not exist El nombre de la columna de texto cambia al redesplegar el modelo Consulta el nombre real con un Preview sin $select o en $metadata
No aparece el botón de validación en la text entity La text entity es una tabla local: la validación de datos solo existe en vistas Crea una vista encima con Semantic Usage = Text y valida esa
La validación no muestra algunas reglas La vista o sus fuentes tienen data access control, parámetros de entrada o fuentes remotas no replicadas Valida en una vista sin DAC ni parámetros, o replica la fuente
Unique Language Identifiers en error con datos que “parecen” distintos Mismo idioma con distinta capitalización (es/ES) o con - y _ (en-US/en_US) Normaliza el identificador en la vista o corrige el origen
Language Identifier Data Type en aviso Columna de idioma más larga de lo necesario (p. ej. String(5) con valores en) Reduce el tipo a String(2): SAP indica que mejora el rendimiento
Los nombres de columnas siguen en un solo idioma en SAC Las text entities traducen datos, no metadatos Usa la herramienta Translation del espacio para nombres de negocio y columnas

Cierre

Mi recomendación para cualquier modelo que se consuma en más de un idioma: fallback siempre en las asociaciones de texto, con la descripción corporativa como reserva, y la validación de text entities como paso fijo antes de cada transporte. El fallback evita la celda vacía en producción; la validación evita que el fallback se convierta en la excusa para no traducir.

Piensa también en cómo llega la tabla de textos a producción. Un transporte normal lleva la definición de la tabla, no sus filas, así que una tabla mantenida a mano llega vacía. Si tu tenant forma parte de una formation de SAP Business Data Cloud, activa Allow Data Transport en la tabla local (vale con semantic usage Dimension, Text o Relational Dataset) y crea el paquete desde Transport > Packages: aparece un objeto T_BOARD_TYPE_TEXT::data que incluye las filas. Ojo: SAP solo importa esos datos si la tabla se crea en la importación o está vacía. Sirve para la carga inicial; los cambios posteriores de traducciones no viajan así.

El siguiente paso: llevarlo a las dimensiones que los usuarios de otros mercados ven en la primera página de sus stories.

Fuentes