Chuyển tới nội dung chính

Trường tùy chỉnh và loại nội dung

Nhân sự có thể tạo loại nội dung (ví dụ «Sự kiện», «Linh mục quản xứ») và trường tùy chỉnh (ví dụ «Ngày diễn ra», «Địa điểm») trong trang quản trị. Mỗi entry trả về hai trường liên quan:

TrườngKiểuÝ nghĩa
contentTypestring | nullSlug của loại nội dung; null với bài thường và với trang tĩnh.
metaobjectCác giá trị trường tùy chỉnh, khóa là khóa của trường.

Có ở cả mục danh sách lẫn chi tiết.

Thống nhất khóa với nhân sự trước​

API công khai không trả về định nghĩa trường (tên hiển thị, kiểu, bắt buộc hay không). meta chỉ là các cặp khóa và giá trị. Vì vậy:

  1. Thống nhất với nhân sự danh sách loại nội dung và khóa trường mà giao diện của bạn dựa vào, ví dụ loại su-kien có ngay-dien-ra (ngày) và dia-diem (văn bản).
  2. Viết giao diện theo contentType và các khóa đó.
  3. Luôn coi mọi khóa là có thể vắng mặt: trường không bắt buộc, trường mới thêm sau khi bài được viết, giá trị theo ngôn ngữ chưa dịch, hoặc nhân sự đổi cấu trúc sau này.

Khóa trường là slug (chữ thường, số, -), tối đa 40 ký tự, duy nhất trong một trang web.

Giá trị theo từng kiểu trường​

Kiểu trườngGiá trị JSON trong metaHiển thị an toàn
Văn bản ngắnstring, tối đa 300 ký tự, một dòngIn ra như văn bản.
Văn bản dàistring, tối đa 5000 ký tự, có thể có xuống dòngIn ra như văn bản, đổi xuống dòng thành <br> hoặc dùng CSS white-space: pre-line. Không chèn như HTML.
Liên kếtstring, luôn bắt đầu bằng https://Dùng làm href; nên thêm rel="noopener noreferrer".
SốnumberĐịnh dạng theo ngôn ngữ (Intl.NumberFormat).
Ngàystring dạng YYYY-MM-DD (chỉ ngày, không giờ)Phân tích như một ngày lịch, không qua new Date(…) theo giờ địa phương, kẻo lệch một ngày.
Có/khôngboolean
Lựa chọnstring: giá trị (slug) của lựa chọn, không phải nhãnTự ánh xạ giá trị sang nhãn hiển thị.
Hình ảnhobject có url (địa chỉ https:// đầy đủ)Dùng url làm src. Object còn một khóa định danh nội bộ: hãy bỏ qua nó.

Một số trường dùng chung cho mọi ngôn ngữ (ví dụ ngày, ảnh), số khác theo từng ngôn ngữ (ví dụ địa điểm viết bằng tiếng Việt và tiếng Anh). meta bạn nhận được đã gộp sẵn cả hai loại cho locale bạn hỏi. Giá trị theo ngôn ngữ chưa được dịch thì vắng mặt, không dự phòng về ngôn ngữ chính.

Ví dụ: hiển thị một «Sự kiện»​

type Meta = Record<string, unknown>

const text = (v: unknown): string | null => (typeof v === 'string' && v.trim() !== '' ? v : null)

function calendarDate(v: unknown, locale: string): string | null {
if (typeof v !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(v)) return null
const [y, m, d] = v.split('-').map(Number)
// Format in UTC so the calendar day never shifts with the visitor's time zone.
return new Intl.DateTimeFormat(locale, { dateStyle: 'long', timeZone: 'UTC' }).format(new Date(Date.UTC(y, m - 1, d)))
}

function imageUrl(v: unknown): string | null {
if (typeof v !== 'object' || v === null) return null
const url = (v as { url?: unknown }).url
return typeof url === 'string' && url.startsWith('https://') ? url : null
}

function eventDetails(entry: { contentType: string | null; meta: Meta }, locale: string) {
if (entry.contentType !== 'su-kien') return null
return {
date: calendarDate(entry.meta['ngay-dien-ra'], locale),
place: text(entry.meta['dia-diem']),
poster: imageUrl(entry.meta['anh-poster']),
}
}

Các khóa su-kien, ngay-dien-ra, dia-diem, anh-poster ở trên chỉ là ví dụ; dùng khóa mà bạn đã thống nhất với nhân sự.

Loại nội dung «không liệt kê»​

Nhân sự có thể đặt một loại nội dung là không liệt kê. Bài của loại đó không có trong danh sách chung, trong tìm kiếm và trong «Đọc nhiều», nhưng vẫn có trong danh sách theo danh mục hoặc thẻ và vẫn mở được theo slug. Dùng cách này cho những mục có trang riêng (ví dụ một danh mục «Sự kiện» hiển thị dạng lịch) mà không muốn chen vào dòng tin chung.