摘要:國(guó)際化和本地化完成了博客引擎后,我們來(lái)考慮額外的一件事應(yīng)用的國(guó)際化和語(yǔ)言的本地化。國(guó)際化和本地化我們將分兩步討論,先是國(guó)際化,再是本地化。實(shí)際上,兩者是同步進(jìn)行的你在國(guó)際化的同時(shí),往往也是在本地化。
國(guó)際化和本地化
完成了博客引擎后,我們來(lái)考慮額外的一件事:Web應(yīng)用的國(guó)際化和語(yǔ)言的本地化。雖然我們可以一開(kāi)始就做這件事,但是最好還是先完成該應(yīng)用的單一語(yǔ)言版本,然后再添加其他語(yǔ)言的支持。
國(guó)際化和本地化我們將分兩步討論,先是國(guó)際化,再是本地化。這兩樣都會(huì)被重點(diǎn)提及。
國(guó)際化,在編程領(lǐng)域中,指的是移除本地特定的代碼。在Web應(yīng)用中,基本上是修改模板中特定于語(yǔ)言的交互文本。它還包括修改非文本的數(shù)據(jù)類(lèi)型:日期,貨幣和其他數(shù)字。
本地化,是打造應(yīng)用的本地版本。如果應(yīng)用已經(jīng)國(guó)際化了,就意味著存在一個(gè)或多個(gè)可選的本地版本。在Web應(yīng)用中,本地化主要是把交互文本翻譯成特定的語(yǔ)言。這里的“特定語(yǔ)言”,取決于瀏覽器和應(yīng)用自己的設(shè)置。
實(shí)際上,兩者是同步進(jìn)行的:你在國(guó)際化的同時(shí),往往也是在本地化。
YABE我們此次的起點(diǎn),是在Play安裝包的samples-and-tests/yabe中的已完成版本。目標(biāo)是徹底國(guó)際化應(yīng)用,然后添加簡(jiǎn)體中文的本地版本。(我擅自修改了教程的內(nèi)容 :D )
現(xiàn)在開(kāi)始吧。首先打開(kāi)conf/application.conf,去除注釋或添加一行來(lái)支持兩種語(yǔ)言:
# 為英文,簡(jiǎn)體中文本地化 application.langs=en,zh_CN
如果你現(xiàn)在啟動(dòng)應(yīng)用,Play命令行會(huì)顯示兩個(gè)Warning,因?yàn)槟氵€沒(méi)準(zhǔn)備好本地信息文件:
16:19:04,728 WARN ~ Messages file missing for locale en 16:19:04,729 WARN ~ Messages file missing for locale zh_CNUTF-8 信息文件
前面的警告提醒我們需要把現(xiàn)有的conf/messages文件替換成每個(gè)語(yǔ)言對(duì)應(yīng)一個(gè)信息文件:
messages.en messages.zh_CN
在這里,我們遇到跟一般在Java中的做法不一樣的地方。這些文件用的語(yǔ)法跟Java properties文件一樣,但它們不是properties文件,因?yàn)樗鼈冃枰褂肬TF-8編碼。而Java properties文件使用的是Latin-1編碼。
使用UTF-8進(jìn)行編碼能夠給本地化帶來(lái)很多的好處。這使得你可以用純文本記錄下本地化信息。比如,這意味著對(duì)于希臘本地化文本,原本需要:
hello.morning = u0152u222bu0152u00b1u0152u00aau0152u2211u0152u00bau0152u2260u0153u00c5u0152u00b1 hello.informal = u0152u2265u0152u00b5u0152u03c0u0152u00b1 u0153u00c9u0152u00f8u0153u00d6
現(xiàn)在只需直接使用希臘字母:
hello.morning = καλημ?ρα hello.informal = γεια σου
在本教程剩余部分,我們會(huì)在上述文件中定義信息,或在HTML模板中使用國(guó)際化標(biāo)記。
簡(jiǎn)單的信息最簡(jiǎn)單的情況是HTML模板中被包含起來(lái)的一條文本字符串。舉個(gè)例子,在yabe/app/views/main.html模板內(nèi)的tools列表中:
僅需使用&{"key"}語(yǔ)法,把該文本替換成待查找的信息,就能實(shí)現(xiàn)國(guó)際化:
添加對(duì)應(yīng)的行到每個(gè)信息文件,就能實(shí)現(xiàn)本地化。在conf/messages.en:
views.main.tools.login = Log in to write something
在conf/messages.zh_CN:
views.main.tools.login = 寫(xiě)點(diǎn)什么
具體的內(nèi)容由你來(lái)定;在這個(gè)例子中,我使用了一個(gè)鍵來(lái)標(biāo)記位置views/main.html#tools
一旦保存了更改,刷新一下,應(yīng)該可以看到原本的英文文本變成中文了。這是因?yàn)檎?qǐng)求中設(shè)定了Accept-Language為zh-CN的緣故。
應(yīng)用模型的本地化如果登錄進(jìn)博客的"admin"頁(yè)面,你就能看到文章,標(biāo)簽,評(píng)論和用戶的列表。這些頁(yè)面是CRUD模塊的功勞。對(duì)于每個(gè)頁(yè)面,標(biāo)題和列表頭是與應(yīng)用的模型,比如JavaBean類(lèi)和屬性名,聯(lián)系在一起的。
我們可以使用這些模型的名字作為信息鍵,來(lái)國(guó)際化CRUD模塊。就跟前面做的一樣:
在conf/messages.zh_CN
post = 文章 Post = 文章 posts = 文章列表 Posts = 文章列表 comment = 評(píng)論 Comment = 評(píng)論 comments = 評(píng)論列表 Comments = 評(píng)論列表 user = 用戶 User = 用戶 users = 用戶列表 Users = 用戶列表
你將注意到那些圓角的紫色導(dǎo)航鏈接沒(méi)有改變:
它們是在views/admin.html中定義的,通過(guò)用&{"..."}把文本包圍起來(lái),你就能把它們國(guó)際化:
&{"Posts"} … &{"Tags"} … &{"Comments"} … &{"Users"}帶參數(shù)的信息
除了字面量字符串,我們的應(yīng)用還包括帶有變量的信息,比如posts tagged with Play。
對(duì)于帶單個(gè)參數(shù)的字符串,用Java格式化字符串來(lái)插入?yún)?shù):
views.Application.listTagged.title = Posts tagged with %s
接著在模板中,添加這樣的參數(shù):
&{"views.Application.listTagged.title", tag}
當(dāng)一個(gè)信息包括多個(gè)參數(shù)時(shí),在格式化字符串中添加索引來(lái)指定參數(shù)順序:
views.Admin.index.welcome = Welcome %1$s, you have written %2$s posts so far
……然后就是這樣:
&{"views.Admin.index.welcome", user, posts.size()}
在這個(gè)例子中,我們想要使用“post”的正確的復(fù)數(shù)形式,所以也把這個(gè)詞當(dāng)做一個(gè)參數(shù):
views.Admin.index.welcome = Welcome %1$s, you have written %2$s %3$s so far
然后在模板中使用pluralize拓展:
&{"views.Admin.index.welcome", user, posts.size(), posts.pluralize(messages.get("post"), messages.get("posts"))}
注意我們需要使用messages.get來(lái)查找對(duì)應(yīng)的單數(shù)和復(fù)數(shù)形式。
對(duì)模型層的本地化對(duì)Play模型的本地化就跟對(duì)其他地方的本地化一樣。這個(gè)應(yīng)用使用到了CRUD和Secure模塊,意味著我們需要本地化play/modules/crud/conf/messages和play/modules/secure/conf/messages中的用到的信息。
在conf/messages.zh_CN:
# play/modules/crud (administration) crud.title = 管理面板 crud.home = 主頁(yè) crud.blank = 新增功能 crud.index.title = 選擇編輯對(duì)象 crud.index.objectType = 輸入對(duì)象 crud.index.action = crud.index.add = 添加 crud.add = &{%s} 添加 crud.list.title = &{%s} crud.list.size = %d &{%s} crud.list.totalSize = %d 總計(jì) crud.pagination.previous = ? 上一頁(yè) crud.pagination.next = 下一頁(yè) ? crud.pagination.last = 末頁(yè) ?? crud.pagination.first = ?? 首頁(yè) crud.show.title = &{%s} 編輯 crud.save = 保存 crud.saveAndContinue = 保存并繼續(xù)編輯 crud.cancel = 取消 crud.hasErrors = 請(qǐng)更正錯(cuò)誤 crud.blank.title = &{%s} 添加 crud.saveAndAddAnother = 保存并新增 crud.delete = &{%s} 刪除 crud.created = &{%s} 已創(chuàng)建 crud.saved = &{%s} 已保存 crud.deleted = &{%s} 已刪除 crud.delete.error = 此對(duì)象無(wú)法刪除 crud.search = 搜索 crud.none = (無(wú)) crud.help.required = 必填 crud.help.minlength = 至少要有 %d. crud.help.maxlength = 最多只能是 %d. crud.help.email = 需要有效郵箱 crud.help.dateformat = 時(shí)間格式 YYYY-MM-DD crud.help.numeric = 需要數(shù)值類(lèi)型 crud.help.min = 至少需要 %d crud.help.future = 在將來(lái) crud.help.past = 在之前 crud.help.after = 之上 %s. crud.help.before = 之下 %s. crud.help.range = 從 %d 到 %d # play/modules/secure secure.username = 您的郵箱: secure.password = 您的密碼: secure.signin = 馬上登錄特殊情況
當(dāng)你在本地化一個(gè)Web應(yīng)用時(shí),假如你正在使用一個(gè)基于組件的Web應(yīng)用框架,比如JavaServer Faces,難免會(huì)遇到一些難以下手的地方:
在屬性的值中用到了參數(shù)信息
格式化字符串中的信息
用作信息的鏈接
在Play里,這三點(diǎn)都不是問(wèn)題。
第一種情況,你在模板的屬性的值里用到了參數(shù)信息,比如:
這是JSF的一個(gè)問(wèn)題,因?yàn)橥ǔP枰褂肵ML標(biāo)簽來(lái)完成參數(shù)替換,而不能直接在屬性值里完成。在Play中,你可以直接這么寫(xiě):
第二種情況是在想要使用格式化字符串來(lái)排版一個(gè)值,比如用參數(shù)拼出By Bob on 2009-06-14這樣的日期格式。這又是由于使用XML標(biāo)簽來(lái)格式化所導(dǎo)致的問(wèn)題。本來(lái)如果能使用一個(gè)XML屬性的值來(lái)排版,就能解決這個(gè)問(wèn)題。在Play中,由于傳遞信息參數(shù)的語(yǔ)法不一樣,你不會(huì)遇到這樣的問(wèn)題。你可以:
&{"views.tags.display.author", _post.author.fullname, comment.postedAt.format("yyyy-MM-dd")}"}
你也可以這樣寫(xiě):
&{"views.tags.display.author", _post.author.fullname, comment.postedAt.format(messages.get("views.dateFormat"))}"}
第三種情況發(fā)生在你想把一個(gè)特定信息作為超鏈接的時(shí)候。在JSF,這是一個(gè)問(wèn)題。因?yàn)槌溄邮且粋€(gè)JSF組件,意味著它的標(biāo)記不能放在信息文件中。Play,正好相反,允許你在模板中使用原生HTML,所以你可以把用于URL的參數(shù)直接放入帶信息的標(biāo)記中:
logIn = Log in to write something &{"logIn", "/admin"}
我們應(yīng)用就曾用這樣的語(yǔ)法會(huì)讓框架生成基于路由文件的URL。要想在本地化的過(guò)程中處理它,使用:
&{"logIn"}, actionBridge.Admin.index()}最終成果
來(lái)看下我們給“Yet Another Blog Engine”進(jìn)行本地化(漢化)的結(jié)果。
其實(shí)沒(méi)有漢化完全,對(duì)吧……(╯▽╰)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64092.html
摘要:確保你的文本編輯器已經(jīng)做了相應(yīng)的配置。第一個(gè),會(huì)自動(dòng)監(jiān)測(cè)源代碼的改變并在運(yùn)行時(shí)自動(dòng)重載。檢查下面的一行是否出現(xiàn)在應(yīng)用日志中使用版本控制系統(tǒng)來(lái)追蹤變化當(dāng)你開(kāi)發(fā)一個(gè)項(xiàng)目時(shí),最好使用版本控制系統(tǒng)來(lái)存儲(chǔ)你的源代碼。 Play是一個(gè)Java Web敏捷開(kāi)發(fā)的框架http://www.playframework.com/documentation/1.2.7/home 之所以要翻譯這個(gè)教程,是因...
摘要:通過(guò)來(lái)實(shí)現(xiàn)一個(gè)基本的管理面板目前,我們還沒(méi)法使用博客的來(lái)寫(xiě)新的文章,或修改評(píng)論。提供了一個(gè)即開(kāi)即用的模塊,可以快速生成一個(gè)基本的管理面板。這是因?yàn)槟J(rèn)是以的輸出來(lái)得到一個(gè)模型對(duì)象的表示。在本教程的最后一章,你會(huì)學(xué)到關(guān)于本地化信息的更多東西。 通過(guò)CRUD來(lái)實(shí)現(xiàn)一個(gè)基本的管理面板 目前,我們還沒(méi)法使用博客的UI來(lái)寫(xiě)新的文章,或修改評(píng)論。Play提供了一個(gè)即開(kāi)即用的CRUD模塊,可以快速...
摘要:對(duì)的詳細(xì)配置已經(jīng)超出了本教程的范圍,但大體上看上去像這樣然后在中加入下面一行,讓本地的反向代理能夠連接上你的應(yīng)用這才只是個(gè)開(kāi)始如果一路上你一直跟著本教程,你應(yīng)該已經(jīng)懂得如何開(kāi)發(fā)一個(gè)應(yīng)用了。 部署應(yīng)用 如今我們已經(jīng)完成了博客引擎了。讓我們來(lái)看一下一些部署Play應(yīng)用的步驟。 定義一個(gè)框架ID 一般,你需要部署你的應(yīng)用到一臺(tái)跟開(kāi)發(fā)時(shí)不一樣的電腦。這臺(tái)電腦(很有可能是臺(tái)服務(wù)器)上面的P...
摘要:設(shè)置驗(yàn)證碼任何人都可以在我們的博客下發(fā)布評(píng)論,所以我們需要避免非人類(lèi)用戶來(lái)擾亂秩序。一個(gè)簡(jiǎn)單的防范方法是設(shè)置驗(yàn)證碼。然后我們修改表單來(lái)顯示驗(yàn)證碼,并把寫(xiě)入隱藏的域里面。檢查驗(yàn)證碼功能是否完成了。 設(shè)置驗(yàn)證碼 任何人都可以在我們的博客下發(fā)布評(píng)論,所以我們需要避免非人類(lèi)用戶來(lái)擾亂秩序。一個(gè)簡(jiǎn)單的防范方法是設(shè)置驗(yàn)證碼。 生成驗(yàn)證碼 如何利用Play框架來(lái)生成驗(yàn)證碼?簡(jiǎn)單來(lái)說(shuō),我們需要增...
摘要:瀏覽和提交評(píng)論博客主頁(yè)現(xiàn)在已經(jīng)完成,接下來(lái)要完成博客正文頁(yè)面。整個(gè)頁(yè)面將展示當(dāng)前文章的所有評(píng)論,還包括一個(gè)用于提交新的評(píng)論的表單。刷新瀏覽器,檢查這次是否使用了正確的。給模板添加表單在后面試下提交新的評(píng)論。 瀏覽和提交評(píng)論 博客主頁(yè)現(xiàn)在已經(jīng)完成,接下來(lái)要完成博客正文頁(yè)面。整個(gè)頁(yè)面將展示當(dāng)前文章的所有評(píng)論,還包括一個(gè)用于提交新的評(píng)論的表單。 創(chuàng)建show action 要顯示文章內(nèi)...
閱讀 2396·2021-11-24 10:26
閱讀 2586·2021-11-16 11:44
閱讀 1704·2021-09-22 15:26
閱讀 3583·2021-09-10 11:11
閱讀 3191·2021-09-07 10:25
閱讀 3631·2021-09-01 10:41
閱讀 1014·2021-08-27 13:11
閱讀 3513·2021-08-16 11:02