Click here to Skip to main content
15,881,709 members
Articles / Web Development / IIS
Article

Localizing Software Applications

Rate me:
Please Sign up or sign in to vote.
2.50/5 (3 votes)
3 Sep 200121 min read 155K   45   14
Introduction to localizing your ASP applications

You are kidding right?

When it comes time to make an application language independent is the time all the sales people cheer and developers hide.  To a salesman localized software means more markets and more sales, to a developer it equals a mind-numbing list of problems. 

One of the main problems is that software is generally never designed from the ground up to include support for changing the language.  Not building from the ground up with this support means that every single piece of code that represents language to the user (buttons, menus, images, prompts, help, text) must be found and altered to support language independence.  This problem multiplies exponentially when you deal with applications that have hundreds of thousands lines of code, which have been poured over and modified constantly by different developers.

Web based E-Commerce applications present the same aforementioned problem, but brings currency issues into the picture.  For each language supported all functionality dealing with currency must be located and modified to support each languages currency denomination.  The currency has to be stored in a way that is easily transferable between all the languages supported whether the user is viewing it in US dollars the stored value must be able to be converted to Pesos , Franks , or Pounds.  The other thing to keep in mind is that currency exchange rates are not static, they change.

Object Orientation to the Rescue

From whatever side you are from (sales or development) you can now see the issues that are present.  If the targeted application was not built with localization in mind there is twice the amount of work to do.  If on the other hand the target application is in design phase we can lay out a plan of action for localization.

Object Oriented Programming (OOP) is a means to encapsulate programming code into pre-defined execution and data.  Instead of having a huge list of functions and variables we can use OOP to take developing large scale (or small) applications easy to understand and implement.  A simple real-world example of object orientation is basic business structure.  Although in small businesses the president knows everyone, what they are supposed to be doing, how they should do it, on a large scale this is not possible.  Breaking this company down object oriented style we can see the following:

Object Employee
Object Manager
Object Vice President
Object President:

Each object has its own properties (attributes) and methods (actions):

Object Employee
           Skill                                    (property)
           Pay                                      (property)
             Responsibilities                       (property)
           Execute                                  (method)
Object Manager
           Skill                                    (property)
           Pay                                      (property)
Responsibilities                                    (property)
Execute                                             (method)
           Collection of Employee Objects           (employees he is responsible for)
Object Vice President
           Skill                                    (property)
           Pay                                      (property)
Responsibilities                                    (property)
Execute                                             (method)
           Collection of Manager Objects            (managers he is responsible for)
Object President:
           Skill                                    (property)
           Pay                                      (property)
Responsibilities                                    (property)
Execute                                             (method)
           Collection of Vice President Objects     (Vice Presidents he is responsible for)

The whole company can now be represented in the following object:

Object Company:
           Incoming                                 (property)
           Outgoing                                 (property)
           President Object                         (property)
           Collection of Vice President Objects     (property)
Collection of Manager Objects                       (property)
Collection of Employee Objects                      (property)

By using Object Orientation (OO) we can execute actions without even knowing who is involved or how it works.  An example is if a President wishes to hand out bonus checks and he has 3000 employees it would be next to impossible for him to evaluate performance on all the employees and hand out the appropriate bonus checks.  By using OO the president simply hands the order over to his Vice President who then passes it on to each manager underneath them which finally gets down to the employee level.  So without knowing anything about the employees or managers a president can do this:

Company -> President -> ExecuteBonusCheckPayments()

And all the employees get appropriate bonus checks.

Moving back to our application we can use OOP to maximize development and implementation of language and currency independence.  By removing the need for a developer to know or care what language the application is using we simplify their development and maximize use of their time to functionality.  Although implementation of localization is a hefty job, once the preliminary pieces of code are in place developers will not need to address it much if at all.  I will be focussing on an ASP E-Commerce application but the theory can easily be transported to any development environment.

Data Representation

