Skip to content

Commit df8ac88

Browse files
committed
feat(vite-vue-app): enhance example app with TypeScript support, add vue-router integration, and improve localization handling
1 parent 9e1002d commit df8ac88

24 files changed

+440
-183
lines changed

docs/en/intlayer_with_vite+vue.md

+48-78
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ useI18nHTMLAttributes();
413413
414414
To use Intlayer in your Vue application, you need to register the plugin in your main file:
415415
416-
```js fileName="src/main.js" codeFormat="javascript"
416+
```js fileName="src/main.ts"
417417
import { createApp } from "vue";
418418
import App from "./App.vue";
419419
import "./style.css";
@@ -547,104 +547,74 @@ npm install vue-router
547547

548548
Then, create a router configuration that handles locale-based routing:
549549

550-
```js fileName="src/router/index.js" codeFormat="javascript"
551-
import { createRouter, createWebHistory } from "vue-router";
552-
import { configuration, getPathWithoutLocale } from "intlayer";
553-
import HomeView from "../views/HomeView.vue";
554-
import AboutView from "../views/AboutView.vue";
550+
```js fileName="src/router/index.ts"
551+
import {
552+
configuration,
553+
getPathWithoutLocale,
554+
localeMapper,
555+
Locales,
556+
} from 'intlayer';
557+
import { createIntlayerClient } from 'vue-intlayer';
558+
import { createRouter, createWebHistory } from 'vue-router';
559+
import HomeView from './views/home/HomeView.vue';
560+
import RootView from './views/root/Root.vue';
555561

556562
// Get internationalization configuration
557563
const { internationalization, middleware } = configuration;
558-
const { locales, defaultLocale } = internationalization;
564+
const { defaultLocale } = internationalization;
559565

560-
// Define your routes without locale prefixes
561-
const routes = [
566+
const routes = localeMapper((localizedData) => [
562567
{
563-
path: "/",
564-
name: "Home",
565-
component: HomeView,
568+
path: `/${localizedData.urlPrefix}/`,
569+
name: `${localizedData.locale}-Root`,
570+
component: RootView,
571+
meta: {
572+
locale: localizedData.locale,
573+
},
566574
},
567575
{
568-
path: "/about",
569-
name: "About",
570-
component: AboutView,
576+
path: `/${localizedData.urlPrefix}/home`,
577+
name: `${localizedData.locale}-Home`,
578+
component: HomeView,
579+
meta: {
580+
locale: localizedData.locale,
581+
},
571582
},
572-
];
573-
574-
// Create a function to generate localized routes
575-
const generateLocalizedRoutes = () => {
576-
let allRoutes = [];
577-
578-
// Add locale prefix to all routes except for default locale when prefixDefault is false
579-
locales.forEach((locale) => {
580-
// Skip default locale if prefixDefault is false
581-
if (!middleware.prefixDefault && locale === defaultLocale) {
582-
return;
583-
}
584-
585-
const localizedRoutes = routes.map((route) => {
586-
return {
587-
...route,
588-
path: `/${locale}${route.path}`,
589-
meta: {
590-
...route.meta,
591-
locale,
592-
},
593-
};
594-
});
595-
596-
allRoutes = [...allRoutes, ...localizedRoutes];
597-
});
598-
599-
// If default locale is not prefixed, add routes without locale prefix
600-
if (!middleware.prefixDefault) {
601-
allRoutes = [
602-
...allRoutes,
603-
...routes.map((route) => ({
604-
...route,
605-
meta: {
606-
...route.meta,
607-
locale: defaultLocale,
608-
},
609-
})),
610-
];
611-
}
612-
613-
return allRoutes;
614-
};
583+
]);
615584

