Python | f文字列でのローカライズ(通貨記号や桁区切りのロケール対応)

Python Python
スポンサーリンク

ローカライズ(地域ごとの通貨記号・桁区切り)を f文字列で扱う方法を、初心者でも実務で使えるようにやさしくまとめます。ポイント・短所・安全な実装例(localeBabel)を両方お見せします。

ポイントまとめ

  • f文字列自体は「埋め込み式を評価して文字列化する」機能。数値の見た目(桁区切り・小数桁など)は f文字列のフォーマット指定子でかなりできる。
    例:f"{value:,.2f}" は英語圏でよく見る「3桁カンマ+小数2桁」。
  • **ロケール依存の表現(小数の区切りが .,、通貨シンボルの位置など)**を正しくやるには、標準ライブラリの locale を使う方法と、より正確で便利な外部ライブラリ Babel(推奨)を使う方法がある。
  • 注意点:locale.setlocale()プロセス全体に影響(スレッド安全ではない)。サーバーアプリやマルチスレッドでは避けるか影響を把握して使う。Webアプリ等では Babel のようなライブラリが安全で便利。

手軽な方法:f文字列+フォーマット(ロケール無視)

最も簡単。グローバルなロケールは無視して「常にカンマ区切り」「固定小数」を表示するパターン。

price = 1234567.89
print(f"{price:,.2f}")   # 出力: 1,234,567.89
Python

長所:簡単、依存なし。
短所:欧州の小数区切りが , の国では誤り。通貨記号の位置・空白・通貨単位のローカライズは自分で実装する必要あり。


標準ライブラリ locale を使う(小規模スクリプト向け)

locale を設定すると :n フォーマットや locale.format_string がロケールに従う出力を行えます。

import locale
from datetime import datetime

# 例:日本(Windowsでは "ja_JP" や "Japanese_Japan.932" などが必要)
locale.setlocale(locale.LC_ALL, "ja_JP.UTF-8")  # Unix系で一般的

value = 1234567.89
# ロケールに依存した数値フォーマット('n' はロケール依存)
print(f"{value:n}")            # 日本なら "1234567.89"(小数点は .)
# locale.format_string で桁区切りを明示
print(locale.format_string("%0.2f", value, grouping=True))  # "1,234,567.89"

# 通貨表示(locale によるが locale.currency は通貨記号を付ける)
print(locale.currency(value, grouping=True))  # 例: "¥1,234,567.89"(ロケール次第)
Python

注意

  • locale.setlocale() はプロセス全体に作用します(スレッドセーフでない)。Webサーバー等で使う際は注意。
  • Windows と Unix でロケール名が違うことがある(例: "ja_JP.UTF-8" vs "Japanese_Japan.932")。環境ごとに試す必要あり。

実務での推奨:Babel を使う(ロケールごとに安全・確実)

Babel はロケールごとの通貨表示・桁区切り・小数・通貨記号配置を正しくやってくれるライブラリ。スレッド安全で、一回の呼び出しで任意のロケールに対してフォーマットできます。

インストール:

pip install Babel

使い方(例):

from babel.numbers import format_currency, format_decimal

value = 1234567.89

# 日本円(JPY)は小数を出さないことが多いので小数0にする例
print(format_currency(1234567, 'JPY', locale='ja_JP'))      # '¥1,234,567'

# 米ドル($)英語(米国)
print(format_currency(value, 'USD', locale='en_US'))        # '$1,234,567.89'

# ドイツ語(ドイツ): 小数区切りがカンマ、桁区切りがドット
print(format_currency(value, 'EUR', locale='de_DE'))        # '1.234.567,89\xa0€'

# 純数値(ロケール依存の小数/桁区切り)
print(format_decimal(value, locale='de_DE'))                # '1.234.567,89'
Python

長所

  • ロケールごとのルールに忠実(通貨記号の位置、空白、単位の省略の仕方など)。
  • スレッド安全で任意ロケールを指定可能(setlocale 不要)。
  • 通貨通しの違い(JPY の小数有無など)にも配慮される。

短所:外部依存(ただし pip で簡単に入る)。


実例:ユーザーごとに異なるロケールでメール本文を作る(Babel と f文字列の組合せ)

from babel.numbers import format_currency

def order_email(user, amount, currency, locale):
    money = format_currency(amount, currency, locale=locale)
    return f"""{user}

ご注文ありがとうございます。
合計金額: {money}

よろしくお願いします。
"""

print(order_email("田中", 122400, "JPY", "ja_JP"))
print(order_email("John", 122400.5, "USD", "en_US"))
print(order_email("Hans", 122400.5, "EUR", "de_DE"))
Python

出力例(ロケールごとに適切に表示):

  • 日本語: ¥122,400
  • 英語 (US): $122,400.50
  • ドイツ語: 122.400,50 €(小数カンマ、通貨記号は末尾)

実装上の注意と落とし穴

  1. スレッド/プロセス全体への影響
    • locale.setlocale() はプロセス全体を変える → マルチスレッド環境や Web サーバーでは危険。Babel を使うと安全。
  2. ロケール名の違い
    • Windows と Unix(Linux/macOS)で利用できるロケール名が異なる。テストが必要。
  3. 通貨の小数桁
    • 通貨によっては小数を表示しない(JPY)/2桁(USD, EUR)。Babel はこの情報を正しく扱う。
  4. 表示と内部値は分ける
    • 通貨の計算は整数(セント単位など)か Decimal 型で行い、表示だけロケールで整形するのが安全(浮動小数点の丸め誤差回避)。
    • 例:from decimal import Decimal を使う。
  5. サードパーティの信頼性
    • Babel は広く使われているが、特殊要件があれば ICU(PyICU)等の採用検討も。

まとめ(選び方)

  • 単純な用途/単一ロケール:f"{value:,.2f}" で十分。
  • スクリプトで環境に応じてロケールを変えて良い(かつ単一スレッド):locale が使える。
  • 多言語対応のアプリ・Web サービス:Babel を強く推奨。ロケールごとの表示ルールを安全に、正確にやってくれます。
Python
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました