nuxt-users 1.38.0 → 1.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +13 -1
  2. package/dist/cli.mjs +57 -27
  3. package/dist/module.d.mts +2 -2
  4. package/dist/module.d.ts +2 -2
  5. package/dist/module.json +4 -1
  6. package/dist/module.mjs +29 -7
  7. package/dist/runtime/assets/nuxt-users.css +1 -1
  8. package/dist/runtime/components/NUsersEmailConfirmation.d.vue.ts +5 -3
  9. package/dist/runtime/components/NUsersEmailConfirmation.vue +22 -15
  10. package/dist/runtime/components/NUsersEmailConfirmation.vue.d.ts +5 -3
  11. package/dist/runtime/components/NUsersGoogleLoginButton.d.vue.ts +4 -2
  12. package/dist/runtime/components/NUsersGoogleLoginButton.vue +5 -2
  13. package/dist/runtime/components/NUsersGoogleLoginButton.vue.d.ts +4 -2
  14. package/dist/runtime/components/NUsersList.vue +25 -11
  15. package/dist/runtime/components/NUsersLoginForm.d.vue.ts +13 -2
  16. package/dist/runtime/components/NUsersLoginForm.vue +35 -13
  17. package/dist/runtime/components/NUsersLoginForm.vue.d.ts +13 -2
  18. package/dist/runtime/components/NUsersLogoutLink.d.vue.ts +3 -4
  19. package/dist/runtime/components/NUsersLogoutLink.vue +8 -5
  20. package/dist/runtime/components/NUsersLogoutLink.vue.d.ts +3 -4
  21. package/dist/runtime/components/NUsersPasswordStrengthIndicator.d.vue.ts +6 -0
  22. package/dist/runtime/components/NUsersPasswordStrengthIndicator.vue +17 -9
  23. package/dist/runtime/components/NUsersPasswordStrengthIndicator.vue.d.ts +6 -0
  24. package/dist/runtime/components/NUsersProfileInfo.d.vue.ts +13 -1
  25. package/dist/runtime/components/NUsersProfileInfo.vue +23 -9
  26. package/dist/runtime/components/NUsersProfileInfo.vue.d.ts +13 -1
  27. package/dist/runtime/components/NUsersRegisterForm.d.vue.ts +26 -11
  28. package/dist/runtime/components/NUsersRegisterForm.vue +34 -16
  29. package/dist/runtime/components/NUsersRegisterForm.vue.d.ts +26 -11
  30. package/dist/runtime/components/NUsersResetPasswordForm.d.vue.ts +11 -2
  31. package/dist/runtime/components/NUsersResetPasswordForm.vue +25 -12
  32. package/dist/runtime/components/NUsersResetPasswordForm.vue.d.ts +11 -2
  33. package/dist/runtime/components/NUsersUserCard.d.vue.ts +2 -0
  34. package/dist/runtime/components/NUsersUserCard.vue +8 -4
  35. package/dist/runtime/components/NUsersUserCard.vue.d.ts +2 -0
  36. package/dist/runtime/components/NUsersUserForm.d.vue.ts +2 -2
  37. package/dist/runtime/components/NUsersUserForm.vue +5 -4
  38. package/dist/runtime/components/NUsersUserForm.vue.d.ts +2 -2
  39. package/dist/runtime/composables/useAuthentication.js +14 -0
  40. package/dist/runtime/composables/useNuxtUsersLocale.d.ts +15 -0
  41. package/dist/runtime/composables/useNuxtUsersLocale.js +27 -0
  42. package/dist/runtime/composables/usePasswordValidation.d.ts +1 -1
  43. package/dist/runtime/composables/usePublicPaths.js +2 -1
  44. package/dist/runtime/locales/en.d.ts +2 -0
  45. package/dist/runtime/locales/en.js +130 -0
  46. package/dist/runtime/locales/hu.d.ts +3 -0
  47. package/dist/runtime/locales/hu.js +188 -0
  48. package/dist/runtime/locales/index.d.ts +5 -0
  49. package/dist/runtime/locales/index.js +8 -0
  50. package/dist/runtime/server/api/nuxt-users/[id].delete.js +1 -1
  51. package/dist/runtime/server/api/nuxt-users/[id].get.js +1 -1
  52. package/dist/runtime/server/api/nuxt-users/[id].patch.js +1 -1
  53. package/dist/runtime/server/api/nuxt-users/auth/google/callback.get.js +1 -1
  54. package/dist/runtime/server/api/nuxt-users/auth/google/redirect.get.js +1 -1
  55. package/dist/runtime/server/api/nuxt-users/confirm-email.get.js +3 -3
  56. package/dist/runtime/server/api/nuxt-users/inactive.get.js +1 -2
  57. package/dist/runtime/server/api/nuxt-users/index.get.js +1 -2
  58. package/dist/runtime/server/api/nuxt-users/index.post.js +1 -1
  59. package/dist/runtime/server/api/nuxt-users/me.get.js +20 -13
  60. package/dist/runtime/server/api/nuxt-users/me.patch.js +1 -1
  61. package/dist/runtime/server/api/nuxt-users/password/forgot.post.js +2 -1
  62. package/dist/runtime/server/api/nuxt-users/password/index.patch.js +1 -1
  63. package/dist/runtime/server/api/nuxt-users/password/reset.post.d.ts +1 -1
  64. package/dist/runtime/server/api/nuxt-users/password/reset.post.js +4 -2
  65. package/dist/runtime/server/api/nuxt-users/session/index.delete.js +1 -1
  66. package/dist/runtime/server/api/nuxt-users/session/index.post.js +5 -3
  67. package/dist/runtime/server/composables/useServerAuth.js +1 -1
  68. package/dist/runtime/server/internal/index.d.ts +1 -7
  69. package/dist/runtime/server/internal/index.js +23 -7
  70. package/dist/runtime/server/middleware/authorization.server.js +22 -5
  71. package/dist/runtime/server/tasks/cleanup-tokens.d.ts +1 -1
  72. package/dist/runtime/server/utils/add-indexes.d.ts +3 -0
  73. package/dist/runtime/server/utils/add-indexes.js +17 -0
  74. package/dist/runtime/server/utils/google-oauth.js +2 -1
  75. package/dist/runtime/server/utils/index.d.ts +2 -2
  76. package/dist/runtime/server/utils/index.js +2 -2
  77. package/dist/runtime/server/utils/migrate.d.ts +6 -0
  78. package/dist/runtime/server/utils/migrate.js +10 -1
  79. package/dist/runtime/utils/deep-merge.d.ts +8 -0
  80. package/dist/runtime/utils/deep-merge.js +17 -0
  81. package/dist/runtime/utils/locale.d.ts +14 -0
  82. package/dist/runtime/utils/locale.js +38 -0
  83. package/dist/shared/{nuxt-users.BnOQs2LI.mjs → nuxt-users.DfZ7bc_P.mjs} +16 -8
  84. package/dist/shared/{nuxt-users.SXaMnaEL.d.mts → nuxt-users.XW6DYM7t.d.mts} +46 -2
  85. package/dist/shared/{nuxt-users.SXaMnaEL.d.ts → nuxt-users.XW6DYM7t.d.ts} +46 -2
  86. package/dist/utils.d.mts +4 -1
  87. package/dist/utils.d.ts +4 -1
  88. package/dist/utils.mjs +4 -1
  89. package/package.json +11 -6
  90. package/scripts/check-locale-consistency.ts +156 -0
  91. package/scripts/check-peer-dependencies.js +5 -5
  92. package/scripts/check-translations.ts +255 -0
  93. package/scripts/post-build.js +1 -1
  94. package/scripts/test-nuxt3.sh +78 -0
