Skip to content
Open
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-plugin-sharing-locales.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@objectstack/plugin-sharing': patch
---

i18n(plugin-sharing): the sharing and queue objects ship in all eleven platform languages

Clause-②: no
Metadata-protocol: none

The sharing objects (`sys_record_share`, `sys_sharing_rule`, `sys_share_link`) and the queue objects (`sys_queue`, `sys_queue_member`) now carry `zh-Hant`, `ar`, `fr`, `pt-BR`, `ru`, `de` and `ko` beside the existing `en`, `zh-CN`, `ja-JP` and `es-ES`, so an administrator in one of those languages reads the sharing and queue screens in their own language instead of English. Each recipient option reads the same on every object within a locale. The queue record page (`sys_queue_detail`) carries its title in the seven languages too, the same word as the queue object's own label. Each new locale is registered under its platform-table tag with its source-hash companion, and the package's extract command lists the tags, so the existing `check:i18n` bundle check covers them. Package 8 of #30512.
16 changes: 15 additions & 1 deletion packages/plugins/plugin-sharing/scripts/i18n-extract.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* strings were seeded from @objectstack/platform-objects.)
*
* os i18n extract packages/plugins/plugin-sharing/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/plugins/plugin-sharing/src/translations
*
Expand Down Expand Up @@ -48,6 +48,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';
import { SysQueueDetailPage } from '../src/sys-queue.page.js';
import { sharingPageTranslations } from '../src/translations/pages.js';

