Localization Guide¶
Comprehensive guide to using Carbonic's multi-language support for datetime formatting and humanization.
Overview¶
Carbonic provides comprehensive localization support for: - Date/time formatting with localized month and day names - Duration humanization with proper pluralization rules - Number formatting with locale-specific decimal separators - 6 languages: English, Polish, Spanish, French, German, Portuguese
Supported Locales¶
from carbonic import DateTime, Duration
# Available locales
locales = ["en", "pl", "es", "fr", "de", "pt"]
dt = DateTime(2024, 1, 15, 14, 30)
duration = Duration(hours=2, minutes=30)
for locale in locales:
formatted = dt.format("l, F j, Y", locale=locale)
humanized = duration.humanize(locale=locale)
print(f"{locale}: {formatted} - {humanized}")
Date and Time Formatting¶
Month Names¶
from carbonic import DateTime
dt = DateTime(2024, 1, 15, 14, 30)
# Full month names
print("Full month names:")
print(f"English: {dt.format('F', locale='en')}") # January
print(f"Polish: {dt.format('F', locale='pl')}") # stycznia (genitive)
print(f"Spanish: {dt.format('F', locale='es')}") # enero
print(f"French: {dt.format('F', locale='fr')}") # janvier
print(f"German: {dt.format('F', locale='de')}") # Januar
print(f"Portuguese: {dt.format('F', locale='pt')}") # janeiro
# Short month names
print("\nShort month names:")
print(f"English: {dt.format('M', locale='en')}") # Jan
print(f"Polish: {dt.format('M', locale='pl')}") # sty
print(f"Spanish: {dt.format('M', locale='es')}") # ene
Day Names¶
from carbonic import DateTime
dt = DateTime(2024, 1, 15, 14, 30) # Monday
# Full day names
print("Full day names:")
print(f"English: {dt.format('l', locale='en')}") # Monday
print(f"Polish: {dt.format('l', locale='pl')}") # poniedziałek
print(f"Spanish: {dt.format('l', locale='es')}") # lunes
print(f"French: {dt.format('l', locale='fr')}") # lundi
print(f"German: {dt.format('l', locale='de')}") # Montag
print(f"Portuguese: {dt.format('l', locale='pt')}") # segunda-feira
# Short day names
print("\nShort day names:")
print(f"English: {dt.format('D', locale='en')}") # Mon
print(f"Polish: {dt.format('D', locale='pl')}") # pon
print(f"Spanish: {dt.format('D', locale='es')}") # lun
Complete Date Formats¶
from carbonic import DateTime
dt = DateTime(2024, 1, 15, 14, 30)
# Natural date formats for each locale
formats = {
"en": "l, F j, Y", # Monday, January 15, 2024
"pl": "l, j F Y", # poniedziałek, 15 stycznia 2024
"es": "l, j {d}e F {d}e Y", # lunes, 15 de enero de 2024
"fr": "l j F Y", # lundi 15 janvier 2024
"de": "l, j. F Y", # Montag, 15. Januar 2024
"pt": "l, j {d}e F {d}e Y", # segunda-feira, 15 de janeiro de 2024
}
for locale, format_str in formats.items():
result = dt.format(format_str, locale=locale)
print(f"{locale}: {result}")
Duration Humanization¶
Basic Humanization¶
from carbonic import Duration
duration = Duration(hours=2, minutes=30)
print("2 hours 30 minutes:")
print(f"English: {duration.humanize(locale='en')}") # 2 hours 30 minutes
print(f"Polish: {duration.humanize(locale='pl')}") # 2 godziny 30 minut
print(f"Spanish: {duration.humanize(locale='es')}") # 2 horas 30 minutos
print(f"French: {duration.humanize(locale='fr')}") # 2 heures 30 minutes
print(f"German: {duration.humanize(locale='de')}") # 2 Stunden 30 Minuten
print(f"Portuguese: {duration.humanize(locale='pt')}") # 2 horas 30 minutos
Pluralization Rules¶
Different languages have different pluralization rules:
from carbonic import Duration
# English: simple plural (1 hour, 2 hours)
print("English pluralization:")
print(Duration(hours=1).humanize(locale="en")) # 1 hour
print(Duration(hours=2).humanize(locale="en")) # 2 hours
print(Duration(hours=5).humanize(locale="en")) # 5 hours
# Polish: complex 3-form pluralization
print("\nPolish pluralization:")
print(Duration(hours=1).humanize(locale="pl")) # 1 godzina (singular)
print(Duration(hours=2).humanize(locale="pl")) # 2 godziny (plural 2-4)
print(Duration(hours=5).humanize(locale="pl")) # 5 godzin (plural 5+)
print(Duration(hours=22).humanize(locale="pl")) # 22 godziny (ends in 2-4)
print(Duration(hours=25).humanize(locale="pl")) # 25 godzin (ends in 5+)
Different Time Units¶
from carbonic import Duration
# Various durations
durations = [
Duration(seconds=30),
Duration(minutes=1),
Duration(hours=1),
Duration(days=1),
Duration(weeks=1),
Duration(months=1),
Duration(years=1)
]
print("Duration humanization across locales:")
for duration in durations:
en = duration.humanize(locale="en")
pl = duration.humanize(locale="pl")
es = duration.humanize(locale="es")
print(f"{en:15} | {pl:15} | {es}")
Number Formatting¶
Decimal Separators¶
from carbonic import Duration
# Duration with fractional seconds
duration = Duration(seconds=45, microseconds=500000) # 45.5 seconds
print("Decimal separator formatting:")
print(f"English (dot): {duration.humanize(locale='en')}") # 45.5 seconds
print(f"Polish (comma): {duration.humanize(locale='pl')}") # 45,5 sekundy
print(f"Spanish (comma): {duration.humanize(locale='es')}") # 45,5 segundos
print(f"French (comma): {duration.humanize(locale='fr')}") # 45,5 secondes
print(f"German (comma): {duration.humanize(locale='de')}") # 45,5 Sekunden
print(f"Portuguese (comma): {duration.humanize(locale='pt')}") # 45,5 segundos
Advanced Localization¶
Handling Special Cases¶
from carbonic import DateTime
# Month names in different contexts
dt = DateTime(2024, 5, 15, 14, 30)
# Polish months change form in different contexts
print("Polish month handling:")
print(f"Nominative: {dt.format('F', locale='pl')}") # maja (genitive case)
print(f"With day: {dt.format('j F', locale='pl')}") # 15 maja
# French months (some are invariant)
dt_march = DateTime(2024, 3, 15)
print(f"French March: {dt_march.format('F', locale='fr')}") # mars (no change)
Zero and Negative Durations¶
from carbonic import Duration
zero_duration = Duration()
negative_duration = Duration(hours=-2, minutes=-30)
print("Special duration cases:")
for locale in ["en", "pl", "es", "fr", "de", "pt"]:
zero = zero_duration.humanize(locale=locale)
negative = negative_duration.humanize(locale=locale)
print(f"{locale}: '{zero}' | '{negative}'")
Controlling Precision¶
from carbonic import Duration
long_duration = Duration(days=1, hours=2, minutes=30, seconds=45)
print("Duration precision control:")
for locale in ["en", "pl", "es"]:
# Default (all units)
full = long_duration.humanize(locale=locale)
# Limited units
limited = long_duration.humanize(locale=locale, max_units=2)
print(f"{locale}:")
print(f" Full: {full}")
print(f" Limited: {limited}")
Practical Examples¶
User Interface Localization¶
from carbonic import DateTime, Duration
def format_user_datetime(dt, user_locale="en"):
"""Format datetime for user interface based on their locale."""
formats = {
"en": "l, M j, Y \\a\\t g:i A", # Monday, Jan 15, 2024 at 2:30 PM
"pl": "l, j M Y o G:i", # poniedziałek, 15 sty 2024 o 14:30
"es": "l, j {d}e M {d}e Y {a} \\l\\a\\s G:i", # lunes, 15 de ene de 2024 a las 14:30
"fr": "l j M Y \\à G:i", # lundi 15 jan 2024 à 14:30
"de": "l, j. M Y \\u\\m G:i", # Montag, 15. Jan 2024 um 14:30
"pt": "l, j {d}e M {d}e Y \\à\\s G:i", # segunda-feira, 15 de jan de 2024 às 14:30
}
format_str = formats.get(user_locale, formats["en"])
return dt.format(format_str, locale=user_locale)
# Usage
dt = DateTime(2024, 1, 15, 14, 30)
for locale in ["en", "pl", "es", "fr", "de", "pt"]:
formatted = format_user_datetime(dt, locale)
print(f"{locale}: {formatted}")
Relative Time Display¶
from carbonic import DateTime, Duration
def relative_time_display(past_dt, current_dt=None, locale="en"):
"""Display relative time like 'posted 2 hours ago'."""
if current_dt is None:
current_dt = DateTime.now()
duration = current_dt.diff(past_dt)
humanized = duration.humanize(locale=locale, max_units=1)
# Locale-specific formatting
ago_text = {
"en": "ago",
"pl": "temu",
"es": "hace",
"fr": "il y a",
"de": "vor",
"pt": "atrás"
}
ago = ago_text.get(locale, ago_text["en"])
if locale in ["fr"]:
return f"{ago} {humanized}" # French: "il y a 2 heures"
elif locale in ["es"]:
return f"{ago} {humanized}" # Spanish: "hace 2 horas"
else:
return f"{humanized} {ago}" # Others: "2 hours ago"
# Usage
past_time = DateTime.now().subtract(hours=2, minutes=15)
current_time = DateTime.now()
for locale in ["en", "pl", "es", "fr", "de", "pt"]:
relative = relative_time_display(past_time, current_time, locale)
print(f"{locale}: {relative}")
Multilingual Logging¶
from carbonic import DateTime
class LocalizedLogger:
def __init__(self, locale="en"):
self.locale = locale
def log_event(self, event, level="INFO"):
"""Create localized log entry."""
timestamp = DateTime.now()
# Locale-specific timestamp format
if self.locale == "en":
time_str = timestamp.format("M j, Y H:i:s")
elif self.locale == "pl":
time_str = timestamp.format("j M Y H:i:s", locale="pl")
elif self.locale == "es":
time_str = timestamp.format("j {d}e M {d}e Y H:i:s", locale="es")
else:
time_str = timestamp.to_iso_string()
return f"[{time_str}] {level}: {event}"
# Usage
loggers = {
"en": LocalizedLogger("en"),
"pl": LocalizedLogger("pl"),
"es": LocalizedLogger("es")
}
for locale, logger in loggers.items():
entry = logger.log_event("User login successful")
print(f"{locale}: {entry}")
Error Handling¶
from carbonic import DateTime, Duration
def safe_localized_format(dt, format_str, locale="en"):
"""Safely format with fallback to English."""
try:
return dt.format(format_str, locale=locale)
except (ValueError, KeyError):
# Fallback to English if locale not supported
return dt.format(format_str, locale="en")
# Usage
dt = DateTime(2024, 1, 15, 14, 30)
result = safe_localized_format(dt, "l, F j, Y", locale="invalid_locale")
print(result) # Falls back to English
Performance Considerations¶
Locale Caching¶
Carbonic automatically caches locale data for performance:
from carbonic import DateTime, Duration
# First call loads locale data
dt = DateTime(2024, 1, 15)
result1 = dt.format("l, F j, Y", locale="pl") # Loads Polish locale
# Subsequent calls use cached data
result2 = dt.format("j F Y", locale="pl") # Uses cached Polish locale
# Different locale loads separately
result3 = dt.format("l, F j, Y", locale="es") # Loads Spanish locale
Bulk Operations¶
from carbonic import DateTime
# Efficient for multiple operations with same locale
dates = [DateTime(2024, 1, i) for i in range(1, 32)]
# Good: Consistent locale
formatted_pl = [dt.format("j F", locale="pl") for dt in dates]
# Less efficient: Switching locales frequently
# formatted_mixed = [dt.format("j F", locale="pl" if i % 2 else "en") for i, dt in enumerate(dates)]
See Also¶
- Parsing & Formatting - Format token reference
- Duration Guide - Duration humanization details
- DateTime Guide - Complete DateTime formatting
- API Reference - Complete localization API