Formatting and Internationalization
Metric Engine provides flexible formatting capabilities for displaying financial values, numbers, and percentages with proper locale support through optional Babel integration.
Overview
The formatting system is built around two key components:
Display Policies - Control how values should be formatted (decimal places, grouping, currency symbols, etc.)
Formatters - Handle the actual formatting logic with locale awareness
Formatter Architecture
Metric Engine uses a plugin-based formatter system:
from metricengine.formatters.base import get_formatter
# Automatically selects the best available formatter
formatter = get_formatter()
Available Formatters
BabelFormatter (when Babel is installed)
Full internationalization support
Locale-aware currency, number, and percentage formatting
CLDR-compliant formatting patterns
Support for multiple currencies and locales
BuiltinFormatter (fallback)
Basic formatting without external dependencies
Simple currency symbols and decimal formatting
Used when Babel is not available
Display Policies
Display policies control formatting behavior:
from metricengine.policy import DisplayPolicy
# Basic policy
policy = DisplayPolicy(
locale="en_US",
currency="USD",
max_frac=2,
use_grouping=True
)
# Advanced policy with accounting style
accounting_policy = DisplayPolicy(
locale="en_US",
currency="USD",
max_frac=2,
currency_style="accounting",
negative_parens=True,
use_grouping=True
)
Key Policy Options
locale: Target locale (e.g., “en_US”, “de_DE”, “ja_JP”)currency: Currency code (e.g., “USD”, “EUR”, “JPY”)max_frac/min_frac: Control decimal placesuse_grouping: Enable/disable thousands separatorscurrency_style: “standard” or “accounting”negative_parens: Use parentheses for negative valuespercent_scale: “ratio” (0.15) or “percent” (15) input interpretation
Babel Integration
Installation
Install Metric Engine with Babel support:
pip install "metric-engine[babel]"
Locale-Aware Formatting
With Babel installed, you get full internationalization support:
from metricengine.factories import money, percent
from metricengine.policy import DisplayPolicy
# Create values
revenue = money(1234567.89)
growth = percent(15.5, input="percent")
# US English formatting
us_policy = DisplayPolicy(locale="en_US", currency="USD")
print(revenue.format(us_policy)) # $1,234,567.89
print(growth.format(us_policy)) # 15.50%
# German formatting
de_policy = DisplayPolicy(locale="de_DE", currency="EUR")
print(revenue.format(de_policy)) # 1.234.567,89 €
print(growth.format(de_policy)) # 15,50 %
# Japanese formatting
jp_policy = DisplayPolicy(locale="ja_JP", currency="JPY", max_frac=0)
print(revenue.format(jp_policy)) # ¥1,234,568
Currency Formatting
Babel provides sophisticated currency formatting:
from metricengine.factories import money
from metricengine.policy import DisplayPolicy
amount = money(1234.56)
# Different locales, same currency
policies = [
DisplayPolicy(locale="en_US", currency="USD"), # $1,234.56
DisplayPolicy(locale="en_GB", currency="USD"), # US$1,234.56
DisplayPolicy(locale="fr_FR", currency="USD"), # 1 234,56 $US
]
for policy in policies:
print(f"{policy.locale}: {amount.format(policy)}")
Accounting Style
For financial applications, use accounting style formatting:
from metricengine.factories import money
from metricengine.policy import DisplayPolicy
profit = money(1000)
loss = money(-1000)
accounting_policy = DisplayPolicy(
locale="en_US",
currency="USD",
currency_style="accounting",
negative_parens=True
)
print(profit.format(accounting_policy)) # $1,000.00
print(loss.format(accounting_policy)) # ($1,000.00)
Percentage Formatting
Handle both ratio and percentage inputs correctly:
from metricengine.factories import percent
from metricengine.policy import DisplayPolicy
# Ratio input (0.15 = 15%)
ratio_value = percent(0.15, input="ratio")
# Percentage input (15 = 15%)
percent_value = percent(15, input="percent")
policy = DisplayPolicy(
locale="en_US",
max_frac=2,
percent_scale="ratio" # How to interpret the stored value
)
print(ratio_value.format(policy)) # 15.00%
print(percent_value.format(policy)) # 15.00%
Number Formatting
Format plain numbers with locale-specific conventions:
from metricengine.factories import ratio
from metricengine.policy import DisplayPolicy
large_number = ratio(1234567.89)
# US formatting
us_policy = DisplayPolicy(locale="en_US", max_frac=2)
print(large_number.format(us_policy)) # 1,234,567.89
# European formatting
eu_policy = DisplayPolicy(locale="de_DE", max_frac=2)
print(large_number.format(eu_policy)) # 1.234.567,89
# No grouping
no_group_policy = DisplayPolicy(locale="en_US", max_frac=2, use_grouping=False)
print(large_number.format(no_group_policy)) # 1234567.89
Fallback Behavior
When Babel is not available, Metric Engine gracefully falls back to basic formatting:
# This works whether Babel is installed or not
from metricengine.factories import money
from metricengine.policy import DisplayPolicy
amount = money(1234.56)
policy = DisplayPolicy(currency="USD", max_frac=2)
# With Babel: $1,234.56
# Without Babel: USD 1,234.56
print(amount.format(policy))
Custom Formatting
For advanced use cases, you can work directly with formatters:
from metricengine.formatters.base import get_formatter
from metricengine.policy import DisplayPolicy
from decimal import Decimal
formatter = get_formatter()
policy = DisplayPolicy(locale="en_US", currency="USD", max_frac=2)
# Format different value types
money_result = formatter.money(Decimal("1234.56"), None, policy)
number_result = formatter.number(Decimal("1234.56"), policy)
percent_result = formatter.percent(Decimal("0.1556"), policy)
print(f"Money: {money_result}") # Money: $1,234.56
print(f"Number: {number_result}") # Number: 1,234.56
print(f"Percent: {percent_result}") # Percent: 15.56%
Error Handling
The formatting system handles errors gracefully:
from metricengine.formatters.base import BabelUnavailable
try:
from metricengine.formatters.babel_adapter import BabelFormatter
formatter = BabelFormatter()
except BabelUnavailable:
print("Babel not available, using builtin formatter")
from metricengine.formatters.base import BuiltinFormatter
formatter = BuiltinFormatter()
Best Practices
Use Display Policies: Always format through display policies rather than direct formatter calls
Install Babel for Production: Use
pip install "metric-engine[babel]"for full internationalizationTest Multiple Locales: Verify your formatting works across target locales
Handle Fallbacks: Design your application to work with or without Babel
Cache Policies: Reuse display policy instances for better performance
Supported Locales
With Babel, Metric Engine supports all CLDR locales. Common examples:
en_US- US Englishen_GB- British Englishde_DE- German (Germany)fr_FR- French (France)ja_JP- Japanesezh_CN- Chinese (Simplified)es_ES- Spanish (Spain)pt_BR- Portuguese (Brazil)
Performance Considerations
Formatter instances are lightweight and can be cached
Display policies are immutable and safe to reuse
Babel formatting is slightly slower than builtin but provides much better locale support
Consider using the factory function
get_formatter()to automatically select the best available formatter