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%>
-->
<%elseif USING_LANGUAGE = "LANGUAGE_SPANISH" then%>
-->
<%elseif USING_LANGUAGE = "LANGUAGE_FRENCH" then%>
-->
<%elseif USING_LANGUAGE = "LANGUAGE_CUBAN" then%>
-->
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:
<!---->
<% USING_LANGUAGE = "LANUGAGE_ENGLISH" %>
-->
<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 FILE=" language files / I_supported_languages.asp" -->
<% USING_LANGUAGE = "LANUGAGE_ENGLISH" %>
<% 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
ConvertFromUS (method)
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.