feat(client): 返信も翻訳できるように

This commit is contained in:
NoriDev 2023-06-15 16:52:01 +09:00
parent c4991b8ea6
commit 851d2a48a0
2 changed files with 38 additions and 1 deletions

View file

@ -67,6 +67,7 @@
- CherryPick 고유 기능 및 개선된 기능은 [CherryPick] 배지 추가
- 네비게이션 메뉴 편집 페이지 UI 개선 ([shrimpia bf8c84d](https://github.com/shrimpia/misskey/commit/bf8c84d299bd06cb21e18a9fe68ff9abc11fd4a0))
- 「노트 본문에 번역 버튼 표시」를 선택 사항으로 설정
- 답글도 번역할 수 있도록 개선
- Fix: (Friendly) 플로팅 메뉴를 길게 눌렀을 때 프로필 이미지를 드래그 할 수 있는 문제
- Fix: (Friendly) 타임라인이 변경되었을 때 네비게이션 바의 인디케이터가 사라지지 않는 문제
- Fix: (Friendly) 모바일에서 헤더가 사라졌을 때 프로필 아이콘의 높이가 잘못 설정되는 문제

View file

@ -6,6 +6,18 @@
<MkA v-if="note.replyId" :class="$style.reply" :to="`/notes/${note.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i" :emojiUrls="note.emojis"/>
<MkA v-if="note.renoteId" :class="$style.rp" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
<div style="padding-top: 5px; color: var(--accent);"><button v-if="defaultStore.state.showTranslateButtonInNote" ref="translateButton" class="_button" @mousedown="translate()">{{ i18n.ts.translateNote }}</button></div>
<div v-if="translating || translation" :class="$style.translation">
<MkLoading v-if="translating" mini/>
<div v-else>
<b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}:</b><hr style="margin: 10px 0;">
<Mfm :text="translation.text" :author="note.user" :i="$i" :emojiUrls="note.emojis"/>
<div v-if="translation.translator == 'ctav3'" style="margin-top: 10px; padding: 0 0 15px;">
<img v-if="!defaultStore.state.darkMode" src="/client-assets/color-short.svg" alt="" style="float: right;">
<img v-else src="/client-assets/white-short.svg" alt="" style="float: right;"/>
</div>
</div>
</div>
</div>
<details v-if="note.files.length > 0">
<summary>({{ i18n.t('withNFiles', { n: note.files.length }) }})</summary>
@ -23,12 +35,18 @@
</template>
<script lang="ts" setup>
import { } from 'vue';
import { ref } from 'vue';
import * as misskey from 'cherrypick-js';
import * as os from '@/os';
import MkMediaList from '@/components/MkMediaList.vue';
import MkPoll from '@/components/MkPoll.vue';
import { i18n } from '@/i18n';
import { $i } from '@/account';
import { defaultStore } from '@/store';
import { miLocalStorage } from '@/local-storage';
const translation = ref<any>(null);
const translating = ref(false);
const props = defineProps<{
note: misskey.entities.Note;
@ -39,6 +57,17 @@ const collapsed = $ref(
(props.note.text.split('\n').length > 9) ||
(props.note.text.length > 500)
));
async function translate(): Promise<void> {
if (translation.value != null) return;
translating.value = true;
const res = await os.api('notes/translate', {
noteId: props.note.id,
targetLang: miLocalStorage.getItem('lang') ?? navigator.language,
});
translating.value = false;
translation.value = res;
}
</script>
<style lang="scss" module>
@ -87,4 +116,11 @@ const collapsed = $ref(
font-style: oblique;
color: var(--renote);
}
.translation {
border: solid 0.5px var(--divider);
border-radius: var(--radius);
padding: 12px;
margin-top: 8px;
}
</style>