Sitecore Multilingual Sites: Single Domain vs. Multiple Domain Implementation

Before we get into the implementation, let me start by saying that this is more of a high-level marketing decision than a technical one.   The important thing is from a technical side – it can be done. This post should help determining which option is right for you and your organization.  You may need to involve a marketing person in helping you obtain the answers needed.  If you need mental preparation to deal with your marketing team, go through a Dilbert calendar.

Corporate Identity

Do your global sites have their own identity? If so, multiple domains may be the way to go – especially as far as search engine optimization (SEO) is concerned.  If there are search engine marketing (SEM) campaigns being strategized and/or individual content campaigns being designed for each site, the campaigns may end up easier to manage if you have multiple domains (e.g. mysite.com, mysite.co.uk, mysite.com.fr).

You can also use subdomains, which may be less costly from an SSL certificate perspective, discussed below, but there may be cultural considerations.  If you are going to have a large audience in UK, for example, where the dominant domain suffix is .co.uk, how many will know to access their localized site using uk.mysite.com versus mysite.co.uk? How many subdomains can you name at the top of your head?

SSL

If the multiple-domain setup is the chosen route and you are planning to collect user data such as registration information, credit card, or any other sensitive information that may need to be served via the https protocol, you will need to decide what kind of certificate you will need.  If you are doing subdomains (e.g. france.mysite.com, spain.mysite.com, etc.), you may be able to purchase a wildcard certificate that will work for all sites ending in *.mysite.com.  This may end up less costly in the end than purchasing individual SSL certificates for each domain, but there are the cultural questions to consider from above.

From an IIS perspective, if a subdomain is your ticket, you are able to host the sites from a single IIS instance.  For separate domains, you will need to set up separate IIS sites pointed to the same location.  In addition, if you are hosting the sites from the same IP, you will need to set up SSL bindings using IIS Admin Tools.  The detailed step-by-step commands are outlined in this MSDN article: http://bit.ly/bOtGXB

Multiple Domain Implementation in Sitecore

The good news is Sitecore makes it real easy to implement the multiple-domain scenario.  All that is required are some minor tweaks to the web.config and some optional code to implement depending on how you form your links.  I will go into detail in the a post shortly following this one.

On the other hand, if all you are doing is providing a translated version of your site in multiple languages with minor content differences, the single domain implementation may be better for you, also making the SSL problem easier to solve with just a single certificate.  In addition, no web.config tweaking is necessary.  You are ready to go out of the box.

Tutorial: Refresher on Sorting Generics in C# – IComparable & IComparer

I thought I’d post a quick refresher for sorting Lists<> and generics since it will be used in the post about working with Sitecore Fast Query.

There are a lot of ways of sorting items you get back from Sitecore, including even implementing a bubble sort in the code-behind aspx.cs file.  That may work for a quick prototyping exercise; however, when working with enterprise class systems, why not leverage the tools C# gave you to create elegant and robust code by creating line-of-business model objects and using a C# List<T> that already comes with sort functionality (provided you define the rules on how to compare your objects)?

IComparable

If you want to your objects to be sortable, you have to make sure they implement the IComparable method, otherwise when you try to do a List<T>.Sort() on them, you will get an exception.  To implement the IComparable class, you will need to implement the CompareTo() method, which essentially describes how to compare two objects.  If you compare your objects alphabetically, you can take advantage of the String.CompareTo() method here.  Take a look at the code example below using a Movie object.

public class Movie : IComparable
{
public int YearReleased { get; set; }
public string MovieTitle { get; set; }

//need to implement this as a result
//of declaring the IComparable interface
int CompareTo(Movie otherMovie)
{
return MovieTitle.CompareTo(otherMovie.Title);
}
}

IComparer

When you implement the IComparable interface and the CompareTo method, that is the default sort method.  When you want to create additional properties on which to sort, this is where the IComparer interface comes in.   For every method on which you will want to sort, you will have to create a class that implements the IComparer interface.  So, if you wanted to create two sorts – ascending and descending – on the year the movie was released, you will need two classes that implement the IComparer interface.  With this particular example, we can create these classes as nested.

public class Movie : IComparable //main class
{
public int YearReleased { get; set; }
public string MovieTitle { get; set; }

public class SortByYearReleasedAscending : IComparer
{
int Compare(Movie a, Movie b)
{
var compareResult = a.YearReleased - b.YearReleased;

return ( (compareResult == 0) ? 0 : compareResult / Math.Abs(compareResult) );

}
}

public class SortByYearReleasedDescending : IComparer
{
}
}

In case I lost you in the Compare() method, I am all about C# shortcuts (thanks to ReSharper) and didn’t feel like writing this out:

if (a.year > b.year)
return 1;
if (a.year < b.year)
return -1;
else
return 0;

Since the year is an integer, we can just take the difference. If the value on the left is bigger, the result will be positive, otherwise negative. At that point, we will need to return 1, -1, or if it’s the same, the result is 0. To get our result down to a 1 (positive or negative), we simply divide by the absolute value of the result, but not before we check if it’s 0 to bypass the divide by zero error.

And that’s all there is to it. To piece it all together, if you have a List<movieList>, you can do a sort on it using movieList.Sort() which will use the default IComparable.CompareTo method, or you can specify how you want it sorted by passing in the IComparer component, like movieList.Sort(new movieList.SortByYearReleasedAscending())

Questions or comments – drop me a line.

Sitecore Multilingual Sites: Item Versions & the API

In this example, let’s assume we are working with Sitecore content tree with 2 languages, English and French.

Suppose you have a product, represented by a Sitecore item, that was carried at one point by US but then discontinued, and is carried by France. The item hierarchy would look like the following
- Item {ID: some arbitrary GUID}
– English (unpublished)
– French (published)

Now, suppose you are on the English site getting a collection items using a call like Database.GetItems(“some query”) that will return Items of which this product is a part of. Even though it is unpublished, it will still return an Item object. Just this find alone resulted in hours if not days of code rewrite on my part to prep the site for global rollout!

The reason for this is that the item object and its core properties are “Shared” across languages.

The solve: check for Item.Versions.Count being at least 1. Take a look the most common code scenario using a foreach statement:

foreach(var item in mySitecoreItemCollection)
{
     if(item.Versions.Count == 0); continue;

     lblHeadline.Text = FieldRenderer.Render(item,"Headline");
     // ... //
}

If you knew immediately what the continue keyword did from your OOP 101 class, give yourself a gold star.

Developing Multilingual Sites in Sitecore: A Series

I’m working on rolling out a site for my company, developed in Sitecore, across the globe to our international partners.

While the Sitecore documentation outlines the basics, there have been a lot of lessons learned trying to perfect a robust enough codebase to ensure maximum flexibility in features. The basic goal is to allow the maintenance of content for our partners independently without having to touch and recompile the code.

In the posts following, I will talk in detail about gotchas I’ve encountered along the way and will be presenting some code samples as I go along.

Click on the ‘sitecore series’ tag at the bottom of this article to see all related posts