Skip to content

Commit a5d8524

Browse files
Benoit Ngohomersimpsons
Benoit Ngo
authored andcommitted
feat(i18n): Add internationalisation
1 parent d892812 commit a5d8524

File tree

18 files changed

+404
-66
lines changed

18 files changed

+404
-66
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import localeFr from "../../src/locales/fr";
2+
import localeEn from "../../src/locales/en";
3+
export default defineI18nConfig(() => ({
4+
legacy: false,
5+
locale: "fr",
6+
messages: {
7+
en: localeEn,
8+
fr: localeFr,
9+
},
10+
}));

apps/front/nuxt.config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ import svgLoader from "vite-svg-loader";
33

44
export default defineNuxtConfig({
55
srcDir: "src/",
6-
modules: ["@pinia/nuxt"],
6+
modules: ["@pinia/nuxt", "@nuxtjs/i18n"],
77
runtimeConfig: {
88
API_URL: process.env.API_URL || "",
99
},
10+
i18n: {
11+
vueI18n: "./modules_config/nuxt/i18n.config.ts", // if you are using custom path, default
12+
},
1013
app: {
1114
head: {
1215
// @see https://getbootstrap.com/docs/5.0/getting-started/introduction/#starter-template

apps/front/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"vue-tsc": "^1.6.5"
2222
},
2323
"dependencies": {
24+
"@nuxtjs/i18n": "^8.0.0-rc.5",
2425
"@pinia/nuxt": "^0.4.11",
2526
"defu": "^6.1.2",
2627
"h3": "^1.8.2",

apps/front/src/components/layout/AppHeader.vue

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
<template>
22
<div class="grid">
3-
<div class="col-2 col-offset-8">
4-
<NuxtLink to="/auth/register">Register</NuxtLink>
5-
</div>
3+
<div class="col-2 col-offset-8"></div>
64
<div class="col-2">
7-
<p v-if="username">Welcome {{ username }}</p>
5+
<p
6+
v-if="username"
7+
v-t="{
8+
path: 'components.layout.appHeader.welcome',
9+
args: { username },
10+
}"
11+
></p>
812
</div>
913
</div>
1014
</template>

apps/front/src/components/layout/menu/AppMenu.vue

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,33 @@
22
<TieredMenu :model="items" class="h-screen sticky w-full"> </TieredMenu>
33
</template>
44
<script setup lang="ts">
5+
const { t } = useI18n();
56
const items = computed(() => [
67
{
7-
label: "Users",
8+
label: t("components.layout.menu.appMenu.users"),
89
icon: "pi pi-fw pi-file",
910
to: "/users",
1011
},
1112
{
12-
label: "Page1",
13+
label: t("components.layout.menu.appMenu.page1"),
1314
icon: "pi pi-fw pi-pencil",
1415
to: "/demo/page1",
1516
},
1617
{
17-
label: "Page2",
18+
label: t("components.layout.menu.appMenu.page2"),
1819
icon: "pi pi-fw pi-pencil",
1920
to: "/demo/page2",
2021
},
2122
{
22-
label: "Page3",
23+
label: t("components.layout.menu.appMenu.page3"),
2324
icon: "pi pi-fw pi-pencil",
2425
to: "/demo/page3",
2526
},
2627
{
2728
separator: true,
2829
},
2930
{
30-
label: "Quit",
31+
label: t("components.layout.menu.appMenu.quit"),
3132
icon: "pi pi-fw pi-power-off",
3233
},
3334
]);

apps/front/src/components/user/UserCreateForm.vue

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<h1>Register</h1>
2+
<h1 v-t="{ path: 'components.user.createForm.title' }"></h1>
33
<form @submit.prevent.stop="registerUser">
44
<UserForm
55
v-model:email="email"
@@ -8,7 +8,9 @@
88
:is-password-confirmed="isPasswordConfirmed"
99
/>
1010
{{ errorMessage }}
11-
<button :disabled="!securedPassword">Register</button>
11+
<button :disabled="!isPasswordConfirmed">
12+
{{ $t("components.user.createForm.ok") }}
13+
</button>
1214
</form>
1315
</template>
1416
<script setup lang="ts">
@@ -25,10 +27,6 @@ const {
2527
} = useUser();
2628
2729
const registerUser = async () => {
28-
if (!securedPassword.value) {
29-
// That mean you call this action without checking that data are OK. this shall not be executed
30-
throw createError("You need a valid password");
31-
}
3230
try {
3331
await createUser(email.value, securedPassword.value);
3432
await navigateTo("/users");

apps/front/src/components/user/UserForm.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<template>
22
<div>
3-
<label for="email">Email</label>
3+
<label for="email">{{ $t("components.user.form.email") }}</label>
44
<input
55
type="text"
66
:value="email"
77
@input="$emit('update:email', clearInput($event))"
88
/>
99
</div>
1010
<div>
11-
<label for="password">Password</label>
11+
<label for="password">{{ $t("components.user.form.password") }}</label>
1212
<input
1313
name="password"
1414
type="password"
@@ -17,15 +17,17 @@
1717
/>
1818
</div>
1919
<div>
20-
<label for="passwordConfirm">Confirm password</label>
20+
<label for="passwordConfirm">{{
21+
$t("components.user.form.passwordConfirm")
22+
}}</label>
2123
<input
2224
name="passwordConfirm"
2325
type="password"
2426
:value="passwordConfirm"
2527
@input="$emit('update:passwordConfirm', clearInput($event))"
2628
/>
2729
<span v-if="!isPasswordConfirmed" class="text-danger">
28-
The confirm password is not the same as the password
30+
{{ $t("components.user.form.errorPasswordConfirm") }}
2931
</span>
3032
</div>
3133
</template>

apps/front/src/components/user/UserUpdateForm.vue

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
<template>
2-
<div v-show="userPending">(Chargement)</div>
3-
4-
<form v-if="!userPending" @submit.prevent.stop="updateUser">
5-
<h1>Update user {{ data.email }}</h1>
2+
<div
3+
v-show="userPending"
4+
v-t="{ path: 'components.user.updateForm.pending' }"
5+
></div>
6+
<form v-if="data" @submit.prevent.stop="updateUser">
7+
<h1 v-t="{ path: 'components.user.updateForm.title', args: data }"></h1>
68
<UserForm
79
v-model:email="email"
810
v-model:password="password"
@@ -11,7 +13,9 @@
1113
/>
1214
{{ errorMessage }}
1315
{{ error }}
14-
<button type="submit">Save</button>
16+
<Button type="submit" :disabled="!isPasswordConfirmed">{{
17+
$t("components.user.updateForm.ok")
18+
}}</Button>
1519
</form>
1620
</template>
1721

apps/front/src/composables/api/user/useGetUser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import useAppFetch from "~/composables/useAppFetch";
44

55
export default async function useGetUser(userId: string) {
66
return useAppFetch<User>(() => "/users/" + userId, {
7-
key: "getUser",
7+
key: "getUser" + userId,
88
method: GET,
99
});
1010
}

apps/front/src/composables/api/user/useListUsers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ export default async function useListUsers() {
66
return useAppFetch<Array<User>>(() => "/users", {
77
key: "listUsers",
88
method: GET,
9+
lazy: true,
910
});
1011
}

apps/front/src/composables/user/useUser.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,21 @@ import { User } from "~/types/User";
33
export default function useUser(user: Ref<User> | undefined = undefined) {
44
const password = ref("");
55
const passwordConfirm = ref("");
6+
// This wont be kept in sync if user is modified! (to resolve)
67
const email = user ? toRef(user?.value?.email) : ref("");
78
const isPasswordConfirmed = computed(
89
() => password.value === passwordConfirm.value
910
);
1011

1112
const isPasswordEmpty = computed(() => !password.value);
13+
const securedPassword = computed(() =>
14+
isPasswordConfirmed && isPasswordEmpty ? password.value : ""
15+
);
1216
return {
1317
password,
1418
passwordConfirm,
1519
email: email,
1620
isPasswordConfirmed,
17-
securedPassword: computed(() =>
18-
isPasswordConfirmed && isPasswordEmpty ? password.value : ""
19-
),
21+
securedPassword,
2022
};
2123
}

apps/front/src/locales/en.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
export default {
2+
components: {
3+
user: {
4+
createForm: {
5+
title: "Create a new user",
6+
ok: "Create",
7+
},
8+
updateForm: {
9+
pending: "Loading user",
10+
title: "Update {email}",
11+
ok: "Update",
12+
},
13+
form: {
14+
email: "Email",
15+
password: "Password",
16+
passwordConfirm: "Confirm your password",
17+
errorPasswordConfirm: "The confirmation of the password is invalid",
18+
},
19+
},
20+
layout: {
21+
appHeader: {
22+
welcome: "Welcome {username}",
23+
},
24+
menu: {
25+
appMenu: {
26+
users: "Users",
27+
page1: "page1",
28+
page2: "page2",
29+
page3: "page3",
30+
quit: "Quit",
31+
},
32+
},
33+
},
34+
},
35+
pages: {
36+
page1: {
37+
altPanda: "This is to discover images",
38+
background: "This is to discover background",
39+
},
40+
auth: {
41+
login: {
42+
username: "Email",
43+
password: "Password",
44+
title: "Please log-in",
45+
ok: "Submit",
46+
},
47+
},
48+
user: {
49+
index: {
50+
createButton: "New user",
51+
pending: "Loading users",
52+
title: "Users",
53+
edit: "Edit",
54+
delete: "Delete",
55+
},
56+
},
57+
},
58+
};

apps/front/src/locales/fr.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
export default {
2+
components: {
3+
user: {
4+
createForm: {
5+
title: "Créer un nouvel utilisateur",
6+
ok: "Créer",
7+
},
8+
updateForm: {
9+
pending: "Chargement de l'utilisateur",
10+
title: "Mise à jour de {email}",
11+
ok: "Mettre à jour",
12+
},
13+
form: {
14+
email: "Email",
15+
password: "Mot de passe",
16+
passwordConfirm: "Confirmez votre mot de passe",
17+
errorPasswordConfirm: "La confirmation du mot de passe est invalide",
18+
},
19+
},
20+
layout: {
21+
appHeader: {
22+
welcome: "Bienvenue {username}",
23+
},
24+
menu: {
25+
appMenu: {
26+
users: "Utilisateurs",
27+
page1: "page1",
28+
page2: "page2",
29+
page3: "page3",
30+
quit: "Quitter",
31+
},
32+
},
33+
},
34+
},
35+
pages: {
36+
page1: {
37+
altPanda: "Découvrez les images",
38+
background: "Découvrez les fonds d'écrans",
39+
},
40+
auth: {
41+
login: {
42+
username: "email",
43+
password: "mot de passe",
44+
title: "Connectez-vous",
45+
ok: "Connexion",
46+
},
47+
},
48+
user: {
49+
index: {
50+
createButton: "Créer un utilisateur",
51+
pending: "Chargement des utilisateurs",
52+
title: "Utilisateurs",
53+
edit: "Editer",
54+
delete: "Supprimer",
55+
},
56+
},
57+
},
58+
};

apps/front/src/pages/auth/login.vue

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
11
<template>
2-
<div>
3-
<div>
4-
<h1>Welcome to the login page</h1>
5-
<form @submit.prevent.stop="submitAuthenticateUser">
6-
<div>
7-
<label for="email">Email</label>
8-
<input v-model="username" name="email" type="text" />
2+
<main id="main" class="main">
3+
<section class="login flex-nowrap">
4+
<div class="welcome-box">
5+
<div class="content-box no-padding">
6+
<h1>{{ $t("pages.auth.login.title") }}</h1>
97
</div>
10-
<div>
11-
<label for="password">Password</label>
12-
<input v-model="password" name="password" type="password" />
13-
</div>
14-
<button type="submit">Log-in</button>
8+
</div>
9+
<form
10+
class="login-form temporary-primary-bg"
11+
@submit.prevent.stop="submitAuthenticateUser"
12+
>
13+
<InputText
14+
v-model="username"
15+
type="text"
16+
:placeholder="$t('pages.auth.login.username')"
17+
/>
18+
<InputText
19+
v-model="password"
20+
type="password"
21+
:placeholder="$t('pages.auth.login.password')"
22+
/>
23+
24+
<Button type="submit"> {{ $t("pages.auth.login.ok") }}</Button>
1525
<div v-if="errorMessage">{{ errorMessage }}</div>
1626
</form>
17-
</div>
18-
</div>
27+
</section>
28+
</main>
1929
</template>
2030
<script setup lang="ts">
2131
import { ref } from "vue";

apps/front/src/pages/demo/page1.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<template>
22
<div>
33
Page 1
4-
<img src="~/assets/images/panda.webp" alt="Discover Pandas" />
5-
<div class="panda-background">This is to discover background scss</div>
4+
<img src="~/assets/images/panda.webp" :alt="$t('pages.page1.altPanda')" />
5+
<div class="panda-background">{{ $t("pages.page1.background") }}</div>
66
</div>
77
</template>
88
<script lang="ts" setup>

0 commit comments

Comments
 (0)