65.9K
CodeProject 正在变化。 阅读更多。
Home

本地化软件应用程序

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.50/5 (3投票s)

2001 年 9 月 4 日

21分钟阅读

viewsIcon

156643

本地化 ASP 应用程序简介。

你是在开玩笑吧?

当需要让应用程序实现语言独立时,所有销售人员都会欢呼雀跃,而开发人员则会躲起来。对销售人员来说,本地化软件意味着更多的市场和更多的销售额;对开发人员来说,它意味着一长串令人头疼的问题。

主要问题之一是软件通常不是从头开始就设计成支持语言切换的。如果不是从头开始就包含这种支持,那么每一个向用户呈现语言的代码片段(按钮、菜单、图像、提示、帮助、文本)都必须被找到并修改,以支持语言独立性。当处理有数十万行代码,并且由不同开发人员不断修改的应用程序时,这个问题会呈指数级增长。

基于网络的电子商务应用程序也存在上述问题,但还带来了货币问题。对于每种支持的语言,所有处理货币的功能都必须被定位并修改,以支持每种语言的货币面额。货币必须以一种易于在所有支持的语言之间转换的方式存储,无论用户以美元查看,存储的值都必须能够转换为比索、法郎或英镑。另一件要记住的事情是汇率不是静态的,它们会变化。

面向对象来救援

无论您来自哪一方(销售或开发),现在都可以看到存在的问题。如果目标应用程序在构建时没有考虑到本地化,那么工作量将是两倍。另一方面,如果目标应用程序处于设计阶段,我们可以制定本地化行动计划。

面向对象编程 (OOP) 是一种将编程代码封装到预定义执行和数据中的方法。我们无需拥有一长串函数和变量,而是可以使用 OOP 来使开发大型(或小型)应用程序变得易于理解和实现。一个简单的现实世界面向对象示例是基本的业务结构。尽管在小型企业中,总裁了解每个人、他们应该做什么、他们应该如何做,但在大型企业中这是不可能的。以面向对象的方式分解这家公司,我们可以看到以下内容

Object Employee
Object Manager
Object Vice President
Object President:

每个对象都有自己的属性(attributes)和方法(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)

整个公司现在可以用以下对象来表示

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)

通过使用面向对象 (OO),我们可以执行操作,甚至无需知道涉及谁或它是如何工作的。例如,如果一位总裁希望发放奖金支票,并且他有 3000 名员工,那么他几乎不可能评估所有员工的绩效并分发适当的奖金支票。通过使用 OO,总裁只需将命令交给他的副总裁,副总裁再将其传递给他们手下的每位经理,最终到达员工层面。因此,在不了解员工或经理的任何信息的情况下,总裁可以这样做:

           Company -> President -> ExecuteBonusCheckPayments()

所有员工都会收到适当的奖金支票。

回到我们的应用程序,我们可以使用 OOP 来最大限度地开发和实施语言和货币独立性。通过消除开发人员了解或关心应用程序使用何种语言的需要,我们简化了他们的开发,并最大限度地利用他们的时间来关注功能。尽管本地化的实施是一项艰巨的工作,但一旦初步代码到位,开发人员将无需过多处理,甚至完全无需处理。我将重点关注一个 ASP 电子商务应用程序,但该理论可以轻松地应用于任何开发环境。

数据表示

数据表示是为开发人员和翻译人员准备的。使用本地化软件的客户端永远不会看到或需要看到数据是如何表示的。基本上,数据表示就是我们在代码中表示本地化数据的方式。我们数据表示的基础语言将是英语。应用程序创建后,开发人员将引用文本的数据表示,而不是实际文本,翻译人员将引用文本并忽略数据表示。让我们以一个需要本地化的按钮为例。该按钮上显示“Help”字样,但本地化后,西班牙语中的“HELP”是“Socorro”。我们的数据表示是 dr_txt_HELP。

英文

dr_txt_HELP = "Help"

西班牙语

dr_txt_HELP = "Socorro"

现在我们的开发人员对帮助按钮的语言毫不关心,因为在代码中他们将始终只使用 dr_txt_HELP。这种数据表示也可以用于图像。

英文

dr_img_HELP = "Help.jpg"

西班牙语

dr_img_HELP = "Socorro.jpg"

如您所见,这种数据表示在编程和翻译方面为我们提供了两全其美的优势。您支持的语言越多,翻译人员查看文本文件并将其翻译成目标语言就越容易。定义数据表示后,开发人员无需关心应用程序以何种语言显示。

