Skip to content

Commit

Permalink
feat: added durationFormat
Browse files Browse the repository at this point in the history
  • Loading branch information
schummar committed Mar 19, 2024
1 parent 8df71e3 commit 71e9120
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 2 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"intl-messageformat": "^10.5.0"
},
"peerDependencies": {
"@formatjs/intl-durationformat": "^0.2.2",
"@types/react": ">=16.8.0",
"react": ">=16.8.0"
},
Expand All @@ -80,6 +81,7 @@
}
},
"devDependencies": {
"@formatjs/intl-durationformat": "^0.2.2",
"@js-temporal/polyfill": "^0.4.4",
"@schummar/runp": "1.12.0",
"@testing-library/react": "14.0.0",
Expand Down
23 changes: 23 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion src/intlHelpers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Cache } from './cache';
import { toDate } from './helpers';
import { TemporalLike } from './polyfill/temporal';
import { IntlHelpers } from './types';
import { DurationFormatOptions, IntlHelpers } from './types';

export function intlHelpers<Output>({
cache,
Expand All @@ -19,6 +19,7 @@ export function intlHelpers<Output>({
numberFormatOptions?: Intl.NumberFormatOptions;
pluralRulesOptions?: Intl.PluralRulesOptions;
relativeTimeFormatOptions?: Intl.RelativeTimeFormatOptions;
durationFormatOptions?: DurationFormatOptions;
}): IntlHelpers<Output> {
return {
dateTimeFormat(date, options = dateTimeFormatOptions) {
Expand Down Expand Up @@ -52,6 +53,14 @@ export function intlHelpers<Output>({
relativeTimeFormat(value, unit, options = relativeTimeFormatOptions) {
return transform((locale) => cache.get(Intl.RelativeTimeFormat, locale, options).format(value, unit));
},

durationFormat(duration, options) {
const intl = Intl as { DurationFormat?: any };
if (!intl.DurationFormat) {
throw new Error('Intl.DurationFormat is not available in this environment. Try using the polyfill');
}
return transform((locale) => cache.get(intl.DurationFormat, locale, options).format(duration));
},
};
}

Expand Down
2 changes: 2 additions & 0 deletions src/translator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const createGetTranslator =
numberFormatOptions,
pluralRulesOptions,
relativeTimeFormatOptions,
durationFormatOptions,
ignoreMissingArgs,
provideArgs,
}: CreateTranslatorOptions<D, ProvidedArgs>,
Expand Down Expand Up @@ -73,6 +74,7 @@ export const createGetTranslator =
numberFormatOptions,
pluralRulesOptions,
relativeTimeFormatOptions,
durationFormatOptions,
}),
});
};
Expand Down
8 changes: 8 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CacheOptions } from './cache';
import { GetICUArgs } from './extractICU';
import { TemporalLike } from './polyfill/temporal';
import { DurationFormat } from '@formatjs/intl-durationformat';

////////////////////////////////////////////////////////////////////////////////
// Helpers
Expand Down Expand Up @@ -41,6 +42,9 @@ export type Flatten<T> = T extends object
}
: T;

export type DurationFormatOptions = Partial<ReturnType<DurationFormat['resolvedOptions']>>;
export type DurationInput = Parameters<DurationFormat['format']>[0];

////////////////////////////////////////////////////////////////////////////////
// Public types
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -89,6 +93,8 @@ export type CreateTranslatorOptions<D extends Dict, ProvidedArgs extends string
pluralRulesOptions?: Intl.PluralRulesOptions;
/** Default options */
relativeTimeFormatOptions?: Intl.RelativeTimeFormatOptions;
/** Default options */
durationFormatOptions?: DurationFormatOptions;
} & (IsNever<ProvidedArgs> extends true
? { provideArgs?: Record<string, never> }
: {
Expand Down Expand Up @@ -189,6 +195,8 @@ export interface IntlHelpers<Output = string> {

/** Wraps Intl.RelativeTimeFormat.format */
relativeTimeFormat(value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions): Output;
/** Wraps Intl.DurationFormat.format */
durationFormat(duration: DurationInput, options?: DurationFormatOptions): Output;
}

export type ICUArgument = string | number | boolean | Date;
Expand Down
3 changes: 2 additions & 1 deletion test/_setup.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { afterEach } from 'vitest';
import '@formatjs/intl-durationformat/polyfill';
import { cleanup } from '@testing-library/react';
import { afterEach } from 'vitest';

Object.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true });

Expand Down
14 changes: 14 additions & 0 deletions test/react.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,20 @@ forCases(
},
);

forCases(
'durationFormat',
() => t.durationFormat({ seconds: 1 }, { style: 'long' }),
async (div) => {
expect(div.textContent).toBe('1 second');

act(() => {
div.click();
});

expect(div.textContent).toBe('1 Sekunde');
},
);

forCases(
'match locales',
() => t('key1'),
Expand Down
8 changes: 8 additions & 0 deletions test/translator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,14 @@ test('relativeTimeFormat', async () => {
expect(de.relativeTimeFormat(-30, 'seconds')).toBe('vor 30 Sekunden');
});

test('durationFormat', async () => {
const en = await getTranslator('en');
const de = await getTranslator('de');

expect(en.durationFormat({ seconds: 1 }, { style: 'long' })).toBe('1 second');
expect(de.durationFormat({ seconds: 1 }, { style: 'long' })).toBe('1 Sekunde');
});

test('clear', async () => {
let count = 0;

Expand Down

0 comments on commit 71e9120

Please sign in to comment.