Fallback languages of xml lang files

Vote:
 

Hi guys

Hopefully a quick easy question. My understanding is that we can provide translations in xml files which are placed in the /lang folder. The files are loaded one by one in alphabetical order and the later file overwriting anything from a previous. So i have created 2 new files:

 

Profile.xml

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<languages>
<language id="en-GB" name="GB">
<profile>

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<languages>
<language id="en-GB" name="GB">
<profile>
<username>Username:</username>
<password>Password:</password>
</profile>
</language>
</languages>

Profile_RU.xml

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<languages>
<language id="en-GB" name="GB">
<profile

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<languages>
<language id="en-GB" name="GB">
<profile>
<username>Имя пользователя:</username>
</profile>
</language>
</languages>

 

Now I now you can use the following methods to retrieve this text:

<EPiServer:Translate runat="server" Text="/profile/password" />

Translate("/profile/password");

 

If I set the fallback languages in Episerver (Russian -> English) then I would expect both the above to retrieve the english for Password, regardless of which language is selected, since Russian does not provide a translation for password. Instead what I am receiving is a message 

[Missing text /Profile/Password for ru-RU]

 

Maybe I have miss understood, and the fallback for the xml files does not work as I expected it to... can anyone confirm how this is meant to work?

I am using EpiServer CMS 5 R2.

 

thanks

#45357
Nov 04, 2010 15:39
Vote:
 

Hi Kamruz!

First off your ID for Profile_RU.xml has the language id of "en-GB".

But unfortunately the Translate control won't perform a fallback to the english language. It will call the LanguageManager.Instance.Translate("/yourPath").

Here's what you can do: use the Translate-method of the LanguageManager-class with the fallback-overload and set the fallback string in markup.

Like so:

<%= EPiServer.Core.LanguageManager.Instance.TranslateFallback("/profile/password", "Password") %>

#45440
Nov 05, 2010 21:45
Vote:
 

And using an approach like that you can chain it to return the en-GB branch instead of a static text, like so:

<%= EPiServer.Core.LanguageManager.Instance.TranslateFallback("/profile/password", EPiServer.Core.LanguageManager.Instance.TranslateFallback("/profile/password", "en-GB")) %>

Or, perhaps preferably, create an extension method which does exactly this (freehand code below, don't be suprised if it doesn't compile ;) ):

// Method can't be called Translate or TranslateFallback since two-string-overloads of those methods already exist.
public static string TranslateWithFallbackLanguageBranch(this LanguageManager mgr, string languagePath, string fallbackLanguageBranch)
{
return mgr.TranslateFallback(languagePath, mgr.Translate(languagePath, fallbackLanguageBranch);
}

#45441
Nov 06, 2010 10:18
Vote:
 
#45442
Nov 06, 2010 10:27
Vote:
 

Awesome!

Though the first code example there Magnus would actually return "en-GB" as a string. It should be the TranslateFallback(string,string,string) overload where the middle string is the worst case scenario fallback. :)

The extension method is really cool, though! And it got me thinking - maybe we can tie it together with the actual fallback language defined in the CMS? This is what Kamruz was expecting it to do. To work!

Here is what I came up with (and I'm stealing some of your code, Magnus... :)):

 

// Method can't be called Translate or TranslateFallback since two-string-overloads of those methods already exist.
        public static string TranslateWithFallbackLanguageBranch(this LanguageManager mgr, string key)
        {
            string fallbackLanguageID = GetFallbackLanguageIDFromCMS();
            return mgr.TranslateFallback(key, mgr.Translate(key, fallbackLanguageID));
        }

 

// Method can't be called Translate or TranslateFallback since two-string-overloads of those methods already exist.      

public static string TranslateWithFallbackLanguageBranch(this LanguageManager mgr, string key)        

{

string fallbackLanguageID = GetFallbackLanguageIDFromCMS();

return mgr.TranslateFallback(key, mgr.Translate(key, fallbackLanguageID));        

}

 

/// <summary>

/// Get the fallback lanuage from the CMS

/// </summary>

private static string GetFallbackLanguageIDFromCMS()

{

// Get PageBase using the current handler

var page = HttpContext.Current.Handler as PageBase;

 

// Get the page fallback language setting from the root page, using the current page's language

        PageLanguageSetting pageLanguageSetting = PageLanguageSetting.Load(PageReference.RootPage, page.CurrentPage.LanguageID);

 

         if (pageLanguageSetting != null)

         {

                // Check if there actually is a fallback language defined

                // If so, use the first one

                if (pageLanguageSetting.LanguageBranchFallback.Length > 0)

                    return pageLanguageSetting.LanguageBranchFallback[0];

         }

         // If there is no fallback language defined then we return the current page's language ID

return page.CurrentPage.LanguageID;

}

 

#45443
Nov 06, 2010 22:30
Vote:
 

Thanks for the replies guys.

@Daniel, yes, sorry the Russian ID should be ru-RU and name RU, I missed that when I copied and pasted the sample xml.

But those are both very useful replies, gives me a bit to think about. Useful link to the labs blog post too. Unfortunately we're using CMS5 so Data Store will not be available, but that makes a lot more sense to me (coming from a Sitecore background) than using XML files.

I like the use of extension methods too. I wonder if we can use .Net Tag Mapping capabilities to define fallback functionality for all <EpiServer:Translate> instances in the project (this is something I have read about, but never used). I think using a combination of these 2 we should be able to set the translations with fallback from both code behind and the aspx pages using existing server controls.

I've requested access to Epicode project so can take a look through the code from the labs link.


On a different note, do you guys know how I retrieve all the Available languages for a particular page? So a particular node (and all it's children inherite) I have set English and Russian to be the available languages. On a different node I have English and Malaysian.

I can retrieve current page language versions for particular node, where the specific language pages have been created. But if, for example, I set the Available Languages to English and Russian, but do not create an Russian version, then only English is returned.

I can also retrieve all available languages for the Sitecore Instance, but in this case I am returned maybe 15 languages (as defined in Admin Mode > Config > Manage Web Site Languages).

Eventually we will end up with a "master site" with all language pages available, and then we can replicate this and turn off languages to customise for a local market.

So I need to retrieve only the Available Languages set in Language Settings for the Site Root Node page... this must be accessible via the API somehow, just can't seem to find where I should be looking.

thanks

#45460
Nov 08, 2010 12:49
Vote:
 

Hi again Kamruz!

The fallback languages can be retrieved from the root-page. To get the root page of an EPiServer CMS site you can use PageReference.RootPage.

Then using EPiServer.DataAbstraction.PageLanguageSetting.Load(PageReference.RootPage, CurrentPage.LanguageID) you get a PageLanguageSetting-object.

This object contains a string array with the fallback-languages (if any) for the language ID of the page you're currently viewing. In my sample code we retrieve the first fallback language for the current page's language. So if you have Russian -> English fallback defined in the CMS you'll get back "EN" as fallback language for the russian version of the page.

You can then use this fallback language ID with LanguageManager. Like so (free-styling it, so it might not compile): LanguageManager.Instance.Translate("/yourKey", LanguageManager.Instance.Translate("/yourKey", PageLanguageSetting.LanguageBranchFallback[0]));

But that's all a bit messy to keep in your code-behind. So as Magnus said it should be put in an extension-method.

I wrote a blog post about it, too: http://blog.bergdaniel.se/post/Using-CMS-fallback-language-for-lang-files.aspx

#45461
Edited, Nov 08, 2010 13:16
Vote:
 

Ha, cool, see you were suitably fired up over the weekend. Good write-up, thanks, I'm mid-way through a whole bunch of other stuff but will implement this soon.

I understood the fallback code which you provided. What I am after i guess is a language switcher, a dropdown with all available languages for a site (we're using Enterprise so each instance of Episerver may host many country/market specific sites).

So in this instance it's not the fallback that I am interested in but the Available Languages for PageReference.StartPage

I guess what I am trying to replicate is the the Page View/Compare With language drop down lists that appear in the top right when you select a page in edit mode.

(this is slightly off topic to what we are discussing, so happy to start a new thread)

 

thanks

#45462
Edited, Nov 08, 2010 13:28
Vote:
 

Thanks!

If you install the Public Templates sample project you can take a peek at the Functions user-control. This contains sample code on how to get the language branches available for the page. This is more dynamic than simply getting the available page languages from the start page since that won't actually tell you if the current page is available in those languages or not.

You could use a generic language-switcher menu with all the available languages for the site (use the same code, only instead of the current page you can use PageReference.StartPage to query the start page of the site).

But doing so (and using that control in a master page) I'd recommend you that the menu transports the visitor to the start page when selecting a new language since we don't know if the current page is available in that language.

Cheers :)

#45464
Nov 08, 2010 14:00
Vote:
 

I'll download and take a look through the suggested samples.

I don't (at this point) care about providing the language switch based on context of current page. I think if the fallback is set up correctly then every page will be available... and rather then redirect user by prefixing the URL (or adding lang querystring variable), I was going to set the "epslanguage" cookie. This should ensure that fallback rules are correctly adhered to (and I can then just "refresh" the current page).

Problem I have with using language branches (from my initial trials so far) is as follows...

So we create a master "base" site that holds all possible language version, so far English, Russian and Malaysian (we will add more in the future). We create a duplicate of this base site for each country/market specific site and turn off languages that should not be available, eg.

- Root Folder
-- Base Master Site (English / Russian / Malaysian)
-- Russian Site (English / Russian)
-- Malaysian Site (English / Malaysian)

Following code only gives me languages for pages has been specifically created... in this instance en-GB, ru-RU and ms-MY, no matter which page I point at (StartPage or CurrentPage). This is because the base site includes languages versions for al, these to start with.

var languageBranches = EPiServer.DataFactory.Instance.GetLanguageBranches(CurrentPage.PageLink);

Reading through your blog gave me a pointer and I have the following:
var startPage = EPiServer.DataFactory.Instance.GetPage(new PageReference(PageReference.StartPage.ID));
var pageLangSettings = EPiServer.DataAbstraction.PageLanguageSetting.Load(startPage.PageLink);

I can now always get the "Available Languages" set for a site, regardless of whether the page has been created in a given language.

 

thanks

Kam

 

 

 

 

thanks            var rootPage = EPiServer.DataFactory.Instance.GetPage(new PageReference(PageReference.StartPage.ID));

            var rootPageLangs = rootPage.PageLanguages;
            var rootPagelangBranches = EPiServer.DataFactory.Instance.GetLanguageBranches(rootPage.PageLink);

            var pageLangSettings = EPiServer.DataAbstraction.PageLanguageSetting.Load(rootPage.PageLink);Readinf 

 

thanks

 

 

#45467
Nov 08, 2010 15:50
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.