Cách sử dụng Vuejs và CMS Strapi để làm chức năng đa ngôn ngữ
Em đang sử dụng VueJS để làm giao diện và quản lý CMS + nội dung bằng Strapi, Strapi đã hỗ trợ em tạo ra các bản ghi đa ngôn ngữ trong một bảng dữ liệu chỉ cần khi call api gọi theo đúng cái key locales='xxx' là được.
Tuy nhiên em vẫn chưa biết cách làm sao để nó có thể hoạt động. Theo logic của em trong cái dropdown để thay đổi ngôn ngữ khi em click vào EN hoặc VI thì sẽ check điều kiện để thay đổi đường dẫn call api... Nhưng cú pháp thuật toán em vẫn chưa biết nên xử lý ntn, mong nhận được sự giúp đỡ từ mn ^^ em cảm ơn!
1 CÂU TRẢ LỜI
Bạn tham khảo thử cách sau.
Ví dụ Strapi API bạn có route /api/movies
để lấy danh sách phim từ Strapi. Khi call API thì nhận được content dạng như:
{
"data": [
{
"id": 1,
"attributes": {
"name": "The Terminator",
"slug": "the-terminator",
"description": "Super robot saves the world from evil AI",
"locale": "en"
}
}
]
}
Danh sách phim đã được đa ngữ sẽ có 2 route /api/movies?locale=en
(EN) và /api/movies?locale=vi
(VI). Route VI của bạn sẽ có dạng như:
{
"data": [
{
"id": 1,
"attributes": {
"name": "Kẻ hủy diệt",
"slug": "ke-huy-diet",
"description": "Siêu người máy giải cứu khỏi bọn AI xấu xa",
"locale": "vi"
}
}
]
}
Như bạn thấy thì chỉ có phần content được thay đổi cho đa ngữ, các attribute key như name
, description
vẫn giống nhau, nên trong Vue component, sau khi mount, bạn chỉ việc gọi đến API route tương ứng rồi render dựa theo các key đó là được.
<template>
<ul>
<li v-for="movie in movies" :key="movie.id">
<h2>{{ movie.name }}</h2>
<p>{{ movie.description }}</p>
</li>
</ul>
</template>
<script>
export default {
data() {
return {
movies: []
};
},
async mounted() {
const { data } = await fetch(`/api/movies?locale=${locale}`);
this.movies = data;
}
};
</script>
locale
bạn có thấy truy xuất từ route nếu dùng vue router, hoặc từ prop của component, hoặc thậm chí từ localStorage.
@khangnd vâng ạ nhưng điều em chưa làm được ở đây chính là cái locale ở router ấy a, thực tế em chưa làm bh ạ, bh em sẽ có 1 cái dropdown và 2 cái lá cờ click vào cờ Anh thì sẽ có thêm cái /en phía sau và load lại hết nội dung của web lun ấy ạ... Câu trả lời của anh chi tiết quá em cảm ơn nhiều nếu được anh có thể chỉ dẫn e lm luôn cái router kia đc ko ạ, em xin gửi anh ly cf với ạ ^^ một lần nữa em cảm ơn nhiều
@binchanhkun99 Mình ko rõ bạn đang dùng Vue + Vue Router version mấy với cũng lâu rồi ko code Vue 😄 nhưng nhìn chung thì ý tưởng vẫn là bạn quy định format của route như thế nào thì bạn cứ dựa vào đó mà truy xuất locale
(keyword ở đây là "dynamic routing"). Ví dụ như trang danh sách phim của bạn có route dạng /movies/en
hay /movies/vi
, thì format sẽ là /movies/:locale
, rồi trong component bạn muốn truy xuất locale thì chỉ việc gọi this.$route.params.locale
.
Bạn có thể đọc thêm tại https://router.vuejs.org/guide/essentials/dynamic-matching.html. Bạn cứ đặt câu hỏi trên này, mn có thời gian thì sẽ giải đáp cho, còn hướng dẫn 1-1 thì chắc là khó 🙂
@khangnd e đang xài Vue 2 và Vue router 3.2 thôi a ạ, em muốn hỏi thêm anh là ví dụ như em đang xài cái dynamic routing này để làm luôn thanh menu thì sẽ có thêm một trường ở trong tag router link là 'exact' để làm cái mặc định nó sáng màu vậy giờ em lm đa ngôn ngữ chắc e sẽ phải dùng v-for v thì lmsao để set cho thằng đầu tiên luôn có thuộc tính exact đc ạ? Em cảm ơn
Ui em đã làm đc cho trang chủ rồi a, nhưng ví dụ em muốn vào một trang khác nhưng nó vẫn giữ nguyên cái ngôn ngữ khi mà em bấm chọn ở trang chủ thì em phải làm ntn ạ? thanks a ^^
@binchanhkun99 bạn có thể xử lý trong hàm beforeEach
của router (docs tham khảo). Hàm này được trigger mỗi khi bạn điều hướng đi bất kì trang nào, thường được sử dụng để xử lý authentication, nhưng bạn cũng có thể tận dụng để xử lý giữ nguyên ngôn ngữ từ trang hiện tại sang trang khác.
router.beforeEach((to, from, next) => {
next({
name: to.name,
params: { locale: from.params.locale || 'en' }
})
});
@khangnd Dạ vâng ạ, nhưng ví dụ em từ trang chủ muốn sang trang tuyển dụng thì phải làm như thế nào v anh? ._.