feat(campaigns/translate): switch from literal to copywriter-mode AI prompt

User feedback: previous prompt produced robotic word-for-word output that
lost the marketing impact. The system prompt was too restrictive on
preservation, suppressing Gemini's natural rephrasing ability.

Rewrote the system prompt with three structural changes:

1. FRAME shifted from "translator" to "senior marketing copywriter"
   The opening line now says "You are NOT translating words — you are
   rewriting marketing copy that lands the same way for a different
   audience." This unlocks idiomatic rephrasing, sentence reorganization,
   active/passive switching, and cultural metaphor adaptation.

2. FEW-SHOT EXAMPLES showing the desired style
   4 FR→EN pairs in the prompt itself, with explicit "NOT: <literal>"
   anti-examples to show what to avoid:
     • "loyauté envers l'achat local" → "keeping it local"
       (not "loyalty to local shopping")
     • "connexions stables et relations durables" →
       "steady connections — both the fiber kind and the human kind"
       (not "stable connections and lasting relationships")
     • "On est juste à côté" → "We're right next door"
     • "Avec l'arrivée de l'été" → "Summer's here"
   These ground Gemini in the brand voice with concrete examples.

3. TONE constraint explicit
   "Warm, conversational, slightly playful. Like a neighbor explaining
   something — never corporate, never stiff." Use of contractions
   ("we're", "you'll") encouraged.

Plus: temperature bumped from 0.2 → 0.7 so Gemini actually exercises
creative rephrasing instead of staying glued to source word order.

Structural preservation rules (HTML, Mustache vars, brand names, emojis,
URLs, technical values like "3.5 Gbit/s") kept as HARD CONSTRAINTS but
clearly separated from the creative freedom on text content.

Live re-translation of gift-email-fr → gift-email-en applied:
  • 51s response time (similar to literal version)
  • 35,934 → 36,067 bytes (slight expansion, normal for EN)
  • Output markers confirm idiomatic phrasing landed:
    "Thanks for keeping it local", "steady connections — both kinds",
    "right next door", "lending a hand", "Summer's here"
  • Mustache vars + brand names + HTML preserved (verified)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
louispaulb 2026-05-22 07:29:16 -04:00
parent a6cd6ee453
commit 2c47d3269e
5 changed files with 272 additions and 67 deletions

View File

@ -76,7 +76,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<tbody>
<tr>
<td style="display:none !important;visibility:hidden;mso-hide:all;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">
Just like you, we love stable connections and lasting relationships.
Like you, we believe in steady connections — both the fiber kind and the human kind.
</td>
</tr>
@ -102,10 +102,10 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<td style="overflow-wrap:break-word;word-break:break-word;padding:0px;font-family:'Plus Jakarta Sans', sans-serif;" align="left">
<div>
<div style="display:none;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">Just like you, we love stable connections and lasting relationships.</div>
<div style="display:none;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">Like you, we believe in steady connections — both the fiber kind and the human kind.</div>
<div
aria-label="An exclusive offer from TARGO" aria-roledescription="email" role="article" lang="und" dir="auto" style="word-spacing:normal;background-color:#F5FAF7;"
aria-label="Your exclusive offer from TARGO" aria-roledescription="email" role="article" lang="und" dir="auto" style="word-spacing:normal;background-color:#F5FAF7;"
>
<!-- ════════ HEADER LOGO ════════ -->
@ -211,7 +211,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;"
>Hi {{firstname}},</div>
>Hey {{firstname}},</div>
</td>
</tr>
@ -222,11 +222,11 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
>
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;"
>Summer's here, and we have a <strong>gift for you, available for a limited time</strong>.</div>
>Summer's here, and we've got something special just for you — but only for a little while.</div>
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:500;line-height:1.5;text-align:left;color:#1B2E24;"
>Thank you for your loyalty to local shopping.<br />
Just like you, we love stable connections and lasting relationships.</div>
>Thanks for keeping it local — it means more than you think.<br />
Like you, we believe in steady connections — both the fiber kind and the human kind.</div>
</td>
</tr>
@ -237,8 +237,8 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
align="left" style="font-size:0px;padding:10px 25px;padding-bottom:0;word-break:break-word;"
>
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;">Thanks to our customers' trust, we now offer plans at <strong>the highest speed in the industry</strong>, up to <strong>3.5&nbsp;Gbit/s</strong>.<br />
Whether you want more speed, want to beat another offer, or want equipment optimization — just reach out. We're right around the corner and love to help.</div>
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;">Because our customers trust us, we're now able to offer the <strong>fastest plans around</strong>, with speeds up to <strong>3.5&nbsp;Gbit/s</strong>.<br />
Whether you're looking for more speed, want to beat another offer, or just need to optimize your gear, don't be shy! We're right next door — and we genuinely love lending a hand.</div>
</td>
</tr>
@ -299,7 +299,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:700;line-height:1.5;text-align:left;color:#1B2E24;"
>🎁 {{amount}} at hundreds of brands</div>
>🎁 {{amount}} to spend at hundreds of your favorite stores</div>
</td>
</tr>
@ -311,7 +311,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:14px;line-height:1.5;text-align:left;color:#64748B;"
>⚡ Available instantly on Giftbit by clicking your amount</div>
>⚡ Instantly available on Giftbit — just click your {{amount}} to claim it!</div>
</td>
</tr>
@ -323,7 +323,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:14px;line-height:1.5;text-align:left;color:#64748B;"
>🤝 Condition: Keep your subscription for {{commitment_months}} months or more</div>
>🤝 You just need to keep your subscription for {{commitment_months}} months or more.</div>
</td>
</tr>
@ -519,7 +519,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:14px;line-height:1.5;text-align:left;color:#6b7280;"
>🪂 If you leave before {{commitment_months}} months, the prorated amount is refundable.</div>
>🪂 If you decide to leave before {{commitment_months}} months, we'll refund the pro-rated amount.</div>
</td>
</tr>
@ -623,7 +623,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:15px;line-height:1.55;text-align:left;color:#4b5563;"
>Do nothing. Your monthly subscription continues as usual — no commitment, no gift card.</div>
>Just kick back! Your monthly subscription will continue as usual, with no commitment and no gift card.</div>
</td>
</tr>
@ -677,7 +677,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:15px;line-height:1.5;text-align:left;color:#1B2E24;"
>🤝 Thanks for helping our regional economy thrive!</div>
>🤝 Thanks for helping keep our local economy buzzing!</div>
</td>
</tr>
@ -689,7 +689,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:14px;line-height:1.5;text-align:left;color:#64748B;"
>The TARGO team</div>
>The TARGO Team</div>
</td>
</tr>
@ -744,11 +744,11 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:12px;line-height:1.55;text-align:center;color:#64748B;"
>You're getting this email because you're a TARGO customer at <strong style="color:#1B2E24;">{{description}}</strong>.<br />
Got a question? Write to
Got a question? Shoot us an email at
<a href="mailto:support@targo.ca" style="color:#00C853;text-decoration:none;">support@targo.ca</a>
or call
or give us a call at
<a href="tel:5144480773" style="color:#00C853;text-decoration:none;">514&nbsp;448-0773</a>.
Support&nbsp;7j/7.</div>
We're here 7&nbsp;days/week to help!</div>
</td>
</tr>
@ -878,4 +878,4 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<!--[if IE]></div><![endif]-->
</body>
</html>
</html>

File diff suppressed because one or more lines are too long

View File

