@leancodepl/mail-translation 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -0
- package/README.md +248 -0
- package/package.json +27 -0
- package/schema.json +53 -0
- package/src/bin.d.ts +2 -0
- package/src/bin.js +19 -0
- package/src/bin.js.map +1 -0
- package/src/compileMjml.d.ts +13 -0
- package/src/compileMjml.js +29 -0
- package/src/compileMjml.js.map +1 -0
- package/src/config.d.ts +21 -0
- package/src/config.js +35 -0
- package/src/config.js.map +1 -0
- package/src/generate.d.ts +2 -0
- package/src/generate.js +23 -0
- package/src/generate.js.map +1 -0
- package/src/generateConfigSchema.d.ts +1 -0
- package/src/generateConfigSchema.js +17 -0
- package/src/generateConfigSchema.js.map +1 -0
- package/src/generateKratosOutputTemplates.d.ts +9 -0
- package/src/generateKratosOutputTemplates.js +48 -0
- package/src/generateKratosOutputTemplates.js.map +1 -0
- package/src/generateOutputTemplates.d.ts +12 -0
- package/src/generateOutputTemplates.js +18 -0
- package/src/generateOutputTemplates.js.map +1 -0
- package/src/generateRazorOutputTemplates.d.ts +8 -0
- package/src/generateRazorOutputTemplates.js +50 -0
- package/src/generateRazorOutputTemplates.js.map +1 -0
- package/src/index.d.ts +2 -0
- package/src/index.js +6 -0
- package/src/index.js.map +1 -0
- package/src/loadConfig.d.ts +2 -0
- package/src/loadConfig.js +41 -0
- package/src/loadConfig.js.map +1 -0
- package/src/loadTemplates.d.ts +7 -0
- package/src/loadTemplates.js +47 -0
- package/src/loadTemplates.js.map +1 -0
- package/src/loadTranslations.d.ts +7 -0
- package/src/loadTranslations.js +37 -0
- package/src/loadTranslations.js.map +1 -0
- package/src/processTemplate.d.ts +28 -0
- package/src/processTemplate.js +36 -0
- package/src/processTemplate.js.map +1 -0
- package/src/processTranslations.d.ts +6 -0
- package/src/processTranslations.js +31 -0
- package/src/processTranslations.js.map +1 -0
- package/src/saveOutputs.d.ts +5 -0
- package/src/saveOutputs.js +16 -0
- package/src/saveOutputs.js.map +1 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file. See
|
|
4
|
+
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
# [9.2.0](https://github.com/leancodepl/js_corelibrary/compare/v9.1.0...v9.2.0) (2025-07-24)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- add empty lines at the end to test examples
|
|
11
|
+
([a5872b8](https://github.com/leancodepl/js_corelibrary/commit/a5872b8d0059968f9b7a7c09ea77429c3042cac6))
|
|
12
|
+
- add newline at the end of schema.json
|
|
13
|
+
([ef4eb59](https://github.com/leancodepl/js_corelibrary/commit/ef4eb598320c119ff775cd4a99e31c334218aa05))
|
|
14
|
+
- building and publishing mail-translation package
|
|
15
|
+
([88acaa6](https://github.com/leancodepl/js_corelibrary/commit/88acaa6bbe1e08f5a510479411250a9bf5ad9d29))
|
|
16
|
+
- export only processTemplate functionality
|
|
17
|
+
([cf2ab8b](https://github.com/leancodepl/js_corelibrary/commit/cf2ab8bb769d2712b0162772fd8c6e86beecec72))
|
|
18
|
+
- handling no translations and no default language
|
|
19
|
+
([8e64bfd](https://github.com/leancodepl/js_corelibrary/commit/8e64bfdf9ef3226006ffeced47ab4eb0dd30ff66))
|
|
20
|
+
- include all css at rules for razor escaping
|
|
21
|
+
([274ac88](https://github.com/leancodepl/js_corelibrary/commit/274ac88a38245bcd31020adedecf34634a7acca3))
|
|
22
|
+
- include schema.json usage examples in readme
|
|
23
|
+
([2bb9009](https://github.com/leancodepl/js_corelibrary/commit/2bb90093a7f56f424af94dc4e246c430652b30da))
|
|
24
|
+
- including common mjml templates
|
|
25
|
+
([ac4dad0](https://github.com/leancodepl/js_corelibrary/commit/ac4dad018b717654e9756cfd316e2178ab58b4e7))
|
|
26
|
+
- leave only simple interpolations in translations
|
|
27
|
+
([3e57b3f](https://github.com/leancodepl/js_corelibrary/commit/3e57b3f178b00a1e23b4c2645af20f7737b0a191))
|
|
28
|
+
- mail-translation package version
|
|
29
|
+
([2c70fbd](https://github.com/leancodepl/js_corelibrary/commit/2c70fbdadc89ed355840b2c9777efb742b1a989a))
|
|
30
|
+
- remove package.json config reference from readme
|
|
31
|
+
([5f56832](https://github.com/leancodepl/js_corelibrary/commit/5f56832fecf7d333873c56df412c9ca8a00e1ea0))
|
|
32
|
+
- resolving cheerio dependencies
|
|
33
|
+
([c08303f](https://github.com/leancodepl/js_corelibrary/commit/c08303f3eb0dffea1a5ea66be1d3f81305d6849a))
|
|
34
|
+
- simplify generating kratos output
|
|
35
|
+
([bbab869](https://github.com/leancodepl/js_corelibrary/commit/bbab86941dfbc71ab275a716d1fa24a8a1f9e79b))
|
|
36
|
+
- simplify ProcessedTemplate interface
|
|
37
|
+
([d494888](https://github.com/leancodepl/js_corelibrary/commit/d494888b081cd381caef393f832febb95b7cd972))
|
|
38
|
+
- translations template and parsing parameters
|
|
39
|
+
([2dbd6f5](https://github.com/leancodepl/js_corelibrary/commit/2dbd6f531479aa3f28adef953c4d0d0409841b1e))
|
|
40
|
+
|
|
41
|
+
### Features
|
|
42
|
+
|
|
43
|
+
- add better support for yaml configuration files
|
|
44
|
+
([6cf386f](https://github.com/leancodepl/js_corelibrary/commit/6cf386f5a68ae595001024926d8cae8fbe9fb261))
|
|
45
|
+
- add handling plaintext templates
|
|
46
|
+
([93bab30](https://github.com/leancodepl/js_corelibrary/commit/93bab30feef7124b09be57f8f2ce15be1cf0758c))
|
|
47
|
+
- add overriding kratos language variable
|
|
48
|
+
([8d810db](https://github.com/leancodepl/js_corelibrary/commit/8d810dbf2f5cbd21765bd5f7bab8125ee7364bea))
|
|
49
|
+
- escape [@media](https://github.com/media) and [@import](https://github.com/import) statement in razor outputs
|
|
50
|
+
([f960be6](https://github.com/leancodepl/js_corelibrary/commit/f960be6dd395486e97a9aa760919f66395a87c29))
|
|
51
|
+
- export config schema
|
|
52
|
+
([5cdd27c](https://github.com/leancodepl/js_corelibrary/commit/5cdd27cdd44672ca3ecb2f9a857b1bb729eb21a0))
|
|
53
|
+
- generate mails without any translations
|
|
54
|
+
([beb4ad0](https://github.com/leancodepl/js_corelibrary/commit/beb4ad00a4d2cbbbf1104be9dc7ca585ca82a0cf))
|
|
55
|
+
- initial mail translation tool implementation
|
|
56
|
+
([da7f050](https://github.com/leancodepl/js_corelibrary/commit/da7f0501e6696d969d505316b72db215798203a9))
|
|
57
|
+
- move generation logic from bin to generate function
|
|
58
|
+
([c7f1218](https://github.com/leancodepl/js_corelibrary/commit/c7f12186311a88e1b873d1b505c94a81bc39f898))
|
|
59
|
+
- refactor template processing
|
|
60
|
+
([10b226b](https://github.com/leancodepl/js_corelibrary/commit/10b226bebe8bd98bcbaaaf794662d32c1d7c80b4))
|
|
61
|
+
- test processTemplate and fix folders structure
|
|
62
|
+
([50a7c81](https://github.com/leancodepl/js_corelibrary/commit/50a7c81d796a3520c064a09588dd542a86b9b8cf))
|
|
63
|
+
- use ICU format and add passing parameters in mjml templates
|
|
64
|
+
([fe0bd1c](https://github.com/leancodepl/js_corelibrary/commit/fe0bd1cf6d4c74471e9adddbab0141415a257e60))
|
package/README.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# @leancodepl/mail-translation
|
|
2
|
+
|
|
3
|
+
A command-line tool for processing MJML and plaintext email templates with optional internationalization support.
|
|
4
|
+
Compiles MJML templates to HTML and can convert templates with translation placeholders into localized email files for
|
|
5
|
+
Kratos or Razor templating systems.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install -D @leancodepl/mail-translation
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npx @leancodepl/mail-translation
|
|
17
|
+
|
|
18
|
+
# Or with custom config file
|
|
19
|
+
npx @leancodepl/mail-translation --config custom-config.js
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Configuration
|
|
23
|
+
|
|
24
|
+
Mail translation is configured using [lilconfig](https://github.com/antonk52/lilconfig). Valid configuration sources
|
|
25
|
+
include:
|
|
26
|
+
|
|
27
|
+
- `.mail-translationrc.json`, `.mail-translationrc` for JSON format
|
|
28
|
+
- `.mail-translationrc.yaml`, `.mail-translationrc.yml` for YAML format
|
|
29
|
+
- `mail-translation.config.js`, `mail-translation.config.cjs`, `.mail-translationrc.js`, `.mail-translationrc.cjs` for
|
|
30
|
+
JavaScript configuration files
|
|
31
|
+
- Path to JavaScript/JSON/YAML config file passed via optional `--config/-c` parameter
|
|
32
|
+
|
|
33
|
+
### Configuration Options
|
|
34
|
+
|
|
35
|
+
- `mailsPath` (`string`, **required**) - Path to directory containing MJML email templates
|
|
36
|
+
- `outputPath` (`string`, **required**) - Directory where processed templates will be saved
|
|
37
|
+
- `outputMode` (`"kratos" | "razor"`, **required**) - Target templating system format
|
|
38
|
+
- `translationsPath` (`string`, optional) - Path to translation files directory. When omitted, templates are compiled
|
|
39
|
+
without translations
|
|
40
|
+
- `plaintextMailsPath` (`string`, optional) - Path to plaintext templates (defaults to `mailsPath`)
|
|
41
|
+
- `defaultLanguage` (`string`, **required when `translationsPath` is provided**) - Default language code for templates
|
|
42
|
+
with translations
|
|
43
|
+
- `languages` (`string[]`, optional) - Array of language codes to process. When omitted, all languages found in
|
|
44
|
+
translation files are processed
|
|
45
|
+
- `kratosLanguageVariable` (`string`, optional, **Kratos mode only**) - Variable path used for language detection in
|
|
46
|
+
Kratos templates (defaults to `".Identity.traits.lang"`).
|
|
47
|
+
|
|
48
|
+
### JSON Schema
|
|
49
|
+
|
|
50
|
+
The package exports a JSON Schema file (`schema.json`) that can be used for configuration validation and IDE
|
|
51
|
+
autocompletion. For JSON configuration files, add the `$schema` property to get autocompletion and validation. Example:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"$schema": "./node_modules/@leancodepl/mail-translation/schema.json"
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Example Configuration
|
|
60
|
+
|
|
61
|
+
**With translations:**
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"$schema": "./node_modules/@leancodepl/mail-translation/schema.json",
|
|
66
|
+
"translationsPath": "./translations",
|
|
67
|
+
"mailsPath": "./templates/mjml",
|
|
68
|
+
"plaintextMailsPath": "./templates/plaintext",
|
|
69
|
+
"outputPath": "./dist/emails",
|
|
70
|
+
"outputMode": "kratos",
|
|
71
|
+
"defaultLanguage": "en",
|
|
72
|
+
"kratosLanguageVariable": ".Identity.traits.locale", // optional - defaults to .Identity.traits.lang
|
|
73
|
+
"languages": ["en", "pl", "de"] // optional - will auto-detect from translation files
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**MJML compilation only (no translations):**
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"$schema": "./node_modules/@leancodepl/mail-translation/schema.json",
|
|
82
|
+
"mailsPath": "./templates/mjml",
|
|
83
|
+
"outputPath": "./dist/emails",
|
|
84
|
+
"outputMode": "kratos"
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Template Structure
|
|
89
|
+
|
|
90
|
+
### MJML Templates
|
|
91
|
+
|
|
92
|
+
Place MJML files in your `mailsPath` directory:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
templates/
|
|
96
|
+
├── welcome.mjml
|
|
97
|
+
├── password-reset.mjml
|
|
98
|
+
└── components/
|
|
99
|
+
├── header.mjml
|
|
100
|
+
└── footer.mjml
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Translation Files
|
|
104
|
+
|
|
105
|
+
Create JSON translation files in your `translationsPath`:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
translations/
|
|
109
|
+
├── en.json
|
|
110
|
+
├── pl.json
|
|
111
|
+
└── de.json
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Example translation file (`en.json`):
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"welcome_title": "Welcome to our platform!",
|
|
119
|
+
"welcome_greeting": "Hello {name}!",
|
|
120
|
+
"verify_button": "Verify Account",
|
|
121
|
+
"footer_text": "© 2024 Company. All rights reserved."
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Template Syntax
|
|
126
|
+
|
|
127
|
+
Use `((t "key"))` for simple translations:
|
|
128
|
+
|
|
129
|
+
```mjml
|
|
130
|
+
<mj-text>((t "welcome_title"))</mj-text>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Use `((t "key", {...}))` for parameterized translations with JSON objects:
|
|
134
|
+
|
|
135
|
+
```mjml
|
|
136
|
+
<mj-text>((t "welcome_greeting", {"name": "{{ .Identity.traits.first_name }}"}))</mj-text>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Use multiple parameters for complex translations:
|
|
140
|
+
|
|
141
|
+
```mjml
|
|
142
|
+
<mj-text>
|
|
143
|
+
((t "account_info", {"email": "{{ .Identity.traits.email }}", "plan": "{{ .Identity.traits.plan }}"}))
|
|
144
|
+
</mj-text>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Output Modes
|
|
148
|
+
|
|
149
|
+
### Kratos Mode
|
|
150
|
+
|
|
151
|
+
Generates Go template files compatible with Ory Kratos identity management system:
|
|
152
|
+
|
|
153
|
+
**File Structure:**
|
|
154
|
+
|
|
155
|
+
- **Body templates**: `template_name.gotmpl` (e.g., `welcome.gotmpl`)
|
|
156
|
+
- **Plaintext templates**: `template_name.plaintext.gotmpl` (e.g., `welcome.plaintext.gotmpl`)
|
|
157
|
+
- Single file with multiple language template definitions
|
|
158
|
+
|
|
159
|
+
**Template Syntax:**
|
|
160
|
+
|
|
161
|
+
- Uses Go template `{{define "language"}}` blocks for each language
|
|
162
|
+
- Template selection logic at the bottom using Kratos variables
|
|
163
|
+
- Kratos variables available (e.g., `{{ .Identity.traits.email }}`)
|
|
164
|
+
- Language detection via `{{ .Identity.traits.lang }}` by default (configurable via `kratosLanguageVariable`)
|
|
165
|
+
|
|
166
|
+
**Example Output:**
|
|
167
|
+
|
|
168
|
+
```gotmpl
|
|
169
|
+
{{define "en"}}
|
|
170
|
+
<html>
|
|
171
|
+
<body>
|
|
172
|
+
<h1>Welcome to our platform!</h1>
|
|
173
|
+
<p>Hello {{ .Identity.traits.first_name }}!</p>
|
|
174
|
+
<p>Thank you for registering with us.</p>
|
|
175
|
+
<p><strong>Verification Code: {{ .VerificationCode }}</strong></p>
|
|
176
|
+
<p>Account: {{ .Identity.traits.email }}</p>
|
|
177
|
+
</body>
|
|
178
|
+
</html>
|
|
179
|
+
{{end}}
|
|
180
|
+
|
|
181
|
+
{{define "pl"}}
|
|
182
|
+
<html>
|
|
183
|
+
<body>
|
|
184
|
+
<h1>Witamy na naszej platformie!</h1>
|
|
185
|
+
<p>Witaj {{ .Identity.traits.first_name }}!</p>
|
|
186
|
+
<p>Dziękujemy za rejestrację.</p>
|
|
187
|
+
<p><strong>Kod weryfikacyjny: {{ .VerificationCode }}</strong></p>
|
|
188
|
+
<p>Konto: {{ .Identity.traits.email }}</p>
|
|
189
|
+
</body>
|
|
190
|
+
</html>
|
|
191
|
+
{{end}}
|
|
192
|
+
|
|
193
|
+
{{- if eq .Identity.traits.lang "pl" -}}
|
|
194
|
+
{{ template "pl" . }}
|
|
195
|
+
{{- else -}}
|
|
196
|
+
{{ template "en" . }}
|
|
197
|
+
{{- end -}}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Razor Mode
|
|
201
|
+
|
|
202
|
+
Generates C# Razor template files:
|
|
203
|
+
|
|
204
|
+
**File Structure:**
|
|
205
|
+
|
|
206
|
+
- **HTML templates**: `TemplateName.cshtml` (default language), `TemplateName.language.cshtml` (other languages)
|
|
207
|
+
- **Plain text templates**: `TemplateName.txt.cshtml` (default language), `TemplateName.language.txt.cshtml` (other
|
|
208
|
+
languages)
|
|
209
|
+
- Separate files for each language
|
|
210
|
+
|
|
211
|
+
**Template Syntax:**
|
|
212
|
+
|
|
213
|
+
- Uses Razor syntax: `@Model.Property`
|
|
214
|
+
- CSS `@` symbols escaped as `@@` for media queries
|
|
215
|
+
|
|
216
|
+
**Example Output:**
|
|
217
|
+
|
|
218
|
+
Assuming english is the default language, the output will be:
|
|
219
|
+
|
|
220
|
+
English template (`notification.cshtml`):
|
|
221
|
+
|
|
222
|
+
```html
|
|
223
|
+
<html>
|
|
224
|
+
<body>
|
|
225
|
+
<h1>System Notification</h1>
|
|
226
|
+
<p>Dear @Model.User.FullName,</p>
|
|
227
|
+
<p>Your account status has been updated to: @Model.Status as of @Model.UpdateDate.</p>
|
|
228
|
+
<p>Action required: @Model.RequiredAction</p>
|
|
229
|
+
<a href="@Model.ActionUrl">Take Action Now</a>
|
|
230
|
+
<p>Reference: @Model.ReferenceNumber</p>
|
|
231
|
+
</body>
|
|
232
|
+
</html>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Polish template (`notification.pl.cshtml`):
|
|
236
|
+
|
|
237
|
+
```html
|
|
238
|
+
<html>
|
|
239
|
+
<body>
|
|
240
|
+
<h1>Powiadomienie systemowe</h1>
|
|
241
|
+
<p>Szanowny/a @Model.User.FullName,</p>
|
|
242
|
+
<p>Status Twojego konta został zaktualizowany na: @Model.Status z dniem @Model.UpdateDate.</p>
|
|
243
|
+
<p>Wymagane działanie: @Model.RequiredAction</p>
|
|
244
|
+
<a href="@Model.ActionUrl">Wykonaj działanie teraz</a>
|
|
245
|
+
<p>Numer referencyjny: @Model.ReferenceNumber</p>
|
|
246
|
+
</body>
|
|
247
|
+
</html>
|
|
248
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@leancodepl/mail-translation",
|
|
3
|
+
"version": "9.2.0",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"bin": {
|
|
6
|
+
"mail-translation": "src/bin.js"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"intl-messageformat": "^10.7.16",
|
|
10
|
+
"js-beautify": "^1.15.4",
|
|
11
|
+
"lilconfig": "^3.1.3",
|
|
12
|
+
"mjml": "^4.15.3",
|
|
13
|
+
"tslib": "^2.8.1",
|
|
14
|
+
"yaml": "^2.8.0",
|
|
15
|
+
"yargs": "^18.0.0",
|
|
16
|
+
"zod": "^4.0.5"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/js-beautify": "^1.14.3",
|
|
20
|
+
"@types/mjml": "^4.7.4",
|
|
21
|
+
"@types/yaml": "^1.9.7",
|
|
22
|
+
"@types/yargs": "^17.0.33"
|
|
23
|
+
},
|
|
24
|
+
"types": "./src/index.d.ts",
|
|
25
|
+
"main": "./src/index.js",
|
|
26
|
+
"type": "commonjs"
|
|
27
|
+
}
|
package/schema.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "@leancodepl/mail-translation Configuration",
|
|
4
|
+
"description": "Schema for @leancodepl/mail-translation configuration",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"translationsPath": {
|
|
8
|
+
"description": "Path to directory containing translation JSON files. When omitted, templates are compiled without translations. Each JSON file should be named with the language code (e.g., en.json, pl.json).",
|
|
9
|
+
"type": "string"
|
|
10
|
+
},
|
|
11
|
+
"mailsPath": {
|
|
12
|
+
"description": "Path to directory containing MJML email templates. All .mjml files in this directory will be processed.",
|
|
13
|
+
"type": "string"
|
|
14
|
+
},
|
|
15
|
+
"plaintextMailsPath": {
|
|
16
|
+
"description": "Path to directory containing plaintext templates. If not specified, defaults to the same value as mailsPath. Used for generating text-only versions of emails alongside HTML versions.",
|
|
17
|
+
"type": "string"
|
|
18
|
+
},
|
|
19
|
+
"outputPath": {
|
|
20
|
+
"description": "Directory where processed templates will be saved. The tool will create this directory if it doesn't exist.",
|
|
21
|
+
"type": "string"
|
|
22
|
+
},
|
|
23
|
+
"outputMode": {
|
|
24
|
+
"description": "Target templating system format: 'kratos' for Go template files compatible with Ory Kratos, 'razor' for C# Razor template files.",
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": [
|
|
27
|
+
"kratos",
|
|
28
|
+
"razor"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
"defaultLanguage": {
|
|
32
|
+
"description": "Default language code for templates with translations. Required when translationsPath is provided.",
|
|
33
|
+
"type": "string"
|
|
34
|
+
},
|
|
35
|
+
"languages": {
|
|
36
|
+
"description": "Array of language codes to process. When omitted, all languages found in translation files are automatically processed. Use this to limit output to specific languages.",
|
|
37
|
+
"type": "array",
|
|
38
|
+
"items": {
|
|
39
|
+
"type": "string"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"kratosLanguageVariable": {
|
|
43
|
+
"description": "Variable path used for language detection in Kratos templates. Defaults to '.Identity.traits.lang'. This determines how the generated template will access the user's language preference. Only used in Kratos mode.",
|
|
44
|
+
"type": "string"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"required": [
|
|
48
|
+
"mailsPath",
|
|
49
|
+
"outputPath",
|
|
50
|
+
"outputMode"
|
|
51
|
+
],
|
|
52
|
+
"additionalProperties": false
|
|
53
|
+
}
|
package/src/bin.d.ts
ADDED
package/src/bin.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const helpers_1 = require("yargs/helpers");
|
|
6
|
+
const yargs_1 = tslib_1.__importDefault(require("yargs/yargs"));
|
|
7
|
+
const generate_1 = require("./generate");
|
|
8
|
+
const loadConfig_1 = require("./loadConfig");
|
|
9
|
+
const saveOutputs_1 = require("./saveOutputs");
|
|
10
|
+
const argv = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
11
|
+
.option("config", {
|
|
12
|
+
alias: "c",
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Config file location",
|
|
15
|
+
})
|
|
16
|
+
.parseSync();
|
|
17
|
+
const config = (0, loadConfig_1.loadConfig)(argv.config);
|
|
18
|
+
(0, generate_1.generate)(config).then(processedTemplates => (0, saveOutputs_1.saveOutputs)({ processedTemplates, outputPath: config.outputPath }));
|
|
19
|
+
//# sourceMappingURL=bin.js.map
|
package/src/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/bin.ts"],"names":[],"mappings":";;;;AAEA,2CAAuC;AACvC,gEAA+B;AAC/B,yCAAqC;AACrC,6CAAyC;AACzC,+CAA2C;AAE3C,MAAM,IAAI,GAAG,IAAA,eAAK,EAAC,IAAA,iBAAO,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;KACtC,MAAM,CAAC,QAAQ,EAAE;IAChB,KAAK,EAAE,GAAG;IACV,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,sBAAsB;CACpC,CAAC;KACD,SAAS,EAAE,CAAA;AAEd,MAAM,MAAM,GAAG,IAAA,uBAAU,EAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAEtC,IAAA,mBAAQ,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,IAAA,yBAAW,EAAC,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface MjmlParseError {
|
|
2
|
+
line: number;
|
|
3
|
+
message: string;
|
|
4
|
+
tagName: string;
|
|
5
|
+
}
|
|
6
|
+
export interface MjmlCompileResult {
|
|
7
|
+
html: string;
|
|
8
|
+
mjmlParseErrors: MjmlParseError[];
|
|
9
|
+
}
|
|
10
|
+
export declare function compileMjml({ mjmlContent, filePath }: {
|
|
11
|
+
mjmlContent: string;
|
|
12
|
+
filePath: string;
|
|
13
|
+
}): MjmlCompileResult;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.compileMjml = compileMjml;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const js_beautify_1 = require("js-beautify");
|
|
6
|
+
const mjml_1 = tslib_1.__importDefault(require("mjml"));
|
|
7
|
+
function compileMjml({ mjmlContent, filePath }) {
|
|
8
|
+
try {
|
|
9
|
+
const result = (0, mjml_1.default)(mjmlContent, {
|
|
10
|
+
keepComments: false,
|
|
11
|
+
validationLevel: "soft",
|
|
12
|
+
filePath,
|
|
13
|
+
});
|
|
14
|
+
// js-beautify is used to format the HTML as beautify option is deprecated in mjml-core
|
|
15
|
+
const html = (0, js_beautify_1.html)(result.html, {
|
|
16
|
+
indent_size: 2,
|
|
17
|
+
preserve_newlines: true,
|
|
18
|
+
max_preserve_newlines: 1,
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
html,
|
|
22
|
+
mjmlParseErrors: result.errors || [],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
throw new Error(`MJML compilation failed: ${error}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=compileMjml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compileMjml.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/compileMjml.ts"],"names":[],"mappings":";;AAcA,kCAsBC;;AApCD,6CAAkD;AAClD,wDAA4B;AAa5B,SAAgB,WAAW,CAAC,EAAE,WAAW,EAAE,QAAQ,EAA6C;IAC9F,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,cAAS,EAAC,WAAW,EAAE;YACpC,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,MAAM;YACvB,QAAQ;SACT,CAAC,CAAA;QAEF,uFAAuF;QACvF,MAAM,IAAI,GAAG,IAAA,kBAAY,EAAC,MAAM,CAAC,IAAI,EAAE;YACrC,WAAW,EAAE,CAAC;YACd,iBAAiB,EAAE,IAAI;YACvB,qBAAqB,EAAE,CAAC;SACzB,CAAC,CAAA;QAEF,OAAO;YACL,IAAI;YACJ,eAAe,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;SACrC,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,EAAE,CAAC,CAAA;IACtD,CAAC;AACH,CAAC"}
|
package/src/config.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
declare const outputModeSchema: z.ZodEnum<{
|
|
3
|
+
kratos: "kratos";
|
|
4
|
+
razor: "razor";
|
|
5
|
+
}>;
|
|
6
|
+
export type OutputMode = z.infer<typeof outputModeSchema>;
|
|
7
|
+
export declare const mailTranslationConfigSchema: z.ZodObject<{
|
|
8
|
+
translationsPath: z.ZodOptional<z.ZodString>;
|
|
9
|
+
mailsPath: z.ZodString;
|
|
10
|
+
plaintextMailsPath: z.ZodOptional<z.ZodString>;
|
|
11
|
+
outputPath: z.ZodString;
|
|
12
|
+
outputMode: z.ZodEnum<{
|
|
13
|
+
kratos: "kratos";
|
|
14
|
+
razor: "razor";
|
|
15
|
+
}>;
|
|
16
|
+
defaultLanguage: z.ZodOptional<z.ZodString>;
|
|
17
|
+
languages: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
18
|
+
kratosLanguageVariable: z.ZodOptional<z.ZodString>;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
export type MailTranslationConfig = z.infer<typeof mailTranslationConfigSchema>;
|
|
21
|
+
export {};
|
package/src/config.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mailTranslationConfigSchema = void 0;
|
|
4
|
+
const v4_1 = require("zod/v4");
|
|
5
|
+
const outputModeSchema = v4_1.z.enum(["kratos", "razor"]);
|
|
6
|
+
exports.mailTranslationConfigSchema = v4_1.z.object({
|
|
7
|
+
translationsPath: v4_1.z
|
|
8
|
+
.string()
|
|
9
|
+
.optional()
|
|
10
|
+
.describe("Path to directory containing translation JSON files. When omitted, templates are compiled without translations. Each JSON file should be named with the language code (e.g., en.json, pl.json)."),
|
|
11
|
+
mailsPath: v4_1.z
|
|
12
|
+
.string()
|
|
13
|
+
.describe("Path to directory containing MJML email templates. All .mjml files in this directory will be processed."),
|
|
14
|
+
plaintextMailsPath: v4_1.z
|
|
15
|
+
.string()
|
|
16
|
+
.optional()
|
|
17
|
+
.describe("Path to directory containing plaintext templates. If not specified, defaults to the same value as mailsPath. Used for generating text-only versions of emails alongside HTML versions."),
|
|
18
|
+
outputPath: v4_1.z
|
|
19
|
+
.string()
|
|
20
|
+
.describe("Directory where processed templates will be saved. The tool will create this directory if it doesn't exist."),
|
|
21
|
+
outputMode: outputModeSchema.describe("Target templating system format: 'kratos' for Go template files compatible with Ory Kratos, 'razor' for C# Razor template files."),
|
|
22
|
+
defaultLanguage: v4_1.z
|
|
23
|
+
.string()
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("Default language code for templates with translations. Required when translationsPath is provided."),
|
|
26
|
+
languages: v4_1.z
|
|
27
|
+
.array(v4_1.z.string())
|
|
28
|
+
.optional()
|
|
29
|
+
.describe("Array of language codes to process. When omitted, all languages found in translation files are automatically processed. Use this to limit output to specific languages."),
|
|
30
|
+
kratosLanguageVariable: v4_1.z
|
|
31
|
+
.string()
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("Variable path used for language detection in Kratos templates. Defaults to '.Identity.traits.lang'. This determines how the generated template will access the user's language preference. Only used in Kratos mode."),
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/config.ts"],"names":[],"mappings":";;;AAAA,+BAA0B;AAE1B,MAAM,gBAAgB,GAAG,MAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;AAIvC,QAAA,2BAA2B,GAAG,MAAC,CAAC,MAAM,CAAC;IAClD,gBAAgB,EAAE,MAAC;SAChB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,iMAAiM,CAClM;IACH,SAAS,EAAE,MAAC;SACT,MAAM,EAAE;SACR,QAAQ,CACP,yGAAyG,CAC1G;IACH,kBAAkB,EAAE,MAAC;SAClB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,wLAAwL,CACzL;IACH,UAAU,EAAE,MAAC;SACV,MAAM,EAAE;SACR,QAAQ,CACP,6GAA6G,CAC9G;IACH,UAAU,EAAE,gBAAgB,CAAC,QAAQ,CACnC,kIAAkI,CACnI;IACD,eAAe,EAAE,MAAC;SACf,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,oGAAoG,CAAC;IACjH,SAAS,EAAE,MAAC;SACT,KAAK,CAAC,MAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CACP,yKAAyK,CAC1K;IACH,sBAAsB,EAAE,MAAC;SACtB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,sNAAsN,CACvN;CACJ,CAAC,CAAA"}
|
package/src/generate.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generate = generate;
|
|
4
|
+
const loadTemplates_1 = require("./loadTemplates");
|
|
5
|
+
const loadTranslations_1 = require("./loadTranslations");
|
|
6
|
+
const processTemplate_1 = require("./processTemplate");
|
|
7
|
+
async function generate(config) {
|
|
8
|
+
const translationData = await (0, loadTranslations_1.loadTranslations)(config.translationsPath);
|
|
9
|
+
const mjmlTemplates = await (0, loadTemplates_1.loadMjmlTemplates)(config.mailsPath);
|
|
10
|
+
const plaintextTemplates = await (0, loadTemplates_1.loadPlaintextTemplates)({
|
|
11
|
+
plaintextMailsPath: config.plaintextMailsPath ?? config.mailsPath,
|
|
12
|
+
outputMode: config.outputMode,
|
|
13
|
+
});
|
|
14
|
+
return [...mjmlTemplates, ...plaintextTemplates].map(template => (0, processTemplate_1.processTemplate)({
|
|
15
|
+
template,
|
|
16
|
+
translationData,
|
|
17
|
+
outputMode: config.outputMode,
|
|
18
|
+
defaultLanguage: config.defaultLanguage,
|
|
19
|
+
kratosLanguageVariable: config.kratosLanguageVariable,
|
|
20
|
+
mailsPath: config.mailsPath,
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/generate.ts"],"names":[],"mappings":";;AAKA,4BAoBC;AAxBD,mDAA2E;AAC3E,yDAAqD;AACrD,uDAAmD;AAE5C,KAAK,UAAU,QAAQ,CAAC,MAAiD;IAC9E,MAAM,eAAe,GAAG,MAAM,IAAA,mCAAgB,EAAC,MAAM,CAAC,gBAAgB,CAAC,CAAA;IAEvE,MAAM,aAAa,GAAG,MAAM,IAAA,iCAAiB,EAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAC/D,MAAM,kBAAkB,GACtB,MAAM,IAAA,sCAAsB,EAAC;QAC7B,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,IAAI,MAAM,CAAC,SAAS;QACjE,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC,CAAA;IAEF,OAAO,CAAC,GAAG,aAAa,EAAE,GAAG,kBAAkB,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAC9D,IAAA,iCAAe,EAAC;QACd,QAAQ;QACR,eAAe;QACf,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;QACrD,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC,CACH,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const fs_1 = require("fs");
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const v4_1 = require("zod/v4");
|
|
6
|
+
const config_1 = require("./config");
|
|
7
|
+
const jsonSchema = v4_1.z.toJSONSchema(config_1.mailTranslationConfigSchema);
|
|
8
|
+
const output = {
|
|
9
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
10
|
+
title: "@leancodepl/mail-translation Configuration",
|
|
11
|
+
description: "Schema for @leancodepl/mail-translation configuration",
|
|
12
|
+
...jsonSchema,
|
|
13
|
+
};
|
|
14
|
+
const packageRoot = (0, path_1.join)(__dirname, "..");
|
|
15
|
+
const outputPath = (0, path_1.join)(packageRoot, "schema.json");
|
|
16
|
+
(0, fs_1.writeFileSync)(outputPath, JSON.stringify(output, null, 2) + '\n');
|
|
17
|
+
//# sourceMappingURL=generateConfigSchema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateConfigSchema.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/generateConfigSchema.ts"],"names":[],"mappings":";;AAAA,2BAAkC;AAClC,+BAA2B;AAC3B,+BAA0B;AAC1B,qCAAsD;AAEtD,MAAM,UAAU,GAAG,MAAC,CAAC,YAAY,CAAC,oCAA2B,CAAC,CAAA;AAE9D,MAAM,MAAM,GAAG;IACb,OAAO,EAAE,yCAAyC;IAClD,KAAK,EAAE,4CAA4C;IACnD,WAAW,EAAE,uDAAuD;IACpE,GAAG,UAAU;CACd,CAAA;AAED,MAAM,WAAW,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,CAAC,CAAA;AACzC,MAAM,UAAU,GAAG,IAAA,WAAI,EAAC,WAAW,EAAE,aAAa,CAAC,CAAA;AAEnD,IAAA,kBAAa,EAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TranslatedTemplate } from "./processTemplate";
|
|
2
|
+
export declare function generateKratosOutputTemplates({ translatedTemplates, defaultLanguage, kratosLanguageVariable, }: {
|
|
3
|
+
translatedTemplates: TranslatedTemplate[];
|
|
4
|
+
defaultLanguage?: string;
|
|
5
|
+
kratosLanguageVariable?: string;
|
|
6
|
+
}): {
|
|
7
|
+
filename: string;
|
|
8
|
+
content: string;
|
|
9
|
+
}[];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateKratosOutputTemplates = generateKratosOutputTemplates;
|
|
4
|
+
function generateKratosOutputTemplates({ translatedTemplates, defaultLanguage, kratosLanguageVariable, }) {
|
|
5
|
+
const plainTextTemplates = translatedTemplates.filter(template => template.isPlaintext);
|
|
6
|
+
const htmlTemplates = translatedTemplates.filter(template => !template.isPlaintext);
|
|
7
|
+
const htmlOutputTemplates = htmlTemplates.map(template => ({
|
|
8
|
+
filename: `${template.name}.gotmpl`,
|
|
9
|
+
content: generateKratosOutputTemplate({
|
|
10
|
+
templates: htmlTemplates,
|
|
11
|
+
defaultLanguage,
|
|
12
|
+
kratosLanguageVariable,
|
|
13
|
+
}),
|
|
14
|
+
}));
|
|
15
|
+
const plainTextOutputTemplates = plainTextTemplates.map(template => ({
|
|
16
|
+
filename: `${template.name}.plaintext.gotmpl`,
|
|
17
|
+
content: generateKratosOutputTemplate({
|
|
18
|
+
templates: plainTextTemplates,
|
|
19
|
+
defaultLanguage,
|
|
20
|
+
kratosLanguageVariable,
|
|
21
|
+
}),
|
|
22
|
+
}));
|
|
23
|
+
return [...htmlOutputTemplates, ...plainTextOutputTemplates];
|
|
24
|
+
}
|
|
25
|
+
function generateKratosOutputTemplate({ templates, defaultLanguage, kratosLanguageVariable = ".Identity.traits.lang", }) {
|
|
26
|
+
if (templates.length === 1 || !defaultLanguage) {
|
|
27
|
+
return templates[0].content;
|
|
28
|
+
}
|
|
29
|
+
let outputTemplate = "";
|
|
30
|
+
templates.forEach(template => {
|
|
31
|
+
outputTemplate += `{{define "${template.language}"}}\n`;
|
|
32
|
+
outputTemplate += template.content;
|
|
33
|
+
outputTemplate += "\n{{end}}\n\n";
|
|
34
|
+
});
|
|
35
|
+
const nonDefaultLanguages = templates
|
|
36
|
+
.filter(template => template.language !== defaultLanguage)
|
|
37
|
+
.map(template => template.language);
|
|
38
|
+
nonDefaultLanguages.forEach((language, index) => {
|
|
39
|
+
const condition = index === 0 ? "if" : "else if";
|
|
40
|
+
outputTemplate += `{{- ${condition} eq ${kratosLanguageVariable} "${language}" -}}\n`;
|
|
41
|
+
outputTemplate += `{{ template "${language}" . }}\n`;
|
|
42
|
+
});
|
|
43
|
+
outputTemplate += "{{- else -}}\n";
|
|
44
|
+
outputTemplate += `{{ template "${defaultLanguage}" . }}\n`;
|
|
45
|
+
outputTemplate += "{{- end -}}\n";
|
|
46
|
+
return outputTemplate;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=generateKratosOutputTemplates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateKratosOutputTemplates.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/generateKratosOutputTemplates.ts"],"names":[],"mappings":";;AAEA,sEA+BC;AA/BD,SAAgB,6BAA6B,CAAC,EAC5C,mBAAmB,EACnB,eAAe,EACf,sBAAsB,GAKvB;IACC,MAAM,kBAAkB,GAAG,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IACvF,MAAM,aAAa,GAAG,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IAEnF,MAAM,mBAAmB,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACzD,QAAQ,EAAE,GAAG,QAAQ,CAAC,IAAI,SAAS;QACnC,OAAO,EAAE,4BAA4B,CAAC;YACpC,SAAS,EAAE,aAAa;YACxB,eAAe;YACf,sBAAsB;SACvB,CAAC;KACH,CAAC,CAAC,CAAA;IAEH,MAAM,wBAAwB,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACnE,QAAQ,EAAE,GAAG,QAAQ,CAAC,IAAI,mBAAmB;QAC7C,OAAO,EAAE,4BAA4B,CAAC;YACpC,SAAS,EAAE,kBAAkB;YAC7B,eAAe;YACf,sBAAsB;SACvB,CAAC;KACH,CAAC,CAAC,CAAA;IAEH,OAAO,CAAC,GAAG,mBAAmB,EAAE,GAAG,wBAAwB,CAAC,CAAA;AAC9D,CAAC;AAED,SAAS,4BAA4B,CAAC,EACpC,SAAS,EACT,eAAe,EACf,sBAAsB,GAAG,uBAAuB,GAKjD;IACC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;QAC/C,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;IAC7B,CAAC;IAED,IAAI,cAAc,GAAG,EAAE,CAAA;IAEvB,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;QAC3B,cAAc,IAAI,aAAa,QAAQ,CAAC,QAAQ,OAAO,CAAA;QACvD,cAAc,IAAI,QAAQ,CAAC,OAAO,CAAA;QAClC,cAAc,IAAI,eAAe,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,MAAM,mBAAmB,GAAG,SAAS;SAClC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,KAAK,eAAe,CAAC;SACzD,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAErC,mBAAmB,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE;QAC9C,MAAM,SAAS,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;QAEhD,cAAc,IAAI,OAAO,SAAS,OAAO,sBAAsB,KAAK,QAAQ,SAAS,CAAA;QACrF,cAAc,IAAI,gBAAgB,QAAQ,UAAU,CAAA;IACtD,CAAC,CAAC,CAAA;IAEF,cAAc,IAAI,gBAAgB,CAAA;IAClC,cAAc,IAAI,gBAAgB,eAAe,UAAU,CAAA;IAC3D,cAAc,IAAI,eAAe,CAAA;IAEjC,OAAO,cAAc,CAAA;AACvB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { OutputMode } from "./config";
|
|
2
|
+
import { TranslatedTemplate } from "./processTemplate";
|
|
3
|
+
export interface OutputTemplate {
|
|
4
|
+
filename: string;
|
|
5
|
+
content: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function generateOutputTemplates({ translatedTemplates, outputMode, defaultLanguage, kratosLanguageVariable, }: {
|
|
8
|
+
translatedTemplates: TranslatedTemplate[];
|
|
9
|
+
outputMode: OutputMode;
|
|
10
|
+
defaultLanguage?: string;
|
|
11
|
+
kratosLanguageVariable?: string;
|
|
12
|
+
}): OutputTemplate[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateOutputTemplates = generateOutputTemplates;
|
|
4
|
+
const generateKratosOutputTemplates_1 = require("./generateKratosOutputTemplates");
|
|
5
|
+
const generateRazorOutputTemplates_1 = require("./generateRazorOutputTemplates");
|
|
6
|
+
function generateOutputTemplates({ translatedTemplates, outputMode, defaultLanguage, kratosLanguageVariable, }) {
|
|
7
|
+
switch (outputMode) {
|
|
8
|
+
case "kratos":
|
|
9
|
+
return (0, generateKratosOutputTemplates_1.generateKratosOutputTemplates)({
|
|
10
|
+
translatedTemplates,
|
|
11
|
+
defaultLanguage,
|
|
12
|
+
kratosLanguageVariable,
|
|
13
|
+
});
|
|
14
|
+
case "razor":
|
|
15
|
+
return (0, generateRazorOutputTemplates_1.generateRazorOutputTemplates)({ translatedTemplates, defaultLanguage });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=generateOutputTemplates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateOutputTemplates.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/generateOutputTemplates.ts"],"names":[],"mappings":";;AAUA,0DAqBC;AA9BD,mFAA+E;AAC/E,iFAA6E;AAQ7E,SAAgB,uBAAuB,CAAC,EACtC,mBAAmB,EACnB,UAAU,EACV,eAAe,EACf,sBAAsB,GAMvB;IACC,QAAQ,UAAU,EAAE,CAAC;QACnB,KAAK,QAAQ;YACX,OAAO,IAAA,6DAA6B,EAAC;gBACnC,mBAAmB;gBACnB,eAAe;gBACf,sBAAsB;aACvB,CAAC,CAAA;QACJ,KAAK,OAAO;YACV,OAAO,IAAA,2DAA4B,EAAC,EAAE,mBAAmB,EAAE,eAAe,EAAE,CAAC,CAAA;IACjF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TranslatedTemplate } from "./processTemplate";
|
|
2
|
+
export declare function generateRazorOutputTemplates({ translatedTemplates, defaultLanguage, }: {
|
|
3
|
+
translatedTemplates: TranslatedTemplate[];
|
|
4
|
+
defaultLanguage?: string;
|
|
5
|
+
}): {
|
|
6
|
+
filename: string;
|
|
7
|
+
content: string;
|
|
8
|
+
}[];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateRazorOutputTemplates = generateRazorOutputTemplates;
|
|
4
|
+
function generateRazorOutputTemplates({ translatedTemplates, defaultLanguage, }) {
|
|
5
|
+
return translatedTemplates.map(template => ({
|
|
6
|
+
filename: getFilename({ template, defaultLanguage }),
|
|
7
|
+
content: escapeRazorConflicts(template.content),
|
|
8
|
+
}));
|
|
9
|
+
}
|
|
10
|
+
function escapeRazorConflicts(templateContent) {
|
|
11
|
+
const cssAtRules = [
|
|
12
|
+
"annotation",
|
|
13
|
+
"character-variant",
|
|
14
|
+
"charset",
|
|
15
|
+
"color-profile",
|
|
16
|
+
"container",
|
|
17
|
+
"counter-style",
|
|
18
|
+
"font-face",
|
|
19
|
+
"font-feature-values",
|
|
20
|
+
"font-palette-values",
|
|
21
|
+
"import",
|
|
22
|
+
"keyframes",
|
|
23
|
+
"-webkit-keyframes",
|
|
24
|
+
"layer",
|
|
25
|
+
"media",
|
|
26
|
+
"namespace",
|
|
27
|
+
"ornaments",
|
|
28
|
+
"page",
|
|
29
|
+
"position-try",
|
|
30
|
+
"property",
|
|
31
|
+
"scope",
|
|
32
|
+
"starting-style",
|
|
33
|
+
"styleset",
|
|
34
|
+
"stylistic",
|
|
35
|
+
"supports",
|
|
36
|
+
"swash",
|
|
37
|
+
"view-transition",
|
|
38
|
+
].join("|");
|
|
39
|
+
return templateContent.replace(new RegExp(`(?<!@)@(${cssAtRules})`, "g"), "@@$1");
|
|
40
|
+
}
|
|
41
|
+
function getFilename({ template, defaultLanguage, }) {
|
|
42
|
+
const includeLanguage = !!defaultLanguage && !!template.language && template.language !== defaultLanguage;
|
|
43
|
+
return [
|
|
44
|
+
template.name,
|
|
45
|
+
...(includeLanguage ? [template.language] : []),
|
|
46
|
+
...(template.isPlaintext ? ["txt"] : []),
|
|
47
|
+
"cshtml",
|
|
48
|
+
].join(".");
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=generateRazorOutputTemplates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateRazorOutputTemplates.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/generateRazorOutputTemplates.ts"],"names":[],"mappings":";;AAEA,oEAWC;AAXD,SAAgB,4BAA4B,CAAC,EAC3C,mBAAmB,EACnB,eAAe,GAIhB;IACC,OAAO,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC1C,QAAQ,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;QACpD,OAAO,EAAE,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC;KAChD,CAAC,CAAC,CAAA;AACL,CAAC;AAED,SAAS,oBAAoB,CAAC,eAAuB;IACnD,MAAM,UAAU,GAAG;QACjB,YAAY;QACZ,mBAAmB;QACnB,SAAS;QACT,eAAe;QACf,WAAW;QACX,eAAe;QACf,WAAW;QACX,qBAAqB;QACrB,qBAAqB;QACrB,QAAQ;QACR,WAAW;QACX,mBAAmB;QACnB,OAAO;QACP,OAAO;QACP,WAAW;QACX,WAAW;QACX,MAAM;QACN,cAAc;QACd,UAAU;QACV,OAAO;QACP,gBAAgB;QAChB,UAAU;QACV,WAAW;QACX,UAAU;QACV,OAAO;QACP,iBAAiB;KAClB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAEX,OAAO,eAAe,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,WAAW,UAAU,GAAG,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,CAAA;AACnF,CAAC;AAED,SAAS,WAAW,CAAC,EACnB,QAAQ,EACR,eAAe,GAIhB;IACC,MAAM,eAAe,GAAG,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,KAAK,eAAe,CAAA;IAEzG,OAAO;QACL,QAAQ,CAAC,IAAI;QACb,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,QAAQ;KACT,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACb,CAAC"}
|
package/src/index.d.ts
ADDED
package/src/index.js
ADDED
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/index.ts"],"names":[],"mappings":";;;AAAA,qDAA0B;AAC1B,wDAA6B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadConfig = loadConfig;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const lilconfig_1 = require("lilconfig");
|
|
6
|
+
const yaml = tslib_1.__importStar(require("yaml"));
|
|
7
|
+
const config_1 = require("./config");
|
|
8
|
+
function loadYaml(filepath, content) {
|
|
9
|
+
return yaml.parse(content);
|
|
10
|
+
}
|
|
11
|
+
const packageName = "mail-translation";
|
|
12
|
+
const options = {
|
|
13
|
+
searchPlaces: [
|
|
14
|
+
`.${packageName}rc`,
|
|
15
|
+
`.${packageName}rc.json`,
|
|
16
|
+
`.${packageName}rc.yaml`,
|
|
17
|
+
`.${packageName}rc.yml`,
|
|
18
|
+
`.${packageName}rc.js`,
|
|
19
|
+
`.${packageName}rc.cjs`,
|
|
20
|
+
`${packageName}.config.js`,
|
|
21
|
+
`${packageName}.config.cjs`,
|
|
22
|
+
],
|
|
23
|
+
loaders: {
|
|
24
|
+
".yaml": loadYaml,
|
|
25
|
+
".yml": loadYaml,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
function loadConfig(configPath) {
|
|
29
|
+
const searcher = (0, lilconfig_1.lilconfigSync)("mail-translation", options);
|
|
30
|
+
const result = configPath ? searcher.load(configPath) : searcher.search();
|
|
31
|
+
if (!result) {
|
|
32
|
+
throw new Error("No configuration file found");
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
return config_1.mailTranslationConfigSchema.parse(result.config);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
throw new Error(`Failed to load configuration: ${error}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=loadConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadConfig.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/loadConfig.ts"],"names":[],"mappings":";;AA2BA,gCAaC;;AAxCD,yCAA8E;AAC9E,mDAA4B;AAC5B,qCAA6E;AAE7E,SAAS,QAAQ,CAAC,QAAgB,EAAE,OAAe;IACjD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAC5B,CAAC;AAED,MAAM,WAAW,GAAG,kBAAkB,CAAA;AAEtC,MAAM,OAAO,GAAyB;IACpC,YAAY,EAAE;QACZ,IAAI,WAAW,IAAI;QACnB,IAAI,WAAW,SAAS;QACxB,IAAI,WAAW,SAAS;QACxB,IAAI,WAAW,QAAQ;QACvB,IAAI,WAAW,OAAO;QACtB,IAAI,WAAW,QAAQ;QACvB,GAAG,WAAW,YAAY;QAC1B,GAAG,WAAW,aAAa;KAC5B;IACD,OAAO,EAAE;QACP,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE,QAAQ;KACjB;CACF,CAAA;AAED,SAAgB,UAAU,CAAC,UAAmB;IAC5C,MAAM,QAAQ,GAAG,IAAA,yBAAa,EAAC,kBAAkB,EAAE,OAAO,CAAC,CAAA;IAE3D,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAA;IACzE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAChD,CAAC;IAED,IAAI,CAAC;QACH,OAAO,oCAA2B,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACzD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,EAAE,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { OutputMode } from "./config";
|
|
2
|
+
import { Template } from "./processTemplate";
|
|
3
|
+
export declare function loadMjmlTemplates(mailsPath: string): Promise<Template[]>;
|
|
4
|
+
export declare function loadPlaintextTemplates({ plaintextMailsPath, outputMode, }: {
|
|
5
|
+
plaintextMailsPath: string;
|
|
6
|
+
outputMode: OutputMode;
|
|
7
|
+
}): Promise<Template[]>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadMjmlTemplates = loadMjmlTemplates;
|
|
4
|
+
exports.loadPlaintextTemplates = loadPlaintextTemplates;
|
|
5
|
+
const promises_1 = require("fs/promises");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
async function loadMjmlTemplates(mailsPath) {
|
|
8
|
+
try {
|
|
9
|
+
const files = await (0, promises_1.readdir)(mailsPath);
|
|
10
|
+
const mjmlFiles = files.filter(file => (0, path_1.extname)(file) === ".mjml");
|
|
11
|
+
return Promise.all(mjmlFiles.map(async (file) => {
|
|
12
|
+
const templateName = (0, path_1.basename)(file, ".mjml");
|
|
13
|
+
const filePath = (0, path_1.join)(mailsPath, file);
|
|
14
|
+
const content = await (0, promises_1.readFile)(filePath, "utf8");
|
|
15
|
+
return {
|
|
16
|
+
name: templateName,
|
|
17
|
+
content,
|
|
18
|
+
isPlaintext: false,
|
|
19
|
+
};
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
throw new Error(`Failed to load templates: ${error}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function loadPlaintextTemplates({ plaintextMailsPath, outputMode, }) {
|
|
27
|
+
try {
|
|
28
|
+
const files = await (0, promises_1.readdir)(plaintextMailsPath);
|
|
29
|
+
const plaintextFiles = outputMode === "kratos"
|
|
30
|
+
? files.filter(file => file.endsWith(".plaintext.gotmpl"))
|
|
31
|
+
: files.filter(file => file.endsWith(".txt.cshtml"));
|
|
32
|
+
return Promise.all(plaintextFiles.map(async (file) => {
|
|
33
|
+
const templateName = outputMode === "kratos" ? file.replace(/\.plaintext\.gotmpl$/, "") : file.replace(/\.txt\.cshtml$/, "");
|
|
34
|
+
const filePath = (0, path_1.join)(plaintextMailsPath, file);
|
|
35
|
+
const content = await (0, promises_1.readFile)(filePath, "utf8");
|
|
36
|
+
return {
|
|
37
|
+
name: templateName,
|
|
38
|
+
content,
|
|
39
|
+
isPlaintext: true,
|
|
40
|
+
};
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw new Error(`Failed to load plaintext templates: ${error}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=loadTemplates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadTemplates.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/loadTemplates.ts"],"names":[],"mappings":";;AAKA,8CAqBC;AAED,wDAgCC;AA5DD,0CAA+C;AAC/C,+BAA8C;AAIvC,KAAK,UAAU,iBAAiB,CAAC,SAAiB;IACvD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAO,EAAC,SAAS,CAAC,CAAA;QACtC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAA,cAAO,EAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAA;QAEjE,OAAO,OAAO,CAAC,GAAG,CAChB,SAAS,CAAC,GAAG,CAAC,KAAK,EAAC,IAAI,EAAC,EAAE;YACzB,MAAM,YAAY,GAAG,IAAA,eAAQ,EAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAC5C,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,CAAC,CAAA;YACtC,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YAEhD,OAAO;gBACL,IAAI,EAAE,YAAY;gBAClB,OAAO;gBACP,WAAW,EAAE,KAAK;aACnB,CAAA;QACH,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,EAAE,CAAC,CAAA;IACvD,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,sBAAsB,CAAC,EAC3C,kBAAkB,EAClB,UAAU,GAIX;IACC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAO,EAAC,kBAAkB,CAAC,CAAA;QAE/C,MAAM,cAAc,GAClB,UAAU,KAAK,QAAQ;YACrB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;YAC1D,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAA;QAExD,OAAO,OAAO,CAAC,GAAG,CAChB,cAAc,CAAC,GAAG,CAAC,KAAK,EAAC,IAAI,EAAC,EAAE;YAC9B,MAAM,YAAY,GAChB,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAA;YACzG,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,kBAAkB,EAAE,IAAI,CAAC,CAAA;YAC/C,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YAEhD,OAAO;gBACL,IAAI,EAAE,YAAY;gBAClB,OAAO;gBACP,WAAW,EAAE,IAAI;aAClB,CAAA;QACH,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,uCAAuC,KAAK,EAAE,CAAC,CAAA;IACjE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadTranslations = loadTranslations;
|
|
4
|
+
const promises_1 = require("fs/promises");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
async function loadTranslations(translationsPath) {
|
|
7
|
+
const translationData = {};
|
|
8
|
+
if (!translationsPath) {
|
|
9
|
+
return translationData;
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
const files = await (0, promises_1.readdir)(translationsPath);
|
|
13
|
+
const jsonFiles = files.filter(file => (0, path_1.extname)(file) === ".json");
|
|
14
|
+
if (jsonFiles.length === 0) {
|
|
15
|
+
console.warn(`No translation files found in: ${translationsPath}. Continuing without translations.`);
|
|
16
|
+
return translationData;
|
|
17
|
+
}
|
|
18
|
+
for (const file of jsonFiles) {
|
|
19
|
+
const language = (0, path_1.basename)(file, ".json");
|
|
20
|
+
const filePath = (0, path_1.join)(translationsPath, file);
|
|
21
|
+
try {
|
|
22
|
+
const content = await (0, promises_1.readFile)(filePath, "utf8");
|
|
23
|
+
const translations = JSON.parse(content);
|
|
24
|
+
translationData[language] = translations;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.warn(`Failed to load translation file ${file}:`, error);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return translationData;
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.warn(`Failed to load translations: ${error}. Continuing without translations.`);
|
|
34
|
+
return translationData;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=loadTranslations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadTranslations.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/loadTranslations.ts"],"names":[],"mappings":";;AAWA,4CAkCC;AA7CD,0CAA+C;AAC/C,+BAA8C;AAUvC,KAAK,UAAU,gBAAgB,CAAC,gBAAyB;IAC9D,MAAM,eAAe,GAAoB,EAAE,CAAA;IAE3C,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,eAAe,CAAA;IACxB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAO,EAAC,gBAAgB,CAAC,CAAA;QAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAA,cAAO,EAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAA;QAEjE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,kCAAkC,gBAAgB,oCAAoC,CAAC,CAAA;YACpG,OAAO,eAAe,CAAA;QACxB,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAA,eAAQ,EAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YACxC,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,gBAAgB,EAAE,IAAI,CAAC,CAAA;YAE7C,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;gBAChD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;gBACxC,eAAe,CAAC,QAAQ,CAAC,GAAG,YAAY,CAAA;YAC1C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,mCAAmC,IAAI,GAAG,EAAE,KAAK,CAAC,CAAA;YACjE,CAAC;QACH,CAAC;QAED,OAAO,eAAe,CAAA;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,gCAAgC,KAAK,oCAAoC,CAAC,CAAA;QACvF,OAAO,eAAe,CAAA;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { MjmlParseError } from "./compileMjml";
|
|
2
|
+
import { OutputMode } from "./config";
|
|
3
|
+
import { OutputTemplate } from "./generateOutputTemplates";
|
|
4
|
+
import { TranslationData } from "./loadTranslations";
|
|
5
|
+
export interface Template {
|
|
6
|
+
name: string;
|
|
7
|
+
content: string;
|
|
8
|
+
isPlaintext: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface TranslatedTemplate {
|
|
11
|
+
name: string;
|
|
12
|
+
content: string;
|
|
13
|
+
isPlaintext: boolean;
|
|
14
|
+
language?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ProcessedTemplate {
|
|
17
|
+
name: string;
|
|
18
|
+
mjmlParseErrors: MjmlParseError[];
|
|
19
|
+
outputTemplates: OutputTemplate[];
|
|
20
|
+
}
|
|
21
|
+
export declare function processTemplate({ template, translationData, outputMode, defaultLanguage, kratosLanguageVariable, mailsPath, }: {
|
|
22
|
+
template: Template;
|
|
23
|
+
translationData: TranslationData;
|
|
24
|
+
outputMode: OutputMode;
|
|
25
|
+
defaultLanguage?: string;
|
|
26
|
+
kratosLanguageVariable?: string;
|
|
27
|
+
mailsPath: string;
|
|
28
|
+
}): ProcessedTemplate;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processTemplate = processTemplate;
|
|
4
|
+
const compileMjml_1 = require("./compileMjml");
|
|
5
|
+
const generateOutputTemplates_1 = require("./generateOutputTemplates");
|
|
6
|
+
const processTranslations_1 = require("./processTranslations");
|
|
7
|
+
function processTemplate({ template, translationData, outputMode, defaultLanguage, kratosLanguageVariable, mailsPath, }) {
|
|
8
|
+
const availableLanguages = Object.keys(translationData);
|
|
9
|
+
const languagesToProcess = availableLanguages.length > 0 ? availableLanguages : [defaultLanguage];
|
|
10
|
+
const mjmlCompileResult = template.isPlaintext
|
|
11
|
+
? undefined
|
|
12
|
+
: (0, compileMjml_1.compileMjml)({ mjmlContent: template.content, filePath: mailsPath });
|
|
13
|
+
const content = template.isPlaintext ? template.content : (mjmlCompileResult?.html ?? "");
|
|
14
|
+
const translatedTemplates = languagesToProcess.map(language => {
|
|
15
|
+
const translations = language ? (translationData[language] ?? {}) : {};
|
|
16
|
+
const translatedContent = (0, processTranslations_1.processTranslations)({ template: content, translations, language });
|
|
17
|
+
return {
|
|
18
|
+
name: template.name,
|
|
19
|
+
content: translatedContent,
|
|
20
|
+
isPlaintext: template.isPlaintext,
|
|
21
|
+
language,
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
const outputTemplates = (0, generateOutputTemplates_1.generateOutputTemplates)({
|
|
25
|
+
translatedTemplates,
|
|
26
|
+
outputMode,
|
|
27
|
+
defaultLanguage,
|
|
28
|
+
kratosLanguageVariable,
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
name: template.name,
|
|
32
|
+
mjmlParseErrors: mjmlCompileResult?.mjmlParseErrors ?? [],
|
|
33
|
+
outputTemplates,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=processTemplate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processTemplate.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/processTemplate.ts"],"names":[],"mappings":";;AAyBA,0CAiDC;AA1ED,+CAA2D;AAE3D,uEAAmF;AAEnF,+DAA2D;AAqB3D,SAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,eAAe,EACf,UAAU,EACV,eAAe,EACf,sBAAsB,EACtB,SAAS,GAQV;IACC,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IACvD,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;IAEjG,MAAM,iBAAiB,GAAG,QAAQ,CAAC,WAAW;QAC5C,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAA,yBAAW,EAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAA;IAEvE,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,iBAAiB,EAAE,IAAI,IAAI,EAAE,CAAC,CAAA;IAEzF,MAAM,mBAAmB,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;QAC5D,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAEtE,MAAM,iBAAiB,GAAG,IAAA,yCAAmB,EAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAA;QAE5F,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,OAAO,EAAE,iBAAiB;YAC1B,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,QAAQ;SACT,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,MAAM,eAAe,GAAG,IAAA,iDAAuB,EAAC;QAC9C,mBAAmB;QACnB,UAAU;QACV,eAAe;QACf,sBAAsB;KACvB,CAAC,CAAA;IAEF,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,eAAe,EAAE,iBAAiB,EAAE,eAAe,IAAI,EAAE;QACzD,eAAe;KAChB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processTranslations = processTranslations;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const intl_messageformat_1 = tslib_1.__importDefault(require("intl-messageformat"));
|
|
6
|
+
function processTranslations({ template, translations, language, }) {
|
|
7
|
+
const translationRegex = /\(\(t\s+['"]([^'"]+)['"]\s*(?:,\s*(\{.*?\}))?\s*\)\)/g;
|
|
8
|
+
const processedTemplate = template.replace(translationRegex, (match, key, jsonParams) => {
|
|
9
|
+
const translation = translations[key];
|
|
10
|
+
if (!translation || !language) {
|
|
11
|
+
console.warn(`Translation is missing for key "${key}"` + (language ? ` for "${language}" language` : ""));
|
|
12
|
+
return key;
|
|
13
|
+
}
|
|
14
|
+
if (jsonParams && language) {
|
|
15
|
+
try {
|
|
16
|
+
const params = JSON.parse(jsonParams);
|
|
17
|
+
const formatter = new intl_messageformat_1.default(translation, language);
|
|
18
|
+
return formatter.format(params);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
console.warn(`Error parsing JSON parameters or formatting message for key "${key}":`, error);
|
|
22
|
+
return key;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return translation;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return processedTemplate;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=processTranslations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processTranslations.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/processTranslations.ts"],"names":[],"mappings":";;AAGA,kDAkCC;;AArCD,oFAAkD;AAGlD,SAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,YAAY,EACZ,QAAQ,GAKT;IACC,MAAM,gBAAgB,GAAG,uDAAuD,CAAA;IAEhF,MAAM,iBAAiB,GAAG,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE;QACtF,MAAM,WAAW,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;QAErC,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,mCAAmC,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,QAAQ,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACzG,OAAO,GAAG,CAAA;QACZ,CAAC;QAED,IAAI,UAAU,IAAI,QAAQ,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;gBACrC,MAAM,SAAS,GAAG,IAAI,4BAAiB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;gBAC9D,OAAO,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YACjC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,gEAAgE,GAAG,IAAI,EAAE,KAAK,CAAC,CAAA;gBAC5F,OAAO,GAAG,CAAA;YACZ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,WAAW,CAAA;QACpB,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,iBAAiB,CAAA;AAC1B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.saveOutputs = saveOutputs;
|
|
4
|
+
const promises_1 = require("fs/promises");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
async function saveOutputs({ processedTemplates, outputPath, }) {
|
|
7
|
+
await (0, promises_1.mkdir)(outputPath, { recursive: true });
|
|
8
|
+
const outputTemplates = processedTemplates.flatMap(processedTemplate => processedTemplate.outputTemplates);
|
|
9
|
+
await Promise.all(outputTemplates.map(template => (0, promises_1.writeFile)((0, path_1.join)(outputPath, template.filename), template.content, "utf8")));
|
|
10
|
+
for (const processedTemplate of processedTemplates) {
|
|
11
|
+
if (processedTemplate.mjmlParseErrors.length > 0) {
|
|
12
|
+
console.warn(`Errors in ${processedTemplate.name}:`, processedTemplate.mjmlParseErrors);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=saveOutputs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"saveOutputs.js","sourceRoot":"","sources":["../../../../packages/mail-translation/src/saveOutputs.ts"],"names":[],"mappings":";;AAIA,kCAoBC;AAxBD,0CAA8C;AAC9C,+BAA2B;AAGpB,KAAK,UAAU,WAAW,CAAC,EAChC,kBAAkB,EAClB,UAAU,GAIX;IACC,MAAM,IAAA,gBAAK,EAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE5C,MAAM,eAAe,GAAG,kBAAkB,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAA;IAE1G,MAAM,OAAO,CAAC,GAAG,CACf,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAA,oBAAS,EAAC,IAAA,WAAI,EAAC,UAAU,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAC1G,CAAA;IAED,KAAK,MAAM,iBAAiB,IAAI,kBAAkB,EAAE,CAAC;QACnD,IAAI,iBAAiB,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,aAAa,iBAAiB,CAAC,IAAI,GAAG,EAAE,iBAAiB,CAAC,eAAe,CAAC,CAAA;QACzF,CAAC;IACH,CAAC;AACH,CAAC"}
|