Skip to content

Commit 854d77a

Browse files
author
misostack
committed
add sample multi language
1 parent 2ea417b commit 854d77a

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

content/post/khoa-hoc-nextjs-bai-03-advanced-routing.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Các nội dung chính trong bài học lần này:
1616
1. Phân quyền và chuyển hướng
1717
2. Tạo layout dùng chung
1818
3. Loading Screen
19+
4. I18n - đa ngôn ngữ
1920

2021
Với nội dung trên, chúng ta sẽ tiếp tục với việc phân quyền và chuyển hướng, cũng như thực hành chia layout dùng chung, hiển thị màn hình chờ ( loading screen )
2122

@@ -232,4 +233,144 @@ export function middleware(req: NextRequest) {
232233

233234
## Loading Screen
234235

236+
Trong một trang web có quá nhiều block không cần thiết phải hiện thị ngay. Như ví dụ bên dưới, thì thông tin khi khách hàng vừa truy cập vào cần thấy ngay thông thường sẽ là header, main content (top products). Còn phần random products có thể hiển thị sau.
237+
235238
![image](https://gist.github.com/assets/31009750/34e5e0b7-2cd2-4c2a-8e3b-656fbe0b4271)
239+
240+
Với một trang web thông thường chúng ta sẽ sử dụng AJAX để lazy load phần này.
241+
Ngay trong NextJS, chỉ cần với cú pháp đơn giản, ta có ngay kết quả như trên.
242+
243+
Dưới đây là cơ chế của nextjs
244+
245+
![image](https://gist.github.com/assets/31009750/b2e916b4-edd0-40a1-9514-8518a1dc0e23)
246+
247+
1. Đầu tiên khi client request lên server, lúc này theo trình tự server sẽ generate html từ page component
248+
2. Nếu trong page có các component được gói trong tag Suspend, thì được chuyển đổi để load sau với javascript
249+
3. Khi trang web được tải xuống thì tài nguyên html sẽ được tải xuống trước, trong lúc đó javascript cùng được tải đồng thời (sẽ có đoạn mã kiểm soát phần tải các component cần stream ). Khi các script này được thực thi thì quá trình stream data diễn ra, trước đó nextjs sẽ tự động tạo ra các placeholder có nội dung mà bạn đã define trong Loading Component. Sau khi dữ liệu sẵn sàng, toàn bộ component của bạn sẽ xuất hiện trên giao diện.
250+
4. Trong lúc stream diễn ra, bạn hoàn toàn vẫn tương tác được với trang web, đây chính là điểm mấu chốt của công nghệ này.
251+
252+
Lợi ích:
253+
254+
- Thời gian tải trang nhanh
255+
- Hiển thị nội dung các cùng chờ thân thiện với user
256+
257+
Nào cũng xem code
258+
259+
> src/components/SlowComponent.tsx
260+
261+
```ts
262+
const wait = (timeout: number) => {
263+
return new Promise((resolve) => {
264+
setTimeout(() => {
265+
fetch("https://jsonplaceholder.typicode.com/todos/1")
266+
.then((res) => res.json())
267+
.then((data) => resolve(data));
268+
}, timeout);
269+
});
270+
};
271+
export const SlowComponent = async () => {
272+
const data: any = await wait(5000);
273+
274+
return (
275+
<>
276+
<p>{JSON.stringify(data)}</p>
277+
</>
278+
);
279+
};
280+
```
281+
282+
> src/app/page.tsx
283+
284+
```ts
285+
import { SlowComponent } from "@/components/SlowComponent";
286+
import Link from "next/link";
287+
import { Suspense } from "react";
288+
import Loading from "./loading";
289+
290+
export default function Home() {
291+
return (
292+
<main className="container-xl mx-auto p-4">
293+
<h1>Home Page</h1>
294+
<p>Links to other pages with a tag</p>
295+
<ul>
296+
<li>
297+
<a href="/products">Products</a>
298+
</li>
299+
<li>
300+
<a href="/products/mouse-pad-nextjsvietnam">
301+
Mouse Pad NextJSVietNam
302+
</a>
303+
</li>
304+
<li>
305+
<a href="/cart">Cart</a>
306+
</li>
307+
<li>
308+
<a href="/order">Order</a>
309+
</li>
310+
<li>
311+
<a href="/my-account">My Account</a>
312+
</li>
313+
<li>
314+
<a href="/my-account/orders">My orders</a>
315+
</li>
316+
<li>
317+
<a href="/my-account/orders/1">My order detail</a>
318+
</li>
319+
</ul>
320+
<p>Links to other pages with Link tag</p>
321+
<ul>
322+
<li>
323+
<Link href="/products">Products</Link>
324+
</li>
325+
</ul>
326+
<h2>Slow Component</h2>
327+
<Suspense fallback={<Loading />}>
328+
<SlowComponent></SlowComponent>
329+
</Suspense>
330+
</main>
331+
);
332+
}
333+
```
334+
335+
## I18n - Đa ngôn ngữ
336+
337+
Thông thường khi làm việc với React, để làm website đa ngôn ngữ chúng ta hay sử dụng https://react.i18next.com/ giúp việc setup trở nên dễ dàng.
338+
339+
Còn trong nextjs thì chúng ta làm thế nào, khá đơn giản, các bạn nhớ quy tắc về cấu trúc thư mục chứ. Lúc này chúng ta chỉ cần tạo cấu trúc thư mục tương ứng
340+
341+
```
342+
[lang]
343+
page.tsx
344+
dictionaries.ts
345+
dictionaries
346+
en.json
347+
vi.json
348+
```
349+
350+
```json
351+
{
352+
"products": {
353+
"cart": "Add to Cart"
354+
}
355+
}
356+
```
357+
358+
```ts
359+
import "server-only";
360+
361+
const dictionaries = {
362+
en: () => import("./dictionaries/en.json").then((module) => module.default),
363+
nl: () => import("./dictionaries/vi.json").then((module) => module.default),
364+
};
365+
366+
export const getDictionary = async (locale) => dictionaries[locale]();
367+
```
368+
369+
```tsx
370+
import { getDictionary } from "./dictionaries";
371+
372+
export default async function Page({ params: { lang } }) {
373+
const dict = await getDictionary(lang); // en
374+
return <button>{dict.products.cart}</button>; // Add to Cart
375+
}
376+
```

0 commit comments

Comments
 (0)