mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-08-18 03:57:06 +08:00
v0.3.8
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
import { computed, ref } from "vue";
|
||||
import {
|
||||
DEFAULT_LOCALE,
|
||||
LOCALE_OPTIONS,
|
||||
LOCALE_STORAGE_KEY,
|
||||
LOCALE_STORAGE_SOURCE_KEY,
|
||||
SOURCE_LOCALE,
|
||||
SUPPORTED_LOCALES,
|
||||
} from "@/i18n/config";
|
||||
import zhCNMessages from "@/i18n/locales/zh-CN.json";
|
||||
import enUSMessages from "@/i18n/locales/en-US.json";
|
||||
import jaJPMessages from "@/i18n/locales/ja-JP.json";
|
||||
|
||||
const localeMessages = {
|
||||
"zh-CN": zhCNMessages,
|
||||
"en-US": enUSMessages,
|
||||
"ja-JP": jaJPMessages,
|
||||
};
|
||||
|
||||
const languageLocaleMap = {
|
||||
zh: "zh-CN",
|
||||
en: "en-US",
|
||||
ja: "ja-JP",
|
||||
};
|
||||
|
||||
function isSupportedLocale(locale) {
|
||||
return SUPPORTED_LOCALES.includes(locale);
|
||||
}
|
||||
|
||||
function matchSupportedLocale(locale) {
|
||||
const normalized = String(locale || "").trim().replace(/_/g, "-");
|
||||
if (!normalized) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const lowered = normalized.toLowerCase();
|
||||
const exactMatch = SUPPORTED_LOCALES.find((supportedLocale) => supportedLocale.toLowerCase() === lowered);
|
||||
if (exactMatch) {
|
||||
return exactMatch;
|
||||
}
|
||||
|
||||
const primaryLanguage = lowered.split("-")[0];
|
||||
return languageLocaleMap[primaryLanguage] || "";
|
||||
}
|
||||
|
||||
function getSystemLocaleCandidates() {
|
||||
const candidates = [];
|
||||
|
||||
if (typeof navigator !== "undefined") {
|
||||
if (Array.isArray(navigator.languages)) {
|
||||
candidates.push(...navigator.languages);
|
||||
}
|
||||
candidates.push(navigator.language);
|
||||
}
|
||||
|
||||
if (typeof Intl !== "undefined" && typeof Intl.DateTimeFormat === "function") {
|
||||
candidates.push(Intl.DateTimeFormat().resolvedOptions()?.locale);
|
||||
}
|
||||
|
||||
return candidates;
|
||||
}
|
||||
|
||||
function resolveSystemLocale() {
|
||||
for (const candidate of getSystemLocaleCandidates()) {
|
||||
const matchedLocale = matchSupportedLocale(candidate);
|
||||
if (matchedLocale) {
|
||||
return matchedLocale;
|
||||
}
|
||||
}
|
||||
|
||||
return DEFAULT_LOCALE;
|
||||
}
|
||||
|
||||
function resolveInitialLocale() {
|
||||
if (typeof window === "undefined" || typeof window.localStorage === "undefined") {
|
||||
return resolveSystemLocale();
|
||||
}
|
||||
|
||||
const storedLocale = window.localStorage.getItem(LOCALE_STORAGE_KEY);
|
||||
const storedSource = window.localStorage.getItem(LOCALE_STORAGE_SOURCE_KEY);
|
||||
if (storedSource === "manual") {
|
||||
return matchSupportedLocale(storedLocale) || resolveSystemLocale();
|
||||
}
|
||||
|
||||
window.localStorage.removeItem(LOCALE_STORAGE_KEY);
|
||||
window.localStorage.removeItem(LOCALE_STORAGE_SOURCE_KEY);
|
||||
return resolveSystemLocale();
|
||||
}
|
||||
|
||||
function applyLocaleToDocument(locale) {
|
||||
if (typeof document !== "undefined") {
|
||||
document.documentElement.lang = locale;
|
||||
}
|
||||
}
|
||||
|
||||
function persistManualLocale(locale) {
|
||||
if (typeof window === "undefined" || typeof window.localStorage === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
window.localStorage.setItem(LOCALE_STORAGE_KEY, locale);
|
||||
window.localStorage.setItem(LOCALE_STORAGE_SOURCE_KEY, "manual");
|
||||
}
|
||||
|
||||
function resolveMessage(id, fallback) {
|
||||
const activeMessages = localeMessages[currentLocale.value] || {};
|
||||
const sourceMessages = localeMessages[SOURCE_LOCALE] || {};
|
||||
return activeMessages[id] || sourceMessages[id] || fallback || "";
|
||||
}
|
||||
|
||||
function interpolateMessage(template, args = []) {
|
||||
return template.replace(/\{(\d+)\}/g, (_match, index) => {
|
||||
const value = args[Number(index)];
|
||||
return value == null ? "" : String(value);
|
||||
});
|
||||
}
|
||||
|
||||
class LocalizedText extends String {
|
||||
constructor(id, fallback, args = null) {
|
||||
super(fallback);
|
||||
this.id = id;
|
||||
this.fallback = fallback;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
toString() {
|
||||
const text = resolveMessage(this.id, this.fallback);
|
||||
return Array.isArray(this.args) ? interpolateMessage(text, this.args) : text;
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
[Symbol.toPrimitive]() {
|
||||
return this.toString();
|
||||
}
|
||||
}
|
||||
|
||||
const currentLocale = ref(resolveInitialLocale());
|
||||
applyLocaleToDocument(currentLocale.value);
|
||||
|
||||
const localizedCache = new Map();
|
||||
|
||||
export function getLocale() {
|
||||
return currentLocale.value;
|
||||
}
|
||||
|
||||
export function setLocale(locale) {
|
||||
const nextLocale = matchSupportedLocale(locale) || DEFAULT_LOCALE;
|
||||
currentLocale.value = nextLocale;
|
||||
persistManualLocale(nextLocale);
|
||||
applyLocaleToDocument(nextLocale);
|
||||
return nextLocale;
|
||||
}
|
||||
|
||||
export function useLocale() {
|
||||
return {
|
||||
locale: currentLocale,
|
||||
localeOptions: LOCALE_OPTIONS,
|
||||
currentLocale: computed(() => currentLocale.value),
|
||||
setLocale,
|
||||
};
|
||||
}
|
||||
|
||||
export function localized(id, fallback) {
|
||||
const cacheKey = `${id}:${fallback}`;
|
||||
if (!localizedCache.has(cacheKey)) {
|
||||
localizedCache.set(cacheKey, new LocalizedText(id, fallback));
|
||||
}
|
||||
return localizedCache.get(cacheKey);
|
||||
}
|
||||
|
||||
export function localizedTemplate(id, fallback, args = []) {
|
||||
return new LocalizedText(id, fallback, args);
|
||||
}
|
||||
|
||||
export function installI18nRuntime(app) {
|
||||
app.config.globalProperties.$ls = localized;
|
||||
app.config.globalProperties.$lt = localizedTemplate;
|
||||
}
|
||||
Reference in New Issue
Block a user