import type { SupportedLocale } from "@/lib/i18n-config";
import { ADDITIONAL_LOCALIZED_BLOG_SOURCES } from "@/lib/localized-blog-content-additional";
import { INCIDENT_LOCALIZED_BLOG_SOURCE } from "@/lib/localized-blog-content-incident";
import { DELIVERY_DELAY_LOCALIZED_BLOG_SOURCE } from "@/lib/localized-blog-content-delivery-delay";
import { MEETING_FOLLOW_UP_LOCALIZED_BLOG_SOURCE } from "@/lib/localized-blog-content-meeting-follow-up";
import { PROJECT_CLOSEOUT_LOCALIZED_BLOG_SOURCE } from "@/lib/localized-blog-content-project-closeout";
import { SPF_PERMERROR_LOCALIZED_BLOG_SOURCE } from "@/lib/localized-blog-content-spf-permerror";
import { LOCALIZED_BLOG_SLUGS } from "@/lib/localized-blog-slugs";

export { LOCALIZED_BLOG_SLUGS } from "@/lib/localized-blog-slugs";

type TranslationRow = readonly [string, string, string, string, string, string];

type LocalizedBlogSource = {
  category: TranslationRow;
  description: TranslationRow;
  sections: readonly {
    body: TranslationRow;
    title: TranslationRow;
  }[];
  slug: string;
  title: TranslationRow;
};

export type LocalizedBlogArticle = {
  category: string;
  description: string;
  sections: readonly { body: string; title: string }[];
  slug: string;
  title: string;
};

const indexByLocale: Record<SupportedLocale, number> = {
  ko: 0,
  en: 1,
  zh: 2,
  ja: 3,
  vi: 4,
  ru: 5,
};