616585
// Create the router instance
617-
const router = createRouter({
586+
export const router = createRouter({
618587
history: createWebHistory(),
619-
routes: generateLocalizedRoutes(),
588+
routes: routes.flat(),
620589
});
621590

622591
// Add navigation guard for locale handling
623-
router.beforeEach((to, from, next) => {
624-
// Extract locale from the path or use default
625-
const pathSegments = to.path.split("/").filter(Boolean);
626-
const localeFromPath = pathSegments[0];
627-
628-
// Check if the path starts with a valid locale
629-
if (locales.includes(localeFromPath)) {
630-
// Valid locale in URL, proceed
631-
next();
632-
} else if (!middleware.prefixDefault) {
633-
// No locale in URL, and we don't prefix default - assume default locale
592+
router.beforeEach((to, _from, next) => {
593+
const client = createIntlayerClient();
594+
595+
const metaLocale = to.meta.locale as Locales | undefined;
596+
597+
if (metaLocale) {
598+
// Reuse the locale defined in the route meta
599+
client.setLocale(metaLocale);
634600
next();
635601
} else {
636-
// No valid locale, redirect to the path with default locale
637-
const pathWithoutLocale = getPathWithoutLocale(to.path);
638-
next(`/${defaultLocale}${pathWithoutLocale}${to.search}`);
602+
// Fallback: no locale in meta, possibly unmatched route
603+
// Optional: handle 404 or redirect to default locale
604+
client.setLocale(defaultLocale);
605+
606+
if (middleware.prefixDefault) {
607+
next(`/${defaultLocale}${getPathWithoutLocale(to.path)}`);
608+
} else {
609+
next(getPathWithoutLocale(to.path));
610+
}
639611
}
640612
});
641-
642-
export default router;
643613
```
644614

645615
Then, register the router in your main.js file:
646616

647-
```js fileName="src/main.js" codeFormat="javascript"
617+
```js fileName="src/main.ts"
648618
import { createApp } from "vue";
649619
import App from "./App.vue";
650620
import router from "./router";
@@ -723,7 +693,7 @@ watch(
723693

724694
When your application supports multiple languages, it's important to update the `<html>` tag's `lang` and `dir` attributes to match the current locale:
725695

726-
```js fileName="src/composables/useI18nHTMLAttributes.js" codeFormat="javascript"
696+
```js fileName="src/composables/useI18nHTMLAttributes.ts"
727697
import { watch } from "vue";
728698
import { useLocale } from "vue-intlayer";
729699
import { getHTMLTextDir } from "intlayer";

examples/vite-vue-app/intlayer.config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Locales, type IntlayerConfig } from 'intlayer';
55
const config: IntlayerConfig = {
66
internationalization: {
77
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
8+
defaultLocale: Locales.ENGLISH,
89
},
910
editor: {
1011
enabled: true,

examples/vite-vue-app/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"intlayer": "workspace:*",
1313
"vite-intlayer": "workspace:*",
1414
"vue": "^3.5.13",
15-
"vue-intlayer": "workspace:*"
15+
"vue-intlayer": "workspace:*",
16+
"vue-router": "^4.5.1"
1617
},
1718
"devDependencies": {
1819
"@types/node": "^22.13.10",

examples/vite-vue-app/shims-vue.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
declare module '*.vue' {
2+
import { DefineComponent } from 'vue';
3+
const component: DefineComponent<{}, {}, any>;
4+
export default component;
5+
}

examples/vite-vue-app/src/App.vue

+1-35
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,10 @@
11
<script setup>
2-
import { useIntlayer } from 'vue-intlayer';
3-
import HelloWorld from './components/HelloWorld.vue';
4-
import LocaleSwitcher from './components/LocaleSwitcher.vue';
52
import { useI18nHTMLAttributes } from './composables/useI18nHTMLAttributes';
6-
import { useLocale } from 'vue-intlayer';
7-
import { ref, watch } from 'vue';
8-
9-
const { locale, availableLocales, setLocale } = useLocale();
10-
11-
// Use the useIntlayer composable to access translations
12-
const content = useIntlayer('app');
133
144
// Apply HTML language attributes based on current locale
155
useI18nHTMLAttributes();
166
</script>
177

188
<template>
19-
<div>
20-
<LocaleSwitcher />
21-
<a href="https://vite.dev" target="_blank">
22-
<img src="/vite.svg" class="logo" :alt="content.viteLogo" />
23-
</a>
24-
<a href="https://vuejs.org/" target="_blank">
25-
<img src="./assets/vue.svg" class="logo vue" :alt="content.vueLogo" />
26-
</a>
27-
</div>
28-
<HelloWorld :msg="content.title" />
9+
<RouterView />
2910
</template>
30-
31-
<style scoped>
32-
.logo {
33-
height: 6em;
34-
padding: 1.5em;
35-
will-change: filter;
36-
transition: filter 300ms;
37-
}
38-
.logo:hover {
39-
filter: drop-shadow(0 0 2em #646cffaa);
40-
}
41-
.logo.vue:hover {
42-
filter: drop-shadow(0 0 2em #42b883aa);
43-
}
44-
</style>

examples/vite-vue-app/src/main.js renamed to examples/vite-vue-app/src/main.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import { createApp } from 'vue';
22
import { installIntlayer } from 'vue-intlayer';
33
import App from './App.vue';
4+
import { router } from './routes';
45
import './style.css';
56

67
const app = createApp(App);
78

9+
// Add the router to the app
10+
app.use(router);
11+
812
// Inject the provider at the top level
913
installIntlayer(app); // provide the singleton instance
1014

examples/vite-vue-app/src/routes.ts

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {
2+
configuration,
3+
getPathWithoutLocale,
4+
localeMapper,
5+
Locales,
6+
} from 'intlayer';
7+
import { createIntlayerClient } from 'vue-intlayer';
8+
import { createRouter, createWebHistory } from 'vue-router';
9+
import HomeView from './views/home/HomeView.vue';
10+
import RootView from './views/root/Root.vue';
11+
12+
// Get internationalization configuration
13+
const { internationalization, middleware } = configuration;
14+
const { defaultLocale } = internationalization;
15+
16+
const routes = localeMapper((localizedData) => [
17+
{
18+
path: `${localizedData.urlPrefix}/`,
19+
name: `${localizedData.locale}-Root`,
20+
component: RootView,
21+
meta: {
22+
locale: localizedData.locale,
23+
},
24+
},
25+
{
26+
path: `${localizedData.urlPrefix}/home`,
27+
name: `${localizedData.locale}-Home`,
28+
component: HomeView,
29+
meta: {
30+
locale: localizedData.locale,
31+
},
32+
},
33+
]);
34+
35+
// Create the router instance
36+
export const router = createRouter({
37+
history: createWebHistory(),
38+
routes: routes.flat(),
39+
});
40+
41+
// Add navigation guard for locale handling
42+
router.beforeEach((to, _from, next) => {
43+
const client = createIntlayerClient();
44+
45+
const metaLocale = to.meta.locale as Locales | undefined;
46+
47+
if (metaLocale) {
48+
// Reuse the locale defined in the route meta
49+
client.setLocale(metaLocale);
50+
next();
51+
} else {
52+
// Fallback: no locale in meta, possibly unmatched route
53+
// Optional: handle 404 or redirect to default locale
54+
client.setLocale(defaultLocale);
55+
56+
if (middleware.prefixDefault) {
57+
next(`/${defaultLocale}${getPathWithoutLocale(to.path)}`);
58+
} else {
59+
next(getPathWithoutLocale(to.path));
60+
}
61+
}
62+
});

0 commit comments

Comments
 (0)