@ -1188,41 +1188,78 @@ async function handle (req, res, method, path) {
})
}
const langNames = { fr: 'French Canadian (français du Québec)', en: 'English' }
const langNames = { fr: 'French Canadian (Quebec)', en: 'English (North American)' }
// System prompt: emphasize MEANING + TONE + IDIOMATIC REPHRASING over
// literal word-by-word translation. The previous version produced robotic
// output because it forced byte-for-byte preservation, which suppressed
// Gemini's natural rephrasing capability. New approach: rephrase freely
// within the constraint of preserving HTML structure + technical content.
const systemPrompt = [
`You are a professional bilingual translator for TARGO, a Quebec-based`,
`fiber Internet ISP. You translate marketing email content between`,
`French Canadian and English while strictly preserving HTML structure.`,
`You are a senior MARKETING COPYWRITER, not a literal translator. You`,
`craft email copy for TARGO, a regional Quebec-based fiber Internet ISP`,
`that prides itself on local presence, warmth, and trust. You're`,
`localizing email content between Quebec French and North American English.`,
``,
`STRICT RULES — DO NOT VIOLATE:`,
`1. PRESERVE every HTML tag, attribute, class, inline style, and Outlook`,
` conditional comment (<!--[if mso]><![endif]-->) byte-for-byte.`,
`2. PRESERVE Mustache variables: {{firstname}}, {{amount}}, {{gift_url}},`,
` {{commitment_months}}, {{description}}, {{expiry}}, {{year}}, etc.`,
` DO NOT translate the content inside {{ }}.`,
`3. PRESERVE URLs (href, src), email addresses, phone numbers, hex colors,`,
` CSS values, font names, brand names (TARGO, Gigafibre, Giftbit, Mailjet,`,
` Amazon, IGA, Tim Hortons, etc.).`,
`4. PRESERVE all emojis as-is (🎁 ⚡ 🤝 🪂 ✅ ⏭️ ⏰).`,
`5. KEEP the warm conversational tone — use "tu" (informal) in French and`,
` "you" (informal) in English. Marketing-friendly, not corporate.`,
`6. TRANSLATE only the visible text content inside elements: paragraphs,`,
` headings, button labels, link text, alt attributes.`,
`7. Output the COMPLETE translated HTML document (starting from <!doctype`,
` html> or <html> to the closing </html>). NO explanation, NO markdown`,
` code fence, NO commentary — just the HTML.`,
`══ YOUR MISSION ══`,
`Recreate the MEANING and EMOTIONAL IMPACT of the source in the target`,
`language. You are NOT translating words — you are rewriting marketing`,
`copy that lands the same way for a different audience. Feel free to:`,
` • Rephrase sentences entirely`,
` • Use idioms native to the target audience`,
` • Shorten or split sentences for clarity`,
` • Change metaphors if the original doesn't translate culturally`,
` • Switch passive↔active voice freely`,
``,
`══ TONE (HARD CONSTRAINT) ══`,
`Warm, conversational, slightly playful. Like a neighbor explaining`,
`something — never corporate, never stiff. Informal "tu" in French and`,
`informal "you" in English. Use contractions ("we're", "you'll", "on est").`,
``,
`══ STRUCTURAL PRESERVATION (HARD CONSTRAINT) ══`,
`Keep IDENTICAL byte-for-byte:`,
` 1. ALL HTML tags, attributes, classes, inline styles, Outlook MSO`,
` conditional comments`,
` 2. Mustache placeholders: {{firstname}}, {{amount}}, {{gift_url}},`,
` {{commitment_months}}, {{description}}, {{expiry}}, {{year}}`,
` 3. URLs, email addresses, phone numbers, hex colors, CSS, font names`,
` 4. Brand names: TARGO, Gigafibre, Giftbit, Mailjet, Amazon, IGA,`,
` Tim Hortons, Pizza Pizza, Home Depot, Best Buy, Walmart,`,
` Petro-Canada, Esso, Home Hardware, Sobeys`,
` 5. ALL emojis: 🎁 ⚡ 🤝 🪂 ✅ ⏭️ ⏰`,
` 6. Technical values like "3.5 Gbit/s", "7j/7" → "7 days/week"`,
``,
`══ FEW-SHOT EXAMPLES (THIS IS THE STYLE I WANT) ══`,
``,
`FR: "On veut te remercier pour ta loyauté envers l'achat local."`,
`EN: "Thanks for keeping it local — it means more than you think."`,
` (NOT: "We want to thank you for your loyalty to local shopping.")`,
``,
`FR: "Comme toi, on aime les connexions stables et les relations durables."`,
`EN: "Like you, we believe in steady connections — both the fiber kind and the human kind."`,
` (NOT: "Like you, we love stable connections and lasting relationships.")`,
``,
`FR: "On est juste à côté et on aime aider."`,
`EN: "We're right next door — and we genuinely love lending a hand."`,
` (NOT: "We are next to you and we love to help.")`,
``,
`FR: "Avec l'arrivée de l'été, voici un cadeau pour toi, disponible pour un temps limité."`,
`EN: "Summer's here, and we've got something for you — but only for a little while."`,
``,
`══ OUTPUT FORMAT ══`,
`Output the COMPLETE translated HTML from <!doctype html> to </html>.`,
`NO commentary, NO markdown fences, NO preamble. Just the HTML.`,
].join('\n')
const userPrompt = `Translate the following ${langNames[srcLang]} email HTML to ${langNames[tgtLang]}. ` +
`Apply the rules from the system prompt strictly.\n\n${srcHtml}`
const userPrompt = `Localize this ${langNames[srcLang]} marketing email into ${langNames[tgtLang]}. ` +
`Apply the COPYWRITER mindset from the system prompt — rephrase for natural flow, ` +
`keep the warm tone. Preserve every HTML tag and Mustache placeholder exactly.\n\n${srcHtml}`
let translated
try {
// Non-JSON mode (we want raw HTML back), high token limit (~35 KB output)
translated = await getAi().aiCall(systemPrompt, userPrompt, {
jsonMode: false,
maxTokens: 32768,
temperature: 0.2, // low temp = stable, less creative translation
temperature: 0.7, // bumped from 0.2 — let the AI rephrase creatively
})
} catch (e) {
return json(res, 502, { error: 'AI translation failed', detail: e.message })

View File

@ -76,7 +76,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<tbody>
<tr>
<td style="display:none !important;visibility:hidden;mso-hide:all;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">
Just like you, we love stable connections and lasting relationships.
Like you, we believe in steady connections — both the fiber kind and the human kind.
</td>
</tr>
@ -102,10 +102,10 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<td style="overflow-wrap:break-word;word-break:break-word;padding:0px;font-family:'Plus Jakarta Sans', sans-serif;" align="left">
<div>
<div style="display:none;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">Just like you, we love stable connections and lasting relationships.</div>
<div style="display:none;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">Like you, we believe in steady connections — both the fiber kind and the human kind.</div>
<div
aria-label="An exclusive offer from TARGO" aria-roledescription="email" role="article" lang="und" dir="auto" style="word-spacing:normal;background-color:#F5FAF7;"
aria-label="Your exclusive offer from TARGO" aria-roledescription="email" role="article" lang="und" dir="auto" style="word-spacing:normal;background-color:#F5FAF7;"
>
<!-- ════════ HEADER LOGO ════════ -->
@ -211,7 +211,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;"
>Hi {{firstname}},</div>
>Hey {{firstname}},</div>
</td>
</tr>
@ -222,11 +222,11 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
>
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;"
>Summer's here, and we have a <strong>gift for you, available for a limited time</strong>.</div>
>Summer's here, and we've got something special just for you — but only for a little while.</div>
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:500;line-height:1.5;text-align:left;color:#1B2E24;"
>Thank you for your loyalty to local shopping.<br />
Just like you, we love stable connections and lasting relationships.</div>
>Thanks for keeping it local — it means more than you think.<br />
Like you, we believe in steady connections — both the fiber kind and the human kind.</div>
</td>
</tr>
@ -237,8 +237,8 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
align="left" style="font-size:0px;padding:10px 25px;padding-bottom:0;word-break:break-word;"
>
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;">Thanks to our customers' trust, we now offer plans at <strong>the highest speed in the industry</strong>, up to <strong>3.5&nbsp;Gbit/s</strong>.<br />
Whether you want more speed, want to beat another offer, or want equipment optimization — just reach out. We're right around the corner and love to help.</div>
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;">Because our customers trust us, we're now able to offer the <strong>fastest plans around</strong>, with speeds up to <strong>3.5&nbsp;Gbit/s</strong>.<br />
Whether you're looking for more speed, want to beat another offer, or just need to optimize your gear, don't be shy! We're right next door — and we genuinely love lending a hand.</div>
</td>
</tr>
@ -299,7 +299,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:700;line-height:1.5;text-align:left;color:#1B2E24;"
>🎁 {{amount}} at hundreds of brands</div>
>🎁 {{amount}} to spend at hundreds of your favorite stores</div>
</td>
</tr>
@ -311,7 +311,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:14px;line-height:1.5;text-align:left;color:#64748B;"
>⚡ Available instantly on Giftbit by clicking your amount</div>
>⚡ Instantly available on Giftbit — just click your {{amount}} to claim it!</div>
</td>
</tr>
@ -323,7 +323,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:14px;line-height:1.5;text-align:left;color:#64748B;"
>🤝 Condition: Keep your subscription for {{commitment_months}} months or more</div>
>🤝 You just need to keep your subscription for {{commitment_months}} months or more.</div>
</td>
</tr>
@ -519,7 +519,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:14px;line-height:1.5;text-align:left;color:#6b7280;"
>🪂 If you leave before {{commitment_months}} months, the prorated amount is refundable.</div>
>🪂 If you decide to leave before {{commitment_months}} months, we'll refund the pro-rated amount.</div>
</td>
</tr>
@ -623,7 +623,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:15px;line-height:1.55;text-align:left;color:#4b5563;"
>Do nothing. Your monthly subscription continues as usual — no commitment, no gift card.</div>
>Just kick back! Your monthly subscription will continue as usual, with no commitment and no gift card.</div>
</td>
</tr>
@ -677,7 +677,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:15px;line-height:1.5;text-align:left;color:#1B2E24;"
>🤝 Thanks for helping our regional economy thrive!</div>
>🤝 Thanks for helping keep our local economy buzzing!</div>
</td>
</tr>
@ -689,7 +689,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:14px;line-height:1.5;text-align:left;color:#64748B;"
>The TARGO team</div>
>The TARGO Team</div>
</td>
</tr>
@ -744,11 +744,11 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<div
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:12px;line-height:1.55;text-align:center;color:#64748B;"
>You're getting this email because you're a TARGO customer at <strong style="color:#1B2E24;">{{description}}</strong>.<br />
Got a question? Write to
Got a question? Shoot us an email at
<a href="mailto:support@targo.ca" style="color:#00C853;text-decoration:none;">support@targo.ca</a>
or call
or give us a call at
<a href="tel:5144480773" style="color:#00C853;text-decoration:none;">514&nbsp;448-0773</a>.
Support&nbsp;7j/7.</div>
We're here 7&nbsp;days/week to help!</div>
</td>
</tr>
@ -878,4 +878,4 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
<!--[if IE]></div><![endif]-->
</body>
</html>
</html>

File diff suppressed because one or more lines are too long