refactor: complete JS i18n migration for confirm dialogs and toast messages

Migrate 34 hardcoded user-facing strings to use I18n.t() for translation:

- CMS: media file operations (5 strings)
- Marketplace: Letzshop integration (16 strings)
- Messaging: notifications, messages, email templates (5 strings)
- Tenancy: platform modules, menu config, theme (5 strings)
- Core: menu config, settings, storefront cart (5 strings)
- Catalog: product creation (3 strings)
- Utils: clipboard operations (2 strings)

Added confirmations and messages keys to module locale files.
Added I18n.loadModule() calls to JS files that were missing them.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-01 17:29:13 +01:00
parent 1d78085085
commit 09d7d282c6
24 changed files with 681 additions and 822 deletions

View File

@@ -1,122 +1,75 @@
{
"title": "Marketplace Integration",
"description": "Letzshop product and order synchronization",
"products": {
"title": "Marketplace Products",
"subtitle": "Products imported from marketplaces",
"empty": "No products found",
"empty_search": "No products match your search",
"import": "Import Products"
},
"import": {
"title": "Import Products",
"subtitle": "Import products from marketplace feeds",
"source_url": "Feed URL",
"source_url_help": "URL to the marketplace CSV feed",
"marketplace": "Marketplace",
"language": "Language",
"language_help": "Language for product translations",
"batch_size": "Batch Size",
"marketplace": {
"title": "Marketplace",
"import": "Import",
"export": "Export",
"sync": "Sync",
"source": "Source",
"source_url": "Source URL",
"import_products": "Import Products",
"start_import": "Start Import",
"cancel": "Cancel"
},
"import_jobs": {
"title": "Import History",
"subtitle": "Past and current import jobs",
"empty": "No import jobs",
"importing": "Importing...",
"import_complete": "Import Complete",
"import_failed": "Import Failed",
"import_history": "Import History",
"job_id": "Job ID",
"marketplace": "Marketplace",
"vendor": "Vendor",
"status": "Status",
"imported": "Imported",
"updated": "Updated",
"errors": "Errors",
"created": "Created",
"completed": "Completed",
"statuses": {
"pending": "Pending",
"processing": "Processing",
"completed": "Completed",
"completed_with_errors": "Completed with Errors",
"failed": "Failed"
}
"started_at": "Started At",
"completed_at": "Completed At",
"duration": "Duration",
"imported_count": "Imported",
"error_count": "Errors",
"total_processed": "Total Processed",
"progress": "Progress",
"no_import_jobs": "No import jobs yet",
"start_first_import": "Start your first import using the form above"
},
"letzshop": {
"title": "Letzshop Integration",
"subtitle": "Manage Letzshop connection and sync",
"credentials": {
"title": "API Credentials",
"api_key": "API Key",
"api_key_help": "Your Letzshop API key",
"endpoint": "API Endpoint",
"test_mode": "Test Mode",
"test_mode_help": "When enabled, no changes are made to Letzshop"
},
"sync": {
"title": "Synchronization",
"auto_sync": "Auto Sync",
"auto_sync_help": "Automatically sync orders from Letzshop",
"interval": "Sync Interval",
"interval_help": "Minutes between syncs",
"last_sync": "Last Sync",
"last_status": "Last Status",
"sync_now": "Sync Now"
},
"carrier": {
"title": "Carrier Settings",
"default_carrier": "Default Carrier",
"greco": "Greco",
"colissimo": "Colissimo",
"xpresslogistics": "XpressLogistics",
"label_url": "Label URL Prefix"
},
"historical": {
"title": "Historical Import",
"subtitle": "Import past orders from Letzshop",
"start_import": "Start Historical Import",
"phase": "Phase",
"confirmed": "Confirmed Orders",
"unconfirmed": "Unconfirmed Orders",
"fetching": "Fetching...",
"processing": "Processing...",
"page": "Page",
"fetched": "Fetched",
"processed": "Processed",
"imported": "Imported",
"updated": "Updated",
"skipped": "Skipped"
},
"vendors": {
"title": "Vendor Directory",
"subtitle": "Browse Letzshop vendors",
"claim": "Claim",
"claimed": "Claimed",
"unclaimed": "Unclaimed",
"last_synced": "Last synced"
"connection": "Connection",
"credentials": "Credentials",
"api_key": "API Key",
"api_endpoint": "API Endpoint",
"auto_sync": "Auto Sync",
"sync_interval": "Sync Interval",
"every_hour": "Every hour",
"every_day": "Every day",
"test_connection": "Test Connection",
"save_credentials": "Save Credentials",
"connection_success": "Connection successful",
"connection_failed": "Connection failed",
"last_sync": "Last Sync",
"sync_status": "Sync Status",
"import_orders": "Import Orders",
"export_products": "Export Products",
"no_credentials": "Configure your API key in Settings to get started",
"carriers": {
"dhl": "DHL",
"ups": "UPS",
"fedex": "FedEx",
"dpd": "DPD",
"gls": "GLS",
"post_luxembourg": "Post Luxembourg",
"other": "Other"
}
},
"export": {
"title": "Export Products",
"subtitle": "Export products to marketplace format",
"format": "Format",
"format_csv": "CSV",
"format_xml": "XML",
"download": "Download Export"
},
"messages": {
"import_started": "Import started successfully",
"import_completed": "Import completed",
"import_failed": "Import failed",
"credentials_saved": "Credentials saved successfully",
"sync_started": "Sync started",
"sync_completed": "Sync completed",
"sync_failed": "Sync failed",
"export_ready": "Export ready for download",
"error_loading": "Error loading data"
"no_error_details_available": "No error details available",
"failed_to_load_error_details": "Failed to load error details",
"copied_to_clipboard": "Copied to clipboard",
"failed_to_copy_to_clipboard": "Failed to copy to clipboard",
"please_configure_api_key_first": "Please configure your API key first",
"please_enter_api_key": "Please enter an API key",
"please_fill_in_all_fields": "Please fill in all fields"
},
"filters": {
"all_marketplaces": "All Marketplaces",
"all_vendors": "All Vendors",
"search_placeholder": "Search products..."
"confirmations": {
"remove_letzshop_credentials": "Are you sure you want to remove your Letzshop credentials?",
"confirm_order": "Confirm this order?",
"reject_order": "Reject this order? This action cannot be undone.",
"remove_letzshop_config_vendor": "Are you sure you want to remove Letzshop configuration for this vendor?",
"decline_order": "Are you sure you want to decline this order? All items will be marked as unavailable.",
"confirm_all_items": "Are you sure you want to confirm all items in this order?",
"decline_all_items": "Are you sure you want to decline all items in this order?",
"remove_letzshop_config": "Are you sure you want to remove the Letzshop configuration? This will disable all Letzshop features for this vendor.",
"ignore_exception": "Are you sure you want to ignore this exception? The order will still be blocked from confirmation."
}
}

View File

@@ -64,6 +64,9 @@ function adminLetzshop() {
vendorOrders: [],
async init() {
// Load i18n translations
await I18n.loadModule('marketplace');
// Guard against multiple initialization
if (window._adminLetzshopInitialized) {
return;
@@ -188,7 +191,7 @@ function adminLetzshop() {
* Delete vendor configuration
*/
async deleteVendorConfig() {
if (!confirm('Are you sure you want to remove Letzshop configuration for this vendor?')) {
if (!confirm(I18n.t('marketplace.confirmations.remove_letzshop_config_vendor'))) {
return;
}

View File

@@ -227,6 +227,9 @@ function adminMarketplaceLetzshop() {
},
async init() {
// Load i18n translations
await I18n.loadModule('marketplace');
marketplaceLetzshopLog.info('init() called');
// Guard against multiple initialization
@@ -1007,7 +1010,7 @@ function adminMarketplaceLetzshop() {
async declineOrder(order) {
if (!this.selectedVendor) return;
if (!confirm('Are you sure you want to decline this order? All items will be marked as unavailable.')) return;
if (!confirm(I18n.t('marketplace.confirmations.decline_order'))) return;
try {
await apiClient.post(`/admin/letzshop/vendors/${this.selectedVendor.id}/orders/${order.id}/reject`);
@@ -1125,7 +1128,7 @@ function adminMarketplaceLetzshop() {
async confirmAllItems(order) {
if (!this.selectedVendor) return;
if (!confirm('Are you sure you want to confirm all items in this order?')) return;
if (!confirm(I18n.t('marketplace.confirmations.confirm_all_items'))) return;
try {
await apiClient.post(
@@ -1146,7 +1149,7 @@ function adminMarketplaceLetzshop() {
async declineAllItems(order) {
if (!this.selectedVendor) return;
if (!confirm('Are you sure you want to decline all items in this order?')) return;
if (!confirm(I18n.t('marketplace.confirmations.decline_all_items'))) return;
try {
await apiClient.post(
@@ -1238,7 +1241,7 @@ function adminMarketplaceLetzshop() {
async deleteCredentials() {
if (!this.selectedVendor) return;
if (!confirm('Are you sure you want to remove the Letzshop configuration? This will disable all Letzshop features for this vendor.')) {
if (!confirm(I18n.t('marketplace.confirmations.remove_letzshop_config'))) {
return;
}
@@ -1456,7 +1459,7 @@ function adminMarketplaceLetzshop() {
* Ignore an exception
*/
async ignoreException(exception) {
if (!confirm('Are you sure you want to ignore this exception? The order will still be blocked from confirmation.')) {
if (!confirm(I18n.t('marketplace.confirmations.ignore_exception'))) {
return;
}
@@ -1540,7 +1543,7 @@ function adminMarketplaceLetzshop() {
if (job.type === 'import') {
const errors = response.errors || [];
if (errors.length === 0) {
Utils.showToast('No error details available', 'info');
Utils.showToast(I18n.t('marketplace.messages.no_error_details_available'), 'info');
return;
}
// Store errors and show in job details modal
@@ -1553,7 +1556,7 @@ function adminMarketplaceLetzshop() {
}
} catch (error) {
marketplaceLetzshopLog.error('Failed to load job errors:', error);
Utils.showToast('Failed to load error details', 'error');
Utils.showToast(I18n.t('marketplace.messages.failed_to_load_error_details'), 'error');
}
},

View File

@@ -81,6 +81,9 @@ function vendorLetzshop() {
exporting: false,
async init() {
// Load i18n translations
await I18n.loadModule('marketplace');
// Guard against multiple initialization
if (window._vendorLetzshopInitialized) {
return;
@@ -196,7 +199,7 @@ function vendorLetzshop() {
*/
async importOrders() {
if (!this.status.is_configured) {
this.error = 'Please configure your API key first';
this.error = I18n.t('marketplace.messages.please_configure_api_key_first');
this.activeTab = 'settings';
return;
}
@@ -229,7 +232,7 @@ function vendorLetzshop() {
*/
async saveCredentials() {
if (!this.credentialsForm.api_key && !this.credentials) {
this.error = 'Please enter an API key';
this.error = I18n.t('marketplace.messages.please_enter_api_key');
return;
}
@@ -288,7 +291,7 @@ function vendorLetzshop() {
* Delete credentials
*/
async deleteCredentials() {
if (!confirm('Are you sure you want to remove your Letzshop credentials?')) {
if (!confirm(I18n.t('marketplace.confirmations.remove_letzshop_credentials'))) {
return;
}
@@ -313,7 +316,7 @@ function vendorLetzshop() {
* Confirm order
*/
async confirmOrder(order) {
if (!confirm('Confirm this order?')) {
if (!confirm(I18n.t('marketplace.confirmations.confirm_order'))) {
return;
}
@@ -337,7 +340,7 @@ function vendorLetzshop() {
* Reject order
*/
async rejectOrder(order) {
if (!confirm('Reject this order? This action cannot be undone.')) {
if (!confirm(I18n.t('marketplace.confirmations.reject_order'))) {
return;
}
@@ -374,7 +377,7 @@ function vendorLetzshop() {
*/
async submitTracking() {
if (!this.trackingForm.tracking_number || !this.trackingForm.tracking_carrier) {
this.error = 'Please fill in all fields';
this.error = I18n.t('marketplace.messages.please_fill_in_all_fields');
return;
}