Internationalization (i18n)
Truthound provides an enterprise-grade i18n system for internationalizing validator error messages.
Supported Languages
Core Languages (7)
Code
Language
Direction
en
English
LTR
ko
Korean
LTR
ja
Japanese
LTR
zh
Chinese
LTR
de
German
LTR
fr
French
LTR
es
Spanish
LTR
Extended Languages (8)
Code
Language
Direction
Notes
pt
Portuguese
LTR
pt-BR
Portuguese (Brazil)
LTR
Brazil
pt-PT
Portuguese (Portugal)
LTR
Portugal
it
Italian
LTR
ru
Russian
LTR
ar
Arabic
RTL
he
Hebrew
RTL
fa
Persian
RTL
Basic Usage
Setting the Locale
from truthound.validators.i18n import (
set_validator_locale ,
get_validator_locale ,
)
# Set locale
set_validator_locale ( "ko" )
# Get current locale
locale = get_validator_locale ()
print ( locale ) # "ko"
Retrieving Messages
from truthound.validators.i18n import (
get_validator_message ,
ValidatorMessageCode ,
)
# Set locale
set_validator_locale ( "ko" )
# Retrieve message
msg = get_validator_message (
ValidatorMessageCode . NULL_VALUES_FOUND ,
column = "email" ,
count = 10 ,
)
print ( msg ) # "'email' 컬럼에서 10개의 null 값이 발견되었습니다"
from truthound.validators.i18n import format_issue_message
from truthound.validators.base import ValidationIssue
issue = ValidationIssue (
column = "email" ,
issue_type = "null_value" ,
count = 10 ,
severity = "high" ,
)
# Format issue message
msg = format_issue_message ( issue , locale = "ko" )
ValidatorMessageCode
All validator message codes:
Completeness
Code
Description
NULL_VALUES_FOUND
Null values found
COMPLETENESS_BELOW_THRESHOLD
Completeness below threshold
REQUIRED_COLUMN_MISSING
Required column missing
Uniqueness
Code
Description
DUPLICATE_VALUES_FOUND
Duplicate values found
UNIQUENESS_CONSTRAINT_VIOLATED
Uniqueness constraint violated
Range & Distribution
Code
Description
VALUES_OUT_OF_RANGE
Values out of range
MIN_VALUE_EXCEEDED
Below minimum value
MAX_VALUE_EXCEEDED
Exceeds maximum value
OUTLIERS_DETECTED
Outliers detected
Code
Description
PATTERN_MISMATCH
Pattern mismatch
INVALID_EMAIL_FORMAT
Invalid email format
INVALID_DATE_FORMAT
Invalid date format
INVALID_PHONE_FORMAT
Invalid phone format
Type
Code
Description
TYPE_MISMATCH
Type mismatch
UNEXPECTED_TYPE
Unexpected type
Relationship
Code
Description
FOREIGN_KEY_VIOLATION
Foreign key violation
REFERENTIAL_INTEGRITY_ERROR
Referential integrity error
CLDR Plural Rules
Support for CLDR (Common Locale Data Repository) standard plural rules:
Plural Categories
Category
Description
Example
zero
Zero
Arabic 0
one
Singular
1 item
two
Dual
Arabic 2
few
Few
Russian 2-4
many
Many
Russian 5-20
other
Other
General plural
Using Plurals
from truthound.validators.i18n import (
pluralize ,
get_plural_category ,
PluralCategory ,
)
# Get plural category
category = get_plural_category ( 5 , "ru" )
print ( category ) # PluralCategory.FEW
# Plural message
msg = pluralize (
count = 5 ,
forms = {
"one" : " {count} файл" ,
"few" : " {count} файла" ,
"many" : " {count} файлов" ,
"other" : " {count} файлов" ,
},
locale = "ru" ,
)
print ( msg ) # "5 файлов"
Plural Rules by Language
Language
Categories
Rules
English
one, other
1 = one, else other
Korean
other
All other
Japanese
other
All other
Chinese
other
All other
Russian
one, few, many, other
Complex rules
Arabic
zero, one, two, few, many, other
6 forms
French
one, other
0, 1 = one, else other
German
one, other
1 = one, else other
from truthound.validators.i18n import (
format_number ,
format_currency ,
NumberStyle ,
)
# Number formatting
format_number ( 1234567.89 , "de" ) # "1.234.567,89"
format_number ( 1234567.89 , "en" ) # "1,234,567.89"
format_number ( 1234567.89 , "ko" ) # "1,234,567.89"
format_number ( 1234567.89 , "ar" ) # "١٬٢٣٤٬٥٦٧٫٨٩"
# Currency formatting
format_currency ( 1000 , "USD" , "en" ) # "$1,000.00"
format_currency ( 1000 , "EUR" , "de" ) # "1.000,00 €"
format_currency ( 1000 , "KRW" , "ko" ) # "₩1,000"
from truthound.validators.i18n import (
format_date ,
format_time ,
format_relative_time ,
DateStyle ,
TimeStyle ,
)
from datetime import datetime , timedelta
now = datetime . now ()
# Date formatting
format_date ( now , "ko" , DateStyle . SHORT ) # "24. 12. 28."
format_date ( now , "ko" , DateStyle . MEDIUM ) # "2024. 12. 28."
format_date ( now , "ko" , DateStyle . LONG ) # "2024년 12월 28일"
format_date ( now , "ko" , DateStyle . FULL ) # "2024년 12월 28일 토요일"
format_date ( now , "de" , DateStyle . LONG ) # "28. Dezember 2024"
format_date ( now , "ja" , DateStyle . LONG ) # "2024年12月28日"
# Time formatting
format_time ( now , "en" , TimeStyle . SHORT ) # "3:30 PM"
format_time ( now , "de" , TimeStyle . SHORT ) # "15:30"
format_time ( now , "ko" , TimeStyle . MEDIUM ) # "오후 3:30:00"
# Relative time
format_relative_time ( timedelta ( days =- 1 ), "ko" ) # "어제"
format_relative_time ( timedelta ( hours =- 3 ), "en" ) # "3 hours ago"
format_relative_time ( timedelta ( days = 2 ), "de" ) # "in 2 Tagen"
RTL Language Support
Right-to-left (RTL) language support:
RTL Languages
from truthound.validators.i18n import (
RTL_LANGUAGES ,
is_rtl_language ,
get_locale_direction ,
TextDirection ,
)
print ( RTL_LANGUAGES )
# {"ar", "he", "fa", "ur", "yi", "ps", "sd", "dv", "ug", "ku"}
is_rtl_language ( "ar" ) # True
is_rtl_language ( "ko" ) # False
get_locale_direction ( "ar" ) # TextDirection.RTL
get_locale_direction ( "en" ) # TextDirection.LTR
BiDi Handling
from truthound.validators.i18n import (
BiDiHandler ,
BiDiConfig ,
BiDiControl ,
wrap_bidi ,
detect_direction ,
)
# Detect text direction
direction = detect_direction ( "مرحبا" ) # TextDirection.RTL
direction = detect_direction ( "Hello" ) # TextDirection.LTR
# BiDi handler
config = BiDiConfig (
insert_marks = True , # Insert direction markers
force_direction = None , # Force direction (None = auto)
isolate_numbers = True , # Isolate numbers
strip_marks = False , # Strip existing markers
)
handler = BiDiHandler ( config )
wrapped = handler . process ( "Hello مرحبا 123" )
# Convenience function
wrapped = wrap_bidi ( "Hello مرحبا" , BiDiControl . LRI )
Regional Dialect Support
Registering Dialects
from truthound.validators.i18n import (
create_dialect ,
register_dialect ,
get_dialect_registry ,
get_fallback_chain ,
)
# Create dialect
en_us = create_dialect (
code = "en-US" ,
parent = "en" ,
name = "English (United States)" ,
overrides = {
ValidatorMessageCode . DATE_FORMAT_ERROR : "Invalid date format. Expected MM/DD/YYYY." ,
},
)
# Register dialect
register_dialect ( en_us )
# Get fallback chain
chain = get_fallback_chain ( "en-US" )
# ["en-US", "en"]
chain = get_fallback_chain ( "pt-BR" )
# ["pt-BR", "pt"]
Setting Regional Locale
from truthound.validators.i18n import set_validator_locale
# Set regional dialect
set_validator_locale ( "en-US" )
set_validator_locale ( "zh-TW" ) # Traditional Chinese
set_validator_locale ( "pt-BR" ) # Brazilian Portuguese
TMS Integration
Translation Management System (TMS) integration:
Supported TMS Providers
Provider
Class
API
Crowdin
CrowdinProvider
REST API v2
Lokalise
LokaliseProvider
REST API v2
Phrase
PhraseProvider
REST API v2
TMS Configuration
from truthound.validators.i18n import (
TMSConfig ,
TMSManager ,
create_provider ,
CrowdinProvider ,
)
# Crowdin configuration
config = TMSConfig (
provider = "crowdin" ,
api_key = "your-api-key" ,
project_id = "your-project-id" ,
base_url = "https://api.crowdin.com/api/v2" ,
sync_interval_seconds = 3600 ,
auto_sync = True ,
)
# Create provider
provider = create_provider ( config )
# Or create directly
provider = CrowdinProvider (
api_key = "your-api-key" ,
project_id = "your-project-id" ,
)
TMS Manager
from truthound.validators.i18n import get_tms_manager
manager = get_tms_manager ( config )
# Sync translations
await manager . sync ()
# Check translation status
status = await manager . get_translation_status ( "ko" )
print ( status . progress_percentage )
print ( status . translated_count )
print ( status . approved_count )
# Handle webhook
event = manager . parse_webhook ( request_body )
if event . event_type == "translation.completed" :
await manager . sync ()
Dynamic Catalog Management
CatalogManager
from truthound.validators.i18n import (
CatalogManager ,
get_catalog_manager ,
FileSystemStorage ,
MemoryStorage ,
)
# Memory storage (default)
manager = get_catalog_manager ()
# File system storage
storage = FileSystemStorage ( path = "/translations" )
manager = CatalogManager ( storage = storage )
# Load catalog
catalog = manager . load_catalog ( "ko" )
# Save catalog
manager . save_catalog ( "ko" , catalog )
# Invalidate cache
manager . invalidate_cache ( "ko" )
manager . clear_cache ()
Context-Based Messages
from truthound.validators.i18n import (
ContextResolver ,
MessageContext ,
resolve_message ,
)
# Context resolver
resolver = ContextResolver ()
# Context-specific message retrieval
msg = resolve_message (
code = ValidatorMessageCode . NULL_VALUES_FOUND ,
context = MessageContext . TECHNICAL , # formal, informal, technical
locale = "ko" ,
column = "email" ,
count = 10 ,
)
Custom Catalogs
Creating Catalogs
from truthound.validators.i18n import (
ValidatorMessageCatalog ,
CatalogBuilder ,
create_custom_catalog ,
)
# Create with builder
builder = CatalogBuilder ( "custom" )
builder . add_message (
ValidatorMessageCode . NULL_VALUES_FOUND ,
"Column ' {column} ' contains {count} null values" ,
)
builder . add_message (
ValidatorMessageCode . DUPLICATE_VALUES_FOUND ,
"Found {count} duplicate values in ' {column} '" ,
)
catalog = builder . build ()
# Convenience function
catalog = create_custom_catalog (
locale = "custom" ,
messages = {
ValidatorMessageCode . NULL_VALUES_FOUND : "Custom null message: {count} " ,
},
fallback = "en" ,
)
Registering Catalogs
from truthound.validators.i18n import get_catalog_manager
manager = get_catalog_manager ()
manager . register_catalog ( "custom" , catalog )
# Use
set_validator_locale ( "custom" )
msg = get_validator_message ( ValidatorMessageCode . NULL_VALUES_FOUND , count = 5 )
Retrieving Existing Catalogs
from truthound.validators.i18n import (
get_all_catalogs ,
get_all_extended_catalogs ,
get_supported_locales ,
get_extended_supported_locales ,
get_default_messages ,
get_korean_messages ,
get_japanese_messages ,
get_chinese_messages ,
get_german_messages ,
get_french_messages ,
get_spanish_messages ,
get_portuguese_messages ,
get_italian_messages ,
get_russian_messages ,
get_arabic_messages ,
get_hebrew_messages ,
get_persian_messages ,
)
# Supported locales list
locales = get_supported_locales ()
# ["en", "ko", "ja", "zh", "de", "fr", "es"]
extended = get_extended_supported_locales ()
# ["pt", "pt-BR", "pt-PT", "it", "ru", "ar", "he", "fa"]
# All catalogs
all_catalogs = get_all_catalogs ()
all_extended = get_all_extended_catalogs ()
# Individual catalogs
en_messages = get_default_messages ()
ko_messages = get_korean_messages ()
ar_messages = get_arabic_messages ()
Next Steps