Data representation is for developers and translators.  A client using localized software will never see or need to see how data is represented.  Basically data representation is the way we will represent localized data in our code.  The base language for our data representation will be English.  Once the application is created developers will be referencing the data representation of text rather than the actual text, translators will be referencing the text and ignoring the data representation.  Lets take a button that will need to be localized.  The button displays the word "Help" on it, but being localized the word "HELP" in Spanish is "Socorro".  Our data representation is dr_txt_HELP.

In English:

dr_txt_HELP = "Help"

In Spanish:

dr_txt_HELP = "Socorro"

Now our developers could care less what language the help button is in because in the code all they will ever use is the dr_txt_HELP.  This data representation can be used for images as well.

In English:

dr_img_HELP = "Help.jpg"

In Spanish:

dr_img_HELP = "Socorro.jpg"

As you can see this data representation gives us the best of both worlds in programming and translation.  The more languages you support the easier it will be for a translator to look at a text file and translate to the target language.  After the data representation has been defined developers do not have to care which language the application is being viewed in.

Includes

By now we have a clear idea on how data will be represented, now we need to define how that data is incorporated into an application.  We will use include files and object orientation to achieve the desired functionality.  At the highest level we need to know which language we will be displaying, this will be accomplished with a single variable called USING_LANGUAGE.  Each language supported will have an associated value which would be contained in a supported languages file. 

Example of our supported languages file:

LANUGAGE_ENGLISH          = 0
LANGUAGE_SPANISH          = 1
LANGUAGE_FRENCH           = 2
LANGUAGE_CUBAN            = 3

The supported languages file would be included on every page in the web application.  Optimization is of concern when dealing with passing script on the server side so I am going to split each language dependent include into a separate file and place them in separate directories.  This will prevent each pages performance from being hurt by a huge amount of if/then/else statements.  Our directory structure will be as follows:

(root)
           (language files)
                      (localized)

So if we are adding the home page the directory would look like this:

(root)
home.asp
           (language files)
           I_supported_languages.asp
           I_home.asp
                      (localized)
                      I_home_english.asp
I_home_spanish.asp
I_home_french.asp
I_home_cuban.asp

The home.asp in the root is the actual page which will include I_supported_languages.asp and the I_home.asp in the "language files" directory.  The I_home.asp in the "language files" directory will include the appropriate localized file based on our USING_LANGUAGE variable.  Lets take a look at what is inside the I_home.asp file:

Listing of I_home.asp:

<%if USING_LANGUAGE = "LANUGAGE_ENGLISH" then%>
<!--#INCLUDE FILE=" localized /I_home_english.asp" -->
<%elseif USING_LANGUAGE = "LANGUAGE_SPANISH" then%>
<!--#INCLUDE FILE=" localized /I_home_spanish.asp" -->
<%elseif USING_LANGUAGE = "LANGUAGE_FRENCH" then%>
<!--#INCLUDE FILE=" localized /I_home_french.asp" -->
<%elseif USING_LANGUAGE = "LANGUAGE_CUBAN" then%>
<!--#INCLUDE FILE=" localized /I_home_cuban.asp" -->

By looking at the above listing we can see that if before we include the I_home.asp we set the USING_LANGUAGE variable to LANUGAGE_ENGLISH it directs I_home.asp to include the I_home_english.asp file.  What does that do you ask?  Lets take a look inside the I_home_english.asp file and find out:

Listing of I_home_english.asp:

<%
‘ English Data Representations for home.asp 
dr_txt_PAGETITLE      = "Welcome to MyStore.com" 
dr_txt.ABOUT          = "MyStore.com is the ecommerce site of the century. " &_
                        "You will find that  we have only the best goods and services."
dr_txt.SENDEMAIL      = "Send Us Some Email" %>

By including the above listed file we can now access the data representations instead of the actual text.  I mentioned before that our base language would be english, hence why the variables are in english.  By looking at theactual home.asp page you will see how all this comes together.

Listing of home.asp:

<!--#INCLUDE FILE=" language files / I_supported_languages.asp" -->
<% USING_LANGUAGE = "LANUGAGE_ENGLISH" %>
<!--#INCLUDE FILE=" language files / I_home.asp" -->
<center>
<b>
<%=dr_txt_PAGETITLE%>
</b>
<br>
<%= dr_txt.ABOUT %>
<br>
<a HREF=mailto://president@aol.com><%=dr_txt.SENDEMAIL %></a>

The output if viewed through a browser would look like this:

Welcome to MyStore.com

MyStore.com is the ecommerce site of the century. You will find that we have only the best goods and services

Send Us Some Email

It is a very simple page, but demonstrates that the developer no longer needs to care what language the text is in.  By changing the USING_LANGUAGE variable the page is immediately changed to the corresponding language.  To add a new language all we need to do is send out the I_home_english.asp page (which is all text) and have a translator modify the text after the "=" sign, and then add the appropriate language title in the supported languages file.  You may be wondering at this point why not just create the page in the desired language.  The reason is that a web based application typically has a lot of code on a page, if we had 5 pages representing the different languages then when developers made a change to the code on one page, they would have to go change the code in all 5 pages.  This also brings up an important issue of when to get files translated.  Only when a page is completed and ready to be published should translation take place.  Any time before this point and you will be facing a constant battle of un-translated items.

Now that we can display our pages in any language we need to tackle two more issues.

Currency

The previous section introduced our method for addressing text and image objects in a language independent manner.  We will now deal with currency conversion.  Object Orientation will provide us with the means to deal with currency as a language independent data representation.  We need to create an object that will take our base denomination US Dollars in pennies, and convert it to the desired currency.  One issue to address is that someone might be viewing a page in Spanish, but is going to buy the item in US Dollars.  We address this by creating a new variable called USING_CURRENCY, which will tell our application which currency the client wishes to view.  Currency exchange rates and conversion are better handled by a third party therefore I propose using Cloanto Currency Server. Cloanto Currency Server ($995) provides a daily update source of currency exchange rates, and interfaced with ASP provides us with a way to convert our US pennies (product, shipping costs) to all denominations Cloanto Currency Server supports - here is a long list (source: www.cloanto.com):

Anguilla

Eastern Caribbean dollar

XCD

Antigua and Barbuda

Eastern Caribbean dollar

XCD

Arab Republic of Egypt

Egyptian pound

EGP

Argentine Republic

Argentine peso

ARS

Aruba

Aruban guilder

AWG

Azerbaijani Republic

Azerbaijani manat

AZM

Barbados

Barbados dollar

BBD

Belize

Belize dollar

BZD

Bermuda

Bermuda dollar

BMD

Bosnia and Herzegovina

Bosnian dinar;

Bosnian convertible mark

BAD;

BAM

British Virgin Islands

US dollar

USD

Burkina Faso

CFA franc

XOF

Canada

Canadian dollar

CAD

Cayman Islands

Cayman Islands dollar

KYD

Central African Republic

CFA franc

XAF

Christmas Island Territory

Australian dollar

AUD

Commonwealth of Australia

Australian dollar

AUD

Commonwealth of Dominica

Eastern Caribbean dollar

XCD

Commonwealth of Puerto Rico

US dollar

USD

Commonwealth of The Bahamas

Bahamian dollar

BSD

Commonwealth of the Northern Mariana Islands

US dollar

USD

Cook Islands

New Zealand dollar

NZD

Cooperative Republic of Guyana

Guyanese dollar

GYD

Czech Republic

Czech koruna

CZK

Democratic People's Republic of Korea

North Korean won

KPW

Democratic Republic of São Tomé and Príncipe

dobra

STD

Democratic Republic of the Congo

new zaire

ZRN

Democratic Socialist Republic of Sri Lanka

Sri Lanka rupee

LKR

Department of French Guiana

French franc

FRF

Department of Guadeloupe

French franc

FRF

Department of Martinique

French franc

FRF

Department of Réunion

French franc

FRF

Dominican Republic

Dominican peso

DOP

East Timor

Indonesian rupiah

IDR

Eastern Republic of Uruguay

Uruguayan peso

UYU

European Union

euro

EUR

Faeroe Islands

Danish krone

DKK

Falkland Islands

Falkland Islands pound

FKP

Federal Democratic Republic of Ethiopia

Ethiopian birr

ETB

Federal Republic of Germany

German mark

DEM

Federal Republic of Nigeria

naira

NGN

Federal Republic of Yugoslavia

Yugoslav dinar

YUM

Federal Republic of Yugoslavia

Yugoslav new dinar

YUD

Federated States of Micronesia

US dollar

USD

Federation of Saint Kitts and Nevis

Eastern Caribbean dollar

XCD

Federative Republic of Brazil

Brazilian real

BRL

Former Yugoslav Republic of Macedonia

denar

MKD

French Republic

French franc

FRF

Gabonese Republic

CFA franc

XAF

Georgia

lari

GEL

Gibraltar

Gibraltar pound

GIP

Grand Duchy of Luxembourg

Luxembourg franc

LUF

Greenland

Danish krone

DKK

Grenada

Eastern Caribbean dollar

XCD

Hashemite Kingdom of Jordan

Jordanian dinar

JOD

Hellenic Republic

Greek drachma

GRD

Hong Kong Special Administrative Region (HKSAR)

Hong Kong dollar

HKD

Independent State of Papua New Guinea

kina

PGK

Independent State of Samoa

tala

WST

Ireland

Irish pound

IEP

Islamic Federal Republic of The Comoros

Comorian franc

KMF

Islamic Republic of Iran

Iranian rial

IRR

Islamic Republic of Mauritania

Mauritanian ouguiya

MRO

Islamic Republic of Pakistan

Pakistani rupee

PKR

Islamic State of Afghanistan

afghani

AFA

Italian Republic

Italian lira

ITL

Jamaica

Jamaica dollar

JMD

Japan

yen

JPY

Kingdom of Belgium

Belgian franc

BEF

Kingdom of Bhutan

ngultrum

BTN

Kingdom of Cambodia

riel

KHR

Kingdom of Denmark

Danish krone

DKK

Kingdom of Lesotho

loti

LSL

Kingdom of Morocco

Moroccan dirham

MAD

Kingdom of Nepal

Nepalese rupee

NPR

Kingdom of Norway

Norwegian krone

NOK

Kingdom of Saudi Arabia

Saudi riyal

SAR

Kingdom of Spain

Spanish peseta

ESP

Kingdom of Swaziland

lilangeni

SZL

Kingdom of Sweden

Swedish krona

SEK

Kingdom of Thailand

baht

THB

Kingdom of the Netherlands

Dutch guilder

NLG

Kingdom of Tonga

pa'anga

TOP

Kyrgyz Republic

som

KGS

Lao People's Democratic Republic

kip

LAK

Lebanese Republic

Lebanese pound

LBP

Macao

pataca

MOP

Malaysia

Malaysian ringgit

MYR

Mongolia

tugrik

MNT

Montserrat

Eastern Caribbean dollar

XCD

Negara Brunei Darussalam

Brunei dollar

BND

Netherlands Antilles

Netherlands Antillean guilder

ANG

New Zealand

New Zealand dollar

NZD

Niue

New Zealand dollar

NZD

People's Democratic Republic of Algeria

Algerian dinar

DZD

People's Republic of Bangladesh

taka

BDT

People's Republic of China

renminbi-yuan

CNY

Pitcairn Islands

New Zealand dollar

NZD

Portuguese Republic

Portuguese escudo

PTE

Principality of Andorra

Spanish peseta; French franc

ESP; FRF

Principality of Liechtenstein

Swiss franc

CHF

Principality of Monaco

French franc

FRF

Republic of Albania

lek

ALL

Republic of Angola

readjusted kwanza

AON

Republic of Armenia

dram

AMD

Republic of Austria

Austrian schilling