@@ -2,10 +2,24 @@
2
2
  import { onMounted, computed, ref } from "vue";
3
3
  import { useUsers } from "../composables/useUsers";
4
4
  import { defaultDisplayFields, defaultFieldLabels } from "nuxt-users/utils";
5
+ import { useNuxtUsersLocale } from "../composables/useNuxtUsersLocale";
6
+ const { t } = useNuxtUsersLocale();
5
7
  const props = defineProps({
6
8
  displayFields: { type: Array, required: false, default: () => defaultDisplayFields },
7
9
  fieldLabels: { type: Object, required: false, default: () => defaultFieldLabels },
8
- filter: { type: [Object, Function], required: false, default: () => ({}) }
10
+ filter: { type: [Object, Function], required: false, default: () => ({}) },
11
+ title: { type: String, required: false },
12
+ loadingText: { type: String, required: false },
13
+ noUsersText: { type: String, required: false },
14
+ errorText: { type: String, required: false },
15
+ editButtonText: { type: String, required: false },
16
+ deleteButtonText: { type: String, required: false },
17
+ pageText: { type: String, required: false },
18
+ ofText: { type: String, required: false },
19
+ totalText: { type: String, required: false },
20
+ usersText: { type: String, required: false },
21
+ previousText: { type: String, required: false },
22
+ nextText: { type: String, required: false }
9
23
  });
10
24
  const emit = defineEmits(["editClick", "delete"]);
11
25
  const usersComposable = ref(null);
