资讯专栏INFORMATION COLUMN

Python locale 多语言模块和我遇到的坑

tracymac7 / 3591人阅读

摘要:遇到的问题今天工作上遇到一个相关的问题,关于字符串格式化的。是根据计算机用户所使用的语言,所在国家或者地区,以及当地的文化传统所定义的一个软件运行时的语言环境。

locale遇到的问题

今天工作上遇到一个 locale 相关的问题,关于字符串格式化的。不过让我们先从 locale 说起。

locale 简介 什么是locale

locale 这个单词中文翻译成地区或者地域,其实这个单词包含的意义要宽泛很多。locale 是根据计算机用户所使用的语言,所在国家或者地区,以及当地的文化传统所定义的一个软件运行时的语言环境。通常情况下它可以按照涉及使用习惯分为12大类:

- 语言符号及其分类(LC_CTYPE)
- 数字(LC_NUMBERIC)
- 比较习惯(LC_COLLATE)
- 时间显示格式(LC_TIME)
- 货币单位(LC_MONETARY)
- 信息主要是提示信息,错误信息,状态信息,标题,标签,按钮和菜单等(LC_MESSAGES)
- 行么书写方式(LC_NAME)
- 地址书写方式(LC_ADDRESS)
- 电话号码书写方式(LC_TELEPHONE)
-度量衡表达方式(LC_MEASUREMENT)
- 默认纸张尺寸大小(LC_PAPER)
- 对locale 自身包含信息的概述(LC_IDENTIFICATION)
- 除此之外还有一个LANGUAGE参数,它与LC_MESSAGES相似

比如像下面的例子里:

在“简体中文”环境,运行date 命令,显示的是:
2016年11月24日 星期四 22时59分26秒 CST

而在英文环境下,运行date 命令,显示的是
Thu Nov 24 23:05:12 CST 2016

简单来说, locale 为计算机上提供了国际化和本地化转化的环境

locale 相关命令

在Unix下可以通过命令 locale 来查看当前语言环境,我的Mac上的显示如下:

➜  locale
LANG=
LC_COLLATE="zh_CN.UTF-8"
LC_CTYPE="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_ALL="zh_CN.UTF-8"

locale值格式类似为: 语言_地区.字符集

可以这样来查看系统支持locals值

locale -a

可以用如下的方式来临时改变shell的locale设定:

➜  test git:(master) ✗ LC_ALL=C
➜  test git:(master) ✗ export LC_ALL
➜  test git:(master) ✗ locale
LANG=
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL="C"

设置的时候注意以下几点:

LANG,LC*的默认值,是最低级别的设置,如果LC*没有设置,则使用该值。类似于 LCALL

LCALL,它是一个宏,如果该值设置了,则该值会覆盖所有LC*的设置值。注意,LANG的值不受该宏影响

LCALL=C 意思是去除所有本地化的设置

Python locale

python提供了 locale 这个模块,可以用来操作locale相关数据,官方文档参见这里。
其中主要的结果方法如下

import locale

# 返回当前环境locale categorg相关的设定,category默认为 LC_CTYPE
# LC_CTYPE 决定字符处理函数相关行为,比如 string 函数
locale.getlocale([category])


# 尝试判断默认的locale设置,并且以元组的形式返回(language code, encoding)
locale.getdefaultlocale([envvars])


# 修改locale category 的设定为 locale的值, 比如locale.setlocale(locale.LC_ALL, "C"),  C 代表去除所有本地化设置
# 如果第二个参数locale没有提供,那么会返回category的设置
locale.setlocale(category[, locale])


# 很多程序会像下面这样开头,这样做会将所有的locale设置成用户默认的设置(通常是环境变量LANF的值)。
# 但setlocale() 不能在所有系统上保证线程安全性,这点要注意
import locale
locale.setlocale(locale.LC_ALL, "")

当在shell里启动python repl(交互器)时,默认的环境local设置为"C", 也就是没有本地化设置,这时候可以通过 locale.getdefaultlocale() 来查看shell当前环境的locale设置, 并通过 locale.setlocale(locale.LC_ALL, "") 将python解释器的locale设置成shell环境的locale,具体事例如下:

Python 2.7.10 (default, Oct 23 2015, 19:19:21)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale

>>> locale.getlocale()
(None, None)

>>> locale.getdefaultlocale()
("zh_CN", "UTF-8")

>>> locale.setlocale(locale.LC_ALL, "")
"zh_CN.UTF-8"

>>> locale.getdefaultlocale()
("zh_CN", "UTF-8")

>>> locale.getlocale()
("zh_CN", "UTF-8")
我踩的坑 strptime 和 strftime

正所谓当局者迷,今天当我遇到同样的代码,不同的环境(shell执行和pycharm执行)居然有不同的执行结果时,我百思不得其姐(嘿嘿)。
代码片段是关于 strptime 的:

import time
time.strptime("Thu, 24 Nov 2016 07:01:59 GMT", "%a, %d %b %Y %H:%M:%S GMT")

其实呢,strptime或者strftime格式化参数里有一些是跟locale相关的,比如这里的 %a %b 等,所以在不对的 locale 环境下,格式化出现了错误。

可以参考下面的示例:

Python 2.7.10 (default, Oct 23 2015, 19:19:21)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.strptime("Thu, 24 Nov 2016 07:01:59 GMT", "%a, %d %b %Y %H:%M:%S GMT")
time.struct_time(tm_year=2016, tm_mon=11, tm_mday=24, tm_hour=7, tm_min=1, tm_sec=59, tm_wday=3, tm_yday=329, tm_isdst=-1)
>>> import locale
>>> locale.setlocale(locale.LC_ALL, "")
"zh_CN.UTF-8"
>>> time.strptime("Thu, 24 Nov 2016 07:01:59 GMT", "%a, %d %b %Y %H:%M:%S GMT")
Traceback (most recent call last):
  File "", line 1, in 
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_strptime.py", line 467, in _strptime_time
    return _strptime(data_string, format)[0]
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_strptime.py", line 325, in _strptime
    (data_string, format))
ValueError: time data "Thu, 24 Nov 2016 07:01:59 GMT" does not match format "%a, %d %b %Y %H:%M:%S GMT"
>>> time.strptime("2016 07:01:59", "%Y %H:%M:%S")
time.struct_time(tm_year=2016, tm_mon=1, tm_mday=1, tm_hour=7, tm_min=1, tm_sec=59, tm_wday=4, tm_yday=1, tm_isdst=-1)
>>>
阿里云oss sdk 使用遇到的问题

用阿里云oss-python-SDK上传文件时,当我本地locale设置成 zh_CN.UTF-8 时,就回一直出问题,原因就在于上述的 strptime, 阿里云sdk代码片段如下:

def to_unixtime(time_string, format_string):
    with _STRPTIME_LOCK:
        return int(calendar.timegm(time.strptime(time_string, format_string)))

然而从oss服务器上获得的timestring是这样的: Thu, 24 Nov 2016 07:01:59 GMT, 所以在我的环境里做格式化就会出错,所以我对代码做了如下修改:

def to_unixtime(time_string, format_string):
    with _STRPTIME_LOCK:
        time_locale = locale.setlocale(locale.LC_TIME)
        if time_locale.find("en") != 0 and time_locale != "C":
            locale.setlocale(locale.LC_TIME, "en_US")
            unixtime = int(calendar.timegm(time.strptime(time_string, format_string)))
            locale.setlocale(locale.LC_TIME, time_locale)
        else:
            unixtime = int(calendar.timegm(time.strptime(time_string, format_string)))
        return unixtime

在调用 strptime 这个方法前增加了兼容,先检查locale,如果不是英文类型并且不是默认的"C"类型时,将 LC_TIME 切换成英文,执行完 strptime 后再还原回来。

参考资料

https://docs.python.org/2/lib...

http://blog.csdn.net/Nicolase...

http://www.cnblogs.com/dolphi...

https://docs.python.org/2/lib...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44313.html

相关文章

  • 记一次开源学习--D2Admin 人人企业版

    摘要:前言上个月月底开源组开源了使用适配人人企业版专业版的前端工程具体详情见人人企业版适配发布。当然,也督促自己产出一篇相关的文章,来记录这次有趣的学习之旅。 Created by huqi at 2019-5-5 13:01:14 Updated by huqi at 2019-5-20 15:57:37 前言 上个月月底@D2开源组 开源了使用 D2Admin 适配 人人企业版(专业版) 的...

    notebin 评论0 收藏0
  • Python学习之路23-文本和字节序列

    摘要:字符编码表,码位码元将编码字符集中的码位转换成有限比特长度的整型值的序列。字符编码方案,码元序列化也称为常说的序列化。每个字节里的二进制数就是字节序列。另一个情况则是压缩字节序列的值,如或进程长度编码等无损压缩技术。 《流畅的Python》笔记。本篇主要讲述不同编码之间的转换问题,比较繁杂,如果平时处理文本不多,或者语言比较单一,没有多语言文本处理的需求,则可以略过此篇。 1. 前言 ...

    anRui 评论0 收藏0
  • 项目经验总结

    摘要:项目中前端开发问题经验总结下的安全限制问题问题描述数据看板中的数据大部分都是实时数据或前一天统计的历史数据,因此这边后端考虑采用来实时和定时推送数据来保证数据的实时性和有效性。 项目中前端开发问题经验总结 ie下websocket的安全限制问题 问题描述:数据看板中的数据大部分都是实时数据或前一天统计的历史数据,因此这边后端考虑采用websocket来实时和定时推送数据来保证数据的实时...

    William_Sang 评论0 收藏0
  • 在 React 项目中使用 React-intl 实现多语支持

    摘要:最近在项目中添加了语言国际化的功能。项目地址是雅虎的语言国际化开源项目的一部分,通过其提供的组件和可以与绑定。你当然可以使用的方式引用,但是,这样有前途么创建配置文件这里,我们将文件命名为和,代表中文和美式英语的配置包。 showImg(https://segmentfault.com/img/bVyv1N?w=900&h=506); 最近在项目中添加了语言国际化的功能。 语言国际化,...

    Mr_zhang 评论0 收藏0
  • 如何让一个vue项目支持多语(vue-i18n)

    摘要:引入是一个插件,主要作用就是让项目支持国际化多语言。所以新建一个文件夹,存放所有跟多语言相关的代码。目前包含三个文件。全局搜索发现一共有多个。 这两天手头的一个任务是给一个五六年的老项目添加多语言。这个项目庞大且复杂,早期是用jQuery实现的,两年前引入Vue并逐渐用组件替换了之前的Mustache风格模板。要添加多语言,不可避免存在很多文本替换的工作,这么庞杂的一个项目,怎么才能使...

    wuyumin 评论0 收藏0

发表评论

0条评论

tracymac7

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<