Skip to main content

Đ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('...')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.
  • vi là 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

  1. Tạo src/i18n/locales/<code>.json (copy từ vi.json).
  2. Mở i18n-ally → "Translate missing keys" để dịch nháp.
  3. Đăng ký locale vào src/i18n/index.js (map messages) và phần chọn locale ở UI (useLocaleStore).
  4. Đồ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 $t mộ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 $n$d cấu hình tại src/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ới setLocale(locale).