diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2021-08-15 20:26:44 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2021-08-15 20:26:44 +0900 |
| commit | cced83024bfb578ee802ab13fc8af72a1be9a1e1 (patch) | |
| tree | 359d6a3eff6250600e714e5ec2a5ae2516cd8353 /src/client | |
| parent | chore: Remove vips from Dockerfile (#7633) (diff) | |
| download | sharkey-cced83024bfb578ee802ab13fc8af72a1be9a1e1.tar.gz sharkey-cced83024bfb578ee802ab13fc8af72a1be9a1e1.tar.bz2 sharkey-cced83024bfb578ee802ab13fc8af72a1be9a1e1.zip | |
feat: ノートの翻訳機能
Resolve #5213
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/components/global/loading.vue | 32 | ||||
| -rw-r--r-- | src/client/components/note-detailed.vue | 32 | ||||
| -rw-r--r-- | src/client/components/note.vue | 32 | ||||
| -rw-r--r-- | src/client/pages/instance/other-settings.vue | 10 |
4 files changed, 89 insertions, 17 deletions
diff --git a/src/client/components/global/loading.vue b/src/client/components/global/loading.vue index 9b810f0a16..7bde53c12e 100644 --- a/src/client/components/global/loading.vue +++ b/src/client/components/global/loading.vue @@ -1,5 +1,5 @@ <template> -<div class="yxspomdl" :class="{ inline, colored }"> +<div class="yxspomdl" :class="{ inline, colored, mini }"> <div class="ring"></div> </div> </template> @@ -18,7 +18,12 @@ export default defineComponent({ type: Boolean, required: false, default: true - } + }, + mini: { + type: Boolean, + required: false, + default: false + }, } }); </script> @@ -38,6 +43,8 @@ export default defineComponent({ text-align: center; cursor: wait; + --size: 48px; + &.colored { color: var(--accent); } @@ -45,19 +52,12 @@ export default defineComponent({ &.inline { display: inline; padding: 0; + --size: 32px; + } - > .ring:after { - width: 32px; - height: 32px; - } - - > .ring { - &:before, - &:after { - width: 32px; - height: 32px; - } - } + &.mini { + padding: 16px; + --size: 32px; } > .ring { @@ -70,8 +70,8 @@ export default defineComponent({ content: " "; display: block; box-sizing: border-box; - width: 48px; - height: 48px; + width: var(--size); + height: var(--size); border-radius: 50%; border: solid 4px; } diff --git a/src/client/components/note-detailed.vue b/src/client/components/note-detailed.vue index d601052927..a2460950cd 100644 --- a/src/client/components/note-detailed.vue +++ b/src/client/components/note-detailed.vue @@ -67,6 +67,13 @@ <MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><i class="fas fa-reply"></i></MkA> <Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/> <a class="rp" v-if="appearNote.renote != null">RN:</a> + <div class="translation" v-if="translating || translation"> + <MkLoading v-if="translating" mini/> + <div class="translated" v-else> + <b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}:</b> + {{ translation.text }} + </div> + </div> </div> <div class="files" v-if="appearNote.files.length > 0"> <XMediaList :media-list="appearNote.files"/> @@ -178,6 +185,8 @@ export default defineComponent({ showContent: false, isDeleted: false, muted: false, + translation: null, + translating: false, }; }, @@ -619,6 +628,11 @@ export default defineComponent({ text: this.$ts.share, action: this.share }, + this.$instance.translatorAvailable ? { + icon: 'fas fa-language', + text: this.$ts.translate, + action: this.translate + } : undefined, null, statePromise.then(state => state.isFavorited ? { icon: 'fas fa-star', @@ -852,6 +866,17 @@ export default defineComponent({ }); }, + async translate() { + if (this.translation != null) return; + this.translating = true; + const res = await os.api('notes/translate', { + noteId: this.appearNote.id, + targetLang: localStorage.getItem('lang') || navigator.language, + }); + this.translating = false; + this.translation = res; + }, + focus() { this.$el.focus(); }, @@ -1050,6 +1075,13 @@ export default defineComponent({ font-style: oblique; color: var(--renote); } + + > .translation { + border: solid 0.5px var(--divider); + border-radius: var(--radius); + padding: 12px; + margin-top: 8px; + } } > .url-preview { diff --git a/src/client/components/note.vue b/src/client/components/note.vue index 873b96030a..38b529dd91 100644 --- a/src/client/components/note.vue +++ b/src/client/components/note.vue @@ -51,6 +51,13 @@ <MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><i class="fas fa-reply"></i></MkA> <Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/> <a class="rp" v-if="appearNote.renote != null">RN:</a> + <div class="translation" v-if="translating || translation"> + <MkLoading v-if="translating" mini/> + <div class="translated" v-else> + <b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}:</b> + {{ translation.text }} + </div> + </div> </div> <div class="files" v-if="appearNote.files.length > 0"> <XMediaList :media-list="appearNote.files"/> @@ -164,6 +171,8 @@ export default defineComponent({ collapsed: false, isDeleted: false, muted: false, + translation: null, + translating: false, }; }, @@ -594,6 +603,11 @@ export default defineComponent({ text: this.$ts.share, action: this.share }, + this.$instance.translatorAvailable ? { + icon: 'fas fa-language', + text: this.$ts.translate, + action: this.translate + } : undefined, null, statePromise.then(state => state.isFavorited ? { icon: 'fas fa-star', @@ -827,6 +841,17 @@ export default defineComponent({ }); }, + async translate() { + if (this.translation != null) return; + this.translating = true; + const res = await os.api('notes/translate', { + noteId: this.appearNote.id, + targetLang: localStorage.getItem('lang') || navigator.language, + }); + this.translating = false; + this.translation = res; + }, + focus() { this.$el.focus(); }, @@ -1053,6 +1078,13 @@ export default defineComponent({ font-style: oblique; color: var(--renote); } + + > .translation { + border: solid 0.5px var(--divider); + border-radius: var(--radius); + padding: 12px; + margin-top: 8px; + } } > .url-preview { diff --git a/src/client/pages/instance/other-settings.vue b/src/client/pages/instance/other-settings.vue index b3954149a8..8002528931 100644 --- a/src/client/pages/instance/other-settings.vue +++ b/src/client/pages/instance/other-settings.vue @@ -7,7 +7,12 @@ Summaly Proxy URL </FormInput> </FormGroup> - + <FormGroup> + <FormInput v-model:value="deeplAuthKey"> + <template #prefix><i class="fas fa-key"></i></template> + DeepL Auth Key + </FormInput> + </FormGroup> <FormButton @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> </FormSuspense> </FormBase> @@ -44,6 +49,7 @@ export default defineComponent({ icon: 'fas fa-cogs' }, summalyProxy: '', + deeplAuthKey: '', } }, @@ -55,10 +61,12 @@ export default defineComponent({ async init() { const meta = await os.api('meta', { detail: true }); this.summalyProxy = meta.summalyProxy; + this.deeplAuthKey = meta.deeplAuthKey; }, save() { os.apiWithDialog('admin/update-meta', { summalyProxy: this.summalyProxy, + deeplAuthKey: this.deeplAuthKey, }).then(() => { fetchInstance(); }); |