i18n: improve translations

This commit is contained in:
Anthony Fu 2022-11-30 07:25:29 +08:00
parent acdd33ef7d
commit ccffe9daa8
15 changed files with 231 additions and 143 deletions

1
.eslintignore Normal file
View file

@ -0,0 +1 @@
*.css

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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)"

View file

@ -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">

View file

@ -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>

View file

@ -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

View file

@ -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,
}),
}

View file

@ -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)) : ''

View file

@ -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"
}
}

View file

@ -1,94 +1,93 @@
{
"account": {
"blocked_domains": "Dominios bloqueados",
"blocked_users": "Usuarios bloqueados",
"favourites": "Favoritos",
"follow": "Seguir",
"follow_back": "Seguir de vuelta",
"follow_requested": "Enviado",
"followers_count": "{0} Seguidores",
"following_count": "{0} Siguiendo",
"follows_you": "Te sigue",
"muted_users": "Usuarios silenciados",
"pinned": "Pinned",
"posts_count": "{0} Posts",
"unfollow": "Dejar de seguir"
},
"action": {
"compose": "Componer",
"enter_app": "Entrar",
"publish": "¡Publicar!",
"save_changes": "Guardar",
"sign_in": "Iniciar sesión"
},
"common": {
"end_of_list": "Final",
"error": "ERROR",
"not_found": "404 No Encontrado"
},
"feature_flag": {
"virtual_scroll": "Virtual Scrolling"
},
"menu": {
"block_account": "Bloqueados {0}",
"block_domain": "Dominios bloqueado/s {0}",
"direct_message_account": "Mensaje Directo {0}",
"mention_account": "Mención {0}",
"mute_account": "Silenciados {0}",
"open_in_original_site": "Abrir original",
"unblock_account": "Desbloqueado/s {0}",
"unblock_domain": "Dominios desbloqueados {0}",
"unmute_account": "No silenciados {0}"
},
"nav_footer": {
"select_feature_flags": "Cambiar Feature Flags",
"select_language": "Seleccionar Lenguaje",
"toggle_theme": "Cambiar Tema",
"zen_mode": "Modo Zen"
},
"nav_side": {
"bookmarks": "Bookmarks",
"conversations": "Conversaciones",
"explore": "Explorar",
"favourites": "Favoritos",
"federated": "Federados",
"home": "Home",
"local": "Local",
"notifications": "Notificaciones",
"profile": "Perfil"
},
"nav_user": {
"sign_in_desc": "Inicia sesión para seguir perfiles o hashtags, marcar como favorito, compartir and responder a publicaciones, or interactuar desde tu usuario con un servidor diferente."
},
"notification": {
"favourited_post": "tu post fue marcado como favorito",
"followed_you": "te ha seguido",
"missing_type": "MISSING notification.type:",
"reblogged_post": "reblogged your post",
"request_to_follow": "ha solicitado seguirte",
"update_status": "ha actualizado su estado"
},
"state": {
"editing": "Editando",
"uploading": "Subiendo..."
},
"tab": {
"media": "Media",
"posts": "Publicaciones",
"posts_with_replies": "Publicaciones y respuestas"
},
"timeline": {
"show_new_items": "Muestra {0} nuevos artículos"
},
"title": {
"federated_timeline": "Timeline Federada",
"local_timeline": "Timeline Local"
},
"tooltip": {
"add_content_warning": "Añadir advertencia",
"add_media": "Añadir imágenes, arhivos de video o audio",
"change_content_visibility": "Cambiar visibilidad",
"toggle_code_block": "Toggle code block"
}
"account": {
"blocked_domains": "Dominios bloqueados",
"blocked_users": "Usuarios bloqueados",
"favourites": "Favoritos",
"follow": "Seguir",
"follow_back": "Seguir de vuelta",
"follow_requested": "Enviado",
"followers_count": "{0} Seguidores",
"following_count": "{0} Siguiendo",
"follows_you": "Te sigue",
"muted_users": "Usuarios silenciados",
"pinned": "Pinned",
"posts_count": "{0} Posts",
"unfollow": "Dejar de seguir"
},
"action": {
"compose": "Componer",
"enter_app": "Entrar",
"publish": "¡Publicar!",
"save_changes": "Guardar",
"sign_in": "Iniciar sesión"
},
"common": {
"end_of_list": "Final",
"error": "ERROR",
"not_found": "404 No Encontrado"
},
"feature_flag": {
"virtual_scroll": "Virtual Scrolling"
},
"menu": {
"block_account": "Bloqueados {0}",
"block_domain": "Dominios bloqueado/s {0}",
"direct_message_account": "Mensaje Directo {0}",
"mention_account": "Mención {0}",
"mute_account": "Silenciados {0}",
"open_in_original_site": "Abrir original",
"unblock_account": "Desbloqueado/s {0}",
"unblock_domain": "Dominios desbloqueados {0}",
"unmute_account": "No silenciados {0}"
},
"nav_footer": {
"select_feature_flags": "Cambiar Feature Flags",
"select_language": "Seleccionar Lenguaje",
"toggle_theme": "Cambiar Tema",
"zen_mode": "Modo Zen"
},
"nav_side": {
"bookmarks": "Bookmarks",
"conversations": "Conversaciones",
"explore": "Explorar",
"favourites": "Favoritos",
"federated": "Federados",
"home": "Home",
"local": "Local",
"notifications": "Notificaciones",
"profile": "Perfil"
},
"nav_user": {
"sign_in_desc": "Inicia sesión para seguir perfiles o hashtags, marcar como favorito, compartir and responder a publicaciones, or interactuar desde tu usuario con un servidor diferente."
},
"notification": {
"favourited_post": "tu post fue marcado como favorito",
"followed_you": "te ha seguido",
"missing_type": "MISSING notification.type:",
"reblogged_post": "reblogged your post",
"request_to_follow": "ha solicitado seguirte",
"update_status": "ha actualizado su estado"
},
"state": {
"editing": "Editando",
"uploading": "Subiendo..."
},
"tab": {
"media": "Media",
"posts": "Publicaciones",
"posts_with_replies": "Publicaciones y respuestas"
},
"timeline": {
"show_new_items": "Muestra {0} nuevos artículos"
},
"title": {
"federated_timeline": "Timeline Federada",
"local_timeline": "Timeline Local"
},
"tooltip": {
"add_content_warning": "Añadir advertencia",
"add_media": "Añadir imágenes, arhivos de video o audio",
"change_content_visibility": "Cambiar visibilidad",
"toggle_code_block": "Toggle code block"
}
}

View file

@ -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": "警告を追加",

View file

@ -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": "对所有人可见,但不出现在公共时间线上"
}
}

View file

@ -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" />