locale – POSIX 文化のローカライゼーション API

目的:ロケーションや言語に依存する値の解析やフォーマット
利用できるバージョン:1.5 以上

locale モジュールは Python の国際化の仕組みの一部でローカライゼーションをサポートするライブラリです。それはユーザの国やその言語に依存する可能性のある操作を扱うための標準的な方法を提供します。例えば、通貨のフォーマット、ソートの文字列比較、日付操作があります。locale モジュールは翻訳( gettext モジュールを参照)やユニコードエンコーディングについては対象としていません。

Note

ロケールを変更することはアプリケーション全体に影響を与えることがあります。そのため、推奨プラクティスはライブラリ内の値を変更しないことと、1度だけアプリケーションにロケールをセットさせることです。次にサンプルがあります。ここでは様々なロケールを設定することの違いを分かり易く説明するために何度かロケールを変更します。通常のアプリケーションは起動時に1度だけロケールを設定して、そのロケールを変更せずに使用することがずっと多いでしょう。

カレントロケールを調べる

ユーザにアプリケーションのロケール設定を変更させる最も一般的な方法は環境変数( LC_ALL, LANG, や LANGUAGE 等プラットホームに依存)を通して行うことです。アプリケーションはハードコーディングされた値ではなく locale.setlocale() を呼び出します。そして、環境変数の値が使用されます。

import locale
import os
import pprint
import codecs
import sys

sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)

# ユーザ環境に基づいたデフォルト設定
locale.setlocale(locale.LC_ALL, '')

print 'Environment settings:'
for env_name in [ 'LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE' ]:
    print '\t%s = %s' % (env_name, os.environ.get(env_name, ''))

# デフォルトロケールは何?
print
print 'Locale from environment:', locale.getlocale()

template = """
Numeric formatting:

  Decimal point      : "%(decimal_point)s"
  Grouping positions : %(grouping)s
  Thousands separator: "%(thousands_sep)s"

Monetary formatting:

  International currency symbol             : "%(int_curr_symbol)r"
  Local currency symbol                     : %(currency_symbol)r (%(currency_symbol_u)s)
  Symbol precedes positive value            : %(p_cs_precedes)s
  Symbol precedes negative value            : %(n_cs_precedes)s
  Decimal point                             : "%(mon_decimal_point)s"
  Digits in fractional values               : %(frac_digits)s
  Digits in fractional values, international: %(int_frac_digits)s
  Grouping positions                        : %(mon_grouping)s
  Thousands separator                       : "%(mon_thousands_sep)s"
  Positive sign                             : "%(positive_sign)s"
  Positive sign position                    : %(p_sign_posn)s
  Negative sign                             : "%(negative_sign)s"
  Negative sign position                    : %(n_sign_posn)s

"""

sign_positions = {
    0 : 'Surrounded by parentheses',
    1 : 'Before value and symbol',
    2 : 'After value and symbol',
    3 : 'Before value',
    4 : 'After value',
    locale.CHAR_MAX : 'Unspecified',
    }

info = {}
info.update(locale.localeconv())
info['p_sign_posn'] = sign_positions[info['p_sign_posn']]
info['n_sign_posn'] = sign_positions[info['n_sign_posn']]
# currency symbol をユニコードに変換する
info['currency_symbol_u'] = info['currency_symbol'].decode('utf-8')

print (template % info)

localeconv() メソッドはロケール規約を含む辞書を返します。値の名前と定義の完全なリストは標準ライブラリのドキュメントで説明されています。

私の MacOS X 10.6 では、全ての変数をアンセットすると次のように出力します。

$ export LANG=; export LC_CTYPE=; python locale_env_example.py
Environment settings:
        LC_ALL =
        LC_CTYPE =
        LANG =
        LANGUAGE =

Locale from environment: (None, None)

Numeric formatting:

  Decimal point      : "."
  Grouping positions : []
  Thousands separator: ""

Monetary formatting:

  International currency symbol             : "''"
  Local currency symbol                     : '' ()
  Symbol precedes positive value            : 127
  Symbol precedes negative value            : 127
  Decimal point                             : ""
  Digits in fractional values               : 127
  Digits in fractional values, international: 127
  Grouping positions                        : []
  Thousands separator                       : ""
  Positive sign                             : ""
  Positive sign position                    : Unspecified
  Negative sign                             : ""
  Negative sign position                    : Unspecified

