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

源代碼: Lib/locale.py


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

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 沒有改動(dòng),則使用多線程應(yīng)該不會(huì)產(chǎn)生問(wèn)題。

locale.localeconv()?

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

類別

含意

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ù)值),見下文。

可以將所有數(shù)值設(shè)置為 CHAR_MAX ,以指示本 locale 中未指定任何值。

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

說(shuō)明

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)該緊跟在值之后。

CHAR_MAX

該地區(qū)未指定內(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ū)都沒有定義該值。定義了該值的一個(gè)案例日本。日本傳統(tǒng)的日期表示方法中,包含了當(dāng)時(shí)天皇統(tǒng)治朝代的名稱。

通常沒有必要直接使用該值。在格式串中指定 E 符號(hào),會(huì)讓 time.strftime() 函數(shù)啟用此信息。返回字符串的格式并沒有定義,因此不得假定各個(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ǔ)言代碼編碼 無(wú)法確定,則可為 None。

3.11 版后已移除: 3.13

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ǔ)言代碼編碼 無(wú)法確定,則可為 None。

locale.getpreferredencoding(do_setlocale=True)?

根據(jù)用戶的偏好,返回用于文本數(shù)據(jù)的 locale encoding。用戶偏好在不同的系統(tǒng)上有不同的表達(dá)方式,而且在某些系統(tǒng)上可能無(wú)法以編程方式獲取到,所以本函數(shù)只是返回猜測(cè)結(jié)果。

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

On Android or if the Python UTF-8 Mode is enabled, always return 'utf-8', the locale encoding and the do_setlocale argument are ignored.

Python preinitialization 用于配置 LC_CTYPE 區(qū)域。還請(qǐng)參閱 filesystem encoding and error handler。

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

locale.getencoding()?

Get the current locale encoding:

  • On Android and VxWorks, return "utf-8".

  • On Unix, return the encoding of the current LC_CTYPE locale. Return "utf-8" if nl_langinfo(CODESET) returns an empty string: for example, if the current LC_CTYPE locale is not supported.

  • On Windows, return the ANSI code page.

Python preinitialization 用于配置 LC_CTYPE 區(qū)域。還請(qǐng)參閱 filesystem encoding and error handler。

This function is similar to getpreferredencoding(False) except this function ignores the Python UTF-8 Mode.

3.11 新版功能.

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。

3.11 版后已移除: 3.13

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() 類似,但只認(rèn)一種 %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)換為標(biāo)準(zhǔn)化的數(shù)字字符串。

3.5 新版功能.

locale.localize(string, grouping=False, monetary=False)?

根據(jù) LC_NUMERIC 的設(shè)置,將標(biāo)準(zhǔn)化的數(shù)字字符串轉(zhuǎn)換為格式化的字符串。

3.10 新版功能.

locale.atof(string, func=float)?

Converts a string to a number, following the LC_NUMERIC settings, by calling func on the result of calling delocalize() on string.

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)?

C 語(yǔ)言標(biāo)準(zhǔn)將區(qū)域定義為程序級(jí)別的屬性,修改的代價(jià)可能相對(duì)較高。此外,有某些實(shí)現(xiàn)代碼寫得不好,頻繁改變區(qū)域可能會(huì)導(dǎo)致內(nèi)核崩潰。于是要想正確使用區(qū)域就變得有些痛苦。

當(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è)置,所以也沒什么用(也許只能用于確認(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)確找到其消息目錄。