TypeScript, Formatting & Internationalization
How Plotcn achieves strict compile-time type safety, standards-based Intl formatting, and culturally neutral runtime internationalization without framework lock-in.
Governing principle
Plotcn treats type safety, formatting, locale behavior, and directional layout as foundational architecture rather than documentation polish added after the fact.
The governing principle is:
Strict TypeScript architecture
All public Plotcn chart APIs use strict TypeScript. any is forbidden in public prop contracts.
Generic data models
Charts are generic over the consumer's existing data model (Chart<TData>). Rather than forcing consumers to transform objects into arbitrary { x, y } structures, Plotcn reads domain properties directly:
Typed accessors
For deeply nested or computed values, charts support typed accessors alongside keys:
Literal series preservation
Series definitions preserve exact string literals rather than widening to string:
Standards-based formatting
Plotcn delegates formatting to native Intl standards (Intl.NumberFormat, Intl.DateTimeFormat, Intl.RelativeTimeFormat), eliminating bloated custom localization tables.
Core formatting utilities
All formatting functions are pure, tree-shakeable, and renderer-neutral (chart-core/formatting):
| Utility | Primary function | Key options |
|---|---|---|
formatNumber() | Localized digit grouping & fractions | locale, minimumFractionDigits, maximumFractionDigits |
formatCurrency() | Currency values with explicit ISO code | currency (mandatory), locale, currencyDisplay |
formatPercentage() | Ratios & percentage points | decimals, isRatio (0.42 vs 42), locale |
formatCompactNumber() | Compact axis/badge notation | locale, maximumFractionDigits (1.2M, 4.5K) |
formatDate() | Locale-aware calendar & time formatting | dateStyle, timeStyle, timeZone, locale |
formatDuration() | Human-readable elapsed durations | Total seconds to "2h 15m" / "45s" |
Explicit currency policy
formatCurrency() strictly forbids defaulting to USD:
Explicit percentage semantics
Never guess percentage scale based on value <= 1. Input semantics must be explicit:
Keep raw values raw
Formatting occurs strictly at presentation boundaries (axis ticks, tooltips, data tables). Data arrays and scale domains always preserve raw numeric and date values:
Directionality & Internationalization (RTL)
Plotcn supports right-to-left (RTL) interfaces without distorting mathematical coordinates.
Separating UI chrome from data domains
CSS logical properties
All layout rules prioritize logical properties over physical left/right rules:
Unicode safety & label typography
Plotcn respects diverse writing systems:
- Arabic & Hebrew: Never letter-spaced; rendered with natural ligatures.
- Devanagari & Thai: Accommodates tall ascenders and complex diacritics in container padding.
- CJK Scripts: Supports natural ideograph wrapping without requiring space separators.
- Bidi Isolation: Mixed-direction labels (e.g., Hebrew category with USD currency) wrap with
<bdi>or directional isolation. - No Forced Uppercasing: Consumer-provided localized strings are never transformed with
text-transform: uppercase.
Summary of architectural invariants
15 Core TypeScript invariants
- Public APIs never use
any. - Consumer datum types remain generic (
Chart<TData>). - Key-based APIs infer valid keys from
TData. - Numeric fields are constrained at compile-time.
- Accessors remain strongly typed
(d: TData) => number. - Literal series keys are preserved using
as const. - Readonly arrays and configs are accepted (
readonly TData[]). - Runtime boundary inputs use
unknownbefore validation. - Public event payloads are typed with domain semantics.
- Engine-specific types remain narrow and intentional.
- Internal normalized types are never leaked publicly.
- Empty/loading arrays do not require weakening types to
any[]. - Nullability reflects actual gaps (
number | null). - Compile-time type behavior is verified in automated tests.
- Type sophistication never degrades developer ergonomics.
15 Core formatting invariants
- Formatting operates on raw semantic values.
- Native
IntlAPIs are preferred over custom tables. - USD is never globally assumed.
en-USis never globally assumed.- Percentage input semantics (ratio vs. point) are explicit.
- Dates and timestamps are validated before formatting.
- Reporting time zones can be explicitly specified.
- Compact formatting (
1.2M,45K) is locale-aware. - Axis precision and tooltip precision can differ intentionally.
- Missing values (
null,NaN) bypass normal formatters. - Currency codes are explicit and never inferred from locale.
- Formatting operations never mutate underlying data.
- Accessible screen-reader summaries share identical locale semantics.
- Formatting utilities remain renderer-neutral and pure.
- All chart engines share unified formatting contracts.
12 Core internationalization invariants
- Plotcn does not assume left-to-right UI layouts.
- CSS logical properties (
*-inline) are enforced. - UI chrome direction and data-domain direction remain distinct.
- Consumer labels are never forcibly uppercased.
- Long translated strings are supported with flexible containers.
- Unicode text renders naturally in ticks, legends, and tooltips.
- Mixed-direction text remains readable with bidirectional isolation.
- Brand names and registry IDs remain stable ASCII identifiers.
- Components integrate with application i18n frameworks (
next-intl,react-intl). - Plotcn does not ship a mandatory translation catalog.
- Server-side rendering (SSR) formatting remains deterministic.
- Localization support is verified through representative tests.