enhance(frontend): 実験的機能としてTranslator APIを用いた翻訳を実装 (#16600)
* enhance(frontend): 実験的機能としてTranslator APIを用いた翻訳を実装 * remove unused imports * remove unnecessary console.log * fix 表記揺れ * fix lint
This commit is contained in:
parent
7796fce779
commit
46b0e8115a
|
@ -102,6 +102,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkSwitch v-model="enableHapticFeedback">
|
||||
<template #label>Enable haptic feedback</template>
|
||||
</MkSwitch>
|
||||
<MkSwitch v-model="enableWebTranslatorApi">
|
||||
<template #label>Enable in-browser translator API</template>
|
||||
</MkSwitch>
|
||||
</div>
|
||||
</MkFolder>
|
||||
</SearchMarker>
|
||||
|
@ -182,6 +185,7 @@ const devMode = prefer.model('devMode');
|
|||
const stackingRouterView = prefer.model('experimental.stackingRouterView');
|
||||
const enableFolderPageView = prefer.model('experimental.enableFolderPageView');
|
||||
const enableHapticFeedback = prefer.model('experimental.enableHapticFeedback');
|
||||
const enableWebTranslatorApi = prefer.model('experimental.enableWebTranslatorApi');
|
||||
|
||||
watch(skipNoteRender, () => {
|
||||
suggestReload();
|
||||
|
|
|
@ -516,4 +516,7 @@ export const PREF_DEF = definePreferences({
|
|||
'experimental.enableHapticFeedback': {
|
||||
default: false,
|
||||
},
|
||||
'experimental.enableWebTranslatorApi': {
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { url } from '@@/js/config.js';
|
||||
import { claimAchievement } from './achievements.js';
|
||||
|
@ -27,6 +26,11 @@ import { prefer } from '@/preferences.js';
|
|||
import { getPluginHandlers } from '@/plugin.js';
|
||||
import { globalEvents } from '@/events.js';
|
||||
|
||||
const isInBrowserTranslationAvailable = (
|
||||
'LanguageDetector' in window &&
|
||||
'Translator' in window
|
||||
);
|
||||
|
||||
export async function getNoteClipMenu(props: {
|
||||
note: Misskey.entities.Note;
|
||||
currentClip?: Misskey.entities.Clip;
|
||||
|
@ -285,6 +289,40 @@ export function getNoteMenu(props: {
|
|||
|
||||
async function translate(): Promise<void> {
|
||||
if (props.translation.value != null) return;
|
||||
if (prefer.s['experimental.enableWebTranslatorApi'] && isInBrowserTranslationAvailable && appearNote.text != null) {
|
||||
props.translating.value = true;
|
||||
try {
|
||||
// @ts-expect-error 実験的なAPIなので型定義がない
|
||||
const detector = await LanguageDetector.create();
|
||||
const langResult = await detector.detect(appearNote.text);
|
||||
let localStorageLang = miLocalStorage.getItem('lang');
|
||||
if (localStorageLang != null) {
|
||||
localStorageLang = localStorageLang.split('-')[0];
|
||||
}
|
||||
|
||||
// 翻訳元と翻訳先の言語が同じ場合はTranslatorがthrowするのでそのまま返す
|
||||
if (langResult[0]?.detectedLanguage === localStorageLang || langResult[0]?.detectedLanguage === navigator.language) {
|
||||
props.translation.value = {
|
||||
sourceLang: langResult[0]?.detectedLanguage ?? 'unknown',
|
||||
text: appearNote.text,
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-expect-error 実験的なAPIなので型定義がない
|
||||
const translator = await Translator.create({
|
||||
sourceLanguage: langResult[0]?.detectedLanguage,
|
||||
targetLanguage: localStorageLang ?? navigator.language,
|
||||
});
|
||||
const translated = await translator.translate(appearNote.text);
|
||||
props.translation.value = {
|
||||
sourceLang: langResult[0]?.detectedLanguage ?? 'unknown',
|
||||
text: translated,
|
||||
};
|
||||
} finally {
|
||||
props.translating.value = false;
|
||||
}
|
||||
} else if ($i?.policies.canUseTranslator && instance.translatorAvailable) {
|
||||
props.translating.value = true;
|
||||
const res = await misskeyApi('notes/translate', {
|
||||
noteId: appearNote.id,
|
||||
|
@ -293,6 +331,7 @@ export function getNoteMenu(props: {
|
|||
props.translating.value = false;
|
||||
props.translation.value = res;
|
||||
}
|
||||
}
|
||||
|
||||
const menuItems: MenuItem[] = [];
|
||||
|
||||
|
@ -349,7 +388,7 @@ export function getNoteMenu(props: {
|
|||
});
|
||||
}
|
||||
|
||||
if ($i.policies.canUseTranslator && instance.translatorAvailable) {
|
||||
if ((prefer.s['experimental.enableWebTranslatorApi'] && isInBrowserTranslationAvailable) || ($i.policies.canUseTranslator && instance.translatorAvailable)) {
|
||||
menuItems.push({
|
||||
icon: 'ti ti-language-hiragana',
|
||||
text: i18n.ts.translate,
|
||||
|
|
Loading…
Reference in New Issue