LANG 環境変数をセットして同じスクリプトを実行すると、それに応じてデフォルトエンコーディングとロケールが変更されることを確認できます。

フランス (fr_FR):

$ LANG=fr_FR LC_CTYPE=fr_FR LC_ALL=fr_FR python locale_env_example.py
Environment settings:
        LC_ALL = fr_FR
        LC_CTYPE = fr_FR
        LANG = fr_FR
        LANGUAGE =

Locale from environment: ('fr_FR', 'ISO8859-1')

Numeric formatting:

  Decimal point      : ","
  Grouping positions : [127]
  Thousands separator: ""

Monetary formatting:

  International currency symbol             : "'EUR '"
  Local currency symbol                     : 'Eu' (Eu)
  Symbol precedes positive value            : 0
  Symbol precedes negative value            : 0
  Decimal point                             : ","
  Digits in fractional values               : 2
  Digits in fractional values, international: 2
  Grouping positions                        : [3, 3, 0]
  Thousands separator                       : " "
  Positive sign                             : ""
  Positive sign position                    : Before value and symbol
  Negative sign                             : "-"
  Negative sign position                    : After value and symbol

スペイン (es_ES):

$ LANG=es_ES LC_CTYPE=es_ES LC_ALL=es_ES python locale_env_example.py
Environment settings:
        LC_ALL = es_ES
        LC_CTYPE = es_ES
        LANG = es_ES
        LANGUAGE =

Locale from environment: ('es_ES', 'ISO8859-1')

Numeric formatting:

  Decimal point      : ","
  Grouping positions : [127]
  Thousands separator: ""

Monetary formatting:

  International currency symbol             : "'EUR '"
  Local currency symbol                     : 'Eu' (Eu)
  Symbol precedes positive value            : 1
  Symbol precedes negative value            : 1
  Decimal point                             : ","
  Digits in fractional values               : 2
  Digits in fractional values, international: 2
  Grouping positions                        : [3, 3, 0]
  Thousands separator                       : "."
  Positive sign                             : ""
  Positive sign position                    : Before value and symbol
  Negative sign                             : "-"
  Negative sign position                    : Before value and symbol

ポルトガル (pt_PT):

$ LANG=pt_PT LC_CTYPE=pt_PT LC_ALL=pt_PT python locale_env_example.py
Environment settings:
        LC_ALL = pt_PT
        LC_CTYPE = pt_PT
        LANG = pt_PT
        LANGUAGE =

Locale from environment: ('pt_PT', 'ISO8859-1')

Numeric formatting:

  Decimal point      : ","
  Grouping positions : []
  Thousands separator: " "

Monetary formatting:

  International currency symbol             : "'EUR '"
  Local currency symbol                     : 'Eu' (Eu)
  Symbol precedes positive value            : 0
  Symbol precedes negative value            : 0
  Decimal point                             : "."
  Digits in fractional values               : 2
  Digits in fractional values, international: 2
  Grouping positions                        : [3, 3, 0]
  Thousands separator                       : "."
  Positive sign                             : ""
  Positive sign position                    : Before value and symbol
  Negative sign                             : "-"
  Negative sign position                    : Before value and symbol

ポーランド (pl_PL):

$ LANG=pl_PL LC_CTYPE=pl_PL LC_ALL=pl_PL python locale_env_example.py
Environment settings:
        LC_ALL = pl_PL
        LC_CTYPE = pl_PL
        LANG = pl_PL
        LANGUAGE =

Locale from environment: ('pl_PL', 'ISO8859-2')

Numeric formatting:

  Decimal point      : ","
  Grouping positions : [3, 3, 0]
  Thousands separator: " "

Monetary formatting:

  International currency symbol             : "'PLN '"
  Local currency symbol                     : 'z\xc5\x82' (zł)
  Symbol precedes positive value            : 1
  Symbol precedes negative value            : 1
  Decimal point                             : ","
  Digits in fractional values               : 2
  Digits in fractional values, international: 2
  Grouping positions                        : [3, 3, 0]
  Thousands separator                       : " "
  Positive sign                             : ""
  Positive sign position                    : After value
  Negative sign                             : "-"
  Negative sign position                    : After value

通貨

上述したサンプルの出力は、ロケール設定を変更すると通貨記号の設定や小数の数字の区切り文字を更新することを表します。このサンプルは複数の異なるロケール設定を行って、ロケール毎の正負の通貨の値を表示します。

