mirror of
https://github.com/elk-zone/elk.git
synced 2024-11-22 09:25:24 +03:00
feat(i18n): Emojimart localization and fetching
entry at en
… (#1731)
Co-authored-by: userquin <userquin@gmail.com>
This commit is contained in:
parent
3118ed6012
commit
0fdbb17591
11 changed files with 94 additions and 9 deletions
|
@ -1,4 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import importEmojiLang from 'virtual:emoji-mart-lang-importer'
|
||||||
import type { Picker } from 'emoji-mart'
|
import type { Picker } from 'emoji-mart'
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -6,12 +7,15 @@ const emit = defineEmits<{
|
||||||
(e: 'selectCustom', image: any): void
|
(e: 'selectCustom', image: any): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const { locale } = useI18n()
|
||||||
|
|
||||||
const el = $ref<HTMLElement>()
|
const el = $ref<HTMLElement>()
|
||||||
let picker = $ref<Picker>()
|
let picker = $ref<Picker>()
|
||||||
const colorMode = useColorMode()
|
const colorMode = useColorMode()
|
||||||
|
|
||||||
async function openEmojiPicker() {
|
async function openEmojiPicker() {
|
||||||
await updateCustomEmojis()
|
await updateCustomEmojis()
|
||||||
|
|
||||||
if (picker) {
|
if (picker) {
|
||||||
picker.update({
|
picker.update({
|
||||||
theme: colorMode.value,
|
theme: colorMode.value,
|
||||||
|
@ -19,10 +23,14 @@ async function openEmojiPicker() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const promise = import('@emoji-mart/data/sets/14/twitter.json').then(r => r.default)
|
const [Picker, dataPromise, i18n] = await Promise.all([
|
||||||
const { Picker } = await import('emoji-mart')
|
import('emoji-mart').then(({ Picker }) => Picker),
|
||||||
|
import('@emoji-mart/data/sets/14/twitter.json').then((r: any) => r.default).catch(() => {}),
|
||||||
|
importEmojiLang(locale.value.split('-')[0]),
|
||||||
|
])
|
||||||
|
|
||||||
picker = new Picker({
|
picker = new Picker({
|
||||||
data: () => promise,
|
data: () => dataPromise,
|
||||||
onEmojiSelect({ native, src, alt, name }: any) {
|
onEmojiSelect({ native, src, alt, name }: any) {
|
||||||
native
|
native
|
||||||
? emit('select', native)
|
? emit('select', native)
|
||||||
|
@ -31,6 +39,7 @@ async function openEmojiPicker() {
|
||||||
set: 'twitter',
|
set: 'twitter',
|
||||||
theme: colorMode.value,
|
theme: colorMode.value,
|
||||||
custom: customEmojisData.value,
|
custom: customEmojisData.value,
|
||||||
|
i18n,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
await nextTick()
|
await nextTick()
|
||||||
|
|
|
@ -43,7 +43,7 @@ const chooseIcon = (i: number, text: string) => {
|
||||||
<div flex="~ col gap4">
|
<div flex="~ col gap4">
|
||||||
<div v-for="i in fieldCount" :key="i" flex="~ gap3" items-center>
|
<div v-for="i in fieldCount" :key="i" flex="~ gap3" items-center>
|
||||||
<CommonDropdown ref="dropdown" placement="left">
|
<CommonDropdown ref="dropdown" placement="left">
|
||||||
<CommonTooltip content="Pick a icon">
|
<CommonTooltip :content="$t('tooltip.pick_an_icon')">
|
||||||
<button type="button" btn-action-icon>
|
<button type="button" btn-action-icon>
|
||||||
<div :class="fieldIcons[i - 1] || 'i-ri:question-mark'" />
|
<div :class="fieldIcons[i - 1] || 'i-ri:question-mark'" />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -83,7 +83,7 @@ defineExpose({
|
||||||
<template v-if="isPending">
|
<template v-if="isPending">
|
||||||
<div flex gap-1 items-center p2 animate-pulse>
|
<div flex gap-1 items-center p2 animate-pulse>
|
||||||
<div i-ri:loader-2-line animate-spin />
|
<div i-ri:loader-2-line animate-spin />
|
||||||
<span>Fetching...</span>
|
<span>{{ $t('common.fetching') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="items.length">
|
<template v-if="items.length">
|
||||||
|
|
|
@ -52,7 +52,7 @@ defineExpose({
|
||||||
<div animate-spin preserve-3d>
|
<div animate-spin preserve-3d>
|
||||||
<div i-ri:loader-2-line />
|
<div i-ri:loader-2-line />
|
||||||
</div>
|
</div>
|
||||||
<span>Fetching...</span>
|
<span>{{ $t('common.fetching') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="items.length">
|
<template v-if="items.length">
|
||||||
|
|
|
@ -52,7 +52,7 @@ defineExpose({
|
||||||
<div animate-spin preserve-3d>
|
<div animate-spin preserve-3d>
|
||||||
<div i-ri:loader-2-line />
|
<div i-ri:loader-2-line />
|
||||||
</div>
|
</div>
|
||||||
<span>Fetching...</span>
|
<span>{{ $t('common.fetching') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="items.length">
|
<template v-if="items.length">
|
||||||
|
|
3
emoji-mart-traslation.d.ts
vendored
Normal file
3
emoji-mart-traslation.d.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
declare module 'virtual:emoji-mart-lang-importer' {
|
||||||
|
export default function(lang: string): Promise<any>
|
||||||
|
}
|
|
@ -95,6 +95,7 @@
|
||||||
"common": {
|
"common": {
|
||||||
"end_of_list": "End of the list",
|
"end_of_list": "End of the list",
|
||||||
"error": "ERROR",
|
"error": "ERROR",
|
||||||
|
"fetching": "Fetching...",
|
||||||
"in": "in",
|
"in": "in",
|
||||||
"not_found": "404 Not Found",
|
"not_found": "404 Not Found",
|
||||||
"offline_desc": "Seems like you are offline. Please check your network connection."
|
"offline_desc": "Seems like you are offline. Please check your network connection."
|
||||||
|
@ -563,6 +564,7 @@
|
||||||
"explore_posts_intro": "These posts from this and other servers in the decentralized network are gaining traction on this server right now.",
|
"explore_posts_intro": "These posts from this and other servers in the decentralized network are gaining traction on this server right now.",
|
||||||
"explore_tags_intro": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
|
"explore_tags_intro": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
|
||||||
"open_editor_tools": "Editor tools",
|
"open_editor_tools": "Editor tools",
|
||||||
|
"pick_an_icon": "Pick an icon",
|
||||||
"publish_failed": "Close failed messages at the top of editor to republish posts",
|
"publish_failed": "Close failed messages at the top of editor to republish posts",
|
||||||
"toggle_bold": "Toggle bold",
|
"toggle_bold": "Toggle bold",
|
||||||
"toggle_code_block": "Toggle code block",
|
"toggle_code_block": "Toggle code block",
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"end_of_list": "Fin de la lista",
|
"end_of_list": "Fin de la lista",
|
||||||
|
"fetching": "Listando...",
|
||||||
"offline_desc": "No tienes acceso a internet. Por favor, comprueba que tienes una conexión a la red."
|
"offline_desc": "No tienes acceso a internet. Por favor, comprueba que tienes una conexión a la red."
|
||||||
},
|
},
|
||||||
"confirm": {
|
"confirm": {
|
||||||
|
@ -150,7 +151,8 @@
|
||||||
"under_construction": "En desarrollo"
|
"under_construction": "En desarrollo"
|
||||||
},
|
},
|
||||||
"preferences": {
|
"preferences": {
|
||||||
"grayscale_mode": "Tema en escala de grises"
|
"grayscale_mode": "Tema en escala de grises",
|
||||||
|
"hide_username_emojis_description": "Oculta, de la historia, los emojis en los nombres de usuario. Los emojis seguirán visibles en los perfiles."
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"appearance": {
|
"appearance": {
|
||||||
|
@ -183,6 +185,7 @@
|
||||||
},
|
},
|
||||||
"tooltip": {
|
"tooltip": {
|
||||||
"add_emojis": "Insertar emoji",
|
"add_emojis": "Insertar emoji",
|
||||||
|
"add_media": "Insertar imágenes, un video o archivos de audio",
|
||||||
"change_content_visibility": "Cambiar visibilidad"
|
"change_content_visibility": "Cambiar visibilidad"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
|
|
|
@ -95,6 +95,7 @@
|
||||||
"common": {
|
"common": {
|
||||||
"end_of_list": "Fin",
|
"end_of_list": "Fin",
|
||||||
"error": "ERROR",
|
"error": "ERROR",
|
||||||
|
"fetching": "Cargando...",
|
||||||
"in": "en",
|
"in": "en",
|
||||||
"not_found": "404 No Encontrado",
|
"not_found": "404 No Encontrado",
|
||||||
"offline_desc": "Al parecer no tienes conexión a internet. Por favor, comprueba tu conexión a la red."
|
"offline_desc": "Al parecer no tienes conexión a internet. Por favor, comprueba tu conexión a la red."
|
||||||
|
@ -413,7 +414,7 @@
|
||||||
"hide_reply_count": "Ocultar número de respuestas",
|
"hide_reply_count": "Ocultar número de respuestas",
|
||||||
"hide_translation": "Ocultar traducción",
|
"hide_translation": "Ocultar traducción",
|
||||||
"hide_username_emojis": "Ocultar emojis en el nombre de usuario",
|
"hide_username_emojis": "Ocultar emojis en el nombre de usuario",
|
||||||
"hide_username_emojis_description": "Se ocultan los emojis en el nombre de usuario en las líneas de tiempo. Los emojis seguirán siendo visibles en sus perfiles.",
|
"hide_username_emojis_description": "Oculta los emojis de los nombres de usuarios en la línea de tiempo. Los emojis permanecerán visibles en sus perfiles.",
|
||||||
"label": "Preferencias",
|
"label": "Preferencias",
|
||||||
"title": "Funcionalidades experimentales",
|
"title": "Funcionalidades experimentales",
|
||||||
"user_picker": "Selector de usuarios",
|
"user_picker": "Selector de usuarios",
|
||||||
|
@ -428,6 +429,8 @@
|
||||||
"label": "Apariencia",
|
"label": "Apariencia",
|
||||||
"profile_metadata": "Metadatos de perfil",
|
"profile_metadata": "Metadatos de perfil",
|
||||||
"profile_metadata_desc": "Puede mostrar hasta 4 elementos en forma de tabla en tu perfil",
|
"profile_metadata_desc": "Puede mostrar hasta 4 elementos en forma de tabla en tu perfil",
|
||||||
|
"profile_metadata_label": "Texto",
|
||||||
|
"profile_metadata_value": "Contenido",
|
||||||
"title": "Editar perfil"
|
"title": "Editar perfil"
|
||||||
},
|
},
|
||||||
"featured_tags": {
|
"featured_tags": {
|
||||||
|
@ -559,6 +562,7 @@
|
||||||
"explore_posts_intro": "Estos mensajes de este y otros servidores de la red descentralizada están siendo tendencia ahora mismo en este servidor.",
|
"explore_posts_intro": "Estos mensajes de este y otros servidores de la red descentralizada están siendo tendencia ahora mismo en este servidor.",
|
||||||
"explore_tags_intro": "Estas etiquetas están siendo tendencia ahora mismo entre los usuarios de este y otros servidores de la red descentralizada.",
|
"explore_tags_intro": "Estas etiquetas están siendo tendencia ahora mismo entre los usuarios de este y otros servidores de la red descentralizada.",
|
||||||
"open_editor_tools": "Herramientas de edición",
|
"open_editor_tools": "Herramientas de edición",
|
||||||
|
"pick_an_icon": "Selecciona un icono",
|
||||||
"publish_failed": "Cierra los mensajes fallidos en la parte superior del editor para volver a publicar",
|
"publish_failed": "Cierra los mensajes fallidos en la parte superior del editor para volver a publicar",
|
||||||
"toggle_bold": "Cambiar a negrita",
|
"toggle_bold": "Cambiar a negrita",
|
||||||
"toggle_code_block": "Cambiar a bloque de código",
|
"toggle_code_block": "Cambiar a bloque de código",
|
||||||
|
|
63
modules/emoji-mart-translation.ts
Normal file
63
modules/emoji-mart-translation.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import fs from 'fs-extra'
|
||||||
|
import { createResolver, defineNuxtModule } from '@nuxt/kit'
|
||||||
|
import { i18n } from '../config/i18n'
|
||||||
|
import type { LocaleObject } from '#i18n'
|
||||||
|
|
||||||
|
const virtual = 'virtual:emoji-mart-lang-importer'
|
||||||
|
const resolvedVirtual = `\0${virtual}.mjs`
|
||||||
|
|
||||||
|
export default defineNuxtModule({
|
||||||
|
meta: {
|
||||||
|
name: 'emoji-mark-translation',
|
||||||
|
},
|
||||||
|
setup(_, nuxt) {
|
||||||
|
const resolver = createResolver(import.meta.url)
|
||||||
|
nuxt.hook('vite:extendConfig', async (viteInlineConfig) => {
|
||||||
|
viteInlineConfig.plugins = viteInlineConfig.plugins || []
|
||||||
|
viteInlineConfig.plugins.push({
|
||||||
|
name: 'vite-emoji-mart-translation',
|
||||||
|
enforce: 'pre',
|
||||||
|
resolveId(id) {
|
||||||
|
if (id === virtual)
|
||||||
|
return resolvedVirtual
|
||||||
|
},
|
||||||
|
async load(id) {
|
||||||
|
if (id === resolvedVirtual) {
|
||||||
|
const locales = await Promise.all(
|
||||||
|
Array
|
||||||
|
.from(new Set((i18n.locales as LocaleObject[]).map(l => l.code.split('-')[0])))
|
||||||
|
.map(async (l) => {
|
||||||
|
const exists = await isFile(resolver.resolve(`../node_modules/@emoji-mart/data/i18n/${l}.json`))
|
||||||
|
return [l, exists] as [code: string, exists: boolean]
|
||||||
|
}))
|
||||||
|
.then(l => l.filter(l => l[1]).map(l => l[0]))
|
||||||
|
const switchStmt = locales.filter(l => l[1]).map((l) => {
|
||||||
|
return `
|
||||||
|
case "${l}":
|
||||||
|
return import("@emoji-mart/data/i18n/${l}.json").catch(() => {});`
|
||||||
|
})
|
||||||
|
return `export default function(lang) {
|
||||||
|
switch(lang) {
|
||||||
|
${switchStmt.join('')}
|
||||||
|
default:
|
||||||
|
return import("@emoji-mart/data/i18n/en.json").catch(() => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
async function isFile(path: string) {
|
||||||
|
return new Promise<boolean>((resolve) => {
|
||||||
|
fs.lstat(path, (err, stats) => {
|
||||||
|
if (err)
|
||||||
|
resolve(false)
|
||||||
|
else
|
||||||
|
resolve(stats.isFile())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ export default defineNuxtConfig({
|
||||||
'@nuxtjs/color-mode',
|
'@nuxtjs/color-mode',
|
||||||
'nuxt-vitest',
|
'nuxt-vitest',
|
||||||
...(isDevelopment || isWindows) ? [] : ['nuxt-security'],
|
...(isDevelopment || isWindows) ? [] : ['nuxt-security'],
|
||||||
|
'~/modules/emoji-mart-translation',
|
||||||
'~/modules/purge-comments',
|
'~/modules/purge-comments',
|
||||||
'~/modules/setup-components',
|
'~/modules/setup-components',
|
||||||
'~/modules/build-env',
|
'~/modules/build-env',
|
||||||
|
|
Loading…
Reference in a new issue