@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
207 lines (206 loc) • 5.82 kB
JavaScript
import { DEFAULT_LOCALIZATION_CONFIG as h } from "./defaults.js";
import { DEFAULT_LOCALE_MESSAGES as N } from "./defaults.js";
import { LOCALE_INFO as s } from "../locales/index.js";
var g = Object.defineProperty, d = (a, e, t) => e in a ? g(a, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[e] = t, c = (a, e, t) => d(a, typeof e != "symbol" ? e + "" : e, t);
class m {
constructor(e) {
c(this, "config"), c(this, "currentLocale"), c(this, "loadedMessages", /* @__PURE__ */ new Map()), c(this, "listeners", /* @__PURE__ */ new Set()), this.config = { ...h, ...e }, this.currentLocale = this.config.defaultLocale, this.loadedMessages.set(this.currentLocale, {
...s[this.currentLocale],
...this.config.messages
});
}
/**
* Get current locale
*/
getCurrentLocale() {
return this.currentLocale;
}
/**
* Get current locale metadata
*/
getCurrentLocaleMetadata() {
return s[this.currentLocale];
}
/**
* Set current locale
*/
async setLocale(e) {
this.config.supportedLocales.includes(e) || (console.warn(`Locale ${e} is not supported. Falling back to ${this.config.fallbackLocale}`), e = this.config.fallbackLocale), this.currentLocale = e, this.loadedMessages.has(e) || await this.loadLocaleMessages(e), this.notifyListeners();
}
/**
* Get translation for a key
*/
t(e, t) {
const r = this.getCurrentMessages(), o = this.getNestedValue(r, e);
return typeof o != "string" ? (console.warn(`Translation key "${e}" not found for locale "${this.currentLocale}"`), e) : this.interpolate(o, t);
}
/**
* Get plural translation
*/
plural(e, t) {
const { count: r } = t, i = s[this.currentLocale].pluralRules.select(r);
let n;
if (r === 0 && t.zero)
return this.interpolate(t.zero, { count: r });
switch (i) {
case "one":
n = t.one || t.other;
break;
case "two":
n = t.two || t.other;
break;
case "few":
n = t.few || t.other;
break;
case "many":
n = t.many || t.other;
break;
default:
n = t.other;
}
return this.interpolate(n, { count: r });
}
/**
* Format date according to current locale
*/
formatDate(e, t) {
return s[this.currentLocale], new Intl.DateTimeFormat(this.currentLocale, {
...t,
...t || {}
}).format(e);
}
/**
* Format time according to current locale
*/
formatTime(e, t) {
return new Intl.DateTimeFormat(this.currentLocale, {
timeStyle: "short",
...t
}).format(e);
}
/**
* Format number according to current locale
*/
formatNumber(e, t) {
const r = s[this.currentLocale];
return new Intl.NumberFormat(this.currentLocale, {
...r.numberFormat,
...t
}).format(e);
}
/**
* Format currency according to current locale
*/
formatCurrency(e, t, r) {
return new Intl.NumberFormat(this.currentLocale, {
style: "currency",
currency: t,
...r
}).format(e);
}
/**
* Format relative time (e.g., "2 hours ago")
*/
formatRelativeTime(e, t) {
const r = new Intl.RelativeTimeFormat(this.currentLocale, {
numeric: "auto",
...t
}), o = /* @__PURE__ */ new Date(), i = e.getTime() - o.getTime(), n = Math.round(i / 1e3), l = Math.round(n / 60), u = Math.round(l / 60), f = Math.round(u / 24);
return Math.abs(n) < 60 ? r.format(n, "second") : Math.abs(l) < 60 ? r.format(l, "minute") : Math.abs(u) < 24 ? r.format(u, "hour") : r.format(f, "day");
}
/**
* Get available locales
*/
getAvailableLocales() {
return this.config.supportedLocales.map((e) => ({
code: e,
name: s[e].name,
nativeName: s[e].nativeName
}));
}
/**
* Subscribe to locale changes
*/
subscribe(e) {
return this.listeners.add(e), () => {
this.listeners.delete(e);
};
}
/**
* Update localization configuration
*/
updateConfig(e) {
this.config = { ...this.config, ...e }, e.messages && this.loadedMessages.set(this.currentLocale, {
...s[this.currentLocale],
...this.config.messages
});
}
// Private methods
getCurrentMessages() {
return this.loadedMessages.get(this.currentLocale) || s[this.currentLocale];
}
getNestedValue(e, t) {
return t.split(".").reduce((r, o) => r?.[o], e);
}
interpolate(e, t) {
return t ? e.replace(/\{\{(\w+)\}\}/g, (r, o) => {
const i = t[o];
return i === void 0 ? r : i instanceof Date ? this.formatDate(i) : String(i);
}) : e;
}
async loadLocaleMessages(e) {
try {
const t = s[e] || s[this.config.fallbackLocale];
this.loadedMessages.set(e, {
...t,
...this.config.messages
});
} catch (t) {
console.error(`Failed to load messages for locale ${e}:`, t);
const r = s[this.config.fallbackLocale];
this.loadedMessages.set(e, r);
}
}
notifyListeners() {
this.listeners.forEach((e) => e(this.currentLocale));
}
}
function w(a) {
return new m(a);
}
function p(a) {
if (typeof navigator > "u") return "en";
const e = [
navigator.language,
...navigator.languages || []
];
for (const t of e) {
const r = t.split("-")[0];
if (a.includes(r))
return r;
}
return "en";
}
function L(a) {
return s[a]?.direction || "ltr";
}
function y(a) {
return L(a) === "rtl";
}
function F(a, e) {
return {
t: (t, r) => a.t(`${e}.${t}`, r),
plural: (t, r) => a.plural(`${e}.${t}`, r)
};
}
export {
N as DEFAULT_LOCALE_MESSAGES,
h as DEFAULT_LOCALIZATION_CONFIG,
m as LocalizationManager,
w as createLocalizationManager,
F as createTranslationNamespace,
p as detectBrowserLocale,
L as getLocaleDirection,
y as isRTL
};
//# sourceMappingURL=localization.js.map