ATS

Republic of Belarus

Belarusian rouble

BYB

Republic of Benin

CFA franc

XOF

Republic of Bolivia

boliviano

BOB

Republic of Botswana

pula

BWP

Republic of Bulgaria

lev

BGL

Republic of Burundi

Burundi franc

BIF

Republic of Cameroon

CFA franc

XAF

Republic of Cape Verde

Cape Verde escudo

CVE

Republic of Chad

CFA franc

XAF

Republic of Chile

Chilean peso

CLP

Republic of China

new Taiwan dollar

TWD

Republic of Colombia

Colombian peso

COP

Republic of Costa Rica

Costa Rican colón

CRC

Republic of Côte d'Ivoire

CFA franc

XOF

Republic of Croatia

kuna

HRK

Republic of Cuba

Cuban peso

CUP

Republic of Cyprus

Cyprus pound

CYP

Republic of Djibouti

Djibouti franc

DJF

Republic of Ecuador

sucre

ECS

Republic of El Salvador

El Salvador colón

SVC

Republic of Equatorial Guinea

CFA franc

XAF

Republic of Estonia

Estonian kroon

EEK

Republic of Fiji

Fiji dollar

FJD

Republic of Finland

Finnish markka

FIM

Republic of Ghana

cedi

GHC

Republic of Guatemala

Guatemalan quetzal

GTQ

Republic of Guinea

Guinean franc

GNF

Republic of Guinea-Bissau

CFA franc

XOF

Republic of Haiti

gourde

HTG

Republic of Honduras

lempira

HNL

Republic of Hungary

forint

HUF

Republic of Iceland

Icelandic króna

ISK

Republic of India

Indian rupee

INR

Republic of Indonesia

Indonesian rupiah

IDR

Republic of Iraq

Iraqi dinar

IQD

Republic of Kazakhstan

tenge

KZT

Republic of Kenya

Kenyan shilling

KES

Republic of Kiribati

Australian dollar

AUD

Republic of Korea

South Korean won

KRW

Republic of Latvia

lats

LVL

Republic of Liberia

Liberian dollar

LRD

Republic of Lithuania

litas

LTL

Republic of Madagascar

Malagasy franc

MGF

Republic of Malawi

Malawi kwacha

MWK

Republic of Maldives

rufiyaa

MVR

Republic of Mali

CFA franc

XOF

Republic of Malta

Maltese lira

MTL

Republic of Mauritius

Mauritian rupee

MUR

Republic of Moldova

Moldovan leu

MDL

Republic of Mozambique

metical

MZM

Republic of Namibia

Namibian dollar

NAD

Republic of Nauru

Australian dollar

AUD

Republic of Nicaragua

córdoba

NIO

Republic of Niger

CFA franc

XOF

Republic of Palau

US dollar

USD

Republic of Panama

balboa

PAB

Republic of Paraguay

guaraní

PYG

Republic of Peru

new sol

PEN

Republic of Poland

zloty

PLZ

Republic of San Marino

Italian lira

ITL

Republic of Senegal

CFA franc

XOF

Republic of Seychelles

Seychelles rupee

SCR

Republic of Sierra Leone

leone

SLL

Republic of Singapore

Singapore dollar

SGD

Republic of Slovenia

tolar

SIT

Republic of South Africa

rand

ZAR

Republic of Sudan

Sudanese pound

SDD

Republic of Suriname

Suriname guilder

SRG

Republic of Tajikistan

Tajik rouble

TJR

Republic of the Congo

CFA franc

XAF

Republic of The Gambia

dalasi

GMD

Republic of the Marshall Islands

US dollar

USD

Republic of the Philippines

Philippine peso

PHP

Republic of Trinidad and Tobago

Trinidad and Tobago dollar

TTD

Republic of Tunisia

Tunisian dinar

TND

Republic of Turkey

Turkish lira

TRL

Republic of Uganda

Uganda shilling

UGX

Republic of Uzbekistan

sum

UZS

Republic of Vanuatu

vatu

VUV

Republic of Venezuela

bolívar

VEB

Republic of Yemen

Yemeni rial

YER

Republic of Zambia

Zambian kwacha

ZMK

Republic of Zimbabwe

Zimbabwe dollar

ZWD

Romania

Romanian leu

ROL

Russian Federation

new rouble

RUB

Rwandese Republic

Rwandese franc

RWF

Saint Helena and Dependencies

Saint Helena pound

SHP

Saint Lucia

Eastern Caribbean dollar

XCD

Saint Vincent and the Grenadines

Eastern Caribbean dollar

XCD

Slovak Republic

Slovak koruna

SKK

Socialist People's Libyan Arab Jamahiriya

Libyan dinar

LYD

Socialist Republic of Viet Nam

dong

VND

Solomon Islands

Solomon Islands dollar

SBD

Somali Democratic Republic

Somali shilling

SOS

State of Bahrain

Bahraini dinar

BHD

State of Eritrea

nakfa

ERN

State of Israel

new shekel

ILS

State of Kuwait

Kuwaiti dinar

KWD

State of Qatar

Qatari riyal

QAR

Sultanate of Oman

Omani rial

OMR

Svalbard and Jan Mayen Islands

Norwegian krone

NOK

Swiss Confederation

Swiss franc

CHF

Syrian Arab Republic

Syrian pound

SYP

Territorial collectivity of Mayotte

French franc

FRF

Territorial collectivity of Saint Pierre and Miquelon

French franc

FRF

Territory of American Samoa

US dollar

USD

Territory of Cocos (Keeling) Islands

Australian dollar

AUD

Territory of French Polynesia

CFP franc

XPF

Territory of Guam

US dollar

USD

Territory of New Caledonia and Dependencies

CFP franc

XPF

Territory of Norfolk Island

Australian dollar

AUD

Territory of the Wallis and Futuna Islands

CFP franc

XPF

The Holy see

Italian lira

ITL

Togolese Republic

CFA franc

XOF

Tokelau

New Zealand dollar

NZD

Turkmenistan

Turkmen manat

TMM

Turks and Caicos Islands

US dollar

USD

Tuvalu

Australian dollar

AUD

Ukraine

hryvnia

UKH

Union of Myanmar

kyat

MMK

United Arab Emirates

UAE dirham

AED

United Kingdom of Great Britain and Northern Ireland

pound sterling

GBP

United Mexican States

Mexican peso

MXN

United Republic of Tanzania

Tanzanian shilling

TZS

United States Minor Outlying Islands

US dollar

USD

United States of America

US dollar

USD

Virgin Islands of the United States

US dollar

USD

Implementing a conversion routine ourselves would be non-productive and more than likely cost much more than the $995.00 than Cloanto charges.  As I mentioned before we will be using the USING_CURRENCY variable to define which conversion is required.   We will create an asp-scripted object to buffer the actual implementation of currency conversion.  When we are done to get the value of any currency we should be able to do the following:

// Include the supported languages file
<!--#INCLUDE FILE=" language files / I_supported_languages.asp" -->
// Set the language to English
<% USING_LANGUAGE = "LANUGAGE_ENGLISH" %>
// Set our target currency to be Tanzanian shillings
<% USING_CURRENCY = "TZS" %>
<center>
Us Dollars: $10.00
Tanzanian shillings: <%=localCurrency.ConvertFromUS(1000)%>

Take note of the line "<%=local_Currency(1000)%>" we are taking $10.00 in pennies and sending it to a function called ConvertFromUS in an object called localCurrency.  The result should be the Tanzanian shillings representation of $10.00.  We use pennies for currency in our code because pennies can reflect a whole or partial dollar amount without using decimal places (which speeds up calculations).

Creating the localCurrency Object

In the previous section we used an imaginary object called "localCurrency" to convert us pennies into any denomination we want.  Now we will create the localCurrency Object.

Outline:

