Add localization support for various components, including dialogs and views, in English, Spanish, and French. Implemented translations for user profile management, payment processes, and creator functionalities. Updated existing components to utilize the new translation system.
This commit is contained in:
3
frontend/src/views/creators/ActualBanner.en.json
Normal file
3
frontend/src/views/creators/ActualBanner.en.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"alt": "Creator banner"
|
||||
}
|
||||
3
frontend/src/views/creators/ActualBanner.es.json
Normal file
3
frontend/src/views/creators/ActualBanner.es.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"alt": "Banner del creador"
|
||||
}
|
||||
3
frontend/src/views/creators/ActualBanner.fr.json
Normal file
3
frontend/src/views/creators/ActualBanner.fr.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"alt": "Bannière du créateur"
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
<img
|
||||
class="w-[990px] h-[330px] banner object-cover"
|
||||
:src="brandingStore.value?.images?.banner ?? '/images/placeholders/banner.png'"
|
||||
alt="Profile Banner"
|
||||
:alt="t('alt')"
|
||||
>
|
||||
<!-- Tint Effect -->
|
||||
<div
|
||||
@@ -43,9 +43,11 @@ import BannerEditor from "@/views/creators/BannerEditor.vue";
|
||||
import {computed, ref} from "vue";
|
||||
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||
import {useAuthStore} from "@/stores/authStore.js";
|
||||
import { useTranslations } from '@/translations/translations';
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const brandingStore = useBrandingStore();
|
||||
const t = useTranslations();
|
||||
|
||||
// State
|
||||
const showTint = ref(false);
|
||||
|
||||
12
frontend/src/views/creators/BannerActions.en.json
Normal file
12
frontend/src/views/creators/BannerActions.en.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"social": {
|
||||
"facebook": "Facebook",
|
||||
"instagram": "Instagram",
|
||||
"linkedin": "LinkedIn",
|
||||
"reddit": "Reddit",
|
||||
"tiktok": "TikTok",
|
||||
"x": "X (Twitter)",
|
||||
"youtube": "YouTube",
|
||||
"website": "Website"
|
||||
}
|
||||
}
|
||||
12
frontend/src/views/creators/BannerActions.es.json
Normal file
12
frontend/src/views/creators/BannerActions.es.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"social": {
|
||||
"facebook": "Facebook",
|
||||
"instagram": "Instagram",
|
||||
"linkedin": "LinkedIn",
|
||||
"reddit": "Reddit",
|
||||
"tiktok": "TikTok",
|
||||
"x": "X (Twitter)",
|
||||
"youtube": "YouTube",
|
||||
"website": "Sitio Web"
|
||||
}
|
||||
}
|
||||
12
frontend/src/views/creators/BannerActions.fr.json
Normal file
12
frontend/src/views/creators/BannerActions.fr.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"social": {
|
||||
"facebook": "Facebook",
|
||||
"instagram": "Instagram",
|
||||
"linkedin": "LinkedIn",
|
||||
"reddit": "Reddit",
|
||||
"tiktok": "TikTok",
|
||||
"x": "X (Twitter)",
|
||||
"youtube": "YouTube",
|
||||
"website": "Site Web"
|
||||
}
|
||||
}
|
||||
@@ -12,11 +12,11 @@ import Tiktok from "@/views/svg/Tiktok.vue";
|
||||
import Reddit from "@/views/svg/Reddit.vue";
|
||||
import Youtube from "@/views/svg/Youtube.vue";
|
||||
import Web from "@/views/svg/Web.vue";
|
||||
import { useTranslations } from '@/translations/translations'
|
||||
|
||||
const brandingStore = useBrandingStore();
|
||||
const baseURL = window.location.origin;
|
||||
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
// Gèrer le breakpoint du block information.
|
||||
// Définir un point de rupture pour "moyen" (correspondant à md: de Tailwind)
|
||||
@@ -88,49 +88,57 @@ onUnmounted(() => {
|
||||
|
||||
<a v-if="brandingStore.value?.socials?.facebookUrl"
|
||||
:href="brandingStore.value?.socials?.facebookUrl"
|
||||
target="_blank">
|
||||
target="_blank"
|
||||
:title="t('social.facebook')">
|
||||
<facebook class="social-icon"></facebook>
|
||||
</a>
|
||||
|
||||
<a v-if="brandingStore.value?.socials?.instagramUrl"
|
||||
:href="brandingStore.value?.socials?.instagramUrl"
|
||||
target="_blank">
|
||||
target="_blank"
|
||||
:title="t('social.instagram')">
|
||||
<instagram class="social-icon"></instagram>
|
||||
</a>
|
||||
|
||||
<a v-if="brandingStore.value?.socials?.linkedInUrl"
|
||||
:href="brandingStore.value?.socials?.linkedInUrl"
|
||||
target="_blank">
|
||||
target="_blank"
|
||||
:title="t('social.linkedin')">
|
||||
<linkedin class="social-icon"></linkedin>
|
||||
</a>
|
||||
|
||||
<a v-if="brandingStore.value?.socials?.redditUrl"
|
||||
:href="brandingStore.value?.socials?.redditUrl"
|
||||
target="_blank">
|
||||
target="_blank"
|
||||
:title="t('social.reddit')">
|
||||
<reddit class="social-icon"></reddit>
|
||||
</a>
|
||||
|
||||
<a v-if="brandingStore.value?.socials?.tikTokUrl"
|
||||
:href="brandingStore.value?.socials?.tikTokUrl"
|
||||
target="_blank">
|
||||
target="_blank"
|
||||
:title="t('social.tiktok')">
|
||||
<tiktok class="social-icon"></tiktok>
|
||||
</a>
|
||||
|
||||
<a v-if="brandingStore.value?.socials?.xUrl"
|
||||
:href="brandingStore.value?.socials?.xUrl"
|
||||
target="_blank">
|
||||
target="_blank"
|
||||
:title="t('social.x')">
|
||||
<x class="social-icon"></x>
|
||||
</a>
|
||||
|
||||
<a v-if="brandingStore.value?.socials?.youtubeUrl"
|
||||
:href="brandingStore.value?.socials?.youtubeUrl"
|
||||
target="_blank">
|
||||
target="_blank"
|
||||
:title="t('social.youtube')">
|
||||
<youtube class="social-icon"></youtube>
|
||||
</a>
|
||||
|
||||
<a v-if="brandingStore.value?.socials?.websiteUrl"
|
||||
:href="brandingStore.value?.socials?.websiteUrl"
|
||||
target="_blank">
|
||||
target="_blank"
|
||||
:title="t('social.website')">
|
||||
<web class="social-icon"></web>
|
||||
</a>
|
||||
|
||||
|
||||
7
frontend/src/views/creators/BannerEditor.en.json
Normal file
7
frontend/src/views/creators/BannerEditor.en.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "Choose your Banner",
|
||||
"description": "The banner must have a 3:1 ratio. Target dimensions are 960 x 320.",
|
||||
"chooseImage": "Choose an image...",
|
||||
"clickToEdit": "Click to edit",
|
||||
"preview": "Banner preview"
|
||||
}
|
||||
7
frontend/src/views/creators/BannerEditor.es.json
Normal file
7
frontend/src/views/creators/BannerEditor.es.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "Elige tu Banner",
|
||||
"description": "El banner debe tener una relación de 3:1. Las dimensiones objetivo son 960 x 320.",
|
||||
"chooseImage": "Elegir una imagen...",
|
||||
"clickToEdit": "Clic para editar",
|
||||
"preview": "Vista previa del banner"
|
||||
}
|
||||
7
frontend/src/views/creators/BannerEditor.fr.json
Normal file
7
frontend/src/views/creators/BannerEditor.fr.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "Choisissez votre Bannière",
|
||||
"description": "La bannière doit avoir un ratio de 3:1. Les dimensions cibles sont 960 x 320.",
|
||||
"chooseImage": "Choisir une image...",
|
||||
"clickToEdit": "Cliquez pour modifier",
|
||||
"preview": "Aperçu de la bannière"
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<div class="card-title">
|
||||
Choisissez votre Bannière
|
||||
{{ t('title') }}
|
||||
</div>
|
||||
|
||||
<div class="card-content">
|
||||
<p class="card-text">
|
||||
La bannière doit avoir un ratio de 3:1. Les dimensions cibles sont 960 x 320.
|
||||
{{ t('description') }}
|
||||
</p>
|
||||
|
||||
<div class="file-input-container">
|
||||
@@ -21,7 +21,7 @@
|
||||
class="choose-file-button"
|
||||
@click="triggerFileInput"
|
||||
>
|
||||
Choisir une image...
|
||||
{{ t('chooseImage') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -44,11 +44,11 @@
|
||||
<div v-else class="image-preview-container" @click="startEditing">
|
||||
<img
|
||||
:src="fileUrl || fallbackUrl"
|
||||
alt="Aperçu de la bannière"
|
||||
:alt="t('preview')"
|
||||
class="preview-image"
|
||||
/>
|
||||
<div class="edit-overlay">
|
||||
<span class="edit-text">Cliquez pour modifier</span>
|
||||
<span class="edit-text">{{ t('clickToEdit') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -56,12 +56,12 @@
|
||||
<div class="card-actions">
|
||||
<button class="secondary"
|
||||
@click="cancel">
|
||||
Annuler
|
||||
{{ t('cancel') }}
|
||||
</button>
|
||||
<button class="primary"
|
||||
@click="showCropper ? applyCrop() : publish()"
|
||||
:disabled="!selectedFile">
|
||||
{{ showCropper ? 'Appliquer' : 'Enregistrer' }}
|
||||
{{ showCropper ? t('apply') : t('save') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,6 +72,7 @@ import {ref} from 'vue'
|
||||
import {useClient} from '@/plugins/api.js'
|
||||
import { Cropper } from 'vue-advanced-cropper'
|
||||
import 'vue-advanced-cropper/dist/style.css'
|
||||
import { useTranslations } from '@/translations/translations'
|
||||
|
||||
const props = defineProps({
|
||||
creator: {
|
||||
@@ -92,6 +93,9 @@ const cropper = ref(null)
|
||||
const TARGET_WIDTH = 960
|
||||
const TARGET_HEIGHT = 320
|
||||
|
||||
// Get translations for this component
|
||||
const t = useTranslations()
|
||||
|
||||
const triggerFileInput = () => {
|
||||
fileInput.value.click()
|
||||
}
|
||||
@@ -126,7 +130,7 @@ const startEditing = () => {
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading image for editing:', error)
|
||||
errorMessage.value = 'Une erreur est survenue lors du chargement de l\'image'
|
||||
errorMessage.value = t('errors.imageLoad')
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -162,7 +166,7 @@ const publish = async () => {
|
||||
emits('closeRequested')
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
errorMessage.value = 'Une erreur est survenue lors de l\'envoi de l\'image'
|
||||
errorMessage.value = t('errors.imageUpload')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3
frontend/src/views/creators/CreateCreator.en.json
Normal file
3
frontend/src/views/creators/CreateCreator.en.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Create your Hutopy"
|
||||
}
|
||||
3
frontend/src/views/creators/CreateCreator.es.json
Normal file
3
frontend/src/views/creators/CreateCreator.es.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Crea tu Hutopy"
|
||||
}
|
||||
3
frontend/src/views/creators/CreateCreator.fr.json
Normal file
3
frontend/src/views/creators/CreateCreator.fr.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Créez votre Hutopy"
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import {useCreatorProfileStore} from "@/stores/creatorProfileStore.js";
|
||||
import {useClient} from "@/plugins/api.js";
|
||||
import {useRouter, useRoute} from "vue-router";
|
||||
import NameEditor from "@/views/creators/NameEditor.vue";
|
||||
import { useTranslations } from '@/translations/translations'
|
||||
|
||||
const creatorName = ref('');
|
||||
const creatorNameReservationId = ref(undefined);
|
||||
@@ -17,6 +18,7 @@ const router = useRouter();
|
||||
const route = useRoute();
|
||||
const creatorProfileStore = useCreatorProfileStore();
|
||||
const userProfileStore = useUserProfileStore();
|
||||
const t = useTranslations();
|
||||
|
||||
function handleCreatorNameReservationIdChanged($event) {
|
||||
creatorNameReservationId.value = $event
|
||||
@@ -48,9 +50,9 @@ async function createAccount() {
|
||||
await router.push(`/@${creatorProfileStore.creator.slug}`);
|
||||
} catch (error) {
|
||||
if (error?.response?.data?.errors) {
|
||||
errorMessage.value = error.response.data.errors[0]?.['reason'] || 'An unexpected error occurred.';
|
||||
errorMessage.value = error.response.data.errors[0]?.['reason'] || t('errors.unexpected');
|
||||
} else {
|
||||
errorMessage.value = error?.response?.data?.message || error.message || 'An unexpected error occurred.';
|
||||
errorMessage.value = error?.response?.data?.message || error.message || t('errors.unexpected');
|
||||
}
|
||||
} finally {
|
||||
isOperationPending.value = false;
|
||||
@@ -64,7 +66,7 @@ async function createAccount() {
|
||||
<div class="card">
|
||||
|
||||
<div class="card-title">
|
||||
Créez votre Hutopy.
|
||||
{{ t('title') }}
|
||||
</div>
|
||||
|
||||
<div class="card-content">
|
||||
@@ -79,13 +81,13 @@ async function createAccount() {
|
||||
<button
|
||||
class="secondary"
|
||||
@click="cancel">
|
||||
Cancel
|
||||
{{ t('cancel') }}
|
||||
</button>
|
||||
<button
|
||||
class="primary"
|
||||
:disabled="!canSave || isOperationPending"
|
||||
@click="createAccount">
|
||||
Créer
|
||||
{{ t('create') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
19
frontend/src/views/creators/CreatorHome.en.json
Normal file
19
frontend/src/views/creators/CreatorHome.en.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"sections": {
|
||||
"about": {
|
||||
"title": "About Us",
|
||||
"description": "Description",
|
||||
"mainImage": "Main image"
|
||||
},
|
||||
"support": {
|
||||
"title": "Why Support Us",
|
||||
"description": "Description",
|
||||
"subtitle": "Subtitle"
|
||||
}
|
||||
},
|
||||
"fields": {
|
||||
"phoneNumber": "Phone Number",
|
||||
"email": "Email Address",
|
||||
"videoUrl": "Video URL"
|
||||
}
|
||||
}
|
||||
19
frontend/src/views/creators/CreatorHome.es.json
Normal file
19
frontend/src/views/creators/CreatorHome.es.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"sections": {
|
||||
"about": {
|
||||
"title": "Quiénes Somos",
|
||||
"description": "Descripción",
|
||||
"mainImage": "Imagen principal"
|
||||
},
|
||||
"support": {
|
||||
"title": "Por Qué Apoyarnos",
|
||||
"description": "Descripción",
|
||||
"subtitle": "Subtítulo"
|
||||
}
|
||||
},
|
||||
"fields": {
|
||||
"phoneNumber": "Número de Teléfono",
|
||||
"email": "Dirección de Correo",
|
||||
"videoUrl": "URL del Video"
|
||||
}
|
||||
}
|
||||
19
frontend/src/views/creators/CreatorHome.fr.json
Normal file
19
frontend/src/views/creators/CreatorHome.fr.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"sections": {
|
||||
"about": {
|
||||
"title": "Qui sommes-nous",
|
||||
"description": "Description",
|
||||
"mainImage": "Image principale"
|
||||
},
|
||||
"support": {
|
||||
"title": "Pourquoi nous supporter",
|
||||
"description": "Description",
|
||||
"subtitle": "Sous-titre"
|
||||
}
|
||||
},
|
||||
"fields": {
|
||||
"phoneNumber": "Numéro de Téléphone",
|
||||
"email": "Adresse Email",
|
||||
"videoUrl": "URL Vidéo"
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
class="primary"
|
||||
@click="isEditMode ? saveChanges() : toggleEditMode()"
|
||||
>
|
||||
{{ isEditMode ? 'Enregistrer' : 'Éditer la page' }}
|
||||
{{ isEditMode ? t('save') : t('edit') }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
@@ -17,14 +17,14 @@
|
||||
class="secondary"
|
||||
@click="cancelEdit"
|
||||
>
|
||||
Annuler
|
||||
{{ t('cancel') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- MainPage -->
|
||||
<div class="flex flex-col mt-4">
|
||||
|
||||
<h1 class="flex justify-start text-2xl font-bold text-center mb-4">Qui sommes-nous</h1>
|
||||
<h1 class="flex justify-start text-2xl font-bold text-center mb-4">{{ t('sections.about.title') }}</h1>
|
||||
|
||||
<div>
|
||||
<!-- Main image Bloc D'information-->
|
||||
@@ -35,7 +35,7 @@
|
||||
{{ mainImageText }}
|
||||
</p>
|
||||
</div>
|
||||
<v-textarea v-if="isEditMode" v-model="editableMainImageText" class="w-full p-2 py-6 " label="Description"
|
||||
<v-textarea v-if="isEditMode" v-model="editableMainImageText" class="w-full p-2 py-6 " :label="t('sections.about.description')"
|
||||
variant="outlined"></v-textarea>
|
||||
|
||||
<div class="flex flex-row items-center space-x-4">
|
||||
@@ -44,26 +44,26 @@
|
||||
<img
|
||||
v-if="mainImageUrl"
|
||||
:src="mainImageUrl"
|
||||
alt="Image principale"
|
||||
:alt="t('sections.about.mainImage')"
|
||||
class="max-w-full h-auto cursor-pointer"/>
|
||||
</div>
|
||||
<div v-if="isEditMode" class="relative flex justify-center">
|
||||
<label>
|
||||
<input class="hidden" type="file" @change="updateImage('mainImageUrl', $event)"/>
|
||||
<img :src="mainImageUrl || fallbackImage"
|
||||
alt="Image principale"
|
||||
:alt="t('sections.about.mainImage')"
|
||||
class=" max-w-full h-auto cursor-pointer max-h-96"/>
|
||||
</label>
|
||||
<button v-if="isEditMode"
|
||||
class="absolute top-10 right-2 px-2 py-1 bg-red-500 text-white hover:bg-red-600"
|
||||
@click="deleteImage('mainImageUrl')">
|
||||
X
|
||||
{{ t('delete') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="w-1/2 flex flex-col justify-center">
|
||||
<h2 v-if="videoSubtitleMain" class="text-xl font-semibold text-center">
|
||||
Pourquoi nous supporter
|
||||
{{ t('sections.support.title') }}
|
||||
</h2>
|
||||
|
||||
<div v-if="!isEditMode">
|
||||
@@ -76,7 +76,7 @@
|
||||
<v-textarea
|
||||
v-model="editableMainVideoText"
|
||||
class="p-2 rounded-md mt-4"
|
||||
label="Description"
|
||||
:label="t('sections.support.description')"
|
||||
rows="10"
|
||||
variant="outlined"
|
||||
></v-textarea>
|
||||
@@ -92,23 +92,17 @@
|
||||
<v-text-field
|
||||
v-model="editableVideoSubtitle"
|
||||
class="w-full p-2"
|
||||
label="Titre"
|
||||
:label="t('sections.support.subtitle')"
|
||||
variant="outlined"
|
||||
></v-text-field>
|
||||
</div>
|
||||
|
||||
<v-textarea v-if="isEditMode"
|
||||
v-model="editableImagesText"
|
||||
class="w-full p-2 border rounded-md"
|
||||
rows="10"
|
||||
variant="outlined">
|
||||
</v-textarea>
|
||||
|
||||
<div v-if="!isEditMode">
|
||||
<p v-if="imagesText" class="text-lg text-justify">
|
||||
{{ imagesText }}
|
||||
</p>
|
||||
</div>
|
||||
v-model="editableVideoText"
|
||||
class="w-full p-2"
|
||||
:label="t('sections.support.description')"
|
||||
variant="outlined"
|
||||
></v-textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -127,10 +121,9 @@
|
||||
|
||||
<div v-if="isEditMode">
|
||||
<v-text-field
|
||||
v-if="isEditMode"
|
||||
v-model="editableVideoUrlMain"
|
||||
class="w-full p-2 rounded-md"
|
||||
label="URL Video"
|
||||
:label="t('fields.videoUrl')"
|
||||
type="text"
|
||||
variant="outlined"
|
||||
/>
|
||||
@@ -248,14 +241,14 @@
|
||||
<v-text-field
|
||||
v-model="editablePhoneNumber"
|
||||
class="w-full p-2"
|
||||
label="Numéro de Téléphone"
|
||||
:label="t('fields.phoneNumber')"
|
||||
variant="outlined"
|
||||
></v-text-field>
|
||||
|
||||
<v-text-field
|
||||
v-model="editableEmail"
|
||||
class="w-full p-2"
|
||||
label="Adresse Email"
|
||||
:label="t('fields.email')"
|
||||
variant="outlined"
|
||||
></v-text-field>
|
||||
</div>
|
||||
@@ -290,9 +283,13 @@ import {onMounted, ref} from "vue";
|
||||
import {useClient} from "@/plugins/api.js";
|
||||
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||
import {useCreatorProfileStore} from "@/stores/creatorProfileStore.js";
|
||||
import {useAuthStore} from "@/stores/authStore.js";
|
||||
import {useTranslations} from '@/translations/translations'
|
||||
|
||||
const creatorProfileStore = useCreatorProfileStore();
|
||||
const brandingStore = useBrandingStore();
|
||||
const authStore = useAuthStore();
|
||||
const t = useTranslations();
|
||||
const client = useClient();
|
||||
|
||||
const isLoading = ref(true);
|
||||
|
||||
5
frontend/src/views/creators/CreatorLayout.en.json
Normal file
5
frontend/src/views/creators/CreatorLayout.en.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"deletion": {
|
||||
"pending": "This Creator page is pending deletion. You can revert the action in your profile."
|
||||
}
|
||||
}
|
||||
5
frontend/src/views/creators/CreatorLayout.es.json
Normal file
5
frontend/src/views/creators/CreatorLayout.es.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"deletion": {
|
||||
"pending": "Esta página de creador está pendiente de eliminación. Puede revertir la acción en su perfil."
|
||||
}
|
||||
}
|
||||
5
frontend/src/views/creators/CreatorLayout.fr.json
Normal file
5
frontend/src/views/creators/CreatorLayout.fr.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"deletion": {
|
||||
"pending": "Cette page de créateur est en attente de suppression. Vous pouvez annuler l'action dans votre profil."
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,11 @@ import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||
import {onMounted} from "vue";
|
||||
import Banner from "@/views/creators/Banner.vue";
|
||||
import Footer from "@/views/main/Footer.vue";
|
||||
import { useTranslations } from '@/translations/translations'
|
||||
|
||||
const brandingStore = useBrandingStore();
|
||||
const creatorName = window.location.pathname.split('/@').pop();
|
||||
const t = useTranslations();
|
||||
|
||||
onMounted(async () => {
|
||||
await brandingStore.updateBrand(creatorName);
|
||||
@@ -23,7 +25,7 @@ onMounted(async () => {
|
||||
<div v-else>
|
||||
<div v-if="brandingStore.value.isDeleted"
|
||||
class="bg-red-500 p-2 m-4 text-center font-semibold">
|
||||
This Creator page is pending deletion. You can revert the action in your profile.
|
||||
{{ t('deletion.pending') }}
|
||||
</div>
|
||||
<banner></banner>
|
||||
<router-view></router-view>
|
||||
|
||||
4
frontend/src/views/creators/CreatorLogo.en.json
Normal file
4
frontend/src/views/creators/CreatorLogo.en.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"alt": "Profile Picture",
|
||||
"edit": "Edit Profile Picture"
|
||||
}
|
||||
4
frontend/src/views/creators/CreatorLogo.es.json
Normal file
4
frontend/src/views/creators/CreatorLogo.es.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"alt": "Foto de perfil",
|
||||
"edit": "Editar foto de perfil"
|
||||
}
|
||||
4
frontend/src/views/creators/CreatorLogo.fr.json
Normal file
4
frontend/src/views/creators/CreatorLogo.fr.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"alt": "Photo de profil",
|
||||
"edit": "Modifier la photo de profil"
|
||||
}
|
||||
@@ -8,13 +8,14 @@
|
||||
<img
|
||||
class="shadow-2xl object-cover rounded-full border-solid border-hSecondary border-102 w-[200px] h-[200px] logo-image"
|
||||
:src="brandingStore.value.images?.logo ?? '/images/placeholders/profile.png'"
|
||||
alt="Profile Picture"
|
||||
:alt="t('alt')"
|
||||
/>
|
||||
|
||||
<!-- Tint Effect -->
|
||||
<div
|
||||
v-if="showTint"
|
||||
class="absolute rounded-full inset-0 bg-black/25 cursor-pointer"
|
||||
:title="t('edit')"
|
||||
>
|
||||
<!-- Top-right Icon -->
|
||||
<div
|
||||
@@ -42,9 +43,11 @@ import {useAuthStore} from "@/stores/authStore.js";
|
||||
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||
import CreatorLogoEditor from "@/views/creators/CreatorLogoEditor.vue";
|
||||
import {computed, ref} from "vue";
|
||||
import { useTranslations } from '@/translations/translations'
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const brandingStore = useBrandingStore();
|
||||
const t = useTranslations();
|
||||
|
||||
// State
|
||||
const showTint = ref(false);
|
||||
|
||||
7
frontend/src/views/creators/CreatorLogoEditor.en.json
Normal file
7
frontend/src/views/creators/CreatorLogoEditor.en.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "Choose your Logo",
|
||||
"description": "The logo must be square. Recommended dimensions are 200 x 200 pixels.",
|
||||
"chooseImage": "Choose an image...",
|
||||
"clickToEdit": "Click to edit",
|
||||
"preview": "Logo preview"
|
||||
}
|
||||
7
frontend/src/views/creators/CreatorLogoEditor.es.json
Normal file
7
frontend/src/views/creators/CreatorLogoEditor.es.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "Elige tu Logo",
|
||||
"description": "El logo debe ser cuadrado. Las dimensiones recomendadas son 200 x 200 píxeles.",
|
||||
"chooseImage": "Elegir una imagen...",
|
||||
"clickToEdit": "Clic para editar",
|
||||
"preview": "Vista previa del logo"
|
||||
}
|
||||
7
frontend/src/views/creators/CreatorLogoEditor.fr.json
Normal file
7
frontend/src/views/creators/CreatorLogoEditor.fr.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "Choisissez votre Logo",
|
||||
"description": "Le logo doit être carré. Les dimensions recommandées sont 200 x 200 pixels.",
|
||||
"chooseImage": "Choisir une image...",
|
||||
"clickToEdit": "Cliquez pour modifier",
|
||||
"preview": "Aperçu du logo"
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<div class="card-title">
|
||||
Choisissez votre Logo
|
||||
{{ t('title') }}
|
||||
</div>
|
||||
|
||||
<div class="card-content">
|
||||
<p class="card-text">
|
||||
Le logo doit être carré. Les dimensions recommandées sont 200 x 200 pixels.
|
||||
{{ t('description') }}
|
||||
</p>
|
||||
|
||||
<div class="file-input-container">
|
||||
@@ -21,7 +21,7 @@
|
||||
class="choose-file-button"
|
||||
@click="triggerFileInput"
|
||||
>
|
||||
Choisir une image...
|
||||
{{ t('chooseImage') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -46,11 +46,11 @@
|
||||
<div class="circular-preview">
|
||||
<img
|
||||
:src="fileUrl || fallbackUrl"
|
||||
alt="Aperçu du logo"
|
||||
:alt="t('preview')"
|
||||
class="preview-image"
|
||||
/>
|
||||
<div class="edit-overlay">
|
||||
<span class="edit-text">Cliquez pour modifier</span>
|
||||
<span class="edit-text">{{ t('clickToEdit') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -59,12 +59,12 @@
|
||||
<div class="card-actions">
|
||||
<button class="secondary"
|
||||
@click="cancel">
|
||||
Annuler
|
||||
{{ t('cancel') }}
|
||||
</button>
|
||||
<button class="primary"
|
||||
@click="showCropper ? applyCrop() : publish()"
|
||||
:disabled="!selectedFile">
|
||||
{{ showCropper ? 'Appliquer' : 'Enregistrer' }}
|
||||
{{ showCropper ? t('apply') : t('save') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,6 +75,7 @@ import {ref} from 'vue'
|
||||
import {useClient} from '@/plugins/api.js'
|
||||
import { Cropper, CircleStencil } from 'vue-advanced-cropper'
|
||||
import 'vue-advanced-cropper/dist/style.css'
|
||||
import { useTranslations } from '@/translations/translations'
|
||||
|
||||
const props = defineProps({
|
||||
creator: {
|
||||
@@ -95,6 +96,9 @@ const cropper = ref(null)
|
||||
const TARGET_WIDTH = 200
|
||||
const TARGET_HEIGHT = 200
|
||||
|
||||
// Get translations for this component
|
||||
const t = useTranslations()
|
||||
|
||||
const triggerFileInput = () => {
|
||||
fileInput.value.click()
|
||||
}
|
||||
@@ -129,7 +133,7 @@ const startEditing = () => {
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading image for editing:', error)
|
||||
errorMessage.value = 'Une erreur est survenue lors du chargement de l\'image'
|
||||
errorMessage.value = t('errors.imageLoad')
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -165,7 +169,7 @@ const publish = async () => {
|
||||
emits('closeRequested')
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
errorMessage.value = 'Une erreur est survenue lors de l\'envoi de l\'image'
|
||||
errorMessage.value = t('errors.imageUpload')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
10
frontend/src/views/creators/DonationButtonBanner.en.json
Normal file
10
frontend/src/views/creators/DonationButtonBanner.en.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"isupport": "I Support",
|
||||
"amount": "Amount",
|
||||
"message": "Message",
|
||||
"send": "Send",
|
||||
"cancel": "Cancel",
|
||||
"errors": {
|
||||
"payment": "An error occurred during payment processing"
|
||||
}
|
||||
}
|
||||
10
frontend/src/views/creators/DonationButtonBanner.es.json
Normal file
10
frontend/src/views/creators/DonationButtonBanner.es.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"isupport": "Apoyo",
|
||||
"amount": "Cantidad",
|
||||
"message": "Mensaje",
|
||||
"send": "Enviar",
|
||||
"cancel": "Cancelar",
|
||||
"errors": {
|
||||
"payment": "Ocurrió un error durante el procesamiento del pago"
|
||||
}
|
||||
}
|
||||
10
frontend/src/views/creators/DonationButtonBanner.fr.json
Normal file
10
frontend/src/views/creators/DonationButtonBanner.fr.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"isupport": "Je Soutiens",
|
||||
"amount": "Montant",
|
||||
"message": "Message",
|
||||
"send": "Envoyer",
|
||||
"cancel": "Annuler",
|
||||
"errors": {
|
||||
"payment": "Une erreur s'est produite lors du traitement du paiement"
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,13 @@
|
||||
class="secondary donation-action"
|
||||
@click="openDonationDialog()"
|
||||
>
|
||||
{{ $t('isupportbtn.isupport') }}
|
||||
{{ t('isupport') }}
|
||||
</button>
|
||||
|
||||
<v-dialog v-model="donationModal">
|
||||
<div class="card">
|
||||
<div class="card-title">
|
||||
{{ $t('isupportbtn.isupport') }}
|
||||
{{ t('isupport') }}
|
||||
</div>
|
||||
|
||||
<div class="card-content">
|
||||
@@ -20,7 +20,7 @@
|
||||
placeholder="0"
|
||||
:min="0"
|
||||
class="p-2"
|
||||
:label="`${$t('isupportbtn.amount')}`"
|
||||
:label="t('amount')"
|
||||
density="comfortable"
|
||||
variant="outlined"
|
||||
hide-details
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
<v-textarea
|
||||
v-model="tipMessage"
|
||||
:label="`${$t('isupportbtn.message')}`"
|
||||
:label="t('message')"
|
||||
class="p-2"
|
||||
density="comfortable"
|
||||
variant="outlined"
|
||||
@@ -45,12 +45,12 @@
|
||||
|
||||
<button class="secondary"
|
||||
@click="closeDonationDialog()">
|
||||
Cancel
|
||||
{{ t('cancel') }}
|
||||
</button>
|
||||
|
||||
<button class="primary"
|
||||
@click="goPay()">
|
||||
{{ $t('isupportbtn.send') }}
|
||||
{{ t('send') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
@@ -71,7 +71,7 @@
|
||||
class="ma-auto"
|
||||
style="width: 200px"
|
||||
@click="closeDialog()"
|
||||
>Annuler
|
||||
>{{ t('cancel') }}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
@@ -84,8 +84,10 @@ import {useClient} from '@/plugins/api.js';
|
||||
import {useBrandingStore} from '@/stores/brandingStore.js';
|
||||
import {loadStripe} from '@stripe/stripe-js';
|
||||
import {onMounted, ref} from 'vue';
|
||||
import { useTranslations } from '@/translations/translations'
|
||||
|
||||
const brandingStore = useBrandingStore();
|
||||
const t = useTranslations();
|
||||
|
||||
const props = defineProps({
|
||||
creatorId: {default: 'missing-creator-id', required: true},
|
||||
@@ -134,7 +136,7 @@ async function createCheckoutSession() {
|
||||
return clientSecret.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
errorMessage.value = 'Une erreur est survenue. Veuillez réessayer.';
|
||||
errorMessage.value = t('errors.payment');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3
frontend/src/views/creators/NameEditor.en.json
Normal file
3
frontend/src/views/creators/NameEditor.en.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"label": "Page name"
|
||||
}
|
||||
3
frontend/src/views/creators/NameEditor.es.json
Normal file
3
frontend/src/views/creators/NameEditor.es.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"label": "Nombre de la página"
|
||||
}
|
||||
4
frontend/src/views/creators/NameEditor.fr.json
Normal file
4
frontend/src/views/creators/NameEditor.fr.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Nom de la page"
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
import {ref, onMounted, onUnmounted} from "vue";
|
||||
import {v7} from "uuid";
|
||||
import {useClient} from "@/plugins/api.js";
|
||||
import { useTranslations } from '@/translations/translations'
|
||||
|
||||
const props = defineProps({
|
||||
name: {
|
||||
@@ -18,6 +19,7 @@ const emits = defineEmits([
|
||||
]);
|
||||
|
||||
const name = ref(props.name);
|
||||
const t = useTranslations();
|
||||
|
||||
const isOperationPending = ref(false);
|
||||
const reservationState = ref(null);
|
||||
@@ -110,7 +112,7 @@ onUnmounted(() => {
|
||||
<template>
|
||||
<v-text-field
|
||||
variant="outlined"
|
||||
label="Nom de la page"
|
||||
:label="t('label')"
|
||||
v-model="name"
|
||||
outlined
|
||||
@input="handleInput"
|
||||
|
||||
3
frontend/src/views/creators/NameTitle.en.json
Normal file
3
frontend/src/views/creators/NameTitle.en.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"verified": "Verified Account"
|
||||
}
|
||||
3
frontend/src/views/creators/NameTitle.es.json
Normal file
3
frontend/src/views/creators/NameTitle.es.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"verified": "Cuenta Verificada"
|
||||
}
|
||||
3
frontend/src/views/creators/NameTitle.fr.json
Normal file
3
frontend/src/views/creators/NameTitle.fr.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"verified": "Compte Vérifié"
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
|
||||
<div v-show="brandingStore.value.verified"
|
||||
class="text-blue m-4">
|
||||
class="text-blue m-4"
|
||||
:title="t('verified')">
|
||||
<icon-account-verified></icon-account-verified>
|
||||
</div>
|
||||
|
||||
@@ -20,5 +21,8 @@
|
||||
<script setup>
|
||||
import IconAccountVerified from "@/components/icons/IconAccountVerified.vue";
|
||||
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||
import { useTranslations } from '@/translations/translations'
|
||||
|
||||
const brandingStore = useBrandingStore();
|
||||
const t = useTranslations();
|
||||
</script>
|
||||
Reference in New Issue
Block a user