mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-06 14:46:04 +02:00
Translate bio button (#1432)
* Translation button finished * Fix bug in theme * revert cause some stuff broke * "Translated by Google" text * Translate that too * I am very stupid sorry * Add API Key * Make toggle work, oops * Fix merge issues * Fixed as requested * Change translation icon * Return settings back (oops) * Beep * Boop * Delete import again as the icon has been replaced with a better one * Change text
This commit is contained in:
@@ -249,6 +249,11 @@
|
|||||||
style="margin-left: 5px"
|
style="margin-left: 5px"
|
||||||
@click="showBioDialog"></el-button>
|
@click="showBioDialog"></el-button>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="userDialog.id !== currentUser.id" style="float: right">
|
||||||
|
<el-button type="text" size="small" style="margin-left: 5px" @click="translateBio"
|
||||||
|
><i class="ri-translate-2"></i
|
||||||
|
></el-button>
|
||||||
|
</div>
|
||||||
<div style="margin-top: 5px">
|
<div style="margin-top: 5px">
|
||||||
<el-tooltip v-for="(link, index) in userDialog.ref.bioLinks" :key="index">
|
<el-tooltip v-for="(link, index) in userDialog.ref.bioLinks" :key="index">
|
||||||
<template #content>
|
<template #content>
|
||||||
@@ -1305,8 +1310,10 @@
|
|||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const advancedSettingsStore = useAdvancedSettingsStore();
|
||||||
|
|
||||||
const { hideUserNotes, hideUserMemos } = storeToRefs(useAppearanceSettingsStore());
|
const { hideUserNotes, hideUserMemos } = storeToRefs(useAppearanceSettingsStore());
|
||||||
const { avatarRemoteDatabase } = storeToRefs(useAdvancedSettingsStore());
|
const { bioLanguage, avatarRemoteDatabase } = storeToRefs(useAdvancedSettingsStore());
|
||||||
const { userDialog, languageDialog, currentUser, isLocalUserVrcPlusSupporter } = storeToRefs(useUserStore());
|
const { userDialog, languageDialog, currentUser, isLocalUserVrcPlusSupporter } = storeToRefs(useUserStore());
|
||||||
const {
|
const {
|
||||||
cachedUsers,
|
cachedUsers,
|
||||||
@@ -2270,6 +2277,52 @@
|
|||||||
D.visible = true;
|
D.visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bioCache = ref({
|
||||||
|
userID: null,
|
||||||
|
original: null,
|
||||||
|
translated: null,
|
||||||
|
showingTranslated: false
|
||||||
|
});
|
||||||
|
async function translateBio() {
|
||||||
|
const bio = userDialog.value.ref.bio;
|
||||||
|
if (!bio || bio === '-' || !advancedSettingsStore.translationApi) return;
|
||||||
|
|
||||||
|
const targetLang = bioLanguage.value;
|
||||||
|
|
||||||
|
if (bioCache.value.userID !== userDialog.value.id) {
|
||||||
|
bioCache.value.userID = userDialog.value.id;
|
||||||
|
bioCache.value.original = null;
|
||||||
|
bioCache.value.translated = null;
|
||||||
|
bioCache.value.showingTranslated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bioCache.value.original) bioCache.value.original = bio;
|
||||||
|
|
||||||
|
if (bioCache.value.showingTranslated) {
|
||||||
|
userDialog.value.ref.bio = bioCache.value.original;
|
||||||
|
bioCache.value.showingTranslated = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bioCache.value.translated) {
|
||||||
|
userDialog.value.ref.bio = bioCache.value.translated;
|
||||||
|
bioCache.value.showingTranslated = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const translated = await advancedSettingsStore.translateText(bio + '\n\nTranslated by Google', targetLang);
|
||||||
|
|
||||||
|
if (!translated) throw new Error('No translation returned');
|
||||||
|
|
||||||
|
bioCache.value.translated = translated;
|
||||||
|
bioCache.value.showingTranslated = true;
|
||||||
|
userDialog.value.ref.bio = translated;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Translation failed:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function showPreviousInstancesUserDialog(userRef) {
|
function showPreviousInstancesUserDialog(userRef) {
|
||||||
const D = previousInstancesUserDialog.value;
|
const D = previousInstancesUserDialog.value;
|
||||||
D.userRef = userRef;
|
D.userRef = userRef;
|
||||||
|
|||||||
@@ -409,6 +409,7 @@
|
|||||||
"appearance": {
|
"appearance": {
|
||||||
"header": "Appearance",
|
"header": "Appearance",
|
||||||
"language": "Language",
|
"language": "Language",
|
||||||
|
"bio_language": "Target Language",
|
||||||
"theme_mode": "Theme",
|
"theme_mode": "Theme",
|
||||||
"theme_mode_system": "System",
|
"theme_mode_system": "System",
|
||||||
"theme_mode_light": "Light",
|
"theme_mode_light": "Light",
|
||||||
@@ -638,6 +639,12 @@
|
|||||||
"youtube_api_key": "YouTube API Key",
|
"youtube_api_key": "YouTube API Key",
|
||||||
"enable_tooltip": "Fetches video titles for use with gameLog and duration for overlay progress bar"
|
"enable_tooltip": "Fetches video titles for use with gameLog and duration for overlay progress bar"
|
||||||
},
|
},
|
||||||
|
"translation_api": {
|
||||||
|
"header": "Translation API",
|
||||||
|
"enable": "Enable",
|
||||||
|
"translation_api_key": "Translation API Key",
|
||||||
|
"enable_tooltip": "Translates user bios using a button on the bottom right"
|
||||||
|
},
|
||||||
"video_progress_pie": {
|
"video_progress_pie": {
|
||||||
"header": "Progress pie overlay for videos",
|
"header": "Progress pie overlay for videos",
|
||||||
"enable": "Enable",
|
"enable": "Enable",
|
||||||
@@ -1297,6 +1304,13 @@
|
|||||||
"guide": "Guide",
|
"guide": "Guide",
|
||||||
"save": "Save"
|
"save": "Save"
|
||||||
},
|
},
|
||||||
|
"translation_api": {
|
||||||
|
"header": "Translation API",
|
||||||
|
"description": "Enter your Translation API Key (optional)",
|
||||||
|
"placeholder": "Translation API Key",
|
||||||
|
"guide": "Guide (skip the restrict usage part)",
|
||||||
|
"save": "Save"
|
||||||
|
},
|
||||||
"set_world_tags": {
|
"set_world_tags": {
|
||||||
"header": "Set World Tags",
|
"header": "Set World Tags",
|
||||||
"avatar_scaling_disabled": "Disable avatar scaling",
|
"avatar_scaling_disabled": "Disable avatar scaling",
|
||||||
|
|||||||
@@ -18,13 +18,14 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
const vrcxStore = useVrcxStore();
|
const vrcxStore = useVrcxStore();
|
||||||
const VRCXUpdaterStore = useVRCXUpdaterStore();
|
const VRCXUpdaterStore = useVRCXUpdaterStore();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { availableLocales, t } = useI18n();
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
folderSelectorDialogVisible: false
|
folderSelectorDialogVisible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const enablePrimaryPassword = ref(false);
|
const enablePrimaryPassword = ref(false);
|
||||||
|
const bioLanguage = ref('en');
|
||||||
const relaunchVRChatAfterCrash = ref(false);
|
const relaunchVRChatAfterCrash = ref(false);
|
||||||
const vrcQuitFix = ref(true);
|
const vrcQuitFix = ref(true);
|
||||||
const autoSweepVRChatCache = ref(false);
|
const autoSweepVRChatCache = ref(false);
|
||||||
@@ -40,7 +41,9 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
const screenshotHelperModifyFilename = ref(false);
|
const screenshotHelperModifyFilename = ref(false);
|
||||||
const screenshotHelperCopyToClipboard = ref(false);
|
const screenshotHelperCopyToClipboard = ref(false);
|
||||||
const youTubeApi = ref(false);
|
const youTubeApi = ref(false);
|
||||||
|
const translationApi = ref(false);
|
||||||
const youTubeApiKey = ref('');
|
const youTubeApiKey = ref('');
|
||||||
|
const translationApiKey = ref('');
|
||||||
const progressPie = ref(false);
|
const progressPie = ref(false);
|
||||||
const progressPieFilter = ref(true);
|
const progressPieFilter = ref(true);
|
||||||
const showConfirmationOnSwitchAvatar = ref(false);
|
const showConfirmationOnSwitchAvatar = ref(false);
|
||||||
@@ -68,6 +71,7 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
async function initAdvancedSettings() {
|
async function initAdvancedSettings() {
|
||||||
const [
|
const [
|
||||||
enablePrimaryPasswordConfig,
|
enablePrimaryPasswordConfig,
|
||||||
|
bioLanguageConfig,
|
||||||
relaunchVRChatAfterCrashConfig,
|
relaunchVRChatAfterCrashConfig,
|
||||||
vrcQuitFixConfig,
|
vrcQuitFixConfig,
|
||||||
autoSweepVRChatCacheConfig,
|
autoSweepVRChatCacheConfig,
|
||||||
@@ -83,7 +87,9 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
screenshotHelperModifyFilenameConfig,
|
screenshotHelperModifyFilenameConfig,
|
||||||
screenshotHelperCopyToClipboardConfig,
|
screenshotHelperCopyToClipboardConfig,
|
||||||
youTubeApiConfig,
|
youTubeApiConfig,
|
||||||
|
translationApiConfig,
|
||||||
youTubeApiKeyConfig,
|
youTubeApiKeyConfig,
|
||||||
|
translationApiKeyConfig,
|
||||||
progressPieConfig,
|
progressPieConfig,
|
||||||
progressPieFilterConfig,
|
progressPieFilterConfig,
|
||||||
showConfirmationOnSwitchAvatarConfig,
|
showConfirmationOnSwitchAvatarConfig,
|
||||||
@@ -97,6 +103,7 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
sentryErrorReportingConfig
|
sentryErrorReportingConfig
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
configRepository.getBool('enablePrimaryPassword', false),
|
configRepository.getBool('enablePrimaryPassword', false),
|
||||||
|
configRepository.getString('VRCX_bioLanguage'),
|
||||||
configRepository.getBool('VRCX_relaunchVRChatAfterCrash', false),
|
configRepository.getBool('VRCX_relaunchVRChatAfterCrash', false),
|
||||||
configRepository.getBool('VRCX_vrcQuitFix', true),
|
configRepository.getBool('VRCX_vrcQuitFix', true),
|
||||||
configRepository.getBool('VRCX_autoSweepVRChatCache', false),
|
configRepository.getBool('VRCX_autoSweepVRChatCache', false),
|
||||||
@@ -121,7 +128,9 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
false
|
false
|
||||||
),
|
),
|
||||||
configRepository.getBool('VRCX_youtubeAPI', false),
|
configRepository.getBool('VRCX_youtubeAPI', false),
|
||||||
|
configRepository.getBool('VRCX_translationAPI', false),
|
||||||
configRepository.getString('VRCX_youtubeAPIKey', ''),
|
configRepository.getString('VRCX_youtubeAPIKey', ''),
|
||||||
|
configRepository.getString('VRCX_translationAPIKey', ''),
|
||||||
configRepository.getBool('VRCX_progressPie', false),
|
configRepository.getBool('VRCX_progressPie', false),
|
||||||
configRepository.getBool('VRCX_progressPieFilter', true),
|
configRepository.getBool('VRCX_progressPieFilter', true),
|
||||||
configRepository.getBool(
|
configRepository.getBool(
|
||||||
@@ -138,6 +147,15 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
configRepository.getString('VRCX_SentryEnabled', '')
|
configRepository.getString('VRCX_SentryEnabled', '')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!bioLanguageConfig ||
|
||||||
|
!availableLocales.includes(bioLanguageConfig)
|
||||||
|
) {
|
||||||
|
bioLanguage.value = 'en';
|
||||||
|
} else {
|
||||||
|
bioLanguage.value = bioLanguageConfig;
|
||||||
|
}
|
||||||
|
|
||||||
enablePrimaryPassword.value = enablePrimaryPasswordConfig;
|
enablePrimaryPassword.value = enablePrimaryPasswordConfig;
|
||||||
relaunchVRChatAfterCrash.value = relaunchVRChatAfterCrashConfig;
|
relaunchVRChatAfterCrash.value = relaunchVRChatAfterCrashConfig;
|
||||||
vrcQuitFix.value = vrcQuitFixConfig;
|
vrcQuitFix.value = vrcQuitFixConfig;
|
||||||
@@ -157,7 +175,9 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
screenshotHelperCopyToClipboard.value =
|
screenshotHelperCopyToClipboard.value =
|
||||||
screenshotHelperCopyToClipboardConfig;
|
screenshotHelperCopyToClipboardConfig;
|
||||||
youTubeApi.value = youTubeApiConfig;
|
youTubeApi.value = youTubeApiConfig;
|
||||||
|
translationApi.value = translationApiConfig;
|
||||||
youTubeApiKey.value = youTubeApiKeyConfig;
|
youTubeApiKey.value = youTubeApiKeyConfig;
|
||||||
|
translationApiKey.value = translationApiKeyConfig;
|
||||||
progressPie.value = progressPieConfig;
|
progressPie.value = progressPieConfig;
|
||||||
progressPieFilter.value = progressPieFilterConfig;
|
progressPieFilter.value = progressPieFilterConfig;
|
||||||
showConfirmationOnSwitchAvatar.value =
|
showConfirmationOnSwitchAvatar.value =
|
||||||
@@ -299,6 +319,10 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
youTubeApi.value = !youTubeApi.value;
|
youTubeApi.value = !youTubeApi.value;
|
||||||
await configRepository.setBool('VRCX_youtubeAPI', youTubeApi.value);
|
await configRepository.setBool('VRCX_youtubeAPI', youTubeApi.value);
|
||||||
}
|
}
|
||||||
|
async function setTranslationApi() {
|
||||||
|
translationApi.value = !translationApi.value;
|
||||||
|
await configRepository.setBool('VRCX_translationAPI', youTubeApi.value);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @param {string} value
|
* @param {string} value
|
||||||
*/
|
*/
|
||||||
@@ -309,6 +333,17 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
youTubeApiKey.value
|
youTubeApiKey.value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
async function setTranslationApiKey(value) {
|
||||||
|
translationApiKey.value = value;
|
||||||
|
await configRepository.setString(
|
||||||
|
'VRCX_translationAPIKey',
|
||||||
|
translationApiKey.value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function setBioLanguage(language) {
|
||||||
|
bioLanguage.value = language;
|
||||||
|
configRepository.setString('VRCX_bioLanguage', language);
|
||||||
|
}
|
||||||
async function setProgressPie() {
|
async function setProgressPie() {
|
||||||
progressPie.value = !progressPie.value;
|
progressPie.value = !progressPie.value;
|
||||||
await configRepository.setBool('VRCX_progressPie', progressPie.value);
|
await configRepository.setBool('VRCX_progressPie', progressPie.value);
|
||||||
@@ -548,6 +583,31 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function translateText(text, targetLang) {
|
||||||
|
if (!translationApiKey.value) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(
|
||||||
|
`https://translation.googleapis.com/language/translate/v2?key=${translationApiKey.value}`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
q: text,
|
||||||
|
target: targetLang,
|
||||||
|
format: 'text'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (data.error) return null;
|
||||||
|
return data.data.translations[0].translatedText;
|
||||||
|
} catch (err) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function cropPrintsChanged() {
|
function cropPrintsChanged() {
|
||||||
if (!cropInstancePrints.value) return;
|
if (!cropInstancePrints.value) return;
|
||||||
ElMessageBox.confirm(
|
ElMessageBox.confirm(
|
||||||
@@ -728,6 +788,7 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
return {
|
return {
|
||||||
state,
|
state,
|
||||||
|
|
||||||
|
bioLanguage,
|
||||||
enablePrimaryPassword,
|
enablePrimaryPassword,
|
||||||
relaunchVRChatAfterCrash,
|
relaunchVRChatAfterCrash,
|
||||||
vrcQuitFix,
|
vrcQuitFix,
|
||||||
@@ -744,7 +805,9 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
screenshotHelperModifyFilename,
|
screenshotHelperModifyFilename,
|
||||||
screenshotHelperCopyToClipboard,
|
screenshotHelperCopyToClipboard,
|
||||||
youTubeApi,
|
youTubeApi,
|
||||||
|
translationApi,
|
||||||
youTubeApiKey,
|
youTubeApiKey,
|
||||||
|
translationApiKey,
|
||||||
progressPie,
|
progressPie,
|
||||||
progressPieFilter,
|
progressPieFilter,
|
||||||
showConfirmationOnSwitchAvatar,
|
showConfirmationOnSwitchAvatar,
|
||||||
@@ -761,6 +824,7 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
sentryErrorReporting,
|
sentryErrorReporting,
|
||||||
|
|
||||||
setEnablePrimaryPasswordConfigRepository,
|
setEnablePrimaryPasswordConfigRepository,
|
||||||
|
setBioLanguage,
|
||||||
setRelaunchVRChatAfterCrash,
|
setRelaunchVRChatAfterCrash,
|
||||||
setVrcQuitFix,
|
setVrcQuitFix,
|
||||||
setAutoSweepVRChatCache,
|
setAutoSweepVRChatCache,
|
||||||
@@ -776,7 +840,9 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
setScreenshotHelperModifyFilename,
|
setScreenshotHelperModifyFilename,
|
||||||
setScreenshotHelperCopyToClipboard,
|
setScreenshotHelperCopyToClipboard,
|
||||||
setYouTubeApi,
|
setYouTubeApi,
|
||||||
|
setTranslationApi,
|
||||||
setYouTubeApiKey,
|
setYouTubeApiKey,
|
||||||
|
setTranslationApiKey,
|
||||||
setProgressPie,
|
setProgressPie,
|
||||||
setProgressPieFilter,
|
setProgressPieFilter,
|
||||||
setShowConfirmationOnSwitchAvatar,
|
setShowConfirmationOnSwitchAvatar,
|
||||||
@@ -788,6 +854,7 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
getSqliteTableSizes,
|
getSqliteTableSizes,
|
||||||
handleSetAppLauncherSettings,
|
handleSetAppLauncherSettings,
|
||||||
lookupYouTubeVideo,
|
lookupYouTubeVideo,
|
||||||
|
translateText,
|
||||||
resetUGCFolder,
|
resetUGCFolder,
|
||||||
openUGCFolder,
|
openUGCFolder,
|
||||||
openUGCFolderSelector,
|
openUGCFolderSelector,
|
||||||
|
|||||||
@@ -137,6 +137,20 @@
|
|||||||
}}</el-button>
|
}}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="options-container">
|
||||||
|
<span class="header">{{ t('view.settings.advanced.advanced.translation_api.header') }}</span>
|
||||||
|
<simple-switch
|
||||||
|
:label="t('view.settings.advanced.advanced.translation_api.enable')"
|
||||||
|
:value="translationApi"
|
||||||
|
:tooltip="t('view.settings.advanced.advanced.translation_api.enable_tooltip')"
|
||||||
|
:long-label="true"
|
||||||
|
@change="changeTranslationAPI('VRCX_translationAPI')" />
|
||||||
|
<div class="options-container-item">
|
||||||
|
<el-button size="small" :icon="CaretRight" @click="showTranslationApiDialog">{{
|
||||||
|
t('view.settings.advanced.advanced.translation_api.translation_api_key')
|
||||||
|
}}</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="options-container">
|
<div class="options-container">
|
||||||
<span class="header">{{ t('view.settings.advanced.advanced.video_progress_pie.header') }}</span>
|
<span class="header">{{ t('view.settings.advanced.advanced.video_progress_pie.header') }}</span>
|
||||||
<simple-switch
|
<simple-switch
|
||||||
@@ -323,6 +337,7 @@
|
|||||||
|
|
||||||
<RegistryBackupDialog />
|
<RegistryBackupDialog />
|
||||||
<YouTubeApiDialog v-model:isYouTubeApiDialogVisible="isYouTubeApiDialogVisible" />
|
<YouTubeApiDialog v-model:isYouTubeApiDialogVisible="isYouTubeApiDialogVisible" />
|
||||||
|
<TranslationApiDialog v-model:isTranslationApiDialogVisible="isTranslationApiDialogVisible" />
|
||||||
<AvatarProviderDialog v-model:isAvatarProviderDialogVisible="isAvatarProviderDialogVisible" />
|
<AvatarProviderDialog v-model:isAvatarProviderDialogVisible="isAvatarProviderDialogVisible" />
|
||||||
<PhotonSettings v-if="photonLoggingEnabled" />
|
<PhotonSettings v-if="photonLoggingEnabled" />
|
||||||
</div>
|
</div>
|
||||||
@@ -368,6 +383,7 @@
|
|||||||
import PhotonSettings from '../PhotonSettings.vue';
|
import PhotonSettings from '../PhotonSettings.vue';
|
||||||
import RegistryBackupDialog from '../../dialogs/RegistryBackupDialog.vue';
|
import RegistryBackupDialog from '../../dialogs/RegistryBackupDialog.vue';
|
||||||
import SimpleSwitch from '../SimpleSwitch.vue';
|
import SimpleSwitch from '../SimpleSwitch.vue';
|
||||||
|
import TranslationApiDialog from '../../dialogs/TranslationApiDialog.vue';
|
||||||
import YouTubeApiDialog from '../../dialogs/YouTubeApiDialog.vue';
|
import YouTubeApiDialog from '../../dialogs/YouTubeApiDialog.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@@ -400,6 +416,7 @@
|
|||||||
enableAppLauncherAutoClose,
|
enableAppLauncherAutoClose,
|
||||||
enableAppLauncherRunProcessOnce,
|
enableAppLauncherRunProcessOnce,
|
||||||
youTubeApi,
|
youTubeApi,
|
||||||
|
translationApi,
|
||||||
progressPie,
|
progressPie,
|
||||||
progressPieFilter,
|
progressPieFilter,
|
||||||
showConfirmationOnSwitchAvatar,
|
showConfirmationOnSwitchAvatar,
|
||||||
@@ -428,6 +445,7 @@
|
|||||||
const { showAvatarProviderDialog } = useAvatarProviderStore();
|
const { showAvatarProviderDialog } = useAvatarProviderStore();
|
||||||
|
|
||||||
const isYouTubeApiDialogVisible = ref(false);
|
const isYouTubeApiDialogVisible = ref(false);
|
||||||
|
const isTranslationApiDialogVisible = ref(false);
|
||||||
|
|
||||||
const cacheSize = reactive({
|
const cacheSize = reactive({
|
||||||
cachedUsers: 0,
|
cachedUsers: 0,
|
||||||
@@ -496,6 +514,10 @@
|
|||||||
isYouTubeApiDialogVisible.value = true;
|
isYouTubeApiDialogVisible.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showTranslationApiDialog() {
|
||||||
|
isTranslationApiDialogVisible.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
function refreshCacheSize() {
|
function refreshCacheSize() {
|
||||||
cacheSize.cachedUsers = cachedUsers.size;
|
cacheSize.cachedUsers = cachedUsers.size;
|
||||||
cacheSize.cachedWorlds = cachedWorlds.size;
|
cacheSize.cachedWorlds = cachedWorlds.size;
|
||||||
@@ -516,4 +538,10 @@
|
|||||||
updateVRLastLocation();
|
updateVRLastLocation();
|
||||||
updateOpenVR();
|
updateOpenVR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function changeTranslationAPI(configKey = '') {
|
||||||
|
if (configKey === 'VRCX_translationAPI') {
|
||||||
|
advancedSettingsStore.setTranslationApi();
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
class="x-dialog"
|
||||||
|
:model-value="isTranslationApiDialogVisible"
|
||||||
|
:title="t('dialog.translation_api.header')"
|
||||||
|
width="400px"
|
||||||
|
@close="closeDialog">
|
||||||
|
<div class="options-container-item">
|
||||||
|
<span class="name">{{ t('view.settings.appearance.appearance.bio_language') }}</span>
|
||||||
|
<el-dropdown trigger="click" size="small" @click.stop>
|
||||||
|
<el-button size="small">
|
||||||
|
<span>
|
||||||
|
{{ messages[bioLanguage]?.language || bioLanguage }}
|
||||||
|
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
|
||||||
|
</span>
|
||||||
|
</el-button>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item
|
||||||
|
v-for="(obj, language) in messages"
|
||||||
|
:key="language"
|
||||||
|
@click="setBioLanguage(language)"
|
||||||
|
v-text="obj.language" />
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
<div style="font-size: 12px">{{ t('dialog.translation_api.description') }} <br /></div>
|
||||||
|
|
||||||
|
<el-input
|
||||||
|
v-model="translationApiKey"
|
||||||
|
type="textarea"
|
||||||
|
:placeholder="t('dialog.translation_api.placeholder')"
|
||||||
|
maxlength="39"
|
||||||
|
show-word-limit
|
||||||
|
style="display: block; margin-top: 10px">
|
||||||
|
</el-input>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div style="display: flex">
|
||||||
|
<el-button
|
||||||
|
@click="
|
||||||
|
openExternalLink(
|
||||||
|
'https://translatepress.com/docs/automatic-translation/generate-google-api-key/'
|
||||||
|
)
|
||||||
|
">
|
||||||
|
{{ t('dialog.translation_api.guide') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" style="margin-left: auto" @click="testTranslationApiKey">
|
||||||
|
{{ t('dialog.translation_api.save') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ArrowDown } from '@element-plus/icons-vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import { openExternalLink } from '../../../shared/utils';
|
||||||
|
import { useAdvancedSettingsStore } from '../../../stores';
|
||||||
|
|
||||||
|
const advancedSettingsStore = useAdvancedSettingsStore();
|
||||||
|
|
||||||
|
const { bioLanguage, translationApiKey } = storeToRefs(advancedSettingsStore);
|
||||||
|
|
||||||
|
const { setBioLanguage, translateText, setTranslationApiKey } = advancedSettingsStore;
|
||||||
|
|
||||||
|
const { messages, t } = useI18n();
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
isTranslationApiDialogVisible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:isTranslationApiDialogVisible']);
|
||||||
|
|
||||||
|
async function testTranslationApiKey() {
|
||||||
|
const previousKey = translationApiKey.value;
|
||||||
|
if (!translationApiKey.value) {
|
||||||
|
ElMessage({
|
||||||
|
message: 'Translation API key removed',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
closeDialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const testText = 'Hello world';
|
||||||
|
const data = await translateText(testText, 'fr');
|
||||||
|
if (!data) {
|
||||||
|
setTranslationApiKey(previousKey);
|
||||||
|
ElMessage({
|
||||||
|
message: 'Invalid Translation API key',
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setTranslationApiKey(translationApiKey.value);
|
||||||
|
ElMessage({
|
||||||
|
message: 'Translation API key valid!',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
closeDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeDialog() {
|
||||||
|
emit('update:isTranslationApiDialogVisible', false);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user