Forráskód Böngészése

fix: cfg menu options not loading without en-US

Sv443 3 napja
szülő
commit
fd0b459e5f
5 módosított fájl, 27 hozzáadás és 18 törlés
  1. 1 0
      changelog.md
  2. 7 6
      contributing.md
  3. 7 2
      src/index.ts
  4. 6 6
      src/menu/menu_old.ts
  5. 6 4
      src/utils/translations.ts

+ 1 - 0
changelog.md

@@ -25,6 +25,7 @@
     - BREAKING: Renamed `createRipple()`'s `speed` prop values:
       - From `faster` to `fastest`
       - From `slower` to `slowest`
+    - BREAKING: `hasKey()` and `hasKeyFor()` now return a Promise, since they might need to load the given locale
     - `getCurrentMediaType()` now always returns `"video"` on YT instead of throwing an error
 
 </details> -->

+ 7 - 6
contributing.md

@@ -1100,7 +1100,7 @@ The usage and example blocks on each are written in TypeScript but can be used i
 > ### hasKey()
 > Signature:  
 > ```ts
-> unsafeWindow.BYTM.hasKey(key: string): boolean
+> unsafeWindow.BYTM.hasKey(key: string): Promise<boolean>
 > ```
 >   
 > Description:  
@@ -1112,8 +1112,8 @@ The usage and example blocks on each are written in TypeScript but can be used i
 > <details><summary><b>Example <i>(click to expand)</i></b></summary>
 > 
 > ```ts
-> unsafeWindow.BYTM.hasKey("lyrics_rate_limited"); // true
-> unsafeWindow.BYTM.hasKey("some_key_that_doesnt_exist"); // false
+> await unsafeWindow.BYTM.hasKey("lyrics_rate_limited"); // true
+> await unsafeWindow.BYTM.hasKey("some_key_that_doesnt_exist"); // false
 > ```
 > </details>
 
@@ -1122,11 +1122,12 @@ The usage and example blocks on each are written in TypeScript but can be used i
 > ### hasKeyFor()
 > Signature:  
 > ```ts
-> unsafeWindow.BYTM.hasKeyFor(locale: string, key: string): boolean
+> unsafeWindow.BYTM.hasKeyFor(locale: string, key: string): Promise<boolean>
 > ```
 >   
 > Description:  
 > Returns true if the specified translation key exists in the specified locale.  
+> If the locale isn't loaded yet, it will be loaded before resolving the promise.  
 >   
 > Arguments:  
 > - `locale` - The locale to check for the translation key in - refer to the keys of the object in [`assets/locales.json`](assets/locales.json).
@@ -1135,8 +1136,8 @@ The usage and example blocks on each are written in TypeScript but can be used i
 > <details><summary><b>Example <i>(click to expand)</i></b></summary>
 > 
 > ```ts
-> unsafeWindow.BYTM.hasKeyFor("en-GB", "lyrics_rate_limited"); // true
-> unsafeWindow.BYTM.hasKeyFor("en-GB", "some_key_that_doesnt_exist"); // false
+> await unsafeWindow.BYTM.hasKeyFor("en-GB", "lyrics_rate_limited"); // true
+> await unsafeWindow.BYTM.hasKeyFor("en-GB", "some_key_that_doesnt_exist"); // false
 > ```
 > </details>
 

+ 7 - 2
src/index.ts

@@ -115,8 +115,13 @@ async function init() {
 
     await initLyricsCache();
 
-    await initTranslations(features.locale ?? "en-US");
-    setLocale(features.locale ?? "en-US");
+    const initLoc = features.locale ?? "en-US";
+    const locPromises: Promise<void>[] = [];
+    locPromises.push(initTranslations(initLoc));
+    // since en-US always has the complete set of keys, it needs to always be loaded:
+    initLoc !== "en-US" && locPromises.push(initTranslations("en-US"));
+    await Promise.allSettled(locPromises);
+    setLocale(initLoc);
 
     try {
       initPlugins();

+ 6 - 6
src/menu/menu_old.ts

@@ -435,7 +435,7 @@ async function mountCfgMenu() {
             ftConfElem.title = `${featKey}${rel}${adv}${extraTxts.length > 0 ? `\n${extraTxts.join(" - ")}` : ""}`;
           }
 
-          if(!hasKeyFor("en-US", `feature_desc_${featKey}`)) {
+          if(!await hasKeyFor("en-US", `feature_desc_${featKey}`)) {
             error(`Missing en-US translation with key "feature_desc_${featKey}" for feature description, skipping this config menu feature...`);
             continue;
           }
@@ -463,7 +463,7 @@ async function mountCfgMenu() {
           // @ts-ignore
           const helpTextVal: string | undefined = hasHelpTextFunc && featInfo[featKey as keyof typeof featInfo]!.helpText();
 
-          if(hasKey(`feature_helptext_${featKey}`) || (helpTextVal && hasKey(helpTextVal))) {
+          if(await hasKey(`feature_helptext_${featKey}`) || (helpTextVal && await hasKey(helpTextVal))) {
             const helpElemImgHtml = await resourceAsString("icon-help");
             if(helpElemImgHtml) {
               helpElem = document.createElement("div");
@@ -703,7 +703,7 @@ async function mountCfgMenu() {
               customInputEl = document.createElement("button");
               customInputEl.classList.add("bytm-btn");
               customInputEl.tabIndex = 0;
-              customInputEl.textContent = hasKey(`feature_btn_${featKey}`) ? t(`feature_btn_${featKey}`) : t("trigger_btn_action");
+              customInputEl.textContent = await hasKey(`feature_btn_${featKey}`) ? t(`feature_btn_${featKey}`) : t("trigger_btn_action");
               customInputEl.ariaLabel = customInputEl.title = t(`feature_desc_${featKey}`);
 
               onInteraction(customInputEl, async () => {
@@ -715,15 +715,15 @@ async function mountCfgMenu() {
 
                 (customInputEl as HTMLButtonElement).disabled = true;
                 customInputEl!.classList.add("bytm-busy");
-                customInputEl!.textContent = hasKey(`feature_btn_${featKey}_running`) ? t(`feature_btn_${featKey}_running`) : t("trigger_btn_action_running");
+                customInputEl!.textContent = await hasKey(`feature_btn_${featKey}_running`) ? t(`feature_btn_${featKey}_running`) : t("trigger_btn_action_running");
 
                 if(res instanceof Promise)
                   await res;
 
-                const finalize = () => {
+                const finalize = async () => {
                   (customInputEl as HTMLButtonElement).disabled = false;
                   customInputEl!.classList.remove("bytm-busy");
-                  customInputEl!.textContent = hasKey(`feature_btn_${featKey}`) ? t(`feature_btn_${featKey}`) : t("trigger_btn_action");
+                  customInputEl!.textContent = await hasKey(`feature_btn_${featKey}`) ? t(`feature_btn_${featKey}`) : t("trigger_btn_action");
                 };
 
                 // artificial timeout ftw

+ 6 - 4
src/utils/translations.ts

@@ -84,12 +84,14 @@ export function getLocale() {
 }
 
 /** Returns whether the given translation key exists in the current locale */
-export function hasKey(key: TFuncKey) {
-  return hasKeyFor(getLocale(), key);
+export async function hasKey(key: TFuncKey) {
+  return await hasKeyFor(getLocale(), key);
 }
 
-/** Returns whether the given translation key exists in the given locale */
-export function hasKeyFor(locale: TrLocale, key: TFuncKey) {
+/** Returns whether the given translation key exists in the given locale - if it hasn't been initialized yet, initializes it first. */
+export async function hasKeyFor(locale: TrLocale, key: TFuncKey) {
+  if(!initializedLocales.has(locale))
+    await initTranslations(locale);
   return typeof tr.getTranslations(locale)?.[key] === "string";
 }