import locale

sample_locales = [ ('USA',      'en_US'),
                   ('France',   'fr_FR'),
                   ('Spain',    'es_ES'),
                   ('Portugal', 'pt_PT'),
                   ('Poland',   'pl_PL'),
                   ]

for name, loc in sample_locales:
    locale.setlocale(locale.LC_ALL, loc)
    print '%20s: %10s  %10s' % (name, locale.currency(1234.56), locale.currency(-1234.56))

結果はこの小さな表です。

$ python locale_currency_example.py
                 USA:   $1234.56   -$1234.56
              France: 1234,56 Eu  1234,56 Eu-
               Spain: Eu 1234,56  -Eu 1234,56
            Portugal: 1234.56 Eu  -1234.56 Eu
              Poland: zł 1234,56  zł 1234,56-

数値のフォーマット

通貨を表さない数値もロケールに依存して違うフォーマットになります。特に大きな数値を読み易くするため分割に使用される 区切り 文字が変更されます。

import locale

sample_locales = [ ('USA',      'en_US'),
                   ('France',   'fr_FR'),
                   ('Spain',    'es_ES'),
                   ('Portugal', 'pt_PT'),
                   ('Poland',   'pl_PL'),
                   ]

print '%20s %15s %20s' % ('Locale', 'Integer', 'Float')
for name, loc in sample_locales:
    locale.setlocale(locale.LC_ALL, loc)

    print '%20s' % name,
    print locale.format('%15d', 123456, grouping=True),
    print locale.format('%20.2f', 123456.78, grouping=True)

通貨記号なしで数値のフォーマットを使用するために currency() の代わりに format() を使用してください。

$ python locale_grouping.py
              Locale         Integer                Float
                 USA         123,456           123,456.78
              France          123456            123456,78
               Spain          123456            123456,78
            Portugal          123456            123456,78
              Poland         123 456           123 456,78

数値の解析

違うフォーマットの出力を生成することに加えて locale モジュールは入力の解析にも役立ちます。それはロケールの数値フォーマット変換に基づいて文字列から整数や浮動小数の値へ変換するために atoi()atof() 関数を提供します。

import locale

sample_data = [ ('USA',      'en_US', '1,234.56'),
                ('France',   'fr_FR', '1234,56'),
                ('Spain',    'es_ES', '1234,56'),
                ('Portugal', 'pt_PT', '1234.56'),
                ('Poland',   'pl_PL', '1 234,56'),
                ]

for name, loc, a in sample_data:
    locale.setlocale(locale.LC_ALL, loc)
    f = locale.atof(a)
    print '%20s: %9s => %f' % (name, a, f)
    

数字の括りや小数の区切りは次のようになります。

$ python locale_atof_example.py
                 USA:  1,234.56 => 1234.560000
              France:   1234,56 => 1234.560000
               Spain:   1234,56 => 1234.560000
            Portugal:   1234.56 => 1234.560000
              Poland:  1 234,56 => 1234.560000

日付と時刻

その他にローカライゼーションの重要な表示として日付と時刻のフォーマットがあります。

import locale
import time

sample_locales = [ ('USA',      'en_US'),
                   ('France',   'fr_FR'),
                   ('Spain',    'es_ES'),
                   ('Portugal', 'pt_PT'),
                   ('Poland',   'pl_PL'),
                   ]

for name, loc in sample_locales:
    locale.setlocale(locale.LC_ALL, loc)
    print '%20s: %s' % (name, time.strftime(locale.nl_langinfo(locale.D_T_FMT)))
$ python locale_date_example.py
                 USA: Sun Feb 17 11:32:32 2013
              France: Dim 17 fév 11:32:32 2013
               Spain: dom 17 feb 11:32:32 2013
            Portugal: Dom 17 Fev 11:32:32 2013
              Poland: ndz 17 lut 11:32:32 2013

ここでの話題は locale モジュールの高レベル関数のみ説明します。低レベルの関数(format_string())、アプリケーションでロケールを管理するために関連する関数(resetlocale())といった関数群もあります。いつもの通り、あなたは Python のライブラリドキュメントでさらに詳細を確認したくなるでしょう。

See also

locale
本モジュールの標準ライブラリドキュメント
gettext
翻訳のためのメッセージカタログ
Bookmark and Share