mirror of
https://github.com/chenasraf/nextcloud-forum.git
synced 2026-05-18 01:28:58 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccd7f1d98d | ||
| 53a8e3cc72 | |||
| 3e7ccbb02a | |||
|
|
58c25e4c64 |
@@ -1 +1 @@
|
||||
{".":"0.34.2"}
|
||||
{".":"0.35.0"}
|
||||
|
||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,5 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
## [0.35.0](https://github.com/chenasraf/nextcloud-forum/compare/v0.34.2...v0.35.0) (2026-03-29)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* audio attachment support ([3e7ccbb](https://github.com/chenasraf/nextcloud-forum/commit/3e7ccbb02ac9831d3e69e434e1723825a69880d5))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **l10n:** Update translations from Transifex ([58c25e4](https://github.com/chenasraf/nextcloud-forum/commit/58c25e4c6443df4f99d5192759116ea8112fbc66))
|
||||
|
||||
## [0.34.2](https://github.com/chenasraf/nextcloud-forum/compare/v0.34.1...v0.34.2) (2026-03-29)
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ Create discussions, share ideas, and collaborate with your community directly in
|
||||
|
||||
The forum integrates seamlessly with your Nextcloud instance, using your existing accounts and teams for authentication and access control.
|
||||
]]></description>
|
||||
<version>0.34.2</version>
|
||||
<version>0.35.0</version>
|
||||
<licence>agpl</licence>
|
||||
<author mail="contact@casraf.dev" homepage="https://casraf.dev">Chen Asraf</author>
|
||||
<namespace>Forum</namespace>
|
||||
|
||||
@@ -57,8 +57,15 @@ OC.L10N.register(
|
||||
"Welcome to the forum!" : "Welcome to the forum!",
|
||||
"Deleted user" : "Deleted user",
|
||||
"A community-driven forum built right into your Nextcloud instance" : "A community-driven forum built right into your Nextcloud instance",
|
||||
"Create discussions, share ideas, and collaborate with your community directly in Nextcloud.\n\n**Key features:**\n- **Threaded Discussions** - Create and reply to organized discussion threads with pagination\n- **Category Organization** - Structure your forum with customizable categories, headers, colors, and drag-and-drop reordering\n- **Rich Text Formatting** - BBCode formatting with built-in and custom tags, toolbar with overflow menu\n- **File Attachments** - Attach files from your Nextcloud storage or upload via drag-and-drop\n- **Notifications** - Subscribe to threads and get notified on replies and @mentions\n- **Post Reactions** - React to posts with emoji reactions\n- **Read/Unread Tracking** - Track unread posts at thread and category level\n- **Bookmarks** - Save threads for quick access\n- **Search** - Advanced search with boolean operators and category filtering\n- **User Profiles** - View post history, statistics, and role badges\n- **Roles and Teams** - Fine-grained permissions per role or Nextcloud Team, per category\n- **Guest Access** - Optional public access for unauthenticated visitors with configurable permissions\n- **Edit History** - View post revision history with configurable visibility and per-account privacy controls\n- **Reusable Templates** - Save and insert frequently used content snippets\n- **Signatures** - BBCode-formatted signatures on posts\n- **Thread Drafts** - Auto-saved drafts per category\n- **Dashboard Widgets** - Recent activity, top threads, and top categories on the Nextcloud dashboard\n- **Direct Post Links** - Link directly to a specific post within a thread\n- **Moderation Tools** - Pin, lock, hide, and move threads; review and restore deleted content\n- **Management Tools** - Manage categories, roles, BBCodes, and forum settings with granular permissions\n- **Server Administration** - Repair seeds, rebuild statistics, and assign roles from the Nextcloud admin panel\n\n**Perfect for:**\n- Team discussions and collaboration\n- Community forums\n- Support channels\n- Knowledge bases\n- Project discussions\n- Internal communication\n\nThe forum integrates seamlessly with your Nextcloud instance, using your existing accounts and teams for authentication and access control." : "Create discussions, share ideas, and collaborate with your community directly in Nextcloud.\n\n**Key features:**\n- **Threaded Discussions** - Create and reply to organized discussion threads with pagination\n- **Category Organization** - Structure your forum with customizable categories, headers, colors, and drag-and-drop reordering\n- **Rich Text Formatting** - BBCode formatting with built-in and custom tags, toolbar with overflow menu\n- **File Attachments** - Attach files from your Nextcloud storage or upload via drag-and-drop\n- **Notifications** - Subscribe to threads and get notified on replies and @mentions\n- **Post Reactions** - React to posts with emoji reactions\n- **Read/Unread Tracking** - Track unread posts at thread and category level\n- **Bookmarks** - Save threads for quick access\n- **Search** - Advanced search with boolean operators and category filtering\n- **User Profiles** - View post history, statistics, and role badges\n- **Roles and Teams** - Fine-grained permissions per role or Nextcloud Team, per category\n- **Guest Access** - Optional public access for unauthenticated visitors with configurable permissions\n- **Edit History** - View post revision history with configurable visibility and per-account privacy controls\n- **Reusable Templates** - Save and insert frequently used content snippets\n- **Signatures** - BBCode-formatted signatures on posts\n- **Thread Drafts** - Auto-saved drafts per category\n- **Dashboard Widgets** - Recent activity, top threads, and top categories on the Nextcloud dashboard\n- **Direct Post Links** - Link directly to a specific post within a thread\n- **Moderation Tools** - Pin, lock, hide, and move threads; review and restore deleted content\n- **Management Tools** - Manage categories, roles, BBCodes, and forum settings with granular permissions\n- **Server Administration** - Repair seeds, rebuild statistics, and assign roles from the Nextcloud admin panel\n\n**Perfect for:**\n- Team discussions and collaboration\n- Community forums\n- Support channels\n- Knowledge bases\n- Project discussions\n- Internal communication\n\nThe forum integrates seamlessly with your Nextcloud instance, using your existing accounts and teams for authentication and access control.",
|
||||
"Forum server administration" : "Forum server administration",
|
||||
"Database Initial Data" : "Database Initial Data",
|
||||
"Restore default forum data (roles, categories, permissions, BBCodes). This is safe to run multiple times as it will skip data that already exists." : "Restore default forum data (roles, categories, permissions, BBCodes). This is safe to run multiple times as it will skip data that already exists.",
|
||||
"Repair Database Initial Data" : "Repair Database Initial Data",
|
||||
"Rebuild Statistics" : "Rebuild Statistics",
|
||||
"Recalculate all forum statistics including account post counts, thread counts, and category counters. Use this if statistics appear incorrect or out of sync." : "Recalculate all forum statistics including account post counts, thread counts, and category counters. Use this if statistics appear incorrect or out of sync.",
|
||||
"User Roles" : "User Roles",
|
||||
"Assign forum roles to accounts. This allows you to grant administrative or moderator privileges to specific accounts." : "Assign forum roles to accounts. This allows you to grant administrative or moderator privileges to specific accounts.",
|
||||
"User ID" : "User ID",
|
||||
"Enter user ID" : "Enter user ID",
|
||||
"Role" : "Role",
|
||||
@@ -70,6 +77,7 @@ OC.L10N.register(
|
||||
"Home" : "Home",
|
||||
"Bookmarks" : "Bookmarks",
|
||||
"User preferences" : "User preferences",
|
||||
"Management" : "Management",
|
||||
"Dashboard" : "Dashboard",
|
||||
"Forum settings" : "Forum settings",
|
||||
"Users" : "Users",
|
||||
@@ -161,8 +169,14 @@ OC.L10N.register(
|
||||
"The forum has not been set up yet. Please contact an administration member to complete the setup." : "The forum has not been set up yet. Please contact an administration member to complete the setup.",
|
||||
"Deleted" : "Deleted",
|
||||
"Restore" : "Restore",
|
||||
"Error loading content" : "Error loading content",
|
||||
"Retry" : "Retry",
|
||||
"No deleted content" : "No deleted content",
|
||||
"There is no deleted content to review." : "There is no deleted content to review.",
|
||||
"Deleted reply" : "Deleted reply",
|
||||
"In thread" : "In thread",
|
||||
"Restore reply" : "Restore reply",
|
||||
"Restore thread" : "Restore thread",
|
||||
"Move thread to category" : "Move thread to category",
|
||||
"Select the category to move this thread to:" : "Select the category to move this thread to:",
|
||||
"Select a category …" : "Select a category …",
|
||||
@@ -365,6 +379,9 @@ OC.L10N.register(
|
||||
"You can use BBCode formatting in your signature" : "You can use BBCode formatting in your signature",
|
||||
"Enter your signature …" : "Enter your signature …",
|
||||
"Privacy" : "Privacy",
|
||||
"Control the visibility of your activity" : "Control the visibility of your activity",
|
||||
"Hide my edit history from other accounts" : "Hide my edit history from other accounts",
|
||||
"When enabled, other accounts cannot view the edit history of your posts. Administration and moderators can always view edit history." : "When enabled, other accounts cannot view the edit history of your posts. Administration and moderators can always view edit history.",
|
||||
"Failed to save preferences" : "Failed to save preferences",
|
||||
"Select upload directory" : "Select upload directory",
|
||||
"BBCode management" : "BBCode management",
|
||||
@@ -447,6 +464,7 @@ OC.L10N.register(
|
||||
"Select target header" : "Select target header",
|
||||
"Move up" : "Move up",
|
||||
"Move down" : "Move down",
|
||||
"Management dashboard" : "Management dashboard",
|
||||
"Overview of forum activity and statistics" : "Overview of forum activity and statistics",
|
||||
"Loading statistics …" : "Loading statistics …",
|
||||
"Error loading dashboard" : "Error loading dashboard",
|
||||
@@ -474,9 +492,21 @@ OC.L10N.register(
|
||||
"Manage who can access the forum" : "Manage who can access the forum",
|
||||
"Allow guest access" : "Allow guest access",
|
||||
"When enabled, unauthenticated users can view forum content in read-only mode" : "When enabled, unauthenticated users can view forum content in read-only mode",
|
||||
"Control who can view the edit history of posts" : "Control who can view the edit history of posts",
|
||||
"Allow all accounts to view edit history" : "Allow all accounts to view edit history",
|
||||
"When enabled, any account can view the edit history of any post. When disabled, only post owners can view their own edit history. Administration and moderators can always view edit history." : "When enabled, any account can view the edit history of any post. When disabled, only post owners can view their own edit history. Administration and moderators can always view edit history.",
|
||||
"Allow accounts to hide their own edit history" : "Allow accounts to hide their own edit history",
|
||||
"When enabled, accounts can choose to hide their edit history from other accounts in their preferences." : "When enabled, accounts can choose to hide their edit history from other accounts in their preferences.",
|
||||
"Posts" : "Posts",
|
||||
"Configure posting features" : "Configure posting features",
|
||||
"Enable signatures" : "Enable signatures",
|
||||
"When enabled, accounts can set a signature in their preferences that appears at the bottom of their posts." : "When enabled, accounts can set a signature in their preferences that appears at the bottom of their posts.",
|
||||
"Settings saved" : "Settings saved",
|
||||
"Failed to save settings" : "Failed to save settings",
|
||||
"Review and restore deleted content" : "Review and restore deleted content",
|
||||
"Deleted threads" : "Deleted threads",
|
||||
"Deleted replies" : "Deleted replies",
|
||||
"Search deleted content …" : "Search deleted content …",
|
||||
"Newest first" : "Newest first",
|
||||
"Oldest first" : "Oldest first",
|
||||
"Create role" : "Create role",
|
||||
@@ -493,12 +523,21 @@ OC.L10N.register(
|
||||
"Reset" : "Reset",
|
||||
"Role permissions" : "Role permissions",
|
||||
"Set global permissions for this role" : "Set global permissions for this role",
|
||||
"Dashboard and forum settings" : "Dashboard and forum settings",
|
||||
"Allow access to the management dashboard and forum settings" : "Allow access to the management dashboard and forum settings",
|
||||
"Account management" : "Account management",
|
||||
"Allow viewing accounts and assigning roles" : "Allow viewing accounts and assigning roles",
|
||||
"Roles and teams management" : "Roles and teams management",
|
||||
"Allow creating, editing and deleting roles and team permissions" : "Allow creating, editing and deleting roles and team permissions",
|
||||
"Category management" : "Category management",
|
||||
"Allow creating, editing and deleting categories" : "Allow creating, editing and deleting categories",
|
||||
"Allow creating, editing and deleting custom BBCodes" : "Allow creating, editing and deleting custom BBCodes",
|
||||
"Allow access to the moderation page to review and restore deleted content" : "Allow access to the moderation page to review and restore deleted content",
|
||||
"Category permissions" : "Category permissions",
|
||||
"Set which categories this role can access" : "Set which categories this role can access",
|
||||
"Admin role must have all permissions enabled" : "Admin role must have all permissions enabled",
|
||||
"Admin role has full access to all categories" : "Admin role has full access to all categories",
|
||||
"Guest role cannot have management permissions" : "Guest role cannot have management permissions",
|
||||
"Guest role cannot moderate categories" : "Guest role cannot moderate categories",
|
||||
"You can control which categories guests can view using the checkboxes below." : "You can control which categories guests can view using the checkboxes below.",
|
||||
"Guest access is currently disabled" : "Guest access is currently disabled",
|
||||
|
||||
@@ -55,8 +55,15 @@
|
||||
"Welcome to the forum!" : "Welcome to the forum!",
|
||||
"Deleted user" : "Deleted user",
|
||||
"A community-driven forum built right into your Nextcloud instance" : "A community-driven forum built right into your Nextcloud instance",
|
||||
"Create discussions, share ideas, and collaborate with your community directly in Nextcloud.\n\n**Key features:**\n- **Threaded Discussions** - Create and reply to organized discussion threads with pagination\n- **Category Organization** - Structure your forum with customizable categories, headers, colors, and drag-and-drop reordering\n- **Rich Text Formatting** - BBCode formatting with built-in and custom tags, toolbar with overflow menu\n- **File Attachments** - Attach files from your Nextcloud storage or upload via drag-and-drop\n- **Notifications** - Subscribe to threads and get notified on replies and @mentions\n- **Post Reactions** - React to posts with emoji reactions\n- **Read/Unread Tracking** - Track unread posts at thread and category level\n- **Bookmarks** - Save threads for quick access\n- **Search** - Advanced search with boolean operators and category filtering\n- **User Profiles** - View post history, statistics, and role badges\n- **Roles and Teams** - Fine-grained permissions per role or Nextcloud Team, per category\n- **Guest Access** - Optional public access for unauthenticated visitors with configurable permissions\n- **Edit History** - View post revision history with configurable visibility and per-account privacy controls\n- **Reusable Templates** - Save and insert frequently used content snippets\n- **Signatures** - BBCode-formatted signatures on posts\n- **Thread Drafts** - Auto-saved drafts per category\n- **Dashboard Widgets** - Recent activity, top threads, and top categories on the Nextcloud dashboard\n- **Direct Post Links** - Link directly to a specific post within a thread\n- **Moderation Tools** - Pin, lock, hide, and move threads; review and restore deleted content\n- **Management Tools** - Manage categories, roles, BBCodes, and forum settings with granular permissions\n- **Server Administration** - Repair seeds, rebuild statistics, and assign roles from the Nextcloud admin panel\n\n**Perfect for:**\n- Team discussions and collaboration\n- Community forums\n- Support channels\n- Knowledge bases\n- Project discussions\n- Internal communication\n\nThe forum integrates seamlessly with your Nextcloud instance, using your existing accounts and teams for authentication and access control." : "Create discussions, share ideas, and collaborate with your community directly in Nextcloud.\n\n**Key features:**\n- **Threaded Discussions** - Create and reply to organized discussion threads with pagination\n- **Category Organization** - Structure your forum with customizable categories, headers, colors, and drag-and-drop reordering\n- **Rich Text Formatting** - BBCode formatting with built-in and custom tags, toolbar with overflow menu\n- **File Attachments** - Attach files from your Nextcloud storage or upload via drag-and-drop\n- **Notifications** - Subscribe to threads and get notified on replies and @mentions\n- **Post Reactions** - React to posts with emoji reactions\n- **Read/Unread Tracking** - Track unread posts at thread and category level\n- **Bookmarks** - Save threads for quick access\n- **Search** - Advanced search with boolean operators and category filtering\n- **User Profiles** - View post history, statistics, and role badges\n- **Roles and Teams** - Fine-grained permissions per role or Nextcloud Team, per category\n- **Guest Access** - Optional public access for unauthenticated visitors with configurable permissions\n- **Edit History** - View post revision history with configurable visibility and per-account privacy controls\n- **Reusable Templates** - Save and insert frequently used content snippets\n- **Signatures** - BBCode-formatted signatures on posts\n- **Thread Drafts** - Auto-saved drafts per category\n- **Dashboard Widgets** - Recent activity, top threads, and top categories on the Nextcloud dashboard\n- **Direct Post Links** - Link directly to a specific post within a thread\n- **Moderation Tools** - Pin, lock, hide, and move threads; review and restore deleted content\n- **Management Tools** - Manage categories, roles, BBCodes, and forum settings with granular permissions\n- **Server Administration** - Repair seeds, rebuild statistics, and assign roles from the Nextcloud admin panel\n\n**Perfect for:**\n- Team discussions and collaboration\n- Community forums\n- Support channels\n- Knowledge bases\n- Project discussions\n- Internal communication\n\nThe forum integrates seamlessly with your Nextcloud instance, using your existing accounts and teams for authentication and access control.",
|
||||
"Forum server administration" : "Forum server administration",
|
||||
"Database Initial Data" : "Database Initial Data",
|
||||
"Restore default forum data (roles, categories, permissions, BBCodes). This is safe to run multiple times as it will skip data that already exists." : "Restore default forum data (roles, categories, permissions, BBCodes). This is safe to run multiple times as it will skip data that already exists.",
|
||||
"Repair Database Initial Data" : "Repair Database Initial Data",
|
||||
"Rebuild Statistics" : "Rebuild Statistics",
|
||||
"Recalculate all forum statistics including account post counts, thread counts, and category counters. Use this if statistics appear incorrect or out of sync." : "Recalculate all forum statistics including account post counts, thread counts, and category counters. Use this if statistics appear incorrect or out of sync.",
|
||||
"User Roles" : "User Roles",
|
||||
"Assign forum roles to accounts. This allows you to grant administrative or moderator privileges to specific accounts." : "Assign forum roles to accounts. This allows you to grant administrative or moderator privileges to specific accounts.",
|
||||
"User ID" : "User ID",
|
||||
"Enter user ID" : "Enter user ID",
|
||||
"Role" : "Role",
|
||||
@@ -68,6 +75,7 @@
|
||||
"Home" : "Home",
|
||||
"Bookmarks" : "Bookmarks",
|
||||
"User preferences" : "User preferences",
|
||||
"Management" : "Management",
|
||||
"Dashboard" : "Dashboard",
|
||||
"Forum settings" : "Forum settings",
|
||||
"Users" : "Users",
|
||||
@@ -159,8 +167,14 @@
|
||||
"The forum has not been set up yet. Please contact an administration member to complete the setup." : "The forum has not been set up yet. Please contact an administration member to complete the setup.",
|
||||
"Deleted" : "Deleted",
|
||||
"Restore" : "Restore",
|
||||
"Error loading content" : "Error loading content",
|
||||
"Retry" : "Retry",
|
||||
"No deleted content" : "No deleted content",
|
||||
"There is no deleted content to review." : "There is no deleted content to review.",
|
||||
"Deleted reply" : "Deleted reply",
|
||||
"In thread" : "In thread",
|
||||
"Restore reply" : "Restore reply",
|
||||
"Restore thread" : "Restore thread",
|
||||
"Move thread to category" : "Move thread to category",
|
||||
"Select the category to move this thread to:" : "Select the category to move this thread to:",
|
||||
"Select a category …" : "Select a category …",
|
||||
@@ -363,6 +377,9 @@
|
||||
"You can use BBCode formatting in your signature" : "You can use BBCode formatting in your signature",
|
||||
"Enter your signature …" : "Enter your signature …",
|
||||
"Privacy" : "Privacy",
|
||||
"Control the visibility of your activity" : "Control the visibility of your activity",
|
||||
"Hide my edit history from other accounts" : "Hide my edit history from other accounts",
|
||||
"When enabled, other accounts cannot view the edit history of your posts. Administration and moderators can always view edit history." : "When enabled, other accounts cannot view the edit history of your posts. Administration and moderators can always view edit history.",
|
||||
"Failed to save preferences" : "Failed to save preferences",
|
||||
"Select upload directory" : "Select upload directory",
|
||||
"BBCode management" : "BBCode management",
|
||||
@@ -445,6 +462,7 @@
|
||||
"Select target header" : "Select target header",
|
||||
"Move up" : "Move up",
|
||||
"Move down" : "Move down",
|
||||
"Management dashboard" : "Management dashboard",
|
||||
"Overview of forum activity and statistics" : "Overview of forum activity and statistics",
|
||||
"Loading statistics …" : "Loading statistics …",
|
||||
"Error loading dashboard" : "Error loading dashboard",
|
||||
@@ -472,9 +490,21 @@
|
||||
"Manage who can access the forum" : "Manage who can access the forum",
|
||||
"Allow guest access" : "Allow guest access",
|
||||
"When enabled, unauthenticated users can view forum content in read-only mode" : "When enabled, unauthenticated users can view forum content in read-only mode",
|
||||
"Control who can view the edit history of posts" : "Control who can view the edit history of posts",
|
||||
"Allow all accounts to view edit history" : "Allow all accounts to view edit history",
|
||||
"When enabled, any account can view the edit history of any post. When disabled, only post owners can view their own edit history. Administration and moderators can always view edit history." : "When enabled, any account can view the edit history of any post. When disabled, only post owners can view their own edit history. Administration and moderators can always view edit history.",
|
||||
"Allow accounts to hide their own edit history" : "Allow accounts to hide their own edit history",
|
||||
"When enabled, accounts can choose to hide their edit history from other accounts in their preferences." : "When enabled, accounts can choose to hide their edit history from other accounts in their preferences.",
|
||||
"Posts" : "Posts",
|
||||
"Configure posting features" : "Configure posting features",
|
||||
"Enable signatures" : "Enable signatures",
|
||||
"When enabled, accounts can set a signature in their preferences that appears at the bottom of their posts." : "When enabled, accounts can set a signature in their preferences that appears at the bottom of their posts.",
|
||||
"Settings saved" : "Settings saved",
|
||||
"Failed to save settings" : "Failed to save settings",
|
||||
"Review and restore deleted content" : "Review and restore deleted content",
|
||||
"Deleted threads" : "Deleted threads",
|
||||
"Deleted replies" : "Deleted replies",
|
||||
"Search deleted content …" : "Search deleted content …",
|
||||
"Newest first" : "Newest first",
|
||||
"Oldest first" : "Oldest first",
|
||||
"Create role" : "Create role",
|
||||
@@ -491,12 +521,21 @@
|
||||
"Reset" : "Reset",
|
||||
"Role permissions" : "Role permissions",
|
||||
"Set global permissions for this role" : "Set global permissions for this role",
|
||||
"Dashboard and forum settings" : "Dashboard and forum settings",
|
||||
"Allow access to the management dashboard and forum settings" : "Allow access to the management dashboard and forum settings",
|
||||
"Account management" : "Account management",
|
||||
"Allow viewing accounts and assigning roles" : "Allow viewing accounts and assigning roles",
|
||||
"Roles and teams management" : "Roles and teams management",
|
||||
"Allow creating, editing and deleting roles and team permissions" : "Allow creating, editing and deleting roles and team permissions",
|
||||
"Category management" : "Category management",
|
||||
"Allow creating, editing and deleting categories" : "Allow creating, editing and deleting categories",
|
||||
"Allow creating, editing and deleting custom BBCodes" : "Allow creating, editing and deleting custom BBCodes",
|
||||
"Allow access to the moderation page to review and restore deleted content" : "Allow access to the moderation page to review and restore deleted content",
|
||||
"Category permissions" : "Category permissions",
|
||||
"Set which categories this role can access" : "Set which categories this role can access",
|
||||
"Admin role must have all permissions enabled" : "Admin role must have all permissions enabled",
|
||||
"Admin role has full access to all categories" : "Admin role has full access to all categories",
|
||||
"Guest role cannot have management permissions" : "Guest role cannot have management permissions",
|
||||
"Guest role cannot moderate categories" : "Guest role cannot moderate categories",
|
||||
"You can control which categories guests can view using the checkboxes below." : "You can control which categories guests can view using the checkboxes below.",
|
||||
"Guest access is currently disabled" : "Guest access is currently disabled",
|
||||
|
||||
39
l10n/ga.js
39
l10n/ga.js
File diff suppressed because one or more lines are too long
39
l10n/ga.json
39
l10n/ga.json
File diff suppressed because one or more lines are too long
@@ -57,8 +57,15 @@ OC.L10N.register(
|
||||
"Welcome to the forum!" : "歡迎來到論壇!",
|
||||
"Deleted user" : "已刪除的用戶",
|
||||
"A community-driven forum built right into your Nextcloud instance" : "直接建置在你 Nextcloud 實例中的社群主導論壇",
|
||||
"Create discussions, share ideas, and collaborate with your community directly in Nextcloud.\n\n**Key features:**\n- **Threaded Discussions** - Create and reply to organized discussion threads with pagination\n- **Category Organization** - Structure your forum with customizable categories, headers, colors, and drag-and-drop reordering\n- **Rich Text Formatting** - BBCode formatting with built-in and custom tags, toolbar with overflow menu\n- **File Attachments** - Attach files from your Nextcloud storage or upload via drag-and-drop\n- **Notifications** - Subscribe to threads and get notified on replies and @mentions\n- **Post Reactions** - React to posts with emoji reactions\n- **Read/Unread Tracking** - Track unread posts at thread and category level\n- **Bookmarks** - Save threads for quick access\n- **Search** - Advanced search with boolean operators and category filtering\n- **User Profiles** - View post history, statistics, and role badges\n- **Roles and Teams** - Fine-grained permissions per role or Nextcloud Team, per category\n- **Guest Access** - Optional public access for unauthenticated visitors with configurable permissions\n- **Edit History** - View post revision history with configurable visibility and per-account privacy controls\n- **Reusable Templates** - Save and insert frequently used content snippets\n- **Signatures** - BBCode-formatted signatures on posts\n- **Thread Drafts** - Auto-saved drafts per category\n- **Dashboard Widgets** - Recent activity, top threads, and top categories on the Nextcloud dashboard\n- **Direct Post Links** - Link directly to a specific post within a thread\n- **Moderation Tools** - Pin, lock, hide, and move threads; review and restore deleted content\n- **Management Tools** - Manage categories, roles, BBCodes, and forum settings with granular permissions\n- **Server Administration** - Repair seeds, rebuild statistics, and assign roles from the Nextcloud admin panel\n\n**Perfect for:**\n- Team discussions and collaboration\n- Community forums\n- Support channels\n- Knowledge bases\n- Project discussions\n- Internal communication\n\nThe forum integrates seamlessly with your Nextcloud instance, using your existing accounts and teams for authentication and access control." : "建立討論、分享點子、直接在 Nextcloud 上與您的社群協作。\n\n**重要功能:**\n- **討論串** - 建立並回覆具有分頁功能的討論串\n- **分類管理** - 透過可自訂的分類、標題、顏色以及拖放重新排序功能,來規劃您的論壇結構\n- **富文字格式設定** - 支援內建與自訂標籤的 BBCode 格式化功能,以及附帶溢出選單的工具列\n- **檔案附件** - 從您的 Nextcloud 儲存空間附加檔案,或透過拖放上傳\n- **通知** - 訂閱討論串,並在有人回覆或@提及時收到通知\n- **貼文反應** - 使用表情符號對貼文做出反應\n- **已讀/未讀追蹤** - 在討論串與分類層級追蹤未讀文章\n- **書籤** - 儲存討論串以供快速存取\n- **搜尋** - 使用布林運算子與分類篩選功能進行進階搜尋\n- **使用者個人資料** - 檢視貼文歷史紀錄、統計資料與角色徽章\n- **角色與團隊** - 依據角色或 Nextcloud 團隊、以及各分類進行細粒度權限設定\n- **訪客存取** - 選擇性公開存取功能,適用於未經身份驗證的訪客,並可自訂權限\n- **編輯歷史紀錄** - 檢視文章修訂歷史紀錄,並可自訂能見度及針對每個帳號的隱私權控管\n- **可重複使用的範本** - 儲存並插入常用內容片段\n- **簽名** - 貼文中使用 BBCode 格式的簽名\n- **討論串草稿** - 根據分類自動儲存草稿\n- **儀表板小工具** - Nextcloud 儀表板上的近期活動、熱門討論串與熱門分類\n- **直接貼文連結** - 直接連結至討論串中的特定貼文\n- **審核工具** - 釘選、鎖定、隱藏、移動討論串,審閱與還原刪除的內容\n- **管理工具** - 使用細粒度權限管理分類、角色、BBCode、論壇設定\n- **伺服器管理** - 從 Nextcloud 管理面板修復種子、重建統計資料、指派角色\n\n**適用於:**\n- 團隊討論與協作\n- 社群論壇\n- 支援管道\n- 知識庫\n- 專案討論\n- 內部溝通\n\n此論壇能與您的 Nextcloud 站台無縫整合,並利用您現有的帳號與團隊進行驗證與存取控制。",
|
||||
"Forum server administration" : "論壇伺服器管理",
|
||||
"Database Initial Data" : "資料庫初始資料",
|
||||
"Restore default forum data (roles, categories, permissions, BBCodes). This is safe to run multiple times as it will skip data that already exists." : "還原論壇預設資料(角色、分類、權限、BBCode)。此操作可安全地重複執行,因為系統會跳過已存在的資料。",
|
||||
"Repair Database Initial Data" : "修復資料庫初始資料",
|
||||
"Rebuild Statistics" : "重建統計資料",
|
||||
"Recalculate all forum statistics including account post counts, thread counts, and category counters. Use this if statistics appear incorrect or out of sync." : "重新計算所有論壇統計資料,包括帳號發文數、討論串數及分類計數器。若統計資料顯示不正確或未同步,請使用此功能。",
|
||||
"User Roles" : "用戶角色",
|
||||
"Assign forum roles to accounts. This allows you to grant administrative or moderator privileges to specific accounts." : "為帳號指派論壇角色。此功能可讓您授予特定帳號管理員或版主權限。",
|
||||
"User ID" : "用戶 ID",
|
||||
"Enter user ID" : "輸入用戶 ID",
|
||||
"Role" : "角色",
|
||||
@@ -70,6 +77,7 @@ OC.L10N.register(
|
||||
"Home" : "主頁",
|
||||
"Bookmarks" : "書籤",
|
||||
"User preferences" : "用戶偏愛設定",
|
||||
"Management" : "管理",
|
||||
"Dashboard" : "儀表板",
|
||||
"Forum settings" : "論壇設定",
|
||||
"Users" : "用戶",
|
||||
@@ -161,8 +169,14 @@ OC.L10N.register(
|
||||
"The forum has not been set up yet. Please contact an administration member to complete the setup." : "論壇尚未設定完成。請聯絡管理員以完成設定。",
|
||||
"Deleted" : "已刪除",
|
||||
"Restore" : "還原",
|
||||
"Error loading content" : "載入內容時發生錯誤",
|
||||
"Retry" : "重試",
|
||||
"No deleted content" : "沒有已刪除的內容",
|
||||
"There is no deleted content to review." : "沒有待審閱的已刪除內容。",
|
||||
"Deleted reply" : "已刪除的回覆",
|
||||
"In thread" : "所在主題",
|
||||
"Restore reply" : "還原回覆",
|
||||
"Restore thread" : "還原討論串",
|
||||
"Move thread to category" : "將討論串移至分類",
|
||||
"Select the category to move this thread to:" : "選擇要將此討論串移至的分類:",
|
||||
"Select a category …" : "選擇分類…",
|
||||
@@ -365,6 +379,9 @@ OC.L10N.register(
|
||||
"You can use BBCode formatting in your signature" : "您可以使用 BBCode 格式化您的簽名",
|
||||
"Enter your signature …" : "輸入您的簽名 …",
|
||||
"Privacy" : "私隱",
|
||||
"Control the visibility of your activity" : "控制您活動的能見度",
|
||||
"Hide my edit history from other accounts" : "對其他帳號隱藏我的編輯歷史紀錄",
|
||||
"When enabled, other accounts cannot view the edit history of your posts. Administration and moderators can always view edit history." : "啟用時,其他帳號無法檢視您貼文的編輯歷史紀錄。管理員與版主總是能檢視編輯歷史紀錄。",
|
||||
"Failed to save preferences" : "儲存偏好設定失敗",
|
||||
"Select upload directory" : "選擇上載目錄",
|
||||
"BBCode management" : "BBCode 管理",
|
||||
@@ -447,6 +464,7 @@ OC.L10N.register(
|
||||
"Select target header" : "選擇目標標題列",
|
||||
"Move up" : "向上移動",
|
||||
"Move down" : "向下移動",
|
||||
"Management dashboard" : "管理儀表板",
|
||||
"Overview of forum activity and statistics" : "檢視論壇活動與統計總覽",
|
||||
"Loading statistics …" : "正在載入統計資料 …",
|
||||
"Error loading dashboard" : "載入控制台時發生錯誤",
|
||||
@@ -474,9 +492,21 @@ OC.L10N.register(
|
||||
"Manage who can access the forum" : "管理哪些人可以存取論壇。",
|
||||
"Allow guest access" : "允許訪客存取",
|
||||
"When enabled, unauthenticated users can view forum content in read-only mode" : "啟用後,未登入用戶亦可在唯讀模式下檢視論壇內容。",
|
||||
"Control who can view the edit history of posts" : "控制誰可以檢視貼文的編輯歷史紀錄",
|
||||
"Allow all accounts to view edit history" : "允許所有帳號檢視編輯歷史紀錄",
|
||||
"When enabled, any account can view the edit history of any post. When disabled, only post owners can view their own edit history. Administration and moderators can always view edit history." : "啟用時,任何帳號都能檢視任何貼文的編輯歷史紀錄。停用時,僅貼文擁有者可以檢視他們自己的編輯歷史紀錄。管理員與版主總是可以檢視編輯歷史紀錄。",
|
||||
"Allow accounts to hide their own edit history" : "允許帳號隱藏他們的編輯歷史紀錄",
|
||||
"When enabled, accounts can choose to hide their edit history from other accounts in their preferences." : "啟用時,帳號可以在偏好設定中選擇對其他帳號隱藏他們的編輯歷史紀錄。",
|
||||
"Posts" : "帖文",
|
||||
"Configure posting features" : "設定貼文功能",
|
||||
"Enable signatures" : "啟用簽名",
|
||||
"When enabled, accounts can set a signature in their preferences that appears at the bottom of their posts." : "啟用時,帳號可以在他們的偏好設定中設定簽名,簽名會出現在他們貼文的底部。",
|
||||
"Settings saved" : "設定已保存",
|
||||
"Failed to save settings" : "設定儲存失敗",
|
||||
"Review and restore deleted content" : "審閱並還原已刪除的內容",
|
||||
"Deleted threads" : "已刪除的討論串",
|
||||
"Deleted replies" : "已刪除的回覆",
|
||||
"Search deleted content …" : "搜尋已刪除的內容……",
|
||||
"Newest first" : "最新先",
|
||||
"Oldest first" : "最舊先",
|
||||
"Create role" : "建立角色",
|
||||
@@ -493,12 +523,21 @@ OC.L10N.register(
|
||||
"Reset" : "重設",
|
||||
"Role permissions" : "角色權限",
|
||||
"Set global permissions for this role" : "設定此角色的全域權限。",
|
||||
"Dashboard and forum settings" : "儀表板與論壇設定",
|
||||
"Allow access to the management dashboard and forum settings" : "允許存取管理儀表板與論壇設定",
|
||||
"Account management" : "帳戶管理",
|
||||
"Allow viewing accounts and assigning roles" : "允許檢視帳號與指派角色",
|
||||
"Roles and teams management" : "角色與團隊管理",
|
||||
"Allow creating, editing and deleting roles and team permissions" : "允許建立、編輯與刪除角色及團隊權限",
|
||||
"Category management" : "分類管理",
|
||||
"Allow creating, editing and deleting categories" : "允許建立、編輯及刪除分類。",
|
||||
"Allow creating, editing and deleting custom BBCodes" : "允許建立、編輯與刪除自訂 BBCode",
|
||||
"Allow access to the moderation page to review and restore deleted content" : "允許存取審核頁面以審閱並還原已刪除的內容",
|
||||
"Category permissions" : "分類權限",
|
||||
"Set which categories this role can access" : "設定此角色可存取哪些分類。",
|
||||
"Admin role must have all permissions enabled" : "管理員角色必須啟用所有權限。",
|
||||
"Admin role has full access to all categories" : "管理員角色對所有分類擁有完整存取權。",
|
||||
"Guest role cannot have management permissions" : "訪客角色不能擁有管理權限",
|
||||
"Guest role cannot moderate categories" : "訪客角色不能管理分類。",
|
||||
"You can control which categories guests can view using the checkboxes below." : "你可使用下方的核取方格控制訪客能查看哪些分類。",
|
||||
"Guest access is currently disabled" : "目前已停用訪客存取。",
|
||||
|
||||
@@ -55,8 +55,15 @@
|
||||
"Welcome to the forum!" : "歡迎來到論壇!",
|
||||
"Deleted user" : "已刪除的用戶",
|
||||
"A community-driven forum built right into your Nextcloud instance" : "直接建置在你 Nextcloud 實例中的社群主導論壇",
|
||||
"Create discussions, share ideas, and collaborate with your community directly in Nextcloud.\n\n**Key features:**\n- **Threaded Discussions** - Create and reply to organized discussion threads with pagination\n- **Category Organization** - Structure your forum with customizable categories, headers, colors, and drag-and-drop reordering\n- **Rich Text Formatting** - BBCode formatting with built-in and custom tags, toolbar with overflow menu\n- **File Attachments** - Attach files from your Nextcloud storage or upload via drag-and-drop\n- **Notifications** - Subscribe to threads and get notified on replies and @mentions\n- **Post Reactions** - React to posts with emoji reactions\n- **Read/Unread Tracking** - Track unread posts at thread and category level\n- **Bookmarks** - Save threads for quick access\n- **Search** - Advanced search with boolean operators and category filtering\n- **User Profiles** - View post history, statistics, and role badges\n- **Roles and Teams** - Fine-grained permissions per role or Nextcloud Team, per category\n- **Guest Access** - Optional public access for unauthenticated visitors with configurable permissions\n- **Edit History** - View post revision history with configurable visibility and per-account privacy controls\n- **Reusable Templates** - Save and insert frequently used content snippets\n- **Signatures** - BBCode-formatted signatures on posts\n- **Thread Drafts** - Auto-saved drafts per category\n- **Dashboard Widgets** - Recent activity, top threads, and top categories on the Nextcloud dashboard\n- **Direct Post Links** - Link directly to a specific post within a thread\n- **Moderation Tools** - Pin, lock, hide, and move threads; review and restore deleted content\n- **Management Tools** - Manage categories, roles, BBCodes, and forum settings with granular permissions\n- **Server Administration** - Repair seeds, rebuild statistics, and assign roles from the Nextcloud admin panel\n\n**Perfect for:**\n- Team discussions and collaboration\n- Community forums\n- Support channels\n- Knowledge bases\n- Project discussions\n- Internal communication\n\nThe forum integrates seamlessly with your Nextcloud instance, using your existing accounts and teams for authentication and access control." : "建立討論、分享點子、直接在 Nextcloud 上與您的社群協作。\n\n**重要功能:**\n- **討論串** - 建立並回覆具有分頁功能的討論串\n- **分類管理** - 透過可自訂的分類、標題、顏色以及拖放重新排序功能,來規劃您的論壇結構\n- **富文字格式設定** - 支援內建與自訂標籤的 BBCode 格式化功能,以及附帶溢出選單的工具列\n- **檔案附件** - 從您的 Nextcloud 儲存空間附加檔案,或透過拖放上傳\n- **通知** - 訂閱討論串,並在有人回覆或@提及時收到通知\n- **貼文反應** - 使用表情符號對貼文做出反應\n- **已讀/未讀追蹤** - 在討論串與分類層級追蹤未讀文章\n- **書籤** - 儲存討論串以供快速存取\n- **搜尋** - 使用布林運算子與分類篩選功能進行進階搜尋\n- **使用者個人資料** - 檢視貼文歷史紀錄、統計資料與角色徽章\n- **角色與團隊** - 依據角色或 Nextcloud 團隊、以及各分類進行細粒度權限設定\n- **訪客存取** - 選擇性公開存取功能,適用於未經身份驗證的訪客,並可自訂權限\n- **編輯歷史紀錄** - 檢視文章修訂歷史紀錄,並可自訂能見度及針對每個帳號的隱私權控管\n- **可重複使用的範本** - 儲存並插入常用內容片段\n- **簽名** - 貼文中使用 BBCode 格式的簽名\n- **討論串草稿** - 根據分類自動儲存草稿\n- **儀表板小工具** - Nextcloud 儀表板上的近期活動、熱門討論串與熱門分類\n- **直接貼文連結** - 直接連結至討論串中的特定貼文\n- **審核工具** - 釘選、鎖定、隱藏、移動討論串,審閱與還原刪除的內容\n- **管理工具** - 使用細粒度權限管理分類、角色、BBCode、論壇設定\n- **伺服器管理** - 從 Nextcloud 管理面板修復種子、重建統計資料、指派角色\n\n**適用於:**\n- 團隊討論與協作\n- 社群論壇\n- 支援管道\n- 知識庫\n- 專案討論\n- 內部溝通\n\n此論壇能與您的 Nextcloud 站台無縫整合,並利用您現有的帳號與團隊進行驗證與存取控制。",
|
||||
"Forum server administration" : "論壇伺服器管理",
|
||||
"Database Initial Data" : "資料庫初始資料",
|
||||
"Restore default forum data (roles, categories, permissions, BBCodes). This is safe to run multiple times as it will skip data that already exists." : "還原論壇預設資料(角色、分類、權限、BBCode)。此操作可安全地重複執行,因為系統會跳過已存在的資料。",
|
||||
"Repair Database Initial Data" : "修復資料庫初始資料",
|
||||
"Rebuild Statistics" : "重建統計資料",
|
||||
"Recalculate all forum statistics including account post counts, thread counts, and category counters. Use this if statistics appear incorrect or out of sync." : "重新計算所有論壇統計資料,包括帳號發文數、討論串數及分類計數器。若統計資料顯示不正確或未同步,請使用此功能。",
|
||||
"User Roles" : "用戶角色",
|
||||
"Assign forum roles to accounts. This allows you to grant administrative or moderator privileges to specific accounts." : "為帳號指派論壇角色。此功能可讓您授予特定帳號管理員或版主權限。",
|
||||
"User ID" : "用戶 ID",
|
||||
"Enter user ID" : "輸入用戶 ID",
|
||||
"Role" : "角色",
|
||||
@@ -68,6 +75,7 @@
|
||||
"Home" : "主頁",
|
||||
"Bookmarks" : "書籤",
|
||||
"User preferences" : "用戶偏愛設定",
|
||||
"Management" : "管理",
|
||||
"Dashboard" : "儀表板",
|
||||
"Forum settings" : "論壇設定",
|
||||
"Users" : "用戶",
|
||||
@@ -159,8 +167,14 @@
|
||||
"The forum has not been set up yet. Please contact an administration member to complete the setup." : "論壇尚未設定完成。請聯絡管理員以完成設定。",
|
||||
"Deleted" : "已刪除",
|
||||
"Restore" : "還原",
|
||||
"Error loading content" : "載入內容時發生錯誤",
|
||||
"Retry" : "重試",
|
||||
"No deleted content" : "沒有已刪除的內容",
|
||||
"There is no deleted content to review." : "沒有待審閱的已刪除內容。",
|
||||
"Deleted reply" : "已刪除的回覆",
|
||||
"In thread" : "所在主題",
|
||||
"Restore reply" : "還原回覆",
|
||||
"Restore thread" : "還原討論串",
|
||||
"Move thread to category" : "將討論串移至分類",
|
||||
"Select the category to move this thread to:" : "選擇要將此討論串移至的分類:",
|
||||
"Select a category …" : "選擇分類…",
|
||||
@@ -363,6 +377,9 @@
|
||||
"You can use BBCode formatting in your signature" : "您可以使用 BBCode 格式化您的簽名",
|
||||
"Enter your signature …" : "輸入您的簽名 …",
|
||||
"Privacy" : "私隱",
|
||||
"Control the visibility of your activity" : "控制您活動的能見度",
|
||||
"Hide my edit history from other accounts" : "對其他帳號隱藏我的編輯歷史紀錄",
|
||||
"When enabled, other accounts cannot view the edit history of your posts. Administration and moderators can always view edit history." : "啟用時,其他帳號無法檢視您貼文的編輯歷史紀錄。管理員與版主總是能檢視編輯歷史紀錄。",
|
||||
"Failed to save preferences" : "儲存偏好設定失敗",
|
||||
"Select upload directory" : "選擇上載目錄",
|
||||
"BBCode management" : "BBCode 管理",
|
||||
@@ -445,6 +462,7 @@
|
||||
"Select target header" : "選擇目標標題列",
|
||||
"Move up" : "向上移動",
|
||||
"Move down" : "向下移動",
|
||||
"Management dashboard" : "管理儀表板",
|
||||
"Overview of forum activity and statistics" : "檢視論壇活動與統計總覽",
|
||||
"Loading statistics …" : "正在載入統計資料 …",
|
||||
"Error loading dashboard" : "載入控制台時發生錯誤",
|
||||
@@ -472,9 +490,21 @@
|
||||
"Manage who can access the forum" : "管理哪些人可以存取論壇。",
|
||||
"Allow guest access" : "允許訪客存取",
|
||||
"When enabled, unauthenticated users can view forum content in read-only mode" : "啟用後,未登入用戶亦可在唯讀模式下檢視論壇內容。",
|
||||
"Control who can view the edit history of posts" : "控制誰可以檢視貼文的編輯歷史紀錄",
|
||||
"Allow all accounts to view edit history" : "允許所有帳號檢視編輯歷史紀錄",
|
||||
"When enabled, any account can view the edit history of any post. When disabled, only post owners can view their own edit history. Administration and moderators can always view edit history." : "啟用時,任何帳號都能檢視任何貼文的編輯歷史紀錄。停用時,僅貼文擁有者可以檢視他們自己的編輯歷史紀錄。管理員與版主總是可以檢視編輯歷史紀錄。",
|
||||
"Allow accounts to hide their own edit history" : "允許帳號隱藏他們的編輯歷史紀錄",
|
||||
"When enabled, accounts can choose to hide their edit history from other accounts in their preferences." : "啟用時,帳號可以在偏好設定中選擇對其他帳號隱藏他們的編輯歷史紀錄。",
|
||||
"Posts" : "帖文",
|
||||
"Configure posting features" : "設定貼文功能",
|
||||
"Enable signatures" : "啟用簽名",
|
||||
"When enabled, accounts can set a signature in their preferences that appears at the bottom of their posts." : "啟用時,帳號可以在他們的偏好設定中設定簽名,簽名會出現在他們貼文的底部。",
|
||||
"Settings saved" : "設定已保存",
|
||||
"Failed to save settings" : "設定儲存失敗",
|
||||
"Review and restore deleted content" : "審閱並還原已刪除的內容",
|
||||
"Deleted threads" : "已刪除的討論串",
|
||||
"Deleted replies" : "已刪除的回覆",
|
||||
"Search deleted content …" : "搜尋已刪除的內容……",
|
||||
"Newest first" : "最新先",
|
||||
"Oldest first" : "最舊先",
|
||||
"Create role" : "建立角色",
|
||||
@@ -491,12 +521,21 @@
|
||||
"Reset" : "重設",
|
||||
"Role permissions" : "角色權限",
|
||||
"Set global permissions for this role" : "設定此角色的全域權限。",
|
||||
"Dashboard and forum settings" : "儀表板與論壇設定",
|
||||
"Allow access to the management dashboard and forum settings" : "允許存取管理儀表板與論壇設定",
|
||||
"Account management" : "帳戶管理",
|
||||
"Allow viewing accounts and assigning roles" : "允許檢視帳號與指派角色",
|
||||
"Roles and teams management" : "角色與團隊管理",
|
||||
"Allow creating, editing and deleting roles and team permissions" : "允許建立、編輯與刪除角色及團隊權限",
|
||||
"Category management" : "分類管理",
|
||||
"Allow creating, editing and deleting categories" : "允許建立、編輯及刪除分類。",
|
||||
"Allow creating, editing and deleting custom BBCodes" : "允許建立、編輯與刪除自訂 BBCode",
|
||||
"Allow access to the moderation page to review and restore deleted content" : "允許存取審核頁面以審閱並還原已刪除的內容",
|
||||
"Category permissions" : "分類權限",
|
||||
"Set which categories this role can access" : "設定此角色可存取哪些分類。",
|
||||
"Admin role must have all permissions enabled" : "管理員角色必須啟用所有權限。",
|
||||
"Admin role has full access to all categories" : "管理員角色對所有分類擁有完整存取權。",
|
||||
"Guest role cannot have management permissions" : "訪客角色不能擁有管理權限",
|
||||
"Guest role cannot moderate categories" : "訪客角色不能管理分類。",
|
||||
"You can control which categories guests can view using the checkboxes below." : "你可使用下方的核取方格控制訪客能查看哪些分類。",
|
||||
"Guest access is currently disabled" : "目前已停用訪客存取。",
|
||||
|
||||
@@ -68,20 +68,16 @@ class BBCodeService {
|
||||
}, $content);
|
||||
}
|
||||
|
||||
// Preprocess [youtube] tags — the builtin handler generates malformed HTML
|
||||
$youtubePlaceholders = [];
|
||||
$content = preg_replace_callback('/\[youtube\](.*?)\[\/youtube\]/s', function ($matches) use (&$youtubePlaceholders) {
|
||||
$placeholder = '___YOUTUBE_' . count($youtubePlaceholders) . '___';
|
||||
$videoId = htmlspecialchars(trim($matches[1]), ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$youtubePlaceholders[$placeholder] = '<div class="embed-video">'
|
||||
. '<iframe class="youtube-player" width="560" height="315"'
|
||||
. ' src="https://www.youtube.com/embed/' . $videoId . '"'
|
||||
. ' title="YouTube video player" frameborder="0"'
|
||||
. ' allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"'
|
||||
. ' referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>'
|
||||
. '</div>';
|
||||
return $placeholder;
|
||||
}, $content);
|
||||
// Preprocess builtin tag overrides (tags whose library rendering we replace)
|
||||
$builtinOverridePlaceholders = [];
|
||||
foreach ($this->getBuiltinOverrides() as $tag => $renderer) {
|
||||
$pattern = '/\[' . preg_quote($tag, '/') . '\](.*?)\[\/' . preg_quote($tag, '/') . '\]/s';
|
||||
$content = preg_replace_callback($pattern, function ($matches) use (&$builtinOverridePlaceholders, $renderer) {
|
||||
$placeholder = '___BUILTIN_OVERRIDE_' . count($builtinOverridePlaceholders) . '___';
|
||||
$builtinOverridePlaceholders[$placeholder] = $renderer(trim($matches[1]));
|
||||
return $placeholder;
|
||||
}, $content);
|
||||
}
|
||||
|
||||
// Preprocess [code] blocks to prevent nl2br and trim whitespace
|
||||
// The built-in [code] tag wraps content in <pre><code>, so we don't want <br/> tags inside
|
||||
@@ -191,8 +187,8 @@ class BBCodeService {
|
||||
$html = str_replace($placeholder, $replacement, $html);
|
||||
}
|
||||
|
||||
// Replace YouTube placeholders
|
||||
foreach ($youtubePlaceholders as $placeholder => $replacement) {
|
||||
// Replace builtin override placeholders
|
||||
foreach ($builtinOverridePlaceholders as $placeholder => $replacement) {
|
||||
$html = str_replace($placeholder, $replacement, $html);
|
||||
}
|
||||
|
||||
@@ -245,8 +241,10 @@ class BBCodeService {
|
||||
// Create a new parser instance each time to ensure fresh state
|
||||
$parser = new BBCodeParser();
|
||||
|
||||
// Ignore the builtin youtube tag — we handle it in preprocessing
|
||||
$parser->ignoreTag('youtube');
|
||||
// Ignore builtin tags that we override in preprocessing
|
||||
foreach (array_keys($this->getBuiltinOverrides()) as $tag) {
|
||||
$parser->ignoreTag($tag);
|
||||
}
|
||||
|
||||
// Register custom BBCodes from database
|
||||
foreach ($bbCodes as $bbCode) {
|
||||
@@ -387,7 +385,6 @@ class BBCodeService {
|
||||
* @return string The rendered HTML for the attachment
|
||||
*/
|
||||
private function renderAttachment(string $filePath, ?string $authorId, ?int $postId): string {
|
||||
// Trim whitespace from file path
|
||||
$filePath = trim($filePath);
|
||||
|
||||
if (empty($filePath)) {
|
||||
@@ -395,111 +392,52 @@ class BBCodeService {
|
||||
return '<span class="attachment-error">Invalid attachment</span>';
|
||||
}
|
||||
|
||||
// If no author ID provided, we can't verify ownership
|
||||
if (empty($authorId)) {
|
||||
$this->logger->warning('Attachment rendering attempted without author ID: ' . $filePath);
|
||||
return '<span class="attachment-error">Attachment unavailable</span>';
|
||||
}
|
||||
|
||||
// If no post ID provided, we can't generate proxy URLs
|
||||
if (empty($postId)) {
|
||||
$this->logger->warning('Attachment rendering attempted without post ID: ' . $filePath);
|
||||
return '<span class="attachment-error">Attachment unavailable</span>';
|
||||
}
|
||||
|
||||
try {
|
||||
// Get the user's folder
|
||||
$userFolder = $this->rootFolder->getUserFolder($authorId);
|
||||
|
||||
$this->logger->debug('Attempting to load attachment', [
|
||||
'filePath' => $filePath,
|
||||
'authorId' => $authorId,
|
||||
]);
|
||||
|
||||
// Get the file - path is relative to user's home directory
|
||||
$file = $userFolder->get($filePath);
|
||||
|
||||
// Verify it's actually a file (not a folder)
|
||||
if (!($file instanceof \OCP\Files\File)) {
|
||||
$this->logger->warning('Attachment path is not a file: ' . $filePath);
|
||||
return '<span class="attachment-error">Invalid attachment</span>';
|
||||
}
|
||||
|
||||
// Get file metadata
|
||||
$fileName = $file->getName();
|
||||
$mimeType = $file->getMimeType();
|
||||
$fileSize = $file->getSize();
|
||||
$fileId = $file->getId();
|
||||
$mimeCategory = explode('/', $mimeType)[0];
|
||||
|
||||
// Check if it's an image
|
||||
if (str_starts_with($mimeType, 'image/')) {
|
||||
// Generate preview URL for images using proxy endpoint
|
||||
$previewUrl = $this->urlGenerator->linkToRouteAbsolute(
|
||||
// Resolve URLs and metadata once
|
||||
$ctx = [
|
||||
'fileName' => $this->esc($file->getName()),
|
||||
'mimeType' => $this->esc($mimeType),
|
||||
'downloadUrl' => $this->esc($this->urlGenerator->linkToRouteAbsolute(
|
||||
'forum.file.download',
|
||||
['postId' => $postId, 'filePath' => $filePath]
|
||||
)),
|
||||
'previewUrl' => $this->esc($this->urlGenerator->linkToRouteAbsolute(
|
||||
'forum.file.preview',
|
||||
['postId' => $postId, 'filePath' => $filePath, 'x' => 1920, 'y' => 1080]
|
||||
);
|
||||
)),
|
||||
'fileSize' => $this->formatFileSize($file->getSize()),
|
||||
'iconClass' => $this->getFileIconClass($mimeType),
|
||||
];
|
||||
|
||||
// Render as image
|
||||
$escapedFileName = htmlspecialchars($fileName, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$escapedUrl = htmlspecialchars($previewUrl, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$html = match ($mimeCategory) {
|
||||
'image' => $this->renderImageAttachment($ctx),
|
||||
'video' => $this->renderVideoAttachment($ctx),
|
||||
'audio' => $this->renderAudioAttachment($ctx),
|
||||
default => $this->renderFileAttachment($ctx),
|
||||
};
|
||||
|
||||
return sprintf(
|
||||
'<div class="attachment attachment-image"><img src="%s" alt="%s" title="%s" loading="lazy" /></div>',
|
||||
$escapedUrl,
|
||||
$escapedFileName,
|
||||
$escapedFileName
|
||||
);
|
||||
} elseif (str_starts_with($mimeType, 'video/')) {
|
||||
// Generate download URL for video (used as source)
|
||||
$videoUrl = $this->urlGenerator->linkToRouteAbsolute(
|
||||
'forum.file.download',
|
||||
['postId' => $postId, 'filePath' => $filePath]
|
||||
);
|
||||
|
||||
$escapedFileName = htmlspecialchars($fileName, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$escapedUrl = htmlspecialchars($videoUrl, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$escapedMimeType = htmlspecialchars($mimeType, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
|
||||
return sprintf(
|
||||
'<div class="attachment attachment-video">'
|
||||
. '<video controls playsinline preload="metadata" title="%s">'
|
||||
. '<source src="%s" type="%s" />'
|
||||
. '</video>'
|
||||
. '</div>',
|
||||
$escapedFileName,
|
||||
$escapedUrl,
|
||||
$escapedMimeType
|
||||
);
|
||||
} else {
|
||||
// Generate download URL for non-image files using proxy endpoint
|
||||
$downloadUrl = $this->urlGenerator->linkToRouteAbsolute(
|
||||
'forum.file.download',
|
||||
['postId' => $postId, 'filePath' => $filePath]
|
||||
);
|
||||
|
||||
// Render as file link with icon
|
||||
$escapedFileName = htmlspecialchars($fileName, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$escapedUrl = htmlspecialchars($downloadUrl, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$formattedSize = $this->formatFileSize($fileSize);
|
||||
|
||||
// Get appropriate icon for file type
|
||||
$iconClass = $this->getFileIconClass($mimeType);
|
||||
|
||||
return sprintf(
|
||||
'<div class="attachment attachment-file">'
|
||||
. '<span class="attachment-icon %s"></span>'
|
||||
. '<div class="attachment-info">'
|
||||
. '<a href="%s" class="attachment-name" download="%s">%s</a>'
|
||||
. '<span class="attachment-size">%s</span>'
|
||||
. '</div>'
|
||||
. '</div>',
|
||||
$iconClass,
|
||||
$escapedUrl,
|
||||
$escapedFileName,
|
||||
$escapedFileName,
|
||||
$formattedSize
|
||||
);
|
||||
}
|
||||
return $html;
|
||||
} catch (NotFoundException $e) {
|
||||
$this->logger->warning('Attachment file not found: ' . $filePath);
|
||||
return '<span class="attachment-error">Attachment not found</span>';
|
||||
@@ -509,6 +447,109 @@ class BBCodeService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{fileName: string, previewUrl: string} $ctx
|
||||
*/
|
||||
private function renderImageAttachment(array $ctx): string {
|
||||
return sprintf(
|
||||
'<div class="attachment attachment-image">'
|
||||
. '<img src="%s" alt="%s" title="%s" loading="lazy" />'
|
||||
. '</div>',
|
||||
$ctx['previewUrl'],
|
||||
$ctx['fileName'],
|
||||
$ctx['fileName']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{fileName: string, downloadUrl: string, mimeType: string} $ctx
|
||||
*/
|
||||
private function renderVideoAttachment(array $ctx): string {
|
||||
return sprintf(
|
||||
'<div class="attachment attachment-video">'
|
||||
. '<video controls playsinline preload="metadata" title="%s">'
|
||||
. '<source src="%s" type="%s" />'
|
||||
. '</video>'
|
||||
. '</div>',
|
||||
$ctx['fileName'],
|
||||
$ctx['downloadUrl'],
|
||||
$ctx['mimeType']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{fileName: string, downloadUrl: string, mimeType: string} $ctx
|
||||
*/
|
||||
private function renderAudioAttachment(array $ctx): string {
|
||||
return sprintf(
|
||||
'<div class="attachment attachment-audio">'
|
||||
. '<audio controls preload="metadata" title="%s">'
|
||||
. '<source src="%s" type="%s" />'
|
||||
. '</audio>'
|
||||
. '</div>',
|
||||
$ctx['fileName'],
|
||||
$ctx['downloadUrl'],
|
||||
$ctx['mimeType']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{fileName: string, downloadUrl: string, fileSize: string, iconClass: string} $ctx
|
||||
*/
|
||||
private function renderFileAttachment(array $ctx): string {
|
||||
return sprintf(
|
||||
'<div class="attachment attachment-file">'
|
||||
. '<span class="attachment-icon %s"></span>'
|
||||
. '<div class="attachment-info">'
|
||||
. '<a href="%s" class="attachment-name" download="%s">%s</a>'
|
||||
. '<span class="attachment-size">%s</span>'
|
||||
. '</div>'
|
||||
. '</div>',
|
||||
$ctx['iconClass'],
|
||||
$ctx['downloadUrl'],
|
||||
$ctx['fileName'],
|
||||
$ctx['fileName'],
|
||||
$ctx['fileSize']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML-escape a string for safe use in attributes and content
|
||||
*/
|
||||
private function esc(string $value): string {
|
||||
return htmlspecialchars($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of builtin tag names to renderer callables.
|
||||
* Each renderer receives the raw inner content and returns HTML.
|
||||
* These tags are ignored by the library parser and handled in preprocessing.
|
||||
*
|
||||
* To override another builtin tag, add an entry here — the preprocessing
|
||||
* loop and parser ignoreTag loop will pick it up automatically.
|
||||
*
|
||||
* @return array<string, \Closure(string): string>
|
||||
*/
|
||||
private function getBuiltinOverrides(): array {
|
||||
return [
|
||||
'youtube' => fn (string $content): string => $this->renderYoutubeEmbed($content),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a YouTube embed from a video ID
|
||||
*/
|
||||
private function renderYoutubeEmbed(string $videoId): string {
|
||||
$escapedId = $this->esc($videoId);
|
||||
return '<div class="embed-video">'
|
||||
. '<iframe class="youtube-player" width="560" height="315"'
|
||||
. ' src="https://www.youtube.com/embed/' . $escapedId . '"'
|
||||
. ' title="YouTube video player" frameborder="0"'
|
||||
. ' allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"'
|
||||
. ' referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>'
|
||||
. '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format file size in human-readable format
|
||||
*
|
||||
|
||||
@@ -78,6 +78,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-audio {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
|
||||
audio {
|
||||
width: 100%;
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&-file {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -284,12 +284,7 @@ class BBCodeServiceTest extends TestCase {
|
||||
}
|
||||
|
||||
public function testParseVideoAttachmentRendersVideoTag(): void {
|
||||
$bbCode = new BBCode();
|
||||
$bbCode->setTag('attachment');
|
||||
$bbCode->setReplacement('');
|
||||
$bbCode->setEnabled(true);
|
||||
$bbCode->setParseInner(false);
|
||||
$bbCode->setSpecialHandler('attachment');
|
||||
$bbCode = $this->createAttachmentBBCode();
|
||||
|
||||
$file = $this->createMock(\OCP\Files\File::class);
|
||||
$file->method('getName')->willReturn('video.mp4');
|
||||
@@ -314,12 +309,7 @@ class BBCodeServiceTest extends TestCase {
|
||||
}
|
||||
|
||||
public function testParseImageAttachmentRendersImgTag(): void {
|
||||
$bbCode = new BBCode();
|
||||
$bbCode->setTag('attachment');
|
||||
$bbCode->setReplacement('');
|
||||
$bbCode->setEnabled(true);
|
||||
$bbCode->setParseInner(false);
|
||||
$bbCode->setSpecialHandler('attachment');
|
||||
$bbCode = $this->createAttachmentBBCode();
|
||||
|
||||
$file = $this->createMock(\OCP\Files\File::class);
|
||||
$file->method('getName')->willReturn('photo.jpg');
|
||||
@@ -340,6 +330,119 @@ class BBCodeServiceTest extends TestCase {
|
||||
$this->assertStringNotContainsString('<video', $result);
|
||||
}
|
||||
|
||||
public function testParseAudioAttachmentRendersAudioTag(): void {
|
||||
$bbCode = $this->createAttachmentBBCode();
|
||||
|
||||
$file = $this->createMock(\OCP\Files\File::class);
|
||||
$file->method('getName')->willReturn('podcast.mp3');
|
||||
$file->method('getMimeType')->willReturn('audio/mpeg');
|
||||
$file->method('getSize')->willReturn(5 * 1024 * 1024);
|
||||
$file->method('getId')->willReturn(44);
|
||||
|
||||
$userFolder = $this->createMock(\OCP\Files\Folder::class);
|
||||
$userFolder->method('get')->willReturn($file);
|
||||
$this->rootFolder->method('getUserFolder')->willReturn($userFolder);
|
||||
$this->urlGenerator->method('linkToRouteAbsolute')->willReturn('https://example.com/download');
|
||||
|
||||
$content = '[attachment]Forum/podcast.mp3[/attachment]';
|
||||
$result = $this->service->parse($content, [$bbCode], 'alice', 1);
|
||||
|
||||
$this->assertStringContainsString('<audio', $result);
|
||||
$this->assertStringContainsString('controls', $result);
|
||||
$this->assertStringContainsString('<source', $result);
|
||||
$this->assertStringContainsString('type="audio/mpeg"', $result);
|
||||
$this->assertStringContainsString('class="attachment attachment-audio"', $result);
|
||||
$this->assertStringNotContainsString('<video', $result);
|
||||
$this->assertStringNotContainsString('<img', $result);
|
||||
}
|
||||
|
||||
public function testParseGenericFileAttachmentRendersDownloadLink(): void {
|
||||
$bbCode = $this->createAttachmentBBCode();
|
||||
|
||||
$file = $this->createMock(\OCP\Files\File::class);
|
||||
$file->method('getName')->willReturn('document.pdf');
|
||||
$file->method('getMimeType')->willReturn('application/pdf');
|
||||
$file->method('getSize')->willReturn(2 * 1024 * 1024);
|
||||
$file->method('getId')->willReturn(45);
|
||||
|
||||
$userFolder = $this->createMock(\OCP\Files\Folder::class);
|
||||
$userFolder->method('get')->willReturn($file);
|
||||
$this->rootFolder->method('getUserFolder')->willReturn($userFolder);
|
||||
$this->urlGenerator->method('linkToRouteAbsolute')->willReturn('https://example.com/download');
|
||||
|
||||
$content = '[attachment]Forum/document.pdf[/attachment]';
|
||||
$result = $this->service->parse($content, [$bbCode], 'alice', 1);
|
||||
|
||||
$this->assertStringContainsString('class="attachment attachment-file"', $result);
|
||||
$this->assertStringContainsString('download="document.pdf"', $result);
|
||||
$this->assertStringContainsString('attachment-size', $result);
|
||||
$this->assertStringNotContainsString('<video', $result);
|
||||
$this->assertStringNotContainsString('<audio', $result);
|
||||
$this->assertStringNotContainsString('<img', $result);
|
||||
}
|
||||
|
||||
public function testAttachmentTypeDispatchSelectsCorrectRenderer(): void {
|
||||
$bbCode = $this->createAttachmentBBCode();
|
||||
|
||||
$types = [
|
||||
['image/png', 'attachment-image', '<img'],
|
||||
['video/webm', 'attachment-video', '<video'],
|
||||
['audio/ogg', 'attachment-audio', '<audio'],
|
||||
['application/zip', 'attachment-file', 'attachment-name'],
|
||||
];
|
||||
|
||||
foreach ($types as [$mimeType, $expectedClass, $expectedElement]) {
|
||||
$file = $this->createMock(\OCP\Files\File::class);
|
||||
$file->method('getName')->willReturn('file.ext');
|
||||
$file->method('getMimeType')->willReturn($mimeType);
|
||||
$file->method('getSize')->willReturn(1024);
|
||||
$file->method('getId')->willReturn(1);
|
||||
|
||||
$userFolder = $this->createMock(\OCP\Files\Folder::class);
|
||||
$userFolder->method('get')->willReturn($file);
|
||||
|
||||
$rootFolder = $this->createMock(\OCP\Files\IRootFolder::class);
|
||||
$rootFolder->method('getUserFolder')->willReturn($userFolder);
|
||||
|
||||
$urlGenerator = $this->createMock(\OCP\IURLGenerator::class);
|
||||
$urlGenerator->method('linkToRouteAbsolute')->willReturn('https://example.com/file');
|
||||
|
||||
$service = new BBCodeService(
|
||||
$this->bbCodeMapper,
|
||||
$this->logger,
|
||||
$rootFolder,
|
||||
$urlGenerator,
|
||||
$this->userManager,
|
||||
);
|
||||
|
||||
$result = $service->parse('[attachment]test[/attachment]', [$bbCode], 'user', 1);
|
||||
|
||||
$this->assertStringContainsString($expectedClass, $result, "Failed for mime: $mimeType");
|
||||
$this->assertStringContainsString($expectedElement, $result, "Missing element for mime: $mimeType");
|
||||
}
|
||||
}
|
||||
|
||||
public function testBuiltinOverrideYoutubeReplacesBrokenLibraryOutput(): void {
|
||||
// The library generates malformed HTML for youtube — our override should produce clean output
|
||||
$content = '[youtube]testVideoId[/youtube]';
|
||||
$result = $this->service->parse($content, []);
|
||||
|
||||
// Should not contain the library's broken backslash in width attribute
|
||||
$this->assertStringNotContainsString('\\', $result);
|
||||
// Should contain our clean iframe
|
||||
$this->assertStringContainsString('www.youtube.com/embed/testVideoId', $result);
|
||||
$this->assertStringContainsString('allowfullscreen', $result);
|
||||
}
|
||||
|
||||
public function testYoutubeEmbedWithSurroundingContent(): void {
|
||||
$content = 'Check this video: [youtube]abc123[/youtube] and this text after.';
|
||||
$result = $this->service->parse($content, []);
|
||||
|
||||
$this->assertStringContainsString('Check this video:', $result);
|
||||
$this->assertStringContainsString('embed/abc123', $result);
|
||||
$this->assertStringContainsString('and this text after.', $result);
|
||||
}
|
||||
|
||||
// ── XSS injection tests ─────────────────────────────────────
|
||||
|
||||
public function testXssInBoldTagContentIsEscaped(): void {
|
||||
@@ -462,4 +565,14 @@ class BBCodeServiceTest extends TestCase {
|
||||
$bbCode->setParseInner($parseInner);
|
||||
return $bbCode;
|
||||
}
|
||||
|
||||
private function createAttachmentBBCode(): BBCode {
|
||||
$bbCode = new BBCode();
|
||||
$bbCode->setTag('attachment');
|
||||
$bbCode->setReplacement('');
|
||||
$bbCode->setEnabled(true);
|
||||
$bbCode->setParseInner(false);
|
||||
$bbCode->setSpecialHandler('attachment');
|
||||
return $bbCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.34.2
|
||||
0.35.0
|
||||
|
||||
Reference in New Issue
Block a user