Skip to content

Commit

Permalink
Convert to typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
cibernox committed Jan 20, 2020
1 parent cab9be8 commit b66ae96
Show file tree
Hide file tree
Showing 24 changed files with 653 additions and 150 deletions.
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
tsconfig.json
src
28 changes: 28 additions & 0 deletions dist/config.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
interface Formats {
number: Record<string, any>;
date: Record<string, any>;
time: Record<string, any>;
}
interface Options {
fallbackLocale: string;
initialLocale: string;
formats: Formats;
loadingDelay: number;
warnOnMissingMessages: boolean;
}
interface GetClientLocaleOptions {
navigator?: boolean;
hash?: string;
search?: string;
pathname?: RegExp;
hostname?: RegExp;
}
interface ConfigureOptions {
fallbackLocale: string;
initialLocale?: string | GetClientLocaleOptions;
formats?: Partial<Formats>;
loadingDelay?: number;
}
export declare function init(opts: ConfigureOptions): void;
export declare function getOptions(): Options;
export {};
111 changes: 111 additions & 0 deletions dist/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { currentLocale } from "./stores";
const defaultFormats = {
number: {
scientific: { notation: "scientific" },
engineering: { notation: "engineering" },
compactLong: { notation: "compact", compactDisplay: "long" },
compactShort: { notation: "compact", compactDisplay: "short" }
},
date: {
short: { month: "numeric", day: "numeric", year: "2-digit" },
medium: { month: "short", day: "numeric", year: "numeric" },
long: { month: "long", day: "numeric", year: "numeric" },
full: { weekday: "long", month: "long", day: "numeric", year: "numeric" }
},
time: {
short: { hour: "numeric", minute: "numeric" },
medium: { hour: "numeric", minute: "numeric", second: "numeric" },
long: {
hour: "numeric",
minute: "numeric",
second: "numeric",
timeZoneName: "short"
},
full: {
hour: "numeric",
minute: "numeric",
second: "numeric",
timeZoneName: "short"
}
}
};
const defaultOptions = {
fallbackLocale: null,
initialLocale: null,
loadingDelay: 200,
formats: defaultFormats,
warnOnMissingMessages: true
};
const options = defaultOptions;
const getFromQueryString = (queryString, key) => {
const keyVal = queryString.split("&").find(i => i.indexOf(`${key}=`) === 0);
if (keyVal) {
return keyVal.split("=").pop();
}
return null;
};
const getFirstMatch = (base, pattern) => {
const match = pattern.exec(base);
// istanbul ignore if
if (!match)
return null;
// istanbul ignore else
return match[1] || null;
};
function getClientLocale({ navigator, hash, search, pathname, hostname }) {
let locale;
// istanbul ignore next
if (typeof window === "undefined")
return null;
if (hostname) {
locale = getFirstMatch(window.location.hostname, hostname);
if (locale)
return locale;
}
if (pathname) {
locale = getFirstMatch(window.location.pathname, pathname);
if (locale)
return locale;
}
if (navigator) {
// istanbul ignore else
locale = window.navigator.language || window.navigator.languages[0];
if (locale)
return locale;
}
if (search) {
locale = getFromQueryString(window.location.search.substr(1), search);
if (locale)
return locale;
}
if (hash) {
locale = getFromQueryString(window.location.hash.substr(1), hash);
if (locale)
return locale;
}
return null;
}
export function init(opts) {
const { formats, ...rest } = opts;
const initialLocale = opts.initialLocale
? typeof opts.initialLocale === "string"
? opts.initialLocale
: getClientLocale(opts.initialLocale) || opts.fallbackLocale
: opts.fallbackLocale;
Object.assign(options, rest, { initialLocale });
if (formats) {
if ("number" in formats) {
Object.assign(options.formats.number, formats.number);
}
if ("date" in formats) {
Object.assign(options.formats.date, formats.date);
}
if ("time" in formats) {
Object.assign(options.formats.time, formats.time);
}
}
return currentLocale.set(initialLocale);
}
export function getOptions() {
return options;
}
14 changes: 14 additions & 0 deletions dist/formatters.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
declare type IntlFormatterOptions<T> = T & {
format?: string;
locale?: string;
};
interface MemoizedIntlFormatter<T, U> {
(options?: IntlFormatterOptions<U>): T;
}
export declare const getNumberFormatter: MemoizedIntlFormatter<Intl.NumberFormat, Intl.NumberFormatOptions>;
export declare const getDateFormatter: MemoizedIntlFormatter<Intl.DateTimeFormat, Intl.DateTimeFormatOptions>;
export declare const getTimeFormatter: MemoizedIntlFormatter<Intl.DateTimeFormat, Intl.DateTimeFormatOptions>;
export declare const formatTime: (t: Date, options: Record<string, any>) => string;
export declare const formatDate: (d: Date, options: Record<string, any>) => string;
export declare const formatNumber: (n: number, options: Record<string, any>) => string;
export {};
124 changes: 124 additions & 0 deletions dist/formatters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { getCurrentLocale } from './stores';
import { getOptions } from './config';
import { monadicMemoize } from './memoize';
const getIntlFormatterOptions = (type, name) => {
const formats = getOptions().formats;
if (type in formats && name in formats[type]) {
return formats[type][name];
}
throw new Error(`[icu-helpers] Unknown "${name}" ${type} format.`);
};
export const getNumberFormatter = monadicMemoize(({ locale, format, ...options } = {}) => {
locale = locale || getCurrentLocale();
if (locale == null) {
throw new Error('[icu-helpers] A "locale" must be set to format numbers');
}
if (format) {
options = getIntlFormatterOptions('number', format);
}
return new Intl.NumberFormat(locale, options);
});
export const getDateFormatter = monadicMemoize(({ locale, format, ...options } = {}) => {
locale = locale || getCurrentLocale();
if (locale == null) {
throw new Error('[icu-helpers] A "locale" must be set to format dates');
}
if (format)
options = getIntlFormatterOptions('date', format);
else if (Object.keys(options).length === 0) {
options = getIntlFormatterOptions('date', 'short');
}
return new Intl.DateTimeFormat(locale, options);
});
export const getTimeFormatter = monadicMemoize(({ locale, format, ...options } = {}) => {
locale = locale || getCurrentLocale();
if (locale == null) {
throw new Error('[svelte-i18n] A "locale" must be set to format time values');
}
if (format)
options = getIntlFormatterOptions('time', format);
else if (Object.keys(options).length === 0) {
options = getIntlFormatterOptions('time', 'short');
}
return new Intl.DateTimeFormat(locale, options);
});
export const formatTime = (t, options) => getTimeFormatter(options).format(t);
export const formatDate = (d, options) => getDateFormatter(options).format(d);
export const formatNumber = (n, options) => getNumberFormatter(options).format(n);
// import { getOptions } from "./config";
// const CACHED = Object.create(null);
// export function formatterOptions(type, style) {
// return getOptions().formats[type][style] || {};
// }
// const getIntlFormatterOptions = (type, name) => {
// const formats = getOptions().formats
// if (type in formats && name in formats[type]) {
// return formats[type][name]
// }
// throw new Error(`[icu-helpers] Unknown "${name}" ${type} format.`)
// }
// // const getIntlFormatterOptions = (
// // type: 'time' | 'number' | 'date',
// // name: string
// // ): any => {
// // const formats = getOptions().formats
// // if (type in formats && name in formats[type]) {
// // return formats[type][name]
// // }
// // throw new Error(`[svelte-i18n] Unknown "${name}" ${type} format.`)
// // }
// // export const getNumberFormatter: MemoizedIntlFormatter<
// // Intl.NumberFormat,
// // Intl.NumberFormatOptions
// // > = monadicMemoize(({ locale, format, ...options } = {}) => {
// // locale = locale || getCurrentLocale()
// // if (locale == null) {
// // throw new Error('[svelte-i18n] A "locale" must be set to format numbers')
// // }
// // if (format) {
// // options = getIntlFormatterOptions('number', format)
// // }
// // return new Intl.NumberFormat(locale, options)
// // })
// // export const getDateFormatter: MemoizedIntlFormatter<
// // Intl.DateTimeFormat,
// // Intl.DateTimeFormatOptions
// // > = monadicMemoize(({ locale, format, ...options } = {}) => {
// // locale = locale || getCurrentLocale()
// // if (locale == null) {
// // throw new Error('[svelte-i18n] A "locale" must be set to format dates')
// // }
// // if (format) options = getIntlFormatterOptions('date', format)
// // else if (Object.keys(options).length === 0) {
// // options = getIntlFormatterOptions('date', 'short')
// // }
// // return new Intl.DateTimeFormat(locale, options)
// // })
// // export const getTimeFormatter: MemoizedIntlFormatter<
// // Intl.DateTimeFormat,
// // Intl.DateTimeFormatOptions
// // > = monadicMemoize(({ locale, format, ...options } = {}) => {
// // locale = locale || getCurrentLocale()
// // if (locale == null) {
// // throw new Error(
// // '[svelte-i18n] A "locale" must be set to format time values'
// // )
// // }
// // if (format) options = getIntlFormatterOptions('time', format)
// // else if (Object.keys(options).length === 0) {
// // options = getIntlFormatterOptions('time', 'short')
// // }
// // return new Intl.DateTimeFormat(locale, options)
// // })
// // export function getNumberFormatter({ locale, format, ...options }) {
// // let key = "number" + locale + JSON.stringify(opts);
// // return CACHED[key] || (CACHED[key] = new Intl.NumberFormat(locale, opts));
// // }
// // export function getDateFormatter(locale, opts) {
// // let key = "date" + locale + JSON.stringify(opts);
// // return CACHED[key] || (CACHED[key] = new Intl.DateTimeFormat(locale, opts));
// // }
// // export function getTimeFormatter(locale, opts) {
// // let key = "time" + locale + JSON.stringify(opts);
// // return CACHED[key] || (CACHED[key] = new Intl.DateTimeFormat(locale, opts));
// // }
14 changes: 14 additions & 0 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { init } from "./config";
import { currentLocale, dictionary, locales, LocaleDictionary } from "./stores";
import { getNumberFormatter, getDateFormatter, getTimeFormatter, formatTime, formatDate, formatNumber } from "./formatters";
declare type PluralRule = "zero" | "one" | "two" | "few" | "many" | "other" | number;
declare type PluralOptions = Record<PluralRule, string>;
export declare function __interpolate(value: any): any;
export declare function __plural(value: number, offsetOrOptions: number | PluralOptions, opts?: PluralOptions): string;
export declare function __select(value: any, opts: Record<any, string>): string;
export declare function __number(value: number, format?: string): string;
export declare function __date(value: Date, format?: string): string;
export declare function __time(value: Date, format?: string): string;
export declare function addMessages(locale: string, messages: LocaleDictionary): void;
export declare function lookupMessage(key: string, locale?: string): string;
export { init, currentLocale, dictionary, locales, getNumberFormatter, getDateFormatter, getTimeFormatter, formatTime, formatDate, formatNumber };
46 changes: 46 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { init } from "./config";
import { currentLocale, dictionary, locales, getCurrentLocale } from "./stores";
import { getNumberFormatter, getDateFormatter, getTimeFormatter, formatTime, formatDate, formatNumber } from "./formatters";
export function __interpolate(value) {
return value === 0 ? 0 : value || '';
}
const PLURAL_RULES = Object.create(null);
function getLocalPluralFor(v) {
let loc = getCurrentLocale();
let pluralRules = PLURAL_RULES[loc] || (PLURAL_RULES[loc] = new Intl.PluralRules(loc));
return pluralRules.select(v);
}
export function __plural(value, offsetOrOptions, opts) {
if (typeof offsetOrOptions === "number") {
return (opts[value] ||
opts[getLocalPluralFor(value - offsetOrOptions)] ||
"");
}
else {
return (offsetOrOptions[value] ||
offsetOrOptions[getLocalPluralFor(value)] ||
"");
}
}
export function __select(value, opts) {
return opts[value] || opts['other'] || '';
}
export function __number(value, format) {
return formatNumber(value, { format });
}
export function __date(value, format = "short") {
return formatDate(value, { format });
}
export function __time(value, format = "short") {
return formatTime(value, { format });
}
export function addMessages(locale, messages) {
dictionary.update(value => {
value[locale] = Object.assign(value[locale] || {}, messages);
return value;
});
}
export function lookupMessage(key, locale = getCurrentLocale()) {
return dictionary._value[locale][key];
}
export { init, currentLocale, dictionary, locales, getNumberFormatter, getDateFormatter, getTimeFormatter, formatTime, formatDate, formatNumber };
3 changes: 3 additions & 0 deletions dist/memoize.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare type MemoizedFunction = <F extends any>(fn: F) => F;
declare const monadicMemoize: MemoizedFunction;
export { monadicMemoize };
12 changes: 12 additions & 0 deletions dist/memoize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const monadicMemoize = fn => {
const cache = Object.create(null);
const memoizedFn = (arg) => {
const cacheKey = JSON.stringify(arg);
if (cacheKey in cache) {
return cache[cacheKey];
}
return (cache[cacheKey] = fn(arg));
};
return memoizedFn;
};
export { monadicMemoize };
14 changes: 14 additions & 0 deletions dist/stores.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
declare class WritableStore<T> {
_value: T;
_subscribers: ((T: any) => void)[];
constructor(v: any);
subscribe(fn: (value: T) => void): () => ((T: any) => void)[];
set(v: T): void;
update(cb: (value: T) => T): void;
}
export declare type LocaleDictionary = Record<string, string>;
export declare const currentLocale: WritableStore<string>;
export declare const dictionary: WritableStore<Record<string, Record<string, string>>>;
export declare const locales: WritableStore<string[]>;
export declare function getCurrentLocale(): string;
export {};
Loading

0 comments on commit b66ae96

Please sign in to comment.