Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/30512-service-mailbox-locales.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@objectstack/service-mailbox': patch
---

i18n(service-mailbox): the mailbox objects' labels, help, options and views ship in all eleven platform languages

Clause-②: no
Metadata-protocol: none

The mailbox objects (`sys_mailbox`, `sys_mail_message` and `sys_mail_association`) now carry Traditional Chinese (`zh-Hant`), Arabic (`ar`), French (`fr`), Brazilian Portuguese (`pt-BR`), Russian (`ru`), German (`de`) and Korean (`ko`) beside the existing `en`, `zh-CN`, `ja-JP` and `es-ES`, so a user reading the app in one of those languages sees the mailbox screens in their own language instead of English. RFC 5322 header names (`Message-ID`, `In-Reply-To`, `Reply-To`, …) and the IMAP `UIDVALIDITY` term stay as written, as they already do in `zh-CN`. Each new locale is registered under its platform-table tag with its source-hash companion, and the package's extract command lists the seven tags, so the existing `check:i18n` bundle check covers them. Part of #30512.
16 changes: 15 additions & 1 deletion packages/services/service-mailbox/scripts/i18n-extract.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* `--merge` preserves every hand-translated string.
*
* os i18n extract packages/services/service-mailbox/scripts/i18n-extract.config.ts \
* --locales=zh-CN,ja-JP,es-ES --fill=default --objects-only --no-metadata-forms \
* --locales=zh-CN,ja-JP,es-ES,zh-Hant,ar,fr,pt-BR,ru,de,ko --fill=default --objects-only --no-metadata-forms \
* --source-hashes \
* --out=packages/services/service-mailbox/src/translations
*
Expand Down Expand Up @@ -41,6 +41,13 @@ import { enObjects } from '../src/translations/en.objects.generated.js';
import { zhCNObjects } from '../src/translations/zh-CN.objects.generated.js';
import { jaJPObjects } from '../src/translations/ja-JP.objects.generated.js';
import { esESObjects } from '../src/translations/es-ES.objects.generated.js';
import { zhHantObjects } from '../src/translations/zh-Hant.objects.generated.js';
import { arObjects } from '../src/translations/ar.objects.generated.js';
import { frObjects } from '../src/translations/fr.objects.generated.js';
import { ptBRObjects } from '../src/translations/pt-BR.objects.generated.js';
import { ruObjects } from '../src/translations/ru.objects.generated.js';
import { deObjects } from '../src/translations/de.objects.generated.js';
import { koObjects } from '../src/translations/ko.objects.generated.js';

