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
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import importEmojiLang from 'virtual:emoji-mart-lang-importer'
|
||||
import type { Picker } from 'emoji-mart'
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -6,12 +7,15 @@ const emit = defineEmits<{
|
|||
(e: 'selectCustom', image: any): void
|
||||
}>()
|
||||
|
||||
const { locale } = useI18n()
|
||||
|
||||
const el = $ref<HTMLElement>()
|
||||
let picker = $ref<Picker>()
|
||||
const colorMode = useColorMode()
|
||||
|
||||
async function openEmojiPicker() {
|
||||
await updateCustomEmojis()
|
||||
|
||||
if (picker) {
|
||||
picker.update({
|
||||
theme: colorMode.value,
|
||||
|
@ -19,10 +23,14 @@ async function openEmojiPicker() {
|
|||
})
|
||||
}
|
||||
else {
|
||||
const promise = import('@emoji-mart/data/sets/14/twitter.json').then(r => r.default)
|
||||
const { Picker } = await import('emoji-mart')
|
||||
const [Picker, dataPromise, i18n] = await Promise.all([
|
||||
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({
|
||||
data: () => promise,
|
||||
data: () => dataPromise,
|
||||
onEmojiSelect({ native, src, alt, name }: any) {
|
||||
native
|
||||
? emit('select', native)
|
||||
|
@ -31,6 +39,7 @@ async function openEmojiPicker() {
|
|||
set: 'twitter',
|
||||
theme: colorMode.value,
|
||||
custom: customEmojisData.value,
|
||||
i18n,
|
||||
})
|
||||
}
|
||||
await nextTick()
|
||||
|
|
|
@ -43,7 +43,7 @@ const chooseIcon = (i: number, text: string) => {
|
|||
<div flex="~ col gap4">
|
||||
<div v-for="i in fieldCount" :key="i" flex="~ gap3" items-center>
|
||||
<CommonDropdown ref="dropdown" placement="left">
|
||||
<CommonTooltip content="Pick a icon">
|
||||
<CommonTooltip :content="$t('tooltip.pick_an_icon')">
|
||||
<button type="button" btn-action-icon>
|
||||
<div :class="fieldIcons[i - 1] || 'i-ri:question-mark'" />
|
||||
</button>
|
||||
|
|
|
@ -83,7 +83,7 @@ defineExpose({
|
|||
<template v-if="isPending">
|
||||
<div flex gap-1 items-center p2 animate-pulse>
|
||||
<div i-ri:loader-2-line animate-spin />
|
||||
<span>Fetching...</span>
|
||||
<span>{{ $t('common.fetching') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="items.length">
|
||||
|
|
|
@ -52,7 +52,7 @@ defineExpose({
|
|||
<div animate-spin preserve-3d>
|
||||
<div i-ri:loader-2-line />
|
||||
</div>
|
||||
<span>Fetching...</span>
|
||||
<span>{{ $t('common.fetching') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="items.length">
|
||||
|
|
|
@ -52,7 +52,7 @@ defineExpose({
|
|||
<div animate-spin preserve-3d>
|
||||
<div i-ri:loader-2-line />
|
||||
</div>
|
||||
<span>Fetching...</span>
|
||||
<span>{{ $t('common.fetching') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<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": {
|
||||
"end_of_list": "End of the list",
|
||||
"error": "ERROR",
|
||||
"fetching": "Fetching...",
|
||||
"in": "in",
|
||||
"not_found": "404 Not Found",
|
||||
"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_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",
|
||||
"pick_an_icon": "Pick an icon",
|
||||
"publish_failed": "Close failed messages at the top of editor to republish posts",
|
||||
"toggle_bold": "Toggle bold",
|
||||
"toggle_code_block": "Toggle code block",
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
},
|
||||
"common": {
|
||||
"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."
|
||||
},
|
||||
"confirm": {
|
||||
|
@ -150,7 +151,8 @@
|
|||
"under_construction": "En desarrollo"
|
||||
},
|
||||
"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": {
|
||||
"appearance": {
|
||||
|
@ -183,6 +185,7 @@
|
|||
},
|
||||
"tooltip": {
|
||||
"add_emojis": "Insertar emoji",
|
||||
"add_media": "Insertar imágenes, un video o archivos de audio",
|
||||
"change_content_visibility": "Cambiar visibilidad"
|
||||
},
|
||||
"user": {
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
"common": {
|
||||
"end_of_list": "Fin",
|
||||
"error": "ERROR",
|
||||
"fetching": "Cargando...",
|
||||
"in": "en",
|
||||
"not_found": "404 No Encontrado",
|
||||
"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_translation": "Ocultar traducción",
|
||||
"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",
|
||||
"title": "Funcionalidades experimentales",
|
||||
"user_picker": "Selector de usuarios",
|
||||
|
@ -428,6 +429,8 @@
|
|||
"label": "Apariencia",
|
||||
"profile_metadata": "Metadatos de 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"
|
||||
},
|
||||
"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_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",
|
||||
"pick_an_icon": "Selecciona un icono",
|
||||
"publish_failed": "Cierra los mensajes fallidos en la parte superior del editor para volver a publicar",
|
||||
"toggle_bold": "Cambiar a negrita",
|
||||
"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',
|
||||
'nuxt-vitest',
|
||||
...(isDevelopment || isWindows) ? [] : ['nuxt-security'],
|
||||
'~/modules/emoji-mart-translation',
|
||||
'~/modules/purge-comments',
|
||||
'~/modules/setup-components',
|
||||
'~/modules/build-env',
|
||||
|
|
Loading…
Reference in a new issue