Đa ngôn ngữ (i18n)
builderx_spa dùng vue-i18n 9 kết hợp tiện ích VS Code i18n-ally để quản lý khoá dịch.
Bố cục
src/i18n/
├── index.js # createI18n + nạp locale
├── locales/
│ ├── vi.json
│ ├── en.json
│ ├── th.json
│ └── …
└── helpers.js # Helper định dạng (nếu có)
- Locale mặc định:
vi. - Locale dự phòng:
en. - Ngôn ngữ nguồn của i18n-ally:
vi.
Cấu hình i18n-ally
Đã cố định trong .vscode/settings.json:
"i18n-ally.localesPaths": ["src/i18n/locales"],
"i18n-ally.keystyle": "nested",
"i18n-ally.sourceLanguage": "vi",
"i18n-ally.sortKeys": true,
"i18n-ally.translate.engines": ["google"],
"i18n-ally.regex.usageMatchAppend": [
"t\\.success\\(\\s*['\"]({key})['\"]",
"t\\.error\\(\\s*['\"]({key})['\"]"
]
Nhờ usageMatchAppend, các helper t.success('...') và t.error('...') cũng được nhận diện.
Cách dùng
Options API
<template>
<a-button>{{ $t('product.create_new') }}</a-button>
</template>
<script>
export default {
methods: {
onCreate() {
this.$t('product.create_new');
this.$message.success(this.$t('product.created'));
},
},
};
</script>
Composition API
<script setup>
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n();
const label = t('product.create_new');
</script>
Trong module thuần
import i18n from '@/i18n';
i18n.global.t('product.create_new');
Quy ước đặt khoá
- Lồng theo feature:
product.create_new,order.status.completed,… - Không tái sử dụng cùng một khoá ở hai ngữ cảnh khác nhau.
- Khoá viết bằng tiếng Anh snake_case; nội dung dịch theo locale.
- Khi xoá một khoá, xoá ở mọi locale để không tồn đọng khoá rác.
vilà ngôn ngữ nguồn — i18n-ally sẽ tự đề xuất dịch sang các locale khác.
Lint
eslint-plugin-i18n-json đã chạy cho src/i18n/locales/*.json qua lint-staged:
"lint-staged": {
"src/i18n/locales/*.json": "eslint --fix",
"*.{js,ts,vue}": "eslint --fix"
}
Plugin sẽ giữ thứ tự khoá đồng bộ giữa các locale, cảnh báo placeholder \{tên\} không khớp và phát hiện khoá thiếu so với sourceLanguage.
Thêm một locale mới
- Tạo
src/i18n/locales/<code>.json(copy từvi.json). - Mở i18n-ally → "Translate missing keys" để dịch nháp.
- Đăng ký locale vào
src/i18n/index.js(mapmessages) và phần chọn locale ở UI (useLocaleStore). - Đồng bộ danh sách locale ở backend nếu liên quan đến nội dung storefront.
Sai sót thường gặp
-
Tránh khoá động dựng từ biến nội suy (ví dụ truyền vào
$tmột template string chứa biến) — i18n-ally không nhận diện được, dễ bị thu hồi khi dọn dẹp. Thay vào đó dùng map khoá cố định:const KEY_BY_TYPE = {info: 'product.type.info',sale: 'product.type.sale',};$t(KEY_BY_TYPE[type]); -
Với định dạng số và ngày, dùng
$nvà$dcấu hình tạisrc/i18n/index.js(numberFormats/datetimeFormats). -
Khi nạp locale theo dạng lazy (split chunk), gọi
i18n.global.setLocaleMessage(locale, msgs)rồi mớisetLocale(locale).