locale --- 國(guó)際化服務(wù)?

源代碼: Lib/locale.py


locale 模塊開(kāi)通了 POSIX 本地化數(shù)據(jù)庫(kù)和功能的訪問(wèn)。POSIX 本地化機(jī)制讓程序員能夠?yàn)閼?yīng)用程序處理某些本地化的問(wèn)題,而不需要去了解運(yùn)行軟件的每個(gè)國(guó)家的全部文化特點(diǎn)。

locale 模塊是在 _locale 模塊的基礎(chǔ)上實(shí)現(xiàn)的,而 _locale 則又用到了 ANSI C 語(yǔ)言實(shí)現(xiàn)的本地化功能。

locale 模塊定義了以下異常和函數(shù):

exception locale.Error?

當(dāng)傳給 setlocale() 的 locale 無(wú)法識(shí)別時(shí),會(huì)觸發(fā)異常。

locale.setlocale(category, locale=None)?

如果給定了 locale 而不是 None,setlocale() 會(huì)修改 category 的 locale 設(shè)置??捎玫念悇e會(huì)在下面的數(shù)據(jù)描述中列出。locale 可以是一個(gè)字符串,也可以是兩個(gè)字符串(語(yǔ)言代碼和編碼)組成的可迭代對(duì)象。若為可迭代對(duì)象,則會(huì)用地區(qū)別名引擎轉(zhuǎn)換為一個(gè)地區(qū)名稱。若為空字符串則指明采用用戶的默認(rèn)設(shè)置。如果 locale 設(shè)置修改失敗,會(huì)觸發(fā) Error 異常。如果成功則返回新的 locale 設(shè)置。

如果省略 locale 或?yàn)?None,將返回 category 但當(dāng)前設(shè)置。

setlocale() 在大多數(shù)系統(tǒng)上都不是線程安全的。應(yīng)用程序通常會(huì)如下調(diào)用:

import locale
locale.setlocale(locale.LC_ALL, '')

這會(huì)把所有類別的 locale 都設(shè)為用戶的默認(rèn)設(shè)置(通常在 LANG 環(huán)境變量中指定)。如果后續(xù) locale 沒(méi)有改動(dòng),則使用多線程應(yīng)該不會(huì)產(chǎn)生問(wèn)題。

locale.localeconv()?

以字典的形式返回本地約定的數(shù)據(jù)庫(kù)。此字典具有以下字符串作為鍵:

類別

(Windows 注冊(cè)表的)鍵

含義

LC_NUMERIC

'decimal_point'

小數(shù)點(diǎn)字符。

'grouping'

數(shù)字列表,指定 'thousands_sep' 應(yīng)該出現(xiàn)的位置。 如果列表以 CHAR_MAX 結(jié)束,則不會(huì)作分組。如果列表以 0 結(jié)束,則重復(fù)使用最后的分組大小。

'thousands_sep'

組之間使用的字符。

LC_MONETARY

'int_curr_symbol'

國(guó)際貨幣符號(hào)。

'currency_symbol'

當(dāng)?shù)刎泿欧?hào)。

'p_cs_precedes/n_cs_precedes'

貨幣符號(hào)是否在值之前(對(duì)于正值或負(fù)值)。

'p_sep_by_space/n_sep_by_space'

貨幣符號(hào)是否通過(guò)空格與值分隔(對(duì)于正值或負(fù)值)。

'mon_decimal_point'

用于貨幣金額的小數(shù)點(diǎn)。

'frac_digits'

貨幣值的本地格式中使用的小數(shù)位數(shù)。

'int_frac_digits'

貨幣價(jià)值的國(guó)際格式中使用的小數(shù)位數(shù)。

'mon_thousands_sep'

用于貨幣值的組分隔符。

'mon_grouping'

相當(dāng)于 'grouping' ,用于貨幣價(jià)值。

'positive_sign'

用于標(biāo)注正貨幣價(jià)值的符號(hào)。

'negative_sign'

用于注釋負(fù)貨幣價(jià)值的符號(hào)。

'p_sign_posn/n_sign_posn'

符號(hào)的位置(對(duì)于正值或負(fù)值),見(jiàn)下文。

可以將所有數(shù)值設(shè)置為 CHAR_MAX ,以指示此語(yǔ)言環(huán)境中未指定任何值。

下面給出了 'p_sign_posn''n_sign_posn' 的可能值。

解釋

0

被括號(hào)括起來(lái)的貨幣和金額。

1

該標(biāo)志應(yīng)位于值和貨幣符號(hào)之前。

2

該標(biāo)志應(yīng)位于值和貨幣符號(hào)之后。

3

標(biāo)志應(yīng)該緊跟在值之前。

4

標(biāo)志應(yīng)該緊跟值項(xiàng)。

CHAR_MAX

此語(yǔ)言環(huán)境中未指定任何內(nèi)容。

該函數(shù)將 LC_CTYPE 地區(qū)設(shè)為 LC_NUMERIC 地區(qū),若地區(qū)不同且數(shù)字或貨幣字符為非 ASCII,則設(shè)置為 LC_MONETARY 地區(qū)。這個(gè)臨時(shí)的改變會(huì)影響到其他線程。

在 3.7 版更改: 現(xiàn)在在某些情況下,該函數(shù)會(huì)將 LC_CTYPE 地區(qū)設(shè)為 LC_NUMERIC 地區(qū)。

locale.nl_langinfo(option)?

以字符串形式返回一些地區(qū)相關(guān)的信息。本函數(shù)并非在所有系統(tǒng)都可用,而且可用的 option 在不同平臺(tái)上也可能不同??商畹膮?shù)值為數(shù)值,在 locale 模塊中提供了對(duì)應(yīng)的符號(hào)常量。

nl_langinfo() 函數(shù)可接受以下值。大部分含義都取自 GNU C 庫(kù)。

locale.CODESET?

獲取一個(gè)字符串,代表所選地區(qū)采用的字符編碼名稱。

locale.D_T_FMT?

獲取一個(gè)字符串,可用作 time.strftime() 的格式串,以便以地區(qū)特定格式表示日期和時(shí)間。

locale.D_FMT?

獲取一個(gè)字符串,可用作 time.strftime() 的格式串,以便以地區(qū)特定格式表示日期。

locale.T_FMT?

獲取一個(gè)字符串,可用作 time.strftime() 的格式串,以便以地區(qū)特定格式表示時(shí)間。

locale.T_FMT_AMPM?

獲取一個(gè)字符串,可用作 time.strftime() 的格式串,以便以 am/pm 的格式表示時(shí)間。

DAY_1 ... DAY_7

獲取一周中第 n 天的名稱。

注解

這里遵循美國(guó)慣例,即 DAY_1 是星期天,而不是國(guó)際慣例(ISO 8601),即星期一是一周的第一天。

ABDAY_1 ... ABDAY_7

獲取一周中第 n 天的縮寫名稱。

MON_1 ... MON_12

獲取第 n 個(gè)月的名稱。

ABMON_1 ... ABMON_12

獲取第 n 個(gè)月的縮寫名稱。

locale.RADIXCHAR?

獲取小數(shù)點(diǎn)字符(小數(shù)點(diǎn)、小數(shù)逗號(hào)等)。

locale.THOUSEP?

獲取千位數(shù)(三位數(shù)一組)的分隔符。

locale.YESEXPR?

獲取一個(gè)可供 regex 函數(shù)使用的正則表達(dá)式,用于識(shí)別需要回答是或否的問(wèn)題的肯定回答。

注解

該表達(dá)式的語(yǔ)法適用于 C 庫(kù)的 regex() 函數(shù),可能與 re 中的語(yǔ)法不一樣。

locale.NOEXPR?

獲取一個(gè)可供 regex(3) 函數(shù)使用的正則表達(dá)式,用于識(shí)別需要回答是或否的問(wèn)題的否定回答。

locale.CRNCYSTR?

獲取貨幣符號(hào),如果符號(hào)應(yīng)位于數(shù)字之前,則在其前面加上“-”;如果符號(hào)應(yīng)位于數(shù)字之后,則前面加“+”;如果符號(hào)應(yīng)取代小數(shù)點(diǎn)字符,則前面加“.”。

locale.ERA?

獲取一個(gè)字符串,代表當(dāng)前地區(qū)使用的紀(jì)元。

大多數(shù)地區(qū)都沒(méi)有定義該值。定義了該值的一個(gè)案例日本。日本傳統(tǒng)的日期表示方法中,包含了當(dāng)時(shí)天皇統(tǒng)治朝代的名稱。

通常沒(méi)有必要直接使用該值。在格式串中指定 E 符號(hào),會(huì)讓 time.strftime() 函數(shù)啟用此信息。返回字符串的格式并沒(méi)有定義,因此不得假定各個(gè)系統(tǒng)都能理解。

locale.ERA_D_T_FMT?

獲取一個(gè)字符串,可用作 time.strftime() 的格式串,以便以地區(qū)特定格式表示帶紀(jì)元的日期和時(shí)間。

locale.ERA_D_FMT?

