From 0876f192fa16cc71f24e1a39327a536a5b2f5a35 Mon Sep 17 00:00:00 2001 From: iliya Date: Mon, 23 Mar 2026 20:18:02 +0200 Subject: [PATCH] feat(landing): enhance localization and improve UI components - Added support for German (de), French (fr), and Japanese (ja) languages, expanding the localization capabilities of the application. - Updated the LanguageSwitcher component to include new language options and a search feature for better user experience. - Enhanced the HeroSection with dynamic download URLs and a release version badge for improved visibility of updates. - Refactored the ScreenshotsSection to utilize a new data structure for screenshots, improving maintainability and performance. - Improved the styling of various components, including the addition of search functionality in the LanguageSwitcher and adjustments to the layout of the HeroSection. - Fixed type handling in several components to ensure better TypeScript compatibility and reduce potential runtime errors. --- .../components/layout/LanguageSwitcher.vue | 134 +++++++++++++++--- .../components/sections/DownloadSection.vue | 26 ++-- .../components/sections/FeaturesSection.vue | 2 +- landing/components/sections/HeroSection.vue | 49 ++++++- .../sections/ScreenshotsSection.vue | 22 +-- .../sections/TestimonialsSection.vue | 2 +- landing/composables/useLocation.ts | 2 +- landing/composables/usePageSeo.ts | 4 +- landing/content/de.json | 102 +++++++++++++ landing/content/fr.json | 102 +++++++++++++ landing/content/ja.json | 102 +++++++++++++ landing/data/content.ts | 8 +- landing/data/i18n.ts | 5 +- landing/data/screenshots.ts | 22 +++ landing/locales/ar.json | 5 +- landing/locales/de.json | 113 +++++++++++++++ landing/locales/en.json | 5 +- landing/locales/es.json | 5 +- landing/locales/fr.json | 113 +++++++++++++++ landing/locales/hi.json | 5 +- landing/locales/ja.json | 113 +++++++++++++++ landing/locales/pt.json | 5 +- landing/locales/ru.json | 5 +- landing/locales/zh.json | 5 +- landing/nuxt.config.ts | 8 +- landing/server/routes/robots.txt.ts | 11 ++ landing/server/routes/sitemap.xml.ts | 32 +++++ 27 files changed, 942 insertions(+), 65 deletions(-) create mode 100644 landing/content/de.json create mode 100644 landing/content/fr.json create mode 100644 landing/content/ja.json create mode 100644 landing/data/screenshots.ts create mode 100644 landing/locales/de.json create mode 100644 landing/locales/fr.json create mode 100644 landing/locales/ja.json create mode 100644 landing/server/routes/robots.txt.ts create mode 100644 landing/server/routes/sitemap.xml.ts diff --git a/landing/components/layout/LanguageSwitcher.vue b/landing/components/layout/LanguageSwitcher.vue index a00ac10d..13826664 100644 --- a/landing/components/layout/LanguageSwitcher.vue +++ b/landing/components/layout/LanguageSwitcher.vue @@ -23,6 +23,9 @@ const flagIconMap: Record = { hi: "circle-flags:in", ar: "circle-flags:sa", pt: "circle-flags:br", + fr: "circle-flags:fr", + ja: "circle-flags:jp", + de: "circle-flags:de", ru: "circle-flags:ru" }; @@ -43,6 +46,25 @@ const currentFlagIcon = computed(() => { }); const iconMenuOpen = ref(false); +const searchQuery = ref(""); +const searchInputRef = ref(null); + +const filteredDropdownItems = computed(() => { + const q = searchQuery.value.toLowerCase().trim(); + if (!q) return dropdownItems.value; + return dropdownItems.value.filter( + (item) => + item.title.toLowerCase().includes(q) || + item.value.toLowerCase().includes(q) + ); +}); + +watch(iconMenuOpen, (open) => { + if (open) { + searchQuery.value = ""; + nextTick(() => searchInputRef.value?.focus()); + } +}); const { trackLanguageSwitch } = useAnalytics(); @@ -51,8 +73,8 @@ const onChange = async (value: string | LocaleCode) => { iconMenuOpen.value = false; trackLanguageSwitch(locale.value as string, nextLocale); localeStore.setLocale(nextLocale, true); - if (nuxtApp.$i18n?.setLocale) { - await nuxtApp.$i18n.setLocale(nextLocale); + if ((nuxtApp.$i18n as any)?.setLocale) { + await (nuxtApp.$i18n as any).setLocale(nextLocale); } else { locale.value = nextLocale; } @@ -64,27 +86,44 @@ const onChange = async (value: string | LocaleCode) => {