1 import { c, msgid } from 'ttag';
3 import { sizeUnits } from './size';
5 export type SizeUnits = keyof typeof sizeUnits;
7 export const getSizeFormat = (key: SizeUnits, n: number) => {
9 return c('file size format').ngettext(msgid`byte`, `bytes`, n);
12 return c('file size format').t`KB`;
15 return c('file size format').t`MB`;
18 return c('file size format').t`GB`;
21 return c('file size format').t`TB`;
23 throw new Error('Unknown unit');
26 export const getLongSizeFormat = (key: SizeUnits, n: number) => {
28 return c('file size format, long').ngettext(msgid`Byte`, `Bytes`, n);
31 return c('file size format, long').ngettext(msgid`Kilobyte`, `Kilobytes`, n);
34 return c('file size format, long').ngettext(msgid`Megabyte`, `Megabytes`, n);
37 return c('file size format, long').ngettext(msgid`Gigabyte`, `Gigabytes`, n);
40 return c('file size format, long').ngettext(msgid`Terabyte`, `Terabytes`, n);
42 throw new Error('Unknown unit');
45 // Due to legacy reasons, we keep the default max to GB instead of TB to avoid changing expectations of current consumers
46 const defaultUnitOptions: { max?: SizeUnits } = {
49 export const getUnit = (bytes: number, options = defaultUnitOptions): SizeUnits => {
50 if (bytes < sizeUnits.KB || options?.max === 'B') {
54 if (bytes < sizeUnits.MB || options?.max === 'KB') {
58 if (bytes < sizeUnits.GB || options?.max === 'MB') {
62 if (bytes < sizeUnits.TB || options?.max === 'GB') {
69 const transformTo = ({
78 withoutUnit?: boolean;
79 fractionDigits?: number;
82 const completeValue = bytes / sizeUnits[unit];
84 if (fractionDigits === 0 && !truncate) {
85 value = `${Number(completeValue.toFixed(1))}`;
87 value = completeValue.toFixed(fractionDigits);
89 const suffix = withoutUnit ? '' : ` ${getSizeFormat(unit, Number(value))}`;
91 return value + suffix;
98 fraction: maybeFraction,
103 bytes: number | undefined;
105 unitOptions?: Parameters<typeof getUnit>[1];
106 withoutUnit?: boolean;
109 const unit = maybeUnit || getUnit(bytes, unitOptions);
110 const fractionDigits = maybeFraction === undefined && unit === 'B' ? 0 : maybeFraction;
111 return transformTo({ bytes, unit, withoutUnit, fractionDigits, truncate });
114 export default humanSize;
117 * shortHumanSize makes the compact size version to the bytes precision. It drops
118 * the fractional part for sizes smaller than gigabyte--only for bigger files
119 * it shows one fractional digit. Examples:
121 * 12 bytes -> 12 bytes
124 * 12.34 GB -> 12.3 GB
126 export const shortHumanSize = (bytes = 0) => {
127 if (bytes < sizeUnits.KB) {
128 return humanSize({ bytes, unit: 'B', truncate: true, fraction: 0 });
130 if (bytes < sizeUnits.GB) {
131 return humanSize({ bytes, truncate: true, fraction: 0 });
133 return humanSize({ bytes, fraction: 1 });
137 * Produces always readable version in bytes. Useful for titles where we
138 * might want to display the exact size.
140 export const bytesSize = (bytes = 0) => {
141 return `${bytes} ${getSizeFormat('B', bytes)}`;