Virtual Happy Hour this month, Jun 28, we'll be getting a sneak preview at our soon to launch SaaS CMS!

Try our conversational search powered by Generative AI!

Image

Vote:
 

Hi Everyone,
I'm running into an issue. Our website requires translations for everything, so adding culter specific properties is a must. Anyway, I'm looking at adding a culterspecific/translatable property for an image description and alt text. I've created an ImageFile class for this and everything works well however, it appears there an issue with image classes and any CultureSpecific properties aren't translatable. 

Do you guys know of any way around this? Please see the images / code below.

-Paul

#149994
Jun 10, 2016 20:32
Vote:
 

Here's the code for my image model class.

using CMS.Business.Helpers;
using CMS.Business.Rendering;
using EPiServer.Core;
using EPiServer.DataAnnotations;
using EPiServer.Framework.DataAnnotations;
using EPiServer.Shell.ObjectEditing;
using System.ComponentModel.DataAnnotations;

namespace CMS.Models.Media
{
    [ContentType(GUID = "0A89E464-98DF-449F-AEA8-2BF774AB8730")]
    [MediaDescriptor(ExtensionString = "jpg,jpeg,jpe,ico,gif,bmp,png")]
    public class ImageFile : ImageData 
    {
        /// <summary>
        /// Gets or sets the copyright.
        /// </summary>
        /// <value>
        /// The copyright.
        /// </value>
        public virtual string Copyright { get; set; }

        /// <summary>
        /// Gets or sets the alt text of the image.
        /// </summary>
        /// 
        [Display(Name = "Alt Text")]
        [CultureSpecific]
        public virtual string AltText { get; set; }

        /// <summary>
        /// Gets or sets the description of the image. (Used especially in Products)
        /// </summary>
        [CultureSpecific]
        public virtual string Description { get; set; }

        /// <summary>
        /// Gets or sets the image type
        /// </summary>
        [Display(Name = "Image Type")]
        [BackingType(typeof(PropertyNumber))]
        [EditorDescriptor(EditorDescriptorType = typeof(EnumEditorDescriptor<ImageTypes>))]
        public virtual ImageTypes ImageType { get; set; }
    }
}



#149995
Jun 10, 2016 20:33
Vote:
 

Here's an image showing that the list of languages is missing.


Here's an image showing in the languages widget that translations aren't supported.

#149996
Jun 10, 2016 20:37
Vote:
 

Probably because imagedata doesn't implement ILocalizable? I may be wrong though after 5 beers or so...

#150129
Jun 10, 2016 21:52
Vote:
 

That is correct Daniel. But there are ways to get around this.

#150133
Jun 11, 2016 1:10
Vote:
 

Hi, Paul,

Take a look at this blogpost: https://gregwiechec.com/2015/07/localizable-media-assets/ by Grzegorz.

BR,
Marija

#150171
Jun 13, 2016 12:06
Vote:
 

Yup, that's the way around it :)

Nice implementation of ILocalizable there...

#150172
Jun 13, 2016 12:08
Vote:
 

Hey Guys,

I've gotten wrapped up in some other things and am just getting back to investigating this issue. I've looked at the link Marija shared, and this is great. I did however experiance two issues with this code however.

The first issue is an issue with using the interface ILocalizable.

The second issue is with the LoadMasterContent() method. 

Do you guys have any idea what could be causing these issues? This is a literal copy and paste from the link you sent and I get these errors. Any ideas?

#151268
Jul 13, 2016 17:17
Vote:
 

I was able to fix the ILocalizable issue by changing the MasterLanguage property from public IEnumerable ExistingLanguages { get; set; }, to public IEnumerable<CultureInfo> ExistingLanguages { get; set; }. 

I'm still having isues with that LoadMasterContent() method though.

#151270
Jul 13, 2016 17:27
Vote:
 

I'll take a look later today if noone beats me to it :)

Sounds interesting!

#151271
Jul 13, 2016 17:28
Vote:
 

Have you implement LoadMasterContent in following way

public static class LocalizableMediaDataExtensions

    {
        public static T LoadMasterContent<T>(this ImageFile imageFile) where T : IContent
        {
            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            var content = contentRepository.Get<T>(imageFile.ContentLink.ToReferenceWithoutVersion(), new LanguageSelector(imageFile.MasterLanguage.Name));
            return content;
        }
    }
Otherwise try this.LoadMasterContent<ImageFile>()

Or can be done like this

        private ImageFile  LoadMasterContent(ImageFile imageFile

        {
            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            var content = contentRepository.Get<T>(imageFile.ContentLink.ToReferenceWithoutVersion(), new LanguageSelector(imageFile.MasterLanguage.Name));
            return content;
        }
var blob = LoadMasterContent(this);


#151277
Jul 13, 2016 17:55
Vote:
 

Thanks K Kahn. With your help I was able to get the class to build, however I'm now getting an error when calling, or attempting to edit any image.

This is my code.

using CMS.Business.Helpers;
using CMS.Business.Rendering;
using EPiServer;
using EPiServer.Core;
using EPiServer.DataAnnotations;
using EPiServer.Framework.Blobs;
using EPiServer.Framework.DataAnnotations;
using EPiServer.ServiceLocation;
using EPiServer.Shell.ObjectEditing;
using System.Collections;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System;
using System.Collections.Generic;

namespace CMS.Models.Media
{
    [ContentType(GUID = "0A89E464-56D4-449F-AEA8-2BF774AB8730")]
    [MediaDescriptor(ExtensionString = "jpg,jpeg,jpe,ico,gif,bmp,png")]
    public class ImageFile : ImageData, ILocalizable
    {
        public IEnumerable<CultureInfo> ExistingLanguages { get; set; }
        public CultureInfo MasterLanguage { get; set; }

        public virtual string Copyright { get; set; }

        [CultureSpecific(true)]
        public virtual string Title { get; set; }

        [CultureSpecific(true)]
        public virtual string AlternateText { get; set; }

        public override Blob BinaryData
        {
            get
            {
                if (ContentReference.IsNullOrEmpty(this.ContentLink))
                {
                    return base.BinaryData;
                }
                if (this.Language.Name == this.MasterLanguage.Name)
                {
                    return base.BinaryData;
                }

                return this.LoadMasterContent<ImageFile>().Thumbnail;
            }
            set
            {
                base.BinaryData = value;
            }
        }

        [ImageDescriptor(Height = 48, Width = 48)]
        public override Blob Thumbnail
        {
            get
            {
                if (ContentReference.IsNullOrEmpty(this.ContentLink))
                {
                    return null;
                }
                if (this.Language.Name == this.MasterLanguage.Name)
                {
                    return base.Thumbnail;
                }

                return this.LoadMasterContent<ImageFile>().Thumbnail;
            }
            set
            {
                base.Thumbnail = value;
            }
        }
    }

    public static class LocalizableMediaDataExtensions
    {
        public static T LoadMasterContent<T>(this ImageFile imageFile) where T : IContent
        {
            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            var content = contentRepository.Get<T>(imageFile.ContentLink.ToReferenceWithoutVersion(), new LanguageSelector(imageFile.MasterLanguage.Name));
            return content;
        }
    }
}



#151279
Jul 13, 2016 18:07
Vote:
 

When editing any image now, I get this error.
 

If I open up chrome developer tools, I see it's erroring when pulling in this url... http://localhost:54326/EPiServer/shell/Stores/context/?uri=epi.cms.contentdata%3A%2F%2F%2F11566&dojo.preventCache=1468424787006

Looks like this...

#151280
Jul 13, 2016 18:10
Vote:
 

try this (with assumption you just requires multlingual, Alt an desc)

public static T LoadMasterContent<T>(this ImageFile imageFile) where T : IContent
        {
            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            var content = contentRepository.Get<T>(imageFile.ContentLink);
            return content;
        }
#151286
Edited, Jul 13, 2016 21:10
Vote:
 

Tried it now. Works great if you create a class from scratch and start to upload file. If you modify an existing ImageFile class however you run into issues like the above. So workaround is to create a new content type from scratch with a new guid and use that one.

I tested this and it worked well:

[ContentType(GUID = "0A89E464-56D4-449F-AEA8-2BF774AB8745")]
    [MediaDescriptor(ExtensionString = "jpg,jpeg,jpe,ico,gif,bmp,png,pdf")]
    public class LocalizedImageFile : ImageData, ILocalizable
    {
        public IEnumerable<CultureInfo> ExistingLanguages { get; set; }
        public CultureInfo MasterLanguage { get; set; }

        public virtual string Copyright { get; set; }

        [CultureSpecific(true)]
        public virtual string Title { get; set; }

        [CultureSpecific(true)]
        public virtual string AlternateText { get; set; }

        public override Blob BinaryData
        {
            get
            {
                if (ContentReference.IsNullOrEmpty(this.ContentLink))
                {
                    return base.BinaryData;
                }
                if (this.Language.Name == this.MasterLanguage.Name)
                {
                    return base.BinaryData;
                }

                return this.LoadMasterContent<LocalizedImageFile>().BinaryData;
            }
            set
            {
                base.BinaryData = value;
            }
        }

        [ImageDescriptor(Height = 48, Width = 48)]
        public override Blob Thumbnail
        {
            get
            {
                if (ContentReference.IsNullOrEmpty(this.ContentLink))
                {
                    return null;
                }
                if (this.Language.Name == this.MasterLanguage.Name)
                {
                    return base.Thumbnail;
                }

                return this.LoadMasterContent<LocalizedImageFile>().Thumbnail;
            }
            set
            {
                base.Thumbnail = value;
            }
        }
    }
 
    public static class LocalizableMediaDataExtensions
    {
        public static T LoadMasterContent<T>(this LocalizedImageFile imageFile) where T : IContent
        {
            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            var content = contentRepository.Get<T>(imageFile.ContentLink.ToReferenceWithoutVersion(), new LanguageSelector(imageFile.MasterLanguage.Name));
            return content;
        }
    }

You also have a small typo in your code above for the BinaryData where you return the thumbnail btw...need to change that. 

I removed a few extensions from the original ImageFile class I had and added them instead to my LocalizedImageFile, added a new language to Alloy site and tried it out. Np...

There is probably some issue with routing to the blob file if you use the existing class and make that ILocalizable after the file has been uploaded. Probably possible to fix if you really have to but creating a new contenttype for localized media should work out most of the time I guess.

#151304
Edited, Jul 14, 2016 15:41
Vote:
 

Thanks for the help on this guys! You were all super helpful, thanks! :)

#151405
Jul 20, 2016 16:54
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.