const coreSources = [
  {
    slug: "company-email-address-guide",
    category: ["회사 이메일", "Company email", "公司邮箱", "会社メール", "Email công ty", "Почта компании"],
    title: ["회사 이메일 주소 만들기: 대표 메일부터 도메인 연결까지", "How to Create a Company Email Address: From Primary Mailbox to Domain Setup", "如何创建公司邮箱：从主邮箱到域名连接", "会社メールアドレスの作り方：代表メールからドメイン接続まで", "Cách tạo địa chỉ email công ty: Từ hộp thư chính đến kết nối tên miền", "Как создать адрес компании: от основного ящика до подключения домена"],
    description: ["회사 이름이 들어간 이메일 주소를 만들기 위해 필요한 도메인, 대표 주소, DNS 연결과 운영 순서를 정리합니다.", "A practical sequence for choosing a domain, primary address, DNS records, and operating rules for a company email address.", "整理创建公司邮箱所需的域名、主地址、DNS 连接与运营顺序。", "会社名入りメールを作るためのドメイン、代表アドレス、DNS接続、運用手順を整理します。", "Quy trình thực tế để chọn tên miền, địa chỉ chính, bản ghi DNS và cách vận hành email công ty.", "Практический порядок выбора домена, основного адреса, DNS-записей и правил работы корпоративной почты."],
    sections: [
      {
        title: ["주소보다 먼저 역할을 정하세요", "Define the role before the address", "先确定用途，再确定地址", "アドレスより先に役割を決める", "Xác định vai trò trước địa chỉ", "Сначала определите роль адреса"],
        body: ["대표 주소는 고객이 무엇을 위해 연락하는지 바로 이해할 수 있어야 합니다. 일반 문의는 contact 또는 hello, 고객지원은 support, 정산은 billing처럼 역할이 분명한 이름을 사용하세요. 개인 이름만 사용하면 담당자가 바뀔 때 홈페이지와 문서를 모두 수정해야 합니다.", "A primary address should immediately explain why a customer should use it. Use clear role names such as contact or hello for general inquiries, support for customer care, and billing for invoices. An address based only on one employee creates unnecessary changes when ownership moves.", "主邮箱应让客户立即明白用途。一般咨询可用 contact 或 hello，客服用 support，结算用 billing。仅使用个人姓名会在负责人变更时增加网站和资料修改成本。", "代表アドレスは用途がすぐ伝わる名前にします。一般問い合わせはcontactやhello、サポートはsupport、請求はbillingが分かりやすいです。個人名だけでは担当変更時にサイトや資料の修正が増えます。", "Địa chỉ chính cần cho khách hàng biết ngay mục đích. Dùng contact hoặc hello cho liên hệ chung, support cho hỗ trợ và billing cho thanh toán. Chỉ dùng tên cá nhân sẽ gây nhiều thay đổi khi đổi người phụ trách.", "Основной адрес должен сразу объяснять назначение. Для общих запросов подойдут contact или hello, для поддержки — support, для счетов — billing. Адрес только на имя сотрудника усложняет смену ответственного."],
      },
      {
        title: ["홈페이지와 같은 루트 도메인을 사용합니다", "Use the same root domain as your website", "使用与网站相同的根域名", "Webサイトと同じルートドメインを使う", "Dùng cùng tên miền gốc với website", "Используйте тот же корневой домен, что и сайт"],
        body: ["입력해야 하는 도메인은 www나 https가 없는 yourdomain.com 형태입니다. www는 홈페이지용 호스트이고 이메일 주소의 기준이 되는 도메인은 보통 루트 도메인입니다. 도메인을 구매한 곳과 DNS를 관리하는 곳이 다를 수 있으므로 네임서버가 가리키는 실제 관리 서비스를 확인하세요.", "Enter the root domain in the form yourdomain.com, without www or https. The www host is normally for the website; email uses the root domain. Your registrar and DNS provider may differ, so check the service currently authoritative for the nameservers.", "请输入不含 www 或 https 的 yourdomain.com 根域名。www 通常用于网站，邮箱以根域名为基准。域名注册商与 DNS 管理平台可能不同，请确认当前权威名称服务器。", "wwwやhttpsを除いたyourdomain.comを入力します。wwwは通常Webサイト用で、メールはルートドメインを基準にします。購入先とDNS管理先が異なる場合があるため、現在のネームサーバーを確認してください。", "Nhập tên miền gốc dạng yourdomain.com, không có www hoặc https. www thường dành cho website, còn email dùng tên miền gốc. Nơi mua tên miền và nơi quản lý DNS có thể khác nhau, vì vậy hãy kiểm tra nameserver hiện tại.", "Введите корневой домен вида yourdomain.com без www и https. www обычно относится к сайту, а почта использует корневой домен. Регистратор и DNS-провайдер могут различаться — проверьте действующие серверы имен."],
      },
      {
        title: ["MX와 발신 인증을 함께 설정합니다", "Configure MX and sender authentication together", "同时设置 MX 与发信验证", "MXと送信認証を一緒に設定する", "Thiết lập MX và xác thực gửi cùng nhau", "Настройте MX и аутентификацию отправителя вместе"],
        body: ["MX는 메일을 받을 서버를 지정합니다. SPF는 발송 가능한 서버를 선언하고 DKIM은 전자서명을 검증하며 DMARC는 인증 실패 정책을 정합니다. 수신만 확인하고 발신 인증을 빼면 Gmail 등에서 반송되거나 스팸으로 분류될 가능성이 커집니다.", "MX routes incoming mail. SPF declares authorized sending servers, DKIM verifies a cryptographic signature, and DMARC defines the policy for failed authentication. Testing only reception while skipping sender authentication increases the chance of Gmail rejection or spam placement.", "MX 指定收件服务器；SPF 声明授权发信服务器；DKIM 验证电子签名；DMARC 定义验证失败策略。只测试收信而忽略发信验证，会增加 Gmail 退信或进垃圾箱的风险。", "MXは受信先、SPFは送信許可サーバー、DKIMは署名検証、DMARCは認証失敗時の方針です。受信だけ確認して送信認証を省くと、Gmailで不達や迷惑メール判定が起きやすくなります。", "MX định tuyến thư đến. SPF khai báo máy chủ được phép gửi, DKIM xác minh chữ ký và DMARC quy định xử lý khi xác thực thất bại. Chỉ kiểm tra nhận thư mà bỏ xác thực gửi làm tăng nguy cơ Gmail trả lại hoặc đưa vào spam.", "MX направляет входящую почту. SPF объявляет разрешенные серверы, DKIM проверяет подпись, DMARC задает политику ошибок. Если проверить лишь прием и пропустить аутентификацию, Gmail чаще отклоняет письмо или помещает его в спам."],
      },
      {
        title: ["연결 후 양방향 테스트를 합니다", "Test in both directions after connection", "连接后进行双向测试", "接続後は双方向でテストする", "Kiểm tra hai chiều sau khi kết nối", "После подключения проверьте оба направления"],
        body: ["외부 Gmail이나 포털 메일에서 대표 주소로 보내 수신을 확인하고, 대표 주소에서 다시 외부로 보내 발신을 확인하세요. 메일 원문에서 SPF와 DKIM 결과를 확인하고 홈페이지, 명함, 견적서의 연락처를 새 주소로 통일하면 도입이 끝납니다.", "Send from Gmail or another external provider to the primary address, then reply outward from the company mailbox. Review SPF and DKIM results in the message source. Finally, update the website, proposals, and contact materials to use the same official address.", "先从 Gmail 或其他外部邮箱向主地址发信，再从公司邮箱向外部发信。请在邮件原文中确认 SPF 与 DKIM 结果，并统一更新网站、报价单和联系方式。", "Gmailなど外部から代表アドレスへ送り、次に会社メールから外部へ送ります。メール原文でSPFとDKIMを確認し、サイト、名刺、見積書の連絡先を新しい住所に統一します。", "Gửi từ Gmail hoặc dịch vụ ngoài vào địa chỉ chính, sau đó gửi ngược ra ngoài. Kiểm tra kết quả SPF và DKIM trong nguồn thư, rồi cập nhật website, báo giá và tài liệu liên hệ bằng địa chỉ chính thức.", "Отправьте письмо с Gmail или другого внешнего сервиса на основной адрес, затем обратно из корпоративного ящика. Проверьте SPF и DKIM в исходнике и обновите адрес на сайте, в предложениях и контактах."],
      },
    ],
  },
  {
    slug: "gmail-550-spf-dkim-fix",
    category: ["메일 반송", "Email delivery", "邮件退信", "メール不達", "Gửi email", "Доставка почты"],
    title: ["Gmail 550 5.7.26 해결: SPF와 DKIM 인증 실패 점검 순서", "Fix Gmail 550 5.7.26: A Practical SPF and DKIM Checklist", "解决 Gmail 550 5.7.26：SPF 与 DKIM 检查顺序", "Gmail 550 5.7.26の解決方法：SPF・DKIM確認手順", "Khắc phục Gmail 550 5.7.26: Quy trình kiểm tra SPF và DKIM", "Как исправить Gmail 550 5.7.26: проверка SPF и DKIM"],
    description: ["Gmail이 발신자 미인증으로 메일을 거절할 때 SPF, DKIM, 발신 IP와 From 도메인을 확인하는 순서입니다.", "How to diagnose Gmail rejection for an unauthenticated sender by checking SPF, DKIM, the sending IP, and the From domain.", "当 Gmail 因发件人未验证而拒信时，按顺序检查 SPF、DKIM、发信 IP 与 From 域名。", "Gmailが未認証送信者として拒否した時にSPF、DKIM、送信IP、Fromドメインを確認する手順です。", "Cách chẩn đoán Gmail từ chối người gửi chưa xác thực bằng cách kiểm tra SPF, DKIM, IP gửi và tên miền From.", "Диагностика отказа Gmail из-за неаутентифицированного отправителя: SPF, DKIM, IP отправки и домен From."],
    sections: [
      {
        title: ["반송문에서 인증 결과를 먼저 읽습니다", "Read the authentication result in the bounce", "先阅读退信中的验证结果", "不達通知の認証結果を読む", "Đọc kết quả xác thực trong thư trả lại", "Сначала прочитайте результат аутентификации"],
        body: ["550 5.7.26 메시지에는 Gmail이 검사한 SPF 도메인, 발신 IP, DKIM 통과 여부가 표시됩니다. SPF와 DKIM이 모두 실패했다면 수신자 주소 문제가 아니라 발신 도메인의 인증 문제입니다. 표시된 도메인과 실제 From 주소가 같은지도 확인하세요.", "The 550 5.7.26 response shows the SPF domain, sending IP, and whether DKIM passed. If both SPF and DKIM fail, the recipient address is not the root cause; sender authentication is. Confirm that the reported domain also aligns with the visible From address.", "550 5.7.26 会显示 SPF 域名、发信 IP 与 DKIM 是否通过。若 SPF 与 DKIM 均失败，问题在发信域名验证，而非收件地址。还应确认报告域名与 From 地址一致。", "550 5.7.26にはSPFドメイン、送信IP、DKIM結果が表示されます。両方失敗なら宛先ではなく送信認証の問題です。表示ドメインとFromアドレスが一致するかも確認します。", "Phản hồi 550 5.7.26 hiển thị tên miền SPF, IP gửi và trạng thái DKIM. Nếu cả SPF và DKIM đều thất bại, nguyên nhân là xác thực người gửi chứ không phải địa chỉ nhận. Hãy kiểm tra tên miền báo cáo có khớp From không.", "Ответ 550 5.7.26 показывает домен SPF, IP отправки и результат DKIM. Если оба механизма не прошли, причина в аутентификации отправителя, а не в адресе получателя. Проверьте совпадение домена с From."],
      },
      {
        title: ["SPF에는 실제 발신 서버가 포함되어야 합니다", "SPF must include the actual sending server", "SPF 必须包含实际发信服务器", "SPFに実際の送信サーバーを含める", "SPF phải gồm máy chủ gửi thực tế", "SPF должен включать реальный сервер отправки"],
        body: ["DNS의 루트 도메인에 SPF TXT 레코드는 하나만 두는 것이 원칙입니다. 오피셜메일이 제공한 include 값 또는 발신 IP가 정책 안에 있어야 합니다. SPF 레코드를 여러 개 만들거나 잘못된 하위 호스트에 입력하면 permerror 또는 fail이 발생합니다.", "Publish one SPF TXT policy at the root domain. It must authorize the include value or sending IP supplied by OfficialMail. Multiple SPF records or a record placed on the wrong host can produce permerror or fail.", "根域名原则上只发布一条 SPF TXT 策略，并授权 OfficialMail 提供的 include 值或发信 IP。多条 SPF 或放在错误主机上会导致 permerror 或 fail。", "ルートドメインのSPF TXTは原則1件です。OfficialMailが示すinclude値または送信IPを許可します。複数SPFや誤ったホストへの登録はpermerrorやfailになります。", "Chỉ nên có một chính sách SPF TXT ở tên miền gốc. Chính sách phải cho phép include hoặc IP gửi do OfficialMail cung cấp. Nhiều SPF hoặc đặt sai host có thể gây permerror hoặc fail.", "В корне домена должна быть одна SPF TXT-политика. Она обязана разрешать include или IP, указанный OfficialMail. Несколько SPF или запись на неверном хосте приводят к permerror или fail."],
      },
      {
        title: ["DKIM은 현재 도메인에 발급된 키를 사용합니다", "Use the DKIM key issued for the current domain", "使用为当前域名签发的 DKIM 密钥", "現在のドメイン用DKIMキーを使う", "Dùng khóa DKIM được cấp cho tên miền hiện tại", "Используйте DKIM-ключ текущего домена"],
        body: ["DKIM 공개키는 선택자와 도메인 조합으로 조회됩니다. 다른 회사나 이전 서버의 키를 복사하면 서명과 공개키가 일치하지 않습니다. 키를 재발급했다면 DNS의 기존 값을 새 값으로 교체하고 전파 후 다시 테스트하세요.", "A DKIM public key is resolved by selector and domain. Copying a key from another company or a previous server makes the message signature and DNS key disagree. After regeneration, replace the old DNS value and wait for propagation before testing again.", "DKIM 公钥由选择器与域名共同定位。复制其他公司或旧服务器的密钥会导致签名与 DNS 公钥不匹配。重新签发后应替换旧值，待传播后再测试。", "DKIM公開鍵はセレクタとドメインで特定されます。他社や旧サーバーのキーでは署名と公開鍵が一致しません。再発行後はDNS値を交換し、反映後に再テストします。", "Khóa công khai DKIM được tìm theo selector và tên miền. Sao chép khóa từ công ty khác hoặc máy chủ cũ khiến chữ ký không khớp DNS. Khi cấp lại, hãy thay giá trị cũ và chờ DNS cập nhật trước khi thử lại.", "Открытый ключ DKIM определяется селектором и доменом. Ключ другой компании или старого сервера не совпадет с подписью. После перевыпуска замените DNS-значение и дождитесь распространения."],
      },
      {
        title: ["수정 후 새 메일로 재검증합니다", "Retest with a new message", "修改后用新邮件复测", "修正後は新しいメールで再検証", "Kiểm tra lại bằng email mới", "Проверьте новым письмом"],
        body: ["DNS 조회가 정상이어도 이미 큐에 있던 메일은 이전 서명으로 발송될 수 있습니다. 변경 후에는 새 메일을 작성해 Gmail로 보내고 원문에서 spf=pass, dkim=pass, 가능하면 dmarc=pass를 확인하세요. 반송문에 표시된 IP가 예상 서버와 다르면 발송 경로도 다시 점검해야 합니다.", "Messages already queued can still carry an older signature even after DNS looks correct. Compose a new message and confirm spf=pass, dkim=pass, and preferably dmarc=pass in Gmail's original message view. If the bounce reports an unexpected IP, inspect the outbound route as well.", "即使 DNS 已正常，队列中的旧邮件仍可能使用旧签名。请新建邮件发送至 Gmail，并在原文中确认 spf=pass、dkim=pass，最好还有 dmarc=pass。若退信 IP 与预期不同，还需检查发信路径。", "DNSが正常でもキュー内の既存メールは旧署名の場合があります。新しいメールをGmailへ送り、原文でspf=pass、dkim=pass、可能ならdmarc=passを確認します。想定外のIPなら送信経路も確認します。", "Thư đã nằm trong hàng đợi có thể vẫn dùng chữ ký cũ dù DNS đã đúng. Hãy tạo email mới gửi đến Gmail và kiểm tra spf=pass, dkim=pass, tốt nhất dmarc=pass trong nguồn thư. Nếu IP khác dự kiến, hãy kiểm tra đường gửi.", "Письма в очереди могут сохранить старую подпись даже после исправления DNS. Отправьте новое письмо в Gmail и проверьте spf=pass, dkim=pass и желательно dmarc=pass. Если IP неожидан, проверьте маршрут отправки."],
      },
    ],
  },
  {
    slug: "business-email-external-integration",
    category: ["외부 연동", "Integrations", "外部集成", "外部連携", "Tích hợp", "Интеграции"],
    title: ["기업메일 외부 연동: Outlook IMAP과 발송 API를 구분하는 방법", "Business Email Integrations: Choosing Outlook IMAP or a Sending API", "企业邮箱外部集成：如何选择 Outlook IMAP 或发信 API", "企業メール外部連携：Outlook IMAPと送信APIの選び方", "Tích hợp email doanh nghiệp: Chọn Outlook IMAP hay API gửi thư", "Интеграции деловой почты: Outlook IMAP или API отправки"],
    description: ["사람이 메일을 읽고 답장할 때의 IMAP·SMTP와 서비스가 알림 메일을 보낼 때의 API를 목적별로 구분합니다.", "Understand when to use IMAP and SMTP for a person's mailbox and when an application should use the sending API.", "区分个人收发邮件使用的 IMAP·SMTP 与应用发送通知邮件使用的 API。", "人が読むメールのIMAP・SMTPと、サービス通知に使う送信APIを目的別に整理します。", "Phân biệt IMAP·SMTP cho người dùng hộp thư và API gửi thư cho ứng dụng.", "Разница между IMAP/SMTP для человека и API отправки для приложения."],
    sections: [
      {
        title: ["Outlook에서는 IMAP을 선택합니다", "Choose IMAP in Outlook", "在 Outlook 中选择 IMAP", "OutlookではIMAPを選ぶ", "Chọn IMAP trong Outlook", "В Outlook выбирайте IMAP"],
        body: ["오피셜메일 주소를 Outlook에서 읽고 답장하려면 계정 추가 과정에서 IMAP을 선택합니다. IMAP 수신 서버와 SMTP 보내는 서버를 각각 입력하며, 사용자 이름은 전체 이메일 주소입니다. POP은 한 기기로 내려받는 오래된 방식이라 여러 기기와 웹메일을 함께 쓸 때 권장하지 않습니다.", "To read and reply from Outlook, choose IMAP during account setup. Enter the IMAP incoming server and SMTP outgoing server separately, using the full email address as the username. POP downloads mail to one device and is not recommended when webmail and multiple devices must stay in sync.", "若要在 Outlook 中收发 OfficialMail，请在添加账号时选择 IMAP，分别填写 IMAP 收件服务器和 SMTP 发件服务器，用户名为完整邮箱地址。POP 会下载到单一设备，不适合多设备与网页邮箱同步。", "Outlookで送受信する場合はIMAPを選び、受信IMAPと送信SMTPを別々に入力します。ユーザー名は完全なメールアドレスです。POPは1台へダウンロードする方式のため、複数端末やWebメール併用には推奨しません。", "Để đọc và trả lời trong Outlook, chọn IMAP khi thêm tài khoản. Nhập riêng máy chủ nhận IMAP và gửi SMTP, dùng toàn bộ địa chỉ email làm tên đăng nhập. POP tải thư về một thiết bị nên không phù hợp khi dùng nhiều thiết bị và webmail.", "Для чтения и ответов в Outlook выберите IMAP. Отдельно укажите входящий IMAP и исходящий SMTP, имя пользователя — полный email. POP загружает письма на одно устройство и не подходит для синхронизации с веб-почтой и несколькими устройствами."],
      },
      {
        title: ["SMTP 인증은 같은 메일 계정을 사용합니다", "SMTP uses the same mailbox credentials", "SMTP 使用同一邮箱凭据", "SMTPは同じメールアカウントで認証", "SMTP dùng cùng thông tin hộp thư", "SMTP использует данные того же ящика"],
        body: ["보내는 서버의 사용자 이름도 전체 이메일 주소이며 메일함 비밀번호로 인증합니다. 포트와 보안 방식은 오피셜메일 외부 연동 화면에 표시된 값을 그대로 사용하세요. 서버 주소, 포트, 암호화 방식 중 하나라도 다르면 수신은 되지만 발신만 실패할 수 있습니다.", "The outgoing server also uses the full email address and mailbox password. Copy the port and security mode shown on the OfficialMail integration page. A wrong host, port, or encryption mode can allow receiving while outgoing mail still fails.", "发件服务器同样使用完整邮箱地址与邮箱密码验证。请按 OfficialMail 集成页显示的端口和安全方式填写。主机、端口或加密任一错误，都可能导致能收信但不能发信。", "送信サーバーも完全なメールアドレスとメールボックスのパスワードで認証します。ポートと暗号化方式は外部連携画面の値を使います。サーバー、ポート、暗号化のいずれかが違うと受信できても送信だけ失敗します。", "Máy chủ gửi cũng dùng toàn bộ email và mật khẩu hộp thư. Sao chép cổng và chế độ bảo mật từ trang tích hợp OfficialMail. Sai máy chủ, cổng hoặc mã hóa có thể nhận được nhưng gửi thất bại.", "Исходящий сервер также использует полный email и пароль ящика. Скопируйте порт и режим защиты со страницы интеграций OfficialMail. Ошибка в хосте, порте или шифровании может оставить прием рабочим, а отправку — нет."],
      },
      {
        title: ["서비스 알림에는 발송 API를 사용합니다", "Use the sending API for application notifications", "应用通知应使用发信 API", "サービス通知には送信APIを使う", "Dùng API gửi cho thông báo ứng dụng", "Для уведомлений приложения используйте API"],
        body: ["회원가입, 비밀번호 재설정, 주문 완료처럼 서버가 자동으로 보내는 메일은 IMAP이 아니라 발송 API가 적합합니다. API 키는 서버 환경변수에 보관하고 브라우저 코드나 공개 저장소에 넣지 마세요. 요청 결과의 messageId를 저장하면 이후 발송 상태와 실패 로그를 조회할 수 있습니다.", "For registration, password reset, and order-completion messages sent by a server, use the sending API rather than IMAP. Store API keys in server environment variables, never browser code or a public repository. Save the returned messageId to query delivery status and failures later.", "注册、重置密码、订单完成等服务器自动邮件应使用发信 API，而非 IMAP。API 密钥应保存在服务器环境变量中，不得放入浏览器代码或公开仓库。保存返回的 messageId 便于查询状态与失败日志。", "会員登録、パスワード再設定、注文完了などサーバーが自動送信するメールはIMAPではなく送信APIを使います。APIキーはサーバー環境変数に保存し、ブラウザや公開リポジトリに置かないでください。messageIdを保存すると状態と失敗ログを確認できます。", "Email đăng ký, đặt lại mật khẩu và hoàn tất đơn do máy chủ gửi nên dùng API thay vì IMAP. Lưu API key trong biến môi trường máy chủ, không đưa vào trình duyệt hay kho công khai. Lưu messageId trả về để tra trạng thái và lỗi.", "Для регистрации, сброса пароля и заказов, отправляемых сервером, используйте API, а не IMAP. Храните ключ в переменной окружения сервера, не в браузере и не в публичном репозитории. Сохраняйте messageId для проверки статуса и ошибок."],
      },
      {
        title: ["사람용 계정과 시스템용 키를 분리합니다", "Separate human accounts from system keys", "分离人员账号与系统密钥", "人用アカウントとシステムキーを分ける", "Tách tài khoản người dùng và khóa hệ thống", "Разделяйте аккаунты людей и системные ключи"],
        body: ["담당자가 사용하는 Outlook 자격증명과 쇼핑몰 서버의 API 키를 공유하면 퇴사, 키 교체, 장애 대응이 어려워집니다. 용도별 키를 만들고 최소 권한과 IP 제한을 적용하며, 키를 폐기해도 사람의 메일 로그인은 영향받지 않도록 분리하세요.", "Sharing one credential between Outlook users and a store server makes offboarding, rotation, and incident response difficult. Create keys by purpose, apply least privilege and IP restrictions, and keep mailbox sign-in independent from API key revocation.", "若 Outlook 用户与商城服务器共用凭据，会增加离职、轮换与事故处理难度。应按用途创建密钥，采用最小权限和 IP 限制，并确保撤销 API 密钥不影响人工邮箱登录。", "Outlook利用者とショップサーバーで認証情報を共有すると、退職・ローテーション・障害対応が困難です。用途別キー、最小権限、IP制限を使い、APIキー廃止がメールログインへ影響しないよう分離します。", "Dùng chung thông tin giữa Outlook và máy chủ cửa hàng gây khó khi nhân sự nghỉ, đổi khóa hoặc xử lý sự cố. Tạo khóa theo mục đích, áp dụng quyền tối thiểu và giới hạn IP, tách việc thu hồi khóa khỏi đăng nhập hộp thư.", "Общие данные для Outlook и сервера магазина усложняют увольнение, ротацию и инциденты. Создавайте ключи по назначению, применяйте минимальные права и IP-ограничения, отделяйте отзыв API-ключа от входа в почту."],
      },
    ],
  },
  {
    slug: "online-store-business-email-trust",
    category: ["쇼핑몰 운영", "Online stores", "网店运营", "オンラインストア", "Cửa hàng trực tuyến", "Интернет-магазины"],
    title: ["쇼핑몰 사업자 이메일이 신뢰를 만드는 이유와 대표 주소 운영법", "Why a Business Email Builds Trust for an Online Store", "网店企业邮箱为何提升信任，以及主地址运营方法", "ショップの事業用メールが信頼をつくる理由と運用方法", "Vì sao email doanh nghiệp tạo niềm tin cho cửa hàng trực tuyến", "Почему корпоративная почта повышает доверие к интернет-магазину"],
    description: ["주문, 교환, 제휴, 정산 문의를 공식 도메인 주소로 분리해 고객 신뢰와 인수인계 기록을 함께 관리하는 방법입니다.", "How to organize orders, returns, partnerships, and billing under official domain addresses while preserving trust and handover history.", "将订单、退换货、合作与结算咨询按官方域名地址分类，同时管理客户信任与交接记录。", "注文・交換・提携・請求を公式ドメインで分け、顧客信頼と引き継ぎ記録を管理する方法です。", "Cách phân loại đơn hàng, đổi trả, hợp tác và thanh toán bằng địa chỉ tên miền chính thức, đồng thời giữ niềm tin và lịch sử bàn giao.", "Как разделить заказы, возвраты, партнерства и расчеты по официальным адресам, сохраняя доверие и историю передачи."],
    sections: [
      {
        title: ["고객은 주소에서 공식 채널인지 판단합니다", "Customers judge whether the channel is official", "客户会从邮箱地址判断是否官方", "顧客はアドレスで公式窓口か判断する", "Khách hàng đánh giá kênh chính thức qua địa chỉ", "Клиент определяет официальный канал по адресу"],
        body: ["교환이나 환불처럼 민감한 문의에서 개인 포털 주소가 보이면 고객은 홈페이지의 공식 연락처가 맞는지 다시 확인합니다. 쇼핑몰 도메인과 같은 주소를 사용하면 사이트, 주문 안내, 사업자 정보가 한 브랜드로 연결됩니다.", "For sensitive requests such as returns or refunds, a personal portal address makes customers verify whether it is really the store's channel. An address on the store domain connects the website, order messages, and business identity under one brand.", "在退换货等敏感咨询中，个人邮箱会让客户重新核实是否为官方渠道。使用与商城相同的域名，可将网站、订单通知与企业身份统一为一个品牌。", "交換・返金などでは個人メールだと公式窓口か再確認されます。ショップと同じドメインなら、サイト、注文案内、事業者情報が一つのブランドでつながります。", "Trong yêu cầu nhạy cảm như đổi trả, email cá nhân khiến khách hàng phải xác minh lại. Địa chỉ cùng tên miền cửa hàng kết nối website, thông báo đơn hàng và danh tính doanh nghiệp dưới một thương hiệu.", "В вопросах возврата личный адрес заставляет клиента перепроверять официальный канал. Адрес на домене магазина связывает сайт, уведомления о заказе и данные компании единым брендом."],
      },
      {
        title: ["업무별 주소를 너무 많이 만들지 마세요", "Do not create too many addresses too early", "不要过早创建太多地址", "最初からアドレスを増やしすぎない", "Đừng tạo quá nhiều địa chỉ quá sớm", "Не создавайте слишком много адресов сразу"],
        body: ["처음에는 contact 또는 support 같은 대표 주소 하나로 충분합니다. 문의량이 늘어나면 orders, returns, partnership, billing처럼 실제 담당 흐름이 분리되는 업무만 추가하세요. 주소만 늘고 담당 규칙이 없으면 고객과 직원 모두 더 혼란스러워집니다.", "Start with one address such as contact or support. As volume grows, add only roles with genuinely separate workflows, such as orders, returns, partnership, or billing. Extra addresses without ownership rules create more confusion for customers and staff.", "初期只需 contact 或 support 等一个主地址。咨询量增加后，再为订单、退换货、合作、结算等真正独立的流程添加地址。只有地址没有负责规则会增加混乱。", "最初はcontactまたはsupportの代表アドレス1件で十分です。件数が増えたらorders、returns、partnership、billingなど実際に流れが分かれる業務だけ追加します。担当ルールなしに増やすと混乱します。", "Ban đầu chỉ cần một địa chỉ như contact hoặc support. Khi lượng thư tăng, chỉ thêm các vai trò có quy trình riêng như orders, returns, partnership hoặc billing. Nhiều địa chỉ mà không có quy tắc phụ trách sẽ gây rối.", "Сначала достаточно contact или support. По мере роста добавляйте только реально отдельные процессы: orders, returns, partnership, billing. Множество адресов без правил ответственности запутает клиентов и сотрудников."],
      },
      {
        title: ["자동 메일과 상담 메일을 분리합니다", "Separate automated mail from customer conversations", "分离自动邮件与人工咨询", "自動メールと相談メールを分ける", "Tách thư tự động và trao đổi khách hàng", "Разделяйте автоматические письма и обращения"],
        body: ["주문 완료나 비밀번호 재설정은 API로 보내는 시스템 메일이고, 교환 상담과 제휴 답장은 사람이 이어서 처리하는 메일입니다. 발신 주소와 Reply-To를 목적에 맞게 두고, 답장이 필요한 메일은 실제 담당자가 확인하는 주소로 연결하세요.", "Order confirmations and password resets are system messages sent by API, while return requests and partnership replies continue as human conversations. Set the From and Reply-To addresses by purpose, and route replies to a mailbox monitored by the responsible person.", "订单完成和密码重置属于 API 系统邮件，退换货与合作回复则需要人工处理。请按用途设置 From 与 Reply-To，并将需回复的邮件导向真实负责人的邮箱。", "注文完了やパスワード再設定はAPIのシステムメール、交換相談や提携返信は人が続けるメールです。目的に合わせてFromとReply-Toを設定し、返信は担当者が確認するアドレスへ送ります。", "Xác nhận đơn hàng và đặt lại mật khẩu là thư hệ thống gửi qua API; đổi trả và hợp tác là cuộc trao đổi của con người. Đặt From và Reply-To theo mục đích, chuyển câu trả lời đến hộp thư có người phụ trách.", "Подтверждение заказа и сброс пароля — системные письма через API, а возвраты и партнерства — человеческая переписка. Настройте From и Reply-To по назначению и направляйте ответы в контролируемый ящик."],
      },
      {
        title: ["담당자가 바뀌어도 기록을 남깁니다", "Keep the history when staff changes", "负责人变更后仍保留记录", "担当変更後も記録を残す", "Giữ lịch sử khi thay đổi nhân sự", "Сохраняйте историю при смене сотрудника"],
        body: ["직원 개인 계정에서 고객 문의를 받으면 퇴사 후 대화와 첨부파일을 찾기 어렵습니다. 회사 메일함과 역할 주소를 사용하고, 보낸 메일도 같은 시스템에 남기면 인수인계 시 고객에게 다시 설명을 요구하지 않아도 됩니다.", "When customer mail lives in an employee's personal account, conversations and attachments become hard to recover after departure. Use company mailboxes and role addresses, keeping sent mail in the same system so customers do not need to repeat their history during handover.", "若客户邮件保存在员工个人账号，离职后难以找回对话与附件。使用公司邮箱和职能地址，并统一保存已发邮件，可避免交接时让客户重复说明。", "顧客メールが社員個人アカウントにあると退職後に会話や添付を探せません。会社メールと役割アドレスを使い、送信履歴も同じ場所に残せば引き継ぎ時に顧客へ説明を求めずに済みます。", "Nếu thư khách hàng nằm trong tài khoản cá nhân, rất khó tìm lại trao đổi và tệp sau khi nhân sự nghỉ. Dùng hộp thư công ty, địa chỉ theo vai trò và giữ thư đã gửi cùng hệ thống để khách không phải kể lại khi bàn giao.", "Если письма клиентов находятся в личном аккаунте сотрудника, после ухода трудно найти переписку и вложения. Используйте корпоративные ящики и служебные адреса, сохраняя исходящие письма в одной системе."],
      },
    ],
  },
  {
    slug: "company-email-guide",
    category: ["기업메일 가이드", "Business email guide", "企业邮箱指南", "ビジネスメールガイド", "Hướng dẫn email doanh nghiệp", "Руководство по деловой почте"],
    title: ["기업메일 도입 전 확인할 것: 비용, 도메인, 팀 운영 체크리스트", "Business Email Checklist: Cost, Domain, and Team Operations", "企业邮箱导入清单：费用、域名与团队运营", "企業メール導入チェック：費用・ドメイン・チーム運用", "Danh sách kiểm tra email doanh nghiệp: Chi phí, tên miền và đội ngũ", "Чек-лист деловой почты: стоимость, домен и работа команды"],
    description: ["기업메일 서비스를 고를 때 계정 수, 저장공간, DNS 지원, 발신 인증, 외부 연동과 해지 후 운영까지 확인할 기준입니다.", "Criteria for evaluating mailbox count, storage, DNS support, sender authentication, integrations, and what happens after cancellation.", "选择企业邮箱时，应检查账号数、存储空间、DNS 支持、发信验证、外部集成及取消后的运营。", "企業メール選定時にアカウント数、容量、DNS支援、送信認証、外部連携、解約後を確認する基準です。", "Tiêu chí đánh giá số hộp thư, dung lượng, hỗ trợ DNS, xác thực gửi, tích hợp và xử lý sau khi hủy.", "Критерии выбора: число ящиков, хранилище, DNS-поддержка, аутентификация, интеграции и работа после отмены."],
    sections: [
      {
        title: ["현재 필요한 계정 수부터 계산합니다", "Count the accounts you need now", "先计算当前所需账号数", "今必要なアカウント数を数える", "Tính số tài khoản cần ngay bây giờ", "Сначала посчитайте нужные аккаунты"],
        body: ["대표 혼자 운영한다면 대표 메일 하나로 시작할 수 있습니다. 팀원이 있어도 모두에게 즉시 계정을 만들기보다 고객 응대, 정산, 영업처럼 실제로 개인 책임과 발송 기록이 필요한 역할을 구분하세요. 과금 단위가 사용자, 메일함, 별칭 중 무엇인지도 비교해야 합니다.", "A solo founder can start with one primary mailbox. Even with a team, do not create accounts for everyone immediately; identify roles that need personal responsibility and sent history, such as support, billing, or sales. Compare whether pricing is based on users, mailboxes, or aliases.", "个人经营者可从一个主邮箱开始。即使有团队，也不必立即为所有人创建账号，应先区分客服、结算、销售等需要个人责任与发件记录的角色，并比较按用户、邮箱还是别名计费。", "一人なら代表メール1件から始められます。チームでも全員分をすぐ作らず、サポート・請求・営業など個人責任と送信履歴が必要な役割を見極めます。課金単位が利用者、メールボックス、別名のどれかも比較します。", "Người sáng lập cá nhân có thể bắt đầu với một hộp thư chính. Có đội ngũ cũng không cần tạo ngay cho tất cả; hãy xác định vai trò cần trách nhiệm cá nhân và lịch sử gửi như hỗ trợ, thanh toán, bán hàng. So sánh cách tính phí theo người dùng, hộp thư hay bí danh.", "Индивидуальному предпринимателю достаточно одного основного ящика. Даже в команде не создавайте всем аккаунты сразу: выделите роли, где нужна личная ответственность и история отправки — поддержка, счета, продажи. Сравните оплату за пользователя, ящик или алиас."],
      },
      {
        title: ["DNS 설정 지원 범위를 확인합니다", "Check the scope of DNS support", "确认 DNS 支持范围", "DNS設定支援の範囲を確認", "Kiểm tra phạm vi hỗ trợ DNS", "Проверьте объем помощи с DNS"],
        body: ["도메인 연결 실패의 대부분은 값을 몰라서보다 어디에 입력해야 하는지 몰라서 생깁니다. 도메인 구매처, 현재 네임서버, 홈페이지 호스팅사를 구분해주는지, MX·SPF·DKIM·DMARC 값을 도메인별로 제공하고 검증 결과를 보여주는지 확인하세요.", "Most connection failures happen because users do not know where to enter records, not because the values are unavailable. Check whether the service helps distinguish the registrar, current nameserver provider, and website host, and whether it supplies and verifies MX, SPF, DKIM, and DMARC per domain.", "大多数连接失败源于不知道在哪里填写，而不是缺少值。请确认服务是否帮助区分注册商、当前名称服务器与网站托管，并按域名提供和验证 MX、SPF、DKIM、DMARC。", "接続失敗の多くは値より入力場所が分からないことが原因です。購入先、現在のネームサーバー、サイトホストを区別し、ドメイン別にMX・SPF・DKIM・DMARCと検証結果を示すか確認します。", "Hầu hết lỗi kết nối do không biết nhập ở đâu, không phải thiếu giá trị. Hãy xem dịch vụ có phân biệt nhà đăng ký, nameserver hiện tại, host website và cung cấp, xác minh MX, SPF, DKIM, DMARC theo tên miền không.", "Большинство ошибок связано не со значениями, а с местом их ввода. Проверьте, помогает ли сервис различать регистратора, текущий DNS и хостинг и предоставляет ли проверки MX, SPF, DKIM и DMARC для домена."],
      },
      {
        title: ["저장공간은 초과 시 정책까지 봅니다", "Review what happens when storage is exceeded", "关注存储超限后的政策", "容量超過時の扱いまで確認", "Xem chính sách khi vượt dung lượng", "Узнайте политику при превышении хранилища"],
        body: ["표시된 용량 숫자만 보지 말고 초과 시 기존 메일이 삭제되는지, 새 메일 수신만 중단되는지, 플랜을 낮출 때 데이터가 어떻게 되는지 확인하세요. 첨부파일이 많은 업종은 일반 첨부와 대용량 링크 방식, 보관 기간도 함께 비교해야 합니다.", "Do not compare only the storage number. Check whether existing mail is deleted, whether only new reception stops, and what happens when downgrading. Teams with many attachments should also compare regular attachment limits, large-file links, and retention.", "不要只比较容量数字，还要确认超限后是否删除旧邮件、是否仅停止新邮件接收，以及降级时数据如何处理。附件多的行业还应比较普通附件上限、大文件链接与保留期。", "容量の数字だけでなく、超過時に既存メールが削除されるか、新規受信だけ止まるか、ダウングレード時のデータを確認します。添付が多い場合は通常添付、大容量リンク、保存期間も比較します。", "Đừng chỉ nhìn con số dung lượng. Hãy kiểm tra có xóa thư cũ không, chỉ dừng nhận thư mới hay sao và dữ liệu thế nào khi hạ gói. Đội ngũ nhiều tệp nên so sánh giới hạn đính kèm, liên kết tệp lớn và thời gian lưu.", "Сравнивайте не только объем. Узнайте, удаляются ли старые письма, прекращается ли лишь прием новых и что происходит при снижении тарифа. Для крупных вложений сравните обычный лимит, ссылки на большие файлы и срок хранения."],
      },
      {
        title: ["외부 연동과 이동 가능성을 확인합니다", "Check integrations and portability", "确认外部集成与可迁移性", "外部連携と移行性を確認", "Kiểm tra tích hợp và khả năng di chuyển", "Проверьте интеграции и переносимость"],
        body: ["Outlook이나 모바일 앱을 쓴다면 IMAP·SMTP를, 서비스 알림을 보낸다면 발송 API를 확인하세요. 담당자가 바뀌거나 서비스를 이전할 때 메일을 내보낼 수 있는지, 계정 해지 전에 필요한 데이터를 백업할 수 있는지도 중요한 선택 기준입니다.", "If users need Outlook or mobile apps, confirm IMAP and SMTP. If an application sends notifications, confirm a sending API. Portability also matters: determine whether mail can be exported and backed up before an account is closed or a provider changes.", "如需 Outlook 或移动应用，请确认 IMAP·SMTP；如应用发送通知，请确认发信 API。还应确认更换负责人或服务商时能否导出邮件，并在注销前备份数据。", "OutlookやモバイルアプリにはIMAP・SMTP、サービス通知には送信APIを確認します。担当変更や移行時にメールを出力できるか、解約前にバックアップできるかも重要です。", "Nếu dùng Outlook hoặc ứng dụng di động, kiểm tra IMAP·SMTP; nếu ứng dụng gửi thông báo, kiểm tra API. Hãy xác nhận có thể xuất và sao lưu thư trước khi đóng tài khoản hoặc chuyển nhà cung cấp không.", "Для Outlook и мобильных приложений нужны IMAP/SMTP, для уведомлений сервиса — API. Важно также понять, можно ли экспортировать и резервировать почту перед закрытием аккаунта или сменой поставщика."],
      },
    ],
  },
] as const satisfies readonly LocalizedBlogSource[];

