2
votes

I have a number of PDFs in English language. I have web pages in English and German lang.

If in a German Page I want to display PDF of English lang, it is not possible as that German version PDF is not available, so I tried to do fallback for media library item, even then no help.

So can someone please tell me any alternative for this.

NOTE: I don't want to upload english document in German version, as there are other languages available and customers cannot upload those many times in all lang.

I need to upload a document in Only English but display in all other Languages irrespective of that document is there in that lang or not.

It's ok even if I need to make changes through code.

Thanks in advance

3

3 Answers

0
votes

There are a couple of ways to do this. You can do it in the code for your rendering, or you can use the language fallback module from the Sitecore marketplace.

To do it in code you would need to create a new MediaProvider. Create a class that inherits from Sitecore.Resources.Media.MediaProvider and override the protected virtual MediaData GetMediaData(MediaUri mediaUri) method.

This method gets the sitecore item for the context language or the language in the Uri. So you can implement the fall back here:

public class MediaProviderWithFallback : Sitecore.Resources.Media.MediaProvider
{
    protected override Sitecore.Resources.Media.MediaData GetMediaData(Sitecore.Resources.Media.MediaUri mediaUri)
    {
        Assert.ArgumentNotNull((object)mediaUri, "mediaUri");
        Database database = mediaUri.Database;
        if (database == null)
        {
            return null;
        }
        string mediaPath = mediaUri.MediaPath;
        if (string.IsNullOrEmpty(mediaPath))
        {
            return null;
        }
        Language language = mediaUri.Language;
        if (language == null)
        {
            language = Context.Language;
        }
        Sitecore.Data.Version version = mediaUri.Version;
        if (version == null)
        {
            version = Sitecore.Data.Version.Latest;
        }
        Sitecore.Data.Items.Item mediaItem = database.GetItem(mediaPath, language, version);
        if (mediaItem == null)
        {
            return (MediaData)null;
        }
        // Check for language fallback
        if (mediaItem.Versions.Count == 0)
        {
            // Workout your language fallback here from config or sitecore settings etc...
            language = Language.Parse("en");
            // Try and get the media item in the fallback language
            mediaItem = database.GetItem(mediaPath, language, version);
            if (mediaItem == null)
            {
                return null;
            }
        }
        return MediaManager.Config.ConstructMediaDataInstance(mediaItem);
    }
}

Please note - this is untested code. You should store your fallback in config or modify the language template in sitecore.

Once you have that class you will need to update your web.config to use your provider over Sitecores. So find this section in the web.config and change the type to be your class and assembley:

    <!-- MEDIA PATH -->
<mediaPath defaultProvider="default">
  <providers>
    <clear />
    <add name="default" type="Sitecore.Resources.Media.MediaPathProvider, Sitecore.Kernel" />
  </providers>
</mediaPath>
1
votes

Which template are you using to upload your PDF? If you are using /sitecore/templates/System/Media/Unversioned/Pdf then this inherits from /sitecore/templates/System/Media/Unversioned/File and the blob field for this is marked as shared anyway:

File Template

Shared fields are shared across language versions, so if you upload an English PDF and link to that same media item from a German item then it will link to the original English PDF.

In Sitecore, when adding a field to a template, there's a checkbox called "shared". What's it for?

0
votes

It's best practice to try to identify whether media will need to be versioned ahead of time. If you know media is going to need to be versioned based on language, you should make sure to update in your web.config the following attribute:

<!--By default, Media items are not versionable and the below setting is set to false in the web.config.  
    If you upload an image in one language, it will persist across all language versions.
    If you change this to true, then versioning will apply and you would have to set the media item into all language versions, 
    or enable fallback, but if enforce version presence is turned on and media template guids are included in EnforceVersionPresenceTemplates, 
    then you'll have to make sure all language versions at least exist-->
  <setting name="Media.UploadAsVersionableByDefault">
    <patch:attribute name="value">true</patch:attribute>
  </setting>

Alex Shyba's Partial Language Fallback module will successfully work with this. I would recommend making sure not to enforce version presence on any media templates (don't want to force admins to have to create blank language versions). Then they can create english versions and then only create a language version when they need to override it.

You will need, in the case of using partial language fallback, to make sure the enable fallback checkboxes are checked on the media versionable template fields.

I also recommend updating the media provider so that it embeds language into the media url so that caching doesn't come into play. EG: if you create a pdf named Directions.pdf and it loads at www.site.com/media/Directions.pdf, when you switch between languages, it very well could cache it. So you would want to update the media provider to encode the media url with the context language.

You can see a demo here: https://github.com/Verndale-Corp/Sitecore-Fallback-FullDemo

public class CustomMediaProvider : MediaProvider
{
    public override string GetMediaUrl(MediaItem item, MediaUrlOptions options)
    {
        Assert.ArgumentNotNull((object)item, "item");
        Assert.ArgumentNotNull((object)options, "options");

        string result = base.GetMediaUrl(item, options);

        // Added by Verndale, check if language should be embedded
        UrlOptions urlOptions = UrlOptions.DefaultOptions;
        urlOptions = LanguageHelper.CheckOverrideLanguageEmbedding(urlOptions);
        if (urlOptions.LanguageEmbedding == LanguageEmbedding.Always && options.UseItemPath)
        {
            result = "/" + Sitecore.Context.Language.Name.ToLowerInvariant() + Sitecore.StringUtil.EnsurePrefix('/', result);
        }

        return result;
    }

    public static UrlOptions CheckOverrideLanguageEmbedding(UrlOptions urlOptions)
    {
        var thisSite = Sitecore.Context.Site;

        if (urlOptions.Site != null)
            thisSite = urlOptions.Site;

        if (!String.IsNullOrEmpty(thisSite.SiteInfo.Properties["languageEmbedding"]))
        {
            if (thisSite.SiteInfo.Properties["languageEmbedding"].ToLower() == "never")
                urlOptions.LanguageEmbedding = LanguageEmbedding.Never;
            else if (thisSite.SiteInfo.Properties["languageEmbedding"].ToLower() == "always")
                urlOptions.LanguageEmbedding = LanguageEmbedding.Always;
            else if (thisSite.SiteInfo.Properties["languageEmbedding"].ToLower() == "asneeded")
                urlOptions.LanguageEmbedding = LanguageEmbedding.AsNeeded;
        }

        return urlOptions;
     }
 }