Expand All @@ -73,6 +80,13 @@ const config: ObjectStackDefinition = defineStack({
{ 'zh-CN': { objects: zhCNObjects, pages: sharingPageTranslations['zh-CN'] } },
{ 'ja-JP': { objects: jaJPObjects, pages: sharingPageTranslations['ja-JP'] } },
{ 'es-ES': { objects: esESObjects, pages: sharingPageTranslations['es-ES'] } },
{ 'zh-Hant': { objects: zhHantObjects, pages: sharingPageTranslations['zh-Hant'] } },
{ 'ar': { objects: arObjects, pages: sharingPageTranslations['ar'] } },
{ 'fr': { objects: frObjects, pages: sharingPageTranslations['fr'] } },
{ 'pt-BR': { objects: ptBRObjects, pages: sharingPageTranslations['pt-BR'] } },
{ 'ru': { objects: ruObjects, pages: sharingPageTranslations['ru'] } },
{ 'de': { objects: deObjects, pages: sharingPageTranslations['de'] } },
{ 'ko': { objects: koObjects, pages: sharingPageTranslations['ko'] } },
],
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,347 @@
// 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_record_share: {
label: "مشاركة السجل",
pluralLabel: "مشاركات السجلات",
description: "سجلات مُشارَكة مع غير مالكها، صف واحد لكل منح.",
fields: {
id: {
label: "معرّف المشاركة"
},
object_name: {
label: "الكائن",
help: "الاسم المختصر لكائن السجل المُشارَك"
},
record_id: {
label: "السجل",
help: "المفتاح الأساسي للسجل المُشارَك ضمن object_name"
},
recipient_type: {
label: "نوع المستلِم",
help: "نوع الجهة التي تحمل المنح",
options: {
user: "المستخدم",
group: "المجموعة",
position: "المنصب",
unit_and_subordinates: "وحدة الأعمال والوحدات التابعة لها"
}
},
recipient_id: {
label: "المستلِم",
help: "معرّف المستخدم أو المجموعة أو المنصب الذي يحصل على الوصول"
},
access_level: {
label: "مستوى الوصول",
help: "ما يمكن للمستلِم فعله — القراءة، أو القراءة والتحرير",
options: {
read: "قراءة",
edit: "قراءة وتحرير"
}
},
source: {
label: "المصدر",
help: "سبب وجود هذا المنح — يستخدمه مقيِّم القواعد للمطابقة",
options: {
manual: "يدوي",
rule: "قاعدة",
team: "الفريق",
inherited: "موروث"
}
},
source_id: {
label: "معرّف المصدر",
help: "اسم القاعدة أو معرّف الفريق عندما يكون source != manual"
},
granted_by: {
label: "مَن منحه",
help: "المستخدم الذي أنشأ المنح (يدويًا فقط)"
},
reason: {
label: "السبب",
help: "شرح نصي حر اختياري يُعرض للمستلِم"
},
created_at: {
label: "تاريخ الإنشاء"
},
updated_at: {
label: "تاريخ التحديث"
}
},
_views: {
all_shares: {
label: "الكل"
},
granted_to_me: {
label: "الممنوحة لي"
},
granted_by_me: {
label: "التي منحتُها"
},
by_object: {
label: "حسب الكائن"
},
manual_grants: {
label: "منح يدوية"
},
rule_grants: {
label: "منح بالقواعد"
}
}
},
sys_sharing_rule: {
label: "قاعدة المشاركة",
pluralLabel: "قواعد المشاركة",
description: "يمنح مجموعة من الأشخاص الوصول إلى السجلات المطابقة لشرط.",
fields: {
id: {
label: "معرّف القاعدة"
},
organization_id: {
label: "المؤسسة",
help: "المؤسسة التي تنتمي إليها هذه القاعدة."
},
name: {
label: "الاسم",
help: "يعرّف القاعدة. أحرف لاتينية صغيرة وأرقام وشرطات سفلية فقط."
},
label: {
label: "التسمية المعروضة"
},
description: {
label: "الوصف"
},
object_name: {
label: "الكائن",
help: "الكائن الذي تشارك هذه القاعدة سجلاته."
},
criteria_json: {
label: "المعايير",
help: "أي السجلات تُشارَك. مطلوب — يجب أن تضيّق القاعدة السجلات التي تشاركها، لذا لا يوجد إعداد «مشاركة كل السجلات»."
},
recipient_type: {
label: "نوع المستلِم",
help: "مَن يحصل على الوصول. اختيار فريق أو وحدة أعمال أو منصب أو قائمة انتظار يمنح الوصول لكل من فيها. ويشمل «وحدة الأعمال والوحدات التابعة لها» أيضًا كل وحدة أدنى من الوحدة المختارة. أما «الحقل» فيشارك كل سجل مع المستخدم أو المستخدمين المحفوظين في أحد حقوله — اذكر ذلك الحقل بوصفه المستلِم.",
options: {
user: "المستخدم",
team: "الفريق",
business_unit: "وحدة الأعمال",
position: "المنصب",
unit_and_subordinates: "وحدة الأعمال والوحدات التابعة لها",
queue: "قائمة الانتظار",
field: "الحقل"
}
},
recipient_id: {
label: "المستلِم",
help: "المستخدم أو الفريق أو وحدة الأعمال أو المنصب أو قائمة الانتظار المحدَّد الذي يحصل على الوصول — أو، لنوع المستلِم «الحقل»، اسم حقل السجل الذي يحفظ المستخدم أو المستخدمين المُشارَك معهم."
},
access_level: {
label: "مستوى الوصول",
help: "ما يمكن للمستلمين فعله بالسجلات المطابقة — قراءتها، أو قراءتها وتحريرها.",
options: {
read: "قراءة",
edit: "قراءة وتحرير"
}
},
active: {
label: "نشِط",
help: "أوقفه لسحب الوصول الذي منحته هذه القاعدة دون حذفها."
},
managed_by: {
label: "مصدر الإدارة",
help: "مصدر هذه القاعدة: مدمجة في المنصة، أو مثبّتة مع تطبيق، أو أُنشئت هنا في الإعداد.",
options: {
platform: "المنصة",
package: "الحزمة",
admin: "المسؤول"
}
},
customized: {
label: "مخصَّصة",
help: "يُضبط عند تحريرك قاعدة جاءت مع تطبيق، فتُحفظ تغييراتك عند تحديث التطبيق."
},
created_at: {
label: "تاريخ الإنشاء"
},
updated_at: {
label: "تاريخ التحديث"
}
},
_views: {
active: {
label: "نشِط"
},
inactive: {
label: "غير نشِط"
},
by_object: {
label: "حسب الكائن"
},
all_rules: {
label: "الكل"
}
}
},
sys_share_link: {
label: "رابط المشاركة",
pluralLabel: "روابط المشاركة",
description: "رمز قدرة مُبهم يمنح الوصول إلى سجل واحد. مشاركة عبر رابط عام على طريقة Notion/Figma.",
fields: {
id: {
label: "معرّف الرابط"
},
token: {
label: "الرمز",
help: "رمز عشوائي مُبهم آمن للاستخدام في URL (≥ 22 حرفًا). السر الوحيد في هذا الصف."
},
object_name: {
label: "الكائن",
help: "الاسم المختصر لكائن السجل المُشارَك (مثل ai_conversation و contracts_contract)"
},
record_id: {
label: "السجل",
help: "المفتاح الأساسي للسجل المُشارَك ضمن object_name"
},
permission: {
label: "الإذن",
help: "ما يمكن لحامل الرابط فعله بالسجل",
options: {
view: "عرض",
comment: "تعليق",
edit: "تحرير"
}
},
audience: {
label: "الجمهور",
help: "طبقة تقييد تُطبَّق فوق التحقق من الرمز",
options: {
public: "عام (قابل للفهرسة)",
link_only: "أي شخص لديه الرابط",
signed_in: "المستخدمون المسجّلون الدخول",
email: "عناوين بريد محددة"
}
},
expires_at: {
label: "تاريخ الانتهاء",
help: "عند ضبطه، يعيد resolveToken القيمة null بعد هذا الطابع الزمني"
},
email_allowlist: {
label: "قائمة البريد المسموح",
help: "عناوين بأحرف صغيرة يُتحقق منها عندما audience=email"
},
password_hash: {
label: "تجزئة كلمة المرور",
help: "تجزئة Argon2/bcrypt. عند ضبطها، تطلب الواجهة كلمة مرور قبل العرض."
},
redact_fields: {
label: "الحقول المحجوبة لكل رابط",
help: "حقول إضافية تُزال من الاستجابة، فوق المجموعة الافتراضية للكائن"
},
label: {
label: "التسمية",
help: "نص حر يظهر في نافذة المشاركة (مثل «عقد ACME Q3»)"
},
revoked_at: {
label: "تاريخ الإلغاء",
help: "عند ضبطه، يُعطَّل الرابط نهائيًا"
},
created_by: {
label: "المُنشئ",
help: "مُصدِر الرابط"
},
created_at: {
label: "تاريخ الإنشاء"
},
last_used_at: {
label: "آخر استخدام",
help: "يختمه resolveToken؛ وتستخدمه لوحة المعلومات لإبراز الروابط النشطة"
},
use_count: {
label: "عدد مرات الاستخدام",
help: "يزيده resolveToken عند كل تحليل ناجح"
}
},
_views: {
active_links: {
label: "نشطة"
},
by_me: {
label: "أنشأتُها"
},
revoked: {
label: "ملغاة"
},
all_links: {
label: "الكل"
}
}
},
sys_queue: {
label: "قائمة الانتظار",
pluralLabel: "قوائم الانتظار",
description: "مجموعة مسمّاة من الأشخاص تنتظر فيها السجلات غير المسندة حتى يتولاها أحدهم.",
fields: {
name: {
label: "الاسم",
help: "يعرّف قائمة الانتظار أينما استُخدمت — في السجلات وقواعد الإسناد والموافقات وقواعد المشاركة. أحرف لاتينية صغيرة وأرقام وشرطات سفلية فقط."
},
label: {
label: "الاسم المعروض"
},
description: {
label: "الوصف"
}
},
_views: {
all_queues: {
label: "الكل"
}
}
},
sys_queue_member: {
label: "عضو قائمة الانتظار",
pluralLabel: "أعضاء قائمة الانتظار",
description: "مَن ينتمي إلى قائمة الانتظار: مستخدم أو فريق أو منصب أو وحدة أعمال.",
fields: {
queue: {
label: "قائمة الانتظار",
help: "اسم قائمة الانتظار التي ينتمي إليها هذا العضو."
},
recipient_type: {
label: "نوع العضو",
help: "نوع هذا العضو. الفريق أو المنصب أو وحدة الأعمال يجعل كل من فيه عضوًا. ويشمل «وحدة الأعمال والوحدات التابعة لها» أيضًا كل وحدة أدنى من الوحدة المختارة.",
options: {
user: "المستخدم",
team: "الفريق",
position: "المنصب",
business_unit: "وحدة الأعمال",
unit_and_subordinates: "وحدة الأعمال والوحدات التابعة لها"
}
},
recipient_id: {
label: "العضو",
help: "المستخدم أو الفريق أو المنصب أو وحدة الأعمال المحدَّد."
}
},
_views: {
by_queue: {
label: "حسب قائمة الانتظار"
}
}
}
};
Loading
Loading