Skip to content

Commit 028b5d7

Browse files
Merge pull request #672 from aXenDeveloper/email-lang
feat: Add lang files support for email
2 parents bfedac4 + 3f3af69 commit 028b5d7

File tree

19 files changed

+687
-110
lines changed

19 files changed

+687
-110
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"@vitnode/blog": {
3+
"title": "Blog",
4+
"admin": {
5+
"nav": {
6+
"posts": "Posts",
7+
"categories": "Categories"
8+
},
9+
"categories": {
10+
"desc": "Manage categories for blog posts.",
11+
"table": {
12+
"title": "Title",
13+
"updated_at": "Updated At"
14+
},
15+
"delete": {
16+
"title": "Delete Category",
17+
"desc": "Are you sure you want to delete <title></title> category? This action cannot be undone.",
18+
"confirm": "Yes, delete this category",
19+
"success": "Category has been deleted successfully."
20+
},
21+
"create": {
22+
"title": "Create Category",
23+
"desc": "A new category for your blog posts.",
24+
"form": {
25+
"title": {
26+
"label": "Title",
27+
"already_exists": "This category title already exists."
28+
}
29+
},
30+
"submit": "Create"
31+
},
32+
"edit": {
33+
"title": "Edit Category",
34+
"submit": "Save Changes"
35+
}
36+
},
37+
"posts": {
38+
"desc": "Write and manage your blog posts.",
39+
"table": {
40+
"title": "Title",
41+
"category": "Category",
42+
"updated_at": "Updated At"
43+
},
44+
"create": {
45+
"title": "Create Post",
46+
"desc": "Write a new article for your blog.",
47+
"form": {
48+
"title": {
49+
"label": "Title",
50+
"already_exists": "This post title already exists."
51+
},
52+
"content": "Content",
53+
"category": "Category"
54+
},
55+
"submit": "Create Post"
56+
},
57+
"edit": {
58+
"title": "Edit Post",
59+
"submit": "Save Changes"
60+
},
61+
"delete": {
62+
"title": "Delete Post",
63+
"desc": "Are you sure you want to delete <title></title> post? This action cannot be undone.",
64+
"confirm": "Yes, delete this post",
65+
"success": "Post has been deleted successfully."
66+
}
67+
}
68+
}
69+
}
70+
}
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
{
2+
"core": {
3+
"global": {
4+
"theme_switcher": "Toggle Theme",
5+
"language_switcher": "Switch Language",
6+
"toggle_sidebar": "Toggle Sidebar",
7+
"no_results": {
8+
"title": "No results found",
9+
"desc": "Try adjusting your search or filter criteria."
10+
},
11+
"are_you_sure_want_to_leave_form": {
12+
"title": "Are you sure you want to leave this form?",
13+
"desc": "Your changes will not be saved.",
14+
"cancel": "Cancel",
15+
"confirm": "Yes, leave"
16+
},
17+
"confirm_action": {
18+
"title": "Are you sure?",
19+
"desc": "This action cannot be undone.",
20+
"cancel": "Cancel",
21+
"confirm": "Yes, confirm"
22+
},
23+
"search_placeholder": "Search...",
24+
"results_not_found": "No results found",
25+
"date": "{date, date}",
26+
"date_medium": "{date, date, medium}",
27+
"date_short": "{date, date, short}",
28+
"register": "Register",
29+
"login": "Login",
30+
"save": "Save",
31+
"submit": "Submit",
32+
"cancel": "Cancel",
33+
"optional": "Optional",
34+
"loading": "Loading...",
35+
"or": "or",
36+
"back_home": "Back to home",
37+
"go_back": "Go back",
38+
"select_option": "Select an option",
39+
"select_options": "Select options",
40+
"go_to_prev_page": "Go to previous page",
41+
"go_to_next_page": "Go to next page",
42+
"errors": {
43+
"title": "Oops! Something went wrong.",
44+
"internal_server_error": "Internal server error.",
45+
"field_required": "This field is required.",
46+
"field_min_length": "This field must be at least {min} characters.",
47+
"captcha_internal_error": "Captcha validation failed. Please try again later.",
48+
"404": {
49+
"title": "Page Not Found",
50+
"desc": "Oops! The page you're looking for doesn't exist."
51+
},
52+
"500": {
53+
"title": "Internal Server Error",
54+
"desc": "Sorry, we're experiencing technical difficulties on our server."
55+
},
56+
"400": {
57+
"title": "Bad Request",
58+
"desc": "The request couldn't be processed due to invalid parameters."
59+
},
60+
"403": {
61+
"title": "Forbidden",
62+
"desc": "You don't have permission to access this resource."
63+
}
64+
},
65+
"user_bar": {
66+
"log_out": "Log out",
67+
"admin_cp": "Admin CP"
68+
}
69+
},
70+
"auth": {
71+
"sso": {
72+
"or": "Or continue With",
73+
"access_denied": "You have denied access to the application or the request has expired. Please try again."
74+
},
75+
"sign_up": {
76+
"desc": "Hello there! Create your account to get started.",
77+
"already_have_account": "You already have an account? <link>Sign in</link>.",
78+
"submit": "Register",
79+
"username": {
80+
"label": "Username",
81+
"min_length": "Username must be at least 3 characters long.",
82+
"max_length": "Username must be at most 32 characters long.",
83+
"exists": "Username already exists.",
84+
"your_user_code": "Your user code: <code></code>"
85+
},
86+
"email": {
87+
"label": "Email",
88+
"invalid": "Invalid email address.",
89+
"exists": "Email already exists."
90+
},
91+
"password": {
92+
"label": "Password",
93+
"invalid": "Password is too weak.",
94+
"requirements": {
95+
"label": "Password should contain:",
96+
"min_length": "At least 8 characters",
97+
"uppercase": "At least one uppercase letter",
98+
"number": "At least one number",
99+
"special_char": "At least one special character"
100+
}
101+
},
102+
"terms": {
103+
"label": "Accept terms and conditions",
104+
"required": "You must accept the terms and conditions.",
105+
"desc": "You agree to our <link>Legal documents & Policies</link>."
106+
},
107+
"newsletter": {
108+
"label": "Newsletter",
109+
"desc": "Receive the latest news and updates."
110+
},
111+
"email_confirmation": {
112+
"title": "Check your email",
113+
"desc": "We've sent a confirmation link to your email address",
114+
"check_spam": "If you don't see the email in your inbox, please check your spam folder."
115+
}
116+
},
117+
"sign_in": {
118+
"desc": "Welcome back! Sign in to your account.",
119+
"do_not_have_account": "Don't have an account? <link>Sign up</link>.",
120+
"email": {
121+
"label": "Email",
122+
"invalid": "Invalid email address."
123+
},
124+
"password": {
125+
"label": "Password",
126+
"required": "Password is required."
127+
},
128+
"errors": {
129+
"access_denied": {
130+
"title": "Invalid credentials",
131+
"desc": "The email address or password was incorrect. Please try again (make sure your caps lock is off)."
132+
}
133+
},
134+
"submit": "Login"
135+
}
136+
}
137+
},
138+
"admin": {
139+
"dashboard": {
140+
"dev_mode": "Development Mode",
141+
"version": "Version: {version}"
142+
},
143+
"global": {
144+
"nav": {
145+
"core": "Core",
146+
"dashboard": "Dashboard",
147+
"users": {
148+
"title": "Users",
149+
"list": "User List"
150+
},
151+
"user_bar": {
152+
"home_page": "Home Page",
153+
"debug": "Debug Panel",
154+
"log_out": "Log Out"
155+
}
156+
}
157+
},
158+
"user": {
159+
"list": {
160+
"desc": "Manage users of your application.",
161+
"user": "User",
162+
"createdAt": "Created At",
163+
"emailNotVerified": "Email Not Verified"
164+
}
165+
},
166+
"debug": {
167+
"title": "Debug Panel",
168+
"desc": "Check logs, errors, and other debug information.",
169+
"actions": {
170+
"clear_cache": {
171+
"label": "Clear Cache",
172+
"title": "Are you sure you want to clear the cache?",
173+
"desc": "This action will remove all cached data, which may affect performance temporarily.",
174+
"success": "Cache cleared successfully.",
175+
"confirm": "Yes, clear cache"
176+
}
177+
},
178+
"logs": {
179+
"title": "System Logs",
180+
"created_at": "Created At",
181+
"plugin": "Plugin",
182+
"content": "Content",
183+
"type": "Type",
184+
"types": {
185+
"warn": "Warning",
186+
"error": "Error",
187+
"debug": "Debug"
188+
},
189+
"status_code": "Status Code",
190+
"more": {
191+
"title": "More Details",
192+
"desc": "Log ID: <logId></logId>",
193+
"log_overview": {
194+
"title": "Log Overview",
195+
"log_type": "Log Type",
196+
"status_code": "Status Code",
197+
"log_id": "Log ID",
198+
"created_at": "Created At",
199+
"plugin": "Plugin",
200+
"user": "User"
201+
},
202+
"request_information": {
203+
"title": "Request Information",
204+
"ip_address": "IP Address",
205+
"request_method": "Request Method",
206+
"request_url": "Request URL",
207+
"user_agent": "User Agent"
208+
},
209+
"log_content": {
210+
"title": "Log Content",
211+
"full_log": "Full Log Message"
212+
}
213+
}
214+
}
215+
}
216+
}
217+
}

apps/api/src/vitnode.api.config.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { NodemailerEmailAdapter } from '@vitnode/core/api/adapters/email/nodemailer';
12
import { buildApiConfig } from '@vitnode/core/vitnode.config';
23
import * as dotenv from 'dotenv';
34
import { drizzle } from 'drizzle-orm/postgres-js';
@@ -12,10 +13,19 @@ export const POSTGRES_URL =
1213

1314
export const vitNodeApiConfig = buildApiConfig({
1415
plugins: [],
16+
pathToMessages: async path => await import(`./locales/${path}`),
1517
dbProvider: drizzle({
1618
connection: POSTGRES_URL,
1719
casing: 'camelCase',
1820
}),
21+
email: {
22+
adapter: NodemailerEmailAdapter({
23+
from: process.env.NODE_MAILER_FROM,
24+
host: process.env.NODE_MAILER_HOST,
25+
password: process.env.NODE_MAILER_PASSWORD,
26+
user: process.env.NOD_EMAILER_USER,
27+
}),
28+
},
1929
metadata: {
2030
title: 'VitNode API',
2131
shortTitle: 'VitNode',

apps/docs/src/app/[locale]/(main)/(home)/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const metadata: Metadata = {
1919
export default function HomePage() {
2020
return (
2121
<div className="container">
22-
<section className="border-border/50 mt-10 flex flex-col justify-between gap-20 border-r bg-[linear-gradient(to_right,color-mix(in_oklab,var(--border)_75%,transparent)_1px,transparent_1px),linear-gradient(to_bottom,color-mix(in_oklab,var(--border)_75%,transparent)_1px,transparent_1px)] bg-[size:63px_63px] px-10 py-20 lg:flex-row dark:bg-[linear-gradient(to_right,color-mix(in_oklab,var(--border)_50%,transparent)_1px,transparent_1px),linear-gradient(to_bottom,color-mix(in_oklab,var(--border)_50%,transparent)_1px,transparent_1px)]">
22+
<section className="border-border/50 mt-6 flex flex-col justify-between gap-20 border-r bg-[linear-gradient(to_right,color-mix(in_oklab,var(--border)_75%,transparent)_1px,transparent_1px),linear-gradient(to_bottom,color-mix(in_oklab,var(--border)_75%,transparent)_1px,transparent_1px)] bg-[size:63px_63px] px-6 py-10 sm:mt-10 sm:px-10 sm:py-20 lg:flex-row dark:bg-[linear-gradient(to_right,color-mix(in_oklab,var(--border)_50%,transparent)_1px,transparent_1px),linear-gradient(to_bottom,color-mix(in_oklab,var(--border)_50%,transparent)_1px,transparent_1px)]">
2323
<div className="flex max-w-2xl flex-col">
2424
<h1 className="text-balance text-5xl font-semibold tracking-tight sm:text-6xl">
2525
Extendable <span className="text-primary">Framework</span> for

apps/docs/src/vitnode.api.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const POSTGRES_URL =
1111
process.env.POSTGRES_URL || 'postgresql://root:root@localhost:5432/vitnode';
1212

1313
export const vitNodeApiConfig = buildApiConfig({
14+
pathToMessages: async path => await import(`./locales/${path}`),
1415
captcha: {
1516
type: 'cloudflare_turnstile',
1617
siteKey: process.env.CLOUDFLARE_TURNSTILE_SITE_KEY,

packages/create-vitnode-app/copy-of-vitnode-app/api-single-app/src/vitnode.api.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const POSTGRES_URL =
66
process.env.POSTGRES_URL || 'postgresql://root:root@localhost:5432/vitnode';
77

88
export const vitNodeApiConfig = buildApiConfig({
9+
pathToMessages: async path => await import(`./locales/${path}`),
910
metadata: {
1011
title: 'VitNode',
1112
shortTitle: 'VitNode',

packages/create-vitnode-app/src/create/create-vitnode.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,26 @@ export const createVitNode = async ({
217217
cwd: root,
218218
});
219219

220-
if (mode !== 'onlyApi') {
221-
spinner.text = 'Initializing VitNode files...';
220+
spinner.text = 'Initializing VitNode files...';
221+
if (mode === 'apiMonorepo') {
222+
await Promise.all([
223+
initFilesVitnode({
224+
packageManager,
225+
cwd: monorepoStructure.web,
226+
}),
227+
initFilesVitnode({
228+
packageManager,
229+
cwd: monorepoStructure.api,
230+
}),
231+
initFilesVitnode({
232+
packageManager,
233+
cwd: root,
234+
}),
235+
]);
236+
} else {
222237
initFilesVitnode({
223238
packageManager,
224-
cwd: mode === 'apiMonorepo' || monorepo ? monorepoStructure.web : root,
239+
cwd: root,
225240
});
226241
}
227242

packages/vitnode/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@
2727
"drizzle-kit": "0.31.x",
2828
"drizzle-orm": "^0.44.x",
2929
"hono": "4.8.x",
30+
"motion": "^12.x.x",
3031
"next": "15.3.x",
3132
"next-intl": "4.x.x",
3233
"react": "19.1.x",
3334
"react-dom": "19.1.x",
3435
"react-hook-form": "^7.x.x",
35-
"motion": "^12.x.x",
3636
"typescript": "^5.8.x",
3737
"zod": "4.x.x"
3838
},
@@ -126,6 +126,7 @@
126126
"resend": "^4.7.0",
127127
"tailwind-merge": "^3.3.1",
128128
"use-debounce": "^10.0.5",
129+
"use-intl": "^4.3.4",
129130
"vaul": "^1.1.2"
130131
}
131132
}

0 commit comments

Comments
 (0)