尧图精选

Nhost Auth 邮件模板多语言生成指南:从 React Email 源码到 Go 服务端渲染的完整工作流

🕒 发布时间:2026/9/16 18:06:35 📁 来源:尧图网络
Nhost Auth 邮件模板多语言生成指南从 React Email 源码到 Go 服务端渲染的完整工作流【免费下载链接】nhostThe Open Source Firebase Alternative with GraphQL.项目地址: https://gitcode.com/GitHub_Trending/nh/nhostNhost 的 Auth 服务内置了一套基于 React Email 构建的事务邮件模板覆盖邮箱验证、密码重置、免密登录等核心场景并通过 Go 服务端的模板引擎按语言locale动态渲染、发送。本文以仓库中 services/auth/email-templates/generator/README.md 为骨架完整讲解如何为新语言生成模板、生成器的源码实现、占位符变量的注入机制以及 Go 端加载与回退逻辑帮助你掌握为 Nhost Auth 增加一个全新语言邮件模板的端到端流程。一、邮件模板在 Nhost Auth 中的角色Nhost Auth 在注册、登录、密码重置等流程中需要发送五类事务邮件模板目录名邮件用途email-confirm-change确认修改邮箱地址email-verify验证邮箱地址password-reset重置密码signin-passwordless免密登录Magic Linksignin-otp一次性密码OTP登录此外还有一个独立的 SMS 模板signin-passwordless-smsbody.txt用于短信验证码登录。模板按语言分目录存放在 services/auth/email-templates/ 下当前仓库已内置bg保加利亚语、cs捷克语、en英语、es西班牙语、fr法语五种语言。每种语言的目录结构完全一致例如enservices/auth/email-templates/en/ ├── email-confirm-change/ │ ├── body.html │ └── subject.txt ├── email-verify/ │ ├── body.html │ └── subject.txt ├── password-reset/ │ ├── body.html │ └── subject.txt ├── signin-otp/ │ ├── body.html │ └── subject.txt ├── signin-passwordless/ │ ├── body.html │ └── subject.txt └── signin-passwordless-sms/ └── body.txt每个邮件由两部分组成body.html是邮件正文HTMLsubject.txt是邮件主题行。这一目录结构同时是 Go 端模板加载器的契约详见下文第四节。二、模板的创作基础React Email 组件模板的「源文件」是位于 services/auth/email-templates/generator/ 目录下的 React TSX 组件使用 React Email 框架编写email-confirm-change.tsxemail-verify.tsxpassword-reset.tsxsignin-passwordless.tsxsignin-otp.tsxrender-emails.ts渲染脚本见第三节以 email-verify.tsx 为例组件从react-email/components导入Html、Body、Container、Heading、Text、Button、Hr、Section、Row、Column、Img、Link等现成组件通过内联样式对象定义邮件布局整体背景#f5f5f5、白色圆角卡片容器maxWidth: 560px、标题 24px、主按钮蓝色#0052CD页脚是 Nhost Logo 与 Powered by Nhost 链接。关键点在于占位符按钮的href直接写成${link}Section style{buttonContainer} Button style{button} href${link} Verify Email /Button /Section${link}会被原样保留到渲染出的 HTML 中最终由 Go 服务端在发送邮件时替换为真实的验证链接。signin-otp.tsx则略有不同它把${ticket}和${redirectTo}作为字符串模板渲染在正文中用于展示一次性密码文本。三、开发预览与生成命令1. 开发预览pnpm dev:emailREADME 说明模板使用 React Email 制作可以在仓库根目录运行以下命令进行编辑与实时预览pnpm dev:email该命令会启动 React Email 的开发预览服务你可以在浏览器中逐个查看五类模板的渲染效果确认布局与样式无误后再进行多语言生成。2. 为新语言生成模板pnpm generate:emails locale在仓库根目录执行pnpm generate:emails locale其中locale是目标语言的 BCP 47 语言代码如de、ja、zh。脚本执行完成后会在email-templates目录下创建一个以该 locale 命名的新文件夹内部包含五类邮件各自的body.html与subject.txt随后你只需要把邮件文案改写成对应语言即可。例如为德语生成模板pnpm generate:emails de生成结束后你会得到email-templates/de/目录与现有en、fr等目录平级接下来就可以把其中的英文文案逐条翻译为德语。3. 生成的产物长什么样生成器写入的 HTML 是经过 Prettier 格式化、可直接被邮件客户端解析的标准 HTML。以 en/email-verify/body.html 为参照产物结构为 XHTML 1.0 Transitional 文档html dirltr langen正文内嵌表格布局table套table按钮是一个a href${link}元素并带有 MSOMicrosoft Outlook条件注释与mso-text-raise等兼容处理确保在 Outlook 等桌面客户端中也能正常显示。四、生成器实现剖析render-emails.ts生成流程的核心逻辑在 render-emails.ts 中完整代码只有 80 行左右值得逐段理解。1. 定义邮件清单。emails数组罗列了五种邮件每项包含name、body、subjectconst emails [ { name: email-confirm-change, body: prettier.format(render(EmailConfirmChange()), { parser: html, printWidth: 500, }), subject: subject, }, // ... email-verify / password-reset / signin-passwordless / signin-otp ];render()来自react-email/components把 TSX 组件渲染为 HTML 字符串prettier.format以parser: html、printWidth: 500对 HTML 做格式化保证生成文件的可读性与一致性。2. 注意 subject 是占位符。生成阶段subject统一写为字面量subject这意味着脚本生成出的subject.txt内容就是subject占位文本必须手动改写成真实主题。对比现有语言目录en/email-verify/subject.txt的内容是 Verify your emailes/email-verify/subject.txt是 Verifica tu correo electrónico这些都是生成后人工翻译的结果。3. 创建目录并落盘。脚本按path.resolve(./email-templates/${targetLocale})计算目标目录因此实际落盘位置取决于执行命令时的工作目录README 约定在仓库根运行。目录不存在时自动创建随后为每个邮件写入两个文件fs.writeFileSync(${targetFolder}/${email.name}/body.html, email.body); fs.writeFileSync(${targetFolder}/${email.name}/subject.txt, email.subject);4. locale 参数校验。脚本从process.argv读取第一个参数作为 locale缺失时打印Please provide a locale for the emails.并以退出码 1 终止。5. 一个容易遗漏的点SMS 模板不会自动生成。从emails数组可以看到脚本只处理五类 HTML 邮件不会生成signin-passwordless-sms/body.txt。因此新增语言时需要参照现有语言如 en/signin-passwordless-sms/body.txt内容为Your code is ${code}.手动创建该文件否则短信登录在该语言下会回退到默认 locale。五、占位符变量与 Go 服务端渲染生成出的body.html/subject.txt里保留了${...}形式的占位符Go 端在发送邮件时负责注入真实数据。相关实现集中在 services/auth/go/notifications/templates.go。1. 模板加载。NewTemplatesFromFilesystem(basePath, defaultLocale, logger)遍历模板目录把每个body.html、body.txt、subject.txt文件用 fasttemplate 以${和}为定界符解析为模板对象键为相对路径如en/email-verify/body.html。2. 模板名常量。TemplateName定义了五种模板名与 generator 中的name一一对应const ( TemplateNameEmailVerify TemplateName email-verify TemplateNameEmailConfirmChange TemplateName email-confirm-change TemplateNameSigninPasswordless TemplateName signin-passwordless TemplateNameSigninOTP TemplateName signin-otp TemplateNamePasswordReset TemplateName password-reset )3. 按 locale 查找。GetTemplate(templateName, locale)拼接locale/name/body.html与locale/name/subject.txt两个路径去查找模板任一缺失都会返回ErrTemplateNotFound。4. 可用变量全集。TemplateData结构体定义了模板中可以引用的全部变量其ToMap方法把字段转换为模板变量名模板变量含义${link}验证 / 重置 / 登录链接${displayName}用户显示名${email}用户邮箱${newEmail}修改邮箱时的目标新邮箱${ticket}OTP 一次性密码${redirectTo}登录后的重定向地址${locale}当前语言代码${serverUrl}服务端地址${clientUrl}客户端地址五类模板实际用到的变量如下email-confirm-change、email-verify、password-reset、signin-passwordless主要使用${link}signin-otp使用${ticket}与${redirectTo}SMS 模板RenderSMS仅注入${code}见TemplateSMSData。5. locale 回退机制。Render在指定 locale 找不到模板时会记录警告并回退到默认 locale 再取一次模板SMS 渲染RenderSMS也有同样的回退逻辑。值得留意的是从当前源码看邮件模板的回退分支中模板名被固定为email-verifytemplates.go这意味着如果某个非email-verify的模板在指定 locale 缺失回退时实际取到的是默认 locale 下的email-verify模板。这一实现细节提醒我们新增语言时务必保证五类模板齐全不要依赖回退机制兜底。6. 测试验证。services/auth/go/notifications/templates_test.go 中的TestGetRawTemplates直接以../../email-templates/为路径断言五种语言下每个模板文件的相对路径都在加载结果中TestRenderTemplate之类的用例则验证${link}、${displayName}、${email}、${ticket}、${redirectTo}、${serverUrl}、${clientUrl}、${locale}均被正确替换以及 locale 缺失时的回退行为。email_test.go 则用NewTemplatesFromFilesystem(../../email-templates/, en, logger)加载模板并实际发送邮件验证完整链路。六、配置默认语言、允许语言与模板路径Go 端通过 CLI 参数或环境变量控制模板的加载与语言选择定义于 services/auth/go/cmd/serve.go参数环境变量默认值说明--default-localeAUTH_LOCALE_DEFAULTen默认语言locale 缺失或回退时使用--allowed-localesAUTH_LOCALE_ALLOWED_LOCALES[en]允许使用的语言列表--email-templates-pathAUTH_EMAIL_TEMPLATES_PATH/app/email-templates模板目录路径模板路径的解析顺序在 services/auth/go/cmd/email.go 的getTemplates中实现依次尝试参数指定路径、email-templates相对路径、share/email-templates找到第一个存在的目录即使用全部不存在则报错templates path not found。这意味着你完全可以自建一套翻译好的模板目录通过环境变量挂载给 Auth 服务而无需改动源码。注意--allowed-locales与--default-locale的默认值都是en新增语言后需要把新 locale 追加进 allowed 列表例如AUTH_LOCALE_ALLOWED_LOCALESde,en否则用户即使属于德语区服务也可能不会按德语渲染邮件。七、模板内嵌与分发embed.go为了让 CLI 等下游消费者在不访问远程资源的情况下也能拿到默认模板仓库用 Go 标准库的embed把五种语言模板直接编译进二进制//go:embed all:bg all:cs all:en all:es all:fr var FS embed.FS见 services/auth/email-templates/embed.go。文件头注释明确说明该包将默认模板暴露为内嵌文件系统使 CLI 能在构建期打包它们而不是在运行时从远端获取。这意味着新增语言后如果希望 CLI 内嵌版本也包含该语言需要同步更新//go:embed指令把新语言目录加入内嵌列表。八、为项目新增一个语言模板的完整清单综合以上分析把 README 的流程展开为一份可执行的检查清单在仓库根目录运行pnpm dev:email用 React Email 预览确认模板基线运行pnpm generate:emails locale例如pnpm generate:emails de生成新 locale 目录及五类邮件的body.html、subject.txt将生成文件移动到 services/auth/email-templates/ 下的对应 locale 目录与en、fr等平级翻译并改写每封邮件的正文body.html中的标题、文案、按钮文字与主题subject.txt注意生成时是subject占位符确认${link}、${ticket}、${redirectTo}、${code}等占位符原样保留未被翻译过程破坏手动补充signin-passwordless-sms/body.txtSMS 验证码模板生成器不会自动创建通过 templates_test.go 中TestGetRawTemplates的方式校验新 locale 的模板文件是否完整11 个文件见下将新 locale 加入AUTH_LOCALE_ALLOWED_LOCALES运行配置必要时调整AUTH_LOCALE_DEFAULT若需 CLI 内嵌分发同步更新 embed.go 的//go:embed指令。以现有语言为基准一个完整的 locale 目录共需 11 个文件五个 HTML 邮件各含body.htmlsubject.txt10 个外加一个signin-passwordless-sms/body.txt。TestGetRawTemplates的期望清单templates_test.go逐一列出了这 11 个相对路径可以作为新增语言后完整性自检的权威参照。至此你已经掌握了从 React Email 组件源码、生成脚本到 Go 服务端变量注入与 locale 回退的完整链路。无论是为 Nhost Auth 贡献一个新的语言包还是自建一套品牌化的多语言邮件模板都可以基于本仓库的这套工作流快速落地。【免费下载链接】nhostThe Open Source Firebase Alternative with GraphQL.项目地址: https://gitcode.com/GitHub_Trending/nh/nhost创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →