@gramio/i18n
Version:
i18n plugin for GramIO with type-safety
77 lines (73 loc) • 2.74 kB
JavaScript
import { Plugin } from 'gramio';
import fs from 'node:fs';
import path from 'node:path';
import { FluentBundle, FluentResource } from '@fluent/bundle';
function getFluentClient(options) {
const directory = options?.directory ?? "locales";
const bundles = /* @__PURE__ */ new Map();
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
if (!entry.isFile() || !entry.name.endsWith(".ftl")) continue;
const lang = entry.name.slice(0, -4);
const source = fs.readFileSync(path.resolve(directory, entry.name)).toString();
const bundle = new FluentBundle(lang);
const resource = new FluentResource(source);
bundle.addResource(resource);
bundles.set(lang, bundle);
}
const defaultLocale = options?.defaultLocale ?? bundles.keys().next().value;
if (!defaultLocale)
throw new Error("Please specify one or more translations");
let currentLanguage = defaultLocale;
return {
languages: {
bundles,
fallback: defaultLocale,
all: Array.from(bundles.keys()),
current: currentLanguage,
change: (language) => {
if (!bundles.has(language))
throw new Error(`No ${language} language found`);
currentLanguage = language;
}
},
t: (id, args) => {
const bundle = bundles.get(currentLanguage);
if (!bundle) throw new Error(`No ${currentLanguage} language found`);
const message = bundle.getMessage(id);
if (!message?.value) throw new Error(`No message found for ${id}`);
return bundle.formatPattern(message.value, args);
}
};
}
function i18n(options) {
const client = options && "t" in options ? options : getFluentClient(options);
return new Plugin("@gramio/i18n").derive(() => {
let language = client.languages.current;
return {
/** Object with localization utils and settings */
i18n: {
/** All languages */
locales: client.languages.all,
/** Current user locale */
locale: language,
/** Set locale to current user */
setLocale: (lang, strict = false) => {
if (!client.languages.all.includes(lang)) {
if (strict) throw new Error(`No ${language} language found`);
language = client.languages.fallback;
return;
}
language = lang;
}
},
t: (id, args) => {
const bundle = client.languages.bundles.get(language);
if (!bundle) throw new Error(`No ${language} language found`);
const message = bundle.getMessage(id);
if (!message?.value) throw new Error(`No message found for ${id}`);
return bundle.formatPattern(message.value, args);
}
};
});
}
export { getFluentClient, i18n };