Làm sao để ứng dụng Vue không chỉ dùng được cho một ngôn ngữ mà có thể “nói chuyện” với người dùng ở nhiều vùng miền khác nhau?
Việc bản địa hoá (localization) cùng quốc tế hoá (internationalization) giúp mở rộng phạm vi người dùng và nâng cao trải nghiệm.
1. Khởi tạo ứng dụng và cài đặt vue-i18n
Bắt đầu bằng việc tạo một project Vue mới (giả sử dùng CLI):
vue create localisation-app
Chọn thêm các gói như vue-router và vuex (sẽ dùng sau). Sau đó cài vue-i18n bằng cách:
cd localisation-app
vue add i18n
Gói này sẽ tự thiết lập cấu trúc ban đầu và tạo thư mục locales với tệp mặc định như en.json. Ví dụ en.json:
{
"hello": "hello i18n !!",
"welcomeMessage": "Welcome to Advanced Localization techniques tutorial"
}
Sau đó bạn tạo thêm file chẳng hạn fr.json để dịch sang tiếng Pháp:
{
"hello": "Bonjour i18n !!",
"welcomeMessage": "Bienvenue dans le didacticiel sur les techniques de localisation avancées"
}
Trong App.vue, bạn có thể sử dụng:
<HelloWorld :msg="$t('hello')" />
Và trong component HelloWorld.vue:
<p>{{ $t('welcomeMessage') }}</p>
<select v-model="$i18n.locale">
<option v-for="lang in languageArray" :value="lang">{{ lang }}</option>
</select>
Như vậy, người dùng có thể chọn ngôn ngữ từ dropdown và ứng dụng sẽ hiển thị các chuỗi tương ứng.
2. Cấu trúc thư mục và quản lý file ngôn ngữ của vue-i18n
Một cách quản lý tốt là để các file JSON dịch nằm trong thư mục như:
src/
plugins/
i18n.js
locales/
formats/
en.json
fr.json
zh.json
de.json
Điều này giúp dễ dàng mở rộng khi thêm ngôn ngữ mới, cũng như tách phần logic i18n ra khỏi phần component.
Bạn cũng có thể đặt bản dịch trực tiếp trong component Vue bằng <i18n>…</i18n>, nhưng cách này thường chỉ phù hợp với ứng dụng nhỏ bởi vì:
- Có khả năng phải lặp lại nhiều lần nếu cùng một chuỗi xuất hiện ở nhiều nơi.
- Khi ứng dụng lớn lên, file component sẽ trở nên “phình” vì chứa cả logic + dịch thuật.
- Nhóm dịch thuật (translator) thường không muốn/không nên thao tác với code component – nếu dùng file JSON tách biệt thì dễ hơn.
3. Tự động chọn ngôn ngữ theo trình duyệt
Việc để mặc định là tiếng Anh rồi bắt người dùng tự đổi là chưa tối ưu. Bạn có thể để ứng dụng tự lấy ngôn ngữ của trình duyệt và dùng làm locale ban đầu. Ví dụ trong i18n.js:
const userLang = navigator.language.split('-')[0];
const locale = userLang || process.env.VUE_APP_I18N_LOCALE || 'en';
export default new VueI18n({
locale: locale,
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
messages: loadLocaleMessages()
});
Nếu bạn muốn phân biệt vùng – ví dụ en-US hoặc en-GB – bạn có thể nâng cấp hàm kiểm tra như sau:
- Đầu tiên xem có support chính xác
navigator.language. - Nếu không, xem có support phần ngôn ngữ (chữ trước dấu
-). - Nếu vẫn không, xem các file dịch có vùng tương ứng.
Như vậy ứng dụng sẽ chọn ngôn ngữ phù hợp hơn với người dùng thay vì mặc định luôn một ngôn ngữ xa lạ.
4. Lưu lựa chọn ngôn ngữ của người dùng
Một khi người dùng chọn ngôn ngữ từ dropdown, bạn nên lưu lại lựa chọn đó để khi họ quay lại hoặc reload trang, ứng dụng vẫn giữ ngôn ngữ đã chọn. Có thể dùng localStorage hoặc dùng kết hợp với Vuex + plugin vuex-persistedstate. Ví dụ:
// store/index.js
import createPersistedState from 'vuex-persistedstate';
export default new Vuex.Store({
state: { locale: selectedLocale },
mutations: { updateLocale(state,newLocale){ state.locale = newLocale } },
actions: { changeLocale({commit}, newLocale){ i18n.locale = newLocale; commit('updateLocale', newLocale); } },
plugins: [ createPersistedState() ]
});
Trong component bạn binding v-model của select với lang và computed thực hiện getter/setter với Vuex. Khi reload, plugin tự lấy locale từ storage và thiết lập lại – vậy là người dùng được trải nghiệm liền mạch hơn.
5. Định dạng ngày giờ theo từng vùng miền
Ngôn ngữ không chỉ là văn bản – ngày tháng, giờ, tên tháng, tên ngày cũng khác nhau giữa các quốc gia. Với vue-i18n bạn có thể truyền thêm dateTimeFormats khi khởi tạo:
export const dateTimeFormats = {
fr: { short: { day:'numeric', month:'short', year:'numeric' },
long: { weekday:'short', day:'numeric', month:'short', year:'numeric', hour:'numeric', minute:'numeric', hour12:true }
},
'en-US': { short: { year:'numeric', month:'short', day:'numeric' },
long: { year:'numeric', month:'short', day:'numeric', weekday:'short', hour:'numeric', minute:'numeric' }
}
};
Khi đó bạn có thể sử dụng trong component bằng cách $d(dateValue,'short') hoặc $d(dateValue,'long'). Điều này giúp hiển thị ngày giờ đúng chuẩn người dùng mong đợi, và tận dụng chuẩn quốc tế Intl.DateTimeFormat.
6. Tái sử dụng và tổ chức dữ liệu dịch
Khi ứng dụng càng lớn, bạn sẽ có rất nhiều chuỗi cần dịch – và dễ lặp lại rất nhiều: chẳng hạn chữ “Username”, “Login”, “Click here”… Nếu mỗi lần bạn đều viết lại dưới từng component/tập tin JSON khác nhau thì cực khó bảo trì. Cách tốt hơn:
Tổ chức file dịch theo từng module/đối tượng:
{
"homepage": { "hello":"…", "welcomeMessage":"…", "userName":"Username", "login":"Login" },
"login": { "userName":"Enter Username", "password":"Enter Password", "login":"Login" },
"forgotPassword": { … }
}
Khi muốn dùng lại chuỗi đã khai báo ở nơi khác, bạn có thể dùng cú pháp link:
"login": { "userName":"Enter @:homepage.userName", "login":"@:homepage.login" }
Cú pháp @:homepage.userName cho phép tái sử dụng chuỗi đã định nghĩa, tránh lặp và giúp nhất quán khi cập nhật.
Cú pháp @:homepage.userName cho phép tái sử dụng chuỗi đã định nghĩa, tránh lặp và giúp nhất quán khi cập nhật.
7. Kết hợp bản địa hoá với vue-router để URL “thông minh”
Một điểm nâng cao: khi người dùng chuyển ngôn ngữ, không chỉ văn bản thay đổi mà URL nên cho biết ngôn ngữ – giúp SEO, giúp chia sẻ link chuẩn. Ví dụ: localhost:8080/en/home hoặc localhost:8080/fr/home. Cách thực hiện:
- Trong router cấu hình route gốc
/chuyển đến/:langvớilanglà ngôn ngữ đang dùng. - Trong
beforeEnterkiểm trato.params.langcó nằm trong danh sách ngôn ngữ được hỗ trợ hay không. Nếu có, dispatch hành động đổi locale. Nếu không, redirect đến locale mặc định. - Trong component
App.vue, lắng nghe thay đổilocale, và khi thay đổi cập nhật URL bằngthis.$router.replace({ params:{lang:this.locale} }).
Như vậy, khi người dùng chọn Tiếng Pháp, URL sẽ chuyển ngay thành/frvà toàn bộ ứng dụng sẽ sử dụng locale tương ứng.
8. Kết luận
Việc chuẩn hóa và mở rộng bản địa hoá cho ứng dụng Vue không chỉ là “dịch một vài câu” – mà bao gồm: cấu trúc tổ chức bản dịch, tự động nhận diện vùng miền, lưu lựa chọn người dùng, định dạng ngày giờ, tái sử dụng dữ liệu dịch và đồng bộ URL với ngôn ngữ. Khi sử dụng đúng cách với vue-i18n và Vue ecosystem, bạn có thể xây dựng một ứng dụng rất linh hoạt và sẵn sàng tiếp cận người dùng toàn cầu.
