forked from Mirrors/elk
i18n: improve translations
This commit is contained in:
parent
acdd33ef7d
commit
ccffe9daa8
15 changed files with 231 additions and 143 deletions
1
.eslintignore
Normal file
1
.eslintignore
Normal file
|
@ -0,0 +1 @@
|
|||
*.css
|
|
@ -51,7 +51,7 @@ const { items, prevItems, update, state, endAnchor, error } = usePaginator(pagin
|
|||
<slot v-if="state === 'loading'" name="loading">
|
||||
<div p5 text-center flex="~ col" items-center animate-pulse>
|
||||
<div text-secondary i-ri:loader-2-fill animate-spin text-2xl />
|
||||
<span text-secondary>Loading...</span>
|
||||
<span text-secondary>{{ $t('state.loading') }}</span>
|
||||
</div>
|
||||
</slot>
|
||||
<div v-else-if="state === 'done'" p5 text-secondary italic text-center>
|
||||
|
|
|
@ -7,7 +7,7 @@ const sub = process.dev ? 'dev' : window.location.hostname.includes('deploy-prev
|
|||
<NuxtLink flex px3 py2 items-center text-2xl gap-2 hover:bg-active focus-visible:ring="2 current" rounded-full to="/" external>
|
||||
<img alt="Elk Logo" src="/logo.svg" w-10 h-10>
|
||||
<div>
|
||||
Elk <sup text-sm italic text-secondary mt-1>{{ sub }}</sup>
|
||||
{{ $t('app_name') }} <sup text-sm italic text-secondary mt-1>{{ sub }}</sup>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
|
|
@ -245,9 +245,9 @@ const { isOverDropZone } = useDropZone(dropZoneRef, onDrop)
|
|||
:checked="visibility.value === draft.params.visibility"
|
||||
@click="chooseVisibility(visibility.value)"
|
||||
>
|
||||
{{ visibility.label }}
|
||||
{{ $t(`visibility.${visibility.value}`) }}
|
||||
<template #description>
|
||||
{{ visibility.description }}
|
||||
{{ $t(`visibility.${visibility.value}_desc`) }}
|
||||
</template>
|
||||
</CommonDropdownItem>
|
||||
</template>
|
||||
|
|
|
@ -133,7 +133,7 @@ function editStatus() {
|
|||
<div flex justify-between>
|
||||
<div flex-1>
|
||||
<StatusActionButton
|
||||
content="Reply"
|
||||
:content="$t('action.reply')"
|
||||
:text="status.repliesCount"
|
||||
color="text-blue" hover="text-blue" group-hover="bg-blue/10"
|
||||
icon="i-ri:chat-3-line"
|
||||
|
@ -144,7 +144,7 @@ function editStatus() {
|
|||
|
||||
<div flex-1>
|
||||
<StatusActionButton
|
||||
content="Boost"
|
||||
:content="$t('action.boost')"
|
||||
:text="status.reblogsCount"
|
||||
color="text-green" hover="text-green" group-hover="bg-green/10"
|
||||
icon="i-ri:repeat-line"
|
||||
|
@ -158,7 +158,7 @@ function editStatus() {
|
|||
|
||||
<div flex-1>
|
||||
<StatusActionButton
|
||||
content="Favourite"
|
||||
:content="$t('action.favourite')"
|
||||
:text="status.favouritesCount"
|
||||
color="text-rose" hover="text-rose" group-hover="bg-rose/10"
|
||||
icon="i-ri:heart-3-line"
|
||||
|
@ -172,7 +172,7 @@ function editStatus() {
|
|||
|
||||
<div flex-none>
|
||||
<StatusActionButton
|
||||
content="Bookmark"
|
||||
:content="$t('action.bookmark')"
|
||||
color="text-yellow" hover="text-yellow" group-hover="bg-yellow/10"
|
||||
icon="i-ri:bookmark-line"
|
||||
active-icon="i-ri:bookmark-fill"
|
||||
|
@ -185,7 +185,7 @@ function editStatus() {
|
|||
|
||||
<CommonDropdown flex-none ml3 placement="bottom" :eager-mount="command">
|
||||
<StatusActionButton
|
||||
content="More"
|
||||
:content="$t('action.more')"
|
||||
color="text-purple" hover="text-purple" group-hover="bg-purple/10"
|
||||
icon="i-ri:more-line"
|
||||
/>
|
||||
|
@ -193,7 +193,7 @@ function editStatus() {
|
|||
<template #popper>
|
||||
<div flex="~ col">
|
||||
<CommonDropdownItem
|
||||
text="Copy link to this post"
|
||||
:text="$t('menu.copy_link_to_post')"
|
||||
icon="i-ri:link"
|
||||
:command="command"
|
||||
@click="copyLink(status)"
|
||||
|
@ -202,7 +202,7 @@ function editStatus() {
|
|||
<NuxtLink :to="status.url" target="_blank">
|
||||
<CommonDropdownItem
|
||||
v-if="status.url"
|
||||
text="Open in original site"
|
||||
:text="$t('menu.open_in_original_site')"
|
||||
icon="i-ri:arrow-right-up-line"
|
||||
:command="command"
|
||||
/>
|
||||
|
@ -210,7 +210,7 @@ function editStatus() {
|
|||
|
||||
<CommonDropdownItem
|
||||
v-if="isTranslationEnabled && status.language !== languageCode"
|
||||
:text="translation.visible ? 'Show untranslated' : 'Translate post'"
|
||||
:text="translation.visible ? $t('menu.show_untranslated') : $t('menu.translate_post')"
|
||||
icon="i-ri:translate"
|
||||
:command="command"
|
||||
@click="toggleTranslation"
|
||||
|
@ -219,21 +219,21 @@ function editStatus() {
|
|||
<template v-if="currentUser">
|
||||
<template v-if="isAuthor">
|
||||
<CommonDropdownItem
|
||||
:text="status.pinned ? 'Unpin on profile' : 'Pin on profile'"
|
||||
:text="status.pinned ? $t('menu.unpin_on_profile') : $t('menu.pin_on_profile')"
|
||||
icon="i-ri:pushpin-line"
|
||||
:command="command"
|
||||
@click="togglePin"
|
||||
/>
|
||||
|
||||
<CommonDropdownItem
|
||||
text="Edit"
|
||||
:text="$t('menu.edit')"
|
||||
icon="i-ri:edit-line"
|
||||
:command="command"
|
||||
@click="editStatus"
|
||||
/>
|
||||
|
||||
<CommonDropdownItem
|
||||
text="Delete"
|
||||
:text="$t('menu.delete')"
|
||||
icon="i-ri:delete-bin-line"
|
||||
text-red-600
|
||||
:command="command"
|
||||
|
@ -241,7 +241,7 @@ function editStatus() {
|
|||
/>
|
||||
|
||||
<CommonDropdownItem
|
||||
text="Delete & re-draft"
|
||||
:text="$t('menu.delete_and_redraft')"
|
||||
icon="i-ri:eraser-line"
|
||||
text-red-600
|
||||
:command="command"
|
||||
|
@ -250,7 +250,7 @@ function editStatus() {
|
|||
</template>
|
||||
<template v-else>
|
||||
<CommonDropdownItem
|
||||
:text="`Mention @${status.account.acct}`"
|
||||
:text="$t('menu.mention_account', [`@${status.account.acct}`])"
|
||||
icon="i-ri:at-line"
|
||||
:command="command"
|
||||
@click="mentionUser(status.account)"
|
||||
|
|
|
@ -43,11 +43,11 @@ const visibility = $computed(() => STATUS_VISIBILITIES.find(v => v.value === sta
|
|||
:status="status"
|
||||
:inline="false"
|
||||
>
|
||||
<span ml1 font-bold cursor-pointer>(Edited)</span>
|
||||
<span ml1 font-bold cursor-pointer>{{ $t('state.edited') }}</span>
|
||||
</StatusEditIndicator>
|
||||
</div>
|
||||
<div>·</div>
|
||||
<CommonTooltip :content="visibility.label" placement="bottom">
|
||||
<CommonTooltip :content="$t(`visibility.${visibility.value}`)" placement="bottom">
|
||||
<div :class="visibility.icon" />
|
||||
</CommonTooltip>
|
||||
<div v-if="status.application?.name">
|
||||
|
|
|
@ -33,17 +33,17 @@ const switchUser = (user: UserLogin) => {
|
|||
</button>
|
||||
</template>
|
||||
<div border="t base" pt2>
|
||||
<button btn-text flex="~ gap-1" items-center @click="openSigninDialog">
|
||||
<div i-ri:user-add-line />
|
||||
Add an existing account
|
||||
</button>
|
||||
<button
|
||||
v-if="currentUser" btn-text hover:text-red4 flex="~ gap-1" items-center
|
||||
<CommonDropdownItem
|
||||
:text=" $t('user.add_existing')"
|
||||
icon="i-ri:user-add-line"
|
||||
@click="openSigninDialog"
|
||||
/>
|
||||
<CommonDropdownItem
|
||||
v-if="currentUser"
|
||||
:text="$t('user.sign_out_account', [getFullHandle(currentUser.account)])"
|
||||
icon="i-ri:logout-box-line"
|
||||
@click="signout"
|
||||
>
|
||||
<div i-ri:logout-box-line />
|
||||
Sign out {{ getFullHandle(currentUser.account) }}
|
||||
</button>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -6,27 +6,19 @@ import { withoutProtocol } from 'ufo'
|
|||
export const STATUS_VISIBILITIES = [
|
||||
{
|
||||
value: 'public',
|
||||
label: 'Public',
|
||||
icon: 'i-ri:global-line',
|
||||
description: 'Visible for all',
|
||||
},
|
||||
{
|
||||
value: 'unlisted',
|
||||
label: 'Unlisted',
|
||||
icon: 'i-ri:lock-unlock-line',
|
||||
description: 'Visible for all, but opted-out of discovery features',
|
||||
},
|
||||
{
|
||||
value: 'private',
|
||||
label: 'Followers only',
|
||||
icon: 'i-ri:lock-line',
|
||||
description: 'Visible for followers only',
|
||||
},
|
||||
{
|
||||
value: 'direct',
|
||||
label: 'Mentioned people only',
|
||||
icon: 'i-ri:at-line',
|
||||
description: 'Visible for mentioned users only',
|
||||
},
|
||||
] as const
|
||||
|
||||
|
|
|
@ -24,11 +24,12 @@ export const currentUserDrafts = computed(() => {
|
|||
})
|
||||
|
||||
export function getDefaultDraft(options: Partial<Draft['params'] & Omit<Draft, 'params'>> = {}): Draft {
|
||||
const { t } = useI18n()
|
||||
const {
|
||||
status = '',
|
||||
inReplyToId,
|
||||
visibility = 'public',
|
||||
placeholder = 'What is on your mind?',
|
||||
placeholder = t('placeholder.default_1'),
|
||||
attachments = [],
|
||||
} = options
|
||||
return {
|
||||
|
@ -52,11 +53,12 @@ export function getDraftFromStatus(status: Status, text?: null | string): Draft
|
|||
}
|
||||
|
||||
export function getReplyDraft(status: Status) {
|
||||
const { t } = useI18n()
|
||||
return {
|
||||
key: `reply-${status.id}`,
|
||||
draft: () => getDefaultDraft({
|
||||
inReplyToId: status!.id,
|
||||
placeholder: `Reply to ${status?.account ? getDisplayName(status.account) : 'this thread'}`,
|
||||
placeholder: t('placeholder.reply_to_account', [status?.account ? getDisplayName(status.account) : t('placeholder.the_thread')]),
|
||||
visibility: status.visibility,
|
||||
}),
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ export const useFormattedDateTime = (
|
|||
value: MaybeComputedRef<string | Date | undefined | null>,
|
||||
options: Intl.DateTimeFormatOptions = { dateStyle: 'long', timeStyle: 'medium' },
|
||||
) => {
|
||||
const formatter = Intl.DateTimeFormat(undefined, options)
|
||||
const { locale } = useI18n()
|
||||
const formatter = Intl.DateTimeFormat(locale.value, options)
|
||||
return computed(() => {
|
||||
const v = resolveUnref(value)
|
||||
return v ? formatter.format(new Date(v)) : ''
|
||||
|
|
|
@ -15,12 +15,18 @@
|
|||
"unfollow": "Unfollow"
|
||||
},
|
||||
"action": {
|
||||
"bookmark": "Bookmark",
|
||||
"boost": "Boost",
|
||||
"compose": "Compose",
|
||||
"enter_app": "Enter App",
|
||||
"favourite": "Favourite",
|
||||
"more": "More",
|
||||
"publish": "Publish!",
|
||||
"reply": "Reply",
|
||||
"save_changes": "Save changes",
|
||||
"sign_in": "Sign in"
|
||||
},
|
||||
"app_name": "Elk",
|
||||
"command": {
|
||||
"activate": "Activate",
|
||||
"complete": "Complete"
|
||||
|
@ -39,13 +45,21 @@
|
|||
"menu": {
|
||||
"block_account": "Block {0}",
|
||||
"block_domain": "Block domain {0}",
|
||||
"copy_link_to_post": "Copy link to this post",
|
||||
"delete": "Delete",
|
||||
"delete_and_redraft": "Delete & re-draft",
|
||||
"direct_message_account": "Direct message {0}",
|
||||
"edit": "Edit",
|
||||
"mention_account": "Mention {0}",
|
||||
"mute_account": "Mute {0}",
|
||||
"open_in_original_site": "Open in original site",
|
||||
"pin_on_profile": "Pin on profile",
|
||||
"show_untranslated": "Show untranslated",
|
||||
"translate_post": "Translate post",
|
||||
"unblock_account": "Unblock {0}",
|
||||
"unblock_domain": "Unblock domain {0}",
|
||||
"unmute_account": "Unmute {0}"
|
||||
"unmute_account": "Unmute {0}",
|
||||
"unpin_on_profile": "Unpin on profile"
|
||||
},
|
||||
"nav_footer": {
|
||||
"select_feature_flags": "Toggle Feature Flags",
|
||||
|
@ -75,12 +89,21 @@
|
|||
"request_to_follow": "requested to follow you",
|
||||
"update_status": "updated their status"
|
||||
},
|
||||
"placeholder": {
|
||||
"default_1": "What is on your mind?",
|
||||
"reply_to_account": "Reply to {0}",
|
||||
"the_thread": "the thread"
|
||||
},
|
||||
"state": {
|
||||
"edited": "(Edited)",
|
||||
"editing": "Editing",
|
||||
"loading": "Loading...",
|
||||
"uploading": "Uploading..."
|
||||
},
|
||||
"tab": {
|
||||
"media": "Media",
|
||||
"notifications_all": "All",
|
||||
"notifications_mention": "Mention",
|
||||
"posts": "Posts",
|
||||
"posts_with_replies": "Posts & Replies"
|
||||
},
|
||||
|
@ -96,5 +119,19 @@
|
|||
"add_media": "Add images, a video or an audio file",
|
||||
"change_content_visibility": "Change content visibility",
|
||||
"toggle_code_block": "Toggle code block"
|
||||
},
|
||||
"user": {
|
||||
"add_existing": "Add an existing account",
|
||||
"sign_out_account": "Sign out {0}"
|
||||
},
|
||||
"visibility": {
|
||||
"direct": "Direct",
|
||||
"direct_desc": "Visible for mentioned users only",
|
||||
"private": "Followers only",
|
||||
"private_desc": "Visible for followers only",
|
||||
"public": "Public",
|
||||
"public_desc": "Visible for all",
|
||||
"unlisted": "Unlisted",
|
||||
"unlisted_desc": "Visible for all, but opted-out of discovery features"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,5 +90,4 @@
|
|||
"change_content_visibility": "Cambiar visibilidad",
|
||||
"toggle_code_block": "Toggle code block"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -78,12 +78,11 @@
|
|||
"posts_with_replies": "投稿と返信"
|
||||
},
|
||||
"timeline": {
|
||||
"name": "タイムライン",
|
||||
"show_new_items": "{0}件の新しい投稿"
|
||||
},
|
||||
"title": {
|
||||
"federated_timeline": "@:nav_side.federated @:timeline.name",
|
||||
"local_timeline": "@:nav_side.local @:timeline.name"
|
||||
"federated_timeline": "連合タイムライン",
|
||||
"local_timeline": "ローカルタイムライン"
|
||||
},
|
||||
"tooltip": {
|
||||
"add_content_warning": "警告を追加",
|
||||
|
|
|
@ -15,30 +15,51 @@
|
|||
"unfollow": "取消关注"
|
||||
},
|
||||
"action": {
|
||||
"bookmark": "收藏",
|
||||
"boost": "转发",
|
||||
"compose": "撰写",
|
||||
"enter_app": "进入应用",
|
||||
"favourite": "喜欢",
|
||||
"more": "更多",
|
||||
"publish": "发布!",
|
||||
"reply": "回复",
|
||||
"save_changes": "保存更改",
|
||||
"sign_in": "登录"
|
||||
},
|
||||
"app_name": "鹿鸣",
|
||||
"command": {
|
||||
"activate": "执行",
|
||||
"complete": "完成"
|
||||
},
|
||||
"common": {
|
||||
"end_of_list": "列表到底啦",
|
||||
"error": "错误",
|
||||
"not_found": "无法找到相关内容"
|
||||
},
|
||||
"error": {
|
||||
"account_not_found": "未找到用户 {0}"
|
||||
},
|
||||
"feature_flag": {
|
||||
"virtual_scroll": "虚拟滚动"
|
||||
},
|
||||
"menu": {
|
||||
"block_account": "拉黑 {0}",
|
||||
"block_domain": "拉黑域名 {0}",
|
||||
"copy_link_to_post": "复制这篇文章的链接",
|
||||
"delete": "删除",
|
||||
"delete_and_redraft": "删除并重新编辑",
|
||||
"direct_message_account": "私信 {0}",
|
||||
"edit": "编辑",
|
||||
"mention_account": "提及 {0}",
|
||||
"mute_account": "屏蔽 {0}",
|
||||
"open_in_original_site": "从源站打开",
|
||||
"pin_on_profile": "钉选在个人资料上",
|
||||
"show_untranslated": "显示原文",
|
||||
"translate_post": "翻译帖子",
|
||||
"unblock_account": "解除拉黑 {0}",
|
||||
"unblock_domain": "解除拉黑域名 {0}",
|
||||
"unmute_account": "解除屏蔽 {0}"
|
||||
"unmute_account": "解除屏蔽 {0}",
|
||||
"unpin_on_profile": "取消钉选"
|
||||
},
|
||||
"nav_footer": {
|
||||
"select_feature_flags": "功能开关",
|
||||
|
@ -68,12 +89,21 @@
|
|||
"request_to_follow": "请求关注你",
|
||||
"update_status": "更新了他们的状态"
|
||||
},
|
||||
"placeholder": {
|
||||
"default_1": "在想些什么?",
|
||||
"reply_to_account": "回复 {0}",
|
||||
"the_thread": "这个帖子"
|
||||
},
|
||||
"state": {
|
||||
"edited": "(已编辑)",
|
||||
"editing": "编辑中",
|
||||
"loading": "加载中...",
|
||||
"uploading": "上传中..."
|
||||
},
|
||||
"tab": {
|
||||
"media": "媒体",
|
||||
"notifications_all": "全部",
|
||||
"notifications_mention": "提及",
|
||||
"posts": "帖文",
|
||||
"posts_with_replies": "帖文与留言"
|
||||
},
|
||||
|
@ -89,5 +119,19 @@
|
|||
"add_media": "添加图片、视频或者音频文件",
|
||||
"change_content_visibility": "修改内容是否可见",
|
||||
"toggle_code_block": "切换代码块"
|
||||
},
|
||||
"user": {
|
||||
"add_existing": "添加现有帐户",
|
||||
"sign_out_account": "登出 {0}"
|
||||
},
|
||||
"visibility": {
|
||||
"direct": "私信",
|
||||
"direct_desc": "仅对提及的用户可见",
|
||||
"private": "仅限关注者",
|
||||
"private_desc": "仅关注者可见",
|
||||
"public": "公开",
|
||||
"public_desc": "所有人可见",
|
||||
"unlisted": "不列出",
|
||||
"unlisted_desc": "对所有人可见,但不出现在公共时间线上"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,25 @@ definePageMeta({
|
|||
|
||||
const { t } = useI18n()
|
||||
|
||||
const tabNames = ['All', 'Mentions'] as const
|
||||
const tab = $(useLocalStorage<typeof tabNames[number]>(STORAGE_KEY_NOTIFY_TAB, 'All'))
|
||||
const paginatorAll = useMasto().notifications.getIterator()
|
||||
const paginatorMention = useMasto().notifications.getIterator({ types: ['mention'] })
|
||||
|
||||
const paginator = $computed(() => {
|
||||
return useMasto().notifications.getIterator(tab === 'All' ? undefined : { types: ['mention'] })
|
||||
})
|
||||
const tabs = $computed(() => [
|
||||
{
|
||||
name: 'all',
|
||||
display: t('tab.notifications_all'),
|
||||
paginator: paginatorAll,
|
||||
},
|
||||
{
|
||||
name: 'mention',
|
||||
display: t('tab.notifications_mention'),
|
||||
paginator: paginatorMention,
|
||||
},
|
||||
] as const)
|
||||
|
||||
// Don't use local storage because it is better to default to Posts every time you visit a user's profile.
|
||||
const tab = $ref(tabs[0].name)
|
||||
const paginator = $computed(() => tabs.find(t => t.name === tab)!.paginator)
|
||||
|
||||
useHeadFixed({
|
||||
title: () => t('nav_side.notifications'),
|
||||
|
@ -29,7 +42,7 @@ useHeadFixed({
|
|||
</template>
|
||||
|
||||
<template #header>
|
||||
<CommonTabs v-model="tab" :options="tabNames" />
|
||||
<CommonTabs v-model="tab" :options="tabs" />
|
||||
</template>
|
||||
<slot>
|
||||
<NotificationPaginator :key="tab" :paginator="paginator" />
|
||||
|
|
Loading…
Reference in a new issue