intlrelative
Relative time formatting for gleam_time following the JavaScript Intl.RelativeTimeFormat() API.
This module provides a type-safe wrapper around the Intl.RelativeTimeFormat API,
allowing you to format durations as human-readable relative times (like “in 3 hours”
or “il y a 5 secondes”) according to locale-specific conventions.
Works on both the JavaScript and Erlang runtimes. On JavaScript it delegates to
the native Intl.RelativeTimeFormat(), while on Erlang it uses a pure Gleam
reimplementation that mirrors the same behaviour, so the output stays consistent
whichever target you compile to.
The duration is expressed relative to now: a negative duration is formatted as a time
in the past, and a positive duration as a time in the future. The unit you pass
selects which unit the duration is expressed in, and the duration is divided by that
unit to obtain the amount to display.
Error handling
format never fails: if the locale cannot be resolved, it returns a human-readable,
English-only message describing the error (via describe_error), regardless of the
requested locale.
If you’d rather handle the error yourself, use try_format, which returns a
Result(String, IntlError).
This module also mirrors formatToParts and resolvedOptions from
Intl.RelativeTimeFormat, as format_to_parts and resolved_options.
Types
pub type IntlError {
FailedToLoadLocale(inner: String)
FailedToLoadData(inner: String)
Unknown(inner: String)
}
Constructors
-
FailedToLoadLocale(inner: String)The requested locale could not be loaded or resolved.
-
FailedToLoadData(inner: String)The bundled locale data could not be loaded or validated.
-
Unknown(inner: String)Any error not accounted for by this type.
The locale matching algorithm to use.
LocaleMatcherBestFit: The runtime is allowed to choose the best matching locale, potentially considering extension keys and other options.LocaleMatcherLookup: Use the BCP 47 lookup algorithm to find the best matching locale.
pub type LocaleMatcher {
LocaleMatcherBestFit
LocaleMatcherLookup
}
Constructors
-
LocaleMatcherBestFit -
LocaleMatcherLookup
Whether to always use the numeric value or allow idiomatic phrasing.
Always: Always output a numeric value (e.g., “1 day ago”, “il y a 1 jour”)Auto: Use idiomatic phrasing when available (e.g., “yesterday”, “hier”)
pub type Numeric {
Always
Auto
}
Constructors
-
Always -
Auto
Configuration for relative time formatting.
This type allows you to specify the style and numeric behaviour of the formatted output.
Create a new configuration with new() and customize it with the various
with_* functions.
pub type RelativeTimeFormatConfig {
RelativeTimeFormatConfig(
locale_matcher: option.Option(LocaleMatcher),
style: option.Option(Style),
numeric: option.Option(Numeric),
)
}
Constructors
-
RelativeTimeFormatConfig( locale_matcher: option.Option(LocaleMatcher), style: option.Option(Style), numeric: option.Option(Numeric), )
One structured part of a formatted relative time string.
pub type RelativeTimeFormatPart {
RelativeTimeFormatPart(
kind: RelativeTimePartKind,
value: String,
unit: option.Option(String),
)
}
Constructors
-
RelativeTimeFormatPart( kind: RelativeTimePartKind, value: String, unit: option.Option(String), )
A part type returned by format_to_parts.
pub type RelativeTimePartKind {
RelativeTimePartLiteral
RelativeTimePartInteger
RelativeTimePartFraction
RelativeTimePartDecimal
RelativeTimePartUnit
RelativeTimePartUnknown(inner: String)
}
Constructors
-
RelativeTimePartLiteral -
RelativeTimePartInteger -
RelativeTimePartFraction -
RelativeTimePartDecimal -
RelativeTimePartUnit -
RelativeTimePartUnknown(inner: String)
Options resolved by a relative time formatter.
pub type RelativeTimeResolvedOptions {
RelativeTimeResolvedOptions(
locale: String,
numbering_system: String,
style: String,
numeric: String,
)
}
Constructors
-
RelativeTimeResolvedOptions( locale: String, numbering_system: String, style: String, numeric: String, )
The length of the formatted message.
Long: Full form (e.g., “in 3 hours”, “il y a 5 secondes”)Short: Abbreviated form (e.g., “in 3 hr.”, “in 2 min.”)Narrow: Narrow form, may be identical toShortfor some locales (e.g., “3 hr. ago”, “1h ago”)
pub type Style {
Long
Short
Narrow
}
Constructors
-
Long -
Short -
Narrow
The unit the duration is expressed in.
Second: SecondsMinute: MinutesHour: HoursDay: DaysWeek: WeeksMonth: MonthsQuarter: Quarters (three-month periods)Year: Years
pub type Unit {
Second
Minute
Hour
Day
Week
Month
Quarter
Year
}
Constructors
-
Second -
Minute -
Hour -
Day -
Week -
Month -
Quarter -
Year
Values
pub fn describe_error(error: IntlError) -> String
Convert an error into a human-readable description.
Example
let assert "Failed to load locale: fr-FR" =
describe_error(FailedToLoadLocale("fr-FR"))
pub fn format(
duration duration: duration.Duration,
unit unit: Unit,
locale locale: option.Option(String),
config config: RelativeTimeFormatConfig,
) -> String
Format a duration as a relative time according to the specified locale and configuration.
Parameters
duration: The duration relative to now. A negative duration is formatted as a time in the past, and a positive duration as a time in the future.unit: The unit the duration is expressed in. The duration is divided by this unit to obtain the amount to display.locale: The locale to use for formatting (BCP 47 language tag like “en-US”, “fr-FR”). IfNone, uses the system’s default locale.config: The configuration object specifying the style and numeric behaviour
Example
import gleam/option
import gleam/time/duration
import intlrelative
intlrelative.format(
duration: duration.seconds(-5),
unit: intlrelative.Second,
locale: option.Some("fr-FR"),
config: intlrelative.new(),
)
// -> "il y a 5 secondes"
pub fn format_to_parts(
duration duration: duration.Duration,
unit unit: Unit,
locale locale: option.Option(String),
config config: RelativeTimeFormatConfig,
) -> List(RelativeTimeFormatPart)
Format a duration and return the structured parts of the formatted output.
This mirrors Intl.RelativeTimeFormat.prototype.formatToParts.
pub fn new() -> RelativeTimeFormatConfig
Create a new relative time format configuration with all options unset.
Use the various with_* functions to customize the configuration.
Example
intlrelative.new()
|> intlrelative.with_style(intlrelative.Short)
|> intlrelative.with_numeric(intlrelative.Auto)
pub fn resolved_options(
locale locale: option.Option(String),
config config: RelativeTimeFormatConfig,
) -> Result(RelativeTimeResolvedOptions, IntlError)
Return the options resolved by the relative time formatter.
This mirrors Intl.RelativeTimeFormat.prototype.resolvedOptions.
pub fn try_format(
duration duration: duration.Duration,
unit unit: Unit,
locale locale: option.Option(String),
config config: RelativeTimeFormatConfig,
) -> Result(String, IntlError)
Format a duration as a relative time according to the specified locale and
configuration, returning a Result instead of falling back to an error message.
This is identical to format, except it lets you handle the IntlError
yourself instead of getting a human-readable string when resolution fails.
Example
import gleam/option
import gleam/time/duration
import intlrelative
intlrelative.try_format(
duration: duration.hours(3),
unit: intlrelative.Hour,
locale: option.Some("invalid-locale"),
config: intlrelative.new(),
)
// -> Error(intlrelative.FailedToLoadLocale("invalid-locale"))
pub fn try_format_to_parts(
duration duration: duration.Duration,
unit unit: Unit,
locale locale: option.Option(String),
config config: RelativeTimeFormatConfig,
) -> Result(List(RelativeTimeFormatPart), IntlError)
Format a duration to parts, returning a Result.
pub fn with_locale_matcher(
config: RelativeTimeFormatConfig,
locale_matcher: LocaleMatcher,
) -> RelativeTimeFormatConfig
Set the locale matching algorithm.
The locale matcher determines how the runtime selects the best matching locale when the exact locale you requested isn’t available.
pub fn with_numeric(
config: RelativeTimeFormatConfig,
numeric: Numeric,
) -> RelativeTimeFormatConfig
Set whether to always use the numeric value or allow idiomatic phrasing.
pub fn with_style(
config: RelativeTimeFormatConfig,
style: Style,
) -> RelativeTimeFormatConfig
Set the length of the formatted message.