Instantly share code, notes, and snippets.

Embed
What would you like to do?
Example of a Translation Manager Value Mapper (for stacked Content) - Show how to build a more complex mapper, and pass any inner values back into other mappers (this is now in translation manager core - and supports v2 of stacked content)
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core;
using Jumoo.TranslatePlus.Core.Models;
namespace Jumoo.TranslatePlus.Core.ValueMappers
{
public class StackedContentMapper : BaseValueMapper, IValueMapper
{
public string Name => "Inner Content";
public override string[] Editors => new string[] { "Our.Umbraco.StackedContent" };
public StackedContentMapper() : base() { }
/// <summary>
/// Get the Translation Values out of the content
/// </summary>
/// <param name="displayName">Name shown to editors</param>
/// <param name="propertyTypeAlias">Alias of the propertyType</param>
/// <param name="value">the raw value taken from the Content Item</param>
/// <param name="culture">Culture of the Language (used when one property contains multiple languages [vorto])</param>
/// <returns>A TranslationValue with any child items nested in the InnerValues list</returns>
public TranslationValue GetSourceValue(string displayName, string propertyTypeAlias, object value, CultureInfoView culture)
{
// check we go something valid (not null, and some json)
if (value == null) return null;
var stringValue = (string)value;
if (stringValue.IsNullOrWhiteSpace()) return null;
var array = JsonConvert.DeserializeObject<JArray>(stringValue);
if (array == null || !array.Any()) return null;
// create a translation value we will return
var translationValue = new TranslationValue(displayName, propertyTypeAlias);
// go through each of the items in the array
foreach (var innerContentObject in array)
{
// get the doctype for this item
var docTypeAlias = innerContentObject["icContentTypeAlias"].ToString();
var docType = _contentTypeService.GetContentType(docTypeAlias);
if (docType == null) continue;
// the key (we use this in the innerValues - as a way of identifing this item)
var itemKey = innerContentObject["key"].ToString();
var itemName = innerContentObject["name"].ToString();
// create the child translation value for this doctype
var docTypeTranslationValue = new TranslationValue(docType.Name, docTypeAlias);
int propertyCounterKey = 0;
// go through the properties that this doctype contains
// and get them out of the json object
foreach (var propertyType in docType.CompositionPropertyTypes)
{
propertyCounterKey++;
var propertyValue = innerContentObject[propertyType.Alias];
if (propertyValue == null) continue;
var innerDataType = _dataTypeService.GetDataTypeDefinitionById(propertyType.DataTypeDefinitionId);
if (innerDataType == null) continue;
var editorAlias = innerDataType.PropertyEditorAlias;
// get the Value mapper for this property (so recurse in)
var mapper = ValueMapperFactory.GetMapper(editorAlias);
if (mapper == null) continue;
var innerValueDisplayName = $"{displayName}: {itemName}: {propertyType.Name}";
// get the source value for the child thing (this could be of any type)
var innerValue = mapper.GetSourceValue(
innerValueDisplayName,
editorAlias,
propertyValue.ToString(),
culture);
if (innerValue != null)
{
// add this child property value to our child value
docTypeTranslationValue.InnerValues.Add(propertyCounterKey.ToString(), innerValue);
}
}
// add the doctype translation value to our main translation value
translationValue.InnerValues.Add(itemKey, docTypeTranslationValue);
}
return translationValue;
}
/// <summary>
/// From the TranslationValue (tree) produce the RAW value that will
/// be put back into the Content Item for this property.
/// </summary>
/// <param name="propertyTypeAlias">Alias of property (will be a one our Editor values)</param>
/// <param name="sourceValue">The source value we are going to put our values into</param>
/// <param name="value">The Translation Value (tree)</param>
/// <param name="sourceCulture">The Source Language</param>
/// <param name="targetCulture">The Target Language</param>
/// <returns>the RAW value that will be set in the Content Item</returns>
public object GetTargetValue(string propertyTypeAlias, object sourceValue, TranslationValue value, CultureInfoView sourceCulture, CultureInfoView targetCulture)
{
if (sourceValue == null) return sourceValue;
var innerContentString = (string)sourceValue;
var array = JsonConvert.DeserializeObject<JArray>(innerContentString);
if (array == null || !array.Any()) return sourceValue;
foreach (var innerContentObject in array)
{
var docTypeAlias = innerContentObject["icContentTypeAlias"].ToString();
var itemKey = innerContentObject["key"].ToString();
var docTypeTranslationValue = value.GetInnerValue(itemKey);
if (docTypeTranslationValue == null)
continue;
var docType = _contentTypeService.GetContentType(docTypeAlias);
if (docType == null) continue;
int propertyCounterKey = 0;
foreach (var propertyType in docType.CompositionPropertyTypes)
{
propertyCounterKey++;
var alias = innerContentObject[propertyType.Alias];
if (alias == null) continue;
var innerValue = docTypeTranslationValue.GetInnerValue(propertyCounterKey.ToString());
if (innerValue == null) continue;
var innerDataType = _dataTypeService.GetDataTypeDefinitionById(propertyType.DataTypeDefinitionId);
if (innerDataType == null) continue;
var mapper = ValueMapperFactory.GetMapper(innerDataType.PropertyEditorAlias);
if (mapper == null) continue;
var editorAlias = innerDataType.PropertyEditorAlias;
var innerText = (string)mapper.GetTargetValue(editorAlias, alias.ToString(), innerValue, sourceCulture, targetCulture);
if (innerText != null)
{
innerContentObject[propertyType.Alias] = innerText;
}
}
}
return JsonConvert.SerializeObject(array, Formatting.Indented);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment