@grammyjs/i18n
Version:
Internationalization plugin for grammY based on Fluent.
163 lines (162 loc) • 6.64 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Fluent = void 0;
const dntShim = __importStar(require("../_dnt.shims.js"));
const warning_js_1 = require("./warning.js");
const deps_js_1 = require("./deps.js");
class Fluent {
constructor(options) {
Object.defineProperty(this, "bundles", {
enumerable: true,
configurable: true,
writable: true,
value: new Set()
});
Object.defineProperty(this, "defaultBundle", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "handleWarning", {
enumerable: true,
configurable: true,
writable: true,
value: (0, warning_js_1.defaultWarningHandler)()
});
if (options?.warningHandler) {
this.handleWarning = options.warningHandler;
}
}
async addTranslation(options) {
const source = "source" in options && "filePath" in options
? undefined
: "source" in options && options.source
? options.source
: "filePath" in options && options.filePath
? await dntShim.Deno.readTextFile(options.filePath)
: undefined;
if (source === undefined) {
throw new Error("Provide either filePath or string source as translation source.");
}
this.addBundle(options, source);
}
addTranslationSync(options) {
const source = "source" in options && "filePath" in options
? undefined
: "source" in options && options.source
? options.source
: "filePath" in options && options.filePath
? dntShim.Deno.readTextFileSync(options.filePath)
: undefined;
if (source === undefined) {
throw new Error("Provide either filePath or string source as translation source.");
}
this.addBundle(options, source);
}
translate(localeOrLocales, path, context) {
const locales = Array.isArray(localeOrLocales)
? localeOrLocales
: [localeOrLocales];
const [messageId, attributeName] = path.split(".", 2);
const bundles = this.matchBundles(locales);
const warning = { locales, path, matchedBundles: bundles, context };
for (const bundle of bundles) {
const message = bundle.getMessage(messageId);
if (message === undefined) {
this.handleWarning({
...warning,
type: warning_js_1.TranslateWarnings.MISSING_MESSAGE,
bundle,
messageId,
});
continue;
}
let pattern = message.value ?? "";
if (attributeName) {
if (message.attributes?.[attributeName]) {
pattern = message.attributes?.[attributeName];
}
else {
this.handleWarning({
...warning,
type: warning_js_1.TranslateWarnings.MISSING_ATTRIBUTE,
attributeName,
bundle,
messageId,
});
continue;
}
}
return bundle.formatPattern(pattern, context);
}
// None of the bundles worked out for the given message.
this.handleWarning({
...warning,
type: warning_js_1.TranslateWarnings.MISSING_TRANSLATION,
});
return `{${path}}`;
}
/**
* Returns translation function bound to the specified locale(s).
*/
withLocale(localeOrLocales) {
return this.translate.bind(this, localeOrLocales);
}
createBundle(locales, source, bundleOptions) {
const bundle = new deps_js_1.FluentBundle(locales, bundleOptions);
const resource = new deps_js_1.FluentResource(source);
const errors = bundle.addResource(resource, { allowOverrides: true });
if (errors.length === 0)
return bundle;
for (const error of errors)
console.error(error);
throw new Error("Failed to add resource to the bundle, see the errors above.");
}
addBundle(options, source) {
const bundle = this.createBundle(options.locales, source, options.bundleOptions);
this.bundles.add(bundle);
if (!this.defaultBundle || options.isDefault) {
this.defaultBundle = bundle;
}
}
matchBundles(locales) {
const bundles = Array.from(this.bundles);
// Building a list of all the registered locales
const availableLocales = bundles.reduce((locales, bundle) => [...locales, ...bundle.locales], []);
// Find the best match for the specified locale
const matchedLocales = (0, deps_js_1.negotiateLanguages)(locales, availableLocales);
// For matched locales, find the first bundle they're in.
const matchedBundles = matchedLocales.map((locale) => {
return bundles.find((bundle) => bundle.locales.includes(locale));
}).filter((bundle) => bundle !== undefined);
// Add the default bundle to the end, so it'll be used if other bundles fails.
if (this.defaultBundle)
matchedBundles.push(this.defaultBundle);
return new Set(matchedBundles);
}
}
exports.Fluent = Fluent;