獲取一個(gè)字符串,可用作 time.strftime() 的格式串,以便以地區(qū)特定格式表示帶紀(jì)元的日期。

locale.ERA_T_FMT?

獲取一個(gè)字符串,可用作 time.strftime() 的格式串,以便以地區(qū)特定格式表示帶紀(jì)元的時(shí)間。

locale.ALT_DIGITS?

獲取 0 到 99 的表示法,最多不超過(guò) 100 個(gè)值。

locale.getdefaultlocale([envvars])?

嘗試確定默認(rèn)的地區(qū)設(shè)置,并以 (language code, encoding) 元組的形式返回。

根據(jù) POSIX 的規(guī)范,未調(diào)用 setlocale(LC_ALL, '') 的程序采用可移植的 'C' 區(qū)域設(shè)置運(yùn)行。 調(diào)用 setlocale(LC_ALL, '') 則可采用 LANG 變量定義的默認(rèn)區(qū)域。 由于不想干擾當(dāng)前的區(qū)域設(shè)置,因此就以上述方式進(jìn)行了模擬。

為了維持與其他平臺(tái)的兼容性,不僅需要檢測(cè) LANG 變量,還需要檢測(cè) envvars 參數(shù)給出的變量列表。首先發(fā)現(xiàn)的定義將被采用。 envvars 默認(rèn)為 GNU gettext 采用的搜索路徑;必須包含 'LANG' 變量。 GNU gettext 的搜索路徑依次包含了 'LC_ALL'、'LC_CTYPE'、'LANG''LANGUAGE'

除了 'C' 之外,語(yǔ)言代碼對(duì)應(yīng) RFC 1766 標(biāo)準(zhǔn)。如果 語(yǔ)言代碼編碼 不能確定,可為 None。

locale.getlocale(category=LC_CTYPE)?

以列表的形式返回指定地區(qū)類別的當(dāng)前設(shè)置,結(jié)果包括 語(yǔ)言代碼 、編碼。category 可以是 LC_* 之一, LC_ALL 除外。默認(rèn)為 LC_CTYPE

除了 'C' 之外,語(yǔ)言代碼對(duì)應(yīng) RFC 1766 標(biāo)準(zhǔn)。如果 語(yǔ)言代碼編碼 不能確定,可為 None。

locale.getpreferredencoding(do_setlocale=True)?

Return the encoding used for text data, according to user preferences. User preferences are expressed differently on different systems, and might not be available programmatically on some systems, so this function only returns a guess.

某些系統(tǒng)必須調(diào)用 setlocale() 才能獲取用戶偏好,所以本函數(shù)不是線程安全的。如果不需要或不希望調(diào)用 setlocale,do_setlocale 應(yīng)設(shè)為 False

On Android or in the UTF-8 mode (-X utf8 option), always return 'UTF-8', the locale and the do_setlocale argument are ignored.

在 3.7 版更改: The function now always returns UTF-8 on Android or if the UTF-8 mode is enabled.

locale.normalize(localename)?

為給定的區(qū)域名稱返回標(biāo)準(zhǔn)代碼。返回的區(qū)域代碼已經(jīng)格式化,可供 setlocale() 使用。 如果標(biāo)準(zhǔn)化操作失敗,則返回原名稱。

如果給出的編碼無(wú)法識(shí)別,則本函數(shù)默認(rèn)采用區(qū)域代碼的默認(rèn)編碼,這正類似于 setlocale()。

locale.resetlocale(category=LC_ALL)?

category 的區(qū)域設(shè)為默認(rèn)值。

默認(rèn)設(shè)置通過(guò)調(diào)用 getdefaultlocale() 確定。category 默認(rèn)為 LC_ALL。

locale.strcoll(string1, string2)?

根據(jù)當(dāng)前的 LC_COLLATE 設(shè)置,對(duì)兩個(gè)字符串進(jìn)行比較。與其他比較函數(shù)一樣,根據(jù) string1 位于 string2 之前、之后或是相同,返回負(fù)值、、正值或者 0。

locale.strxfrm(string)?

將字符串轉(zhuǎn)換為可用于本地化比較的字符串。例如 strxfrm(s1) < strxfrm(s2) 相當(dāng)于 strcoll(s1, s2) < 0。在重復(fù)比較同一個(gè)字符串時(shí),可能會(huì)用到本函數(shù),比如整理字符串列表時(shí)。

locale.format_string(format, val, grouping=False, monetary=False)?

根據(jù)當(dāng)前的 LC_NUMERIC 設(shè)置,對(duì)數(shù)字 val 進(jìn)行格式化。格式將遵循 % 運(yùn)算符的約定。浮點(diǎn)值的小數(shù)點(diǎn)會(huì)按需修改。若 grouping 為 True,則還會(huì)考慮分組。

monetary 為 True,則會(huì)用到貨幣千位分隔符和分組字符串。

格式化符的處理類似 format % val ,但會(huì)考慮到當(dāng)前的區(qū)域設(shè)置。

在 3.7 版更改: 增加了關(guān)鍵字參數(shù) monetary

locale.format(format, val, grouping=False, monetary=False)?

請(qǐng)注意,本函數(shù)的工作原理與 format_string() 類似,但只對(duì) %char 格式符起作用。 比如 '%f''%.0f' 都是有效的格式符,但 '%f KiB' 則不是。

若想用到全部的格式化串,請(qǐng)采用 format_string()。

3.7 版后已移除: 請(qǐng)改用 format_string()?。

locale.currency(val, symbol=True, grouping=False, international=False)?

根據(jù)當(dāng)前的 LC_MONETARY 設(shè)置,對(duì)數(shù)字 val 進(jìn)行格式化。

如果 symbol 為 True(默認(rèn)值),則返回的字符串將包含貨幣符號(hào)。如果 grouping 為 True(非默認(rèn)值),則會(huì)進(jìn)行分組。如果 international 為 True(非默認(rèn)值),將采用國(guó)際貨幣符號(hào)。

請(qǐng)注意,本函數(shù)對(duì)區(qū)域 “C” 無(wú)效,所以必須先通過(guò) setlocale() 設(shè)置一個(gè)區(qū)域。

locale.str(float)?

對(duì)浮點(diǎn)數(shù)進(jìn)行格式化,格式要求與內(nèi)置函數(shù) str(float) 相同,但會(huì)考慮小數(shù)點(diǎn)。

locale.delocalize(string)?

根據(jù) LC_NUMERIC 的設(shè)置,將字符串轉(zhuǎn)換為格式化后的數(shù)字字符串。

3.5 新版功能.

locale.atof(string)?

根據(jù) LC_NUMERIC 的設(shè)置,將字符串轉(zhuǎn)換為浮點(diǎn)數(shù)。

locale.atoi(string)?

按照 LC_NUMERIC 的約定,將字符串轉(zhuǎn)換為整數(shù)。

locale.LC_CTYPE?

字符型函數(shù)的區(qū)域類別。根據(jù)該類別的設(shè)置,模塊 string 中處理大小寫的函數(shù)會(huì)改變操作方式。

locale.LC_COLLATE?

字符串排序會(huì)用到的區(qū)域類別。 將會(huì)影響 locale 模塊的 strcoll()strxfrm() 函數(shù)。

locale.LC_TIME?

格式化時(shí)間時(shí)會(huì)用到的區(qū)域類別。 time.strftime() 函數(shù)會(huì)參考這些約定。

locale.LC_MONETARY?

格式化貨幣值時(shí)會(huì)用到的區(qū)域類別。可用值可由 localeconv() 函數(shù)獲取。

locale.LC_MESSAGES?

顯示消息時(shí)用到的區(qū)域類別。目前 Python 不支持應(yīng)用定制的本地化消息。 由操作系統(tǒng)顯示的消息,比如由 os.strerror() 返回的消息可能會(huì)受到該類別的影響。

locale.LC_NUMERIC?

格式化數(shù)字時(shí)用到的區(qū)域類別。 locale 模塊的 format() 、 atoi() 、 atof()str() 函數(shù)會(huì)受到該類別的影響。其他所有數(shù)字格式化操作不受影響。

locale.LC_ALL?

混合所有的區(qū)域設(shè)置。如果在區(qū)域改動(dòng)時(shí)使用該標(biāo)志,將嘗試設(shè)置所有類別的區(qū)域參數(shù)。只要有任何一個(gè)類別設(shè)置失敗,就不會(huì)修改任何類別。在使用此標(biāo)志獲取區(qū)域設(shè)置時(shí),會(huì)返回一個(gè)代表所有類別設(shè)置的字符串。之后可用此字符串恢復(fù)設(shè)置。

locale.CHAR_MAX?

一個(gè)符號(hào)常量, localeconv() 返回多個(gè)值時(shí)將會(huì)用到。

示例:

>>> import locale
>>> loc = locale.getlocale()  # get current locale
# use German locale; name might vary with platform
>>> locale.setlocale(locale.LC_ALL, 'de_DE')
>>> locale.strcoll('f\xe4n', 'foo')  # compare a string containing an umlaut
>>> locale.setlocale(locale.LC_ALL, '')   # use user's preferred locale
>>> locale.setlocale(locale.LC_ALL, 'C')  # use default (C) locale
>>> locale.setlocale(locale.LC_ALL, loc)  # restore saved locale

背景、細(xì)節(jié)、提示、技巧和注意事項(xiàng)?

The C standard defines the locale as a program-wide property that may be relatively expensive to change. On top of that, some implementation are broken in such a way that frequent locale changes may cause core dumps. This makes the locale somewhat painful to use correctly.

當(dāng)程序第一次啟動(dòng)時(shí),無(wú)論用戶偏好定義成什么,區(qū)域值都是 C。不過(guò)有一個(gè)例外,就是在啟動(dòng)時(shí)修改 LC_CTYPE 類別,設(shè)置當(dāng)前區(qū)域編碼為用戶偏好編碼。程序必須調(diào)用 setlocale(LC_ALL, '') 明確表示用戶偏好區(qū)域?qū)⒃O(shè)為其他類別。

若要從庫(kù)程序中調(diào)用 setlocale() ,通常這不是個(gè)好主意,因?yàn)楦弊饔檬菚?huì)影響整個(gè)程序。保存和恢復(fù)區(qū)域設(shè)置也幾乎一樣糟糕:不僅代價(jià)高昂,而且會(huì)影響到恢復(fù)之前運(yùn)行的其他線程。

如果是要編寫通用模塊,需要有一種不受區(qū)域設(shè)置影響的操作方式(比如某些用到 time.strftime() 的格式),將不得不尋找一種不用標(biāo)準(zhǔn)庫(kù)的方案。更好的辦法是說(shuō)服自己,可以采納區(qū)域設(shè)置。只有在萬(wàn)不得已的情況下,才能用文檔標(biāo)注出模塊與非 C 區(qū)域設(shè)置不兼容。

根據(jù)區(qū)域設(shè)置進(jìn)行數(shù)字運(yùn)算的唯一方法,就是采用本模塊定義的函數(shù):atof()atoi() 、 format()str()。

無(wú)法根據(jù)區(qū)域設(shè)置進(jìn)行大小寫轉(zhuǎn)換和字符分類。對(duì)于(Unicode)文本字符串來(lái)說(shuō),這些操作都是根據(jù)字符值進(jìn)行的;而對(duì)于字節(jié)符串來(lái)說(shuō),轉(zhuǎn)換和分類則是根據(jù)字節(jié)的 ASCII 值進(jìn)行的,高位被置位的字節(jié)(即非 ASCII 字節(jié))永遠(yuǎn)不會(huì)被轉(zhuǎn)換或被視作字母或空白符之類。

針對(duì)擴(kuò)展程序編寫人員和嵌入Python 運(yùn)行的程序?

除了要查詢當(dāng)前區(qū)域,擴(kuò)展模塊不應(yīng)去調(diào)用 setlocale()。但由于返回值只能用于恢復(fù)設(shè)置,所以也沒(méi)什么用(也許只能用于確認(rèn)是否為 C)。

當(dāng) Python 代碼利用 locale 模塊修改區(qū)域設(shè)置時(shí),也會(huì)影響到嵌入 Python 運(yùn)行的應(yīng)用程序。如果嵌入運(yùn)行的程序不希望發(fā)生這種情況,則應(yīng)從 config.c 文件的內(nèi)置模塊表中刪除 _locale 擴(kuò)展模塊(所有操作均是由它完成的),并確保 _locale 模塊不能成為一個(gè)共享庫(kù)。

訪問(wèn)信息目錄?

locale.gettext(msg)?
locale.dgettext(domain, msg)?
locale.dcgettext(domain, msg, category)?
locale.textdomain(domain)?
locale.bindtextdomain(domain, dir)?

在提供 gettext 接口的系統(tǒng)中,locale 模塊暴露出了 C 庫(kù)的接口。它由 gettext()dgettext() 、dcgettext()textdomain() 、bindtextdomain()bind_textdomain_codeset() 等函數(shù)組成。 他們與 gettext 模塊中的同名函數(shù)類似,但采用了 C 庫(kù)二進(jìn)制格式的消息目錄,以及 C 庫(kù)的搜索算法來(lái)查找消息目錄。

Python 應(yīng)用程序通常不需要調(diào)用這些函數(shù),而應(yīng)改用 gettext。這條規(guī)則的一個(gè)已知例外,是與附加 C 庫(kù)鏈接的應(yīng)用程序,他們?cè)趦?nèi)部調(diào)用了 gettext()dcgettext()。對(duì)于這些應(yīng)用程序,可能有必要綁定文本域,以便庫(kù)可以準(zhǔn)確找到他們的信息目錄。