UNPKG

@grammyjs/i18n

Version:

Internationalization plugin for grammY based on Fluent.

163 lines (162 loc) 6.64 kB
"use strict"; 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;