feat(i18n): implement internationalization support with English and French locales
This commit is contained in:
parent
abdec720e1
commit
a10773f76a
|
|
@ -1,20 +1,16 @@
|
|||
<script setup>
|
||||
const { t } = useI18n();
|
||||
|
||||
useHead({
|
||||
meta: [{ name: "viewport", content: "width=device-width, initial-scale=1" }],
|
||||
link: [{ rel: "icon", href: "/favicon.ico" }],
|
||||
htmlAttrs: {
|
||||
lang: "en",
|
||||
},
|
||||
});
|
||||
|
||||
const title = "Work Hub";
|
||||
const description = "Project management made simple.";
|
||||
|
||||
useSeoMeta({
|
||||
title,
|
||||
description,
|
||||
ogTitle: title,
|
||||
ogDescription: description,
|
||||
title: () => t("app.title"),
|
||||
description: () => t("app.description"),
|
||||
ogTitle: () => t("app.title"),
|
||||
ogDescription: () => t("app.description"),
|
||||
twitterCard: "summary_large_image",
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
<UFooter data-allow-mismatch="children">
|
||||
<template #left>
|
||||
<p class="text-sm text-muted">Built with Nuxt UI • © {{ new Date().getFullYear() }}</p>
|
||||
<p class="text-sm text-muted">{{ $t('app.title') }} • © {{ new Date().getFullYear() }}</p>
|
||||
</template>
|
||||
|
||||
<template #right>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import { en, fr } from "@nuxt/ui/locale";
|
||||
|
||||
const { locale, setLocale, t } = useI18n();
|
||||
|
||||
function handleLocaleChange(value: string) {
|
||||
setLocale(value as "en" | "fr");
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UHeader>
|
||||
<template #left>
|
||||
|
|
@ -5,10 +15,18 @@
|
|||
<AppLogo class="w-auto h-6 shrink-0" />
|
||||
</NuxtLink>
|
||||
|
||||
<UButton to="/projects" label="Projects" color="neutral" variant="ghost" />
|
||||
<UButton to="/projects" :label="t('nav.projects')" color="neutral" variant="ghost" />
|
||||
</template>
|
||||
|
||||
<template #right>
|
||||
<ULocaleSelect
|
||||
:model-value="locale"
|
||||
:locales="[en, fr]"
|
||||
size="sm"
|
||||
color="neutral"
|
||||
variant="ghost"
|
||||
@update:model-value="handleLocaleChange"
|
||||
/>
|
||||
<UColorModeButton />
|
||||
</template>
|
||||
</UHeader>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { PROJECT_STATUSES, type ProjectStatus } from "@workspace/schema/constants";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
name?: string;
|
||||
|
|
@ -34,21 +36,21 @@ function onSubmit() {
|
|||
|
||||
<template>
|
||||
<form class="space-y-6" @submit.prevent="onSubmit">
|
||||
<UFormField label="Name" required>
|
||||
<UInput v-model="name" placeholder="Project name" class="w-full" required />
|
||||
<UFormField :label="t('form.name')" required>
|
||||
<UInput v-model="name" :placeholder="t('form.namePlaceholder')" class="w-full" required />
|
||||
</UFormField>
|
||||
|
||||
<UFormField label="Description">
|
||||
<UTextarea v-model="description" placeholder="Optional description" class="w-full" :rows="3" />
|
||||
<UFormField :label="t('form.description')">
|
||||
<UTextarea v-model="description" :placeholder="t('form.descriptionPlaceholder')" class="w-full" :rows="3" />
|
||||
</UFormField>
|
||||
|
||||
<UFormField label="Status">
|
||||
<UFormField :label="t('form.status')">
|
||||
<USelect v-model="status" :items="PROJECT_STATUSES.map((s) => ({ label: s, value: s }))" class="w-full" />
|
||||
</UFormField>
|
||||
|
||||
<div class="flex gap-3 justify-end">
|
||||
<UButton label="Cancel" icon="i-lucide-x" color="neutral" variant="outline" to="/projects" />
|
||||
<UButton type="submit" label="Save" icon="i-lucide-save" color="primary" :loading="saving" />
|
||||
<UButton :label="t('form.cancel')" icon="i-lucide-x" color="neutral" variant="outline" to="/projects" />
|
||||
<UButton type="submit" :label="t('form.save')" icon="i-lucide-save" color="primary" :loading="saving" />
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UPageHero
|
||||
title="Nuxt Starter Template"
|
||||
description="A production-ready starter template powered by Nuxt UI. Build beautiful, accessible, and performant applications in minutes, not hours."
|
||||
:title="t('home.heroTitle')"
|
||||
:description="t('home.heroDescription')"
|
||||
:links="[{
|
||||
label: 'Get started',
|
||||
label: t('home.getStarted'),
|
||||
to: 'https://ui.nuxt.com/docs/getting-started/installation/nuxt',
|
||||
target: '_blank',
|
||||
trailingIcon: 'i-lucide-arrow-right',
|
||||
size: 'xl',
|
||||
}, {
|
||||
label: 'Use this template',
|
||||
label: t('home.useTemplate'),
|
||||
to: 'https://github.com/nuxt-ui-templates/starter',
|
||||
target: '_blank',
|
||||
icon: 'i-simple-icons-github',
|
||||
|
|
@ -22,48 +26,48 @@
|
|||
|
||||
<UPageSection
|
||||
id="features"
|
||||
title="Everything you need to build modern Nuxt apps"
|
||||
description="Start with a solid foundation. This template includes all the essentials for building production-ready applications with Nuxt UI's powerful component system."
|
||||
:title="t('home.featuresTitle')"
|
||||
:description="t('home.featuresDescription')"
|
||||
:features="[{
|
||||
icon: 'i-lucide-rocket',
|
||||
title: 'Production-ready from day one',
|
||||
description: 'Pre-configured with TypeScript, ESLint, Tailwind CSS, and all the best practices. Focus on building features, not setting up tooling.',
|
||||
title: t('home.feature1Title'),
|
||||
description: t('home.feature1Description'),
|
||||
}, {
|
||||
icon: 'i-lucide-palette',
|
||||
title: 'Beautiful by default',
|
||||
description: 'Leveraging Nuxt UI\'s design system with automatic dark mode, consistent spacing, and polished components that look great out of the box.',
|
||||
title: t('home.feature2Title'),
|
||||
description: t('home.feature2Description'),
|
||||
}, {
|
||||
icon: 'i-lucide-zap',
|
||||
title: 'Lightning fast',
|
||||
description: 'Optimized for performance with SSR/SSG support, automatic code splitting, and edge-ready deployment. Your users will love the speed.',
|
||||
title: t('home.feature3Title'),
|
||||
description: t('home.feature3Description'),
|
||||
}, {
|
||||
icon: 'i-lucide-blocks',
|
||||
title: '100+ components included',
|
||||
description: 'Access Nuxt UI\'s comprehensive component library. From forms to navigation, everything is accessible, responsive, and customizable.',
|
||||
title: t('home.feature4Title'),
|
||||
description: t('home.feature4Description'),
|
||||
}, {
|
||||
icon: 'i-lucide-code-2',
|
||||
title: 'Developer experience first',
|
||||
description: 'Auto-imports, hot module replacement, and TypeScript support. Write less boilerplate and ship more features.',
|
||||
title: t('home.feature5Title'),
|
||||
description: t('home.feature5Description'),
|
||||
}, {
|
||||
icon: 'i-lucide-shield-check',
|
||||
title: 'Built for scale',
|
||||
description: 'Enterprise-ready architecture with proper error handling, SEO optimization, and security best practices built-in.',
|
||||
title: t('home.feature6Title'),
|
||||
description: t('home.feature6Description'),
|
||||
}]"
|
||||
/>
|
||||
|
||||
<UPageSection>
|
||||
<UPageCTA
|
||||
title="Ready to build your next Nuxt app?"
|
||||
description="Join thousands of developers building with Nuxt and Nuxt UI. Get this template and start shipping today."
|
||||
:title="t('home.ctaTitle')"
|
||||
:description="t('home.ctaDescription')"
|
||||
variant="subtle"
|
||||
:links="[{
|
||||
label: 'Start building',
|
||||
label: t('home.startBuilding'),
|
||||
to: 'https://ui.nuxt.com/docs/getting-started/installation/nuxt',
|
||||
target: '_blank',
|
||||
trailingIcon: 'i-lucide-arrow-right',
|
||||
color: 'neutral',
|
||||
}, {
|
||||
label: 'View on GitHub',
|
||||
label: t('home.viewOnGitHub'),
|
||||
to: 'https://github.com/nuxt-ui-templates/starter',
|
||||
target: '_blank',
|
||||
icon: 'i-simple-icons-github',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import type { Project } from "@workspace/schema";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
definePageMeta({
|
||||
title: "Edit Project",
|
||||
});
|
||||
|
|
@ -19,10 +21,10 @@ const apiBase = config.public.apiBaseUrl as string;
|
|||
|
||||
onMounted(async () => {
|
||||
const res = await fetch(`${apiBase}/projects/${route.params.id}`);
|
||||
if (!res.ok) {
|
||||
notFound.value = true;
|
||||
} else {
|
||||
if (res.ok) {
|
||||
project.value = await res.json();
|
||||
} else {
|
||||
notFound.value = true;
|
||||
}
|
||||
loading.value = false;
|
||||
});
|
||||
|
|
@ -37,14 +39,24 @@ async function handleSubmit(body: { name: string; description?: string; status:
|
|||
|
||||
<template>
|
||||
<UPage>
|
||||
<UPageHeader title="Edit Project" description="Update project details">
|
||||
<UPageHeader :title="t('projects.edit')" :description="t('projects.editDescription')">
|
||||
<template #right>
|
||||
<UButton label="Back" icon="i-lucide-chevron-left" color="neutral" variant="outline" to="/projects" />
|
||||
<UButton
|
||||
:label="t('form.back')"
|
||||
icon="i-lucide-chevron-left"
|
||||
color="neutral"
|
||||
variant="outline"
|
||||
to="/projects" />
|
||||
</template>
|
||||
</UPageHeader>
|
||||
|
||||
<UPageBody>
|
||||
<UAlert v-if="notFound" color="warning" variant="soft" icon="i-lucide-alert-triangle" title="Project not found" />
|
||||
<UAlert
|
||||
v-if="notFound"
|
||||
color="warning"
|
||||
variant="soft"
|
||||
icon="i-lucide-alert-triangle"
|
||||
:title="t('projects.notFound')" />
|
||||
|
||||
<UProgress v-else-if="loading" />
|
||||
|
||||
|
|
@ -54,8 +66,7 @@ async function handleSubmit(body: { name: string; description?: string; status:
|
|||
:description="project.description ?? undefined"
|
||||
:status="project.status"
|
||||
:saving
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
@submit="handleSubmit" />
|
||||
</UCard>
|
||||
</UPageBody>
|
||||
</UPage>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import type { TableColumn } from "@nuxt/ui";
|
||||
import type { Project } from "@workspace/schema";
|
||||
|
||||
|
|
@ -6,6 +7,22 @@ definePageMeta({
|
|||
title: "Projects",
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const pageTitle = computed(() => t("projects.title"));
|
||||
const pageDescription = computed(() => t("projects.description"));
|
||||
const newProjectLabel = computed(() => t("projects.new"));
|
||||
const emptyText = computed(() => t("projects.empty"));
|
||||
const deleteTitle = computed(() => t("projects.delete.title"));
|
||||
const deleteConfirm = computed(() => t("projects.delete.confirm"));
|
||||
const deleteCancel = computed(() => t("projects.delete.cancel"));
|
||||
const deleteDelete = computed(() => t("projects.delete.delete"));
|
||||
const colName = computed(() => t("projects.columns.name"));
|
||||
const colStatus = computed(() => t("projects.columns.status"));
|
||||
const colDescription = computed(() => t("projects.columns.description"));
|
||||
const colCreated = computed(() => t("projects.columns.created"));
|
||||
const colActions = computed(() => t("projects.columns.actions"));
|
||||
|
||||
const { projects, loading, error, fetchProjects, deleteProject } = useProjectApi();
|
||||
|
||||
const deleting = ref<string | null>(null);
|
||||
|
|
@ -28,24 +45,24 @@ async function confirmAndDelete(id: string) {
|
|||
}
|
||||
|
||||
const columns: TableColumn<Project>[] = [
|
||||
{ accessorKey: "name", header: "Name" },
|
||||
{ accessorKey: "status", header: "Status" },
|
||||
{ accessorKey: "name", header: colName.value },
|
||||
{ accessorKey: "status", header: colStatus.value },
|
||||
{
|
||||
accessorKey: "description",
|
||||
header: "Description",
|
||||
header: colDescription.value,
|
||||
cell: ({ row }) => row.getValue("description") ?? "—",
|
||||
},
|
||||
{ accessorKey: "createdAt", header: "Created" },
|
||||
{ id: "actions", header: "Actions" },
|
||||
{ accessorKey: "createdAt", header: colCreated.value },
|
||||
{ id: "actions", header: colActions.value },
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UPage>
|
||||
<UPageHeader
|
||||
title="Projects"
|
||||
description="Manage your projects"
|
||||
:links="[{ label: 'New project', icon: 'i-lucide-plus', to: '/projects/new', color: 'primary' }]" />
|
||||
:title="pageTitle"
|
||||
:description="pageDescription"
|
||||
:links="[{ label: newProjectLabel, icon: 'i-lucide-plus', to: '/projects/new', color: 'primary' }]" />
|
||||
|
||||
<UPageBody>
|
||||
<UAlert v-if="error" color="error" variant="soft" icon="i-lucide-alert-circle" :title="error" class="mb-4" />
|
||||
|
|
@ -90,7 +107,7 @@ const columns: TableColumn<Project>[] = [
|
|||
<template #empty>
|
||||
<div class="py-12 text-center text-muted">
|
||||
<UIcon name="i-lucide-folder-open" class="size-8 mx-auto mb-2" />
|
||||
<p>No projects yet.</p>
|
||||
<p>{{ emptyText }}</p>
|
||||
</div>
|
||||
</template>
|
||||
</UTable>
|
||||
|
|
@ -98,17 +115,29 @@ const columns: TableColumn<Project>[] = [
|
|||
|
||||
<UModal v-model:open="confirmDelete">
|
||||
<template #header>
|
||||
<h3 class="text-lg font-semibold">Delete project</h3>
|
||||
<h3 class="text-lg font-semibold">{{ deleteTitle }}</h3>
|
||||
</template>
|
||||
|
||||
<template #body>
|
||||
<p class="text-sm text-muted">Are you sure you want to delete this project? This action cannot be undone.</p>
|
||||
<p class="text-sm text-muted">{{ deleteConfirm }}</p>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex gap-3 justify-end">
|
||||
<UButton label="Cancel" icon="i-lucide-x" color="neutral" variant="outline" @click="confirmDelete = false; deleting = null" />
|
||||
<UButton label="Delete" icon="i-lucide-trash-2" color="error" @click="deleting && confirmAndDelete(deleting)" />
|
||||
<UButton
|
||||
:label="deleteCancel"
|
||||
icon="i-lucide-x"
|
||||
color="neutral"
|
||||
variant="outline"
|
||||
@click="
|
||||
confirmDelete = false;
|
||||
deleting = null;
|
||||
" />
|
||||
<UButton
|
||||
:label="deleteDelete"
|
||||
icon="i-lucide-trash-2"
|
||||
color="error"
|
||||
@click="deleting && confirmAndDelete(deleting)" />
|
||||
</div>
|
||||
</template>
|
||||
</UModal>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
const { t } = useI18n();
|
||||
|
||||
definePageMeta({
|
||||
title: "New Project",
|
||||
});
|
||||
|
|
@ -18,8 +20,8 @@ async function handleSubmit(body: { name: string; description?: string; status:
|
|||
<template>
|
||||
<UPage>
|
||||
<UPageHeader
|
||||
title="New Project"
|
||||
description="Create a new project"
|
||||
:title="t('projects.create')"
|
||||
:description="t('projects.createDescription')"
|
||||
/>
|
||||
|
||||
<UPageBody>
|
||||
|
|
|
|||
7
apps/web/i18n/i18n.config.ts
Normal file
7
apps/web/i18n/i18n.config.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export default defineI18nConfig(() => ({
|
||||
legacy: false,
|
||||
locale: "en",
|
||||
fallbackLocale: "en",
|
||||
silentFallbackWarn: true,
|
||||
silentTranslationWarn: true,
|
||||
}));
|
||||
67
apps/web/i18n/locales/en.json
Normal file
67
apps/web/i18n/locales/en.json
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"app": {
|
||||
"title": "Work Hub",
|
||||
"description": "Project management made simple."
|
||||
},
|
||||
"nav": {
|
||||
"projects": "Projects"
|
||||
},
|
||||
"projects": {
|
||||
"title": "Projects",
|
||||
"description": "Manage your projects",
|
||||
"new": "New project",
|
||||
"edit": "Edit Project",
|
||||
"editDescription": "Update project details",
|
||||
"create": "New Project",
|
||||
"createDescription": "Create a new project",
|
||||
"columns": {
|
||||
"name": "Name",
|
||||
"status": "Status",
|
||||
"description": "Description",
|
||||
"created": "Created",
|
||||
"actions": "Actions"
|
||||
},
|
||||
"delete": {
|
||||
"title": "Delete project",
|
||||
"confirm": "Are you sure you want to delete this project? This action cannot be undone.",
|
||||
"cancel": "Cancel",
|
||||
"delete": "Delete"
|
||||
},
|
||||
"notFound": "Project not found",
|
||||
"empty": "No projects yet."
|
||||
},
|
||||
"form": {
|
||||
"name": "Name",
|
||||
"namePlaceholder": "Project name",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Optional description",
|
||||
"status": "Status",
|
||||
"save": "Save",
|
||||
"cancel": "Cancel",
|
||||
"back": "Back"
|
||||
},
|
||||
"home": {
|
||||
"heroTitle": "Nuxt Starter Template",
|
||||
"heroDescription": "A production-ready starter template powered by Nuxt UI. Build beautiful, accessible, and performant applications in minutes, not hours.",
|
||||
"getStarted": "Get started",
|
||||
"useTemplate": "Use this template",
|
||||
"featuresTitle": "Everything you need to build modern Nuxt apps",
|
||||
"featuresDescription": "Start with a solid foundation. This template includes all the essentials for building production-ready applications with Nuxt UI's powerful component system.",
|
||||
"feature1Title": "Production-ready from day one",
|
||||
"feature1Description": "Pre-configured with TypeScript, ESLint, Tailwind CSS, and all the best practices. Focus on building features, not setting up tooling.",
|
||||
"feature2Title": "Beautiful by default",
|
||||
"feature2Description": "Leveraging Nuxt UI's design system with automatic dark mode, consistent spacing, and polished components that look great out of the box.",
|
||||
"feature3Title": "Lightning fast",
|
||||
"feature3Description": "Optimized for performance with SSR/SSG support, automatic code splitting, and edge-ready deployment. Your users will love the speed.",
|
||||
"feature4Title": "100+ components included",
|
||||
"feature4Description": "Access Nuxt UI's comprehensive component library. From forms to navigation, everything is accessible, responsive, and customizable.",
|
||||
"feature5Title": "Developer experience first",
|
||||
"feature5Description": "Auto-imports, hot module replacement, and TypeScript support. Write less boilerplate and ship more features.",
|
||||
"feature6Title": "Built for scale",
|
||||
"feature6Description": "Enterprise-ready architecture with proper error handling, SEO optimization, and security best practices built-in.",
|
||||
"ctaTitle": "Ready to build your next Nuxt app?",
|
||||
"ctaDescription": "Join thousands of developers building with Nuxt and Nuxt UI. Get this template and start shipping today.",
|
||||
"startBuilding": "Start building",
|
||||
"viewOnGitHub": "View on GitHub"
|
||||
}
|
||||
}
|
||||
67
apps/web/i18n/locales/fr.json
Normal file
67
apps/web/i18n/locales/fr.json
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"app": {
|
||||
"title": "Work Hub",
|
||||
"description": "La gestion de projets simplifiée."
|
||||
},
|
||||
"nav": {
|
||||
"projects": "Projets"
|
||||
},
|
||||
"projects": {
|
||||
"title": "Projets",
|
||||
"description": "Gérez vos projets",
|
||||
"new": "Nouveau projet",
|
||||
"edit": "Modifier le projet",
|
||||
"editDescription": "Mettre à jour les détails du projet",
|
||||
"create": "Nouveau projet",
|
||||
"createDescription": "Créer un nouveau projet",
|
||||
"columns": {
|
||||
"name": "Nom",
|
||||
"status": "Statut",
|
||||
"description": "Description",
|
||||
"created": "Créé le",
|
||||
"actions": "Actions"
|
||||
},
|
||||
"delete": {
|
||||
"title": "Supprimer le projet",
|
||||
"confirm": "Êtes-vous sûr de vouloir supprimer ce projet ? Cette action est irréversible.",
|
||||
"cancel": "Annuler",
|
||||
"delete": "Supprimer"
|
||||
},
|
||||
"notFound": "Projet introuvable",
|
||||
"empty": "Aucun projet pour le moment."
|
||||
},
|
||||
"form": {
|
||||
"name": "Nom",
|
||||
"namePlaceholder": "Nom du projet",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Description facultative",
|
||||
"status": "Statut",
|
||||
"save": "Enregistrer",
|
||||
"cancel": "Annuler",
|
||||
"back": "Retour"
|
||||
},
|
||||
"home": {
|
||||
"heroTitle": "Nuxt Starter Template",
|
||||
"heroDescription": "Un modèle de démarrage prêt pour la production propulsé par Nuxt UI. Créez des applications belles, accessibles et performantes en quelques minutes.",
|
||||
"getStarted": "Commencer",
|
||||
"useTemplate": "Utiliser ce modèle",
|
||||
"featuresTitle": "Tout ce dont vous avez besoin pour créer des apps Nuxt modernes",
|
||||
"featuresDescription": "Partez sur des bases solides. Ce modèle inclut tous les essentiels pour créer des applications prêtes pour la production avec le système de composants puissant de Nuxt UI.",
|
||||
"feature1Title": "Prêt pour la production dès le premier jour",
|
||||
"feature1Description": "Préconfiguré avec TypeScript, ESLint, Tailwind CSS et toutes les bonnes pratiques. Concentrez-vous sur les fonctionnalités, pas sur la configuration.",
|
||||
"feature2Title": "Beau par défaut",
|
||||
"feature2Description": "Tirez parti du système de design de Nuxt UI avec le mode sombre automatique, une espacement cohérent et des composants soignés qui sont superbes dès la sortie de la boîte.",
|
||||
"feature3Title": "Rapide comme l'éclair",
|
||||
"feature3Description": "Optimisé pour la performance avec le support SSR/SSG, la séparation automatique du code et un déploiement edge-ready. Vos utilisateurs adoreront la vitesse.",
|
||||
"feature4Title": "100+ composants inclus",
|
||||
"feature4Description": "Accédez à la bibliothèque complète de composants de Nuxt UI. Des formulaires à la navigation, tout est accessible, responsive et personnalisable.",
|
||||
"feature5Title": "L'expérience développeur avant tout",
|
||||
"feature5Description": "Auto-imports, remplacement de modules à chaud et support TypeScript. Écrivez moins de code passe-partout et livrez plus de fonctionnalités.",
|
||||
"feature6Title": "Conçu pour passer à l'échelle",
|
||||
"feature6Description": "Architecture prête pour l'entreprise avec une gestion des erreurs appropriée, une optimisation SEO et des bonnes pratiques de sécurité intégrées.",
|
||||
"ctaTitle": "Prêt à créer votre prochaine app Nuxt ?",
|
||||
"ctaDescription": "Rejoignez des milliers de développeurs qui construisent avec Nuxt et Nuxt UI. Obtenez ce modèle et commencez à livrer dès aujourd'hui.",
|
||||
"startBuilding": "Commencer à développer",
|
||||
"viewOnGitHub": "Voir sur GitHub"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
modules: ["@nuxt/eslint", "@nuxt/ui"],
|
||||
modules: ["@nuxt/eslint", "@nuxt/ui", "@nuxtjs/i18n"],
|
||||
|
||||
devtools: {
|
||||
enabled: true,
|
||||
|
|
@ -24,4 +24,20 @@ export default defineNuxtConfig({
|
|||
},
|
||||
},
|
||||
},
|
||||
|
||||
i18n: {
|
||||
locales: [
|
||||
{ code: "en", language: "en", name: "English", file: "en.json" },
|
||||
{ code: "fr", language: "fr", name: "Français", file: "fr.json" },
|
||||
],
|
||||
defaultLocale: "en",
|
||||
strategy: "no_prefix",
|
||||
langDir: "locales",
|
||||
detectBrowserLanguage: {
|
||||
useCookie: true,
|
||||
cookieKey: "i18n_redirected",
|
||||
redirectOn: "root",
|
||||
},
|
||||
vueI18n: "i18n.config.ts",
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue