Skip to main content

Creating Advanced Multilingual Welcome Message

This guide demonstrates how to create multilingual welcome message using an advanced JavaScript approach with a single configuration. The key innovation is separating button display text from the actual messages sent to the LLM for better user experience and AI responses.

Key Innovation: Separating Display Text from LLM Messages

The advanced approach uses data-key attributes to separate:

  • Button Display Text: What users see (short, localized labels)
  • LLM Messages: Detailed questions sent to the AI (comprehensive, also localized)

This allows for concise button labels while sending detailed questions that generate better AI responses.

Step-by-Step Implementation

Step 1: Configure AI Settings and Branding

  1. Go to AI SettingsBranding
  2. Upload screenshots of your website
  3. The system will automatically extract branding information including colors, fonts, and styling

Step 2: Create Web Control Configuration

  1. Navigate to Web Controlsai12z-bot
  2. Create a new configuration
  3. Under Display, select ThemeCustom
  4. Run the branding wizard - this will automatically update CSS based on your branding information

Step 3: Configure Welcome Message

  1. Go to the Info tab
  2. Under Welcome Message, you'll see three tabs:
    • HTML tab
    • Styles tab
    • Script tab
  3. Use the wizard to generate suggested questions based on your organization
  4. The wizard will research your business and suggest relevant buttons

Step 4: Implement Advanced JavaScript Translation

Add JavaScript code that handles both display text and LLM message translations separately.

Complete Example: Kaluani Beach Resort

Here's a complete implementation using the advanced approach with data-key attributes:

HTML Tab

<div class="my-welcome-panel">
<div class="my-welcome-header">🌴 Welcome to Kaluani Beach Resort!</div>
<div class="my-welcome-message">
How can we make your stay unforgettable?
<div class="my-welcome-sub">Select a question below or ask your own!</div>
</div>
<div class="my-btn-row">
<button class="ai12zbutton" data-key="Check Room Availability">
Check Room Availability
</button>
<button class="ai12zbutton" data-key="Explore Resort Amenities">
Explore Resort Amenities
</button>
<button class="ai12zbutton" data-key="Discover Local Attractions">
Discover Local Attractions
</button>
<button class="ai12zbutton" data-key="View Special Offers">
View Special Offers
</button>
<button class="ai12zbutton" data-key="Book Dining or Spa">
Book Dining or Spa
</button>
<button class="ai12zbutton" data-key="Ask About Cancellation Policy">
Ask About Cancellation Policy
</button>
<button class="ai12zbutton" data-key="Arrange Transportation">
Arrange Transportation
</button>
<button class="ai12zbutton" data-key="What is on the Menu">
What is on the Menu
</button>
<button class="ai12zbutton" data-key="Local Restaurants">
Local Restaurants
</button>
<button class="ai12zbutton" data-key="Movies Playing">
Movies Playing
</button>
</div>
</div>

Styles Tab

.my-welcome-panel {
background: #f0f8ff; /* Light ocean blue background */
border-radius: 18px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
padding: 32px 28px 18px 28px;
margin: 16px;
max-width: 520px;
text-align: center;
font-family: inherit;
border: 1px solid #e0f2fe;
}

.my-welcome-header {
font-size: 1.4rem;
font-weight: 600;
margin-bottom: 8px;
color: #0277bd; /* Ocean blue */
letter-spacing: 0.02em;
}

.my-welcome-message {
font-size: 1.08rem;
margin-bottom: 18px;
color: #2a3342;
}

.my-welcome-sub {
font-size: 0.92rem;
color: #7685a6;
margin-top: 2px;
}

.my-btn-row {
display: flex;
flex-direction: column;
gap: 10px;
align-items: stretch;
}

.ai12zbutton {
color: white;
background: #0277bd; /* Resort blue theme */
font-weight: 500;
border: 3px solid #0277bd;
border-radius: 32px;
padding: 12px 18px;
cursor: pointer;
margin: 0;
transition: background 0.18s;
font-size: 1rem;
}

.ai12zbutton:hover {
background: #01579b; /* Darker blue on hover */
border-color: #4fc3f7; /* Light blue border */
}

Script Tab

// Welcome Message (scoped to avoid globals)
;(() => {
function getLayoutNode() {
return ai12zBot.shadowRoot?.querySelector(".layout")
}

// Display text translations (what users see on buttons)
var displayTranslations = {
"Ask me anything": {
es: "Pregúntame lo que quieras",
fr: "Posez-moi une question",
it: "Chiedimi qualsiasi cosa",
},
"🌴 Welcome to Kaluani Beach Resort!": {
fr: "🌴 Bienvenue au Kaluani Beach Resort !",
es: "🌴 ¡Bienvenido al Kaluani Beach Resort!",
it: "🌴 Benvenuto al Kaluani Beach Resort!",
},
"How can we make your stay unforgettable?": {
fr: "Comment pouvons-nous rendre votre séjour inoubliable ?",
es: "¿Cómo podemos hacer que su estadía sea inolvidable?",
it: "Come possiamo rendere il vostro soggiorno indimenticabile?",
},
"Select a question below or ask your own!": {
fr: "Sélectionnez une question ci-dessous ou posez la vôtre !",
es: "Seleccione una pregunta a continuación o haga la suya propia.",
it: "Seleziona una domanda qui sotto o fai la tua!",
},
"Check Room Availability": {
fr: "Vérifier disponibilité",
es: "Verificar disponibilidad",
it: "Verifica disponibilità",
},
"Explore Resort Amenities": {
fr: "Explorer les équipements",
es: "Explorar comodidades",
it: "Esplora servizi",
},
"Discover Local Attractions": {
fr: "Attractions locales",
es: "Atracciones locales",
it: "Attrazioni locali",
},
"View Special Offers": {
fr: "Offres spéciales",
es: "Ofertas especiales",
it: "Offerte speciali",
},
"Book Dining or Spa": {
fr: "Réserver restaurant/spa",
es: "Reservar comedor/spa",
it: "Prenota ristorante/spa",
},
"Ask About Cancellation Policy": {
fr: "Politique d'annulation",
es: "Política de cancelación",
it: "Politica di cancellazione",
},
"Arrange Transportation": {
fr: "Organiser transport",
es: "Organizar transporte",
it: "Organizzare trasporto",
},
"What is on the Menu": {
fr: "Menu disponible",
es: "Qué hay en el menú",
it: "Cosa c'è nel menu",
},
"Local Restaurants": {
fr: "Restaurants locaux",
es: "Restaurantes locales",
it: "Ristoranti locali",
},
"Movies Playing": {
fr: "Films à l'affiche",
es: "Películas en cartelera",
it: "Film in programmazione",
},
}

// LLM message translations (detailed questions sent to AI)
var llmMessages = {
"Check Room Availability": {
en: "What rooms and suites are available right now? Can you show me current availability and rates?",
fr: "Quelles chambres et suites sont disponibles en ce moment ? Pouvez-vous me montrer la disponibilité actuelle et les tarifs ?",
es: "¿Qué habitaciones y suites están disponibles ahora mismo? ¿Puede mostrarme la disponibilidad actual y las tarifas?",
it: "Quali camere e suite sono disponibili in questo momento? Puoi mostrarmi la disponibilità attuale e le tariffe?",
},
"Explore Resort Amenities": {
en: "What amenities and activities does the resort offer? Tell me about pools, fitness, spa, and recreational facilities.",
fr: "Quels équipements et activités le resort propose-t-il ? Parlez-moi des piscines, fitness, spa et installations récréatives.",
es: "¿Qué comodidades y actividades ofrece el resort? Hábleme de las piscinas, gimnasio, spa e instalaciones recreativas.",
it: "Quali servizi e attività offre il resort? Parlami di piscine, fitness, spa e strutture ricreative.",
},
"Discover Local Attractions": {
en: "What local attractions and tours do you recommend? What are the must-see places and activities near the resort?",
fr: "Quelles attractions locales et excursions recommandez-vous ? Quels sont les lieux et activités incontournables près du resort ?",
es: "¿Qué atracciones locales y tours recomienda? ¿Cuáles son los lugares y actividades imperdibles cerca del resort?",
it: "Quali attrazioni locali e tour consigli? Quali sono i luoghi e le attività da non perdere vicino al resort?",
},
"View Special Offers": {
en: "Are there any current promotions or special packages available? What deals can you offer for my stay?",
fr: "Y a-t-il des promotions ou forfaits spéciaux actuellement disponibles ? Quelles offres pouvez-vous proposer pour mon séjour ?",
es: "¿Hay alguna promoción o paquete especial disponible actualmente? ¿Qué ofertas puede ofrecerme para mi estadía?",
it: "Ci sono promozioni o pacchetti speciali attualmente disponibili? Quali offerte puoi offrire per il mio soggiorno?",
},
"Book Dining or Spa": {
en: "Can I book dining or spa reservations? What restaurants and spa services are available, and how do I make reservations?",
fr: "Puis-je réserver un restaurant ou un spa ? Quels restaurants et services de spa sont disponibles, et comment faire des réservations ?",
es: "¿Puedo hacer reservas para cenar o en el spa? ¿Qué restaurantes y servicios de spa están disponibles, y cómo hago reservas?",
it: "Posso prenotare ristorante o spa? Quali ristoranti e servizi spa sono disponibili, e come posso fare prenotazioni?",
},
"Ask About Cancellation Policy": {
en: "What is your cancellation and refund policy? What are the terms and conditions for modifying or canceling my reservation?",
fr: "Quelle est votre politique d'annulation et de remboursement ? Quelles sont les conditions pour modifier ou annuler ma réservation ?",
es: "¿Cuál es su política de cancelación y reembolso? ¿Cuáles son los términos y condiciones para modificar o cancelar mi reserva?",
it: "Qual è la vostra politica di cancellazione e rimborso? Quali sono i termini e le condizioni per modificare o cancellare la mia prenotazione?",
},
"Arrange Transportation": {
en: "How can I arrange airport transfers or transportation? What transportation options are available to and from the resort?",
fr: "Comment puis-je organiser des transferts aéroport ou du transport ? Quelles options de transport sont disponibles vers et depuis le resort ?",
es: "¿Cómo puedo organizar traslados al aeropuerto o transporte? ¿Qué opciones de transporte están disponibles hacia y desde el resort?",
it: "Come posso organizzare trasferimenti aeroportuali o trasporti? Quali opzioni di trasporto sono disponibili da e per il resort?",
},
"What is on the Menu": {
en: "What dining options and menus are available at the resort? Can you show me the restaurant menus and meal options?",
fr: "Quelles options de restauration et menus sont disponibles au resort ? Pouvez-vous me montrer les menus des restaurants et les options de repas ?",
es: "¿Qué opciones gastronómicas y menús están disponibles en el resort? ¿Puede mostrarme los menús de los restaurantes y las opciones de comida?",
it: "Quali opzioni gastronomiche e menu sono disponibili al resort? Puoi mostrarmi i menu dei ristoranti e le opzioni pasto?",
},
"Local Restaurants": {
en: "What local restaurants do you recommend? What are the best dining options outside the resort?",
fr: "Quels restaurants locaux recommandez-vous ? Quelles sont les meilleures options de restauration en dehors du resort ?",
es: "¿Qué restaurantes locales recomienda? ¿Cuáles son las mejores opciones gastronómicas fuera del resort?",
it: "Quali ristoranti locali consigli? Quali sono le migliori opzioni gastronomiche fuori dal resort?",
},
"Movies Playing": {
en: "What entertainment and movies are playing? What evening entertainment options are available at the resort?",
fr: "Quels divertissements et films sont à l'affiche ? Quelles options de divertissement en soirée sont disponibles au resort ?",
es: "¿Qué entretenimiento y películas están en cartelera? ¿Qué opciones de entretenimiento nocturno están disponibles en el resort?",
it: "Che intrattenimento e film ci sono in programmazione? Quali opzioni di intrattenimento serale sono disponibili al resort?",
},
}

var selectedLang = "en" // Default language

// Listen for dropdown change (if using external language selector)
var dropdown = document.getElementById("languageDropdown")
if (dropdown) {
dropdown.addEventListener("change", function () {
selectedLang = this.value
ai12zBot.dataAttributes = { lang: selectedLang }
const node = getLayoutNode()
if (node) translateWelcomePanel(node)
})
}

function translateWelcomePanel(target) {
if (!target) return
const innerContent = target.querySelector(".my-welcome-panel")
if (!innerContent) return

const form = target.querySelector("form")
const field = form?.querySelector("fieldset")
const parentdiv = field?.querySelector(".textarea")

setTimeout(() => {
const textarea = parentdiv?.querySelector("textarea")
const originalText = "Ask me anything"
if (textarea) {
textarea.placeholder =
displayTranslations[originalText.trim()]?.[selectedLang] ||
originalText
}
}, 100)

// Translate header
const header = innerContent.querySelector(".my-welcome-header")
if (header) {
const originalText = header.textContent.trim()
header.textContent =
displayTranslations[originalText]?.[selectedLang] || originalText
}

// Translate main message
const message = innerContent.querySelector(".my-welcome-message")
if (message?.firstChild?.nodeType === Node.TEXT_NODE) {
const originalText = message.firstChild.textContent.trim()
message.firstChild.textContent =
(displayTranslations[originalText]?.[selectedLang] || originalText) +
" "
}

// Translate sub message
const sub = innerContent.querySelector(".my-welcome-sub")
if (sub) {
const originalText = sub.textContent.trim()
sub.textContent =
displayTranslations[originalText]?.[selectedLang] || originalText
}

// Translate buttons and set up click handlers
innerContent.querySelectorAll("button.ai12zbutton").forEach((button) => {
const key = button.getAttribute("data-key")

// Set display text
button.textContent = displayTranslations[key]?.[selectedLang] || key

// Set click handler with translated LLM message
const clickMessage =
llmMessages[key]?.[selectedLang] || llmMessages[key]?.en || key
button.onclick = () => {
ai12zBot.sendMessage(clickMessage)
}
})
}

// Observe layout open state
var observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
if (
mutation.type === "attributes" &&
mutation.attributeName === "class"
) {
const target = mutation.target
if (target.classList.contains("is-open")) {
translateWelcomePanel(target)
}
}
}
})

function waitAndObserveLayout() {
var layoutNodeLocal = getLayoutNode()
if (!layoutNodeLocal) {
setTimeout(waitAndObserveLayout, 100)
return
}

observer.observe(layoutNodeLocal, {
attributes: true,
subtree: true,
attributeFilter: ["class"],
})

if (layoutNodeLocal.classList.contains("is-open")) {
translateWelcomePanel(layoutNodeLocal)
}
}

waitAndObserveLayout()
})()

External Web Page with Language Selector

<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<script
type="module"
src="https://cdn.ai12z.net/pkg/ai12z@latest/dist/esm/library.js"
></script>
<link
rel="stylesheet"
href="https://cdn.ai12z.net/pkg/ai12z@latest/dist/library/library.css"
/>
<style>
label {
font-size: 16px;
margin-right: 10px;
}
select {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 14px;
background-color: #fff;
cursor: pointer;
min-width: 200px;
}
select:focus {
outline: none;
border-color: #0277bd;
box-shadow: 0 0 4px rgba(2, 119, 189, 0.5);
}
</style>
</head>
<body>
<label for="languageDropdown">Choose Language:</label>
<select id="languageDropdown">
<option value="en">English</option>
<option value="fr">Français</option>
<option value="es">Español</option>
<option value="it">Italiano</option>
</select>

<script>
const languages = [
{ code: "en", name: "English" },
{ code: "fr", name: "Français" },
{ code: "es", name: "Español" },
{ code: "it", name: "Italiano" },
]

var dropdown = document.getElementById("languageDropdown")

// Populate dropdown
languages.forEach((lang) => {
const option = document.createElement("option")
option.value = lang.code
option.textContent = lang.name
if (!dropdown.querySelector(`option[value="${lang.code}"]`)) {
dropdown.appendChild(option)
}
})
</script>

<ai12z-bot data-key="YOUR_BOT_KEY_HERE"></ai12z-bot>
</body>
</html>

Key Advantages of the Advanced Approach

1. Separation of Concerns

  • Display Text: Short, user-friendly button labels
  • LLM Messages: Comprehensive, context-rich questions for better AI responses

2. Better AI Responses

  • Detailed questions provide more context to the AI
  • Results in more accurate and helpful responses
  • Maintains user experience with concise button labels

3. Enhanced Scalability

  • Single configuration handles multiple languages
  • Easy to add new languages by extending translation objects
  • Maintainable codebase without configuration proliferation

4. Professional Implementation

  • Uses data-key attributes for clean HTML structure
  • Separates translation logic from display logic
  • Enables professional translation workflows

Implementation Benefits

For Developers

  • Clean Code: Separation of display and functionality
  • Maintainable: Single source of truth for translations
  • Flexible: Easy to modify messages without changing UI

For Content Managers

  • Professional Translation: Can send detailed messages to translation services
  • Context-Aware: Translators understand both button labels and full questions
  • Quality Control: Better translations lead to better AI responses

For Users

  • Concise Interface: Short, clear button labels
  • Better Results: Detailed questions yield more helpful AI responses
  • Consistent Experience: Seamless language switching

This advanced approach provides the best of both worlds: a clean, professional user interface with powerful backend functionality that maximizes AI effectiveness across multiple languages.

Best Practices

Translation Management

  1. Consistent Keys: Use the exact text as translation keys
  2. Fallback Strategy: Always provide English fallback
  3. Professional Translation: Use professional translation services for customer-facing content
  4. Context Awareness: Consider cultural context, not just literal translation

Implementation Tips

  1. Test Thoroughly: Test with different browser language settings
  2. Handle Edge Cases: Account for regional language variants (en-US vs en-GB)
  3. Performance: Keep translation objects reasonable in size
  4. Accessibility: Ensure translations maintain accessibility features

Maintenance

  1. Version Control: Track translation changes
  2. Review Process: Implement review process for translation updates
  3. Analytics: Monitor which languages are most used
  4. Feedback: Provide way for users to report translation issues

This approach provides a scalable, maintainable solution for multilingual support that grows with your business without exponentially increasing configuration complexity.