diff --git a/src/core/i18n/index.ts b/src/core/i18n/index.ts index 2e97e3c..a74e316 100644 --- a/src/core/i18n/index.ts +++ b/src/core/i18n/index.ts @@ -1,3 +1,4 @@ +import { FluxDispatcher } from "@lib/metro/common"; import { findByName } from "@lib/metro/filters"; import { PrimitiveType } from "intl-messageformat"; @@ -7,12 +8,51 @@ const IntlMessageFormat = findByName("MessageFormat") as typeof import("intl-mes type I18nKey = keyof typeof langDefault; +let currentLocale: string | null; +const _loadedLocale = new Set(); +const _loadedStrings = {} as Record; + export const Strings = new Proxy({}, { get: (_t, prop: keyof typeof langDefault) => { + if (currentLocale && _loadedStrings[currentLocale]?.[prop]) { + return _loadedStrings[currentLocale]?.[prop]; + } return langDefault[prop]; } }) as Record; +export function initFetchI18nStrings() { + const cb = ({ locale }: { locale: string; }) => { + const languageMap = { + "es-ES": "es", + "es-419": "es_419", + "zh-TW": "zh-Hant", + "zh-CN": "zh-Hans", + "pt-PT": "pt", + "sv-SE": "sv" + } as Record; + + const resolvedLocale = languageMap[locale] ?? locale; + if (resolvedLocale.startsWith("en-")) { + currentLocale = null; + return; + } + + if (!_loadedLocale.has(resolvedLocale)) { + _loadedLocale.add(resolvedLocale); + + fetch(`https://raw.githubusercontent.com/pyoncord/i18n/main/resources/${resolvedLocale}/bunny.json`) + .then(r => r.json()) + .then(strings => _loadedStrings[resolvedLocale] = strings) + .then(() => currentLocale = resolvedLocale) + .catch(e => console.error(`An error occured while fetching strings for ${resolvedLocale}: ${e}`)); + } + }; + + FluxDispatcher.subscribe("I18N_LOAD_SUCCESS", cb); + return () => FluxDispatcher.unsubscribe("I18N_LOAD_SUCCESS", cb); +} + type FormatStringRet = T extends PrimitiveType ? string : string | T | (string | T)[]; export function formatString(key: I18nKey, val: Record): FormatStringRet { diff --git a/src/index.ts b/src/index.ts index cd2a142..addb35e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ import initFixes from "@core/fixes"; +import { initFetchI18nStrings } from "@core/i18n"; import { initCorePlugins } from "@core/plugins"; import initSettings from "@core/ui/settings"; import { _patchAssets } from "@lib/api/assets"; @@ -31,6 +32,7 @@ export default async () => { _patchAssets(), _patchCommands(), _patchChatBackground(), + initFetchI18nStrings(), initSettings(), initFixes(), initSafeMode(), diff --git a/src/lib/metro/types.ts b/src/lib/metro/types.ts index acf6ef9..adf1c65 100644 --- a/src/lib/metro/types.ts +++ b/src/lib/metro/types.ts @@ -12,8 +12,8 @@ export interface Dispatcher { isDispatching(): boolean; register(name: string, actionHandler: Record void>, storeDidChange: (e: any) => boolean): string; setInterceptor(interceptor?: (payload: any) => void | boolean): void; - subscribe(actionType: string, callback: (payload: any) => void): () => void; - unsubscribe(actionType: string, callback: (payload: any) => void): () => void; + subscribe(actionType: string, callback: (payload: any) => void): void; + unsubscribe(actionType: string, callback: (payload: any) => void): void; wait(cb: () => void): void; }