UNPKG

alpinejs-i18n

Version:

Internationalization (i18n) support for Alpine.js

138 lines (118 loc) 3.12 kB
import { PluginCallback, type Alpine } from 'alpinejs'; const localeChange = new Event('alpine-i18n:locale-change'); const i18nReady = new Event('alpine-i18n:ready'); declare module 'alpinejs' { interface Magics<T> { $locale: $locale; $t: $t; } } declare global { interface Window { AlpineI18n: typeof AlpineI18n; } } type $t = (name: string, vars?: { [name: string]: string }) => string; type $locale = (locale?: string) => string | void; const AlpineI18n = { version: '2.5.3', /** * setter for the current locale */ set locale(name) { this.checkLocale(name); this.currentLocale = name; document.dispatchEvent(localeChange); }, /** * getter for the current locale */ get locale() { return this.currentLocale; }, currentLocale: '', /** * translations data * the first keys are the locale codes. */ messages: <any>{}, fallbackLocale: '', options: <any>{}, /** * Set up i18n's default locale and data. * @param locale the default locale * @param messages the translation data * @param options optional settings */ create( locale: string, messages: { [name: string]: any }, options: { debug: boolean }, ) { this.messages = messages; this.checkLocale(locale); this.locale = locale; this.options = options; }, /** * Check if a locale exists in the message list * If it don't throw an Error. Does nothing otherwise. * @param locale locale to check */ checkLocale(locale: string) { if (!Object.keys(this.messages).includes(locale)) { throw new Error( `Alpine I18n: The locale ${locale} does not exist.`, ); } }, /** * Get the localized version of a string * @param name the name of the message * @param vars optional variables to be passed to the string * @returns string */ t(name: string, vars?: { [name: string]: string }) { let message: string = ''; try { message = name .split('.') .reduce((o, i) => o[i], this.messages[this.locale]); } catch {} if (!message && this.fallbackLocale.length) { message = name .split('.') .reduce((o, i) => o[i], this.messages[this.fallbackLocale]); } else if (!message) { return this.options?.debug ? `???${name}` : name; } for (const key in vars) { if (message && message.replaceAll) { if (Object.prototype.hasOwnProperty.call(vars, key)) { //@ts-ignore const val: string = vars[key]; let regexp = new RegExp('{s*(' + key + ')s*}', 'g'); //@ts-ignore message = message.replaceAll(regexp, val); } } } return this.options?.debug ? `[${message}]` : message; }, }; const i18nPlugin: PluginCallback = function (Alpine: Alpine) { window.AlpineI18n = Alpine.reactive(AlpineI18n); document.dispatchEvent(i18nReady); Alpine.magic('locale', (el: HTMLElement) => { return (locale: string | undefined) => { if (!locale) return window.AlpineI18n.locale; window.AlpineI18n.locale = locale; }; }); Alpine.magic('t', (el: HTMLElement) => { return (name: string, vars?: { [name: string]: any }) => { return window.AlpineI18n.t(name, vars); }; }); }; export default i18nPlugin;