const sources: readonly LocalizedBlogSource[] = [
  ...coreSources,
  ...ADDITIONAL_LOCALIZED_BLOG_SOURCES,
  INCIDENT_LOCALIZED_BLOG_SOURCE,
  DELIVERY_DELAY_LOCALIZED_BLOG_SOURCE,
  MEETING_FOLLOW_UP_LOCALIZED_BLOG_SOURCE,
  PROJECT_CLOSEOUT_LOCALIZED_BLOG_SOURCE,
  SPF_PERMERROR_LOCALIZED_BLOG_SOURCE,
];

if (
  sources.length !== LOCALIZED_BLOG_SLUGS.length ||
  sources.some((source, index) => source.slug !== LOCALIZED_BLOG_SLUGS[index])
) {
  throw new Error("Localized blog content and slug manifest are out of sync.");
}

export function getLocalizedBlogArticle(
  slug: string,
  locale: SupportedLocale,
): LocalizedBlogArticle | null {
  if (locale === "ko") return null;
  const source = sources.find((item) => item.slug === slug);
  if (!source) return null;
  const index = indexByLocale[locale];
  return {
    category: source.category[index],
    description: source.description[index],
    sections: source.sections.map((section) => ({
      body: section.body[index],
      title: section.title[index],
    })),
    slug: source.slug,
    title: source.title[index],
  };
}

export function getLocalizedBlogArticles(locale: SupportedLocale) {
  if (locale === "ko") return [];
  return sources
    .map((source) => getLocalizedBlogArticle(source.slug, locale))
    .filter((article): article is LocalizedBlogArticle => Boolean(article));
}