LocalCurrency
           // Methods
           ConvertFromUS   (method)
           // Properties
           m_sCurrencyCode (string based representation of the destination 
                            denomination EX: "TZS")
           m_objCloanto    (Cloanto Conversion Object)

By creating this object and then calling the ConvertFromUS method developers no longer need to care what currency the client is viewing.  Another benefit to putting this into an object is that if the method of conversion changes from using Cloanto developers only need to change the implementation of this object and nothing else.  An example is that 50 pages use the LocalCurrency object to do their currency conversions.  If our company decides that we will use WidgetCompanies solution instead of Cloanto a developer only needs to modify the implementation of ConvertFromUS (which is located in a single file), and the functionality is passed along to all 50 pages without ever having to touch them.

We will create and contain the LocalCurrency object inside of our I_supported_languages.asp file.  This way whenever that file is included we know we have language and currency independence at our fingertips.

When the LocalCurrency object is created it will be passed the three letter currency code.  There are all kinds of other functionality that could be added to the localCurrency object, but for now our single method is sufficient.

Database Text

  Up to this point we have address a large chunk of localizing a web application.  All of our pages and currency now have the ability to be viewed in different languages.  The last problem to solve is that E-Commerce has a lot of text stored in a database.  Product names, descriptions, store names, informational text, are all stored in a database.  How do we localize database entries?  We only need to concern ourselves with text that will be viewed by end users, but that still leaves us with a significant problem.  The solution is to be able to tell which languages a particular record supports and then pulling the specific language field out of the database.  If a particular record does not support the desired language we will have to default to the language it does support.  This is easy if we are pulling known records out of a database but becomes tricky when dealing with something as dynamic as a product search.  You do not want to have to look at each item when querying a database having thousands (or more) of records, this would be slow and not applicable to a web environment when many users may be hitting the database at the same time.  We will make a trade off between size and speed.  For each entry in a recordset that has viewable text we will actually multiple entries equal to the number of languages being supported.  To clarify this we will create a table representation of supported languages. 

This table will mostly used for reference and administration.

Supported languages table:

Lanugage                  :           (string representation of language)
LanguageID                :           (ID of the language)

If we look at our previous implementation of page-based localization we used the following variables to describe the desired language:

LANGUAGE_ENGLISH          = 0
LANGUAGE_SPANISH          = 1
LANGUAGE_FRENCH           = 2
LANGUAGE_CUBAN            = 3

We now put those values into our Supported languages table:

Language:            English
LanguageID:            0
Language:            Spanish
LanguageID:            1
Language:            French
LanguageID:            2
Language:            Cuban
LanguageID:            3

Now that we have a reference to what languages the entire application supports we need to drill down into a specific recordset to see how it is used.  Let’s use a very simple Product table for an example:

Product Table (not localized)
ProductID                : (ID of product)
ProductName              : (String Representation of products name)
Price_retail             : (retail Price in pennies)
Description              : (string representation of product description)
Notes                    : (string representation of additional product notes)

An example of a Product Entry would be:

ProductID:           55
ProductName:         SuperSlingShot5000
Price_retail:        1000
Description:         Introducing the SuperSlingShot5000, the finest slingshot 
                     you could ever own.  Can propel an acorn over 200 yards.
Notes:               Not recommended for children under the age of 15

Since we are only concerned about text that will be presented to the end user we will not be touching the ProductID, Price_retail, or ProductName fields.  The product name could theoretically be considered for localization but I do not think it applies.  To localize this entry we first need to specify which languages this entry supports by adding a languages_supported string field.  Our modified table now has the following structure:

ProductID            : (ID of product)
ProductName          : (String Representation of products name)
Price_retail         : (retail Price in pennies)
Description          : (string representation of product description)
Notes                : (string representation of additional product notes)
Languages_supported  : (list of languages supported separated by commas)

We will use a string list of supported language IDs seperated by commas:

ProductID:           55
ProductName:         SuperSlingShot5000
Price_retail:        1000
Description:         Introducing the SuperSlingShot5000, the finest slingshot
                     You could ever own.  Can propel an acorn over 200 yards.
Notes:               Not recommended for children under the age of 15
Languages_supported  0

If we supported English and Spanish the Languages_Supported field would look like this:

Languages_supported  0,1

We now have to add localized fields equal to the number of languages being supported by the entire application.  Even though we are only supporting English at this point in our table, the entire application supports 4 languages.  Here is the final structure of our example table:

ProductID            : (ID of product)
ProductName          : (String Representation of products name)
Price_retail         : (retail Price in pennies)
Description0         : (string representation of product description)
Description1         : (string representation of product description)
Description2         : (string representation of product description)
Description3         : (string representation of product description)
Notes0               : (string representation of additional product notes)
Notes1               : (string representation of additional product notes)
Notes2               : (string representation of additional product notes)
Notes3               : (string representation of additional product notes)
Languages_supported  : (list of languages supported separated by commas)

Each field now has the language ID appended to the end.  Now we can get any field in any supported language.  What if our recordset only supports English and the entire application supports four different languages?  This problem is solved when the record is generated.  No matter how many languages the record will eventually support we will take whatever language the record is created with and stuff it into all the language fields.  So if we only support English in this record the Description0-3 will all contain English.  Duplicating data may seem wasteful but remember we are trading speed for size.  With the above method we can query an entire database in English by pulling out Description0 or Spanish with Description1, we do not need to verify if each entry is compliant.

Putting It All Together

A lot of ground was covered in this document but now we will put it all together.  By using a variable called USING_LANGUAGE we now have the ability to change the language in which a page is viewed.  By using a variable called USING_CURRENCY we can change the denomination currency is viewed.  Since we have localized our entire database we can now use the same variable (USING_LANGUAGE  - already defined on each page) to know which fields to pull out.

By starting from the ground-up we have built the foundation for seamless integration of new languages and currency into our application.  Making a trade on the database side for speed over size, using a third-party solution for currency exchanges, and our use of ‘language includes’ maximizes development time and application speed.  I can not overstate the importance of attention to detail when planning for localization of an application.  Everyone involved in the project from sales to developers need to communicate and understand each other’s responsibilities and time frames.  Only by working as a team will a project as massive as an E-Commerce site be successfully localized and launched.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralVery Urgent Pin
sreejith ss nair18-Sep-05 21:13
sreejith ss nair18-Sep-05 21:13 
General54y4sy Pin
15-Nov-01 4:13
suss15-Nov-01 4:13 
GeneralOther Languages Pin
4-Nov-01 8:40
suss4-Nov-01 8:40 
GeneralCurrency name Pin
3-Sep-01 22:01
suss3-Sep-01 22:01 
GeneralRe: Currency name Pin
dswigger4-Sep-01 6:30
dswigger4-Sep-01 6:30 
GeneralRe: Currency name Pin
9-Sep-01 21:45
suss9-Sep-01 21:45 
GeneralRe: Currency name Pin
12-Oct-01 13:09
suss12-Oct-01 13:09 
GeneralAll is included Pin
Uwe Keim3-Sep-01 19:23
sitebuilderUwe Keim3-Sep-01 19:23 
GeneralRe: All is included Pin
dswigger3-Sep-01 21:54
dswigger3-Sep-01 21:54 
GeneralRe: All is included Pin
Christian Tratz4-Sep-01 2:03
Christian Tratz4-Sep-01 2:03 
GeneralRe: All is included Pin
Uwe Keim4-Sep-01 2:05
sitebuilderUwe Keim4-Sep-01 2:05 
GeneralRe: All is included Pin
Christian Tratz4-Sep-01 2:45
Christian Tratz4-Sep-01 2:45 
GeneralRe: All is included Pin
Horatiu CRISTEA9-Sep-01 12:52
Horatiu CRISTEA9-Sep-01 12:52 
GeneralRe: All is included Pin
7-Feb-02 22:09
suss7-Feb-02 22:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.