diff --git a/crates/ui-egui/locales/vi-formats.json b/crates/ui-egui/locales/vi-formats.json new file mode 100644 index 000000000..62e1ef46d --- /dev/null +++ b/crates/ui-egui/locales/vi-formats.json @@ -0,0 +1,251 @@ +{ + " ({unsure} with several look-alike files: use Locate)": " ({unsure} có nhiều tệp trông giống nhau: dùng Định vị)", + " ({} in Recently Deleted)": " ({} trong Đã xóa gần đây)", + " · {:.0}% clipped": " · {:.0}% bị cắt", + " · {failed} couldn't be rendered": " · {failed} không thể kết xuất", + " · {queued} waiting": " · {queued} đang chờ", + " · {skipped} skipped (file exists)": " · {skipped} đã bỏ qua (tệp đã tồn tại)", + " · {} duplicate{} skipped": " · {} bản trùng{:.0} đã bỏ qua", + " · {} failed: {}": " · {} thất bại: {}", + " · {} moved": " · {} đã di chuyển", + " · {} not readable": " · {} không đọc được", + " · {} original{} left at the source": " · {} tệp gốc{:.0} còn ở nguồn", + " · {} restored from Recently Deleted": " · {} đã khôi phục từ Đã xóa gần đây", + " — Capture One won't import a list with ; , < or > in a keyword: {names}": " — Capture One không nhập danh sách có từ khóa chứa ; , < hoặc >: {names}", + " — left out, as a keyword list can't hold them: {names}": " — bỏ qua vì danh sách từ khóa không chứa được: {names}", + " — not carried over: {}{}": " — không được chuyển sang: {}{}", + "+{n} more": "+{n} nữa", + "+{} more": "+{} nữa", + ", {failed} file{} not readable": ", {failed} tệp{:.0} không đọc được", + ", {} label": ", nhãn {}", + ", {} star{}": ", {} sao{:.0}", + "1 task is still running: {names}. Quitting stops it.": "Còn 1 tác vụ đang chạy: {names}. Thoát sẽ dừng tác vụ.", + "; {kept} already had a location": "; {kept} đã có vị trí", + "; {n} gained synonyms": "; {n} có thêm từ đồng nghĩa", + "; {outside} outside its time range": "; {outside} ngoài khoảng thời gian của tuyến", + "@{}: {} PRs, {} commits, +{} / −{} lines (Δ {}), +{} / −{} binary assets, {} – {}": "@{}: {} PR, {} commit, +{} / −{} dòng (Δ {}), +{} / −{} tài nguyên nhị phân, {} – {}", + "Add {local_n} to My Photos": "Thêm {local_n} vào Ảnh của tôi", + "Add {} Photo{}": "Thêm {} ảnh{:.0}", + "Add {} Photo{}, restore {}": "Thêm {} ảnh{:.0}, khôi phục {}", + "Add “{}” to Favorites": "Thêm «{}» vào Yêu thích", + "Added {n} keyword{}": "Đã thêm {n} từ khóa{:.0}", + "Added {n} photo{} to My Photos": "Đã thêm {n} ảnh{:.0} vào Ảnh của tôi", + "Added {n} photo{} to “{}”": "Đã thêm {n} ảnh{0:.0} vào «{1}»", + "Added {what} to {name}": "Đã thêm {what} vào {name}", + "Added “{keyword}” to {n} photo{}": "Đã thêm «{keyword}» vào {n} ảnh{:.0}", + "Adding photos… {} of {}": "Đang thêm ảnh… {} / {}", + "All {n} selected photos move by the same amount.": "Tất cả {n} ảnh đã chọn dịch chuyển cùng một lượng.", + "Already in the library, in Recently Deleted: {} photo{} selected · right-click ▸ Restore, or Delete Permanently to import afresh": "Đã có trong thư viện, trong Đã xóa gần đây: đã chọn {} ảnh{:.0} · nhấp chuột phải ▸ Khôi phục, hoặc Xóa vĩnh viễn để nhập lại", + "Already in the library: {} photo{} selected in All Photos": "Đã có trong thư viện: đã chọn {} ảnh{:.0} trong Tất cả ảnh", + "Auto ({})": "Tự động ({})", + "Auto Import: added {} photo{}": "Tự động nhập: đã thêm {} ảnh{:.0}", + "Auto Sync: edits apply to {n} photos": "Đồng bộ tự động: chỉnh sửa áp dụng cho {n} ảnh", + "Automatic ({} MB)": "Tự động ({} MB)", + "Build 1:1 Previews ({scope})": "Tạo xem trước 1:1 ({scope})", + "Build Smart Previews ({scope})": "Tạo xem trước thông minh ({scope})", + "Build Standard-Sized Previews ({scope})": "Tạo xem trước cỡ chuẩn ({scope})", + "Building previews for {} photos…": "Đang tạo xem trước cho {} ảnh…", + "Click {}:1": "Nhấp {}:1", + "Couldn't open the editor: {e}": "Không thể mở trình chỉnh sửa: {e}", + "Create Keyword Tag Inside “{name}”…": "Tạo từ khóa trong «{name}»…", + "Create {n} Virtual Copies": "Tạo {n} bản sao ảo", + "Creates {} stacks from {} of {scope}": "Tạo {} chồng từ {} trong {scope}", + "Decoder: {reason}": "Bộ giải mã: {reason}", + "Delete \"{label}\"": "Xóa «{label}»", + "Delete \"{label}\" (and the mask)": "Xóa «{label}» (và mặt nạ)", + "Delete the keyword “{name}”?": "Xóa từ khóa «{name}»?", + "Delete {n} Photos": "Xóa {n} ảnh", + "Delete “{current}”": "Xóa «{current}»", + "Denoising {name}: {done} of {total} tiles{}": "Khử nhiễu {name}: {done} / {total} ô{}", + "Discard Smart Previews ({scope})": "Hủy xem trước thông minh ({scope})", + "Done ({what}): {done} photo{plural}": "Xong ({what}): {done} ảnh{plural:.0}", + "Downloads from {host}. Once it has arrived and checked out, LightCraft installs it, {after}.": "Tải từ {host}. Sau khi tải xong và kiểm tra, LightCraft cài đặt, {after}.", + "Duplicate \"{label}\"": "Nhân bản «{label}»", + "Example: {example}": "Ví dụ: {example}", + "Exported {n} keyword{}": "Đã xuất {n} từ khóa{:.0}", + "Exported {n} photo{}": "Đã xuất {n} ảnh{:.0}", + "Exported {ok} of {total} photo{}": "Đã xuất {ok} / {total} ảnh{:.0}", + "Exported {} point curve preset{}": "Đã xuất {} thiết lập sẵn đường cong điểm{:.0}", + "Exported {} preset{}": "Đã xuất {} thiết lập sẵn{:.0}", + "Exporting {} of {total}": "Đang xuất {} / {total}", + "Filter bar — {active} active filter{}": "Thanh lọc — {active} bộ lọc đang bật{:.0}", + "Filtered: {label}": "Đã lọc: {label}", + "Focus {:.0}": "Tiêu điểm {:.0}", + "Folder “{}” (and its subfolders)": "Thư mục «{}» (và thư mục con)", + "Found {n} missing photo{}; {left} still missing{unsure}": "Tìm thấy {n} ảnh thiếu{:.0}; còn thiếu {left}{unsure}", + "Healed {n} dust spot{}": "Đã xử lý {n} vết bụi{:.0}", + "Import cancelled · {} photo{} added": "Đã hủy nhập · đã thêm {} ảnh{:.0}", + "Import failed: {e}": "Nhập thất bại: {e}", + "Import warnings ({n}):\n{warnings}": "Cảnh báo khi nhập ({n}):\n{warnings}", + "Imported {n} point curve preset{}": "Đã nhập {n} thiết lập sẵn đường cong điểm{:.0}", + "Imported {n} preset{}": "Đã nhập {n} thiết lập sẵn{:.0}", + "Imported {n} preset{}, {f} file{} not readable": "Đã nhập {n} thiết lập sẵn{:.0}, {f} tệp{:.0} không đọc được", + "Imported {profiles} profile{} (Profile browser ▸ their groups)": "Đã nhập {profiles} hồ sơ{:.0} (Trình duyệt hồ sơ ▸ nhóm của chúng)", + "Imported {} photo{}": "Đã nhập {} ảnh{:.0}", + "In line for AI Denoise ({ahead} ahead)…": "Đang xếp hàng Khử nhiễu AI (trước bạn: {ahead})…", + "Insert at the cursor (also written {})": "Chèn tại con trỏ (cũng ghi là {})", + "It is taken off {count} photo{}, with the keywords below it. Undo brings it back.": "Sẽ gỡ khỏi {count} ảnh{:.0}, kèm từ khóa con. Hoàn tác sẽ khôi phục.", + "Label Set: {name}": "Bộ nhãn: {name}", + "LightCraft can't decode this raw variant yet ({}). You're editing the camera's embedded JPEG preview, which already includes the camera's picture style (e.g. Monochrome) and white balance.": "LightCraft chưa giải mã được biến thể raw này ({}). Bạn đang chỉnh JPEG xem trước nhúng của máy ảnh, đã gồm style ảnh (ví dụ Monochrome) và cân bằng trắng.", + "LightCraft could not open its window: {e}": "LightCraft không thể mở cửa sổ: {e}", + "LightCraft could not open its window: {e}\n\nThe log file has the details: {path}": "LightCraft không thể mở cửa sổ: {e}\n\nChi tiết trong tệp nhật ký: {path}", + "Lightroom catalog inspected: {photos} photos, {collections} collections, {missing} missing": "Đã kiểm tra catalog Lightroom: {photos} ảnh, {collections} bộ sưu tập, {missing} thiếu", + "Lightroom geometry for {path} was not preserved; Guided Upright saved transform is unsupported.": "Hình học Lightroom cho {path} không được giữ; biến đổi Guided Upright đã lưu không được hỗ trợ.", + "Lightroom geometry for {path} was not preserved; saved Upright transform is unsupported.": "Hình học Lightroom cho {path} không được giữ; biến đổi Upright đã lưu không được hỗ trợ.", + "Lightroom geometry for {path} was not preserved; saved transform is ignored because Upright is Off.": "Hình học Lightroom cho {path} không được giữ; biến đổi đã lưu bị bỏ qua vì Upright đang tắt.", + "Lightroom geometry was not preserved for {path}; {mode} will be recalculated.": "Hình học Lightroom cho {path} không được giữ; {mode} sẽ được tính lại.", + "Lightroom import complete: {imported} photos added": "Nhập Lightroom xong: đã thêm {imported} ảnh", + "Lightroom import complete: {imported} photos added, {failed} failed": "Nhập Lightroom xong: đã thêm {imported} ảnh, {failed} thất bại", + "Lightroom import complete: {imported} photos added; index warning: {warning}": "Nhập Lightroom xong: đã thêm {imported} ảnh; cảnh báo chỉ mục: {warning}", + "Lightroom import failed: {e}{warning}": "Nhập Lightroom thất bại: {e}{warning}", + "Lightroom inspection failed: {e}{warning}": "Kiểm tra Lightroom thất bại: {e}{warning}", + "MIT OR Apache-2.0. Fonts: {} (OFL). Icons: original.": "MIT OR Apache-2.0. Phông: {} (OFL). Biểu tượng: tác phẩm gốc.", + "Making the denoised picture… {}%": "Đang tạo ảnh đã khử nhiễu… {}%", + "Matches: {}": "Khớp: {}", + "Merging… {stage} {:.0}%": "Đang ghép… {stage} {:.0}%", + "Move {what} to Recently Deleted?": "Chuyển {what} vào Đã xóa gần đây?", + "Moved {} photo(s)": "Đã di chuyển {} ảnh", + "Moved; {} photo(s) relinked": "Đã di chuyển; liên kết lại {} ảnh", + "Named ({named_n})": "Có tên ({named_n})", + "New Folder in “{name}”": "Thư mục mới trong «{name}»", + "On {have} of {of} selected photos": "Trên {have} / {of} ảnh đã chọn", + "Painting “{k}”: click photos to add or remove it · Esc stops": "Gán «{k}»: nhấp ảnh để thêm hoặc gỡ · Esc dừng", + "Paste into {n} photo{} — only settings that were copied are pasted": "Dán vào {n} ảnh{:.0} — chỉ dán các thiết lập đã sao chép", + "Preset: {name}": "Thiết lập sẵn: {name}", + "Preview only — editing the camera's embedded JPEG ({})": "Chỉ xem trước — chỉnh sửa JPEG nhúng của máy ảnh ({})", + "Preview only — {}": "Chỉ xem trước — {}", + "Previews ready for {done} photo{plural}": "Xem trước sẵn sàng cho {done} ảnh{plural:.0}", + "Profile: {}": "Hồ sơ: {}", + "Proof Copy ({})": "Bản sao thử ({})", + "Proof Preview · {}": "Xem trước thử · {}", + "Put inside “{parent}”": "Đặt trong «{parent}»", + "Quick Develop · {n} photos": "Phát triển nhanh · {n} ảnh", + "Quick Develop: {name}": "Phát triển nhanh: {name}", + "Rated {}": "Đã xếp hạng {}", + "Reading Lightroom catalog… {done} of {total}": "Đang đọc catalog Lightroom… {done} / {total}", + "Reading photos… {done} of {total}": "Đang đọc ảnh… {done} / {total}", + "Reading photos… {} of {}": "Đang đọc ảnh… {} / {}", + "Redo {}": "Làm lại {}", + "Remove “{name}”": "Gỡ «{name}»", + "Remove “{name}” and its {count} photo{} from the library?": "Gỡ «{name}» và {count} ảnh{:.0} khỏi thư viện?", + "Remove “{}” from Favorites": "Gỡ «{}» khỏi Yêu thích", + "Removed from {}": "Đã gỡ khỏi {}", + "Removed {what} from {name}": "Đã gỡ {what} khỏi {name}", + "Rename {n} Photos…": "Đổi tên {n} ảnh…", + "Rename “{name}”": "Đổi tên «{name}»", + "Renames “{from}” on {n} photo{} (keywords below it too). Use | for levels, e.g. Travel|Italy. An existing name merges the two.": "Đổi tên «{from}» trên {n} ảnh{:.0} (cả từ khóa con). Dùng | cho cấp, ví dụ Du lịch|Ý. Tên đã có sẽ gộp hai mục.", + "Rendering on the CPU: {why}": "Đang kết xuất trên CPU: {why}", + "Replace {} with:": "Thay {} bằng:", + "Reset {name}": "Đặt lại {name}", + "Reset {} Channel": "Đặt lại kênh {}", + "Restore {}": "Khôi phục {}", + "Restore {} Photo{}": "Khôi phục {} ảnh{:.0}", + "Restored {} photo{} from Recently Deleted": "Đã khôi phục {} ảnh{:.0} từ Đã xóa gần đây", + "Running on the processor: {}.": "Chạy trên bộ xử lý: {}.", + "Running on {}.": "Chạy trên {}.", + "Saved export preset “{}”": "Đã lưu thiết lập sẵn xuất «{}»", + "Scores {scope} for focus and exposure and finds similar shots taken within seconds of each other (bursts).": "Chấm điểm {scope} theo tiêu điểm và phơi sáng, tìm ảnh tương tự chụp trong vài giây (burst).", + "Show {hidden} hidden location{}": "Hiện {hidden} vị trí ẩn{:.0}", + "Showing {n} of {}": "Hiển thị {n} / {}", + "Shows the model's terms, then downloads {} from {host}, installs it and starts using it. Nothing else is sent.": "Hiện điều khoản mô hình, rồi tải {} từ {host}, cài và bắt đầu dùng. Không gửi gì khác.", + "Smart album: {}": "Album thông minh: {}", + "Tagged {n} photo{} from the tracklog": "Đã gắn thẻ {n} ảnh{:.0} từ nhật ký tuyến", + "The SAM 3 download failed: {e}": "Tải SAM 3 thất bại: {e}", + "There is a keyword set “{name}” already": "Đã có bộ từ khóa «{name}»", + "There is a “{name}” at the top level already. Merge the two?": "Đã có «{name}» ở cấp cao nhất. Gộp hai mục?", + "Trained on: {provenance}": "Huấn luyện trên: {provenance}", + "Undo {}": "Hoàn tác {}", + "Unknown tag{s} {} stay{} as typed (see Tags)": "Thẻ{s:.0} không xác định {} giữ nguyên như đã gõ{:.0} (xem Thẻ)", + "Updated “{name}”": "Đã cập nhật «{name}»", + "Version {} — a clean-room, pure-Rust photo library and raw developer.": "Phiên bản {} — thư viện ảnh và trình phát triển raw thuần Rust, clean-room.", + "Version: {}": "Phiên bản: {}", + "Virtual copy “{name}” of {of}": "Bản sao ảo «{name}» của {of}", + "Working on {what} for {} photos…": "Đang xử lý {what} cho {} ảnh…", + "XMP adjustments were not imported for {path}: {fields}.": "Điều chỉnh XMP không được nhập cho {path}: {fields}.", + "XMP profile \"{profile}\" was not applied for {path}; colors may differ from Lightroom.": "Hồ sơ XMP «{profile}» không được áp dụng cho {path}; màu có thể khác Lightroom.", + "none (CPU rendering): {why}": "không (kết xuất CPU): {why}", + "not added to Apple Photos: {e}": "không thêm được vào Apple Photos: {e}", + "the {n} selected photos": "{n} ảnh đã chọn", + "the {} photos in view": "{} ảnh đang hiển thị", + "these {count} photos": "{count} ảnh này", + "{:.1} MB": "{:.1} MB", + "{count} smart preview{} · {:.1} MB": "{count} xem trước thông minh{:.0} · {:.1} MB", + "{done} of {total}": "{done} / {total}", + "{done} of {total} MB": "{done} / {total} MB", + "{file} · {size}": "{file} · {size}", + "{f} folders (and their subfolders)": "{f} thư mục (và thư mục con)", + "{label} Grading": "Phân cấp màu {label}", + "{label} {d:+} on every selected photo": "{label} {d:+} trên mọi ảnh đã chọn", + "{label} {index} of {n}": "{label} {index} / {n}", + "{label}, {n} photos": "{label}, {n} ảnh", + "{matching} of {t} photos": "{matching} / {t} ảnh", + "{matching} photos": "{matching} ảnh", + "{mode} spot {} of {}": "Vết {mode} {} / {}", + "{month}": "Tháng {month}", + "{month} {year}": "Tháng {month} năm {year}", + "{msg} ({failed} failed)": "{msg} ({failed} thất bại)", + "{name} Label": "Nhãn {name}", + "{name} Off": "{name} tắt", + "{name} On": "{name} bật", + "{name} opened for editing; it is stacked with the original": "{name} đã mở để chỉnh sửa; được xếp chồng với bản gốc", + "{name} opened in the other editor": "Đã mở {name} trong trình chỉnh sửa khác", + "{name} · {terms}": "{name} · {terms}", + "{name} — double-click to reset it": "{name} — nhấp đúp để đặt lại", + "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "Đã bỏ qua {n} ảnh cục bộ{0:.0}: album chỉ chứa ảnh thư viện (hãy thêm vào Ảnh của tôi trước)", + "{n} added to Apple Photos": "Đã thêm {n} vào Apple Photos", + "{n} added to Apple Photos album “{album}”": "Đã thêm {n} vào album Apple Photos «{album}»", + "{n} change{} couldn't be written to disk: {e}\nIf you quit now, {} lost.": "Không ghi được {n} thay đổi{0:.0} lên đĩa: {e}\nNếu thoát ngay, sẽ mất.{1:.0}", + "{n} change{} saved in memory but not written to disk: {e}\nLightCraft retries automatically; quitting now would lose {}.": "Đã lưu {n} thay đổi{:.0} trong bộ nhớ nhưng chưa ghi đĩa: {e}\nLightCraft sẽ thử lại tự động; thoát ngay sẽ mất.{:.0}", + "{n} change{} saved in memory but not written to disk: {e} — LightCraft will retry": "Đã lưu {n} thay đổi{:.0} trong bộ nhớ nhưng chưa ghi đĩa: {e} — LightCraft sẽ thử lại", + "{n} found · {sel} selected": "Tìm thấy {n} · đã chọn {sel}", + "{n} originals opened in the other editor": "Đã mở {n} bản gốc trong trình chỉnh sửa khác", + "{n} photos": "{n} ảnh", + "{n} photos in {} are hidden by the filters above": "{n} ảnh trong «{}» bị ẩn bởi bộ lọc phía trên", + "{n} photos opened for editing; each is stacked with its original": "Đã mở {n} ảnh để chỉnh sửa; mỗi ảnh xếp chồng với bản gốc", + "{n} photo{}": "{n} ảnh{:.0}", + "{n} photo{} match · updates automatically as photos change": "{n} ảnh{:.0} khớp · tự cập nhật khi ảnh thay đổi", + "{n} photo{} now · updates automatically as photos change": "Hiện {n} ảnh{:.0} · tự cập nhật khi ảnh thay đổi", + "{n} similar photo{} · View ▸ Clear Filters to see all": "{n} ảnh tương tự{:.0} · Xem ▸ Xóa bộ lọc để thấy tất cả", + "{n} tasks are still running: {names}. Quitting stops them.": "Còn {n} tác vụ đang chạy: {names}. Thoát sẽ dừng chúng.", + "{n} {noun}": "{noun}: {n}", + "{pct} %": "{pct} %", + "{pid} (missing)": "{pid} (thiếu)", + "{sel_n} selected · {counted}": "Đã chọn {sel_n} · {counted}", + "{size} GB": "{size} GB", + "{stage}… {:.0}%": "{stage}… {:.0}%", + "{verb} {n} Photo{}": "{verb} {n} ảnh{:.0}", + "{weekday}, {day}": "{weekday}, {day}", + "{weekday}, {day} {month} {year}": "{weekday}, {day}/{month}/{year}", + "{what} merge added": "Đã thêm ghép {what}", + "{what} merge cancelled": "Đã hủy ghép {what}", + "{what} merge failed: {e}": "Ghép {what} thất bại: {e}", + "{year}": "{year}", + "{{date:…}} directives: {}": "Chỉ thị {{date:…}}: {}", + "{} KB": "{} KB", + "{} MB": "{} MB", + "{} and higher": "{} trở lên", + "{} contributors · {} commits": "{} người đóng góp · {} commit", + "{} failed": "{} thất bại", + "{} files": "{} tệp", + "{} files and {f} folder{}": "{} tệp và {f} thư mục{:.0}", + "{} item{}": "{} mục{:.0}", + "{} label (click more labels to show any of them)": "Nhãn «{}» (nhấp thêm nhãn để hiện ảnh có bất kỳ nhãn nào)", + "{} of 4 guides — drag along lines that should be vertical or horizontal.": "{} / 4 đường dẫn — kéo dọc các đường cần thẳng đứng hoặc nằm ngang.", + "{} of {} from {host}": "{} / {} từ {host}", + "{} photos": "{} ảnh", + "{} photos · exposures {} EV": "{} ảnh · phơi sáng {} EV", + "{} photos · {} · {:.0}° × {:.0}°": "{} ảnh · {} · {:.0}° × {:.0}°", + "{} photo{} not readable": "{} ảnh{:.0} không đọc được", + "{} sample{}": "{} mẫu{:.0}", + "{} sec": "{} giây", + "{} spot(s) on this photo": "{} vùng trên ảnh này", + "{} · {}. Kept in the library's “denoise” folder; the oldest ones that no photo uses go first when the limit is reached.": "{} · {}. Giữ trong thư mục «denoise» của thư viện; khi đạt giới hạn, xóa trước bản cũ nhất không ảnh nào dùng.", + "{} — show their photos": "{} — hiện ảnh của họ", + "· {dups} already in the library": "· {dups} đã có trong thư viện", + "· {in_source} identical copies": "· {in_source} bản sao giống hệt", + "· {n} photo{}": "· {n} ảnh{:.0}", + "· {trashed} in Recently Deleted": "· {trashed} trong Đã xóa gần đây", + "“{parent}” has a “{name}” already. Merge the two?": "«{parent}» đã có «{name}». Gộp hai mục?", + "• {assumption}": "• {assumption}", + "… and {more} more": "… và {more} nữa" +} diff --git a/crates/ui-egui/src/i18n.rs b/crates/ui-egui/src/i18n.rs index 109accfa9..735504dd3 100644 --- a/crates/ui-egui/src/i18n.rs +++ b/crates/ui-egui/src/i18n.rs @@ -126,6 +126,7 @@ language_table! { Ru, "ru", "Русский", "Cyrl", include_str!("../locales/ru.json"); Fr, "fr", "Français", "Latn", include_str!("../locales/fr.json"); Uk, "uk", "Українська", "Cyrl", include_str!("../locales/uk.json"); + Vi, "vi", "Tiếng Việt", "Latn", include_str!("../locales/vi.json"); } // The settings file stores the BCP-47 code (`"zh-hans"`), never the Rust variant name, so a @@ -522,6 +523,9 @@ mod tests { for tag in ["es", "es-ES", "es_MX.UTF-8", "es-419"] { assert_eq!(Locale::parse_tag(tag), Some(Locale::Es), "{tag}"); } + for tag in ["vi", "vi-VN", "vi_VN", "vi_VN.UTF-8"] { + assert_eq!(Locale::parse_tag(tag), Some(Locale::Vi), "{tag}"); + } assert_eq!(Locale::parse_tag("xx"), None); } @@ -667,6 +671,7 @@ mod tests { ("app.language.german", Locale::De), ("app.language.russian", Locale::Ru), ("app.language.ukrainian", Locale::Uk), + ("app.language.vietnamese", Locale::Vi), ]; // One command per language, and every command reachable from the menu table. assert_eq!(commands.len(), Locale::ALL.len()); diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 141d6d782..4636162ca 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -24,6 +24,7 @@ pub const LANGUAGE_COMMANDS: &[UiCommand] = &[ ("app.language.german", crate::i18n::Locale::De.name(), None, "Edit>Language"), ("app.language.russian", crate::i18n::Locale::Ru.name(), None, "Edit>Language"), ("app.language.ukrainian", crate::i18n::Locale::Uk.name(), None, "Edit>Language"), + ("app.language.vietnamese", crate::i18n::Locale::Vi.name(), None, "Edit>Language"), ]; /// Every UI command: the languages, then everything else. `xtask parity` reads both tables from @@ -46,6 +47,7 @@ pub fn language_from_command(id: &str) -> Option { "app.language.german" => Some(crate::i18n::Locale::De), "app.language.russian" => Some(crate::i18n::Locale::Ru), "app.language.ukrainian" => Some(crate::i18n::Locale::Uk), + "app.language.vietnamese" => Some(crate::i18n::Locale::Vi), _ => None, } }