Internationalization (i18n)
TimberCloud provides comprehensive internationalization support, allowing you to operate globally with proper currency formatting, locale-specific displays, and regional configurations.
Overview
Our internationalization system supports:
- 135+ Currencies: Full ISO 4217 currency code support via Stripe integration
- 27+ Locales: Regional date, number, and currency formatting
- 193 Countries: Complete country database with automatic currency detection
- Regional Formats: Dates, numbers, addresses, phone numbers, and postal codes
- Tax Variations: Country-specific tax labels (VAT, GST, Sales Tax, etc.)
- Measurement Units: Automatic imperial/metric switching based on region
- Payment Processing: Multi-currency Stripe integration with zero-decimal support
Quick Setup
Step 1: Configure Company Locale
- Navigate to Settings → Company → Locale & Currency Settings
- Select your country from the dropdown
- Currency and locale are automatically detected based on country
- Review the format preview (date, number, currency display)
- Click "Save Changes"
Step 2: Review Currency Settings
- Lock to Country Currency: Enable to automatically sync currency with country
- Manual Currency: Disable the lock to select a different currency
- The currency symbol is automatically set based on your selection
Supported Locales
TimberCloud supports 27 locales with full formatting capabilities:
Americas
| Locale | Name | Date Format | Number Format |
|---|---|---|---|
| en-US | English (United States) | MM/DD/YYYY | 1,234.56 |
| en-CA | English (Canada) | DD/MM/YYYY | 1,234.56 |
| fr-CA | French (Canada) | DD/MM/YYYY | 1 234,56 |
| es-MX | Spanish (Mexico) | DD/MM/YYYY | 1,234.56 |
| pt-BR | Portuguese (Brazil) | DD/MM/YYYY | 1.234,56 |
Europe
| Locale | Name | Date Format | Number Format |
|---|---|---|---|
| en-GB | English (United Kingdom) | DD/MM/YYYY | 1,234.56 |
| de-DE | German (Germany) | DD.MM.YYYY | 1.234,56 |
| fr-FR | French (France) | DD/MM/YYYY | 1 234,56 |
| es-ES | Spanish (Spain) | DD/MM/YYYY | 1.234,56 |
| it-IT | Italian (Italy) | DD/MM/YYYY | 1.234,56 |
| pt-PT | Portuguese (Portugal) | DD/MM/YYYY | 1.234,56 |
| nl-NL | Dutch (Netherlands) | DD-MM-YYYY | 1.234,56 |
| sv-SE | Swedish (Sweden) | YYYY-MM-DD | 1 234,56 |
| no-NO | Norwegian (Norway) | DD.MM.YYYY | 1 234,56 |
| da-DK | Danish (Denmark) | DD-MM-YYYY | 1.234,56 |
| fi-FI | Finnish (Finland) | DD.MM.YYYY | 1 234,56 |
| pl-PL | Polish (Poland) | DD.MM.YYYY | 1 234,56 |
| ru-RU | Russian (Russia) | DD.MM.YYYY | 1 234,56 |
| tr-TR | Turkish (Turkey) | DD.MM.YYYY | 1.234,56 |
Asia-Pacific
| Locale | Name | Date Format | Number Format |
|---|---|---|---|
| en-AU | English (Australia) | DD/MM/YYYY | 1,234.56 |
| ja-JP | Japanese (Japan) | YYYY/MM/DD | 1,234.56 |
| zh-CN | Chinese (China) | YYYY/MM/DD | 1,234.56 |
| ko-KR | Korean (South Korea) | YYYY.MM.DD | 1,234.56 |
Middle East
| Locale | Name | Date Format | Number Format |
|---|---|---|---|
| ar-SA | Arabic (Saudi Arabia) | DD/MM/YYYY | ١٬٢٣٤٫٥٦ |
| he-IL | Hebrew (Israel) | DD/MM/YYYY | 1,234.56 |
| hi-IN | Hindi (India) | DD/MM/YYYY | 1,23,456.78 |
Currency Support
Standard Currencies (2 Decimals)
Most currencies use two decimal places:
- USD - $1,234.56 (US Dollar)
- EUR - €1.234,56 (Euro)
- GBP - £1,234.56 (British Pound)
- CAD - C$1,234.56 (Canadian Dollar)
- AUD - A$1,234.56 (Australian Dollar)
Zero-Decimal Currencies
These currencies have no decimal places:
- JPY - ¥1,234 (Japanese Yen)
- KRW - ₩1,234 (South Korean Won)
- VND - ₫1,234 (Vietnamese Dong)
- HUF - 1,234 Ft (Hungarian Forint)
- CLP - $1,234 (Chilean Peso)
- TWD - NT$1,234 (New Taiwan Dollar)
Three-Decimal Currencies
These currencies use three decimal places:
- BHD - BD 1.234 (Bahraini Dinar)
- KWD - KD 1.234 (Kuwaiti Dinar)
- OMR - OMR 1.234 (Omani Rial)
- JOD - JD 1.234 (Jordanian Dinar)
Special Formatting
- Indian Rupee: ₹12,34,567.89 (lakh/crore grouping system)
- Swiss Franc: CHF 1'234.56 (apostrophe separator)
- Arabic Numerals: ١٬٢٣٤٫٥٦ (Eastern Arabic numerals for ar-SA)
Regional Configurations
Tax Labels
Tax terminology varies by country:
| Region | Tax Label |
|---|---|
| United States | Sales Tax |
| Canada | GST/PST |
| European Union | VAT |
| United Kingdom | VAT |
| Australia | GST |
| Germany | MwSt (VAT) |
| Japan | Consumption Tax |
Address Formats
United States
Street Address
City, State ZIP
CountryUnited Kingdom
Street Address
City
County
Postcode
CountryJapan
〒 Postal Code
Prefecture
City
Street AddressPostal Code Validation
Country-specific postal code formats are validated automatically:
| Country | Format | Example |
|---|---|---|
| US | 5 digits or 5+4 | 12345, 12345-6789 |
| Canada | Letter-Number alternating | K1A 0B1 |
| UK | Alphanumeric | SW1A 1AA |
| Germany | 5 digits | 10115 |
| Japan | 3-4 digits | 100-0001 |
| Australia | 4 digits | 2000 |
| Netherlands | 4 digits + 2 letters | 1234 AB |
Phone Number Formats
International phone formatting by region:
| Country | Format |
|---|---|
| US/Canada | +1 (555) 123-4567 |
| UK | +44 20 1234 5678 |
| Germany | +49 30 12345678 |
| Japan | +81 3-1234-5678 |
| Australia | +61 2 1234 5678 |
Measurement Units
Automatic unit system selection:
| Country | System | Length | Weight |
|---|---|---|---|
| United States | Imperial | inches | lb |
| United Kingdom | Mixed | mm | kg |
| Canada | Metric | cm | kg |
| Australia | Metric | cm | kg |
| Most Others | Metric | cm | kg |
For Developers
Currency Formatting Hook
import { useCurrencyFormatter } from '@/hooks/useCurrencyFormatter';
function PriceDisplay({ company, amount }) {
const formatter = useCurrencyFormatter(company);
return (
<div>
{/* Format as currency: $1,234.56 */}
<p>{formatter.format(amount)}</p>
{/* Format number only: 1,234.56 */}
<p>{formatter.formatNumber(amount)}</p>
{/* Convert to Stripe units (cents) */}
<p>Stripe amount: {formatter.toSmallestUnit(amount)}</p>
</div>
);
}Date Formatting Hook
import { useDateFormatter } from '@/hooks/useDateFormatter';
function DateDisplay({ date }) {
const { formatDate, formatRelative, formatCalendar } = useDateFormatter();
return (
<div>
{/* Locale-aware short date: 12/31/2024 or 31/12/2024 */}
<p>{formatDate(date, 'date.short')}</p>
{/* Medium format: Dec 31, 2024 */}
<p>{formatDate(date, 'date.medium')}</p>
{/* Relative: 2 days ago */}
<p>{formatRelative(date)}</p>
{/* Calendar: Yesterday at 3:30 PM */}
<p>{formatCalendar(date)}</p>
</div>
);
}i18n Utility Functions
import i18n from '@/util/i18n';
// Get currency for a country
const currency = i18n.getCurrencyByCountry('GB');
// { code: 'GBP', symbol: '£', name: 'Pound Sterling', digits: 2 }
// Format currency with locale
const formatted = i18n.formatCurrency(1234.56, 'EUR', 'de-DE');
// "1.234,56 €"
// Get decimal places for Stripe integration
const decimals = i18n.getDecimalPlaces('JPY'); // 0
// Convert to Stripe smallest unit
const stripeAmount = i18n.toStripeCurrencyUnit(100, 'USD'); // 10000
const stripeAmountJPY = i18n.toStripeCurrencyUnit(100, 'JPY'); // 100
// Validate postal code
const isValid = i18n.validatePostalCode('SW1A 1AA', 'GB'); // true
// Get country info
const country = i18n.getCountryByCode('US');
// { code: 'US', name: 'United States', currencies: ['USD'], ... }Stripe Integration
Multi-Currency Payments
TimberCloud integrates with Stripe for payment processing:
- 135+ Currencies: Process payments in customer's preferred currency
- Zero-Decimal Handling: Automatic conversion for currencies like JPY, KRW
- Three-Decimal Support: Proper handling for BHD, KWD, OMR
- Settlement Options: Receive funds in your base currency
Currency Unit Conversion
All Stripe amounts are handled in the smallest currency unit:
// USD: $12.34 → 1234 cents
i18n.toStripeCurrencyUnit(12.34, 'USD'); // 1234
// JPY: ¥100 → 100 (no conversion needed)
i18n.toStripeCurrencyUnit(100, 'JPY'); // 100
// KWD: KD 1.234 → 1234 fils
i18n.toStripeCurrencyUnit(1.234, 'KWD'); // 1234Company Schema Fields
The following fields control internationalization at the company level:
| Field | Type | Default | Description |
|---|---|---|---|
country_code | string(2) | "US" | ISO 3166-1 alpha-2 country code |
currency | string(3) | "USD" | ISO 4217 currency code |
currency_symbol | string(5) | "$" | Currency display symbol |
default_locale | string(10) | "en-US" | BCP 47 locale identifier |
Best Practices
- Always Use Formatters: Use
useCurrencyFormatteranduseDateFormatterhooks instead of manual formatting - Store Raw Values: Store amounts in database as raw numbers, format only for display
- ISO Standards: Use ISO country codes (US, GB) and currency codes (USD, GBP)
- Test Edge Cases: Verify formatting with zero-decimal currencies and large numbers
- Stripe Compatibility: Always convert to smallest unit before sending to Stripe
- Locale Consistency: Match currency to locale for proper formatting
Troubleshooting
Currency Display Issues
- Verify
currencyandcurrency_symbolare set on company - Check that currency code is valid ISO 4217
- Ensure locale supports the selected currency
Date Format Mismatches
- Confirm
default_localeis set correctly - Verify moment.js locale is loaded for the target locale
- Check browser timezone settings for date/time discrepancies
Postal Code Validation Failing
- Ensure country code is correctly set
- Check that postal code matches the expected format for that country
- Spaces and formatting may vary by region
Number Parsing Issues
- Different locales use different decimal separators (. vs ,)
- Use
formatter.parse()to correctly parse locale-formatted numbers - Always normalize to standard format before calculations