一、Tornado的语言国际化方法
Tornado做国际化折腾了一下下,Tornado这部分的官方文档太poor了。所以自己记录一下如何用tornado结合gettext做国际化。
第一步,在项目路径下建立./locales/zh_CN/LC_MESSAGES文件夹。
第二步,使用xgettext或poedit在第一步的文件夹下创建一个po文件,比如messages.po,我用poedit创建,比xgettext方便一些。
第三步,编辑该messages.po文件,当然,po文件有自己特定的格式,需要按照它的格式编写。
msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_CN\n" "X-Generator: Poedit 1.8.4\n" msgid "Sign in" msgstr "登入" msgid "Sign out" msgstr "登出" msgid "Username" msgstr "用户名" msgid "Password" msgstr "密码"
msgid是网页里原先的文本内容,msgstr是准备替换的内容。新内容直接用编辑器往后追加msgid和msgstr就可以了。
第四步,修改HTML网页模板
{% include '../header.html' %} <form method="post" action="/User/Signin"> {{ _("Sign in") }}<br/> {{ _("Username") }}<br/> <input type="text" name="username" /><br/> {{ _("Password") }}<br/> <input type="password" name="password" /><br /> {% module xsrf_form_html() %} <input type="submit" name="submit" value="{{ _("Sign in") }}" /> </form> {% include '../footer.html' %}
html里面的{{ _("Sign in") }}等内容就是需要gettext查找和替换的内容。
第五步,在tornado主文件内添加gettext支持的方法。
import os import tornado.autoreload import tornado.httpserver import tornado.ioloop import tornado.web import tornado.locale ''' ... ''' if __name__ == '__main__': tornado.locale.set_default_locale('zh_CN') tornado.locale.load_gettext_translations('./locales', 'messages') server = tornado.httpserver.HTTPServer(application) server.listen(20000) loop = tornado.ioloop.IOLoop.instance() tornado.autoreload.start(loop) loop.start()
由于我用的ubuntu系统,所以服务器端会被强制认为使用en_US编码,所以我作为调试,强制指定了set_default_locale('zh_CN'),然后使用tornado.locale.load_gettext_translations('./locales', 'messages')来读取locales文件夹下的messages项目的mo文件。
第六步,在自己写的Handler里面,加入locale.translate
class BaseHandler(tornado.web.RequestHandler): def get_current_user(self): _ = self.locale.translate user = self.get_secure_cookie('username') return user class SigninHandler(BaseHandler): def get(self): self.render('User/sign_in.html') def post(self): username = self.get_argument('username') password = self.get_argument('password') if username == 'xianglei': self.set_secure_cookie('username', 'xianglei') self.redirect('/') class SignoutHandler(BaseHandler): def get(self, *args, **kwargs): self.clear_all_cookies() self.redirect('/')
_=self.locale.translate,self.locale.translate实际是一个方法,那么把这个方法放到_这个对象里面,然后_方法会被自动代入到模板中去执行替换_("Sign in"),所以实际在模板里面写的 {{ _("Sign in") }}实际上是让Tornado执行tornado.locale.translate()方法。这样的话,如果我去掉之前的set_default_locale(),页面显示的就是英文的Sign in,加上,显示的就是中文的登入。
同样,Tornado也可以使用一个csv文件作为翻译的基础字典,默认是采用csv方式的。
二、Tornado作为HTTP client执行RESTful命令。
之前已经记录了Tornado异步的客户端,昨天调试了一下用Tornado做HDFS和YARN的RESTful客户端。HDFS的RESTful方式,不能使用异步,需要使用Tornado同步客户端才可以。HDFS和YARN的RESTful管理方式需要用到HTTP的四种查询方式,GET,POST,PUT,DELETE。其中PUT和DELETE的方式跟POST和GET很类似。
比如
class MakeDirectoryHandler(BaseHandler): @tornado.web.authenticated def post(self): host = self.get_argument('host') port = self.get_argument('port') directory = self.get_argument('directory') username = self.get_secure_cookie('username') base_url = 'http://'+host+':'+port+'/webhdfs/v1'+directory+'?op=MKDIRS&user.name='+username put_body = dict() put_body['op'] = 'MKDIRS' put_body['user.name'] = username put_body = urllib.urlencode(put_body) try: http = tornado.httpclient.HTTPClient() response = http.fetch( tornado.httpclient.HTTPRequest( url=base_url, method='PUT', body=put_body, ) ) self.write(response.body) except tornado.httpclient.HTTPError, e: self.write('{"errcode":"'+str(e).replace('\n', '<br />')+'"}')
HDFS的MKDIRS方法放在PUT组里面,所以提交的参数需要用urlencode进行编码转换后PUT给RESTful接口。
而DELETE则是。
class RemoveHandler(BaseHandler): @tornado.web.authenticated def post(self): host = self.get_argument('host') port = self.get_argument('port') filename = self.get_argument('filename') ''' If recursive = true, it use to remove whole directory If recursive = false, it use to remove a file or an empty directory The argument must be string. ''' recursive = self.get_argument('recursive') username = self.get_secure_cookie('username') base_url = 'http://'+host+':'+port+'/webhdfs/v1'+filename+'?op=DELETE&recursive='+recursive+'&user.name='+username try: http = tornado.httpclient.HTTPClient() response = http.fetch( tornado.httpclient.HTTPRequest( url=base_url, method='DELETE', ) ) self.write(response.body) except tornado.httpclient.HTTPError, e: self.write('{"errcode":"'+str(e).replace('\n', '<br />')+'"}')
跟GET方式一样,DELETE不需要封装传递参数。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。