/**
* The annotation is load-bearing, not decoration (#10868). `defineStack`
Expand All @@ -63,6 +70,13 @@ const config: ObjectStackDefinition = defineStack({
{ 'zh-CN': { objects: zhCNObjects } },
{ 'ja-JP': { objects: jaJPObjects } },
{ 'es-ES': { objects: esESObjects } },
{ 'zh-Hant': { objects: zhHantObjects } },
{ 'ar': { objects: arObjects } },
{ 'fr': { objects: frObjects } },
{ 'pt-BR': { objects: ptBRObjects } },
{ 'ru': { objects: ruObjects } },
{ 'de': { objects: deObjects } },
{ 'ko': { objects: koObjects } },
],
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

/**
* Auto-generated by 'os i18n extract' for locale 'ar'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';

export const arObjects: NonNullable<TranslationData['objects']> = {
sys_mailbox: {
label: "صندوق البريد",
pluralLabel: "صناديق البريد",
description: "صندوق بريد وارد تنسخ المنصّة رسائله: عنوانه ومالكه",
fields: {
id: {
label: "معرّف صندوق البريد"
},
name: {
label: "الاسم",
help: "الاسم المعروض لصندوق البريد (مثل \"بريد المبيعات\")"
},
address: {
label: "العنوان",
help: "عنوان صندوق البريد. لا يُطابَق أبدًا كمشارك: فالرسالة المرسلة إلى هذا الصندوق لا تخصّ الصندوق نفسه."
},
owner_user_id: {
label: "المالك",
help: "المستخدم الذي يملك صندوق البريد هذا. تُعرَض على المالك كل رسالة وصلت إليه، بما فيها غير المرتبطة."
},
imap_folder: {
label: "المجلد المتزامن",
help: "مجلد IMAP الذي يتبع له مؤشر المزامنة. عند مزامنة صندوق البريد من مجلد آخر، يبدأ المؤشر من جديد."
},
imap_uid_validity: {
label: "UIDVALIDITY",
help: "قيمة UIDVALIDITY للمجلد التي أُخذ المؤشر بموجبها. عندما يُبلغ الخادم قيمة أخرى، تشير معرّفات UID فيه إلى رسائل أخرى ويبدأ المؤشر من جديد."
},
imap_last_uid: {
label: "آخر UID متزامن",
help: "أعلى UID في المجلد سُلِّم بالفعل إلى الاستيعاب (خُزِّن، أو وُجد مخزَّنًا، أو حُجب، أو تُخطّي). تجلب المزامنة التالية معرّفات UID الأعلى منه."
},
imap_synced_at: {
label: "وقت آخر مزامنة",
help: "وقت انتهاء المزامنة آخر مرة من المرور على المجلد."
}
}
},
sys_mail_message: {
label: "رسالة بريد",
pluralLabel: "رسائل البريد",
description: "رسالة بريد واردة منسوخة من صندوق بريد",
fields: {
id: {
label: "معرّف الرسالة"
},
mailbox_id: {
label: "صندوق البريد",
help: "صندوق البريد الذي وصلت إليه الرسالة"
},
message_id: {
label: "Message-ID",
help: "ترويسة Message-ID بعد إزالة الأقواس الزاوية"
},
in_reply_to: {
label: "In-Reply-To",
help: "ترويسة In-Reply-To: معرّفات الرسائل التي تردّ عليها هذه الرسالة، مفصولة بمسافات"
},
reference_ids: {
label: "References",
help: "ترويسة References: معرّفات رسائل سلسلة المحادثة، مفصولة بمسافات"
},
from_address: {
label: "المرسِل",
help: "أول عنوان في From. تُنسخ الرسالة التي لا تحتوي عليه أيضًا ولا تُسقط أبدًا."
},
from_name: {
label: "اسم المرسِل",
help: "الاسم المعروض لأول عنوان في From"
},
sender_address: {
label: "Sender",
help: "ترويسة Sender، عندما تحملها الرسالة"
},
reply_to: {
label: "Reply-To",
help: "عناوين Reply-To مفصولة بفواصل"
},
to_addresses: {
label: "إلى",
help: "عناوين To مفصولة بفواصل"
},
cc_addresses: {
label: "نسخة إلى",
help: "عناوين Cc مفصولة بفواصل"
},
sent_at: {
label: "وقت الإرسال",
help: "ترويسة Date: الوقت الذي يقول المرسِل إن الرسالة كُتبت فيه"
},
received_at: {
label: "وقت الاستلام",
help: "وقت استلام صندوق البريد للرسالة"
},
subject: {
label: "الموضوع"
},
body_text: {
label: "النص (نص عادي)"
},
body_html: {
label: "النص (HTML)",
help: "جزء HTML كما كتبه المرسِل، يُخزَّن حرفيًا ولا يُعرض أبدًا دون تعقيم"
},
match_addresses: {
label: "عناوين المطابقة",
help: "عناوين المشاركين التي طوبقت معها السجلات، باستثناء عنوان صندوق البريد نفسه؛ تعيد إعادة المطابقة تشغيل هذه العناوين نفسها تمامًا"
},
association_state: {
label: "الارتباط",
help: "ما إذا كان أي سجل قد طابق الرسالة. تنتظر الرسالة غير المرتبطة في المجموعة المقيّدة.",
options: {
associated: "مرتبطة",
unassociated: "غير مرتبطة"
}
},
dedupe_key: {
label: "مفتاح إزالة التكرار",
help: "تجزئة Message-ID بعد التطبيع (أو تجزئة كتلة الترويسات إن لم يوجد)؛ صف واحد لكل رسالة في كل صندوق بريد"
}
}
},
sys_mail_association: {
label: "ارتباط البريد",
pluralLabel: "ارتباطات البريد",
description: "يربط رسالة واردة منسوخة بالسجل الذي تنتمي إليه",
fields: {
id: {
label: "معرّف الارتباط"
},
mail_message_id: {
label: "الرسالة"
},
object_name: {
label: "الكائن",
help: "الاسم البرمجي للكائن الذي ينتمي إليه السجل المرتبط"
},
record_id: {
label: "معرّف السجل",
help: "معرّف السجل المرتبط، في الكائن المحدد في \"الكائن\""
},
matched_address: {
label: "العنوان المطابق",
help: "عنوان المشارك الذي طابق السجل"
},
matched_field: {
label: "الحقل المطابق",
help: "حقل البريد الإلكتروني في السجل الذي ساوت قيمته العنوان المطابق"
},
matched_by: {
label: "طريقة المطابقة",
help: "ما إذا كان الربط قد سُجّل عند وصول الرسالة أم أُضيف بإعادة مطابقة لاحقة",
options: {
ingest: "الاستيعاب",
rematch: "إعادة المطابقة"
}
}
}
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.

/**
* Auto-generated by 'os i18n extract' for locale 'ar'. Do not hand-edit.
*
* Each entry is the digest of the SOURCE REVISION that this locale's leaf at
* that path is still a byte copy of — provenance for the generated half of the
* bundles (commit 09b4f4e4e): a leaf whose digest no longer matches its source is stale and serves the source text instead.
*
* An entry exists only while the leaf IS such a copy. Re-translate the leaf in
* `<locale>.objects.generated.ts` and the next extract drops its entry by
* itself — the table makes no claim about text a translator wrote. A path with
* no entry is LEGACY-TRUSTED and never reported stale.
*
* ⚠️ Do not "fix" a staleness report by editing this file. Refreshing a digest
* records that the current text was copied from the current source, which is
* the false claim the mechanism exists to detect. Fix the TRANSLATION.
*/

export const arGeneratedSourceHashes: Readonly<Record<string, string>> = {
"objects.sys_mail_message.fields.in_reply_to.label": "71bb10a36255d815",
"objects.sys_mail_message.fields.message_id.label": "14cd089a4062f4b1",
"objects.sys_mail_message.fields.reference_ids.label": "5102fd1664d35c0b",
"objects.sys_mail_message.fields.reply_to.label": "90ad8f2ca791a95a",
"objects.sys_mail_message.fields.sender_address.label": "89db06253eee9632",
"objects.sys_mailbox.fields.imap_uid_validity.label": "5a2ec2b384b73bb0",
};
Loading
Loading