Developing an International Site
Summary: This article describes best practices for supporting multiple languages and currencies when you develop a Web site for an international audience.
This article describes best practices for supporting multiple languages and currencies when you develop a Web site for an international audience. Your goal should be to make it easy for your customers to change language or currency at any time without losing context (that is, without being redirected to another page that contains different content). There are several ways to implement multiple languages and currencies. Which one you choose depends on your preferences and on project constraints.
Most companies would benefit from the ability to offer customers a choice of languages in which to interact with their sites. However, many companies either ignore the issue or address it by deploying several versions of their sites. For example, Amazon.com provides several versions of its site (including Amazon.de and Amazon.nl).
If all versions of a site could be updated simultaneously, the existence of multiple versions would not be a problem. However, in most cases, each version must be updated separately, which can cause the versions to differ significantly. For example, the English version of Amazon.com is much richer in functionality than the German and Dutch versions. Such significant differences can cause confusion for the project team and make the site difficult to manage. This section discusses ways to create a single, multilingual site.
There are two types of language-dependent strings used in e-commerce sites:
- Product information
- Site information (including HTML content in advertisements and discount descriptions)
Product information strings are the collections of language-dependent properties pertaining to products, such as name and description. Product information should be stored in the product catalog and should be available in all the languages your site supports because a multilingual product catalog is much easier to manage than separate catalogs for each language.
To manage language-dependent properties, simply adjust your code for each property to identify the language in which it will appear. For example, your product might contain a property called short_description, which you want to display in English, French, and Dutch. To do this, you can rename short_description as short_description_en for the English version, short_description_fr for the French version, and short_description_nl for the Dutch version. When the page displays the product description, you can then adapt your code to select the property short_description plus the language code (en for English, fr for French, or nl for Dutch). The language code can be a parameter that the user enters or a property of the user profile.
Site information is the collection of strings that the site must display, such as "Product of the Week," "Search," and "OK." You can store the whole set of displayable strings in different languages in a database or in an Extensible Markup Language (XML) file. XML is a better choice than HTML because it is more portable. For example, you can send an XML file to a translator by e-mail, if necessary.
The Global.asa file reads the XML file when the application starts. The strings are stored in the Microsoft® Commerce Server 2000 MessageManager object, which has application scope, thus ensuring that every server in your Web farm has its own copy of the string set for every language.
When a string must be displayed on the site, you can retrieve it from the MessageManager object with the following method call:
To speed up page execution, you can store strings that are displayed often, like menu bars (which are concatenations of individual strings), in the CacheManager object for later retrieval. When you do this, the MessageManager object needs to look them up only once.
You can use the same technique for other displayable strings, such as descriptions of discounts that you can't change in Commerce Server Business Desk.
The Commerce Server Solution Sites use the CacheManager object extensively. Essentially, the CacheManager object is an extended Dictionary object, which stores strings in name/value pairs.
If you examine the Solution Site code, you'll see that the name part of a name/value pair is called a cache key. If you decide to implement multilingual pages, you will need to make the cache key generation language specific. You can do this with the following code:
sCacheKey = sCatalogName & sCategoryName & CStr(iPageNumber) & sLanguageCode
Using language-specific cache key generation makes the language code part of the cache key, so that the CacheManager object can detect which language to display.
Choosing the Language
A basic site scenario, often used in European sites, is to offer users a choice of language on the first visit. A user must click a link or a button to access the site in the chosen language. The choice is then either stored as a property in the user profile or stored in a cookie on the user's computer so that the appropriate language appears immediately whenever the user revisits the site.
Some sites use another scenario in their sites: They try to guess a user's language preference by looking up the country extension from the Internet Protocol (IP) address. For example, if the user is surfing from proxy.myprovider.co.uk (a U.K.-based provider), these sites assume that the user speaks English. This is often a convenient strategy, but it is not necessarily the most accurate. For example, many tourists browse the Web from cybercafés when they visit other countries. Many other users browse from a .com, .net, or similar address that doesn't have any obvious relationship to a particular language.
In a third scenario, sites can check the default language setting for users who use Microsoft® Internet Explorer. The drawback to this scenario is that many users install the English version of Internet Explorer and do not change the language settings, even though English might not be their native language. The issue of cybercafés arises in this scenario, too. If a cybercafé using Internet Explorer sets local language parameters, the sites that use this scenario will assume that travelers logging on from that location want to view pages in that language rather than their own.
The best solution for most sites is probably the first scenario: Let the user choose a language that is then saved in the user's profile. The next time the user logs on from any location, the site will automatically switch to the user's preferred language.
Multilingual sites should enable the user to change from one language to another on every page. Some sites do this with a drop-down list from which users can select a new language on any page on the site. Some sites display images of national flags that users can click to select the corresponding language.
Some multilingual sites allow changes in language only on the site's home page, which means that users must return to the home page from other locations in the site to select a new language. This method is easy to implement, but is less user-friendly than letting users change languages on any page to retain the context of the operation being performed.
There are four ways to encode language context:
- Use a client-side cookie to store the active language code.
- Encode the language code in the URL.
- Store the language preference in the user profile.
- Use pre-generated pages.
The method you use depends on project constraints and developer preferences.
Using a Client-Side Cookie with Language Codes
Using a client-side cookie is the easiest way to encode a language context, where permissible. To do this, you store a language code (en, fr, nl, and so on) in the cookie and read the cookie on every page that displays language-dependent strings. You can even make the cookie persistent by having it expire on some date far in the future, such as January 1, 2100, so that the site is always aware of a user's language (assuming that the user agrees to make the cookie persistent).
It is best to use this technique only in situations where you can control the acceptance of cookies; for example, proof-of-concept or company-internal projects. If there is a single user whose browser doesn't support cookies, such as a microbrowser in a cellular phone, this technique will fail.
Encoding the Language Code in the URL
You can embed the language code in the URL, similar to the way in which the Solution Sites generate the session ID ticket. This means adapting the GenerateURL function to add the language code to every link you create, so that the site displays the correct language. For example, you must call GenerateURL for every link so that http://commercesitename.tld/mypage.asp becomes http://commercesitename.tld/mypage.asp?lang=nl. Every page can then simply read the lang parameter.
Note You can't encode the language code with static HTML pages, because HTML pages can't pass any input parameters to other pages.
Storing the Language Preference in the User Profile
Another option for encoding language preferences is to keep a user's language in the user profile. Doing this requires that you add a language property to the user profile. You must then update the property if a user changes languages. This is a cost-effective method of storing language preferences, because the only performance cost involved is retrieving and updating the profile.
Using Pre-Generated Pages
If your site contains mostly static HTML pages, using pre-generated pages is another option for encoding language on your site. Pre-generated pages don't need to pass language identification to other pages, because the context of the pages (the directory that the pages are in) provides that capability. Pre-generated pages can link to other pages without providing language information. In addition, pre-generated pages don't need to read cookies, URL parameters, or user profiles to determine which language to display.
To pre-generate your pages in all the languages you support, you can put all your pages in a /source directory and mark all strings that can be pre-generated with delimiters in your Active Server Pages (ASP) code. For example, you might specify the Search button as:
<INPUT TYPE=SUBMIT VALUE="[[=Search]]">
In this fragment,
[[=Search]] is a mnemonic for a word that will be translated. You must write a page generator that reads all the pages in the /source directory, looks up the delimited mnemonics by using the MessageManager object, translates the delimited mnemonics, and saves the translated pages in a language-specific directory. Using the example of a site supporting English, French, and Dutch, you would read pages from /source and generate pages in the /en, /fr and /nl directories. You can automate this process to run once or twice a day, or whenever you update your site.
The page pre-generation approach saves time at run time and does not rely on the CacheManager object. In addition, it can significantly boost performance if your site has many static pages (pages that perform no logic other than to call the MessageManager object to look up strings), because now those pages can become truly static HTML pages rather than ASP pages. Putting those static pages on dedicated servers that serve only static content can enhance performance even further.
The issues related to supporting multiple currencies are similar to, but simpler to solve than, the issues regarding multiple languages. You can support many currencies and let users switch back and forth between them, or you can display prices in all currencies at the same time. For some e-commerce sites, displaying prices in multiple currencies at the same time might be useful, but for the majority of sites, especially business-to-consumer (B2C) sites, the first method is easier.
You should store product pricing information in only one currency (the reference currency), if possible. For example, you can store your prices in U.S. dollars or European euros, and then recalculate prices in other currencies in real time, as needed. To recalculate prices based on the reference currency, you need an exchange-rate table that specifies the rates for other currencies compared with the reference currency. The exchange-rate table should contain the following fields:
- Currency symbol
- International Organization for Standardization (ISO) currency code
- Display format
The following example shows what an exchange rate table might look like.
|Currency symbol||ISO currency code||Exchange rate||Display format|
|$||USD (U.S. dollar)||1.0||####.##|
|£||UKP (U.K. pound sterling)||1.2||####.##|
|F||BEF (Belgian franc)||0.023||######,00|
|€||EUR (European euro)||0.9||####.##|
When your site displays a price, it recalculates the price based on the exchange rate and displays it with the associated currency symbol and display format.
Important If you store search results and product detail pages with the CacheManager object, you must include the currency in the cache key or you will retrieve the wrong results when you try to display pricing in a different currency.
Different Prices for Different Locales
Some projects require different pricing for different locales. For example, a particular car might cost DM 100,000 in Germany, but only $40,000 in the U.S. However, that is locale-specific pricing, not currency-specific pricing. A German customer living in the U.S. should be charged the same price for the car, whether it is viewed in deutsche marks or U.S. dollars.
Different prices for different locales will, in most cases, require explicit pricing in the product properties. You must therefore keep several prices in your catalogs. You can do this by creating custom catalogs with the Catalog Editor module in Business Desk, or by adding locale-specific pricing properties to your catalog schema. The goal is to create inviting, market-oriented pricing that customers find appealing. For example, instead of simply multiplying a U.S. item price of $9.95 by a conversion factor, which can produce an odd price in Belgian francs (such as 457 francs), it is better to create a custom catalog for Belgium that contains a price (such as 450 francs) tailored to the Belgian market.
Different Discounts for Different Locales
The notion of providing different discounts for different locales is similar to maintaining different pricing for different locales. However, locale-specific discounting does not require custom catalogs or multiple price properties. Instead, you can configure the Commerce Server Purchase pipeline and Content Selection pipeline to perform different discounts based on locale. This is not a currency-related issue, although at first glance it might look like one. For more information about Commerce Server pipelines, see Commerce Server 2000 Help.
The issues associated with changing currency are similar to the issues associated with changing language. You can provide an active currency in any of the following ways:
- Encode the currency code in the URL. Use the same GenerateURL function that you use to change languages to include the active currency.
- Store the currency code in the user profile. Storing the appropriate currency code in the user profile is an option, but every page that displays currency information then needs to invoke the user profile. If a user's profile data is already cached, this is a reliable and speedy method that makes the user's settings available from any location.
You can configure a site to use a different language from your development language. For example, you might develop your site in English but want to use a copy of your English site to create a French site. To create a site by using a different language:
- Set the system locale in Microsoft® Windows® 2000. In Control Panel, set the options in Regional Options for the new locale. You must set locale separately for each computer and enable the display and input of text in a given code page. You must also define default settings specific to the locale, such as currency, numeric format, and date and time formats.
- Configure Microsoft® SQL Server™ collation settings. You set SQL Server collation settings when you install SQL Server; you cannot reconfigure them after installation. The collation settings determine which code page and sort orders the database will accept for non-Unicode data. (The database schema determines whether the data is Unicode.)
- Change the following Commerce Server site properties in Commerce Server Manager by using the App Default Config resource:
- Site default locale
- Page encoding charset
- Unit of Measure for Weight
- Currency: Base currency locale
- Currency: Base currency code
- Currency: Base currency symbol
If you plan to display more than one currency, you also need to configure the following properties for each additional currency:
- Currency: Alternate currency options
- Currency: Alternate currency conversion rate
- Currency: Alternate currency locale
- Currency: Alternate currency code
- Currency: Alternate currency symbol
- Currency: Currency display order options
For more information about configuring the App Default Config resource, see the "Configuring App Default Config Resource Properties" topic in Commerce Server 2000 Help.
After you configure the Windows system locale, SQL Server defaults to the corresponding collation. (Code page and sort orders match the locale.) When you configure Commerce Server, the Commerce Server databases support the code page you have configured. You can change any of the settings in the App Default Config resource in Commerce Server Manager.
After you unpack Business Desk or use one of the Solution Sites, the following site configuration properties are based on the system locale, and you should not need to change them:
- Site default locale (formats for numbers and dates).
- Base currency locale.
Note The Base currency symbol and Base currency code properties are not set the same way.
- Page encoding charset (set to the default charset that supports the language associated with the system locale). You use the encoding charset in Business Desk header files to set the charset for each page.
If you unpack a localized site with Commerce Server Site Packager on a system configured for the same locale, you shouldn't have to change any settings unless you display multiple currencies. The Site Packager package includes all other settings. Be sure to review all settings before publishing your site.
For example, if you install an English site on a Korean system, you can enter Korean language characters into Business Desk without making any other changes.
If, however, you want to run a site in a different language on a system configured for your development language—for example, a French site on an English system—you need to reconfigure the following settings:
- Set Default site locale, Base currency locale, and Page encoding charset properties to
- In the BDHeader.asp and BDXMLHeader.asp files, perform the following steps:
<%'@ LANGUAGE=VBSCRIPT CODEPAGE=1252 %>and set the code page to the correct value for French.
The information contained in this document represents the current view of Microsoft Corporation on the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication.
This Article is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, AS TO THE INFORMATION IN THIS DOCUMENT.
Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.
Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.
The example companies, organizations, products, people and events depicted herein are fictitious. No association with any real company, organization, product, person or event is intended or should be inferred.
©2001 Microsoft Corporation. All rights reserved.
Microsoft and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.
The names of actual companies and products mentioned herein may be the trademarks of their respective owners.