@@ -59,7 +73,7 @@ const handleFetchUsers = (page, limit) => {
59
73
  <div class="n-users-list">
60
74
  <slot name="title">
61
75
  <h2>
62
- Users List
76
+ {{ props.title || t("usersList.title") }}
63
77
  </h2>
64
78
  </slot>
65
79
 
@@ -68,7 +82,7 @@ const handleFetchUsers = (page, limit) => {
68
82
  :loading="loading"
69
83
  >
70
84
  <div v-if="loading">
71
- Loading users...
85
+ {{ props.loadingText || t("usersList.loading") }}
72
86
  </div>
73
87
  </slot>
74
88
 
@@ -77,13 +91,13 @@ const handleFetchUsers = (page, limit) => {
77
91
  :error="error"
78
92
  >
79
93
  <div v-if="error">
80
- Error: {{ error }}
94
+ {{ props.errorText || t("usersList.error") }} {{ error }}
81
95
  </div>
82
96
  </slot>
83
97
 
84
98
  <slot name="noUsers">
85
99
  <div v-if="users.length === 0">
86
- No users found
100
+ {{ props.noUsersText || t("usersList.noUsers") }}
87
101
  </div>
88
102
  </slot>
89
103
 
@@ -126,7 +140,7 @@ const handleFetchUsers = (page, limit) => {
126
140
  class="n-users-edit-btn"
127
141
  @click="editUserFn"
128
142
  >
129
- Edit
143
+ {{ props.editButtonText || t("common.edit") }}
130
144
  </button>
131
145
  </slot>
132
146
  </template>
@@ -142,7 +156,7 @@ const handleFetchUsers = (page, limit) => {
142
156
  class="n-users-delete-btn"
143
157
  @click="deleteUserFn"
144
158
  >
145
- Delete
159
+ {{ props.deleteButtonText || t("common.delete") }}
146
160
  </button>
147
161
  </slot>
148
162
  </template>
@@ -210,8 +224,8 @@ const handleFetchUsers = (page, limit) => {
210
224
  >
211
225
  <div v-if="pagination && pagination.totalPages > 1">
212
226
  <div>
213
- <span>Page {{ pagination.page }} of {{ pagination.totalPages }}</span>
214
- <span>Total: {{ pagination.total }} users</span>
227
+ <span>{{ props.pageText || t("usersList.page") }} {{ pagination.page }} {{ props.ofText || t("usersList.of") }} {{ pagination.totalPages }}</span>
228
+ <span>{{ props.totalText || t("usersList.total") }} {{ pagination.total }} {{ props.usersText || t("usersList.users") }}</span>
215
229
  </div>
216
230
  </div>
217
231
  </slot>
@@ -229,7 +243,7 @@ const handleFetchUsers = (page, limit) => {
229
243
  :disabled="loading"
230
244
  @click="handleFetchUsers(pagination.page - 1)"
231
245
  >
232
- Previous
246
+ {{ props.previousText || t("usersList.previous") }}
233
247
  </button>
234
248
 
235
249
  <button
@@ -237,7 +251,7 @@ const handleFetchUsers = (page, limit) => {
237
251
  :disabled="loading"
238
252
  @click="handleFetchUsers(pagination.page + 1)"
239
253
  >
240
- Next
254
+ {{ props.nextText || t("usersList.next") }}
241
255
  </button>
242
256
  </div>
243
257
  </div>
@@ -2,6 +2,17 @@ interface Props {
2
2
  apiEndpoint?: string;
3
3
  forgotPasswordEndpoint?: string;
4
4
  redirectTo?: string;
5
+ title?: string;
6
+ subtitle?: string;
7
+ emailLabel?: string;
8
+ emailPlaceholder?: string;
9
+ passwordLabel?: string;
10
+ passwordPlaceholder?: string;
11
+ rememberMeLabel?: string;
12
+ submitLabel?: string;
13
+ submittingLabel?: string;
14
+ forgotPasswordLabel?: string;
15
+ forgotPasswordSendingLabel?: string;
5
16
  }
6
17
  declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {}, __VLS_7: {}, __VLS_9: {}, __VLS_11: {}, __VLS_13: {
7
18
  message: string;
@@ -26,15 +37,15 @@ type __VLS_Slots = {} & {
26
37
  'error-message'?: (props: typeof __VLS_15) => any;
27
38
  };
28
39
  declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
29
- success: (user: UserWithoutPassword, rememberMe: boolean) => any;
30
40
  error: (error: string) => any;
31
41
  submit: (data: LoginFormData) => any;
42
+ success: (user: UserWithoutPassword, rememberMe: boolean) => any;
32
43
  "forgot-password-error": (error: string) => any;
33
44
  "forgot-password-success": () => any;
34
45
  }, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
35
- onSuccess?: ((user: UserWithoutPassword, rememberMe: boolean) => any) | undefined;
36
46
  onError?: ((error: string) => any) | undefined;
37
47
  onSubmit?: ((data: LoginFormData) => any) | undefined;
48
+ onSuccess?: ((user: UserWithoutPassword, rememberMe: boolean) => any) | undefined;
38
49
  "onForgot-password-error"?: ((error: string) => any) | undefined;
39
50
  "onForgot-password-success"?: (() => any) | undefined;
40
51
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -2,14 +2,36 @@
2
2
  import { ref, computed } from "vue";
3
3
  import { navigateTo } from "#app";
4
4
  import { useRuntimeConfig } from "#imports";
5
+ import { useNuxtUsersLocale } from "../composables/useNuxtUsersLocale";
5
6
  const { public: { nuxtUsers } } = useRuntimeConfig();
6
7
  const { passwordValidation } = nuxtUsers;
8
+ const { t } = useNuxtUsersLocale();
7
9
  const props = defineProps({
8
10
  apiEndpoint: { type: String, required: false },
9
11
  forgotPasswordEndpoint: { type: String, required: false },
10
- redirectTo: { type: String, required: false }
12
+ redirectTo: { type: String, required: false },
13
+ title: { type: String, required: false },
14
+ subtitle: { type: String, required: false },
15
+ emailLabel: { type: String, required: false },
16
+ emailPlaceholder: { type: String, required: false },
17
+ passwordLabel: { type: String, required: false },
18
+ passwordPlaceholder: { type: String, required: false },
19
+ rememberMeLabel: { type: String, required: false },
20
+ submitLabel: { type: String, required: false },
21
+ submittingLabel: { type: String, required: false },
22
+ forgotPasswordLabel: { type: String, required: false },
23
+ forgotPasswordSendingLabel: { type: String, required: false }
11
24
  });
12
25
  const emit = defineEmits(["success", "error", "forgot-password-error", "submit", "forgot-password-success"]);
26
+ const extractErrorMessage = (err, defaultMessage) => {
27
+ if (err && typeof err === "object" && "data" in err && err.data && typeof err.data === "object" && "statusMessage" in err.data) {
28
+ return String(err.data.statusMessage);
29
+ }
30
+ if (err instanceof Error) {
31
+ return err.message;
32
+ }
33
+ return defaultMessage;
34
+ };
13
35
  const apiEndpoint = computed(() => props.apiEndpoint || `${nuxtUsers?.apiBasePath}/session`);
14
36
  const forgotPasswordEndpoint = computed(() => props.forgotPasswordEndpoint || `${nuxtUsers?.apiBasePath}/password/forgot`);
15
37
  const isLoading = ref(false);
@@ -39,7 +61,7 @@ const handleSubmit = async () => {
39
61
  await navigateTo(props.redirectTo);
40
62
  }
41
63
  } catch (err) {
42
- const errorMessage = err && typeof err === "object" && "data" in err && err.data && typeof err.data === "object" && "statusMessage" in err.data ? String(err.data.statusMessage) : err instanceof Error ? err.message : "Login failed";
64
+ const errorMessage = extractErrorMessage(err, t("login.loginFailed"));
43
65
  error.value = errorMessage;
44
66
  emit("error", errorMessage);
45
67
  } finally {
@@ -48,7 +70,7 @@ const handleSubmit = async () => {
48
70
  };
49
71
  const handleForgotPassword = async () => {
50
72
  if (!formData.value.email) {
51
- error.value = "Please enter your email address first";
73
+ error.value = t("login.emailRequiredForForgotPassword");
52
74
  return;
53
75
  }
54
76
  isForgotPasswordLoading.value = true;
@@ -64,7 +86,7 @@ const handleForgotPassword = async () => {
64
86
  forgotPasswordMessage.value = response.message;
65
87
  emit("forgot-password-success");
66
88
  } catch (err) {
67
- const errorMessage = err && typeof err === "object" && "data" in err && err.data && typeof err.data === "object" && "statusMessage" in err.data ? String(err.data.statusMessage) : err instanceof Error ? err.message : "Failed to send password reset email";
89
+ const errorMessage = extractErrorMessage(err, t("login.forgotPasswordFailed"));
68
90
  error.value = errorMessage;
69
91
  emit("forgot-password-error", errorMessage);
70
92
  } finally {
@@ -80,10 +102,10 @@ const handleForgotPassword = async () => {
80
102
  <slot name="header">
81
103
  <div class="n-users-login-header">
82
104
  <h2 class="n-users-login-title">
83
- Welcome Back
105
+ {{ props.title || t("login.title") }}
84
106
  </h2>
85
107
  <p class="n-users-login-subtitle">
86
- Sign in to your account
108
+ {{ props.subtitle || t("login.subtitle") }}
87
109
  </p>
88
110
  </div>
89
111
  </slot>
@@ -91,13 +113,13 @@ const handleForgotPassword = async () => {
91
113
  <!-- Email field -->
92
114
  <slot name="email-field">
93
115
  <div class="n-users-form-group">
94
- <label for="email">Email</label>
116
+ <label for="email">{{ props.emailLabel || t("common.email") }}</label>
95
117
  <input
96
118
  id="email"
97
119
  v-model="formData.email"
98
120
  type="email"
99
121
  name="email"
100
- placeholder="Enter your email"
122
+ :placeholder="props.emailPlaceholder || t('login.emailPlaceholder')"
101
123
  required
102
124
  >
103
125
  </div>
@@ -106,13 +128,13 @@ const handleForgotPassword = async () => {
106
128
  <!-- Password field -->
107
129
  <slot name="password-field">
108
130
  <div class="n-users-form-group">
109
- <label for="password">Password</label>
131
+ <label for="password">{{ props.passwordLabel || t("login.passwordLabel") }}</label>
110
132
  <input
111
133
  id="password"
112
134
  v-model="formData.password"
113
135
  type="password"
114
136
  name="password"
115
- placeholder="Enter your password"
137
+ :placeholder="props.passwordPlaceholder || t('login.passwordPlaceholder')"
116
138
  required
117
139
  :minlength="passwordValidation.minLength"
118
140
  >
@@ -128,7 +150,7 @@ const handleForgotPassword = async () => {
128
150
  type="checkbox"
129
151
  name="rememberMe"
130
152
  >
131
- <label for="rememberMe">Remember me</label>
153
+ <label for="rememberMe">{{ props.rememberMeLabel || t("login.rememberMe") }}</label>
132
154
  </div>
133
155
  </slot>
134
156
 
@@ -142,7 +164,7 @@ const handleForgotPassword = async () => {
142
164
  v-if="isLoading"
143
165
  class="n-users-loading-spinner"
144
166
  />
145
- {{ isLoading ? "Signing in..." : "Sign In" }}
167
+ {{ isLoading ? props.submittingLabel || t("login.submitting") : props.submitLabel || t("login.submit") }}
146
168
  </button>
147
169
  </slot>
148
170
 
@@ -160,7 +182,7 @@ const handleForgotPassword = async () => {
160
182
  v-if="isForgotPasswordLoading"
161
183
  class="n-users-loading-spinner"
162
184
  />
163
- {{ isForgotPasswordLoading ? "Sending..." : "Forgot your password?" }}
185
+ {{ isForgotPasswordLoading ? props.forgotPasswordSendingLabel || t("login.forgotPasswordSending") : props.forgotPasswordLabel || t("login.forgotPassword") }}
164
186
  </a>
165
187
  </p>
166
188
  </div>
@@ -2,6 +2,17 @@ interface Props {
2
2
  apiEndpoint?: string;
3
3
  forgotPasswordEndpoint?: string;
4
4
  redirectTo?: string;
5
+ title?: string;
6
+ subtitle?: string;
7
+ emailLabel?: string;
8
+ emailPlaceholder?: string;
9
+ passwordLabel?: string;
10
+ passwordPlaceholder?: string;
11
+ rememberMeLabel?: string;
12
+ submitLabel?: string;
13
+ submittingLabel?: string;
14
+ forgotPasswordLabel?: string;
15
+ forgotPasswordSendingLabel?: string;
5
16
  }
6
17
  declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {}, __VLS_7: {}, __VLS_9: {}, __VLS_11: {}, __VLS_13: {
7
18
  message: string;
@@ -26,15 +37,15 @@ type __VLS_Slots = {} & {
26
37
  'error-message'?: (props: typeof __VLS_15) => any;
27
38
  };
28
39
  declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
29
- success: (user: UserWithoutPassword, rememberMe: boolean) => any;
30
40
  error: (error: string) => any;
31
41
  submit: (data: LoginFormData) => any;
42
+ success: (user: UserWithoutPassword, rememberMe: boolean) => any;
32
43
  "forgot-password-error": (error: string) => any;
33
44
  "forgot-password-success": () => any;
34
45
  }, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
35
- onSuccess?: ((user: UserWithoutPassword, rememberMe: boolean) => any) | undefined;
36
46
  onError?: ((error: string) => any) | undefined;
37
47
  onSubmit?: ((data: LoginFormData) => any) | undefined;
48
+ onSuccess?: ((user: UserWithoutPassword, rememberMe: boolean) => any) | undefined;
38
49
  "onForgot-password-error"?: ((error: string) => any) | undefined;
39
50
  "onForgot-password-success"?: (() => any) | undefined;
40
51
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -2,6 +2,7 @@ interface LogoutLinkProps {
2
2
  redirectTo?: string;
3
3
  linkText?: string;
4
4
  confirmMessage?: string;
5
+ loggingOutText?: string;
5
6
  class?: string;
6
7
  style?: string | Record<string, string | number>;
7
8
  linkClass?: string;
@@ -16,17 +17,15 @@ type __VLS_Slots = {} & {
16
17
  default?: (props: typeof __VLS_1) => any;
17
18
  };
18
19
  declare const __VLS_base: import("vue").DefineComponent<LogoutLinkProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
19
- success: () => any;
20
20
  error: (error: string) => any;
21
+ success: () => any;
21
22
  click: () => any;
22
23
  }, string, import("vue").PublicProps, Readonly<LogoutLinkProps> & Readonly<{
23
- onSuccess?: (() => any) | undefined;
24
24
  onError?: ((error: string) => any) | undefined;
25
+ onSuccess?: (() => any) | undefined;
25
26
  onClick?: (() => any) | undefined;
26
27
  }>, {
27
28
  redirectTo: string;
28
- linkText: string;
29
- confirmMessage: string;
30
29
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
31
30
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
32
31
  declare const _default: typeof __VLS_export;
@@ -2,10 +2,13 @@
2
2
  import { ref, onMounted } from "vue";
3
3
  import { navigateTo } from "#app";
4
4
  import { useAuthentication } from "../composables/useAuthentication";
5
+ import { useNuxtUsersLocale } from "../composables/useNuxtUsersLocale";
6
+ const { t } = useNuxtUsersLocale();
5
7
  const props = defineProps({
6
8
  redirectTo: { type: String, required: false, default: "/login" },
7
- linkText: { type: String, required: false, default: "Logout" },
8
- confirmMessage: { type: String, required: false, default: "Are you sure you want to logout?" },
9
+ linkText: { type: String, required: false },
10
+ confirmMessage: { type: String, required: false },
11
+ loggingOutText: { type: String, required: false },
9
12
  class: { type: String, required: false },
10
13
  style: { type: [String, Object], required: false },
11
14
  linkClass: { type: String, required: false },
@@ -24,7 +27,7 @@ onMounted(() => {
24
27
  });
25
28
  const handleLogout = async (event) => {
26
29
  event.preventDefault();
27
- if (!confirm(props.confirmMessage)) {
30
+ if (!confirm(props.confirmMessage || t("logout.confirmMessage"))) {
28
31
  return;
29
32
  }
30
33
  if (!authComposable) {
@@ -71,8 +74,8 @@ const handleLogout = async (event) => {
71
74
  @click="handleLogout"
72
75
  >
73
76
  <slot>
74
- <span v-if="isLoading">Logging out...</span>
75
- <span v-else>{{ linkText }}</span>
77
+ <span v-if="isLoading">{{ props.loggingOutText || t("logout.loggingOut") }}</span>
78
+ <span v-if="!isLoading">{{ props.linkText || t("logout.linkText") }}</span>
76
79
  </slot>
77
80
  </a>
78
81
  </div>
@@ -2,6 +2,7 @@ interface LogoutLinkProps {
2
2
  redirectTo?: string;
3
3
  linkText?: string;
4
4
  confirmMessage?: string;
5
+ loggingOutText?: string;
5
6
  class?: string;
6
7
  style?: string | Record<string, string | number>;
7
8
  linkClass?: string;
@@ -16,17 +17,15 @@ type __VLS_Slots = {} & {
16
17
  default?: (props: typeof __VLS_1) => any;
17
18
  };
18
19
  declare const __VLS_base: import("vue").DefineComponent<LogoutLinkProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
19
- success: () => any;
20
20
  error: (error: string) => any;
21
+ success: () => any;
21
22
  click: () => any;
22
23
  }, string, import("vue").PublicProps, Readonly<LogoutLinkProps> & Readonly<{
23
- onSuccess?: (() => any) | undefined;
24
24
  onError?: ((error: string) => any) | undefined;
25
+ onSuccess?: (() => any) | undefined;
25
26
  onClick?: (() => any) | undefined;
26
27
  }>, {
27
28
  redirectTo: string;
28
- linkText: string;
29
- confirmMessage: string;
30
29
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
31
30
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
32
31
  declare const _default: typeof __VLS_export;
@@ -4,6 +4,12 @@ interface Props {
4
4
  validationResult: PasswordValidationResult | null;
5
5
  showHints?: boolean;
6
6
  showRules?: boolean;
7
+ weakLabel?: string;
8
+ mediumLabel?: string;
9
+ strongLabel?: string;
10
+ unknownLabel?: string;
11
+ requirementsTitleText?: string;
12
+ hintsTitleText?: string;
7
13
  }
8
14
  declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
9
15
  showHints: boolean;
@@ -1,11 +1,19 @@
1
1
  <script setup>
2
2
  import { computed } from "vue";
3
3
  import { useRuntimeConfig } from "#app";
4
+ import { useNuxtUsersLocale } from "../composables/useNuxtUsersLocale";
5
+ const { t } = useNuxtUsersLocale();
4
6
  const props = defineProps({
5
7
  password: { type: String, required: true },
6
8
  validationResult: { type: null, required: true },
7
9
  showHints: { type: Boolean, required: false, default: true },
8
- showRules: { type: Boolean, required: false, default: true }
10
+ showRules: { type: Boolean, required: false, default: true },
11
+ weakLabel: { type: String, required: false },
12
+ mediumLabel: { type: String, required: false },
13
+ strongLabel: { type: String, required: false },
14
+ unknownLabel: { type: String, required: false },
15
+ requirementsTitleText: { type: String, required: false },
16
+ hintsTitleText: { type: String, required: false }
9
17
  });
10
18
  const { public: { nuxtUsers } } = useRuntimeConfig();
11
19
  const moduleOptions = nuxtUsers;
@@ -18,35 +26,35 @@ const validationRules = computed(() => {
18
26
  if (moduleOptions.passwordValidation.minLength) {
19
27
  const hasMinLength = props.password.length >= moduleOptions.passwordValidation.minLength;
20
28
  rules.push({
21
- text: `At least ${moduleOptions.passwordValidation.minLength} characters`,
29
+ text: t("passwordStrength.minLength", [moduleOptions.passwordValidation.minLength]),
22
30
  passed: hasMinLength
23
31
  });
24
32
  }
25
33
  if (moduleOptions.passwordValidation.requireUppercase) {
26
34
  const hasUppercase = /[A-Z]/.test(props.password);
27
35
  rules.push({
28
- text: "Contains uppercase letter (A-Z)",
36
+ text: t("passwordStrength.uppercase"),
29
37
  passed: hasUppercase
30
38
  });
31
39
  }
32
40
  if (moduleOptions.passwordValidation.requireLowercase) {
33
41
  const hasLowercase = /[a-z]/.test(props.password);
34
42
  rules.push({
35
- text: "Contains lowercase letter (a-z)",
43
+ text: t("passwordStrength.lowercase"),
36
44
  passed: hasLowercase
37
45
  });
38
46
  }
39
47
  if (moduleOptions.passwordValidation.requireNumbers) {
40
48
  const hasNumbers = /\d/.test(props.password);
41
49
  rules.push({
42
- text: "Contains number (0-9)",
50
+ text: t("passwordStrength.number"),
43
51
  passed: hasNumbers
44
52
  });
45
53
  }
46
54
  if (moduleOptions.passwordValidation.requireSpecialChars) {
47
55
  const hasSpecialChars = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(props.password);
48
56
  rules.push({
49
- text: "Contains special character (!@#$%^&*)",
57
+ text: t("passwordStrength.specialChar"),
50
58
  passed: hasSpecialChars
51
59
  });
52
60
  }
@@ -74,7 +82,7 @@ const validationRules = computed(() => {
74
82
  color: validationResult?.strength === 'weak' ? '#dc3545' : validationResult?.strength === 'medium' ? '#ffc107' : validationResult?.strength === 'strong' ? '#28a745' : '#6c757d'
75
83
  }"
76
84
  >
77
- {{ validationResult?.strength === "weak" ? "Weak" : validationResult?.strength === "medium" ? "Medium" : validationResult?.strength === "strong" ? "Strong" : "Unknown" }}
85
+ {{ validationResult?.strength === "weak" ? props.weakLabel || t("passwordStrength.weak") : validationResult?.strength === "medium" ? props.mediumLabel || t("passwordStrength.medium") : validationResult?.strength === "strong" ? props.strongLabel || t("passwordStrength.strong") : props.unknownLabel || t("passwordStrength.unknown") }}
78
86
  ({{ validationResult?.score || 0 }}%)
79
87
  </span>
80
88
  </div>
@@ -85,7 +93,7 @@ const validationRules = computed(() => {
85
93
  class="n-users-validation-rules n-users-validation-container"
86
94
  >
87
95
  <div class="n-users-rules-title n-users-container-title">
88
- Password Requirements:
96
+ {{ props.requirementsTitleText || t("passwordStrength.label") }}
89
97
  </div>
90
98
  <ul class="n-users-rules-list n-users-list-unstyled">
91
99
  <li
@@ -124,7 +132,7 @@ const validationRules = computed(() => {
124
132
  class="n-users-password-hints n-users-validation-container"
125
133
  >
126
134
  <div class="n-users-hint-title n-users-container-title">
127
- How to make your password stronger:
135
+ {{ props.hintsTitleText || t("passwordStrength.hintsTitle") }}
128
136
  </div>
129
137
  <ul class="n-users-hint-list n-users-list-unstyled">
130
138
  <li
@@ -4,6 +4,12 @@ interface Props {
4
4
  validationResult: PasswordValidationResult | null;
5
5
  showHints?: boolean;
6
6
  showRules?: boolean;
7
+ weakLabel?: string;
8
+ mediumLabel?: string;
9
+ strongLabel?: string;
10
+ unknownLabel?: string;
11
+ requirementsTitleText?: string;
12
+ hintsTitleText?: string;
7
13
  }
8
14
  declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
9
15
  showHints: boolean;
@@ -1,3 +1,15 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
1
+ interface Props {
2
+ title?: string;
3
+ nameLabel?: string;
4
+ emailLabel?: string;
5
+ roleLabel?: string;
6
+ registeredLabel?: string;
7
+ lastUpdatedLabel?: string;
8
+ activeLabel?: string;
9
+ idLabel?: string;
10
+ yesText?: string;
11
+ noText?: string;
12
+ }
13
+ declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
2
14
  declare const _default: typeof __VLS_export;
3
15
  export default _default;
@@ -1,6 +1,20 @@
1
1
  <script setup>
2
2
  import { computed, onMounted, ref } from "vue";
3
3
  import { useAuthentication } from "../composables/useAuthentication";
4
+ import { useNuxtUsersLocale } from "../composables/useNuxtUsersLocale";
5
+ const { t } = useNuxtUsersLocale();
6
+ const props = defineProps({
7
+ title: { type: String, required: false },
8
+ nameLabel: { type: String, required: false },
9
+ emailLabel: { type: String, required: false },
10
+ roleLabel: { type: String, required: false },
11
+ registeredLabel: { type: String, required: false },
12
+ lastUpdatedLabel: { type: String, required: false },
13
+ activeLabel: { type: String, required: false },
14
+ idLabel: { type: String, required: false },
15
+ yesText: { type: String, required: false },
16
+ noText: { type: String, required: false }
17
+ });
4
18
  const authComposable = ref(null);
5
19
  const user = computed(() => authComposable.value?.user ?? null);
6
20
  onMounted(() => {
@@ -11,31 +25,31 @@ onMounted(() => {
11
25
  <template>
12
26
  <div class="n-users-profile-info n-users-section">
13
27
  <h2 class="n-users-section-header">
14
- Profile Information
28
+ {{ props.title || t("profile.title") }}
15
29
  </h2>
16
30
  <dl
17
31
  v-if="user"
18
32
  class="n-users-profile-details n-users-grid n-users-grid-2"
19
33
  >
20
- <dt>Name:</dt>
34
+ <dt>{{ props.nameLabel || t("profile.name") }}</dt>
21
35
  <dd>{{ user.name }}</dd>
22
36
 
23
- <dt>Email:</dt>
37
+ <dt>{{ props.emailLabel || t("profile.email") }}</dt>
24
38
  <dd>{{ user.email }}</dd>
25
39
 
26
- <dt>Role:</dt>
40
+ <dt>{{ props.roleLabel || t("profile.role") }}</dt>
27
41
  <dd>{{ user.role }}</dd>
28
42
 
29
- <dt>Registered:</dt>
43
+ <dt>{{ props.registeredLabel || t("profile.registered") }}</dt>
30
44
  <dd>{{ Intl.DateTimeFormat().format(new Date(user.created_at)) }}</dd>
31
45
 
32
- <dt>Last updated:</dt>
46
+ <dt>{{ props.lastUpdatedLabel || t("profile.lastUpdated") }}</dt>
33
47
  <dd>{{ Intl.DateTimeFormat().format(new Date(user.updated_at)) }}</dd>
34
48
 
35
- <dt>Active:</dt>
36
- <dd>{{ user.active ? "Yes" : "No" }}</dd>
49
+ <dt>{{ props.activeLabel || t("profile.active") }}</dt>
50
+ <dd>{{ user.active ? props.yesText || t("common.yes") : props.noText || t("common.no") }}</dd>
37
51
 
38
- <dt>ID:</dt>
52
+ <dt>{{ props.idLabel || t("profile.id") }}</dt>
39
53
  <dd>{{ user.id }}</dd>
40
54
  </dl>
41
55
  </div>
@@ -1,3 +1,15 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
1
+ interface Props {
2
+ title?: string;
3
+ nameLabel?: string;
4
+ emailLabel?: string;
5
+ roleLabel?: string;
6
+ registeredLabel?: string;
7
+ lastUpdatedLabel?: string;
8
+ activeLabel?: string;
9
+ idLabel?: string;
10
+ yesText?: string;
11
+ noText?: string;
12
+ }
13
+ declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
2
14
  declare const _default: typeof __VLS_export;
3
15
  export default _default;