Browse Source

Merge pull request #4390 from nocodb/fix/rtl-style

fix(nc-gui): apply ltr/rtl direction on language switch
pull/4297/merge
navi 2 years ago committed by GitHub
parent
commit
393e8be645
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      packages/nc-gui/components/general/language/Menu.vue
  2. 23
      packages/nc-gui/components/smartsheet/toolbar/ShareView.vue
  3. 1
      packages/nc-gui/lib/types.ts
  4. 8
      packages/nc-gui/pages/[projectType]/form/[viewId].vue
  5. 5
      packages/nc-gui/plugins/a.i18n.ts
  6. 14
      packages/nc-gui/utils/viewUtils.ts

19
packages/nc-gui/components/general/language/Menu.vue

@ -1,6 +1,6 @@
<script lang="ts" setup>
import { Language } from '~/lib'
import { onMounted, useGlobal, useI18n, useNuxtApp } from '#imports'
import { useGlobal, useI18n, useNuxtApp } from '#imports'
import { setI18nLanguage } from '~/plugins/a.i18n'
const { $e } = useNuxtApp()
@ -11,31 +11,14 @@ const { locale } = useI18n()
const languages = $computed(() => Object.entries(Language).sort() as [keyof typeof Language, Language][])
const isRtlLang = $computed(() => ['fa', 'ar'].includes(currentLang.value))
function applyDirection() {
const targetDirection = isRtlLang ? 'rtl' : 'ltr'
const oppositeDirection = targetDirection === 'ltr' ? 'rtl' : 'ltr'
document.body.classList.remove(oppositeDirection)
document.body.classList.add(targetDirection)
document.body.style.direction = targetDirection
}
async function changeLanguage(lang: string) {
const nextLang = lang as keyof typeof Language
await setI18nLanguage(nextLang)
currentLang.value = nextLang
applyDirection()
$e('c:navbar:lang', { lang })
}
onMounted(() => {
applyDirection()
})
</script>
<template>

23
packages/nc-gui/components/smartsheet/toolbar/ShareView.vue

@ -40,6 +40,14 @@ const passwordProtected = ref(false)
const shared = ref<SharedView>({ id: '', meta: {}, password: undefined })
const withRTL = computed({
get: () => !!shared.value.meta.rtl,
set: (rtl) => {
shared.value.meta = { ...shared.value.meta, rtl }
updateSharedViewMeta()
},
})
const transitionDuration = computed({
get: () => shared.value.meta.transitionDuration || 250,
set: (duration) => {
@ -105,7 +113,7 @@ const sharedViewUrl = computed(() => {
viewType = 'view'
}
return `${dashboardUrl?.value}#/nc/${viewType}/${shared.value.uuid}`
return encodeURI(`${dashboardUrl?.value}#/nc/${viewType}/${shared.value.uuid}`)
})
async function saveAllowCSVDownload() {
@ -285,6 +293,19 @@ watch(passwordProtected, (value) => {
</Transition>
</div>
<div>
<!-- use RTL orientation in form - todo: i18n -->
<a-checkbox
v-if="shared.type === ViewTypes.FORM"
v-model:checked="withRTL"
data-testid="nc-modal-share-view__locale"
class="!text-sm"
>
<!-- todo i18n -->
RTL Orientation
</a-checkbox>
</div>
<div>
<!-- Password Protection -->
<a-checkbox

1
packages/nc-gui/lib/types.ts

@ -86,6 +86,7 @@ export interface SharedViewMeta extends Record<string, any> {
withTheme?: boolean
theme?: Partial<ThemeConfig>
allowCSVDownload?: boolean
rtl?: boolean
}
export interface SharedView {

8
packages/nc-gui/pages/[projectType]/form/[viewId].vue

@ -4,6 +4,7 @@ import {
IsPublicInj,
MetaInj,
ReloadViewDataHookInj,
applyLanguageDirection,
createError,
createEventHook,
definePageMeta,
@ -26,9 +27,8 @@ useSidebar('nc-left-sidebar', { hasSidebar: false })
const route = useRoute()
const { loadSharedView, sharedView, meta, notFound, password, passwordDlg, passwordError } = useProvideSharedFormStore(
route.params.viewId as string,
)
const { loadSharedView, sharedView, sharedViewMeta, meta, notFound, password, passwordDlg, passwordError } =
useProvideSharedFormStore(route.params.viewId as string)
await loadSharedView()
@ -39,6 +39,8 @@ if (!notFound.value) {
provide(IsFormInj, ref(true))
useProvideSmartsheetStore(sharedView, meta, true)
applyLanguageDirection(sharedViewMeta.value.rtl ? 'rtl' : 'ltr')
} else {
navigateTo('/error/404')
throw createError({ statusCode: 404, statusMessage: 'Page Not Found' })

5
packages/nc-gui/plugins/a.i18n.ts

@ -1,5 +1,6 @@
import { createI18n } from 'vue-i18n'
import { defineNuxtPlugin, nextTick } from '#imports'
import { isClient } from '@vueuse/core'
import { applyLanguageDirection, defineNuxtPlugin, isRtlLang, nextTick } from '#imports'
import type { Language, NocoI18n } from '~/lib'
import { LanguageAlias } from '~/lib'
@ -24,6 +25,8 @@ export async function setI18nLanguage(locale: keyof typeof Language, i18n = glob
}
i18n.global.locale.value = locale
if (isClient) applyLanguageDirection(isRtlLang(locale) ? 'rtl' : 'ltr')
}
export async function loadLocaleMessages(

14
packages/nc-gui/utils/viewUtils.ts

@ -7,6 +7,7 @@ import MdiCalendarIcon from '~icons/mdi/calendar'
import MdiGalleryIcon from '~icons/mdi/camera-image'
import MdiKanbanIcon from '~icons/mdi/tablet-dashboard'
import MdiEyeIcon from '~icons/mdi/eye-circle-outline'
import type { Language } from '~/lib'
export const viewIcons: Record<number | string, { icon: any; color: string }> = {
[ViewTypes.GRID]: { icon: MdiGridIcon, color: '#8f96f2' },
@ -23,3 +24,16 @@ export const viewTypeAlias: Record<number, string> = {
[ViewTypes.GALLERY]: 'gallery',
[ViewTypes.KANBAN]: 'kanban',
}
export const isRtlLang = (lang: keyof typeof Language) => ['fa', 'ar'].includes(lang)
const rtl = 'rtl' as const
const ltr = 'ltr' as const
export function applyLanguageDirection(dir: typeof rtl | typeof ltr) {
const oppositeDirection = dir === ltr ? rtl : ltr
document.body.classList.remove(oppositeDirection)
document.body.classList.add(dir)
document.body.style.direction = dir
}

Loading…
Cancel
Save