feat: module-owned i18n with merge-at-boot translation loading
Each module can now ship its own i18n/ directory with translation files (default_de.json, default_en.json). At boot time, ModuleI18nLoader preloads core translations then merges module translations on top via Reflection into I18n::$strings — the t() helper stays unchanged. - Add i18nPath property to ModuleManifest - Add ModuleI18nLoader with Reflection-based preload - Extract 59 module-exclusive keys from core i18n into module files (notifications: 8, bookmarks: 41, addressbook: 10) - Expand TranslationKeysTest to scan modules/ and validate against merged core + module translations - Add ModuleI18nContractTest for per-module de/en parity and completeness Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -295,7 +295,6 @@
|
||||
"Profile image": "Profile image",
|
||||
"Profile": "Profile",
|
||||
"Profile description": "Profile description",
|
||||
"About": "About",
|
||||
"Info": "Info",
|
||||
"Search results": "Search results",
|
||||
"Result": "Result",
|
||||
@@ -470,10 +469,6 @@
|
||||
"Status & meta": "Status & meta",
|
||||
"Audit": "Audit",
|
||||
"Overview": "Overview",
|
||||
"Quick actions": "Quick actions",
|
||||
"Send email": "Send email",
|
||||
"Call phone": "Call phone",
|
||||
"Call mobile": "Call mobile",
|
||||
"Choose color": "Choose color",
|
||||
"Be careful - this resets the tenants color": "Be careful - this resets the tenant color",
|
||||
"Code": "Code",
|
||||
@@ -520,13 +515,11 @@
|
||||
"Department can not be created": "Department can not be created",
|
||||
"Department can not be updated": "Department can not be updated",
|
||||
"Delete this department?": "Delete this department?",
|
||||
"Delete this bookmark?": "Delete this bookmark?",
|
||||
"Delete department": "Delete department",
|
||||
"This will permanently delete this department.": "This will permanently delete this department.",
|
||||
"Assigned departments": "Assigned departments",
|
||||
"Select departments": "Select departments",
|
||||
"Departments for tenant": "Departments for tenant",
|
||||
"No departments": "No departments",
|
||||
"No departments available for this tenant": "No departments available for this tenant",
|
||||
"Assign tenants first to select departments": "Assign tenants first to select departments",
|
||||
"No tenants available": "No tenants available",
|
||||
@@ -549,7 +542,6 @@
|
||||
"Delete permission": "Delete permission",
|
||||
"This will permanently delete this role.": "This will permanently delete this role.",
|
||||
"This will permanently delete this permission.": "This will permanently delete this permission.",
|
||||
"This action cannot be undone.": "This action cannot be undone.",
|
||||
"Description": "Description",
|
||||
"Description cannot be empty": "Description cannot be empty",
|
||||
"Status is invalid": "Status is invalid",
|
||||
@@ -647,7 +639,6 @@
|
||||
"SMTP security": "SMTP security",
|
||||
"SMTP from address": "SMTP from address",
|
||||
"SMTP from name": "SMTP from name",
|
||||
"Address book": "Address book",
|
||||
"Mobile": "Mobile",
|
||||
"Short dial": "Short dial",
|
||||
"setting.smtp_host": "SMTP server host (e.g. smtp.example.com)",
|
||||
@@ -659,7 +650,6 @@
|
||||
"setting.smtp_from_name": "From name for outgoing emails",
|
||||
"High contrast": "High contrast",
|
||||
"Toggle contrast": "Toggle contrast",
|
||||
"View in address book": "View in address book",
|
||||
"Organization & Quality": "Organization & Quality",
|
||||
"Email security": "Email security",
|
||||
"API": "API",
|
||||
@@ -813,8 +803,6 @@
|
||||
"Please fill required custom field: %s": "Please fill required custom field: %s",
|
||||
"Invalid value for %s": "Invalid value for %s",
|
||||
"Please select": "Please select",
|
||||
"From": "From",
|
||||
"To": "To",
|
||||
"perm.custom_fields.manage": "Manage tenant custom fields",
|
||||
"perm.custom_fields.edit_values": "Edit user custom field values",
|
||||
"Label": "Label",
|
||||
@@ -999,7 +987,6 @@
|
||||
"Import another file": "Import another file",
|
||||
"No row errors found": "No row errors found",
|
||||
"Row": "Row",
|
||||
"Code": "Code",
|
||||
"Message": "Message",
|
||||
"No upload file provided": "No upload file provided",
|
||||
"Upload exceeds the maximum size": "Upload exceeds the maximum size",
|
||||
@@ -1212,7 +1199,6 @@
|
||||
"Actor tenant": "Actor tenant",
|
||||
"Event details": "Event details",
|
||||
"Target type": "Target type",
|
||||
"Request ID": "Request ID",
|
||||
"IP hash": "IP hash",
|
||||
"User agent hash": "User agent hash",
|
||||
"Channel": "Channel",
|
||||
@@ -1299,45 +1285,5 @@
|
||||
"Session expiring": "Session expiring",
|
||||
"Your session will expire in {countdown}. Would you like to continue?": "Your session will expire in {countdown}. Would you like to continue?",
|
||||
"Extend session": "Extend session",
|
||||
"Log out": "Log out",
|
||||
"Bookmarks": "Bookmarks",
|
||||
"Bookmark this page": "Bookmark this page",
|
||||
"Save bookmark": "Save bookmark",
|
||||
"Bookmark name": "Bookmark name",
|
||||
"Delete bookmark": "Delete bookmark",
|
||||
"No bookmarks yet": "No bookmarks yet",
|
||||
"New group": "New group",
|
||||
"No group": "No group",
|
||||
"Assign to group": "Assign to group",
|
||||
"Group name": "Group name",
|
||||
"Delete group": "Delete group",
|
||||
"Group": "Group",
|
||||
"Icon": "Icon",
|
||||
"Maximum bookmarks reached": "Maximum bookmarks reached",
|
||||
"Edit bookmark": "Edit bookmark",
|
||||
"Save changes": "Save changes",
|
||||
"Bookmark saved": "Bookmark saved",
|
||||
"Bookmark updated": "Bookmark updated",
|
||||
"Bookmark deleted": "Bookmark deleted",
|
||||
"Group created": "Group created",
|
||||
"Group deleted": "Group deleted",
|
||||
"Group delete failed": "Group delete failed",
|
||||
"Delete group and keep bookmarks?": "Delete group and keep bookmarks?",
|
||||
"Bookmark action failed": "Bookmark action failed",
|
||||
"Group action failed": "Group action failed",
|
||||
"Reorder saved": "Reorder saved",
|
||||
"Reorder failed": "Reorder failed",
|
||||
"Move group up": "Move group up",
|
||||
"Move group down": "Move group down",
|
||||
"Move bookmark up": "Move bookmark up",
|
||||
"Move bookmark down": "Move bookmark down",
|
||||
"Group actions": "Group actions",
|
||||
"Bookmark actions": "Bookmark actions",
|
||||
"Bookmark name is required": "Bookmark name is required",
|
||||
"Bookmark URL is invalid": "Bookmark URL is invalid",
|
||||
"Group not found": "Group not found",
|
||||
"Edit group": "Edit group",
|
||||
"Group updated": "Group updated",
|
||||
"Group name is required": "Group name is required",
|
||||
"Maximum groups reached": "Maximum groups reached"
|
||||
"Log out": "Log out"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user