Localizing Logically for a Global Marketplace

Posted by on October 21, 2011

An often-overlooked (or underestimated) aspect of internationalizing a website is determining how to localize for a given visitor.  You might detect that a visitor is “German” because their Geo IP locates them as connecting from Germany, or because their browser accept language is German.  But what if your detection is faulty… they’re using a shared computer, or on vacation, or the Geo IP is just plain wrong?

At Etsy, we wanted to use a tiny bit of magic to help provide the best localized experience for visitors, while still allowing users control over their experience.  Websites often use too much magic (e.g. automatically setting incorrect localization settings with a difficult-to-find escape hatch) or use too little (e.g. forcing visitors to a lame splash page where they must choose their home country/language from dropdowns).

For a global marketplace like Etsy, localization breaks down into three components:

For a given visitor, localizing to the correct language, region and currency provides the best experience on Etsy.  We spent time understanding our visitors and members, determining the best cues for our detection logic, and created an EtsyLocale helper class to encapsulate all localization-related functionality on the site.

Understand your visitors

We started by examining primary and secondary use cases.

Primary use cases:

Secondary use cases:

Some countries have clear majority preferences for language, but some don’t!  And there are plenty of edge case exceptions to think through for any userbase.  For that reason, we allow language, region & currency to be set independently.


At Etsy, we use a series of cues to determine which language, region & currency to show a user.  In decreasing order of “signal strength”:

We also have ccTLDs (e.g. etsy.de) and subdomains (e.g. de.etsy.com) that we use for marketing efforts and for search indexing (SEO) purposes, which we’ll discuss in a later blog post.


When a visitor comes to Etsy without preferences set, we iterate through the above cues in order, and for each cue we see if there’s a clear mapping between the cue and our set of supported languages, regions and currencies.  Once we’ve computed our best guess for language, region & currency, we show a gentle nag at the bottom of the page:

The nag is persistent, and is in both the detected language and English.  We always nag instead of auto-setting to minimize confusion/surprises (magic). We don’t nag our primary market users (English-speaking users in the US).  All visitors/members have the ability to change their language, region & currency preferences by clicking links in the footer of any page:

We store these preferences as cookie preferences for signed-out visitors.  When a user registers, we migrate these cookie preferences to user preferences.  When a user signs out, we don’t write their language/region/currency preferences back out as a cookie, providing a “clean slate” experience for other users of that browser.  When we add support for new languages/regions/currencies, we treat that as a new “version” of the preferences, re-nagging where appropriate.


We encapsulate all of this logic in an EtsyLocale() object, which is available across our stack, for easy access to the current visitor/member’s language, region and currency, e.g.

if (EtsyLocale::getInstance()->getRegion() == “DE”) {
    include “hello_etsy_berlin_meetup.tpl”;

We make use of Smarty modifiers to format and display prices based on EtsyLocale->getCurrency().  Our translation tools (specifically, translateMsg()) make use of EtsyLocale->getLanguage() to determine which translations to use.

We use PHP’s built-in setlocale() methods for date formatting (including month name translations), number formatting, string alphabetization and so on.  PHP’s setlocale() function has varying support for locale formats.  For example, if an Etsy visitor has German language preferences but French region preferences, we might represent that locale string as “de_FR” in PHP.   However, setlocale() doesn’t understand that we should use German month names and number formatting for “de_FR”.  So, to be safe, we pass in a list of locale strings that setlocale() should attempt to use including a more generic language-only locale—in this case (“de_FR”, “de_DE”).

You get a lot for free with PHP locales, but there’s still a lot of holes to plug.  At Etsy, we needed to develop date formats for each region, e.g. short dates (“Dec 1, 2010” for en-US, “01. Dez. 2010” for de) and long dates (“December 1, 2010” for en-US, “01 décembre 2010” for fr).  Using setlocale() too aggressively for number formatting can cause SQL-incompatible float writing (e.g. “1.234,56” instead of “1,234.56“).  And keep in mind you often need to use multibyte-aware functions in PHP to take advantage of locale settings.

Na, was sagt ihr?

We’d love to hear from you… any examples of well-localized sites, problems you’ve come across, PHP tricks/solutions?  Share with us below. Stay tuned for more about Etsy’s internationalization.

Posted by on October 21, 2011
Category: engineering, internationalization Tags: , , , ,


[…] Localizing Logically for a Global Marketplace « Code as Craft says: October 21, 2011 at 2:38 pm […]

It all makes sense and it sounds like you guys have covered a lot of scenarios. Not setting cookies with languages preferences after sign out is certainly a different approach and once you explain it, I can *almost* appreciate it. However, my first impression when seeing this was ‘oh shoot, my change of language preferences did not work’. Then after signing back in: ‘ah, it’s set to the user preferences…I wonder why’.

I guess my point is… wouldn’t the majority of users most likely use Etsy on the same browser/same computer? and if there were multiple users/multiple computers (picturing an internet cafe type of thing), wouldn’t the majority of those users still have a preference for the language of the country they are in?

Also, just going through the process of signing in/out multiple times and seeing the site changing from English to German (or whatever language you chose) every time is a bit confusing.

I would still think that a session cookie would make it feel more ‘natural’.

[…] Localizing Logically for a Global Marketplace […]

[…] of their growth comes from. Etsy has done some very interesting localisation of their site – see here (yes, they blogged about that too) but I’d like to drill down into the numbers of pages they […]