memi-board 0.57.0 → 0.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +17 -1
  2. package/dist/{ar-CQhBdHu3.js → ar-DsYwkqiP.js} +49 -5
  3. package/dist/ar-DsYwkqiP.js.map +1 -0
  4. package/dist/{commentImages-mIfyNHgz.js → commentImages-BZOxzRy6.js} +84 -14
  5. package/dist/commentImages-BZOxzRy6.js.map +1 -0
  6. package/dist/composables/useMemiBoardBannerGeneration.d.ts +8 -0
  7. package/dist/composables/useMemiBoardReports.d.ts +102 -3
  8. package/dist/composables/useMemiBoardStorage.d.ts +2 -1
  9. package/dist/config.d.ts +4 -0
  10. package/dist/{de-B4GZqxQj.js → de-Ckqy6xMr.js} +49 -5
  11. package/dist/de-Ckqy6xMr.js.map +1 -0
  12. package/dist/{en-Dc7zQOy-.js → en-Dshxokpu.js} +72 -5
  13. package/dist/en-Dshxokpu.js.map +1 -0
  14. package/dist/{es-DzFDaLwo.js → es-BkaAuj2h.js} +49 -5
  15. package/dist/es-BkaAuj2h.js.map +1 -0
  16. package/dist/{fr-Zf5mcs8m.js → fr-BrhcNuxW.js} +49 -5
  17. package/dist/fr-BrhcNuxW.js.map +1 -0
  18. package/dist/{id-CaWN8212.js → id-B_7SWGzM.js} +49 -5
  19. package/dist/id-B_7SWGzM.js.map +1 -0
  20. package/dist/index.d.ts +3 -2
  21. package/dist/index.js +839 -697
  22. package/dist/index.js.map +1 -1
  23. package/dist/{ja-xDttH9CE.js → ja-DyexZuXX.js} +49 -5
  24. package/dist/ja-DyexZuXX.js.map +1 -0
  25. package/dist/{pt-WIfxYYWQ.js → pt-Az3vABvC.js} +49 -5
  26. package/dist/pt-Az3vABvC.js.map +1 -0
  27. package/dist/runtime/components/AuthorMenu.vue +17 -13
  28. package/dist/runtime/components/BannerEditor.vue +198 -0
  29. package/dist/runtime/components/BoardInfo.vue +29 -49
  30. package/dist/runtime/components/CategorySettings.vue +25 -2
  31. package/dist/runtime/components/CommentFeed.vue +6 -7
  32. package/dist/runtime/components/CommentImageField.vue +12 -10
  33. package/dist/runtime/components/CommentItem.vue +92 -71
  34. package/dist/runtime/components/CustomFieldEditor.vue +10 -8
  35. package/dist/runtime/components/Detail.vue +31 -38
  36. package/dist/runtime/components/ImageLightbox.vue +126 -58
  37. package/dist/runtime/components/LikeButton.vue +22 -20
  38. package/dist/runtime/components/List.vue +23 -11
  39. package/dist/runtime/components/ListCard.vue +5 -3
  40. package/dist/runtime/components/ListDefault.vue +14 -12
  41. package/dist/runtime/components/ListDense.vue +9 -9
  42. package/dist/runtime/components/ListImage.vue +6 -4
  43. package/dist/runtime/components/ListVideo.vue +10 -13
  44. package/dist/runtime/components/ListViewSwitch.vue +10 -10
  45. package/dist/runtime/components/MiniComments.vue +6 -7
  46. package/dist/runtime/components/ReportButton.vue +22 -13
  47. package/dist/runtime/components/ReportList.vue +77 -93
  48. package/dist/runtime/components/Settings.vue +26 -2
  49. package/dist/storage.js +18 -1
  50. package/dist/storage.js.map +1 -1
  51. package/dist/types.d.ts +11 -0
  52. package/dist/utils/bannerGeneration.d.ts +9 -0
  53. package/dist/{zh-CI6Sd8PD.js → zh-B55IygiW.js} +49 -5
  54. package/dist/zh-B55IygiW.js.map +1 -0
  55. package/docs/firebase-setup.md +127 -0
  56. package/docs/firestore.rules.example +17 -2
  57. package/docs/host-integration.md +30 -19
  58. package/docs/storage.rules.example +19 -0
  59. package/package.json +1 -1
  60. package/dist/ar-CQhBdHu3.js.map +0 -1
  61. package/dist/commentImages-mIfyNHgz.js.map +0 -1
  62. package/dist/de-B4GZqxQj.js.map +0 -1
  63. package/dist/en-Dc7zQOy-.js.map +0 -1
  64. package/dist/es-DzFDaLwo.js.map +0 -1
  65. package/dist/fr-Zf5mcs8m.js.map +0 -1
  66. package/dist/id-CaWN8212.js.map +0 -1
  67. package/dist/ja-xDttH9CE.js.map +0 -1
  68. package/dist/pt-WIfxYYWQ.js.map +0 -1
  69. package/dist/zh-CI6Sd8PD.js.map +0 -1
