Guardar traducciones del título y descripción de listas en SharePoint via REST API (SPFx, Batch y alternativa ProcessQuery)

Registrar traducciones para el título y la descripción de una lista es bastante sencillo por CSOM a través del comando:

list.TitleResource.SetValueForUICulture("en-US", "TITLE_IN_ENGLISH");

Para que estos cambios funcionen es necesario hacer los SETs y ejecutar un UPDATE. Sin el update nunca se guardarán las traducciones, por lo que si llamamos por REST al endpoint SetValueForUICulture no funcionará.

REST API Batch

Si queremos hacerlo por REST necesitamos incluir todos los pasos en un Batch, donde podemos añadir todos los cambios de idioma (tanto para el título como la descripción) y el update final:

const batchId = Guid.newGuid().toString();

let batchrequest=`
--batch_${batchId}
Content-type: application/http
Content-Transfer-Encoding: binary

POST https://MY_TENANT.sharepoint.com/sites/MY_SITE/_api/web/lists('${MY_LIST_ID}')/TitleResource/SetValueForUICulture HTTP/1.1
accept: application/json;odata.metadata=minimal
content-type: application/json;charset=utf-8

{ 'cultureName': 'en-US', 'value': 'ENGLISH_VALUE' }

--batch_${batchId}
Content-type: application/http
Content-Transfer-Encoding: binary

POST https://MY_TENANT.sharepoint.com/sites/MY_SITE/_api/web/lists('${MY_LIST_ID}')/TitleResource/SetValueForUICulture HTTP/1.1
accept: application/json;odata.metadata=minimal
content-type: application/json;charset=utf-8

{ 'cultureName': 'es-ES', 'value': 'SPANISH_VALUE' }

--batch_${batchId}
Content-type: application/http
Content-Transfer-Encoding: binary

POST https://MY_TENANT.sharepoint.com/sites/MY_SITE/_api/web/lists('${MY_LIST_ID}')/Update HTTP/1.1
accept: application/json;odata.metadata=minimal
content-type: application/json;charset=utf-8

--batch_${batchId}--
`;

const requestHeaders: Headers = new Headers();
requestHeaders.append("content-type", "multipart/mixed; boundary=batch_" + batchId);
const httpOptions: ISPHttpClientOptions = {
 headers:requestHeaders,
 body: batchrequest
 };
const postRequest = await context.spHttpClient.post(`MY_SITE_URL/_api/$batch`, SPHttpClient.configurations.v1, httpOptions);

IMPORTANTE: La query definida para el batch tiene que estar SIN ESPACIOS. Es obligatorio que cada línea este al principio del todo, sin espacios ni tabulaciones.

Alternativa: ProcessQuery.svc

Otra alternativa es utilizar la query que se hace internamente cuándo lo procesamos por CSOM. Podéis crear una aplicación de consola y capturar el tráfico al ejecutarla para luego ajustarla a vuestras necesidades. Ejemplo para título y descripción:

const contextInfoUrl: string =
 UrlUtilities.removeEndSlash("SITE_URL") +
 "/_api/contextinfo";
let httpPostOptions: ISPHttpClientOptions = {
     headers: {
          accept: "application/json",
          "content-type": "application/json"
     }
};
let response = await context.spHttpClient.post(
contextInfoUrl,
 SPHttpClient.configurations.v1,
 httpPostOptions
);
let jsonResponse = await response.json();
const formDigest = jsonResponse.FormDigestValue;
            
const clientServiceUrl =
 UrlUtilities.removeEndSlash("SITE_URL") +
 "/_vti_bin/client.svc/ProcessQuery";
const data = '<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName=".NET Library" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009">'
     + '<Actions>'
          + '<ObjectPath Id="2" ObjectPathId="1" />'
          + '<ObjectPath Id="4" ObjectPathId="3" />'
          + '<ObjectPath Id="6" ObjectPathId="5" />'
          + '<ObjectPath Id="8" ObjectPathId="7" />'
          + '<ObjectPath Id="10" ObjectPathId="9" />'
          + '<Method Name="SetValueForUICulture" Id="11" ObjectPathId="9">'
               + '<Parameters>'
                    + '<Parameter Type="String">es-es</Parameter>'
                    + '<Parameter Type="String">SPANISH_TITLE</Parameter>'
               + '</Parameters>'
          + '</Method>'
          + '<Method Name="SetValueForUICulture" Id="12" ObjectPathId="9">'
               + '<Parameters>'
                    + '<Parameter Type="String">fr-fr</Parameter>'
                    + '<Parameter Type="String">FRENCH_TITLE</Parameter>'
               + '</Parameters>'
          + '</Method>'
          + '<ObjectPath Id="15" ObjectPathId="14" />'
          + '<Method Name="SetValueForUICulture" Id="16" ObjectPathId="14">'
               + '<Parameters>'
                    + '<Parameter Type="String">es-es</Parameter>'
                    + '<Parameter Type="String">SPANISH_DESCRIPTION</Parameter>'
               + '</Parameters>'
          + '</Method>'
          + '<Method Name="SetValueForUICulture" Id="17" ObjectPathId="14">'
               + '<Parameters>'
                    + '<Parameter Type="String">fr-fr</Parameter>'
                    + '<Parameter Type="String">FRENCH_DESCRIPTION</Parameter>'
               + '</Parameters>'
          + '</Method>'
          + '<Method Name="Update" Id="19" ObjectPathId="7" />'
          + '<Query Id="20" ObjectPathId="3">'
               + '<Query SelectAllProperties="false">'
                    + '<Properties>'
                         + '<Property Name="Language" ScalarProperty="true" />'
                    + '</Properties>'
               + '</Query>'
          + '</Query>'
     + '</Actions>'
     + '<ObjectPaths>'
          + '<StaticProperty Id="1" TypeId="{e8b0df4f-8780-4f5a-88a7-22bd7975cc09}" Name="Current" />'
          + '<Property Id="3" ParentId="1" Name="Web" />'
          + '<Property Id="5" ParentId="3" Name="Lists" />'
          + '<Method Id="7" ParentId="5" Name="GetById">'
               + '<Parameters>'
                    + '<Parameter Type="Guid">{LIST_GUID}</Parameter>'
               + '</Parameters>'
          + '</Method>'
          + '<Property Id="9" ParentId="7" Name="TitleResource" />'
          + '<Property Id="14" ParentId="7" Name="DescriptionResource" />'
     + '</ObjectPaths>'
+ '</Request>';

httpPostOptions = {
     headers: {
          accept: "application/json",
          "content-type": "application/json",
          "X-RequestDigest": formDigest
     },
     body: data
};
let serviceResponse = await context.spHttpClient.post(
     clientServiceUrl,
     SPHttpClient.configurations.v1,
     httpPostOptions
);

No Responses

Leave a Reply

Your email address will not be published. Required fields are marked *