ADR-0005. Tùy chọn locale theo tài khoản phục vụ qua /auth/me chuẩn tắc
| Trường | Giá trị |
|---|---|
| Trạng thái | Accepted |
| Ngày | 2026-06-21 |
| Người quyết định | Phat Nguyen |
| Thay thế | - |
Bối cảnh
- BANA-970 cần ngôn ngữ UI lưu theo tài khoản, đi theo người dùng qua mọi thiết bị/trình duyệt, ghi đè fallback
navigator.languagehiện tại. - Cột
localeđã tồn tại trênUserProfile(mặc địnhen-US);PATCH /users/profileđã nhận giá trị này. Thiếu là một seam đọc ổn định và một tập giá trị ràng buộc. @venizia/ignis0.0.10-0bổ sung seam current-user gốc framework:IAuthService.getUserInformation→GET /auth/mevàGET /auth/who-am-i?withUserInformation=true(cộng thêm, trả501khi chưa hiện thực).- i18n frontend (
apps/core) dùng mã ngắnen/vi; giá trị lưu trữ là BCP-47en-US/vi-VN.
Quyết định
Giữ locale trên UserProfile dạng BCP-47 (en-US | vi-VN), ràng buộc bởi hằng dùng chung Locales + LocaleSchema. Hiện thực AuthenticationService.getUserInformation trả toàn bộ user profile (UserProfileSelectSchema, gồm emails[], phones[], locale), và lấy GET /auth/me làm endpoint đọc current-user chuẩn tắc. Ghi vẫn qua PATCH /users/profile (profile.locale). Frontend ánh xạ BCP-47 ↔ mã ngắn i18n ở biên.
| Vấn đề | Hướng xử lý |
|---|---|
| Lưu trữ | UserProfile.locale sẵn có, text().$type<TLocale>().default('en-US') - không thêm cột |
| Tập giá trị | Locales (EN='en-US', VI='vi-VN') + LocaleSchema; áp trên Zod insert/update + sign-up |
| Đọc | GET /auth/me qua getUserInformation (chuẩn tắc); /who-am-i?withUserInformation=true kèm theo |
| Ghi | PATCH /users/profile → profile.locale (giữ nguyên) |
| Payload | Toàn bộ UserProfileSelectSchema (nullable) - emails[], phones[], tên, locale, … |
| Dữ liệu cũ | Migration backfill chuẩn hoá giá trị ngoài {en-US,vi-VN}/null → en-US |
Hệ quả
| Ưu | Nhược |
|---|---|
| Tái dùng seam framework + cột sẵn có - bề mặt tối thiểu | Tồn tại 2 đường đọc tạm thời (/auth/me vs /users/profile) đến khi FE chuyển |
| Một nguồn sự thật cho shape current-user về sau | Ánh xạ BCP-47 ↔ mã ngắn nằm ở FE, không ở BE |
| Tập giá trị tập trung; giá trị sai bị chặn khi ghi | getUserInformation thêm một truy vấn include profile mỗi lần gọi /me |
| Không có mã app FE trong package này; tài liệu handoff dẫn dắt client | - |
Phương án đã cân nhắc
| Phương án | Ưu | Nhược | Lý do loại |
|---|---|---|---|
Thêm cột locale trên User/account | Đúng câu chữ ticket | Trùng UserProfile.locale sẵn có | Dư thừa; vi phạm fold-into-existing |
Lưu mã ngắn en/vi | Không cần ánh xạ FE | Lệch dữ liệu en-US sẵn có + chuẩn BCP-47 | PO chọn giữ BCP-47 |
Chỉ giữ đọc ở GET /users/profile | Không thêm endpoint | Hai đường "me" song song, không có cái chuẩn tắc | /auth/me là seam current-user gốc framework |
UserConfiguration USER_PREFERENCES jValue | Bucket prefs tổng quát | Thêm bảng + plumbing cho một field | UserProfile.locale đã nối sẵn |
Tham chiếu
- BANA-970 -
[FE/client] Add account locale auto-applied on sign-in core/src/common/constants.ts(Locales,TLocale)core/src/models/schemas/identity/user-profile/(schema.tscột locale,model.tsLocaleSchema)identity/src/services/authentication.service.ts(getUserInformation)identity/src/models/responses/auth.response.ts(GetUserInformationResponse)identity/src/application.ts(auth controllerpayload.getUserInformation)@venizia/ignis0.0.10-0- changelog endpoint thông tin người dùng