包含

到目前为止,我们已经清楚地了解了数据如何表示,现在我们需要定义如何将这些数据集成到应用程序中。我们将使用包含文件和面向对象来实现所需的功能。在最高层,我们需要知道我们将显示哪种语言,这可以通过一个名为 USING_LANGUAGE 的变量来实现。每种支持的语言都将有一个关联的值,该值将包含在一个支持的语言文件中。

我们支持的语言文件示例

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

支持的语言文件将包含在 Web 应用程序的每个页面中。在处理服务器端脚本传递时,优化是需要关注的问题,因此我将把每个依赖语言的 include 拆分成单独的文件,并放置在不同的目录中。这将防止每个页面的性能受到大量 if/then/else 语句的影响。我们的目录结构如下:

(root)
           (language files)
                      (localized)

因此,如果我们添加主页,目录将如下所示:

(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

根目录中的 home.asp 是实际页面,它将包含 I_supported_languages.asp 和“language files”目录中的 I_home.asp。“language files”目录中的 I_home.asp 将根据我们的 USING_LANGUAGE 变量包含适当的本地化文件。让我们看看 I_home.asp 文件里面有什么

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" -->

通过查看上面的列表,我们可以看到,如果在包含 I_home.asp 之前我们将 USING_LANGUAGE 变量设置为 LANGUAGE_ENGLISH,它会指示 I_home.asp 包含 I_home_english.asp 文件。你问那有什么用?让我们看看 I_home_english.asp 文件内部,找出答案

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" %>

通过包含上面列出的文件,我们现在可以访问数据表示,而不是实际文本。我之前提到过,我们的基本语言是英语,这就是为什么变量是英语的原因。通过查看实际的 home.asp 页面,您将看到这一切是如何组合在一起的。

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>

如果通过浏览器查看,输出将如下所示

欢迎来到MyStore.com

MyStore.com是本世纪的电商网站。您将发现我们只提供最好的商品和服务。

给我们发邮件

这是一个非常简单的页面,但它表明开发人员不再需要关心文本是哪种语言。通过更改 USING_LANGUAGE 变量,页面会立即更改为相应的语言。要添加新语言,我们只需要发送 I_home_english.asp 页面(都是文本),让翻译人员修改等号后面的文本,然后在 supported languages 文件中添加相应的语言标题。您此时可能想知道为什么不直接用所需语言创建页面。原因是基于网络的应用程序通常在页面上有很多代码,如果我们有 5 个页面代表不同的语言,那么当开发人员更改一个页面上的代码时,他们将不得不更改所有 5 个页面中的代码。这也带来了一个重要的问题:何时进行文件翻译。只有当页面完成并准备发布时,才应该进行翻译。在此之前的任何时候,您都将面临持续不断的未翻译项目的斗争。

现在我们可以用任何语言显示页面了,我们需要解决另外两个问题。

货币

上一节介绍了我们以语言独立方式处理文本和图像对象的方法。现在我们将处理货币换算。面向对象将为我们提供将货币作为语言独立数据表示来处理的手段。我们需要创建一个对象,它将以美分表示的美元基本面额转换为所需的货币。一个需要解决的问题是,某人可能正在用西班牙语查看页面,但将用美元购买商品。我们通过创建一个名为 USING_CURRENCY 的新变量来解决这个问题,该变量将告诉我们的应用程序客户希望查看哪种货币。汇率和转换最好由第三方处理,因此我建议使用 Cloanto 货币服务器。Cloanto 货币服务器(995 美元)提供每日更新的汇率来源,与 ASP 接口后,它为我们提供了一种将我们的美国美分(产品、运费)转换为 Cloanto 货币服务器支持的所有面额的方法——以下是一个长列表(来源:www.cloanto.com)

安圭拉

东加勒比元

XCD

安提瓜和巴布达

东加勒比元

XCD

阿拉伯埃及共和国

埃及镑

EGP

阿根廷共和国

阿根廷比索

ARS

阿鲁巴

阿鲁巴盾

AWG

阿塞拜疆共和国

阿塞拜疆马纳特

AZM

巴巴多斯

巴巴多斯元

BBD

伯利兹

伯利兹元

BZD

百慕大

百慕大元

BMD

波斯尼亚和黑塞哥维那

波斯尼亚第纳尔;

波斯尼亚可兑换马克

BAD;

BAM

英属维尔京群岛

美元

USD

布基纳法索

非洲金融共同体法郎

XOF

Canada

加拿大元

CAD

开曼群岛

开曼群岛元

KYD

中非共和国

非洲金融共同体法郎

XAF

圣诞岛领地

澳大利亚元

AUD

澳大利亚联邦

澳大利亚元

AUD

多米尼克联邦

东加勒比元

XCD

波多黎各联邦

美元

USD

巴哈马联邦

巴哈马元

BSD

北马里亚纳群岛联邦

美元

USD

库克群岛

新西兰元

NZD

圭亚那合作共和国

圭亚那元

GYD

捷克共和国

捷克克朗

CZK

朝鲜民主主义人民共和国

朝鲜元

KPW

圣多美和普林西比民主共和国

多布拉

STD

刚果民主共和国

新扎伊尔

ZRN

斯里兰卡民主社会主义共和国

斯里兰卡卢比

LKR

法属圭亚那省

法国法郎

FRF

瓜德罗普省

法国法郎

FRF

马提尼克省

法国法郎

FRF

留尼汪省

法国法郎

FRF

多米尼加共和国

多米尼加比索

DOP

东帝汶

印度尼西亚盾

IDR

乌拉圭东岸共和国

乌拉圭比索

UYU

欧盟

欧元

EUR

法罗群岛

丹麦克朗

DKK

福克兰群岛

福克兰群岛镑

FKP

埃塞俄比亚联邦民主共和国

埃塞俄比亚比尔

ETB

德意志联邦共和国

德国马克

DEM

尼日利亚联邦共和国

奈拉

NGN

南斯拉夫联邦共和国

南斯拉夫第纳尔

YUM

南斯拉夫联邦共和国

南斯拉夫新第纳尔

YUD

密克罗尼西亚联邦

美元

USD

圣基茨和尼维斯联邦

东加勒比元

XCD

巴西联邦共和国

巴西雷亚尔

BRL

前南斯拉夫的马其顿共和国

第纳尔

MKD

法兰西共和国

法国法郎

FRF

加蓬共和国

非洲金融共同体法郎

XAF

格鲁吉亚

拉里

GEL

直布罗陀

直布罗陀镑

GIP

卢森堡大公国

卢森堡法郎

LUF

格陵兰

丹麦克朗

DKK

格林纳达

东加勒比元

XCD

约旦哈希姆王国

约旦第纳尔

JOD

希腊共和国

希腊德拉克马

GRD

香港特别行政区(HKSAR)

港元

HKD

巴布亚新几内亚独立国

基那

PGK

萨摩亚独立国

塔拉

WST

爱尔兰

爱尔兰镑

IEP

科摩罗伊斯兰联邦共和国

科摩罗法郎

KMF

伊朗伊斯兰共和国

伊朗里亚尔

IRR

毛里塔尼亚伊斯兰共和国

毛里塔尼亚乌吉亚

MRO

巴基斯坦伊斯兰共和国

巴基斯坦卢比

PKR

阿富汗伊斯兰国

阿富汗尼

AFA

意大利共和国

意大利里拉

ITL

牙买加

牙买加元

JMD

日本

日元

JPY

比利时王国

比利时法郎

BEF

不丹王国

努扎姆

BTN

柬埔寨王国

瑞尔

KHR

丹麦王国

丹麦克朗

DKK

莱索托王国

洛蒂

LSL

摩洛哥王国

摩洛哥迪拉姆

MAD

尼泊尔王国

尼泊尔卢比

NPR

挪威王国

挪威克朗

NOK

沙特阿拉伯王国

沙特里亚尔

SAR

西班牙王国

西班牙比塞塔

ESP

斯威士兰王国

里拉吉尼

SZL

瑞典王国

瑞典克朗

SEK

泰王国

泰铢

THB

荷兰王国

荷兰盾

NLG

汤加王国

潘加

TOP

吉尔吉斯共和国

索姆

KGS

老挝人民民主共和国

基普

LAK

黎巴嫩共和国

黎巴嫩镑

LBP

澳门

澳门元

MOP

马来西亚

马来西亚林吉特

MYR

蒙古

图格里克

MNT

蒙特塞拉特

东加勒比元

XCD

文莱达鲁萨兰国

文莱元

BND

荷属安的列斯群岛

荷属安的列斯盾

ANG

新西兰

新西兰元

NZD

纽埃

新西兰元

NZD

阿尔及利亚民主人民共和国

阿尔及利亚第纳尔

DZD

孟加拉人民共和国

塔卡

BDT

中华人民共和国

人民币元

CNY

皮特凯恩群岛

新西兰元

NZD

葡萄牙共和国

葡萄牙埃斯库多

PTE

安道尔公国

西班牙比塞塔;法国法郎

ESP;FRF

列支敦士登公国

瑞士法郎

CHF

摩纳哥公国

法国法郎

FRF

阿尔巴尼亚共和国

列克

ALL

安哥拉共和国

调整后的宽扎

AON

亚美尼亚共和国

德拉姆

AMD

奥地利共和国

奥地利先令

ATS

白俄罗斯共和国

白俄罗斯卢布

BYB

贝宁共和国

非洲金融共同体法郎

XOF

玻利维亚共和国

玻利维亚诺

BOB

博茨瓦纳共和国

普拉

BWP

保加利亚共和国

列弗

BGL

布隆迪共和国

布隆迪法郎

BIF

喀麦隆共和国

非洲金融共同体法郎

XAF

佛得角共和国

佛得角埃斯库多

CVE

乍得共和国

非洲金融共同体法郎

XAF

智利共和国

智利比索

CLP

中华民国

新台币

TWD

哥伦比亚共和国

哥伦比亚比索

COP

哥斯达黎加共和国

哥斯达黎加科朗

CRC

科特迪瓦共和国

非洲金融共同体法郎

XOF

克罗地亚共和国

库纳

HRK

古巴共和国

古巴比索

CUP

塞浦路斯共和国

塞浦路斯镑

CYP

吉布提共和国

吉布提法郎

DJF

厄瓜多尔共和国

苏克雷

ECS

萨尔瓦多共和国

萨尔瓦多科朗

SVC

赤道几内亚共和国

非洲金融共同体法郎

XAF

爱沙尼亚共和国

爱沙尼亚克朗

EEK

斐济共和国

斐济元

FJD

芬兰共和国

芬兰马克

FIM

加纳共和国

塞地

GHC

危地马拉共和国

危地马拉格查尔

GTQ

几内亚共和国

几内亚法郎

GNF

几内亚比绍共和国

非洲金融共同体法郎

XOF

海地共和国

古德

HTG

洪都拉斯共和国

伦皮拉

HNL

匈牙利共和国

福林

HUF

冰岛共和国

冰岛克朗

ISK

印度共和国

印度卢比

INR

印度尼西亚共和国

印度尼西亚盾

IDR

伊拉克共和国

伊拉克第纳尔

IQD

哈萨克斯坦共和国

坚戈

KZT

肯尼亚共和国

肯尼亚先令

KES

基里巴斯共和国

澳大利亚元

AUD

大韩民国

韩元

KRW

拉脱维亚共和国

拉特

LVL

利比里亚共和国

利比里亚元

LRD

立陶宛共和国

立特

LTL

马达加斯加共和国

马达加斯加法郎

MGF

马拉维共和国

马拉维克瓦查

MWK

马尔代夫共和国

拉菲亚

MVR

马里共和国

非洲金融共同体法郎

XOF

马耳他共和国

马耳他里拉

MTL

毛里求斯共和国

毛里求斯卢比

MUR

摩尔多瓦共和国

摩尔多瓦列伊

MDL

莫桑比克共和国

梅蒂卡尔

MZM

纳米比亚共和国

纳米比亚元

NAD

瑙鲁共和国

澳大利亚元

AUD

尼加拉瓜共和国

科尔多瓦

NIO

尼日尔共和国

非洲金融共同体法郎

XOF

帕劳共和国

美元

USD

巴拿马共和国

巴波亚

PAB

巴拉圭共和国

瓜拉尼

PYG

秘鲁共和国

新索尔

PEN

波兰共和国

兹罗提

PLZ

圣马力诺共和国

意大利里拉

ITL

塞内加尔共和国

非洲金融共同体法郎

XOF

塞舌尔共和国

塞舌尔卢比

SCR

塞拉利昂共和国

利昂

SLL

新加坡共和国

新加坡元

SGD

斯洛文尼亚共和国

托拉尔

SIT

南非共和国

兰特

ZAR

苏丹共和国

苏丹镑

SDD

苏里南共和国

苏里南盾

SRG

塔吉克斯坦共和国

塔吉克卢布

TJR

刚果共和国

非洲金融共同体法郎

XAF

冈比亚共和国

达拉西

GMD

马绍尔群岛共和国

美元

USD

菲律宾共和国

菲律宾比索

PHP

特立尼达和多巴哥共和国

特立尼达和多巴哥元

TTD

突尼斯共和国

突尼斯第纳尔

TND

土耳其共和国

土耳其里拉

TRL

乌干达共和国

乌干达先令

UGX

乌兹别克斯坦共和国

sum

UZS

瓦努阿图共和国

瓦图

VUV

委内瑞拉共和国

玻利瓦尔

VEB

也门共和国

也门里亚尔

YER

赞比亚共和国

赞比亚克瓦查

ZMK

津巴布韦共和国

津巴布韦元

ZWD

罗马尼亚

罗马尼亚列伊

ROL

俄罗斯联邦

新卢布

RUB

卢旺达共和国

卢旺达法郎

RWF

圣赫勒拿岛及属地

圣赫勒拿镑

SHP

圣卢西亚

东加勒比元

XCD

圣文森特和格林纳丁斯

东加勒比元

XCD

斯洛伐克共和国

斯洛伐克克朗

SKK

利比亚阿拉伯社会主义人民民众国

利比亚第纳尔

LYD

越南社会主义共和国

越南盾

VND

所罗门群岛

所罗门群岛元

SBD

索马里民主共和国

索马里先令

SOS

巴林国

巴林第纳尔

BHD

厄立特里亚国

纳克法

ERN

以色列国

新谢克尔

ILS

科威特国

科威特第纳尔

KWD

卡塔尔国

卡塔尔里亚尔

QAR

阿曼苏丹国

阿曼里亚尔

OMR

斯瓦尔巴群岛和扬马延岛

挪威克朗

NOK

瑞士联邦

瑞士法郎

CHF

阿拉伯叙利亚共和国

叙利亚镑

SYP

马约特领土集体

法国法郎

FRF

圣皮埃尔和密克隆领土集体

法国法郎

FRF

美属萨摩亚领地

美元

USD

科科斯(基林)群岛领地

澳大利亚元

AUD

法属波利尼西亚领地

太平洋法郎

XPF

关岛领地

美元

USD

新喀里多尼亚和属地领地

太平洋法郎

XPF

诺福克岛领地

澳大利亚元

AUD

瓦利斯和富图纳群岛领地

太平洋法郎

XPF

教廷

意大利里拉

ITL

多哥共和国

非洲金融共同体法郎

XOF

托克劳

新西兰元

NZD

土库曼斯坦

土库曼马纳特

TMM

特克斯和凯科斯群岛

美元

USD

图瓦卢

澳大利亚元

AUD

乌克兰

格里夫尼亚

UKH

缅甸联邦

缅元

MMK

阿拉伯联合酋长国

阿联酋迪拉姆

AED

大不列颠及北爱尔兰联合王国

英镑

GBP

墨西哥合众国

墨西哥比索

MXN

坦桑尼亚联合共和国

坦桑尼亚先令

TZS

美国本土外小岛屿

美元

USD

美利坚合众国

美元

USD

美属维尔京群岛

美元

USD

自己实现转换程序将是低效的,而且很可能比 Cloanto 收取的 995.00 美元贵得多。正如我之前提到的,我们将使用 USING_CURRENCY 变量来定义所需的转换。我们将创建一个 ASP 脚本对象来缓冲货币转换的实际实现。完成后,要获取任何货币的值,我们应该能够执行以下操作:

// 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)%>

请注意“<%=local_Currency(1000)%>”这一行,我们将 10.00 美元(以美分为单位)发送到名为 localCurrency 的对象中的 ConvertFromUS 函数。结果应该是 10.00 美元在坦桑尼亚先令中的表示。我们在代码中使用美分来表示货币,因为美分可以在不使用小数点的情况下反映全部或部分美元金额(这可以加快计算速度)。

创建 localCurrency 对象

在上一节中,我们使用了一个名为“localCurrency”的虚构对象,将我们(美国)美分转换为我们想要的任何面额。现在我们将创建 localCurrency 对象。

Outline

LocalCurrency
           // Methods

           ConvertFromUS   (method)
           // Properties

           m_sCurrencyCode (string based representation of the destination 
                            denomination EX: "TZS")
           m_objCloanto    (Cloanto Conversion Object)

通过创建此对象并调用 ConvertFromUS 方法,开发人员不再需要关心客户端正在查看何种货币。将此放入对象的另一个好处是,如果转换方法从使用 Cloanto 更改,开发人员只需更改此对象的实现,而无需更改其他任何内容。例如,有 50 个页面使用 LocalCurrency 对象进行货币转换。如果我们的公司决定使用 WidgetCompanies 的解决方案而不是 Cloanto,开发人员只需修改 ConvertFromUS 的实现(它位于单个文件中),功能就会传递到所有 50 个页面,而无需触及它们。

我们将在 I_supported_languages.asp 文件中创建并包含 LocalCurrency 对象。这样,每当该文件被包含时,我们就知道我们已经掌握了语言和货币独立性。

创建 LocalCurrency 对象时,它将传递三字母货币代码。localCurrency 对象可以添加各种其他功能,但目前我们的单一方法已足够。

数据库文本

到目前为止,我们已经解决了网络应用程序本地化的大部分问题。现在,我们所有的页面和货币都能够以不同的语言显示。最后一个要解决的问题是,电子商务在数据库中存储了大量的文本。产品名称、描述、商店名称、信息文本都存储在数据库中。我们如何本地化数据库条目?我们只需要关注最终用户将看到的文本,但这仍然给我们留下了一个重要问题。解决方案是能够判断特定记录支持哪些语言,然后从数据库中提取特定语言字段。如果特定记录不支持所需语言,我们将不得不默认为它所支持的语言。如果我们从数据库中提取已知记录,这很容易,但当处理像产品搜索这样动态的东西时,就变得很棘手了。您不希望在查询包含数千(或更多)条记录的数据库时查看每个项目,这会很慢,并且不适用于多个用户可能同时访问数据库的网络环境。我们将在大小和速度之间进行权衡。对于记录集中每个具有可查看文本的条目,我们将实际复制与所支持语言数量相等的条目。为了阐明这一点,我们将创建支持语言的表格表示。

此表主要用于参考和管理。

支持的语言表

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

如果我们回顾之前基于页面的本地化实现,我们使用以下变量来描述所需语言

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

我们现在将这些值放入我们的支持语言表中

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

现在我们已经有了整个应用程序支持哪些语言的参考,我们需要深入研究特定的记录集,看看它是如何使用的。让我们以一个非常简单的产品表为例

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)

产品条目的一个例子是

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

由于我们只关注将呈现给最终用户的文本,因此我们不会触及 ProductID、Price_retail 或 ProductName 字段。产品名称理论上可以考虑本地化,但我不认为它适用。要本地化此条目,我们首先需要通过添加 languages_supported 字符串字段来指定此条目支持哪些语言。我们修改后的表现在具有以下结构

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)

我们将使用逗号分隔的支持语言 ID 字符串列表

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

如果我们支持英语和西班牙语,Languages_Supported 字段将如下所示

Languages_supported  0,1

我们现在必须添加与整个应用程序支持的语言数量相等的本地化字段。尽管我们目前只在表中支持英语,但整个应用程序支持 4 种语言。这是我们示例表的最终结构

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)

现在每个字段的末尾都附加了语言 ID。现在我们可以获取任何支持语言的任何字段。如果我们的记录集只支持英语,而整个应用程序支持四种不同的语言怎么办?这个问题在记录生成时解决。无论记录最终将支持多少种语言,我们都会将记录创建时使用的任何语言填充到所有语言字段中。因此,如果此记录只支持英语,则 Description0-3 将全部包含英语。复制数据可能看起来很浪费,但请记住我们正在用速度换取大小。使用上述方法,我们可以通过提取 Description0 来查询整个英文数据库,或通过 Description1 来查询西班牙文数据库,我们不需要验证每个条目是否符合要求。

整合

本文档涵盖了大量内容,但现在我们将把它们整合在一起。通过使用名为 USING_LANGUAGE 的变量,我们现在能够更改页面显示的语言。通过使用名为 USING_CURRENCY 的变量,我们可以更改货币显示的面额。由于我们已经对整个数据库进行了本地化,我们现在可以使用相同的变量(USING_LANGUAGE - 已在每个页面上定义)来知道要提取哪些字段。

从头开始,我们为将新语言和货币无缝集成到我们的应用程序中奠定了基础。通过在数据库端牺牲空间换取速度,使用第三方解决方案进行货币兑换,以及我们使用“语言包含文件”,最大限度地提高了开发时间和应用程序速度。在规划应用程序本地化时,我对细节的关注怎么强调都不为过。项目中的每个人,从销售人员到开发人员,都需要沟通并了解彼此的职责和时间表。只有团队合作,像电子商务网站这样庞大的项目才能成功本地化并发布。

© . All rights reserved.