Skip to content

Conversation

@thanhtantran
Copy link

Add Vietnamese translation

@Nerivec Nerivec changed the title Add Vietnamese translation feat: add Vietnamese translation Oct 26, 2025
@Nerivec Nerivec requested a review from Copilot October 26, 2025 13:00
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds Vietnamese translation support to the Zigbee2MQTT WindFront application. It includes a complete Vietnamese translation file with 546 translated strings, integration of the Vietnamese locale into the i18n configuration, and addition of Vietnamese to the language switcher dropdown.

Key Changes

  • Complete Vietnamese translation file covering all application areas (dashboard, devices, groups, settings, etc.)
  • Integration of Vietnamese timeago.js locale and translation resources
  • Language switcher updated to include Vietnamese option with proper alphabetical ordering

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/i18n/locales/vi.json Complete Vietnamese translation file with 546 translated strings covering all UI sections
src/i18n/index.ts Imports Vietnamese timeago.js locale and translation resources, registers Vietnamese language
src/components/LanguageSwitcher.tsx Adds Vietnamese ("Tiếng Việt") to language dropdown with alphabetical reordering

@Nerivec
Copy link
Owner

Nerivec commented Oct 26, 2025

I did an AI pass over the file in the repository's context (I don't speak the language 😅). I'll let you review this, make changes or not, as you see fit.

Here are the AI's notes:

  • “Nhật ký” is used consistently in place of “log.”
  • Use “Khôi phục cài đặt gốc” for factory reset, which is standard in Vietnamese UIs.
  • Fixed spacing and capitalization issues (e.g., “Chuỗi rỗng ("")”, “Mức nguồn điện”, MQTT uppercase).
  • “Xem thêm” is a more natural label for “More” in UI contexts.
  • Slightly clarified phrasings without changing technical meaning (e.g., “lần cập nhật bảng gần nhất”, “thuộc tính đi kèm”).

Here are the AI's suggested changes:

diff --git a/src/i18n/locales/vi.json b/src/i18n/locales/vi.json
--- a/src/i18n/locales/vi.json
+++ b/src/i18n/locales/vi.json
@@ -1,33 +1,33 @@
 {
     "common": {
         "action": "Hành động",
         "actions": "Các hành động",
         "apply": "Áp dụng",
         "attribute": "Thuộc tính",
         "bind": "Liên kết",
         "clear": "Xóa",
         "clear_all": "Xóa tất cả",
         "close": "Đóng",
         "cancel": "Hủy",
         "cluster": "Cụm",
         "clusters": "Các cụm",
         "confirmation": "Xác nhận",
         "delete": "Xóa",
         "destination": "Đích",
         "devices": "Thiết bị",
         "dialog_confirmation_prompt": "Bạn có chắc chắn?",
         "disable": "Vô hiệu hóa",
         "search": "Tìm kiếm",
         "highlight": "Làm nổi bật",
         "groups": "Nhóm",
         "loading": "Đang tải...",
         "none": "Không có",
         "ok": "OK",
         "read": "Đọc",
         "save": "Lưu",
         "select_value": "Chọn giá trị",
         "select_device": "Chọn thiết bị",
         "select_endpoint": "Chọn điểm cuối",
         "select_group": "Chọn nhóm",
         "source_endpoint": "Điểm cuối nguồn",
         "the_only_endpoint": "Điểm cuối duy nhất",
         "unbind": "Hủy liên kết",
         "write": "Ghi",
         "destination_endpoint": "Điểm cuối đích",
         "read_the_docs_info": "Đọc về điều này trong tài liệu...",
         "page": "Trang",
         "go_to_page": "Đi đến trang",
         "show": "Hiển thị",
         "min": "Tối thiểu",
         "max": "Tối đa",
         "done": "Hoàn thành",
         "documentation": "Tài liệu",
         "optional": "Tùy chọn",
         "init": "Khởi tạo",
         "undefined": "Không xác định",
         "type_to_filter": "Gõ để lọc...",
         "name": "Tên",
         "friendly_name": "Tên thân thiện",
         "unknown_device": "Thiết bị không xác định",
         "unknown_group": "Nhóm không xác định",
         "failed": "Thất bại",
         "disabled": "Đã vô hiệu hóa",
         "execute": "Thực thi",
         "command": "Lệnh",
         "payload": "Dữ liệu",
         "execute_command": "Thực thi lệnh",
         "send": "Gửi",
         "columns": "Cột",
         "entries": "Mục",
         "source": "Nguồn",
         "close_notifications": "Đóng thông báo",
-        "more": "Thêm",
+        "more": "Xem thêm",
         "default": "Mặc định",
         "multi_instance": "Đa phiên bản",
         "all_sources": "Tất cả nguồn",
         "show_source_name": "Hiển thị tên nguồn",
         "show_only": "Chỉ hiển thị",
         "empty_exposes_definition": "Định nghĩa exposes trống",
         "hide_static_info_alerts": "Ẩn cảnh báo thông tin tĩnh",
         "advanced_search": "Tìm kiếm nâng cao",
         "reset": "Đặt lại",
         "all": "Tất cả",
-        "last_seen_filter_info": "Tính bằng phút kể từ lần cập nhật bảng cuối",
+        "last_seen_filter_info": "Tính bằng phút kể từ lần cập nhật bảng gần nhất",
         "feature_type": "Loại tính năng",
         "feature_name": "Tên tính năng",
         "state": "Trạng thái",
         "scroll_to_top": "Cuộn lên đầu",
         "notifications": "Thông báo"
     },
     "devicePage": {
@@ -51,18 +51,18 @@
     "logs": {
-        "log_level_config": "Cấu hình mức log",
+        "log_level_config": "Cấu hình mức nhật ký",
         "empty_logs_message": "Không có gì để hiển thị",
         "filter_by_text": "Lọc theo văn bản",
-        "logs_limit": "Giới hạn log",
+        "logs_limit": "Giới hạn nhật ký",
         "highlight_only": "Chỉ làm nổi bật"
     },
@@ -152,7 +152,7 @@
     "touchlink": {
         "detected_devices_message": "Đã phát hiện {{count}} thiết bị touchlink.",
         "rescan": "Quét lại",
         "scan": "Quét",
         "identify": "Nhận dạng",
-        "factory_reset": "Đặt lại xuống xưởng",
+        "factory_reset": "Khôi phục cài đặt gốc",
         "scan_source": "Nguồn quét",
         "select_scan_source": "Chọn nguồn quét"
     },
@@ -164,7 +164,7 @@
         "occupied": "Có người",
         "open": "Mở",
         "supported": "Hỗ trợ",
         "true": "Đúng",
-        "empty_string": "Chuỗi rỗng(\"\" )",
+        "empty_string": "Chuỗi rỗng (\"\")",
         "leaking": "Rò rỉ",
         "tampered": "Bị can thiệp",
         "null": "Null",
@@ -197,7 +197,7 @@
         "power": "Nguồn điện",
-        "power_level": "mức nguồn điện",
+        "power_level": "Mức nguồn điện",
         "reconfigure": "Cấu hình lại",
         "remove_device": "Xóa thiết bị",
         "rename_device": "Đổi tên thiết bị",
         "select_attribute": "Chọn thuộc tính",
         "select_cluster": "Chọn cụm",
@@ -219,12 +219,12 @@
     "scene": {
         "manage_scenes_header": "Quản lý cảnh",
         "add_update_header": "Thêm/cập nhật cảnh",
         "scene_id": "ID cảnh",
-        "recall": "Gọi lại",
+        "recall": "Kích hoạt",
         "store": "Lưu trữ",
         "remove": "Xóa",
         "remove_all": "Xóa tất cả",
         "add": "Thêm",
         "select_scene": "Chọn cảnh",
         "scene_name": "Tên cảnh"
     },
@@ -247,7 +247,7 @@
-        "download_state": "Tải trạng thái",
+        "download_state": "Tải xuống trạng thái",
         "experimental": "Thử nghiệm",
         "external_converters": "Bộ chuyển đổi bên ngoài",
         "frontend": "Frontend",
         "frontend_version": "Phiên bản frontend",
@@ -323,7 +323,7 @@
     "devConsole": {
         "generate_external_definition": "Tạo định nghĩa bên ngoài",
         "generated_external_definition": "Định nghĩa bên ngoài đã tạo",
         "state_property": "Thuộc tính trạng thái",
         "state_property_info": "Đặt kết quả vào trạng thái thiết bị (chỉ cho đọc)",
         "reset_frontend_state": "Đặt lại trạng thái frontend",
         "mqtt": "MQTT",
         "external_converters": "Bộ chuyển đổi bên ngoài",
         "external_extensions": "Tiện ích mở rộng bên ngoài",
         "topic": "Chủ đề",
         "send_mqtt": "Gửi tin nhắn MQTT",
         "mqtt_topic_info": "Bỏ qua 'base_topic', tin nhắn frontend được gửi qua WebSocket trực tiếp đến Zigbee2MQTT.",
         "code": "Mã",
         "add_update_external_extension": "Thêm hoặc cập nhật tiện ích mở rộng bên ngoài",
         "create_new_extension": "Tạo tiện ích mở rộng mới",
         "select_extension_to_edit": "Chọn tiện ích mở rộng để chỉnh sửa",
         "add_update_external_converter": "Thêm hoặc cập nhật bộ chuyển đổi bên ngoài",
         "create_new_converter": "Tạo bộ chuyển đổi mới",
         "select_converter_to_edit": "Chọn bộ chuyển đổi để chỉnh sửa",
-        "codespace_info": "Github Codespace có sẵn để hỗ trợ phát triển",
+        "codespace_info": "GitHub Codespace có sẵn để hỗ trợ phát triển",
         "show_definition": "Hiển thị định nghĩa",
         "hide_definition": "Ẩn định nghĩa"
     },
@@ -345,11 +345,11 @@
         "mqtt-cert": "Đường dẫn tuyệt đối đến chứng chỉ SSL/TLS cho xác thực máy khách",
         "mqtt-user": "Người dùng xác thực máy chủ MQTT",
         "mqtt-password": "Mật khẩu xác thực máy chủ MQTT",
         "mqtt-client_id": "ID máy khách MQTT",
         "mqtt-reject_unauthorized": "Vô hiệu hóa chứng chỉ SSL tự ký",
-        "mqtt-include_device_information": "Bao gồm thông tin thiết bị trong tin nhắn mqtt",
+        "mqtt-include_device_information": "Bao gồm thông tin thiết bị trong tin nhắn MQTT",
         "mqtt-version": "Phiên bản giao thức MQTT",
         "mqtt-force_disable_retain": "Vô hiệu hóa retain cho tất cả tin nhắn gửi. CHỈ bật nếu broker MQTT của bạn không hỗ trợ tin nhắn retained (ví dụ: AWS IoT core, Azure IoT Hub, Google Cloud IoT core, IBM Watson IoT Platform). Việc bật sẽ phá vỡ tích hợp Home Assistant",
         "mqtt-maximum_packet_size": "Chỉ định độ dài gói tối đa được phép (tính bằng byte) mà máy chủ có thể gửi đến Zigbee2MQTT. LƯU Ý: Cùng một giá trị tồn tại trong broker MQTT của bạn nhưng cho độ dài mà máy khách có thể gửi đến nó thay thế.",
         "serial-port": "Vị trí của adapter. Để tự động phát hiện cổng, đặt null",
@@ -382,17 +382,17 @@
         "frontend-url": "URL mà frontend có thể được truy cập, hiện chỉ được sử dụng cho trang cấu hình thiết bị Home Assistant",
-        "frontend-ssl_cert": "Đường dẫn tệp chứng chỉ SSL để hiển thị HTTPS. Thuộc tính anh em 'ssl_key' phải được đặt để HTTPS được kích hoạt.",
-        "frontend-ssl_key": "Đường dẫn tệp khóa SSL để hiển thị HTTPS. Thuộc tính anh em 'ssl_cert' phải được đặt để HTTPS được kích hoạt.",
+        "frontend-ssl_cert": "Đường dẫn tệp chứng chỉ SSL để hiển thị HTTPS. Thuộc tính đi kèm 'ssl_key' phải được đặt để HTTPS được kích hoạt.",
+        "frontend-ssl_key": "Đường dẫn tệp khóa SSL để hiển thị HTTPS. Thuộc tính đi kèm 'ssl_cert' phải được đặt để HTTPS được kích hoạt.",
         "frontend-base_url": "URL cơ sở cho frontend. Nếu được lưu trữ dưới đường dẫn con, ví dụ: 'http://localhost:8080/z2m', đặt thành '/z2m'",
         "frontend-notification_filter": "Ẩn thông báo frontend khớp với chuỗi regex được chỉ định. Ví dụ: 'z2m: Failed to ping.*'",
         "frontend-disable_ui_serving": "Nếu true, UI frontend không được phục vụ, chỉ WebSocket được duy trì bởi Zigbee2MQTT (bạn cần phải phục vụ UI độc lập theo nhu cầu).",
-        "advanced-log_rotation": "Xoay log",
-        "advanced-log_console_json": "Log json console",
-        "advanced-log_symlink_current": "Tạo symlink đến log hiện tại trong thư mục log",
-        "advanced-log_output": "Vị trí đầu ra của log, để trống để ngăn chặn logging",
-        "advanced-log_directory": "Vị trí thư mục log",
-        "advanced-log_file": "Tên tệp log, cũng có thể chứa timestamp",
+        "advanced-log_rotation": "Xoay nhật ký",
+        "advanced-log_console_json": "Ghi nhật ký console ở dạng JSON",
+        "advanced-log_symlink_current": "Tạo symlink tới nhật ký hiện tại trong thư mục nhật ký",
+        "advanced-log_output": "Vị trí lưu nhật ký, để trống để tắt ghi nhật ký",
+        "advanced-log_directory": "Thư mục nhật ký",
+        "advanced-log_file": "Tên tệp nhật ký, cũng có thể chứa timestamp",
         "advanced-log_level": "Mức logging",
-        "advanced-log_namespaced_levels": "Đặt mức log riêng cho các namespace nhất định",
-        "advanced-log_debug_to_mqtt_frontend": "Log mức debug đến MQTT và frontend (có thể giảm hiệu suất tổng thể)",
-        "advanced-log_debug_namespace_ignore": "Không log các namespace này (dựa trên regex) cho mức debug",
-        "advanced-log_directories_to_keep": "Số thư mục log cần giữ trước khi xóa thư mục cũ nhất",
+        "advanced-log_namespaced_levels": "Đặt mức ghi nhật ký riêng cho các namespace nhất định",
+        "advanced-log_debug_to_mqtt_frontend": "Ghi nhật ký mức debug đến MQTT và frontend (có thể giảm hiệu suất tổng thể)",
+        "advanced-log_debug_namespace_ignore": "Không ghi nhật ký các namespace này (dựa trên regex) cho mức debug",
+        "advanced-log_directories_to_keep": "Số thư mục nhật ký cần giữ trước khi xóa thư mục cũ nhất",
         "advanced-log_syslog-host": "Host chạy syslogd, mặc định là localhost.",
         "advanced-log_syslog-port": "Cổng trên host mà syslog đang chạy, mặc định là cổng mặc định của syslogd.",
         "advanced-log_syslog-protocol": "Giao thức mạng để log qua (ví dụ: tcp4, udp4, tls4, unix, unix-connect, v.v.).",
@@ -407,7 +407,7 @@
         "advanced-pan_id": "ID pan Zigbee, thay đổi yêu cầu ghép lại tất cả thiết bị!",
         "advanced-ext_pan_id": "ID pan mở rộng Zigbee, thay đổi yêu cầu ghép lại tất cả thiết bị!",
         "advanced-channel": "Kênh Zigbee, thay đổi có thể yêu cầu ghép lại một số thiết bị! (Lưu ý: sử dụng kênh ZLL: 11, 15, 20, hoặc 25 để tránh vấn đề)",
-        "advanced-adapter_concurrent": "Đồng thời adapter (ví dụ: 2 cho CC2531 hoặc 16 cho CC26X2R1) (mặc định: null, sử dụng giá trị được khuyến nghị)",
+        "advanced-adapter_concurrent": "Mức độ đồng thời của adapter (ví dụ: 2 cho CC2531 hoặc 16 cho CC26X2R1) (mặc định: null, sử dụng giá trị được khuyến nghị)",
         "advanced-adapter_delay": "Độ trễ adapter",
         "advanced-cache_state": "Payload tin nhắn MQTT sẽ chứa tất cả thuộc tính, không chỉ những cái đã thay đổi. Phải là true khi tích hợp qua Home Assistant",
         "advanced-cache_state_persistent": "Duy trì trạng thái được cache, chỉ được sử dụng khi cache_state: true",
@@ -471,7 +471,7 @@
     "health": {
         "awaiting_next_check": "Đang chờ kiểm tra tiếp theo",
-        "last_check": "Kiểm tra cuối",
+        "last_check": "Lần kiểm tra cuối",
         "response_time": "Thời gian phản hồi",
         "os": "Hệ điều hành",
         "process": "Tiến trình",
         "load_average": "Tải trung bình",
         "ram_usage": "Sử dụng RAM",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants