perf: use global caches so we only have one subscription

This commit is contained in:
Lewis Crichton 2023-12-22 16:29:20 +00:00
parent 88375f61c1
commit d977ddc7f4
No known key found for this signature in database

View file

@ -16,6 +16,11 @@ import { Logger } from "./Logger";
// same color as pontoon's logo // same color as pontoon's logo
const logger = new Logger("Translations", "#7bc876"); const logger = new Logger("Translations", "#7bc876");
let subscribed = false;
let bundleCache: Record<string, FluentBundle[]> = {};
let messageCache: Record<string, Record<string, FluentBundle>> = {};
/** /**
* Gets a function that translates strings. * Gets a function that translates strings.
* @param context The context to use for translation (e.g., `vencord`). * @param context The context to use for translation (e.g., `vencord`).
@ -24,20 +29,22 @@ const logger = new Logger("Translations", "#7bc876");
export function getTranslations(context: string) { export function getTranslations(context: string) {
if (!translations[context]) throw new Error(`No translations for ${context}`); if (!translations[context]) throw new Error(`No translations for ${context}`);
let localeCache: FluentBundle[] = []; if (!subscribed) {
let messageCache: Record<string, FluentBundle> = {}; let lastLocale = i18n.getLocale();
let lastLocale = i18n.getLocale(); FluxDispatcher.subscribe("USER_SETTINGS_PROTO_UPDATE", ({ settings }) => {
FluxDispatcher.subscribe("USER_SETTINGS_PROTO_UPDATE", ({ settings }) => { if (settings.proto.localization.locale.value !== lastLocale) {
if (settings.proto.localization.locale.value !== lastLocale) { // locale was updated, clear our caches
// locale was updated, clear our caches
lastLocale = settings.proto.localization.locale.value; lastLocale = settings.proto.localization.locale.value;
localeCache = []; bundleCache = {};
messageCache = {}; messageCache = {};
} }
}); });
subscribed = true;
}
/** /**
* Translates a key. Soft-fails and returns a fallback error string if the key could not be loaded. * Translates a key. Soft-fails and returns a fallback error string if the key could not be loaded.
@ -46,12 +53,16 @@ export function getTranslations(context: string) {
* @returns A translated string. * @returns A translated string.
*/ */
return function t(key: string, variables?: Record<string, FluentVariable>): string { return function t(key: string, variables?: Record<string, FluentVariable>): string {
const msgCache = messageCache[context] ??= {};
// adding the caching here speeds up retrieving translations for this key later // adding the caching here speeds up retrieving translations for this key later
if (messageCache[key]) { if (msgCache[key]) {
const bundle = messageCache[key]; const bundle = msgCache[key];
return bundle.formatPattern(bundle.getMessage(key)!.value!, variables); return bundle.formatPattern(bundle.getMessage(key)!.value!, variables);
} }
const localeCache = bundleCache[context] ??= [];
// we've never loaded this context's translations // we've never loaded this context's translations
if (localeCache.length === 0) { if (localeCache.length === 0) {
const availableLocales = Object.keys(translations[context]); const availableLocales = Object.keys(translations[context]);
@ -85,7 +96,7 @@ export function getTranslations(context: string) {
const message = bundle.getMessage(key); const message = bundle.getMessage(key);
if (message?.value) { if (message?.value) {
messageCache[key] = bundle; msgCache[key] = bundle;
return bundle.formatPattern(message.value, variables); return bundle.formatPattern(message.value, variables);
} }