Files
FixIt/i18n/vi.toml
T
Cell 14a965f9c1 refactor(assets): migrate JavaScript to TypeScript service architecture (#766)
* refactor: add TypeScript support and refactor utility functions

* docs: add CLAUDE.md for Claude Code guidance

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(assets): replace factory-function pattern with service classes and DI container

Introduce typed service container, event bus, and service interfaces to replace
the shared FixItContext factory-function pattern. Each module is now a standalone
class implementing a typed interface, with explicit constructor-injected
dependencies. The window.fixit backward-compatibility facade is built via a
publicAPI() helper that extracts class methods.

Also removes unnecessary setTimeout/afterPaint deferred execution wrappers
from init sequences, and improves module header comments.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor: replace private properties with class fields in modules

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(assets): rewrite link page script in TypeScript

Rename pages/link.js to link.ts with proper type annotations and update
the Hugo template reference accordingly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs: rewrite CLAUDE.md and copilot-instructions.md in English

Update both files to reflect the new service-class architecture with
DI container, typed event bus, and ES6 # private fields.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix: update event handling to use CustomEvent for better type safety

* refactor: enhance theme switching by adding isChanged flag to event details

* refactor(assets): refactor Mermaid module structure and event wiring

* refactor(assets): align lib integrations with TypedEventBus and add module overviews

* chore(assets): remove vite-specific import ignore comments

* refactor(assets): remove deprecated forEach utility and use native forEach

Replace custom forEach wrapper with native .forEach() on NodeList, HTMLCollection (via querySelectorAll), and arrays. The utility was already marked @deprecated and all 30+ call sites use synchronous handlers, making the wrapper unnecessary. Also replace getElementsByClassName/getElementsByTagName with querySelectorAll for consistency.

- Delete utils/array.ts (no longer needed)
- Remove forEach export from utils/index.ts
- Refactor 11 module files to use native .forEach()
- Switch getElementsByClassName to querySelectorAll in theme.ts and charts.ts

* refactor(assets): split ChartsModule into independent lib files

Move ECharts, Mapbox GL, and TypeIt integrations from the ServiceContainer-managed ChartsModule into three standalone lib files (echarts.ts, mapbox.ts, typeit.ts). Each lib:
- Instantiates its own TypedEventBus
- Reads config from window.config.*
- Self-initializes on DOMContentLoaded
- Handles decrypt/re-init events independently
- Uses implicit idempotency via DOM element queries

Key improvements:
- Reduces ServiceContainer complexity
- Makes chart libs independently loadable
- Fixes partial decryption handling in echarts (only re-inits decrypted portion)
- Maintains consistency with aplayer/file-tree lib pattern

* refactor(assets): extract third-party libraries to standalone lib files

Extract twemoji, pangu, cookieconsent, watermark, lightgallery, and json-viewer
from modules into separate lib files for better separation of concerns. Each lib
is loaded conditionally via assets.html and handles its own initialization and
event lifecycle independently.

Additionally, unify fixit event handling by replacing document.addEventListener
calls with TypedEventBus.on() in EncryptionModule and MiscModule for consistent
event architecture.

Remove unused MiscService dependency from ContentModule.

* refactor(assets): unify js.Build pipeline and defaults

- extract shared helper partial function/js-build.html for js.Build + minify

- make plugin script renderer and Mermaid use the same js.Build logic

- default Build.minify to hugo.IsProduction when unset

- default Build.sourceMap to cond hugo.IsDevelopment "linked" "none"

- remove duplicated sourceMap branching in layout templates

- update js targetPath naming to .js (no explicit .min.js suffix)

* refactor(assets): extract comment systems to independent lib files

Extract comment system initialization logic from CommentModule into 7 independent
lib files (artalk, gitalk, valine, waline, utterances, twikoo, giscus). Each lib:
- Conditionally loads based on window.config.comment configuration
- Handles backend-specific initialization via DOMContentLoaded
- Manages its own theme synchronization and event listeners
- Is loaded conditionally in assets.html only when enabled

Simplify CommentModule to handle only:
- Comment section UI display and visibility toggle
- Shared lightGallery initialization utility (used by Artalk and Twikoo)
- Comment expiration handling

This reduces module complexity and enables per-backend lazy loading.

* refactor(assets): unify js.Build pipeline and consolidate PWA config

Enhance js-build.html to accept Build as bool/dict, auto-derive
targetPath from resource name (.ts → .js), and skip js.Build when
Build is false/omit. Simplify assets.html by removing explicit
targetPath dicts for all .ts lib builds. Consolidate enablePWA and
serviceWorkerURL into a PWA config object.

* refactor(assets): decouple toc from content module and add JSDoc headers

- Remove TocService dependency from ContentModule, toc now self-manages
- Rename initContent() → setup(), init() → setup() for toc
- Make initFootnotes private (#initFootnotes)
- Add multi-line JSDoc headers with Responsibilities to all modules,
  main.ts, pages/link.ts, and head/color-scheme.ts

* refactor(assets): split types.ts into types/ directory module

* refactor(assets): simplify JS module architecture and expose typed window.fixit API

- Remove DI container (core/container.ts), use direct constructor calls
- Export shared eventBus singleton from core/event-bus.ts, remove 16 redundant instances
- Merge thin modules: SvgModule/CommentModule/LinkGuardModule into ContentModule/MiscModule
- Trim service interfaces to externally-used methods only
- Replace publicAPI() reflection with minimal typed window.fixit facade
- Expose public APIs: setThemeMode, eventBus, initContent, mask overlay, scroll state
- Extract setThemeMode from initSwitchTheme closure as public method
- Rename fixit:reset to fixit:re-encrypt, remove dead events
- Replace custom.js.example with custom.ts.example
- Update CLAUDE.md and copilot-instructions.md

* style(i18n): use semantic names for comment dividers instead of file paths

Replace file-path-based comment dividers (e.g. partials/base/header.html)
with semantic names (e.g. Header) across all 16 i18n files for consistency.

* chore(workflow): update cron schedule for library updates

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 12:43:42 +08:00

253 lines
7.0 KiB
TOML

# Translations for Vietnamese
# https://gohugo.io/content-management/multilingual/#translation-of-strings
# === Init ===
[init]
hugoVersionError = "Phiên bản Hugo quá thấp.\n\nPhiên bản Hugo hiện tại là {{ .Current }}, phiên bản tối thiểu được hỗ trợ cho FixIt là {{ .Minimal }}.\n\nNếu bạn đang chạy Hugo trên máy tính của mình, hãy xem https://gohugo.io/getting-started/installing/#upgrade-hugo để biết hướng dẫn nâng cấp.\n\nNếu bạn đang triển khai trên nền tảng của bên thứ ba, vui lòng cấu hình phiên bản Hugo cho phù hợp."
hugoExtendedWarn = "Phiên bản Hugo Extended là cần thiết để hỗ trợ SCSS."
configurationError = "Lỗi cấu hình\nBạn chưa cấu hình tham số phiên bản FixIt đúng cách. Xem https://fixit.lruihao.cn/documentation/basics/#theme-configuration"
compatibilityError = "Lỗi tương thích ({{ .From }} -> {{ .To }}):\nBạn có một bản cập nhật không tương thích. Xem https://github.com/hugo-fixit/FixIt/releases"
devVersionWarn = "Bạn đang sử dụng một phiên bản phát triển của FixIt. Vui lòng xem xét sử dụng một phiên bản ổn định.\nXem https://github.com/hugo-fixit/FixIt/releases"
devEnvWarn = "Môi trường hiện tại là \"development\". \"Hệ thống bình luận\", \"PWA\", \"CDN\", \"vân tay\" và \"thống kê\" sẽ bị vô hiệu hóa."
quicklyUpgrade = "Nâng cấp nhanh bằng lệnh: "
# === Init ===
# === Base Layout ===
[baseof]
backToTop = "Lên trên"
viewComments = "Xem bình luận"
noscript = "Trang web này hoạt động tốt nhất khi JavaScript được kích hoạt."
# === Base Layout ===
# === Taxonomy ===
[archives]
other = "Bài viết cũ"
[allSome]
other = "Tất cả {{ .Some }}"
[category]
other = "Danh mục"
[categories]
other = "Danh mục"
[collection]
other = "Collection"
[collections]
other = "Collections"
[tag]
other = "Nhãn"
[tags]
other = "Nhãn"
[posts]
other = "Bài viết"
# === Taxonomy ===
# === Section ===
[section]
recentlyUpdated = "Mới nhất"
[section.totalWordCount]
one = "Chỉ một từ"
other = "Tổng cộng {{ .Count }} từ"
[section.archiveCounter]
one = "Chỉ một bài viết"
other = "{{ .Count }} bài viết"
# === Section ===
# === Pagination ===
[pagination]
more = "Thêm"
# === Pagination ===
# === Header ===
[header]
selectLanguage = "Chọn Ngôn ngữ"
noMoretTranslations = "Không có nữa"
switchTheme = "Đổi chủ đề"
# === Header ===
# === Footer ===
[footer]
poweredBySome = "Cung cấp bởi {{ .Hugo }} | Chủ đề - {{ .Theme }}"
siteUV = "Tổng khách truy cập"
sitePV = "Tổng lượt truy cập"
siteRunning = "Trang web đang chạy ..."
# === Footer ===
# === Comment ===
[comment]
valineLang = "en" # Valine không hỗ trợ tiếng Việt
valinePlaceholder = "Bình luận của bạn ..."
facebookLanguageCode = "vi"
# === Comment ===
# === Assets ===
[assets]
search = "Tìm kiếm"
searchPlaceholder = "Tìm tiêu đề hoặc nội dung..."
searchIn = "Tìm kiếm trong {{ . }}"
gotoResultsPage = "Đi đến trang kết quả tìm kiếm ..."
clear = "Xoá"
cancel = "Huỷ"
noResultsFound = "Không tìm thấy kết quả"
copyToClipboard = "Sao chép vào bộ nhớ tạm"
copyText = "Sao chép"
copiedText = "Đã sao chép"
toggleLineNumbers = "Chuyển đổi số dòng"
toggleLineWrap = "Chuyển đổi xuống dòng"
toggleCodeEditable = "Chuyển đổi khối mã có thể chỉnh sửa"
downloadCode = "Tải mã"
expandCode = "Mở rộng hoặc thu gọn khối mã"
fullscreen = "Toàn màn hình"
exitFullscreen = "Thoát toàn màn hình"
cookieconsentMessage = "Trang web này sử dụng Cookies để cải thiện trải nghiệm của bạn."
cookieconsentDismiss = "Đã hiểu!"
cookieconsentLink = "Tìm hiểu thêm"
# === Assets ===
# === Share ===
[shareOn]
other = "Chia sẻ trên"
# === Share ===
# === Single Post ===
[single]
contents = "Nội dung"
pin = "Ghim ở đầu trang"
repost = "Đăng lại"
publishedOnDate = "đăng ngày {{ .Date }}"
views = "lượt xem"
comments = "bình luận"
author = "Tác giả"
updatedOnDate = "Cập nhật ngày {{ .Date }}"
readMarkdown = "Đọc với định dạng Markdown"
viewSource = "Xem mã nguồn"
editThisPage = "Chỉnh sửa trang này"
reportIssue = "Báo cáo lỗi"
openInEditor = "Mở trong trình chỉnh sửa"
back = "Quay lại"
home = "Trang chủ"
readMore = "Đọc thêm"
expirationReminder = "Bài viết này được cập nhật lần cuối vào {{ .Date }}, nội dung có thể đã lỗi thời."
encryptedAbstract = "Bài viết này đã được mã hóa, nên nội dung gốc không thể nhìn thấy!"
encryptedMessage = "Vui lòng nhập mật khẩu"
password = "Mật khẩu"
enterBtn = "Nhập"
encryptyAgain = "Mã hóa lại"
relatedContent = "Nội dung liên quan"
[single.includedIn]
categories = "trong {{ .Categories }}"
collections = "trong {{ .Collections }}"
both = "trong {{ .Categories }} và {{ .Collections }}"
[single.wordCount]
one = "One word"
other = "{{ .Count }} từ"
[single.fuzzyWordCount]
other = "Khoảng {{ .Count }} từ"
[single.readingTime]
one = "One minute"
other = "{{ .Count }} phút"
[single.reward]
donate = "Ủng hộ"
wechatpay = "WeChat Pay"
alipay = "Alipay"
paypal = "PayPal"
bitcoin = "Bitcoin"
# === Single Post ===
# === Error Pages ===
[pageNotFound]
other = "Không tìm thấy trang"
[pageNotFoundText]
other = "Trang bạn đang tìm kiếm không tồn tại. Xin lỗi."
# === Error Pages ===
# === Offline ===
[offlineTitle]
other = "ngoại tuyến"
[offlineText]
other = "Bạn chưa kết nối với Internet, chỉ các trang được lưu trong bộ nhớ cache sẽ khả dụng."
# === Offline ===
# === Link Redirection ===
[linkRedirection]
title = "Thông báo chuyển hướng"
message = "Bạn sắp rời khỏi {{ .Title }}, vui lòng chú ý an toàn cho tài khoản và tài sản của mình."
confirm = "Tiếp tục truy cập"
# === Link Redirection ===
# === Alert ===
[alert]
note = "Ghi chú"
tip = "Mẹo"
important = "Quan trọng"
warning = "Cảnh báo"
caution = "Chú ý"
# === Alert ===
# === Task List ===
[taskList]
x = "Đã kiểm tra"
" " = "Chưa kiểm tra"
"/" = "Đang tiến hành"
"-" = "Đã hủy"
"<" = "Đã lên lịch"
">" = "Đã lên lịch lại"
"!" = "Quan trọng"
"!x" = "Quan trọng Đã kiểm tra"
"?" = "Câu hỏi"
# === Task List ===
# === Admonition ===
[admonition]
note = "Ghi chú"
abstract = "Tóm tắt"
info = "Thông tin"
todo = "Cần làm"
tip = "Mẹo"
success = "Thành công"
question = "Câu hỏi"
warning = "Cảnh báo"
failure = "Thất bại"
danger = "Nguy hiểm"
bug = "Lỗi"
example = "Ví dụ"
quote = "Trích dẫn"
# === Admonition ===
# === Version ===
[version]
new = "MỚI"
changed = "THAY ĐỔI"
deleted = "XOÁ"
deprecated = "KHÔNG CÒN SỬ DỤNG"
# === Version ===
# === Diagram ===
[diagram]
zoomIn = "Phóng to"
zoomOut = "Thu nhỏ"
reset = "Đặt lại"
download = "Tải SVG"
# === Diagram ===
# === Tabs ===
[tabs]
diagram = "Sơ đồ"
code = "Mã"
# === Tabs ===