MJML
Lingo.dev CLIを使用したMJMLメールテンプレートのAI翻訳
MJMLとは?
MJML(Mailjet Markup Language)は、レスポンシブなメールテンプレートを簡単に作成できるレスポンシブメールフレームワークです。セマンティックな構文を使用してレスポンシブメールの開発を簡素化し、すべての主要なメールクライアントで動作する標準HTMLにコンパイルされます。
Lingo.dev CLIとは?
Lingo.dev CLIは、AIを使用してアプリやコンテンツを翻訳するための無料のオープンソースCLIです。従来の翻訳管理ソフトウェアを置き換えながら、既存のパイプラインと統合できるように設計されています。
詳細については、概要を参照してください。
このガイドについて
このガイドでは、Lingo.dev CLIを使用してMJMLメールテンプレートを翻訳する方法を説明します。
以下の方法を学習します:
- ゼロからプロジェクトを作成する
- 翻訳パイプラインを設定する
- AIで翻訳を生成する
前提条件
Lingo.dev CLIを使用するには、Node.js v18以降がインストールされていることを確認してください:
❯ node -v
v22.17.0
ステップ1. プロジェクトをセットアップする
プロジェクトのディレクトリで、i18n.json ファイルを作成します:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
このファイルは、翻訳する言語やファイルシステム上のローカライズ可能なコンテンツの場所など、翻訳パイプラインの動作を定義します。
利用可能なプロパティの詳細については、i18n.jsonを参照してください。
ステップ2. ソースロケールを設定する
_ソースロケール_は、コンテンツが記述された元の言語と地域です。ソースロケールを設定するには、i18n.json ファイルで locale.source プロパティを設定します:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
ソースロケールは、BCP 47言語タグとして指定する必要があります。
Lingo.dev CLIがサポートするロケールコードの完全なリストについては、サポートされているロケールコードを参照してください。
ステップ3. ターゲットロケールの設定
_ターゲットロケール_は、コンテンツを翻訳したい言語と地域です。ターゲットロケールを設定するには、i18n.jsonファイルのlocale.targetsプロパティを設定します。
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
ステップ4. ソースコンテンツの作成
まだ作成していない場合は、翻訳対象のコンテンツを含む1つ以上のMJMLテンプレートファイルを作成します。これらのファイルは、パスのどこかにソースロケールを含む場所に配置する必要があります(例:en/のようなディレクトリ名、またはexample_en.mjmlのようなファイル名の一部として)。
MJMLテンプレートの場合、翻訳可能なコンテンツには以下が含まれます。
- MJMLコンポーネント内のテキストコンテンツ:
mj-text(本文テキスト)mj-button(ボタンラベル)mj-title(プレビューのメールタイトル)mj-preview(プレビューテキスト)mj-navbar-link(ナビゲーションリンク)mj-accordion-title(アコーディオン見出し)mj-accordion-text(アコーディオンコンテンツ)
- MJML内のHTML要素:
p、h1-h6、li - 属性値には以下が含まれます:
mj-imageのaltおよびtitle属性mj-buttonのtitleおよびaria-label属性mj-social-elementのtitleおよびalt属性- HTML
imgおよびa要素のaltおよびtitle属性
インラインHTMLの処理方法:
テキストにインラインHTML要素(<strong>、<span>、<em>、<a>など)が含まれている場合、テキストブロック全体が1つの完全な単位として翻訳されます。これにより、翻訳品質を向上させるためのコンテキストが保持され、インライン書式が維持されます。
例:
<mj-text>
<p>Welcome to <strong>our platform</strong>!</p>
</mj-text>
段落全体"Welcome to <strong>our platform</strong>!"が単一のブロックとして翻訳され、<strong>タグがそのまま保持されます。これにより、AI翻訳者が完全なコンテキストを持ち、翻訳でもインライン書式が保持されます。
テンプレート変数(Razor変数@Model.UserNameなど)は翻訳中も保持されます。
ステップ5. バケットを作成する
-
i18n.jsonファイルに、bucketsオブジェクトへ"mjml"オブジェクトを追加します:{ "$schema": "https://lingo.dev/schema/i18n.json", "version": "1.10", "locale": { "source": "en", "targets": ["es"] }, "buckets": { "mjml": {} } } -
"mjml"オブジェクト内で、1つ以上のincludeパターンの配列を定義します:{ "$schema": "https://lingo.dev/schema/i18n.json", "version": "1.10", "locale": { "source": "en", "targets": ["es"] }, "buckets": { "mjml": { "include": ["./[locale]/example.mjml"] } } }これらのパターンは、翻訳するファイルを定義します。
パターン自体は:
- 設定されたロケールのプレースホルダーとして
[locale]を含む必要があります - ファイルパスを指定できます(例:
"[locale]/example.mjml") - ワイルドカードプレースホルダーとしてアスタリスクを使用できます(例:
"[locale]/*.mjml")
再帰的なglobパターン(例:
**/*.mjml)はサポートされていません。 - 設定されたロケールのプレースホルダーとして
ステップ6. LLMを設定する
Lingo.dev CLIは、大規模言語モデル(LLM)を使用してAIでコンテンツを翻訳します。これらのモデルのいずれかを使用するには、サポートされているプロバイダーからAPIキーが必要です。
できるだけ早く開始するには、Lingo.dev Engineの使用をお勧めします:
-
次のコマンドを実行します:
npx lingo.dev@latest loginこれによりデフォルトのブラウザが開き、認証を求められます。
-
プロンプトに従います。
ステップ7. 翻訳を生成する
i18n.jsonファイルを含むディレクトリで、次のコマンドを実行します:
npx lingo.dev@latest run
このコマンドは:
i18n.jsonファイルを読み込みます。- 翻訳が必要なファイルを検索します。
- ファイルから翻訳可能なコンテンツを抽出します。
- 設定されたLLMを使用して抽出されたコンテンツを翻訳します。
- 翻訳されたコンテンツをファイルシステムに書き戻します。
翻訳が初めて生成されると、i18n.lockファイルが作成されます。このファイルは、どのコンテンツが翻訳されたかを追跡し、後続の実行で不要な再翻訳を防ぎます。
例
en/example.mjml
<?xml version="1.0" encoding="UTF-8"?>
<mjml>
<mj-head>
<mj-title>Welcome to Our Service</mj-title>
<mj-preview>Get started with your new account today</mj-preview>
<mj-attributes>
<mj-all font-family="Arial, sans-serif" />
</mj-attributes>
</mj-head>
<mj-body>
<mj-section background-color="#f0f0f0">
<mj-column>
<mj-image
src="https://example.com/logo.png"
alt="Company Logo"
width="150px"
/>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" padding="20px">
<mj-column>
<mj-text font-size="24px" color="#333333" font-weight="bold">
Welcome to Our Platform!
</mj-text>
<mj-text font-size="16px" color="#555555" line-height="24px">
Thank you for signing up. We're excited to have you on board.
</mj-text>
<mj-text font-size="16px" color="#555555" line-height="24px">
To get started, please verify your email address by clicking the
button below.
</mj-text>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" padding="20px">
<mj-column>
<mj-button
background-color="#007bff"
color="#ffffff"
href="https://example.com/verify"
title="Verify your email address"
aria-label="Verify email"
>
Verify Email Address!
</mj-button>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" padding="20px">
<mj-column>
<mj-text font-size="14px" color="#666666">
If you didn't create an account, you can safely ignore this email.
</mj-text>
<mj-text font-size="14px" color="#666666">
Need help? Contact our support team.
</mj-text>
</mj-column>
</mj-section>
<mj-section background-color="#f8f9fa" padding="20px">
<mj-column>
<mj-social mode="horizontal">
<mj-social-element
name="facebook"
href="https://facebook.com/example"
title="Follow us on Facebook"
alt="Facebook"
/>
<mj-social-element
name="twitter"
href="https://twitter.com/example"
title="Follow us on Twitter"
alt="Twitter"
/>
<mj-social-element
name="instagram"
href="https://instagram.com/example"
title="Follow us on Instagram"
alt="Instagram"
/>
</mj-social>
<mj-text font-size="12px" color="#999999" align="center">
© 2024 Example Company. All rights reserved.
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
es/example.mjml
<?xml version="1.0" encoding="UTF-8"?>
<mjml>
<mj-head>
<mj-title>Bienvenido a nuestro servicio</mj-title>
<mj-preview>Comienza con tu nueva cuenta hoy</mj-preview>
<mj-attributes>
<mj-all font-family="Arial, sans-serif" />
</mj-attributes>
</mj-head>
<mj-body>
<mj-section background-color="#f0f0f0">
<mj-column>
<mj-image
src="https://example.com/logo.png"
alt="Logo de la empresa"
width="150px"
/>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" padding="20px">
<mj-column>
<mj-text font-size="24px" color="#333333" font-weight="bold">
¡Bienvenido a nuestra plataforma!
</mj-text>
<mj-text font-size="16px" color="#555555" line-height="24px">
Gracias por registrarte. Estamos encantados de tenerte con nosotros.
</mj-text>
<mj-text font-size="16px" color="#555555" line-height="24px">
Para comenzar, por favor verifica tu dirección de correo electrónico
haciendo clic en el botón de abajo.
</mj-text>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" padding="20px">
<mj-column>
<mj-button
background-color="#007bff"
color="#ffffff"
href="https://example.com/verify"
title="Verifica tu dirección de correo electrónico"
aria-label="Verificar correo"
>
¡Verificar dirección de correo!
</mj-button>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" padding="20px">
<mj-column>
<mj-text font-size="14px" color="#666666">
Si no creaste una cuenta, puedes ignorar este correo electrónico.
</mj-text>
<mj-text font-size="14px" color="#666666">
¿Necesitas ayuda? Contacta a nuestro equipo de soporte.
</mj-text>
</mj-column>
</mj-section>
<mj-section background-color="#f8f9fa" padding="20px">
<mj-column>
<mj-social mode="horizontal">
<mj-social-element
name="facebook"
href="https://facebook.com/example"
title="Síguenos en Facebook"
alt="Facebook"
/>
<mj-social-element
name="twitter"
href="https://twitter.com/example"
title="Síguenos en Twitter"
alt="Twitter"
/>
<mj-social-element
name="instagram"
href="https://instagram.com/example"
title="Síguenos en Instagram"
alt="Instagram"
/>
</mj-social>
<mj-text font-size="12px" color="#999999" align="center">
© 2024 Example Company. Todos los derechos reservados.
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
i18n.json
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {
"mjml": {
"include": ["./[locale]/example.mjml"]
}
}
}
i18n.lock
version: 1
checksums:
c1acde0589961652d4caf8a39d080857:
mjml/mj-head/0/mj-title/0: c514a686b50f7158b2dd08ea65d3bc8a
mjml/mj-head/0/mj-preview/0: 4ce14f6062c814cbdcdf8b0a3cb094d3
mjml/mj-body/0/mj-section/0/mj-column/0/mj-image/0#alt: 82d5c0d5994508210ee02d684819f4b8
mjml/mj-body/0/mj-section/1/mj-column/0/mj-text/0: b320b02942617a70dcbd1beac61da11a
mjml/mj-body/0/mj-section/1/mj-column/0/mj-text/1: 028311348a5aeefea365fdf422a3fb21
mjml/mj-body/0/mj-section/1/mj-column/0/mj-text/2: 0dfdc9b80ee70fcc2b28d0e81e03fabc
mjml/mj-body/0/mj-section/2/mj-column/0/mj-button/0#title: 5c96f738bd6153ee07b72094cdfd2b98
mjml/mj-body/0/mj-section/2/mj-column/0/mj-button/0#aria-label: 42dcab68d931f9145d9b6d76740a5c66
mjml/mj-body/0/mj-section/2/mj-column/0/mj-button/0: dc8001d5c58294d22fe0b0e6118dbfb7
mjml/mj-body/0/mj-section/3/mj-column/0/mj-text/0: a18f14ab69467cbdbe467df6255cfda7
mjml/mj-body/0/mj-section/3/mj-column/0/mj-text/1: e83236e98aad1937bc99a47cff159caa
mjml/mj-body/0/mj-section/4/mj-column/0/mj-social/0/mj-social-element/0#title: 180bd8aa700f6cedf65e0a2079503cea
mjml/mj-body/0/mj-section/4/mj-column/0/mj-social/0/mj-social-element/0#alt: ac8afe226a7424849c247e6a9d566f64
mjml/mj-body/0/mj-section/4/mj-column/0/mj-social/0/mj-social-element/1#title: ea4c2a7a9a60cbb0f8f9632222a46abe
mjml/mj-body/0/mj-section/4/mj-column/0/mj-social/0/mj-social-element/1#alt: ba3d4aed69a50759b53a0b7c319a3ad9
mjml/mj-body/0/mj-section/4/mj-column/0/mj-social/0/mj-social-element/2#title: 754efa5f98f51c510ff268e217877d8b
mjml/mj-body/0/mj-section/4/mj-column/0/mj-social/0/mj-social-element/2#alt: c9555810826c30d571ffae869a236494
mjml/mj-body/0/mj-section/4/mj-column/0/mj-text/0: 9ac6c625c7af33d70634846c8c9d11b0