package/README.md CHANGED
@@ -21,10 +21,11 @@ Any host app on the same stack (Nuxt 4 · `@nuxt/ui` · `nuxt-vuefire` · Fireba
21
21
  | Confirmed account deletion and large datasets | [Account deletion](docs/account-deletion.md) — content checkbox, reauthentication, bounded processing, retry, and host server/Rules requirements |
22
22
  | Single language, or choosing multilingual UI and translation | [Internationalization and content translation](docs/internationalization.md) — per-mode setup and when translations are saved |
23
23
  | Connecting Firebase and deploying rules and indexes | [Firebase setup](docs/firebase-setup.md) |
24
+ | Initializing readable post URLs on a new project | [Post URL reservation setup](docs/firebase-setup.md#initialize-post-url-reservations) — one-time initialization before the first post |
24
25
  | Per-store/organization assigned permissions, migrating existing roles | [Roles and migration](docs/roles-migration.md) |
25
26
  | Configuration, API, and troubleshooting details | This README's [host setup](#host-app-setup), [API](#provided-api), [troubleshooting](#troubleshooting) |
26
27
 
27
- `i18n.enabled` and `translation.enabled` are supported in **0.47.0 and later**. Hosts that use these options should install or update with `pnpm add memi-board@^0.47.0`.
28
+ `i18n.enabled` and `translation.enabled` are supported in **0.47.0 and later**. For the current setup described in these guides, install or update with `pnpm add memi-board@^0.57.0`.
28
29
 
29
30
  ## Platform requirements
30
31
 
@@ -323,12 +324,17 @@ Because it is the browser's native `:visited`, no server or DB storage is needed
323
324
  firebase deploy --only firestore:rules,storage,firestore:indexes
324
325
  ```
325
326
  6. Grant Storage permission to read Firestore: approve the prompt to add the cross-service IAM role during deploy, and check that the Storage service account of the host Firebase project has `roles/firebaserules.firestoreServiceAgent`. See the [host setup procedure](docs/firebase-setup.md#firestore-read-access-for-storage-rules-required-host-app-setup). A successful CI deploy alone does not guarantee this permission.
327
+ 7. **Before the first post on a new project (0.57.0+), initialize post URL reservations.** With the posts collection still empty, create `memiBoardPostsSlugs/__migration` with the Boolean field `ready: true` in the Firebase console. This is a one-time setup marker, not a change to post documents. See the [console steps and optional Admin SDK command](docs/firebase-setup.md#initialize-post-url-reservations). A package install, website deploy, or rules deploy does not create this document.
328
+
329
+ New text posts use a title URL within their board; only a conflicting address receives `-2`, `-3`, etc. Unpublished drafts count too. Address reservation, post metadata, and body are saved atomically. Editing or publishing preserves the address, and deleting a post keeps its reservation so an old link cannot point to a different post. Image boards keep ID URLs. See [URL behavior and reservation permissions](docs/host-integration.md#title-only-urls-for-new-posts).
326
330
 
327
331
  Hosts updating to 0.45.1 should also check the [procedure for applying the new rules and migrating](docs/firebase-setup.md#0451-rule-changes-and-migrating-existing-hosts). Installing the package or pushing the site does not deploy Firebase rules.
328
332
 
329
333
  **If Rules are only in the file and not deployed**, writing posts fails with `permission-denied` — the most common installation mistake.
330
334
  **If Storage rules are deployed to a bucket other than the one the app uses**, body images fail with `storage/unauthorized`.
331
335
 
336
+ Board banner uploads also require the banner-specific Storage rule block. See [banner permissions, bucket configuration and deployment verification](docs/firebase-setup.md#board-banner-storage-rules).
337
+
332
338
  #### Composite indexes
333
339
 
334
340
  Merge [docs/firestore.indexes.json.example](docs/firestore.indexes.json.example) into the host `firestore.indexes.json`. If you customized collection names (`memiBoard.postsCollection`, etc.), change the indexes' `collectionGroup` values to match.
@@ -797,3 +803,13 @@ In the npm package settings, register the Trusted Publisher as GitHub repository
797
803
  ### 0.46 roles and per-service names
798
804
 
799
805
  For the 5 roles, per-board manager scope, `roleLabels`, and the host migration procedure, see [role migration](docs/roles-migration.md). Use `canConfigureBoard()` for settings access.
806
+
807
+ ### Report review workflow
808
+
809
+ `MemiBoardReportList` separates pending reports from processed history, ordered by report receipt time. Staff must enter a public review reason (up to 200 characters) for dismissal or review completion. Review completion records the decision only; use the separate post management controls when content needs moderation.
810
+
811
+ Reporters can reopen the report button to read the current status, review time and public reason. Existing reports without a reason show a legacy-entry message. Other reports require a nonblank description. These interfaces support all ten package languages.
812
+
813
+ Deploy the report section in `docs/firestore.rules.example` before enabling these controls. Review records add optional `reviewedByName` and `reviewNote` fields; older client decisions without these fields remain compatible. Custom callers must pass a nonblank reason to `dismissReport(report, note)` / `actionReport(report, note)`.
814
+
815
+ Comment blind/restore is a separate manager action, not a user report. Its in-page confirmation preserves the requested action while saving and displays errors in the dialog. Updated comment rules prevent authors from changing `isBlinded`, `moderatedAt`, or `moderatedBy`; managers must use their own UID and a server timestamp. Blinding changes presentation and retains the original document; it is not deletion or a data-access boundary.
@@ -14,6 +14,7 @@ var e = {
14
14
  },
15
15
  authorMemo: { tooLong: "يمكن أن تصل الملاحظة إلى {max} حرف كحد أقصى." },
16
16
  authorMenu: {
17
+ menu: "قائمة الكاتب",
17
18
  viewProfile: "عرض الملف الشخصي",
18
19
  viewPosts: "عرض المنشورات",
19
20
  viewComments: "عرض التعليقات",
@@ -101,6 +102,10 @@ var e = {
101
102
  },
102
103
  common: {
103
104
  action: {
105
+ zoomIn: "تكبير",
106
+ zoomOut: "تصغير",
107
+ fitImage: "ملاءمة الشاشة",
108
+ originalImage: "الحجم الأصلي (100٪)",
104
109
  cancel: "إلغاء",
105
110
  save: "حفظ",
106
111
  saved: "تم الحفظ",
@@ -124,11 +129,13 @@ var e = {
124
129
  toTop: "للأعلى"
125
130
  },
126
131
  label: {
132
+ imageControls: "أدوات تكبير الصورة",
127
133
  anonymous: "مجهول",
128
134
  user: "مستخدم",
129
135
  image: "صورة",
130
136
  draft: "مسودة",
131
- loading: "جارٍ التحميل…"
137
+ loading: "جارٍ التحميل…",
138
+ viewCount: "{count} مشاهدة"
132
139
  },
133
140
  role: {
134
141
  admin: "مشرف",
@@ -147,6 +154,7 @@ var e = {
147
154
  deleteConfirm: "هل تريد حذف هذا المنشور؟ لا يمكن التراجع عن ذلك.",
148
155
  notFound: "لم يتم العثور على المنشور.",
149
156
  draftPreview: "معاينة غير منشورة",
157
+ tag: "وسم",
150
158
  draftNotice: "لم يُنشر هذا المنشور بعد. لا يمكن لأحد غيرك رؤيته حتى تنشره.",
151
159
  publish: "نشر",
152
160
  notice: "إعلان",
@@ -458,7 +466,22 @@ var e = {
458
466
  done: "تم استلام البلاغ. سيراجعه فريق العمل.",
459
467
  reason: "السبب",
460
468
  detailPlaceholder: "التفاصيل (اختياري)",
461
- submit: "إبلاغ"
469
+ submit: "إبلاغ",
470
+ status: {
471
+ open: "تم الاستلام",
472
+ dismissed: "مرفوض",
473
+ actioned: "اكتملت المراجعة"
474
+ },
475
+ resultTitle: "حالة البلاغ",
476
+ result: {
477
+ open: "تم استلام بلاغك وهو بانتظار المراجعة.",
478
+ dismissed: "لم تجد المراجعة مخالفة.",
479
+ actioned: "اكتملت المراجعة. راجع السبب أدناه."
480
+ },
481
+ reviewedAt: "وقت المراجعة",
482
+ reviewNote: "سبب القرار",
483
+ noNote: "لا يوجد سبب مسجل لهذا السجل القديم.",
484
+ detailRequired: "التفاصيل (مطلوبة عند اختيار أخرى)"
462
485
  },
463
486
  reportList: {
464
487
  staffOnly: "يمكن لفريق العمل فقط عرض البلاغات.",
@@ -467,7 +490,22 @@ var e = {
467
490
  untitled: "منشور بلا عنوان",
468
491
  author: "بواسطة {name}",
469
492
  dismiss: "رفض",
470
- confirm: "معالجة"
493
+ tabs: {
494
+ open: "قيد الانتظار",
495
+ processed: "سجل المراجعات"
496
+ },
497
+ filterLabel: "تصفية البلاغات",
498
+ orderHint: "الأحدث استلامًا أولًا.",
499
+ historyEmpty: "لا يوجد سجل مراجعات.",
500
+ confirm: "وضع علامة تمت المراجعة",
501
+ dismissTitle: "رفض البلاغ",
502
+ resolveTitle: "إكمال المراجعة",
503
+ actionHint: "يغير حالة البلاغ فقط، ولا يخفي المنشور أو يحذفه.",
504
+ publicNote: "هذا السبب ظاهر أيضًا لمقدّم البلاغ.",
505
+ reviewer: "المراجع",
506
+ reviewNote: "سبب القرار",
507
+ unknownReviewer: "مراجع غير معروف",
508
+ actionFailed: "تعذرت المعالجة. حاول مجددًا."
471
509
  },
472
510
  reports: {
473
511
  reason: {
@@ -481,7 +519,13 @@ var e = {
481
519
  signInRequired: "يُرجى تسجيل الدخول.",
482
520
  cannotReportOwn: "لا يمكنك الإبلاغ عن منشورك.",
483
521
  reasonRequired: "يُرجى اختيار سبب.",
484
- detailTooLong: "يمكن أن تصل التفاصيل إلى {max} حرف كحد أقصى."
522
+ detailTooLong: "يمكن أن تصل التفاصيل إلى {max} حرف كحد أقصى.",
523
+ otherDetailRequired: "أدخل التفاصيل عند اختيار أخرى.",
524
+ reviewNoteRequired: "أدخل سبب القرار.",
525
+ alreadyReviewed: "تمت مراجعة هذا البلاغ مسبقًا. راجع القائمة.",
526
+ manageRequired: "ليست لديك صلاحية مراجعة هذا البلاغ.",
527
+ alreadyReported: "لقد أبلغت عن هذا المنشور مسبقًا.",
528
+ statusLoadFailed: "تعذر تحميل الحالة. حدّث الصفحة."
485
529
  },
486
530
  sectionUtil: {
487
531
  kind: {
@@ -759,4 +803,4 @@ var e = {
759
803
  //#endregion
760
804
  export { e as default };
761
805
 
762
- //# sourceMappingURL=ar-CQhBdHu3.js.map
806
+ //# sourceMappingURL=ar-DsYwkqiP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ar-DsYwkqiP.js","names":[],"sources":["../src/i18n/messages/ar.ts"],"sourcesContent":["import type { MemiBoardMessages } from '../translate'\n\n/** 짧은 화면 문구만 번역한다. 빠진 키는 en → ko 순으로 폴백된다. */\nconst messages: MemiBoardMessages = {\n attachments: {\n attach: 'إرفاق ملفات ({count} / {max})',\n dropOrClick: 'أفلت الملفات هنا أو انقر للإضافة',\n uploading: 'جارٍ رفع الملفات…',\n maxFiles: 'يمكنك إرفاق {max} ملفات كحد أقصى.',\n },\n auth: {\n writeRestricted: 'تم تقييد النشر والتعليق مؤقتًا بسبب تكرار تحذيرات المحتوى.',\n strikeSuffix: ' (تحذير {count}/{threshold})',\n strikeRestricted: ' عند بلوغ {count} تحذيرات سيتم تقييد النشر والتعليق.',\n notInitialized: '[memi-board] لم تتم تهيئة Firebase Auth.',\n },\n authorMemo: {\n tooLong: 'يمكن أن تصل الملاحظة إلى {max} حرف كحد أقصى.',\n },\n authorMenu: {\n menu: 'قائمة الكاتب',\n viewProfile: 'عرض الملف الشخصي',\n viewPosts: 'عرض المنشورات',\n viewComments: 'عرض التعليقات',\n memoAriaLabel: 'ملاحظة عن هذا الكاتب',\n memoTitle: 'ملاحظة خاصة',\n memoPlaceholder: 'دوِّن شيئًا عن هذا الكاتب…',\n bad: 'سيئ',\n good: 'جيد',\n },\n avatarCropModal: {\n title: 'قص صورة الملف الشخصي',\n description: 'تُعرض بشكل مربع (1:1). اضبط المنطقة لتناسبها.',\n confirm: 'قص ورفع',\n },\n boardSettings: {\n signInRequired: 'يُرجى تسجيل الدخول.',\n idAndNameRequired: 'يُرجى إدخال معرّف اللوحة واسمها.',\n deleteIdRequired: 'يلزم معرّف اللوحة لحذفها.',\n nameRequired: 'يُرجى إدخال اسم اللوحة.',\n },\n boardUsers: {\n unsupportedRole: 'دور غير مدعوم.',\n roleDescription: {\n admin: 'يدير أدوار المستخدمين وإعدادات اللوحة وكل المحتوى.',\n user: 'يمكنه كتابة المنشورات والتعليقات، وتعديل أو حذف محتواه فقط.',\n },\n },\n commentFeed: {\n empty: 'لا توجد تعليقات بعد.',\n emptyLiked: 'لا توجد تعليقات حصلت على إعجاب بعد.',\n loadFailed: 'تعذّر تحميل القائمة: {error}',\n blinded: 'أخفى المشرف هذا التعليق.',\n },\n commentForm: {\n translationSkipped: 'تم نشر التعليق دون ترجمة. يمكنك ترجمته لاحقًا من نموذج التعديل.',\n hiddenBoardDenied: 'في اللوحات المخفية، يمكن لفريق العمل المعيَّن فقط التعليق.',\n denied: 'ليس لديك إذن بالتعليق في هذه اللوحة.',\n signInRequired: 'يُرجى تسجيل الدخول.',\n writeRestricted: 'تم تقييد النشر مؤقتًا بسبب تكرار تحذيرات المحتوى.',\n moderationBlocked: 'يحتوي هذا على محتوى لا يمكن نشره.',\n replyTo: 'الرد على {name}',\n placeholder: 'اكتب تعليقًا',\n submitReply: 'رد',\n submit: 'تعليق',\n signInToComment: 'سجّل الدخول لكتابة تعليق.',\n attachHint: 'أسقط صورة هنا أو انقر لاختيار واحدة.',\n attachNote: 'jpg وpng وgif وwebp. يتم تصغير الصور الكبيرة إلى 5MB أو أقل.',\n removeImage: 'إزالة الصورة المرفقة',\n imageOnly: 'يمكن إرفاق صور jpg وpng وgif وwebp فقط.',\n uploadFailed: 'تعذر رفع الصورة.',\n uploading: 'جارٍ رفع الصورة…',\n },\n commentItem: {\n editRestricted: 'تم تقييد تعديل التعليقات مؤقتًا.',\n moderationBlocked: 'يحتوي هذا على محتوى لا يمكن نشره.',\n editFailed: 'تعذّر تعديل التعليق.',\n blindFailed: 'تعذّر تغيير حالة الإخفاء.',\n likeFailed: 'تعذّرت معالجة الإعجاب.',\n blinded: 'أخفى المشرف هذا التعليق.',\n attachedImage: 'صورة مرفقة بالتعليق',\n edit: 'تعديل التعليق',\n blind: 'إخفاء التعليق',\n unblind: 'إظهار التعليق',\n delete: 'حذف التعليق',\n },\n commentList: {\n loading: 'جارٍ تحميل التعليقات',\n empty: 'لا توجد تعليقات بعد.',\n loadMore: 'المزيد من التعليقات',\n loadingMore: 'جارٍ تحميل المزيد من التعليقات',\n },\n commentThread: {\n deleteConfirm: 'هل تريد حذف هذا التعليق؟',\n deleteFailed: 'تعذّر حذف التعليق.',\n hideReplies: 'إخفاء الردود',\n showReplies: 'الردود ({count})',\n loadMoreReplies: 'المزيد من الردود',\n },\n comments: {\n bodyRequired: 'يُرجى إدخال تعليق.',\n bodyTooLong: 'يمكن أن يصل التعليق إلى {max} حرف كحد أقصى.',\n replyTargetNotFound: 'تعذّر العثور على التعليق الذي تردّ عليه.',\n threadNotFound: 'تعذّر العثور على سلسلة التعليقات.',\n hasRepliesCannotDelete: 'لا يمكن حذف التعليقات التي لها ردود حاليًا.',\n },\n common: {\n action: {\n zoomIn: \"تكبير\",\n zoomOut: \"تصغير\",\n fitImage: \"ملاءمة الشاشة\",\n originalImage: \"الحجم الأصلي (100٪)\",\n cancel: 'إلغاء',\n save: 'حفظ',\n saved: 'تم الحفظ',\n edit: 'تعديل',\n delete: 'حذف',\n confirm: 'موافق',\n close: 'إغلاق',\n add: 'إضافة',\n more: 'المزيد',\n prev: 'السابق',\n next: 'التالي',\n retry: 'إعادة المحاولة',\n reply: 'رد',\n like: 'إعجاب',\n unlike: 'إلغاء الإعجاب',\n share: 'مشاركة',\n report: 'إبلاغ',\n signIn: 'تسجيل الدخول',\n signOut: 'تسجيل الخروج',\n write: 'كتابة',\n toTop: 'للأعلى',\n },\n label: {\n imageControls: \"أدوات تكبير الصورة\",\n anonymous: 'مجهول',\n user: 'مستخدم',\n image: 'صورة',\n draft: 'مسودة',\n loading: 'جارٍ التحميل…',\n viewCount: '{count} مشاهدة',\n },\n role: {\n admin: 'مشرف',\n staff: 'فريق العمل',\n user: 'مستخدم',\n },\n date: {\n justNow: 'الآن',\n fewSecondsAgo: 'قبل بضع ثوانٍ',\n checking: 'جارٍ التحقق من الوقت',\n createdAt: 'تاريخ الإنشاء: {time}',\n updatedAt: 'تاريخ التعديل: {time}',\n },\n },\n detail: {\n deleteConfirm: 'هل تريد حذف هذا المنشور؟ لا يمكن التراجع عن ذلك.',\n notFound: 'لم يتم العثور على المنشور.',\n draftPreview: 'معاينة غير منشورة',\n tag: 'وسم',\n draftNotice: 'لم يُنشر هذا المنشور بعد. لا يمكن لأحد غيرك رؤيته حتى تنشره.',\n publish: 'نشر',\n notice: 'إعلان',\n pin: 'تثبيت كإعلان',\n unpin: 'إلغاء الإعلان',\n backToList: 'العودة إلى القائمة',\n postNav: 'التنقل بين المنشورات',\n list: 'القائمة',\n comments: 'التعليقات',\n },\n editor: {\n titleOptionalPlaceholder: 'العنوان (اتركه فارغًا ليكتب الذكاء الاصطناعي عنوانًا)',\n titleAiNotice: 'كتب الذكاء الاصطناعي عنوانًا من نصك. احفظه إن أعجبك أو عدّله أولًا.',\n translateView: {\n title: 'معاينة الترجمة: {language}',\n notSaved: 'لم يتم الحفظ. هذه معاينة فقط.',\n },\n titlePlaceholder: 'العنوان',\n contentPlaceholder: 'اكتب شيئًا… اكتب / لفتح قائمة الكتل.',\n imageContentPlaceholder: 'اكتب شيئًا…',\n tagsPlaceholder: 'اكتب وسمًا واضغط Enter',\n pinNotice: 'تثبيت كإعلان',\n submitEdit: 'حفظ التغييرات',\n submitNext: 'التالي: معاينة',\n apply: 'تطبيق',\n imageOptimizing: 'جارٍ تحسين الصورة ورفعها…',\n cover: {\n imageLink: 'رابط الصورة',\n addPhoto: 'إضافة صور',\n alt: 'صورة {n}',\n representative: 'الغلاف',\n setRepresentative: 'تعيين كغلاف',\n setRepresentativeAria: 'تعيين الصورة {n} كغلاف',\n remove: 'إزالة الصورة',\n add: 'إضافة',\n uploading: 'جارٍ الرفع…',\n dropOrClick: 'أفلت الصور هنا أو انقر للإضافة',\n emptyHint: 'يمكن اختيار عدة صور · اختر الغلاف بعد الرفع · اسحب لإعادة الترتيب',\n uploadTitle: 'رفع',\n },\n uploadFailed: 'فشل الرفع',\n aiAssistant: 'مساعد الكتابة بالذكاء الاصطناعي',\n insertBlock: 'إدراج كتلة',\n blockMenu: 'قائمة الكتل',\n imageDialog: {\n title: 'إضافة صورة',\n chooseFile: 'اختيار صورة من جهازك',\n orLink: 'أو رابط صورة',\n urlLabel: 'URL الصورة',\n previewAlt: 'معاينة صورة خارجية',\n addLink: 'إضافة الرابط',\n },\n customDialog: {\n title: 'إعادة الصياغة بأسلوب مخصص',\n label: 'كيف تريد إعادة صياغته؟',\n help: 'مثال: بأسلوب ودّي / بأسلوب رسمي / كنقاط موجزة',\n placeholder: 'بأسلوب ودّي',\n },\n aiPreview: {\n title: 'مراجعة نتيجة AI',\n currentTitle: 'العنوان الحالي',\n newTitle: 'العنوان الجديد',\n currentContent: 'المحتوى الحالي',\n appendedContent: 'المحتوى المضاف',\n before: 'قبل',\n after: 'بعد',\n },\n menu: {\n ai: 'AI',\n aiContinue: 'المتابعة باستخدام AI',\n style: 'النمط',\n insert: 'إدراج',\n paragraph: 'فقرة',\n heading1: 'عنوان 1',\n heading2: 'عنوان 2',\n heading3: 'عنوان 3',\n bulletList: 'قائمة نقطية',\n orderedList: 'قائمة مرقّمة',\n blockquote: 'اقتباس',\n codeBlock: 'كتلة برمجية',\n horizontalRule: 'فاصل',\n image: 'صورة',\n turnInto: 'تحويل إلى',\n resetFormatting: 'إعادة تعيين التنسيق',\n duplicate: 'تكرار',\n moveUp: 'نقل للأعلى',\n moveDown: 'نقل للأسفل',\n delete: 'حذف',\n },\n toolbar: {\n link: 'رابط',\n image: 'صورة',\n format: 'التنسيق',\n bold: 'غامق',\n italic: 'مائل',\n underline: 'تسطير',\n strike: 'يتوسطه خط',\n title: 'العنوان',\n heading: 'عنوان',\n subheading: 'عنوان فرعي',\n body: 'النص',\n mono: 'أحادي المسافة',\n bulletList: 'قائمة نقطية',\n orderedList: 'قائمة مرقّمة',\n blockquote: 'اقتباس',\n codeBlock: 'كتلة برمجية',\n horizontalRule: 'فاصل',\n clearFormatting: 'مسح التنسيق',\n undo: 'تراجع',\n redo: 'إعادة',\n },\n ai: {\n translateView: 'عرض الترجمة',\n translateAll: 'ترجمة وحفظ بـ {count} لغات',\n proofread: 'تدقيق الإملاء',\n polish: 'تحسين الصياغة',\n continue: 'متابعة الكتابة',\n summarize: 'تلخيص موجز',\n translateEn: 'الترجمة إلى الإنجليزية',\n translateKo: 'الترجمة إلى الكورية',\n translateEmpty: 'أدخل عنوانًا أو نصًا للترجمة أولًا.',\n title: 'إنشاء عنوان من النص',\n custom: 'إعادة الصياغة بأسلوب مخصص…',\n failed: 'فشلت مهمة AI. يُرجى المحاولة مرة أخرى.',\n },\n youtubePrompt: 'أدخل رابط YouTube.',\n errors: {\n coverMax: 'يمكنك رفع {max} صور كحد أقصى.',\n imageUrlRequired: 'أدخل URL الصورة.',\n imageUrlInvalid: 'أدخل URL صالحًا للصورة.',\n imageUrlHttps: 'يُسمح فقط بعناوين URL للصور التي تبدأ بـ HTTPS.',\n imageUrlCredentials: 'لا يُسمح بعناوين URL التي تحتوي على بيانات تسجيل الدخول.',\n imageTimeout: 'يستغرق تحميل الصورة وقتًا طويلًا جدًا.',\n imageNotDisplayable: 'لا يمكن عرض هذه الصورة.',\n editorNotReady: 'المحرر غير جاهز. يُرجى المحاولة مرة أخرى.',\n imageLinkFailed: 'تعذّرت إضافة رابط الصورة.',\n imageOnly: 'يمكن رفع ملفات الصور فقط.',\n imageTooLarge: 'يجب ألا يتجاوز حجم الصورة الأصلية {mb}MB.',\n imageUploadFailed: 'فشل رفع الصورة.',\n pasteAsFile: 'الصق الصور كملفات أو اسحبها إلى المنطقة أعلاه.',\n postNotFound: 'لم يتم العثور على المنشور.',\n loadPermission: 'ليس لديك إذن بتحميل هذا المنشور. تأكد من تسجيل الدخول.',\n loadFailed: 'تعذّر تحميل المنشور: {message}',\n titleRequired: 'أدخل عنوانًا.',\n photoRequired: 'ارفع صورة واحدة على الأقل.',\n bodyRequired: 'اكتب نصًا أو أرفق صورة.',\n signInRequired: 'يلزم تسجيل الدخول.',\n boardMissing: 'لم يتم تحديد لوحة.',\n writeRestricted: 'تم تقييد النشر والتعليق مؤقتًا بسبب تكرار تحذيرات المحتوى.',\n moderationBlocked: 'يحتوي هذا على محتوى لا يمكن نشره.',\n },\n hint: {\n titling: 'جارٍ إنشاء العنوان…',\n reviewing: 'جارٍ مراجعة المحتوى…',\n saving: 'جارٍ الحفظ…',\n },\n },\n footer: {\n introduction: \"يعتمد memi-board على Nuxt 4 وVue 3 وTypeScript. وتجمع Nuxt UI وFirebase المنشورات والتعليقات والمحادثات في مكان واحد.\",\n eyebrow: \"مساحة للحوار\",\n tagline: \"مجتمعات صغيرة. قصص مشتركة.\",\n detail: \"التعريف المفصّل\",\n links: \"الروابط والتواصل\",\n email: \"البريد الإلكتروني\",\n credit: \"من تطوير memi\",\n feedback: \"أرسل ملاحظاتك\",\n feedbackSubject: \"ملاحظات memi-board\",\n feedbackBody: \"الملاحظات:\\n\",\n siteEyebrow: \"خدمات تستخدم memi-board\",\n changelog: \"سجل التغييرات\",\n info: {\n title: \"memi-board\",\n about: \"حول memi-board\",\n sites: \"أمثلة الاستخدام\",\n history: 'سجل الإصدارات',\n },\n sites: {\n description: \"خدمات تستخدم memi-board لمشاركة المنشورات والمحادثات.\",\n memi: \"مساحة للتطوير وقصص الحياة اليومية\",\n waiting: \"خدمة انتظار بسيطة عبر رمز QR\",\n track: \"تتبع GPS لتسجيل مسارات التنقل\",\n loop: \"تسجيل حركة المركبات وحلول المستشعرات\",\n safe: \"توصيل وإعداد جهاز منع الخلط بين الدواسات\",\n inviteTitle: \"هل تستخدمه أنت أيضًا؟\",\n invite: \"أخبرنا بعنوان موقعك.\",\n inviteSite: \"اتركه على memi.dev\",\n inviteOr: \"أو\",\n inviteSubject: \"نستخدم memi-board\",\n inviteBody: \"عنوان الموقع:\\n\",\n },\n stack: {\n ui: 'الواجهة والتجربة',\n data: 'البيانات وتسجيل الدخول',\n writing: 'الكتابة والأدوات المساعدة',\n },\n },\n likes: {\n signInRequired: 'يُرجى تسجيل الدخول.',\n commentNotFound: 'لم يتم العثور على التعليق.',\n },\n list: {\n boardInfo: {\n creator: 'أنشأه',\n managers: 'المديرون',\n staff: 'الموظفون',\n },\n commentCount: '{count} تعليقات',\n settings: 'الإعدادات',\n loadFailed: 'تعذّر تحميل القائمة: {error}',\n empty: 'لا توجد منشورات بعد.',\n notice: 'إعلان',\n photo: 'صورة',\n likeCount: 'الإعجابات {count}',\n info: {\n title: 'معلومات اللوحة',\n about: 'عن هذه اللوحة',\n history: 'سجل الإصدارات',\n },\n stack: {\n framework: 'إطار العمل واللغة',\n ui: 'الواجهة والتنسيق',\n backend: 'الخلفية والبيانات',\n },\n tech: {\n nuxt: 'إطار عمل SSR مبني على Vue',\n vue: 'Composition API · script setup',\n typescript: 'أنواع آمنة للبيانات والمكونات',\n nuxtUi: 'واجهة اللوحة والنماذج والنوافذ المنبثقة',\n tailwind: 'متجاوب · أنماط فاتحة/داكنة',\n lucide: 'أيقونات خفيفة ومتناسقة',\n dayjs: 'تواريخ وأوقات نسبية سهلة القراءة',\n firestore: 'قاعدة بيانات فورية للمنشورات والتعليقات',\n auth: 'تسجيل دخول وأذونات آمنة',\n storage: 'تخزين الصور والمرفقات',\n vuefire: 'ربط فوري بين Nuxt وFirebase',\n },\n },\n listViewSwitch: {\n card: 'بطاقة',\n default: 'افتراضي',\n dense: 'مضغوط',\n video: 'فيديو',\n },\n miniComments: {\n empty: 'لا توجد تعليقات بعد.',\n blinded: 'أخفى المشرف هذا التعليق.',\n },\n miniList: {\n empty: 'لا توجد منشورات بعد.',\n },\n miniPicker: {\n selectedCount: 'المحدد {count} / {max}',\n layoutHint: 'من 2 فأكثر تُعرض كشريط دوّار، و4 كشبكة',\n searchPlaceholder: 'البحث في العناوين',\n loading: 'جارٍ تحميل المنشورات…',\n noMore: 'لا توجد منشورات أخرى للاختيار.',\n },\n miniPost: {\n empty: 'لم يتم اختيار منشورات.',\n },\n moderation: {\n writeRestricted: 'تم تقييد النشر والتعليق مؤقتًا بسبب تكرار تحذيرات المحتوى.',\n },\n moderationPrompt: {\n localHit: 'لا يُسمح بتعبيرات مثل «{hit}». يُرجى إعادة الصياغة.',\n localGeneric: 'يحتوي هذا على ألفاظ نابية، لذا لا يمكن نشره. يُرجى إعادة الصياغة.',\n genericBlocked: 'يحتوي هذا على محتوى لا يمكن نشره. يُرجى تعديله.',\n categories: {\n abuse: 'ألفاظ نابية أو إهانات',\n spam: 'رسائل مزعجة أو إعلانات',\n adult: 'محتوى جنسي أو للبالغين',\n violence: 'عنف أو تهديدات',\n other: 'محتوى غير لائق',\n },\n },\n moderationStrike: {\n liftSoon: 'يُرفع قريبًا',\n liftInHours: 'يُرفع بعد {hours} ساعة تقريبًا',\n liftInDays: 'يُرفع بعد {days} يوم تقريبًا',\n liftInDaysHours: 'يُرفع بعد {days} يوم و{hours} ساعة تقريبًا',\n },\n posts: {\n boardIdRequired: '[memi-board] boardId مطلوب.',\n photoRequired: 'يُرجى إضافة صورة.',\n bodyRequired: 'يُرجى إدخال نص أو إرفاق صورة.',\n titleRequired: 'يُرجى إدخال عنوان.',\n },\n profile: {\n stats: {\n posts: '{count} منشورات',\n comments: '{count} تعليقات',\n aiUsage: 'استخدام الذكاء الاصطناعي {used} / {limit}',\n aiUsageResets: 'استخدام الذكاء الاصطناعي {used} / {limit} · يُعاد التعيين بعد {hours} ساعة',\n warnings: '{count} تحذيرات',\n },\n notFound: 'لم يتم العثور على المستخدم.',\n noName: 'بلا اسم',\n joined: 'انضم {time}',\n lastVisit: 'آخر ظهور {time}',\n },\n profileEditModal: {\n imageOnly: 'يمكن اختيار ملفات الصور فقط.',\n nameRequired: 'يُرجى إدخال اسم.',\n saveFailed: 'تعذّر حفظ الملف الشخصي.',\n title: 'تعديل الملف الشخصي',\n changePhoto: 'تغيير الصورة',\n name: 'الاسم',\n bio: 'نبذة',\n bioPlaceholder: 'عرّف الآخرين بنفسك',\n },\n reportButton: {\n failed: 'تعذّر إرسال البلاغ.',\n reported: 'تم الإبلاغ',\n title: 'الإبلاغ عن المنشور',\n done: 'تم استلام البلاغ. سيراجعه فريق العمل.',\n reason: 'السبب',\n detailPlaceholder: 'التفاصيل (اختياري)',\n submit: 'إبلاغ',\n\n \"status\": {\n \"open\": \"تم الاستلام\",\n \"dismissed\": \"مرفوض\",\n \"actioned\": \"اكتملت المراجعة\"\n },\n \"resultTitle\": \"حالة البلاغ\",\n \"result\": {\n \"open\": \"تم استلام بلاغك وهو بانتظار المراجعة.\",\n \"dismissed\": \"لم تجد المراجعة مخالفة.\",\n \"actioned\": \"اكتملت المراجعة. راجع السبب أدناه.\"\n },\n \"reviewedAt\": \"وقت المراجعة\",\n \"reviewNote\": \"سبب القرار\",\n \"noNote\": \"لا يوجد سبب مسجل لهذا السجل القديم.\",\n \"detailRequired\": \"التفاصيل (مطلوبة عند اختيار أخرى)\",\n },\n reportList: {\n staffOnly: 'يمكن لفريق العمل فقط عرض البلاغات.',\n loadFailed: 'تعذّر تحميل القائمة: {error}',\n empty: 'لا توجد بلاغات معلّقة.',\n untitled: 'منشور بلا عنوان',\n author: 'بواسطة {name}',\n dismiss: 'رفض',\n\n \"tabs\": {\n \"open\": \"قيد الانتظار\",\n \"processed\": \"سجل المراجعات\"\n },\n \"filterLabel\": \"تصفية البلاغات\",\n \"orderHint\": \"الأحدث استلامًا أولًا.\",\n \"historyEmpty\": \"لا يوجد سجل مراجعات.\",\n \"confirm\": \"وضع علامة تمت المراجعة\",\n \"dismissTitle\": \"رفض البلاغ\",\n \"resolveTitle\": \"إكمال المراجعة\",\n \"actionHint\": \"يغير حالة البلاغ فقط، ولا يخفي المنشور أو يحذفه.\",\n \"publicNote\": \"هذا السبب ظاهر أيضًا لمقدّم البلاغ.\",\n \"reviewer\": \"المراجع\",\n \"reviewNote\": \"سبب القرار\",\n \"unknownReviewer\": \"مراجع غير معروف\",\n \"actionFailed\": \"تعذرت المعالجة. حاول مجددًا.\",\n },\n reports: {\n reason: {\n spam: 'رسائل مزعجة / إعلانات',\n abuse: 'إساءة / كراهية / تحرّش',\n adult: 'محتوى جنسي',\n illegal: 'محتوى غير قانوني',\n other: 'أخرى',\n },\n fallbackLabel: 'بلاغ',\n signInRequired: 'يُرجى تسجيل الدخول.',\n cannotReportOwn: 'لا يمكنك الإبلاغ عن منشورك.',\n reasonRequired: 'يُرجى اختيار سبب.',\n detailTooLong: 'يمكن أن تصل التفاصيل إلى {max} حرف كحد أقصى.',\n\n \"otherDetailRequired\": \"أدخل التفاصيل عند اختيار أخرى.\",\n \"reviewNoteRequired\": \"أدخل سبب القرار.\",\n \"alreadyReviewed\": \"تمت مراجعة هذا البلاغ مسبقًا. راجع القائمة.\",\n \"manageRequired\": \"ليست لديك صلاحية مراجعة هذا البلاغ.\",\n \"alreadyReported\": \"لقد أبلغت عن هذا المنشور مسبقًا.\",\n \"statusLoadFailed\": \"تعذر تحميل الحالة. حدّث الصفحة.\",\n },\n sectionUtil: {\n kind: {\n list: 'قائمة المنشورات',\n post: 'منشورات',\n comments: 'تعليقات',\n },\n sort: {\n latest: 'الأحدث',\n likes: 'الأكثر إعجابًا',\n },\n untitledPost: 'منشور',\n view: {\n media: 'الوسائط',\n list: 'قائمة',\n },\n },\n sections: {\n defaultTitle: 'القسم {n}',\n },\n seo: {\n allCategory: 'الكل',\n boardDescription: 'لوحة {name}',\n allDescription: 'اللوحة — الإعلانات وأخبار المجتمع.',\n postFallbackTitle: 'منشور | {site}',\n postFallbackDescription: 'اللوحة',\n photo: 'صورة',\n postDescriptionFallback: 'منشور في اللوحة',\n listTitle: '{name} | {site}',\n listTitleAll: 'اللوحة | {site}',\n listDescription: '{name} — تابع أحدث المنشورات.',\n listDescriptionAll: 'اللوحة — إعلانات وقصص.',\n },\n settings: {\n aiTitle: {\n label: 'كتابة العناوين بالذكاء الاصطناعي',\n help: 'عند ترك عنوان المنشور الجديد فارغًا، يكتب الذكاء الاصطناعي عنوانًا من النص (أو من أول صورة إن لم يوجد نص). تُرسل الصور إلى Google AI لهذا الغرض فقط. أوقفه لإلزام كتابة العنوان ولإيقاف إرسال الصور.',\n },\n site: {\n apply: 'تطبيق',\n applied: 'تم التطبيق.',\n title: 'الإعدادات العامة',\n help: 'تُطبَّق على الموقع كله، وتتغلّب على إعدادات التطبيق المضيف، وتسري فور تغييرها.',\n ai: { label: 'استخدام ميزات الذكاء الاصطناعي', help: 'أوقفه إذا تعذّر استخدام الذكاء الاصطناعي، مثلًا بسبب التكلفة. يوقف الترجمة ومساعد الكتابة وعناوين الذكاء الاصطناعي والإشراف بالذكاء الاصطناعي، ولن تُرسل الصور إليه. يستمر عمل فحص الكلمات المحظورة.' },\n i18n: { label: 'استخدام التدويل', help: 'عند إيقافه تُثبَّت كل الشاشات على اللغة المختارة أدناه وتتوقف الترجمة. لا تُحذف الترجمات المحفوظة.' },\n locales: { label: 'اللغات المتاحة', help: 'تُترجم اللغات الـ {count} المختارة فقط وتظهر في قائمة اللغات. لا تُنشأ ترجمات جديدة للغات غير المختارة، ولا تُحذف الترجمات المحفوظة.' },\n locale: { label: 'اللغة الافتراضية', help: 'اللغة المستخدمة عندما لا يحدد التطبيق المضيف لغة.', fixedLabel: 'اللغة الثابتة', fixedHelp: 'تُعرض كل الشاشات بهذه اللغة.' },\n },\n i18nBoard: {\n label: 'التدويل',\n help: 'عند التفعيل تُترجم تلقائيًا إلى {count} لغات اسم اللوحة ووصفها والمنشورات والتعليقات الجديدة وتُحفظ معها. عند الإيقاف يُعرض النص الأصلي فقط.',\n existing: 'ترجمة المنشورات الحالية أيضًا',\n },\n about: {\n label: 'إظهار About memi-board',\n help: 'يعرض رابط About memi-board ونافذته في أسفل كل شاشة لوحة. أوقفه لإخفائه في الموقع كله.',\n },\n postTranslations: {\n label: 'ترجمة المنشورات الحالية',\n help: 'يبحث عن المنشورات التي ترجمتها مفقودة أو لم تعد تطابق الأصل، ثم يترجمها ويحفظها دفعة واحدة. استخدمه للوحات التي أُوقفت فيها الترجمة التلقائية أو لاستكمال المنشورات التي فاتتها الترجمة. لا يستهلك حصة الذكاء الاصطناعي اليومية.',\n scan: 'البحث عن منشورات للترجمة',\n run: 'ترجمة {count} منشورات',\n confirm: 'سيتم ترجمة {count} منشورات وحفظها مع استدعاء الذكاء الاصطناعي لكل منها. هل تتابع؟',\n progress: 'جارٍ الترجمة… اكتمل {done}، فشل {failed}',\n allDone: 'جميع المنشورات المنشورة وعددها {total} ترجماتها محدّثة.',\n found: '{count} من أصل {total} منشورات منشورة تحتاج إلى ترجمة.',\n failed: 'تعذّرت ترجمة {count} منشورات. ابحث مرة أخرى وأعد المحاولة.',\n },\n loading: 'جارٍ تحميل الإعدادات…',\n noAccess: 'ليس لديك صلاحية الوصول',\n notFound: {\n title: 'لم يتم العثور على اللوحة',\n checkAddress: 'يُرجى التحقق من العنوان.',\n checkBoardAddress: 'يُرجى التحقق من عنوان اللوحة.',\n },\n newBoard: {\n title: 'هذه اللوحة غير موجودة بعد',\n description: 'املأ البيانات أدناه واحفظها لإنشائها بهذا المعرّف.',\n },\n noLabel: 'بلا تسمية',\n option: {\n default: 'قياسي',\n },\n id: {\n label: 'معرّف الفئة',\n help: 'يُستخدم في URL والبيانات',\n },\n writeRole: {\n label: 'من يمكنه النشر',\n help: 'الحد الأدنى من الدور المطلوب للنشر في هذه الفئة',\n helpShort: 'الحد الأدنى من الدور المطلوب للنشر',\n options: {\n user: 'المستخدمون فما فوق',\n staff: 'فريق العمل فما فوق',\n admin: 'المشرفون فقط',\n },\n },\n commentWriteRole: {\n label: 'من يمكنه التعليق',\n help: 'الحد الأدنى من الدور المطلوب للتعليق في هذه الفئة',\n helpShort: 'الحد الأدنى من الدور المطلوب للتعليق',\n hiddenFixed: 'فريق العمل المعيَّن فقط (ثابت للوحات المخفية)',\n },\n staff: {\n label: 'فريق العمل المعيَّن',\n help: 'يمكن لفريق العمل المحدد فقط إعداد هذه اللوحة وإدارتها. اتركه فارغًا ليقتصر الأمر على المشرفين',\n placeholder: 'المشرفون فقط (دون تعيين فريق عمل)',\n },\n label: {\n label: 'الاسم المعروض',\n help: 'الاسم الذي يراه المستخدمون',\n },\n description: {\n label: 'الوصف',\n help: 'يظهر أعلى اللوحة وفي أماكن أخرى',\n placeholder: 'وصف قصير لهذه اللوحة (اختياري)',\n },\n visibility: {\n label: 'الظهور',\n options: {\n public: {\n label: 'ظاهرة',\n description: 'تظهر في القائمة الكاملة وعوامل التصفية',\n },\n hidden: {\n label: 'مخفية',\n description: 'يوميات أو خاصة. يمكن لفريق العمل المعيَّن فقط التعليق',\n },\n },\n },\n listView: {\n label: 'عرض القائمة',\n help: 'طريقة عرض قائمة المنشورات',\n options: {\n card: 'بطاقة',\n dense: 'مضغوط',\n video: 'فيديو',\n },\n },\n editorType: {\n label: 'نموذج النشر',\n help: 'طريقة كتابة المنشورات',\n options: {\n default: 'كتابة عنوان ونص',\n image: 'إضافة عدة صور وصورة غلاف',\n },\n },\n bulk: {\n title: 'تطبيق على كل اللوحات',\n apply: 'تطبيق على {count} لوحات',\n applyShort: 'تطبيق',\n confirmTitle: 'تطبيق على كل اللوحات',\n translateUntranslated: 'ترجمة اللوحات غير المترجمة ({count})',\n },\n translationLocales: {\n label: 'لغات الترجمة',\n },\n locale: {\n label: 'لغة اللوحة',\n auto: 'تلقائي (حسب لغة الموقع)',\n },\n autoTranslate: {\n action: \"ترجمة إلى {count} لغات\",\n manualHelp: \"ترجم اسم العرض والوصف معًا، ثم اضغط على حفظ للتطبيق.\",\n pending: \"الترجمات إلى {count} لغات جاهزة. اضغط على حفظ للتطبيق.\",\n manualFailed: \"فشلت الترجمة. تم الاحتفاظ بالنص. يرجى المحاولة مرة أخرى.\",\n label: 'الترجمة إلى {count} لغات عند الحفظ',\n help: 'عند التشغيل تُترجم الاسم والوصف إلى {count} لغات. عند الإيقاف لا تُترجم. لا تُعاد ترجمة النص إذا لم يتغير.',\n failed: 'حُفظت الإعدادات، لكن فشلت الترجمة إلى {count} لغات. احفظ مرة أخرى.',\n ready: 'الاسم والوصف محفوظان بـ {count} لغات.',\n },\n action: {\n moveDown: 'للأسفل',\n goToBoard: 'الانتقال إلى اللوحة',\n deleteBoard: 'حذف اللوحة',\n create: 'إنشاء',\n },\n newCategoryPlaceholder: 'اسم الفئة الجديدة',\n savedCategory: 'تم حفظ الفئة «{label}».',\n savedSettings: 'تم حفظ إعدادات اللوحة.',\n created: 'تم إنشاء اللوحة.',\n error: {\n orderFailed: 'تعذّر حفظ ترتيب الفئات.',\n deleteFailed: 'تعذّر حذف اللوحة وبياناتها.',\n saveFailed: 'تعذّر حفظ إعدادات اللوحة.',\n deleteAllFailed: 'تعذّر حذف بيانات اللوحة.',\n },\n danger: {\n title: 'منطقة الخطر',\n confirmLabel: 'اكتب «{phrase}» للتأكيد',\n phrase: 'حذف بيانات اللوحة',\n button: 'حذف كل البيانات',\n done: 'تم حذف كل بيانات اللوحة.',\n },\n },\n shareButton: {\n copied: 'تم نسخ الرابط',\n },\n signIn: {\n withGoogle: 'تسجيل الدخول باستخدام Google',\n withApple: 'تسجيل الدخول باستخدام Apple',\n or: 'أو',\n name: 'الاسم',\n email: 'البريد الإلكتروني',\n password: 'كلمة المرور',\n signUp: 'إنشاء حساب',\n toSignUp: 'ليس لديك حساب؟ أنشئ حسابًا',\n toSignIn: 'لديك حساب بالفعل؟ سجّل الدخول',\n },\n storage: {\n sourceTooLarge: 'يجب ألا يتجاوز حجم الصورة الأصلية {max}MB.',\n imageOnly: 'يمكن رفع ملفات الصور فقط.',\n canvasUnavailable: 'Canvas غير متاح',\n compressFailed: 'فشل الضغط',\n loadFailed: 'فشل تحميل الصورة',\n },\n swipeHint: {\n title: 'جرّب السحب يمينًا أو يسارًا',\n description: 'اسحب لليسار للمنشور التالي، ولليمين للمنشور السابق.',\n },\n userCommentList: {\n loadFailed: 'تعذّر تحميل القائمة: {error}',\n empty: 'لا توجد تعليقات بعد.',\n blinded: 'أخفى المشرف هذا التعليق.',\n likes: 'الإعجابات {count}',\n },\n userPostList: {\n loadFailed: 'تعذّر تحميل القائمة: {error}',\n empty: 'لا توجد منشورات بعد.',\n },\n users: {\n changeRoleFailed: 'تعذّر تغيير الدور.',\n loading: 'جارٍ تحميل المستخدمين…',\n noPermission: {\n title: 'لا توجد صلاحية',\n description: 'يمكن لمشرفي اللوحة فقط إدارة أدوار المستخدمين.',\n },\n empty: 'لم يسجّل أي مستخدم الدخول إلى اللوحة بعد.',\n noName: 'بلا اسم',\n moderationWarnings: 'تحذيرات المحتوى: {count}',\n },\n writingAssistant: {\n dailyLimit: 'يمكن استخدام مساعد الكتابة بالذكاء الاصطناعي حتى {limit} مرة في اليوم. حاول مرة أخرى بعد حوالي {hours} ساعة.',\n loginRequired: 'سجّل الدخول لاستخدام مساعد الكتابة بالذكاء الاصطناعي.',\n userMissing: 'تعذّر التحقق من معلومات المستخدم. يُرجى المحاولة مرة أخرى.',\n contentRequired: 'أدخل أولًا محتوى ليعمل عليه AI.',\n customRequired: 'أدخل تعليمات لطريقة إعادة الصياغة.',\n emptyResult: 'لم يتمكن AI من إنتاج نتيجة. يُرجى المحاولة مرة أخرى.',\n translateEmpty: 'أدخل عنوانًا أو نصًا للترجمة أولًا.',\n translateTooLong: 'لا يمكن حفظ نص أطول من {limit} حرفًا بـ {count} لغات. اختصره ثم أعد المحاولة.',\n translateIncomplete: 'عادت بعض اللغات فارغة. يُرجى المحاولة مرة أخرى.',\n failed: 'فشلت مهمة AI. يُرجى المحاولة مرة أخرى.',\n actions: {\n proofread: 'تدقيق الإملاء',\n polish: 'تحسين الجمل',\n continue: 'متابعة الكتابة',\n summarize: 'تلخيص',\n translateEn: 'الترجمة إلى الإنجليزية',\n translateKo: 'الترجمة إلى الكورية',\n translateAll: 'ترجمة وحفظ بـ {count} لغات',\n translateSaved: 'تم الحفظ بـ {count} لغات. يرى القارئ ترجمة لغته.',\n translatePending: 'ترجمات {count} لغات جاهزة. تُحفظ مع المنشور.',\n translateEmpty: 'أدخل عنوانًا أو نصًا للترجمة أولًا.',\n title: 'إنشاء عنوان من النص',\n custom: 'إعادة الصياغة بأسلوب مخصص…',\n },\n },\n}\n\nexport default messages\n"],"mappings":"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MAAM;GACN,KAAK;GACL,SAAS;GACT,UAAU;GACV,SAAS;GACT,OAAO;GACP,QAAQ;EACV;EACA,SAAS;EACT,UAAU;EACV,UAAU;GACR,OAAO;GACP,cAAc;GACd,mBAAmB;EACrB;EACA,UAAU;GACR,OAAO;GACP,aAAa;EACf;EACA,SAAS;EACT,QAAQ,EACN,SAAS,QACX;EACA,IAAI;GACF,OAAO;GACP,MAAM;EACR;EACA,WAAW;GACT,OAAO;GACP,MAAM;GACN,WAAW;GACX,SAAS;IACP,MAAM;IACN,OAAO;IACP,OAAO;GACT;EACF;EACA,kBAAkB;GAChB,OAAO;GACP,MAAM;GACN,WAAW;GACX,aAAa;EACf;EACA,OAAO;GACL,OAAO;GACP,MAAM;GACN,aAAa;EACf;EACA,OAAO;GACL,OAAO;GACP,MAAM;EACR;EACA,aAAa;GACX,OAAO;GACP,MAAM;GACN,aAAa;EACf;EACA,YAAY;GACV,OAAO;GACP,SAAS;IACP,QAAQ;KACN,OAAO;KACP,aAAa;IACf;IACA,QAAQ;KACN,OAAO;KACP,aAAa;IACf;GACF;EACF;EACA,UAAU;GACR,OAAO;GACP,MAAM;GACN,SAAS;IACP,MAAM;IACN,OAAO;IACP,OAAO;GACT;EACF;EACA,YAAY;GACV,OAAO;GACP,MAAM;GACN,SAAS;IACP,SAAS;IACT,OAAO;GACT;EACF;EACA,MAAM;GACJ,OAAO;GACP,OAAO;GACP,YAAY;GACZ,cAAc;GACd,uBAAuB;EACzB;EACA,oBAAoB,EAClB,OAAO,eACT;EACA,QAAQ;GACN,OAAO;GACP,MAAM;EACR;EACA,eAAe;GACb,QAAQ;GACR,YAAY;GACZ,SAAS;GACT,cAAc;GACd,OAAO;GACP,MAAM;GACN,QAAQ;GACR,OAAO;EACT;EACA,QAAQ;GACN,UAAU;GACV,WAAW;GACX,aAAa;GACb,QAAQ;EACV;EACA,wBAAwB;EACxB,eAAe;EACf,eAAe;EACf,SAAS;EACT,OAAO;GACL,aAAa;GACb,cAAc;GACd,YAAY;GACZ,iBAAiB;EACnB;EACA,QAAQ;GACN,OAAO;GACP,cAAc;GACd,QAAQ;GACR,QAAQ;GACR,MAAM;EACR;CACF;CACA,aAAa,EACX,QAAQ,gBACV;CACA,QAAQ;EACN,YAAY;EACZ,WAAW;EACX,IAAI;EACJ,MAAM;EACN,OAAO;EACP,UAAU;EACV,QAAQ;EACR,UAAU;EACV,UAAU;CACZ;CACA,SAAS;EACP,gBAAgB;EAChB,WAAW;EACX,mBAAmB;EACnB,gBAAgB;EAChB,YAAY;CACd;CACA,WAAW;EACT,OAAO;EACP,aAAa;CACf;CACA,iBAAiB;EACf,YAAY;EACZ,OAAO;EACP,SAAS;EACT,OAAO;CACT;CACA,cAAc;EACZ,YAAY;EACZ,OAAO;CACT;CACA,OAAO;EACL,kBAAkB;EAClB,SAAS;EACT,cAAc;GACZ,OAAO;GACP,aAAa;EACf;EACA,OAAO;EACP,QAAQ;EACR,oBAAoB;CACtB;CACA,kBAAkB;EAChB,YAAY;EACZ,eAAe;EACf,aAAa;EACb,iBAAiB;EACjB,gBAAgB;EAChB,aAAa;EACb,gBAAgB;EAChB,kBAAkB;EAClB,qBAAqB;EACrB,QAAQ;EACR,SAAS;GACP,WAAW;GACX,QAAQ;GACR,UAAU;GACV,WAAW;GACX,aAAa;GACb,aAAa;GACb,cAAc;GACd,gBAAgB;GAChB,kBAAkB;GAClB,gBAAgB;GAChB,OAAO;GACP,QAAQ;EACV;CACF;AACF"}
@@ -180,6 +180,9 @@ function pe(e) {
180
180
  }), e.translation && (t.translation = {
181
181
  ...t.translation,
182
182
  ...e.translation
183
+ }), e.bannerGeneration && (t.bannerGeneration = {
184
+ ...t.bannerGeneration,
185
+ ...e.bannerGeneration
183
186
  }), e.roleLabels && (t.roleLabels = { ...e.roleLabels }), e.locale && (t.locale = e.locale);
184
187
  }
185
188
  function N() {
@@ -268,6 +271,7 @@ var _e = {
268
271
  },
269
272
  authorMemo: { tooLong: "메모는 {max}자까지 작성할 수 있습니다." },
270
273
  authorMenu: {
274
+ menu: "작성자 메뉴",
271
275
  viewProfile: "프로필 보기",
272
276
  viewPosts: "작성글 보기",
273
277
  viewComments: "작성한 댓글 보기",
@@ -392,6 +396,10 @@ var _e = {
392
396
  },
393
397
  common: {
394
398
  action: {
399
+ zoomIn: "확대",
400
+ zoomOut: "축소",
401
+ fitImage: "화면에 맞추기",
402
+ originalImage: "원래 크기 (100%)",
395
403
  cancel: "취소",
396
404
  save: "저장",
397
405
  saved: "저장됨",
@@ -415,11 +423,13 @@ var _e = {
415
423
  toTop: "위로"
416
424
  },
417
425
  label: {
426
+ imageControls: "이미지 확대 도구",
418
427
  anonymous: "익명",
419
428
  user: "사용자",
420
429
  image: "이미지",
421
430
  draft: "초안",
422
- loading: "불러오는 중…"
431
+ loading: "불러오는 중…",
432
+ viewCount: "조회수 {count}"
423
433
  },
424
434
  role: {
425
435
  owner: "최고 관리자",
@@ -440,6 +450,7 @@ var _e = {
440
450
  deleteConfirm: "이 게시글을 삭제하시겠습니까? 되돌릴 수 없습니다.",
441
451
  notFound: "게시글을 찾을 수 없습니다.",
442
452
  draftPreview: "미공개 미리보기",
453
+ tag: "태그",
443
454
  draftNotice: "아직 게시되지 않았습니다. 게시하기 전까지는 작성자만 볼 수 있어요.",
444
455
  publish: "게시하기",
445
456
  notice: "공지",
@@ -767,7 +778,22 @@ var _e = {
767
778
  done: "신고를 접수했습니다. 스태프가 내용을 확인합니다.",
768
779
  reason: "사유",
769
780
  detailPlaceholder: "자세한 내용 (선택)",
770
- submit: "신고하기"
781
+ submit: "신고하기",
782
+ status: {
783
+ open: "접수됨",
784
+ dismissed: "기각됨",
785
+ actioned: "검토 완료"
786
+ },
787
+ resultTitle: "신고 처리 상태",
788
+ result: {
789
+ open: "신고를 접수했으며 검토를 기다리고 있습니다.",
790
+ dismissed: "검토 결과 위반으로 판단하지 않았습니다.",
791
+ actioned: "검토가 완료되었습니다. 아래 처리 사유를 확인해 주세요."
792
+ },
793
+ reviewedAt: "처리 시각",
794
+ reviewNote: "처리 사유",
795
+ noNote: "기존 이력에 처리 사유가 없습니다.",
796
+ detailRequired: "자세한 내용 (기타 사유는 필수)"
771
797
  },
772
798
  reportList: {
773
799
  staffOnly: "스태프만 신고 목록을 볼 수 있습니다.",
@@ -776,7 +802,22 @@ var _e = {
776
802
  untitled: "제목 없는 글",
777
803
  author: "작성 {name}",
778
804
  dismiss: "기각",
779
- confirm: "확인"
805
+ tabs: {
806
+ open: "대기 중",
807
+ processed: "처리 이력"
808
+ },
809
+ filterLabel: "신고 상태 선택",
810
+ orderHint: "접수 시각 최신순입니다.",
811
+ historyEmpty: "처리 이력이 없습니다.",
812
+ confirm: "검토 완료",
813
+ dismissTitle: "신고 기각",
814
+ resolveTitle: "검토 완료 처리",
815
+ actionHint: "이 처리는 신고 상태만 변경합니다. 게시글을 숨기거나 삭제하지 않습니다.",
816
+ publicNote: "이 사유는 신고자에게도 공개됩니다.",
817
+ reviewer: "처리자",
818
+ reviewNote: "처리 사유",
819
+ unknownReviewer: "처리자 정보 없음",
820
+ actionFailed: "처리하지 못했습니다. 다시 시도해 주세요."
780
821
  },
781
822
  reports: {
782
823
  reason: {
@@ -790,7 +831,13 @@ var _e = {
790
831
  signInRequired: "로그인이 필요합니다.",
791
832
  cannotReportOwn: "자신의 글은 신고할 수 없습니다.",
792
833
  reasonRequired: "신고 사유를 선택해 주세요.",
793
- detailTooLong: "자세한 내용은 {max}자까지입니다."
834
+ detailTooLong: "자세한 내용은 {max}자까지입니다.",
835
+ otherDetailRequired: "기타 사유는 자세한 내용을 입력해 주세요.",
836
+ reviewNoteRequired: "처리 사유를 입력해 주세요.",
837
+ alreadyReviewed: "이미 처리된 신고입니다. 목록을 확인해 주세요.",
838
+ manageRequired: "신고를 처리할 권한이 없습니다.",
839
+ alreadyReported: "이미 신고한 글입니다.",
840
+ statusLoadFailed: "신고 상태를 불러오지 못했습니다. 새로고침해 주세요."
794
841
  },
795
842
  sectionUtil: {
796
843
  kind: {
@@ -823,6 +870,29 @@ var _e = {
823
870
  listDescriptionAll: "보드 — 공지와 이야기를 확인하세요."
824
871
  },
825
872
  settings: {
873
+ banner: {
874
+ requestLabel: "원하는 스타일·추가 요청 (선택)",
875
+ requestHelp: "색감, 분위기, 표현 방식이나 넣고 싶은 요소를 자유롭게 적어 주세요. 최대 1,000자.",
876
+ requestPlaceholder: "예: 파스텔톤 수채화 느낌, 따뜻하고 차분한 분위기. 오른쪽에 작은 책과 식물을 배치해 주세요.",
877
+ generate: "AI로 배너 생성",
878
+ generateHelp: "입력한 제목·설명과 추가 요청으로 배너를 만듭니다. 생성 후 크롭·미리보기를 확인하고 저장하세요.",
879
+ generating: "제목과 설명을 바탕으로 배너를 만드는 중입니다. 잠시 기다려 주세요.",
880
+ titleRequired: "배너를 생성하려면 보드 제목을 먼저 입력해 주세요.",
881
+ noImage: "AI가 이미지를 반환하지 않았습니다. 제목과 설명을 바꾸고 다시 시도해 주세요.",
882
+ contextChanged: "생성 중 제목이나 설명이 바뀌었습니다. 현재 내용으로 다시 생성해 주세요.",
883
+ generateFailed: "배너를 생성하지 못했습니다. AI Logic 이미지 모델 사용 설정과 App Check를 확인한 뒤 다시 시도해 주세요.",
884
+ label: "보드 상단 배너",
885
+ help: "권장 크기 2400 × 300px (8:1). 이미지를 이동하거나 확대해 표시할 영역을 선택하세요. 설정을 저장하면 적용됩니다.",
886
+ select: "이미지 선택",
887
+ remove: "배너 제거",
888
+ crop: "배너 이미지 자르기",
889
+ preview: "배너 미리보기",
890
+ confirm: "이 영역 사용",
891
+ invalid: "JPG, PNG, WebP 이미지(25MB 이하)를 선택해 주세요.",
892
+ failed: "이미지를 처리하지 못했습니다. 다른 이미지로 다시 시도해 주세요.",
893
+ zoomIn: "확대",
894
+ zoomOut: "축소"
895
+ },
826
896
  managers: "담당 매니저",
827
897
  loading: "설정을 불러오고 있습니다.",
828
898
  noAccess: "접근 권한이 없습니다",
@@ -1153,15 +1223,15 @@ var _e = {
1153
1223
  }
1154
1224
  }
1155
1225
  }, ve = {
1156
- en: () => import("./en-Dc7zQOy-.js"),
1157
- ja: () => import("./ja-xDttH9CE.js"),
1158
- de: () => import("./de-B4GZqxQj.js"),
1159
- fr: () => import("./fr-Zf5mcs8m.js"),
1160
- es: () => import("./es-DzFDaLwo.js"),
1161
- pt: () => import("./pt-WIfxYYWQ.js"),
1162
- zh: () => import("./zh-CI6Sd8PD.js"),
1163
- ar: () => import("./ar-CQhBdHu3.js"),
1164
- id: () => import("./id-CaWN8212.js")
1226
+ en: () => import("./en-Dshxokpu.js"),
1227
+ ja: () => import("./ja-DyexZuXX.js"),
1228
+ de: () => import("./de-Ckqy6xMr.js"),
1229
+ fr: () => import("./fr-BrhcNuxW.js"),
1230
+ es: () => import("./es-BkaAuj2h.js"),
1231
+ pt: () => import("./pt-Az3vABvC.js"),
1232
+ zh: () => import("./zh-B55IygiW.js"),
1233
+ ar: () => import("./ar-DsYwkqiP.js"),
1234
+ id: () => import("./id-B_7SWGzM.js")
1165
1235
  }, B = "__MEMI_BOARD_I18N__";
1166
1236
  function V() {
1167
1237
  let e = globalThis;
@@ -1315,4 +1385,4 @@ function Ae(e, t) {
1315
1385
  //#endregion
1316
1386
  export { f as $, b as A, se as B, R as C, v as D, N as E, k as F, de as G, oe as H, A as I, D as J, ne as K, O as L, S as M, ue as N, y as O, fe as P, te as Q, ae as R, I as S, ge as T, re as U, E as V, T as W, C as X, ce as Y, w as Z, me as _, Ee as a, P as b, Ce as c, Y as d, p as et, Z as f, z as g, G as h, we as i, x as j, _ as k, q as l, U as m, Oe as n, g as nt, Te as o, ye as p, le as q, ke as r, h as rt, Q as s, Ae as t, d as tt, X as u, he as v, L as w, F as x, pe as y, ie as z };
1317
1387
 
1318
- //# sourceMappingURL=commentImages-mIfyNHgz.js.map
1388
+ //# sourceMappingURL=commentImages-BZOxzRy6.js.map