Today I needed to create a UserControl to allow a user to select to view the current page from a list of enabled languages. To begin with I thought it would be a fairly easy task, by simply calling GetLanguageBranches() in the DataFactory class. However this ONLY returns the versions of the page that have been translated, which didn't suit me as our requirement was that ALL (enabled) languages should be displayed in the language selector, and if a language version doesn't exist for the specific page then the fallback language be used.
So next I tried looping through the results from EPiServer.DataAbstraction.LanguageBranch.ListEnabled(); This seemed to be just what I needed, so I set about looping through all the languages, displaying a hyperlink for each, with the Text being the name of the language. The NavigateUrl property was much trickier - why is nothing ever simple!
So next I set about trying to return a language specific version of a page for each of my enabled languages, at first I tried using:
EPiServer.DataFactory.Instance.GetPage(
new LanguageSelector( [Language code here] )).LinkURL
This caused two problems, firstly this only works if the page exists in that language, with a LanguageNotFound exception thrown otherwise. So in the Catch block I tried:
EPiServer.DataFactory.Instance.GetPage(
LanguageSelector.FallBack( [Language code here] )).LinkURL
Much to my annoyance however, it always rendered to the currently selected language. My first thought was EPiServer's TemplatePage or a ControlAdapter were causing this when they generate the "FriendlyUrl", however while debugging I realised that the LinkUrl property of the PageData class had the incorrect language code as part of the query string. So it must use the current culture when generating the URL string, regardless of the actual page.
Enter Steve, who suggested I try setting the culture to that of the SPECIFIC language before getting a reference to the page and getting it's LinkUrl property, and bingo it worked! The only thing to remember is to make sure I set the culture back to the correct one at the end of the loop to make sure I didn't break anything further down the response.
Here's the code. I've not included the code listing for the LanguageItem class to keep the post short, but you should get the gist of what's going on...
if (!IsPostBack)
{
//Create a list to hold LanguageItem's (which simply has 'Name'/'Url'/'ImageUrl' properties)
List<LanguageItem> langs = new List<LanguageItem>();
//Get the current culture as we'll need it later
string currentCulture = EPiServer.Globalization.GlobalizationSettings.CultureLanguageCode;
//Loop through every enabled language
foreach (LanguageBranch lang in EPiServer.DataAbstraction.LanguageBranch.ListEnabled())
{
//Set the culture to the language of the link being constructed.
EPiServer.Globalization.ContentLanguage.Instance.SetCulture(lang.LanguageID);
langs.Add(new LanguageItem(
//The name of the language
lang.Name,
//Get the current page (but as we've set a new culture it will get the
//relevant lanaguage if it exists, or the fallback if doesn't.
EPiServer.DataFactory.Instance.GetPage(CurrentPage.PageLink).LinkURL,
//Finally generate the url to the Language's Image (e.g. a flag)
string.Format("~/App_Themes/{0}/Images/Languages/{1}.gif", Page.Theme, lang.LanguageID)));
}
//Finally set the culture back to the what it was at the beginning.
EPiServer.Globalization.ContentLanguage.Instance.SetCulture(currentCulture);
//Set the LanguageItem list as the DataSource for the repeater and bind
rLanguages.DataSource = langs;
rLanguages.DataBind();
}
If anyone happens to know of a 'better' way of doing this please let me know... i spent ages trying to get it to work, and sadly EPiServer's documentation was non-existent. I also couldn't find any blogs/articles on how to do it, which is why i decided to share it with you all...