Compare commits

...

4 commits

12 changed files with 71 additions and 16 deletions

View file

@ -397,6 +397,7 @@ const afterStoreSetup = async ({ store, i18n }) => {
store.dispatch('startFetchingAnnouncements') store.dispatch('startFetchingAnnouncements')
getTOS({ store }) getTOS({ store })
getStickers({ store }) getStickers({ store })
store.dispatch('getSupportedTranslationlanguages')
const router = createRouter({ const router = createRouter({
history: createWebHistory(), history: createWebHistory(),

View file

@ -54,6 +54,7 @@
z-index: 2001; z-index: 2001;
cursor: default; cursor: default;
display: block; display: block;
width: max-content;
background-color: $fallback--bg; background-color: $fallback--bg;
background-color: var(--bg, $fallback--bg); background-color: var(--bg, $fallback--bg);

View file

@ -83,6 +83,9 @@ const GeneralTab = {
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val }) this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
} }
}, },
translationLanguages () {
return (this.$store.getters.mergedConfig.supportedTranslationLanguages.target || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name }))
},
translationLanguage: { translationLanguage: {
get: function () { return this.$store.getters.mergedConfig.translationLanguage }, get: function () { return this.$store.getters.mergedConfig.translationLanguage },
set: function (val) { set: function (val) {

View file

@ -157,14 +157,14 @@
</ul> </ul>
</li> </li>
<li> <li>
<p> <ChoiceSetting
<interface-language-switcher v-if="user && (translationLanguages.length > 0)"
:globe-icon="false" id="translationLanguage"
:prompt-text="$t('settings.translation_language')" path="translationLanguage"
:language="translationLanguage" :options="translationLanguages"
:set-language="setTranslationLanguage" >
/> {{ $t('settings.translation_language') }}
</p> </ChoiceSetting>
</li> </li>
<li> <li>
<BooleanSetting <BooleanSetting

View file

@ -9,6 +9,7 @@ import {
faLink, faLink,
faPollH faPollH
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import Select from 'src/components/select/select.vue'
library.add( library.add(
faFile, faFile,
@ -39,7 +40,8 @@ const StatusContent = {
return { return {
postLength: this.status.text.length, postLength: this.status.text.length,
parseReadyDone: false, parseReadyDone: false,
renderMisskeyMarkdown renderMisskeyMarkdown,
translateFrom: null
} }
}, },
computed: { computed: {
@ -80,10 +82,14 @@ const StatusContent = {
attachmentTypes () { attachmentTypes () {
return this.status.attachments.map(file => fileType.fileType(file.mimetype)) return this.status.attachments.map(file => fileType.fileType(file.mimetype))
}, },
translationLanguages () {
return (this.$store.getters.mergedConfig.supportedTranslationLanguages.source || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name }))
},
...mapGetters(['mergedConfig']) ...mapGetters(['mergedConfig'])
}, },
components: { components: {
RichContent RichContent,
Select
}, },
mounted () { mounted () {
this.status.attentions && this.status.attentions.forEach(attn => { this.status.attentions && this.status.attentions.forEach(attn => {
@ -126,6 +132,10 @@ const StatusContent = {
}, },
generateTagLink (tag) { generateTagLink (tag) {
return `/tag/${tag}` return `/tag/${tag}`
},
translateStatus () {
const translateTo = this.$store.getters.mergedConfig.translationLanguage || this.$store.state.instance.interfaceLanguage
this.$store.dispatch('translateStatus', { id: this.status.id, language: translateTo, from: this.translateFrom })
} }
} }
} }

View file

@ -72,6 +72,27 @@
:attentions="status.attentions" :attentions="status.attentions"
@parseReady="onParseReady" @parseReady="onParseReady"
/> />
<div>
<label class="label">{{ $t('status.override_translation_source_language') }}</label>
{{ ' ' }}
<Select
id="source-language-switcher"
v-model="translateFrom"
class="preset-switcher"
>
<option
v-for="language in translationLanguages"
:key="language.key"
:value="language.value"
>
{{ language.label }}
</option>
</Select>
{{ ' ' }}
<button @click="translateStatus" class="btn button-default">
{{ $t('status.translate') }}
</button>
</div>
</div> </div>
</div> </div>
<button <button

View file

@ -846,6 +846,7 @@
"mute_conversation": "Mute conversation", "mute_conversation": "Mute conversation",
"nsfw": "NSFW", "nsfw": "NSFW",
"open_gallery": "Open gallery", "open_gallery": "Open gallery",
"override_translation_source_language": "Override source language",
"pin": "Pin on profile", "pin": "Pin on profile",
"pinned": "Pinned", "pinned": "Pinned",
"plus_more": "+{number} more", "plus_more": "+{number} more",

View file

@ -252,6 +252,12 @@ const api = {
if (!fetcher) return if (!fetcher) return
store.commit('removeFetcher', { fetcherName: 'announcements', fetcher }) store.commit('removeFetcher', { fetcherName: 'announcements', fetcher })
}, },
getSupportedTranslationlanguages (store) {
store.state.backendInteractor.getSupportedTranslationlanguages({ store })
.then((data) => {
store.dispatch('setOption', { name: 'supportedTranslationLanguages', value: data })
})
},
// Pleroma websocket // Pleroma websocket
setWsToken (store, token) { setWsToken (store, token) {

View file

@ -115,7 +115,8 @@ export const defaultState = {
conversationOtherRepliesButton: undefined, // instance default conversationOtherRepliesButton: undefined, // instance default
conversationTreeFadeAncestors: undefined, // instance default conversationTreeFadeAncestors: undefined, // instance default
maxDepthInThread: undefined, // instance default maxDepthInThread: undefined, // instance default
translationLanguage: undefined // instance default translationLanguage: undefined, // instance default,
supportedTranslationLanguages: {} // instance default
} }
// caching the instance default properties // caching the instance default properties

View file

@ -641,8 +641,8 @@ const statuses = {
rootState.api.backendInteractor.unpinOwnStatus({ id: statusId }) rootState.api.backendInteractor.unpinOwnStatus({ id: statusId })
.then((status) => dispatch('addNewStatuses', { statuses: [status] })) .then((status) => dispatch('addNewStatuses', { statuses: [status] }))
}, },
translateStatus ({ rootState, commit }, { id, translation, language }) { translateStatus ({ rootState, commit }, { id, translation, language, from }) {
return rootState.api.backendInteractor.translateStatus({ id: id, translation, language }) return rootState.api.backendInteractor.translateStatus({ id: id, translation, language, from })
.then((translation) => commit('setTranslatedStatus', { id, translation })) .then((translation) => commit('setTranslatedStatus', { id, translation }))
}, },
muteConversation ({ rootState, commit }, statusId) { muteConversation ({ rootState, commit }, statusId) {

View file

@ -31,6 +31,7 @@ const MASTODON_LOGIN_URL = '/api/v1/accounts/verify_credentials'
const MASTODON_REGISTRATION_URL = '/api/v1/accounts' const MASTODON_REGISTRATION_URL = '/api/v1/accounts'
const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites' const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
const MASTODON_USER_NOTIFICATIONS_URL = '/api/v1/notifications' const MASTODON_USER_NOTIFICATIONS_URL = '/api/v1/notifications'
const AKKOMA_LANGUAGES_URL = '/api/v1/akkoma/translation/languages'
const AKKOMA_TRANSLATE_URL = (id, lang) => `/api/v1/statuses/${id}/translations/${lang}` const AKKOMA_TRANSLATE_URL = (id, lang) => `/api/v1/statuses/${id}/translations/${lang}`
const MASTODON_DISMISS_NOTIFICATION_URL = id => `/api/v1/notifications/${id}/dismiss` const MASTODON_DISMISS_NOTIFICATION_URL = id => `/api/v1/notifications/${id}/dismiss`
const MASTODON_FAVORITE_URL = id => `/api/v1/statuses/${id}/favourite` const MASTODON_FAVORITE_URL = id => `/api/v1/statuses/${id}/favourite`
@ -739,8 +740,13 @@ const unretweet = ({ id, credentials }) => {
.then((data) => parseStatus(data)) .then((data) => parseStatus(data))
} }
const translateStatus = ({ id, credentials, language }) => { const getSupportedTranslationlanguages = ({ credentials }) => {
return promisedRequest({ url: AKKOMA_TRANSLATE_URL(id, language), method: 'GET', credentials }) return promisedRequest({ url: AKKOMA_LANGUAGES_URL, credentials })
}
const translateStatus = ({ id, credentials, language, from }) => {
const queryString = from ? `?from=${from}` : ''
return promisedRequest({ url: AKKOMA_TRANSLATE_URL(id, language) + queryString, method: 'GET', credentials })
.then((data) => { .then((data) => {
return data return data
}) })
@ -1585,7 +1591,8 @@ const apiService = {
editAnnouncement, editAnnouncement,
deleteAnnouncement, deleteAnnouncement,
adminFetchAnnouncements, adminFetchAnnouncements,
translateStatus translateStatus,
getSupportedTranslationlanguages
} }
export default apiService export default apiService

View file

@ -40,6 +40,10 @@ const backendInteractorService = credentials => ({
return ProcessedWS({ url, id: 'User' }) return ProcessedWS({ url, id: 'User' })
}, },
getSupportedTranslationlanguages ({ store }) {
return apiService.getSupportedTranslationlanguages({ store, credentials })
},
...Object.entries(apiService).reduce((acc, [key, func]) => { ...Object.entries(apiService).reduce((acc, [key, func]) => {
return { return {
...acc, ...acc,