fix(i18n): complete translations for production launch and fix CMS store context
Some checks failed
Some checks failed
- Replace CMS custom get_store_context() with core utility (same fix as loyalty) - Add 85 missing translation keys across fr/de/lb for core, tenancy, messaging, customers, and loyalty modules - Convert 21 client-side $t() calls to server-side _() in 9 loyalty templates - Fix 3 broken translation keys in store/cards.html Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,8 @@ from app.modules.cms.services import content_page_service
|
||||
from app.modules.core.services.platform_settings_service import (
|
||||
platform_settings_service, # MOD-004 - shared platform service
|
||||
)
|
||||
from app.modules.tenancy.models import Store, User
|
||||
from app.modules.core.utils.page_context import get_store_context
|
||||
from app.modules.tenancy.models import User
|
||||
from app.templates_config import templates
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -33,54 +34,6 @@ ROUTE_CONFIG = {
|
||||
}
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# HELPER: Build Store Dashboard Context
|
||||
# ============================================================================
|
||||
|
||||
|
||||
def get_store_context(
|
||||
request: Request,
|
||||
db: Session,
|
||||
current_user: User,
|
||||
store_code: str,
|
||||
**extra_context,
|
||||
) -> dict:
|
||||
"""
|
||||
Build template context for store dashboard pages.
|
||||
|
||||
Resolves locale/currency using the platform settings service with
|
||||
store override support.
|
||||
"""
|
||||
# Load store from database
|
||||
store = db.query(Store).filter(Store.subdomain == store_code).first()
|
||||
|
||||
# Get platform defaults
|
||||
platform_config = platform_settings_service.get_storefront_config(db)
|
||||
|
||||
# Resolve with store override
|
||||
storefront_locale = platform_config["locale"]
|
||||
storefront_currency = platform_config["currency"]
|
||||
|
||||
if store and store.storefront_locale:
|
||||
storefront_locale = store.storefront_locale
|
||||
|
||||
context = {
|
||||
"request": request,
|
||||
"user": current_user,
|
||||
"store": store,
|
||||
"store_code": store_code,
|
||||
"storefront_locale": storefront_locale,
|
||||
"storefront_currency": storefront_currency,
|
||||
"dashboard_language": store.dashboard_language if store else "en",
|
||||
}
|
||||
|
||||
# Add any extra context
|
||||
if extra_context:
|
||||
context.update(extra_context)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# CONTENT PAGES MANAGEMENT
|
||||
# ============================================================================
|
||||
|
||||
@@ -65,8 +65,16 @@
|
||||
"profile_updated": "Profil erfolgreich aktualisiert"
|
||||
},
|
||||
"messages": {
|
||||
"failed_to_load_dashboard_data": "Failed to load dashboard data",
|
||||
"dashboard_refreshed": "Dashboard refreshed"
|
||||
"failed_to_load_dashboard_data": "Dashboard-Daten konnten nicht geladen werden",
|
||||
"dashboard_refreshed": "Dashboard aktualisiert",
|
||||
"item_removed_from_cart": "Artikel aus dem Warenkorb entfernt",
|
||||
"cart_cleared": "Warenkorb geleert"
|
||||
},
|
||||
"confirmations": {
|
||||
"show_all_menu_items": "Alle Menüpunkte werden angezeigt. Fortfahren?",
|
||||
"hide_all_menu_items": "Alle Menüpunkte werden ausgeblendet (außer obligatorische). Sie können dann die gewünschten aktivieren. Fortfahren?",
|
||||
"reset_email_settings": "Alle E-Mail-Einstellungen werden auf .env-Standardwerte zurückgesetzt. Fortfahren?",
|
||||
"cleanup_logs": "Alle Protokolle, die älter als {days} Tage sind, werden gelöscht. Fortfahren?"
|
||||
},
|
||||
"menu": {
|
||||
"dashboard": "Dashboard",
|
||||
|
||||
@@ -65,8 +65,16 @@
|
||||
"profile_updated": "Profil mis à jour avec succès"
|
||||
},
|
||||
"messages": {
|
||||
"failed_to_load_dashboard_data": "Failed to load dashboard data",
|
||||
"dashboard_refreshed": "Dashboard refreshed"
|
||||
"failed_to_load_dashboard_data": "Échec du chargement des données du tableau de bord",
|
||||
"dashboard_refreshed": "Tableau de bord actualisé",
|
||||
"item_removed_from_cart": "Article retiré du panier",
|
||||
"cart_cleared": "Panier vidé"
|
||||
},
|
||||
"confirmations": {
|
||||
"show_all_menu_items": "Ceci affichera tous les éléments de menu. Continuer ?",
|
||||
"hide_all_menu_items": "Ceci masquera tous les éléments de menu (sauf les obligatoires). Vous pourrez ensuite activer ceux que vous souhaitez. Continuer ?",
|
||||
"reset_email_settings": "Ceci réinitialisera tous les paramètres e-mail aux valeurs par défaut .env. Continuer ?",
|
||||
"cleanup_logs": "Ceci supprimera tous les journaux de plus de {days} jours. Continuer ?"
|
||||
},
|
||||
"menu": {
|
||||
"dashboard": "Tableau de bord",
|
||||
|
||||
@@ -65,8 +65,16 @@
|
||||
"profile_updated": "Profil erfollegräich aktualiséiert"
|
||||
},
|
||||
"messages": {
|
||||
"failed_to_load_dashboard_data": "Failed to load dashboard data",
|
||||
"dashboard_refreshed": "Dashboard refreshed"
|
||||
"failed_to_load_dashboard_data": "Dashboard-Donnéeë konnten net geluede ginn",
|
||||
"dashboard_refreshed": "Dashboard aktualiséiert",
|
||||
"item_removed_from_cart": "Artikel aus dem Kuerf ewechgeholl",
|
||||
"cart_cleared": "Kuerf eidel gemaach"
|
||||
},
|
||||
"confirmations": {
|
||||
"show_all_menu_items": "All Menüpunkten ginn ugewisen. Weidermaachen?",
|
||||
"hide_all_menu_items": "All Menüpunkten ginn verstopp (ausser obligatoresch). Dir kënnt dann déi gewënscht aktivéieren. Weidermaachen?",
|
||||
"reset_email_settings": "All E-Mail-Astellunge ginn op .env-Standardwäerter zréckgesat. Weidermaachen?",
|
||||
"cleanup_logs": "All Protokoller, déi méi al wéi {days} Deeg sinn, ginn geläscht. Weidermaachen?"
|
||||
},
|
||||
"menu": {
|
||||
"dashboard": "Dashboard",
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
"description": "Nachrichten an Kunden senden"
|
||||
}
|
||||
},
|
||||
"messages": {
|
||||
"failed_to_toggle_customer_status": "Kundenstatus konnte nicht geändert werden",
|
||||
"failed_to_load_customer_details": "Kundendetails konnten nicht geladen werden",
|
||||
"failed_to_load_customer_orders": "Kundenbestellungen konnten nicht geladen werden"
|
||||
},
|
||||
"menu": {
|
||||
"store_operations": "Shop-Betrieb",
|
||||
"customers_section": "Kunden",
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
"description": "Envoyer des messages aux clients"
|
||||
}
|
||||
},
|
||||
"messages": {
|
||||
"failed_to_toggle_customer_status": "Échec du changement de statut du client",
|
||||
"failed_to_load_customer_details": "Échec du chargement des détails du client",
|
||||
"failed_to_load_customer_orders": "Échec du chargement des commandes du client"
|
||||
},
|
||||
"menu": {
|
||||
"store_operations": "Opérations du magasin",
|
||||
"customers_section": "Clients",
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
"description": "Noriichten u Clienten schécken"
|
||||
}
|
||||
},
|
||||
"messages": {
|
||||
"failed_to_toggle_customer_status": "Clientestatus konnt net geännert ginn",
|
||||
"failed_to_load_customer_details": "Clientedetailer konnten net geluede ginn",
|
||||
"failed_to_load_customer_orders": "Clientebestellunge konnten net geluede ginn"
|
||||
},
|
||||
"menu": {
|
||||
"store_operations": "Buttek-Operatiounen",
|
||||
"customers_section": "Clienten",
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"terminal": "Terminal",
|
||||
"customer_cards": "Kundenkarten",
|
||||
"statistics": "Statistiken",
|
||||
"program": "Programm",
|
||||
"overview": "Übersicht",
|
||||
"settings": "Einstellungen"
|
||||
},
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"terminal": "Terminal",
|
||||
"customer_cards": "Clientekaarten",
|
||||
"statistics": "Statistiken",
|
||||
"program": "Programm",
|
||||
"overview": "Iwwersiicht",
|
||||
"settings": "Astellungen"
|
||||
},
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
{% block content %}
|
||||
{% call detail_page_header("merchant?.name || 'Merchant Loyalty'", '/admin/loyalty/programs', subtitle_show='merchant') %}
|
||||
<span x-text="program ? $t('loyalty.admin.merchant_detail.program_active') : $t('loyalty.admin.merchant_detail.no_program_subtitle')"></span>
|
||||
<span x-text="program ? '{{ _('loyalty.admin.merchant_detail.program_active')|replace("'", "\\'") }}' : '{{ _('loyalty.admin.merchant_detail.no_program_subtitle')|replace("'", "\\'") }}'"></span>
|
||||
{% endcall %}
|
||||
|
||||
{{ loading_state(_('loyalty.admin.merchant_detail.loading')) }}
|
||||
@@ -205,14 +205,14 @@
|
||||
<p class="text-xs font-semibold text-gray-600 dark:text-gray-400 uppercase mb-2">{{ _('loyalty.admin.merchant_detail.self_enrollment') }}</p>
|
||||
<span class="inline-flex items-center px-2 py-1 text-xs font-semibold leading-tight rounded-full"
|
||||
:class="settings?.allow_self_enrollment ? 'text-green-700 bg-green-100 dark:bg-green-700 dark:text-green-100' : 'text-gray-700 bg-gray-100 dark:bg-gray-700 dark:text-gray-100'">
|
||||
<span x-text="settings?.allow_self_enrollment ? $t('loyalty.admin.merchant_detail.allowed') : $t('loyalty.admin.merchant_detail.disabled')"></span>
|
||||
<span x-text="settings?.allow_self_enrollment ? '{{ _('loyalty.admin.merchant_detail.allowed')|replace("'", "\\'") }}' : '{{ _('loyalty.admin.merchant_detail.disabled')|replace("'", "\\'") }}'"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-semibold text-gray-600 dark:text-gray-400 uppercase mb-2">{{ _('loyalty.admin.merchant_detail.cross_location_redemption') }}</p>
|
||||
<span class="inline-flex items-center px-2 py-1 text-xs font-semibold leading-tight rounded-full"
|
||||
:class="settings?.allow_cross_location_redemption !== false ? 'text-green-700 bg-green-100 dark:bg-green-700 dark:text-green-100' : 'text-gray-700 bg-gray-100 dark:bg-gray-700 dark:text-gray-100'">
|
||||
<span x-text="settings?.allow_cross_location_redemption !== false ? $t('loyalty.admin.merchant_detail.allowed') : $t('loyalty.admin.merchant_detail.disabled')"></span>
|
||||
<span x-text="settings?.allow_cross_location_redemption !== false ? '{{ _('loyalty.admin.merchant_detail.allowed')|replace("'", "\\'") }}' : '{{ _('loyalty.admin.merchant_detail.disabled')|replace("'", "\\'") }}'"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
:disabled="saving"
|
||||
class="flex items-center px-4 py-2 text-sm font-medium text-white bg-purple-600 border border-transparent rounded-lg hover:bg-purple-700 focus:outline-none focus:shadow-outline-purple disabled:opacity-50">
|
||||
<span x-show="saving" x-html="$icon('spinner', 'w-4 h-4 mr-2 animate-spin')"></span>
|
||||
<span x-text="saving ? $t('loyalty.common.saving') : $t('loyalty.admin.merchant_settings.save_settings')"></span>
|
||||
<span x-text="saving ? '{{ _('loyalty.common.saving')|replace("'", "\\'") }}' : '{{ _('loyalty.admin.merchant_settings.save_settings')|replace("'", "\\'") }}'"></span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
{% block content %}
|
||||
{% call detail_page_header("isNewProgram ? 'Create Program: ' + (merchant?.name || '') : 'Edit Program: ' + (merchant?.name || '')", '/admin/loyalty/merchants/' ~ merchant_id, subtitle_show='merchant') %}
|
||||
<span x-text="isNewProgram ? $t('loyalty.admin.program_edit.create_subtitle') : $t('loyalty.admin.program_edit.edit_subtitle')"></span>
|
||||
<span x-text="isNewProgram ? '{{ _('loyalty.admin.program_edit.create_subtitle')|replace("'", "\\'") }}' : '{{ _('loyalty.admin.program_edit.edit_subtitle')|replace("'", "\\'") }}'"></span>
|
||||
{% endcall %}
|
||||
|
||||
{{ loading_state(_('loyalty.admin.program_edit.loading')) }}
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
<div class="flex flex-col items-center">
|
||||
<span x-html="$icon('gift', 'w-12 h-12 mb-2 text-gray-300')"></span>
|
||||
<p class="font-medium">{{ _('loyalty.admin.programs.no_programs') }}</p>
|
||||
<p class="text-xs mt-1" x-text="filters.search || filters.is_active ? $t('loyalty.admin.programs.adjust_filters') : $t('loyalty.admin.programs.no_merchants_yet')"></p>
|
||||
<p class="text-xs mt-1" x-text="filters.search || filters.is_active ? '{{ _('loyalty.admin.programs.adjust_filters')|replace("'", "\\'") }}' : '{{ _('loyalty.admin.programs.no_merchants_yet')|replace("'", "\\'") }}'"></p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -177,7 +177,7 @@
|
||||
<span x-text="program.loyalty_type?.charAt(0).toUpperCase() + program.loyalty_type?.slice(1) || 'Unknown'"></span>
|
||||
</span>
|
||||
<p class="text-xs text-gray-500 mt-1" x-show="program.is_points_enabled">
|
||||
<span x-text="program.points_per_euro"></span> <span x-text="$t('loyalty.admin.programs.pt_per_eur')"></span>
|
||||
<span x-text="program.points_per_euro"></span> {{ _('loyalty.admin.programs.pt_per_eur') }}
|
||||
</p>
|
||||
</td>
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
<td class="px-4 py-3 text-xs">
|
||||
<span class="inline-flex items-center px-2 py-1 font-semibold leading-tight rounded-full"
|
||||
:class="program.is_active ? 'text-green-700 bg-green-100 dark:bg-green-700 dark:text-green-100' : 'text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700'">
|
||||
<span x-text="program.is_active ? $t('loyalty.common.active') : $t('loyalty.common.inactive')"></span>
|
||||
<span x-text="program.is_active ? '{{ _('loyalty.common.active')|replace("'", "\\'") }}' : '{{ _('loyalty.common.inactive')|replace("'", "\\'") }}'"></span>
|
||||
</span>
|
||||
</td>
|
||||
|
||||
|
||||
@@ -305,7 +305,7 @@
|
||||
<button type="submit" :disabled="saving"
|
||||
class="flex items-center px-6 py-2 text-sm font-medium text-white bg-purple-600 rounded-lg hover:bg-purple-700 disabled:opacity-50">
|
||||
<span x-show="saving" x-html="$icon('spinner', 'w-4 h-4 mr-2 animate-spin')"></span>
|
||||
<span x-text="saving ? $t('loyalty.common.saving') : (isNewProgram ? $t('loyalty.shared.program_form.create_program') : $t('loyalty.shared.program_form.save_changes'))"></span>
|
||||
<span x-text="saving ? '{{ _('loyalty.common.saving')|replace("'", "\\'") }}' : (isNewProgram ? '{{ _('loyalty.shared.program_form.create_program')|replace("'", "\\'") }}' : '{{ _('loyalty.shared.program_form.save_changes')|replace("'", "\\'") }}')"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mb-1">{{ _('loyalty.shared.program_view.staff_pin_required') }}</p>
|
||||
<span class="inline-flex items-center px-2 py-1 text-xs font-semibold leading-tight rounded-full"
|
||||
:class="program?.require_staff_pin ? 'text-green-700 bg-green-100 dark:bg-green-700 dark:text-green-100' : 'text-gray-700 bg-gray-100 dark:bg-gray-700 dark:text-gray-100'">
|
||||
<span x-text="program?.require_staff_pin ? $t('loyalty.common.yes') : $t('loyalty.common.no')"></span>
|
||||
<span x-text="program?.require_staff_pin ? '{{ _('loyalty.common.yes')|replace("'", "\\'") }}' : '{{ _('loyalty.common.no')|replace("'", "\\'") }}'"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -122,8 +122,8 @@
|
||||
<td colspan="6" class="px-4 py-8 text-center text-gray-600 dark:text-gray-400">
|
||||
<div class="flex flex-col items-center">
|
||||
<span x-html="$icon('users', 'w-12 h-12 mb-2 text-gray-300')"></span>
|
||||
<p class="font-medium" x-text="$t('loyalty.store.cards.no_members_found')"></p>
|
||||
<p class="text-xs mt-1" x-text="filters.search ? $t('loyalty.store.cards.try_adjusting_search') : $t('loyalty.store.cards.enroll_first_customer')"></p>
|
||||
<p class="font-medium">{{ _('loyalty.store.cards.no_members') }}</p>
|
||||
<p class="text-xs mt-1" x-text="filters.search ? '{{ _('loyalty.store.cards.adjust_search')|replace("'", "\\'") }}' : '{{ _('loyalty.store.cards.enroll_first')|replace("'", "\\'") }}'"></p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -150,13 +150,12 @@
|
||||
<td class="px-4 py-3 text-xs">
|
||||
<span class="px-2 py-1 font-semibold leading-tight rounded-full"
|
||||
:class="card.is_active ? 'text-green-700 bg-green-100 dark:bg-green-700 dark:text-green-100' : 'text-gray-700 bg-gray-100 dark:bg-gray-700 dark:text-gray-100'"
|
||||
x-text="card.is_active ? $t('loyalty.common.active') : $t('loyalty.common.inactive')"></span>
|
||||
x-text="card.is_active ? '{{ _('loyalty.common.active')|replace("'", "\\'") }}' : '{{ _('loyalty.common.inactive')|replace("'", "\\'") }}'"></span>
|
||||
</td>
|
||||
<td class="px-4 py-3">
|
||||
<a :href="'/store/{{ store_code }}/loyalty/cards/' + card.id"
|
||||
class="text-purple-600 hover:text-purple-700 dark:text-purple-400"
|
||||
x-text="$t('loyalty.common.view')">
|
||||
</a>
|
||||
>{{ _('loyalty.common.view') }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
<button type="submit" :disabled="enrolling || !form.first_name || !form.email"
|
||||
class="flex items-center px-6 py-2 text-sm font-medium text-white bg-purple-600 rounded-lg hover:bg-purple-700 disabled:opacity-50">
|
||||
<span x-show="enrolling" x-html="$icon('spinner', 'w-4 h-4 mr-2 animate-spin')"></span>
|
||||
<span x-text="enrolling ? $t('loyalty.store.enroll.enrolling') : $t('loyalty.store.enroll.enroll_customer')"></span>
|
||||
<span x-text="enrolling ? '{{ _('loyalty.store.enroll.enrolling')|replace("'", "\\'") }}' : '{{ _('loyalty.store.enroll.enroll_customer')|replace("'", "\\'") }}'"></span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
class="w-full flex items-center justify-center px-4 py-3 text-sm font-medium text-white bg-purple-600 rounded-lg hover:bg-purple-700 focus:outline-none disabled:opacity-50"
|
||||
>
|
||||
<span x-show="lookingUp" x-html="$icon('spinner', 'w-5 h-5 mr-2 animate-spin')"></span>
|
||||
<span x-text="lookingUp ? $t('loyalty.store.terminal.looking_up') : $t('loyalty.store.terminal.look_up_customer')"></span>
|
||||
<span x-text="lookingUp ? '{{ _('loyalty.store.terminal.looking_up')|replace("'", "\\'") }}' : '{{ _('loyalty.store.terminal.look_up_customer')|replace("'", "\\'") }}'"></span>
|
||||
</button>
|
||||
|
||||
<!-- Divider -->
|
||||
@@ -137,7 +137,7 @@
|
||||
<!-- Points balance (for points and hybrid) -->
|
||||
<template x-if="program?.is_points_enabled">
|
||||
<div>
|
||||
<p class="text-sm font-medium text-gray-600 dark:text-gray-400" x-text="$t('loyalty.store.terminal.points_balance')"></p>
|
||||
<p class="text-sm font-medium text-gray-600 dark:text-gray-400">{{ _('loyalty.store.terminal.points_balance') }}</p>
|
||||
<p class="text-3xl font-bold"
|
||||
:style="'color: ' + (program?.card_color || '#4F46E5')"
|
||||
x-text="formatNumber(selectedCard?.points_balance || 0)"></p>
|
||||
@@ -146,7 +146,7 @@
|
||||
<!-- Stamps progress (for stamps and hybrid) -->
|
||||
<template x-if="program?.is_stamps_enabled">
|
||||
<div :class="program?.is_points_enabled ? 'mt-3 pt-3 border-t border-gray-200 dark:border-gray-700' : ''">
|
||||
<p class="text-sm font-medium text-gray-600 dark:text-gray-400" x-text="$t('loyalty.store.terminal.stamps')"></p>
|
||||
<p class="text-sm font-medium text-gray-600 dark:text-gray-400">{{ _('loyalty.store.terminal.stamps') }}</p>
|
||||
<p class="text-3xl font-bold"
|
||||
:style="'color: ' + (program?.card_color || '#4F46E5')"
|
||||
x-text="(selectedCard?.stamp_count || 0) + ' / ' + (program?.stamps_target || 10)"></p>
|
||||
@@ -175,7 +175,7 @@
|
||||
{{ _('loyalty.store.terminal.add_stamp') }}
|
||||
</button>
|
||||
<template x-if="!selectedCard?.can_stamp && selectedCard?.cooldown_ends_at">
|
||||
<p class="text-xs text-red-500 mt-2" x-text="$t('loyalty.store.terminal.cooldown_active')"></p>
|
||||
<p class="text-xs text-red-500 mt-2">{{ _('loyalty.store.terminal.cooldown_active') }}</p>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -357,7 +357,7 @@
|
||||
:disabled="pinDigits.length !== 4 || processing"
|
||||
class="px-4 py-2 text-sm font-medium text-white bg-purple-600 rounded-lg hover:bg-purple-700 disabled:opacity-50">
|
||||
<span x-show="processing" x-html="$icon('spinner', 'w-4 h-4 mr-2 inline animate-spin')"></span>
|
||||
<span x-text="processing ? $t('loyalty.store.terminal.processing') : $t('loyalty.store.terminal.confirm')"></span>
|
||||
<span x-text="processing ? '{{ _('loyalty.store.terminal.processing')|replace("'", "\\'") }}' : '{{ _('loyalty.store.terminal.confirm')|replace("'", "\\'") }}'"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -35,7 +35,16 @@
|
||||
"failed_to_delete_notification": "Failed to delete notification",
|
||||
"failed_to_load_alerts": "Failed to load alerts",
|
||||
"alert_resolved_successfully": "Alert resolved successfully",
|
||||
"failed_to_resolve_alert": "Failed to resolve alert"
|
||||
"failed_to_resolve_alert": "Failed to resolve alert",
|
||||
"no_template_for_language": "Keine Vorlage für {language} - erstellen Sie eine durch Speichern",
|
||||
"failed_to_save_template": "Vorlage konnte nicht gespeichert werden",
|
||||
"test_email_sent": "Test-E-Mail an {email} gesendet"
|
||||
},
|
||||
"confirmations": {
|
||||
"delete_notification": "Sind Sie sicher, dass Sie diese Benachrichtigung löschen möchten?",
|
||||
"close_conversation": "Diese Konversation schließen?",
|
||||
"close_conversation_admin": "Sind Sie sicher, dass Sie diese Konversation schließen möchten?",
|
||||
"delete_customization": "Sind Sie sicher, dass Sie Ihre Anpassung löschen und zur Plattform-Standardvorlage zurückkehren möchten?"
|
||||
},
|
||||
"features": {
|
||||
"messaging_basic": {
|
||||
@@ -78,6 +87,7 @@
|
||||
"reply_to": "Antwort an",
|
||||
"related_entity": "Verknüpfte Entität",
|
||||
"error_message": "Fehlermeldung",
|
||||
"retry_count": "Wiederholungsversuche",
|
||||
"actions": "Aktionen",
|
||||
"view_detail": "Details anzeigen",
|
||||
"email_detail": "E-Mail-Detail",
|
||||
@@ -85,6 +95,7 @@
|
||||
"text_preview": "Text-Vorschau",
|
||||
"metadata": "Metadaten",
|
||||
"content": "Inhalt",
|
||||
"status_timeline": "Status-Verlauf",
|
||||
"filter_by_recipient": "Nach Empfänger-E-Mail suchen...",
|
||||
"filter_by_status": "Alle Status",
|
||||
"filter_by_template": "Alle Vorlagen",
|
||||
@@ -104,7 +115,8 @@
|
||||
"status_delivered": "Zugestellt",
|
||||
"status_bounced": "Abgewiesen",
|
||||
"status_opened": "Geöffnet",
|
||||
"status_clicked": "Angeklickt"
|
||||
"status_clicked": "Angeklickt",
|
||||
"retention_note": "E-Mail-Inhalte werden 90 Tage aufbewahrt. Metadaten werden unbegrenzt gespeichert."
|
||||
},
|
||||
"permissions": {
|
||||
"view_messages": "Nachrichten anzeigen",
|
||||
|
||||
@@ -35,7 +35,16 @@
|
||||
"failed_to_delete_notification": "Failed to delete notification",
|
||||
"failed_to_load_alerts": "Failed to load alerts",
|
||||
"alert_resolved_successfully": "Alert resolved successfully",
|
||||
"failed_to_resolve_alert": "Failed to resolve alert"
|
||||
"failed_to_resolve_alert": "Failed to resolve alert",
|
||||
"no_template_for_language": "Pas de modèle pour {language} - créez-en un en enregistrant",
|
||||
"failed_to_save_template": "Échec de l'enregistrement du modèle",
|
||||
"test_email_sent": "E-mail de test envoyé à {email}"
|
||||
},
|
||||
"confirmations": {
|
||||
"delete_notification": "Êtes-vous sûr de vouloir supprimer cette notification ?",
|
||||
"close_conversation": "Fermer cette conversation ?",
|
||||
"close_conversation_admin": "Êtes-vous sûr de vouloir fermer cette conversation ?",
|
||||
"delete_customization": "Êtes-vous sûr de vouloir supprimer votre personnalisation et revenir au modèle par défaut de la plateforme ?"
|
||||
},
|
||||
"features": {
|
||||
"messaging_basic": {
|
||||
@@ -78,6 +87,7 @@
|
||||
"reply_to": "Répondre à",
|
||||
"related_entity": "Entité liée",
|
||||
"error_message": "Message d'erreur",
|
||||
"retry_count": "Tentatives",
|
||||
"actions": "Actions",
|
||||
"view_detail": "Voir le détail",
|
||||
"email_detail": "Détail de l'e-mail",
|
||||
@@ -85,6 +95,7 @@
|
||||
"text_preview": "Aperçu texte",
|
||||
"metadata": "Métadonnées",
|
||||
"content": "Contenu",
|
||||
"status_timeline": "Chronologie du statut",
|
||||
"filter_by_recipient": "Rechercher par e-mail du destinataire...",
|
||||
"filter_by_status": "Tous les statuts",
|
||||
"filter_by_template": "Tous les modèles",
|
||||
@@ -104,7 +115,8 @@
|
||||
"status_delivered": "Livré",
|
||||
"status_bounced": "Rebondi",
|
||||
"status_opened": "Ouvert",
|
||||
"status_clicked": "Cliqué"
|
||||
"status_clicked": "Cliqué",
|
||||
"retention_note": "Le contenu des e-mails est conservé pendant 90 jours. Les métadonnées sont conservées indéfiniment."
|
||||
},
|
||||
"permissions": {
|
||||
"view_messages": "Voir les messages",
|
||||
|
||||
@@ -35,7 +35,16 @@
|
||||
"failed_to_delete_notification": "Failed to delete notification",
|
||||
"failed_to_load_alerts": "Failed to load alerts",
|
||||
"alert_resolved_successfully": "Alert resolved successfully",
|
||||
"failed_to_resolve_alert": "Failed to resolve alert"
|
||||
"failed_to_resolve_alert": "Failed to resolve alert",
|
||||
"no_template_for_language": "Keng Virlag fir {language} - erstellt eng andeems Dir späichert",
|
||||
"failed_to_save_template": "Virlag konnt net gespäichert ginn",
|
||||
"test_email_sent": "Test-E-Mail u {email} geschéckt"
|
||||
},
|
||||
"confirmations": {
|
||||
"delete_notification": "Sidd Dir sécher datt Dir dës Notifikatioun läsche wëllt?",
|
||||
"close_conversation": "Dës Conversatioun zoumaachen?",
|
||||
"close_conversation_admin": "Sidd Dir sécher datt Dir dës Conversatioun zoumaache wëllt?",
|
||||
"delete_customization": "Sidd Dir sécher datt Dir Är Personnaliséierung läschen an zum Plattform-Standard zréckgoe wëllt?"
|
||||
},
|
||||
"features": {
|
||||
"messaging_basic": {
|
||||
@@ -59,7 +68,55 @@
|
||||
"account_settings": "Kont-Astellungen",
|
||||
"messages": "Messagen",
|
||||
"notifications": "Notifikatiounen",
|
||||
"email_templates": "E-Mail-Virlagen"
|
||||
"email_templates": "E-Mail-Virlagen",
|
||||
"email_logs": "E-Mail-Protokoller"
|
||||
},
|
||||
"email_logs": {
|
||||
"title": "E-Mail-Protokoller",
|
||||
"subtitle": "All E-Mailen iwwerpréiwen déi iwwer d'Plattform geschéckt goufen",
|
||||
"recipient": "Empfänger",
|
||||
"subject": "Sujet",
|
||||
"template": "Virlag",
|
||||
"status": "Status",
|
||||
"store": "Buttek",
|
||||
"date": "Datum",
|
||||
"sent_at": "Geschéckt um",
|
||||
"provider": "Ubidder",
|
||||
"from": "Vun",
|
||||
"to": "Un",
|
||||
"reply_to": "Äntwert un",
|
||||
"related_entity": "Verbonnen Entitéit",
|
||||
"error_message": "Feelernotiz",
|
||||
"retry_count": "Widderholungsversich",
|
||||
"actions": "Aktiounen",
|
||||
"view_detail": "Detailer kucken",
|
||||
"email_detail": "E-Mail-Detail",
|
||||
"html_preview": "HTML-Virschau",
|
||||
"text_preview": "Text-Virschau",
|
||||
"metadata": "Metadaten",
|
||||
"content": "Inhalt",
|
||||
"status_timeline": "Status-Verlaf",
|
||||
"filter_by_recipient": "No Empfänger-E-Mail sichen...",
|
||||
"filter_by_status": "All Statussen",
|
||||
"filter_by_template": "All Virlagen",
|
||||
"filter_by_store": "All Butteker",
|
||||
"date_from": "Vun Datum",
|
||||
"date_to": "Bis Datum",
|
||||
"apply_filters": "Uwenden",
|
||||
"reset_filters": "Zrécksetzen",
|
||||
"total_sent": "Total geschéckt",
|
||||
"total_failed": "Feelgeschloen",
|
||||
"total_pending": "Aussteesend",
|
||||
"total_delivered": "Zougestallt",
|
||||
"no_logs": "Keng E-Mail-Protokoller fonnt",
|
||||
"status_sent": "Geschéckt",
|
||||
"status_failed": "Feelgeschloen",
|
||||
"status_pending": "Aussteesend",
|
||||
"status_delivered": "Zougestallt",
|
||||
"status_bounced": "Zréckgeschéckt",
|
||||
"status_opened": "Opgemaach",
|
||||
"status_clicked": "Geklickt",
|
||||
"retention_note": "E-Mail-Inhalt gëtt 90 Deeg gespäichert. Metadaten ginn onbegrenzt gehalen."
|
||||
},
|
||||
"permissions": {
|
||||
"view_messages": "Messagen kucken",
|
||||
|
||||
@@ -90,6 +90,13 @@
|
||||
"failed_to_load_user": "Failed to load user",
|
||||
"user_updated_successfully": "User updated successfully"
|
||||
},
|
||||
"confirmations": {
|
||||
"enable_all_modules": "Alle Module werden aktiviert. Fortfahren?",
|
||||
"disable_optional_modules": "Alle optionalen Module werden deaktiviert, nur Kernmodule bleiben aktiv. Fortfahren?",
|
||||
"reset_theme": "Theme auf Standard zurücksetzen? Dies kann nicht rückgängig gemacht werden.",
|
||||
"show_all_menu_items": "Alle Menüpunkte werden angezeigt. Fortfahren?",
|
||||
"hide_all_menu_items": "Alle Menüpunkte werden ausgeblendet (außer obligatorische). Sie können dann die gewünschten aktivieren. Fortfahren?"
|
||||
},
|
||||
"features": {
|
||||
"team_members": {
|
||||
"name": "Teammitglieder",
|
||||
|
||||
@@ -90,6 +90,13 @@
|
||||
"failed_to_load_user": "Failed to load user",
|
||||
"user_updated_successfully": "User updated successfully"
|
||||
},
|
||||
"confirmations": {
|
||||
"enable_all_modules": "Ceci activera tous les modules. Continuer ?",
|
||||
"disable_optional_modules": "Ceci désactivera tous les modules optionnels, ne conservant que les modules principaux. Continuer ?",
|
||||
"reset_theme": "Réinitialiser le thème par défaut ? Cette action est irréversible.",
|
||||
"show_all_menu_items": "Ceci affichera tous les éléments de menu. Continuer ?",
|
||||
"hide_all_menu_items": "Ceci masquera tous les éléments de menu (sauf les obligatoires). Vous pourrez ensuite activer ceux que vous souhaitez. Continuer ?"
|
||||
},
|
||||
"features": {
|
||||
"team_members": {
|
||||
"name": "Membres de l'équipe",
|
||||
|
||||
@@ -90,6 +90,13 @@
|
||||
"failed_to_load_user": "Failed to load user",
|
||||
"user_updated_successfully": "User updated successfully"
|
||||
},
|
||||
"confirmations": {
|
||||
"enable_all_modules": "All Moduler ginn aktivéiert. Weidermaachen?",
|
||||
"disable_optional_modules": "All optional Moduler ginn deaktivéiert, nëmmen Kärmoduler bleiwen aktiv. Weidermaachen?",
|
||||
"reset_theme": "Theme op Standard zrécksetzen? Dëst kann net réckgängeg gemaach ginn.",
|
||||
"show_all_menu_items": "All Menüpunkten ginn ugewisen. Weidermaachen?",
|
||||
"hide_all_menu_items": "All Menüpunkten ginn verstopp (ausser obligatoresch). Dir kënnt dann déi gewënscht aktivéieren. Weidermaachen?"
|
||||
},
|
||||
"features": {
|
||||
"team_members": {
|
||||
"name": "Team-Memberen",
|
||||
|
||||
@@ -220,6 +220,10 @@
|
||||
"datetime": "DD.MM.YYYY HH:mm",
|
||||
"currency": "{amount} {symbol}"
|
||||
},
|
||||
"clipboard": {
|
||||
"copied": "In die Zwischenablage kopiert",
|
||||
"failed": "Kopieren fehlgeschlagen"
|
||||
},
|
||||
"onboarding": {
|
||||
"banner": {
|
||||
"title": "Erste Schritte",
|
||||
|
||||
@@ -220,6 +220,10 @@
|
||||
"datetime": "DD/MM/YYYY HH:mm",
|
||||
"currency": "{amount} {symbol}"
|
||||
},
|
||||
"clipboard": {
|
||||
"copied": "Copié dans le presse-papiers",
|
||||
"failed": "Échec de la copie"
|
||||
},
|
||||
"onboarding": {
|
||||
"banner": {
|
||||
"title": "Premiers pas",
|
||||
|
||||
@@ -220,6 +220,10 @@
|
||||
"datetime": "DD.MM.YYYY HH:mm",
|
||||
"currency": "{amount} {symbol}"
|
||||
},
|
||||
"clipboard": {
|
||||
"copied": "An d'Zwëschenoflag kopéiert",
|
||||
"failed": "Kopéiere feelgeschloen"
|
||||
},
|
||||
"onboarding": {
|
||||
"banner": {
|
||||
"title": "Ufänken",
|
||||
|
||||
Reference in New Issue
Block a user