-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathagtech_i18n.js
More file actions
425 lines (398 loc) · 27 KB
/
Copy pathagtech_i18n.js
File metadata and controls
425 lines (398 loc) · 27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
(function () {
const VI = {
"Multimodal AgTech 3.0 | Research Website": "Multimodal AgTech 3.0 | Trang nghiên cứu",
"Multimodal AgTech | Water Stress Command": "Multimodal AgTech | Điều phối stress nước",
"Switch language to Vietnamese": "Chuyển ngôn ngữ sang tiếng Việt",
"Switch language to English": "Chuyển ngôn ngữ sang tiếng Anh",
"Skip to content": "Bỏ qua để đến nội dung",
"Open research website": "Trang nghiên cứu mở",
"Research": "Nghiên cứu",
"Dashboard": "Bảng điều khiển",
"Results": "Kết quả",
"About": "Giới thiệu",
"Contact": "Liên hệ",
"Access Dashboard": "Truy cập bảng điều khiển",
"FIWARE-ready / NASA-inspired / Phase 1 water stress": "Sẵn sàng FIWARE / Cảm hứng NASA / Giai đoạn 1: stress nước",
"Spatiotemporal-aware water stress detection and irrigation recommendation for field deployment, academic review, and production-safe decision support.": "Phát hiện stress nước có nhận biết không gian-thời gian và khuyến nghị tưới tiêu cho triển khai thực địa, phản biện học thuật và hỗ trợ quyết định an toàn trong vận hành.",
"View Research": "Xem nghiên cứu",
"System Snapshot": "Ảnh chụp hệ thống",
"Model": "Mô hình",
"Freshness": "Độ mới dữ liệu",
"Latency": "Độ trễ",
"Mode": "Chế độ",
"Reduced-risk UX": "UX giảm rủi ro",
"Design Philosophy": "Triết lý thiết kế",
"Research-grade clarity without hiding operational logic.": "Minh bạch ở chuẩn nghiên cứu mà không che giấu logic vận hành.",
"The website is built around scientific credibility, data-first hierarchy, production-safe UX, open standards, and accessible performance across desktop and mobile.": "Trang web được xây dựng xoay quanh độ tin cậy khoa học, phân cấp ưu tiên dữ liệu, UX an toàn cho sản xuất, tiêu chuẩn mở và hiệu năng dễ tiếp cận trên desktop lẫn mobile.",
"Multimodal Fusion": "Hợp nhất đa phương thức",
"Satellite or UAV imagery, soil sensors, and weather features are fused with visible modality confidence and missing-source states.": "Ảnh vệ tinh hoặc UAV, cảm biến đất và đặc trưng thời tiết được hợp nhất kèm độ tin cậy từng phương thức và trạng thái thiếu nguồn dữ liệu hiển thị rõ ràng.",
"Spatiotemporal Alignment": "Căn chỉnh không gian-thời gian",
"Research pages expose the alignment logic between image timestamp, sensor sampling, rainfall forecast, and zone-level inference.": "Các trang nghiên cứu trình bày logic căn chỉnh giữa thời điểm ảnh, mẫu cảm biến, dự báo mưa và suy luận theo từng vùng.",
"Production-Safe Decisions": "Quyết định an toàn cho vận hành",
"Recommendations keep rule triggers, uncertainty, confirmation requirements, and operator override visible before actuation.": "Khuyến nghị luôn hiển thị điều kiện kích hoạt luật, độ bất định, yêu cầu xác nhận và quyền ghi đè của người vận hành trước khi thực thi.",
"Live Preview": "Xem trước trực tiếp",
"Dashboard preview embedded as a product signal.": "Bản xem trước dashboard được nhúng như một tín hiệu sản phẩm.",
"The homepage does not merely explain the system. It shows the operational surface: zone map, confidence state, recommendation logic, and time-series trend.": "Trang chủ không chỉ giải thích hệ thống. Nó hiển thị bề mặt vận hành: bản đồ vùng, trạng thái tin cậy, logic khuyến nghị và xu hướng chuỗi thời gian.",
"Missing modality guarded": "Có bảo vệ khi thiếu phương thức",
"AI Prediction / Zone C19": "Dự đoán AI / Vùng C19",
"Uncertainty 0.34": "Độ bất định 0.34",
"Stress: 0.78 | Soil: 18% | Rain 3h: 12%": "Stress: 0.78 | Đất: 18% | Mưa 3h: 12%",
"Open Full Dashboard": "Mở dashboard đầy đủ",
"Target weighted F1 for stress classification under balanced field conditions.": "Mục tiêu F1 có trọng số cho phân loại stress trong điều kiện đồng ruộng cân bằng.",
"Projected water savings from conservative irrigation recommendation loops.": "Mức tiết kiệm nước dự kiến từ các vòng khuyến nghị tưới tiêu thận trọng.",
"Interaction latency budget from inference output to operator decision screen.": "Ngân sách độ trễ tương tác từ đầu ra suy luận đến màn hình quyết định của người vận hành.",
"Methodology, dataset, and publication assets in one technical path.": "Phương pháp, bộ dữ liệu và tài sản xuất bản trong một luồng kỹ thuật.",
"The research section is structured for academic review: abstract, architecture, dataset schema, robustness analysis, and citation-ready publication metadata.": "Phần nghiên cứu được cấu trúc cho phản biện học thuật: tóm tắt, kiến trúc, schema bộ dữ liệu, phân tích độ bền vững và metadata trích dẫn sẵn sàng xuất bản.",
"Abstract": "Tóm tắt",
"We model water stress as a multimodal spatiotemporal inference problem, combining image-derived vegetation signals with sensor telemetry and short-horizon weather context.": "Chúng tôi mô hình hóa stress nước như một bài toán suy luận đa phương thức theo không gian-thời gian, kết hợp tín hiệu thảm thực vật từ ảnh với telemetry cảm biến và bối cảnh thời tiết ngắn hạn.",
"Modality dropout": "Loại bỏ phương thức có kiểm soát",
"Dataset Schema": "Schema bộ dữ liệu",
"Dataset cards expose source, timestamp alignment, missing modality flags, and zone-level stress labels.": "Thẻ bộ dữ liệu hiển thị nguồn, căn chỉnh thời gian, cờ thiếu phương thức và nhãn stress theo từng vùng.",
"Copy Schema": "Sao chép schema",
"Ablation, calibration, and robustness are first-class content.": "Ablation, hiệu chỉnh và độ bền vững là nội dung trọng tâm.",
"Charts and tables are compact, export-oriented, and built for review rather than decoration. Every number has a visible context.": "Biểu đồ và bảng được thiết kế gọn, hướng đến xuất dữ liệu và phục vụ đánh giá thay vì trang trí. Mỗi con số đều có ngữ cảnh rõ ràng.",
"Ablation Table": "Bảng ablation",
"Missing Modality": "Thiếu phương thức",
"Image only": "Chỉ ảnh",
"Weak": "Yếu",
"Sensor + Weather": "Cảm biến + Thời tiết",
"Moderate": "Trung bình",
"Cross-attention fusion": "Hợp nhất cross-attention",
"Strong": "Mạnh",
"Confusion Matrix": "Ma trận nhầm lẫn",
"Calibration Plot": "Biểu đồ hiệu chỉnh",
"Robustness Under Missing Modality": "Độ bền vững khi thiếu phương thức",
"Dashboard Access": "Truy cập dashboard",
"Role-aware entry point for researchers and field operators.": "Điểm vào theo vai trò cho nhà nghiên cứu và người vận hành thực địa.",
"Access control, system health, quick links, and preview annotations are grouped so users can quickly decide whether they need the live app, API, docs, or issue tracker.": "Kiểm soát truy cập, tình trạng hệ thống, liên kết nhanh và chú thích xem trước được gom nhóm để người dùng nhanh chóng chọn ứng dụng live, API, tài liệu hoặc trình theo dõi lỗi.",
"Access Control": "Kiểm soát truy cập",
"Researcher": "Nhà nghiên cứu",
"Agronomist": "Nhà nông học",
"Farm Manager": "Quản lý trang trại",
"Admin": "Quản trị",
"SSO or token": "SSO hoặc token",
"Validate Access": "Xác thực truy cập",
"Inline validation appears here.": "Thông báo xác thực sẽ hiển thị tại đây.",
"System Status": "Trạng thái hệ thống",
"Uptime": "Thời gian hoạt động",
"Last sync": "Đồng bộ gần nhất",
"Fresh": "Mới",
"Data state": "Trạng thái dữ liệu",
"Quick Links": "Liên kết nhanh",
"Live App": "Ứng dụng live",
"Open": "Mở",
"API Swagger": "API Swagger",
"Documentation": "Tài liệu",
"Issue Tracker": "Theo dõi lỗi",
"Bridge research and field deployment for precision agriculture.": "Kết nối nghiên cứu và triển khai thực địa cho nông nghiệp chính xác.",
"The about area supports team credibility, partner context, and a three-phase roadmap from water stress to broader crop intelligence.": "Khu vực giới thiệu hỗ trợ uy tín đội ngũ, bối cảnh đối tác và lộ trình ba giai đoạn từ stress nước đến trí tuệ cây trồng rộng hơn.",
"Mission": "Sứ mệnh",
"Build an explainable, open-standard AgTech platform that helps researchers evaluate multimodal models and helps operators make safer irrigation decisions.": "Xây dựng nền tảng AgTech giải thích được, theo tiêu chuẩn mở, giúp nhà nghiên cứu đánh giá mô hình đa phương thức và giúp người vận hành đưa ra quyết định tưới tiêu an toàn hơn.",
"Phase 1 / Water Stress": "Giai đoạn 1 / Stress nước",
"Zone map, multimodal prediction, uncertainty and confirmation flow.": "Bản đồ vùng, dự đoán đa phương thức, độ bất định và luồng xác nhận.",
"Phase 2 / Nutrient and Pest": "Giai đoạn 2 / Dinh dưỡng và sâu bệnh",
"Extend modality set and label taxonomy for nutrient deficit and pest risk.": "Mở rộng tập phương thức và taxonomy nhãn cho thiếu hụt dinh dưỡng và rủi ro sâu bệnh.",
"Phase 3 / Scale": "Giai đoạn 3 / Mở rộng",
"Multi-farm deployment, NGSI-LD integration, and API-ready decision support.": "Triển khai đa trang trại, tích hợp NGSI-LD và hỗ trợ quyết định sẵn sàng qua API.",
"ML Research": "Nghiên cứu ML",
"Model design, ablation, calibration, and robustness evaluation.": "Thiết kế mô hình, ablation, hiệu chỉnh và đánh giá độ bền vững.",
"Agronomy": "Nông học",
"Stress labels, irrigation rules, domain safety and pilot feedback.": "Nhãn stress, luật tưới tiêu, an toàn miền ứng dụng và phản hồi pilot.",
"Product UX": "UX sản phẩm",
"Dashboard workflow, confirmation states, accessibility and handoff.": "Quy trình dashboard, trạng thái xác nhận, khả năng tiếp cận và bàn giao.",
"Smart data models": "Mô hình dữ liệu thông minh",
"Satellite imagery": "Ảnh vệ tinh",
"Pilot deployment": "Triển khai pilot",
"Academic Review": "Phản biện học thuật",
"Publication support": "Hỗ trợ xuất bản",
"Publication": "Xuất bản",
"Citation and supplementary assets are ready for handoff.": "Trích dẫn và tài sản bổ sung đã sẵn sàng bàn giao.",
"The publication block gives reviewers one-click access to the citation string, supplementary code, dataset card, and draft paper status.": "Khối xuất bản cho người phản biện truy cập một lần nhấp đến chuỗi trích dẫn, mã bổ sung, thẻ bộ dữ liệu và trạng thái bản thảo.",
"IEEE Draft Citation": "Trích dẫn bản thảo IEEE",
"Copy Citation": "Sao chép trích dẫn",
"Request IEEE Draft": "Yêu cầu bản thảo IEEE",
"Collaboration, support, and office hours in one clean flow.": "Hợp tác, hỗ trợ và lịch trao đổi trong một luồng gọn gàng.",
"The form keeps validation visible and routes academic, partnership, and technical support messages without hiding response expectations.": "Biểu mẫu giữ thông báo xác thực rõ ràng và phân luồng tin nhắn học thuật, đối tác, hỗ trợ kỹ thuật mà không che khuất kỳ vọng phản hồi.",
"Collaboration Request": "Yêu cầu hợp tác",
"Name": "Tên",
"Email": "Email",
"Organization": "Tổ chức",
"Message": "Nội dung",
"Send Request": "Gửi yêu cầu",
"Required fields: name, email, message.": "Trường bắt buộc: tên, email, nội dung.",
"Support": "Hỗ trợ",
"GitHub Issues for implementation bugs. Email route for academic review, pilot collaboration, and partner questions.": "Dùng GitHub Issues cho lỗi triển khai. Email dùng cho phản biện học thuật, hợp tác pilot và câu hỏi đối tác.",
"SLA 2 business days": "SLA 2 ngày làm việc",
"UTC+7 friendly": "Thân thiện múi giờ UTC+7",
"Office Hours": "Lịch trao đổi",
"Monthly review slot for dataset cards, dashboard feedback, and deployment roadmap alignment.": "Buổi rà soát hằng tháng cho thẻ bộ dữ liệu, phản hồi dashboard và căn chỉnh lộ trình triển khai.",
"Download ICS": "Tải ICS",
"Research website and product documentation surface for water stress detection and irrigation recommendation.": "Trang nghiên cứu và bề mặt tài liệu sản phẩm cho phát hiện stress nước và khuyến nghị tưới tiêu.",
"Version 0.9.4": "Phiên bản 0.9.4",
"Open Standard Aligned": "Phù hợp tiêu chuẩn mở",
"Methodology": "Phương pháp",
"Dataset": "Bộ dữ liệu",
"Product": "Sản phẩm",
"Dashboard HTML": "HTML dashboard",
"Handoff": "Bàn giao",
"Citation": "Trích dẫn",
"Roadmap": "Lộ trình",
"Partners": "Đối tác",
"Water Stress Command": "Điều phối stress nước",
"Multimodal AgTech Pilot / Mekong Zone Grid": "Pilot Multimodal AgTech / Lưới vùng Mekong",
"Field Ops": "Vận hành thực địa",
"Zone Tree": "Cây vùng",
"North A12": "Bắc A12",
"orthomosaic fresh": "orthomosaic mới",
"Canal B07": "Kênh B07",
"weather synced": "thời tiết đã đồng bộ",
"Ridge C19": "Gò C19",
"sensor drift watch": "theo dõi lệch cảm biến",
"Delta D03": "Đồng bằng D03",
"image missing": "thiếu ảnh",
"Block E24": "Lô E24",
"stable trend": "xu hướng ổn định",
"Lowland F15": "Vùng trũng F15",
"recovery watch": "theo dõi phục hồi",
"Filters": "Bộ lọc",
"Stress threshold": "Ngưỡng stress",
"System": "Hệ thống",
"Image": "Ảnh",
"Degraded": "Suy giảm",
"Sensor": "Cảm biến",
"Weather": "Thời tiết",
"Live": "Trực tiếp",
"Queue": "Hàng đợi",
"Idle": "Chờ",
"Pilot Area / Latest Stress Overlay": "Khu vực pilot / Lớp phủ stress mới nhất",
"Last sync 08:42 UTC / uncertainty weighted": "Đồng bộ gần nhất 08:42 UTC / có trọng số bất định",
"0.0 healthy": "0.0 khỏe",
"0.6 watch": "0.6 theo dõi",
"1.0 critical": "1.0 nghiêm trọng",
"Reduced confidence": "Độ tin cậy giảm",
"Image modality missing for one zone. Recommendation logic is conservative.": "Một vùng đang thiếu phương thức ảnh. Logic khuyến nghị được giữ thận trọng.",
"Aggregate Time-Series Trends": "Xu hướng chuỗi thời gian tổng hợp",
"Soil moisture, stress probability, irrigation events, rainfall": "Độ ẩm đất, xác suất stress, sự kiện tưới, lượng mưa",
"Moisture": "Độ ẩm",
"Stress": "Stress",
"Irrigation": "Tưới tiêu",
"Rainfall": "Lượng mưa",
"AI Prediction": "Dự đoán AI",
"Zone A12": "Vùng A12",
"Zone B07": "Vùng B07",
"Zone C19": "Vùng C19",
"Zone D03": "Vùng D03",
"Zone E24": "Vùng E24",
"Zone F15": "Vùng F15",
"08:42 UTC / 24 Apr 2026": "08:42 UTC / 24 Thg 4 2026",
"Stress Probability": "Xác suất stress",
"Uncertainty 0.18": "Độ bất định 0.18",
"Uncertainty 0.24": "Độ bất định 0.24",
"Uncertainty 0.34": "Độ bất định 0.34",
"Uncertainty 0.41": "Độ bất định 0.41",
"Uncertainty 0.21": "Độ bất định 0.21",
"Uncertainty 0.29": "Độ bất định 0.29",
"Requires confirmation": "Cần xác nhận",
"View Explanation": "Xem giải thích",
"Irrigation Recommendation": "Khuyến nghị tưới tiêu",
"No Irrigation": "Không tưới",
"Light": "Tưới nhẹ",
"Heavy": "Tưới nhiều",
"Soil Moisture": "Độ ẩm đất",
"Rain Forecast 3h": "Dự báo mưa 3h",
"Acknowledge uncertainty and proceed": "Xác nhận độ bất định và tiếp tục",
"Confirm": "Xác nhận",
"Sending": "Đang gửi",
"Active": "Đang hoạt động",
"Alert Feed": "Luồng cảnh báo",
"C19 stress spike": "C19 tăng stress đột biến",
"08:42 | Ridge | Review": "08:42 | Gò | Kiểm tra",
"D03 image gap": "D03 thiếu dữ liệu ảnh",
"08:35 | Delta | Log": "08:35 | Đồng bằng | Ghi log",
"Trace": "Truy vết",
"Weather sync": "Đồng bộ thời tiết",
"08:31 | All zones | Done": "08:31 | Tất cả vùng | Hoàn tất",
"Controls": "Điều khiển",
"Manual Override": "Ghi đè thủ công",
"Manual": "Thủ công",
"Volume adjustment": "Điều chỉnh lượng nước",
"Time-Series Trends": "Xu hướng chuỗi thời gian",
"Filtered by selected zone and synchronized image/sensor timestamp": "Được lọc theo vùng đã chọn và thời điểm ảnh/cảm biến đã đồng bộ",
"Stress Overlay": "Lớp phủ stress",
"Operating with reduced confidence": "Đang vận hành với độ tin cậy giảm",
"Image, sensor, and weather modalities aligned": "Các phương thức ảnh, cảm biến và thời tiết đã được căn chỉnh",
"Last update": "Cập nhật cuối",
"Multimodal AgTech home": "Trang chủ Multimodal AgTech",
"Primary navigation": "Điều hướng chính",
"Toggle theme": "Đổi giao diện sáng/tối",
"Menu": "Menu",
"Open menu": "Mở menu",
"Project status summary": "Tóm tắt trạng thái dự án",
"Technology stack": "Ngăn xếp công nghệ",
"Deep learning training and inference": "Huấn luyện và suy luận deep learning",
"Open Smart Data Models and NGSI-LD metadata": "Smart Data Models mở và metadata NGSI-LD",
"Satellite vegetation and moisture proxy source": "Nguồn đại diện thảm thực vật và độ ẩm từ vệ tinh",
"Field telemetry transport": "Truyền telemetry thực địa",
"Time-series storage": "Lưu trữ chuỗi thời gian",
"Prototype and dashboard delivery": "Cung cấp prototype và dashboard",
"Research schema alignment": "Căn chỉnh schema nghiên cứu",
"Dashboard preview": "Xem trước dashboard",
"Methodology hotspot": "Điểm nhấn phương pháp",
"Results hotspot": "Điểm nhấn kết quả",
"Architecture diagram": "Sơ đồ kiến trúc",
"Confusion matrix": "Ma trận nhầm lẫn",
"Access control form": "Biểu mẫu kiểm soát truy cập",
"Role selection": "Chọn vai trò",
"Please provide name, a valid email, and message before submitting.": "Vui lòng nhập tên, email hợp lệ và nội dung trước khi gửi.",
"Request staged successfully. This static prototype does not send data.": "Yêu cầu đã được chuẩn bị thành công. Prototype tĩnh này không gửi dữ liệu.",
"Collaboration request validated.": "Yêu cầu hợp tác đã được xác thực.",
"Copied to clipboard.": "Đã sao chép vào clipboard.",
"Copy unavailable in this browser.": "Trình duyệt này không hỗ trợ sao chép.",
"Token must contain at least 6 characters.": "Token phải có ít nhất 6 ký tự.",
"Access token format accepted for prototype review.": "Định dạng token truy cập được chấp nhận cho review prototype.",
"role selected. Token validation required.": "đã được chọn. Cần xác thực token.",
"Project identity": "Nhận diện dự án",
"Notifications": "Thông báo",
"Signed in user": "Người dùng đã đăng nhập",
"Zone filters and system status": "Bộ lọc vùng và trạng thái hệ thống",
"Time range": "Khoảng thời gian",
"Interactive zone stress map": "Bản đồ stress vùng tương tác",
"Map tools": "Công cụ bản đồ",
"Zoom in": "Phóng to",
"Zoom out": "Thu nhỏ",
"Toggle degraded mode": "Bật/tắt chế độ suy giảm",
"Stress probability legend": "Chú giải xác suất stress",
"Time series charts": "Biểu đồ chuỗi thời gian",
"AI prediction and recommendation": "Dự đoán AI và khuyến nghị",
"Data sources": "Nguồn dữ liệu",
"Image source": "Nguồn ảnh",
"Sensor source": "Nguồn cảm biến",
"Weather source": "Nguồn thời tiết",
"Recommendation trigger rule": "Luật kích hoạt khuyến nghị",
"Adjust volume": "Điều chỉnh lượng nước",
"Decline": "Từ chối",
"Command queue status": "Trạng thái hàng đợi lệnh",
"Mobile navigation": "Điều hướng mobile",
"Map": "Bản đồ",
"Charts": "Biểu đồ",
"Alerts": "Cảnh báo"
};
const REVERSE_VI = Object.fromEntries(Object.entries(VI).map(([en, vi]) => [vi, en]));
const ATTRS = ["title", "aria-label", "placeholder", "alt"];
const SKIP_TAGS = new Set(["SCRIPT", "STYLE", "SVG", "CANVAS", "PRE", "CODE", "SAMP", "KBD"]);
let currentLang = localStorage.getItem("agtech-language") === "vi" ? "vi" : "en";
let translating = false;
function normalize(value) {
return value.replace(/\s+/g, " ").trim();
}
function translate(value, lang = currentLang) {
const normalized = normalize(value);
if (!normalized) return value;
if (lang === "vi") {
return VI[normalized] || translatePattern(normalized) || value;
}
return REVERSE_VI[normalized] || value;
}
function translatePattern(value) {
let match = value.match(/^(.+?) role selected\. Token validation required\.$/);
if (match) return `${translate(match[1], "vi")} đã được chọn. Cần xác thực token.`;
match = value.match(/^Uncertainty ([0-9.]+)( \/ Requires confirmation)?$/);
if (match) return `Độ bất định ${match[1]}${match[2] ? " / Cần xác nhận" : ""}`;
match = value.match(/^(.+?) Time-Series Trends$/);
if (match) return `${translate(match[1], "vi")} Xu hướng chuỗi thời gian`;
match = value.match(/^(.+?) \/ Stress Overlay$/);
if (match) return `${translate(match[1], "vi")} / Lớp phủ stress`;
match = value.match(/^Stress ([0-9]+)% \/ Uncertainty ([0-9.]+)$/);
if (match) return `Stress ${match[1]}% / Độ bất định ${match[2]}`;
match = value.match(/^Last update (.+)$/);
if (match) return `Cập nhật cuối ${match[1]}`;
return "";
}
function shouldSkip(node) {
let element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
while (element) {
if (SKIP_TAGS.has(element.tagName) || element.dataset.noI18n === "true") return true;
element = element.parentElement;
}
return false;
}
function originalText(node) {
const value = normalize(node.nodeValue);
if (!value) return "";
if (!node.__i18nOriginal || (value !== node.__i18nOriginal && value !== translate(node.__i18nOriginal, "vi"))) {
node.__i18nOriginal = REVERSE_VI[value] || value;
}
return node.__i18nOriginal;
}
function translateTextNode(node) {
if (shouldSkip(node)) return;
const original = originalText(node);
if (!original) return;
const translated = translate(original);
const nextValue = node.nodeValue.replace(node.nodeValue.trim(), translated);
if (nextValue !== node.nodeValue) node.nodeValue = nextValue;
}
function translateAttributes(element) {
if (shouldSkip(element)) return;
ATTRS.forEach((attr) => {
if (!element.hasAttribute(attr)) return;
const value = element.getAttribute(attr);
const key = `i18nOriginal${attr.replace(/[^a-z]/gi, "")}`;
const stored = element.dataset[key];
if (!stored || (value !== stored && value !== translate(stored, "vi"))) {
element.dataset[key] = REVERSE_VI[normalize(value)] || normalize(value);
}
const translated = translate(element.dataset[key]);
if (element.getAttribute(attr) !== translated) element.setAttribute(attr, translated);
});
}
function translateTree(root = document.body) {
if (!root) return;
translating = true;
if (root.nodeType === Node.TEXT_NODE) {
translateTextNode(root);
} else {
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
acceptNode(node) {
return node.nodeValue.trim() && !shouldSkip(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
}
});
while (walker.nextNode()) translateTextNode(walker.currentNode);
if (root.nodeType === Node.ELEMENT_NODE) translateAttributes(root);
root.querySelectorAll?.("*").forEach(translateAttributes);
}
document.documentElement.lang = currentLang;
const translatedTitle = translate(document.title, currentLang);
if (document.title !== translatedTitle) document.title = translatedTitle;
updateToggle();
translating = false;
}
function updateToggle() {
const toggle = document.getElementById("languageToggle");
if (!toggle) return;
const nextTitle = currentLang === "vi" ? VI["Switch language to English"] : "Switch language to Vietnamese";
const label = currentLang === "vi" ? "EN" : "VI";
if (toggle.querySelector("span").textContent !== label) toggle.querySelector("span").textContent = label;
if (toggle.title !== nextTitle) toggle.title = nextTitle;
if (toggle.getAttribute("aria-label") !== nextTitle) toggle.setAttribute("aria-label", nextTitle);
}
function setLanguage(lang) {
currentLang = lang === "vi" ? "vi" : "en";
localStorage.setItem("agtech-language", currentLang);
translateTree();
}
document.addEventListener("DOMContentLoaded", () => {
const toggle = document.getElementById("languageToggle");
toggle?.addEventListener("click", () => setLanguage(currentLang === "vi" ? "en" : "vi"));
const observer = new MutationObserver((mutations) => {
if (translating || currentLang !== "vi") return;
mutations.forEach((mutation) => {
if (mutation.type === "characterData") translateTextNode(mutation.target);
mutation.addedNodes.forEach((node) => translateTree(node));
});
});
observer.observe(document.body, { childList: true, subtree: true, characterData: true });
setLanguage(currentLang);
});
window.agtechI18n = { setLanguage, translate };
})();