Skip to content

Commit

Permalink
Add support for parsing error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
brawaru committed Oct 10, 2023
1 parent 2b5a59b commit 81c23b0
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 499 deletions.
11 changes: 11 additions & 0 deletions .changeset/happy-birds-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@vintl/nuxt': minor
---

Support for parsing error handling

`@vintl/nuxt` can now handle errors when parsing message files containing broken messages in a configurable manner.

You can configure how errors are handled using `onParseError` module option, which can either be a name of the built-in strategy, or a function that takes in context and optionally provides fallback message AST.

Check out documentation for more information.
21 changes: 21 additions & 0 deletions apps/docs/content/1.introduction/1.configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Represents the VIntl module options.
| `hostLanguageParam` | `'hl'` | **Deprecated.** An optional name of the query parameter used to override the user language (including automatically detected one). It is used to generate SEO meta tags. Using `null` will disable them. |
| `parserless` | `<...>` | An optional [`ParserlessOptions`] object or [`ParserlessMode`] which configures the parserless mode. |
| `seo` | `<...>` | An optional [`SEOOptions`] object which configures automatic head tags to improve discoverability of other languages by search engines. |
| `onParseError` | | An optional [`ParsingErrorHandlingOption`] value that defines how to handle errors that occur when transforming message files. If not defined, the errors are not handled and thrown during the building, preventing it from succeeding. |

[`BroadcastChannel`]: https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel
[`ParserlessOptions`]: #parserlessoptions
Expand Down Expand Up @@ -161,3 +162,23 @@ By default VIntl will add `<link>` tags for every language to make search engine
| `baseURL` | | **Recommended.** An optional string value representing the base URL of the site. If not set, VIntl will try to guess the URL based on inital request URL or the current `window.location`. |
| `defaultLocaleHasParameter` | `true` | A boolean value representing whether the default locale should have a host language parameter. Disabling this may make URLs of visitors cleaner, however it is not correct, because lack of host language instructs VIntl to use user's language (either the one they've used before or browser's one). |
| `xDefaultHreflang` | `true` | A boolean value representing whether the `x-default` hreflang is present. |

## `ParsingErrorHandlingOption`

[`ParsingErrorHandlingOption`]: #parsingerrorhandlingoption

Represents a value for the message pasing error handling option.

It can be one of the following:

- A string containing a name of the strategy for handling the errors. The following strategies are available:

| Name | Strategy |
| :----------------------- | :-------------------------------------------------------------------------------- |
| `use-message-as-literal` | Use the raw message contents as a literal. |
| `use-id-as-literal` | Use the message ID as a literal. |
| `use-empty-literal` | Use empty string as a literal. |
| `log-and-skip` | Log the error to console and don't include the message into the transformed file. |
| `skip` | Skip including the message into the transformed file. |

- An function that takes in a context for the error (that includes error itself) and optionally returns a fallback AST (not returning anything skips including the message into the transformed file).
3 changes: 3 additions & 0 deletions apps/playground/locales/en-US.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"broken-message": {
"message": "This is {broken, }"
},
"example": {
"message": "Example"
},
Expand Down
1 change: 1 addition & 0 deletions apps/playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ export default defineNuxtConfig({
xDefaultHreflang: false,
defaultLocaleHasParameter: false,
},
onParseError: 'log-and-skip',
},
})
4 changes: 4 additions & 0 deletions apps/playground/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ const messages = defineMessages({
id: 'index.use-automatic',
defaultMessage: 'Use automatic',
},
brokenMessage: {
id: 'broken-message',
defaultMessage: 'This is {broken, }'
},
} as const)
const vintl = useVIntl()
Expand Down
2 changes: 1 addition & 1 deletion packages/vintl-nuxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"@formatjs/intl": "^2.9.3",
"@formatjs/intl-localematcher": "^0.4.2",
"@nuxt/kit": "^3.7.4",
"@vintl/unplugin": "^1.3.0",
"@vintl/unplugin": "^1.4.1",
"@vintl/vintl": "^4.2.3",
"astring": "^1.8.6",
"consola": "^3.2.3",
Expand Down
21 changes: 21 additions & 0 deletions packages/vintl-nuxt/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,31 @@ export default defineNuxtModule<ModuleOptions>({

const { icuMessages } = await import('@vintl/unplugin')

const onParseError = (() => {
let { onParseError } = options

if (onParseError === 'log-and-skip') {
onParseError = (ctx) => {
consola.warn(
`[vintl] Cannot parse the message "${
ctx.messageId
}" in "${relativizePath(
nuxt.options.srcDir,
ctx.moduleId,
)}". It will me skipped.`,
)
}
}

return onParseError
})()

extendWebpackConfig((cfg) => {
const plugins = (cfg.plugins ??= [])
plugins.push(
...pluginOptionsBank
.createOptions({
onParseError,
output: {
type: parserlessModeEnabled ? 'ast' : 'raw',
},
Expand All @@ -143,6 +163,7 @@ export default defineNuxtModule<ModuleOptions>({
...pluginOptionsBank
.createOptions({
pluginsWrapping: true,
onParseError,
output: {
type: parserlessModeEnabled ? 'ast' : 'raw',
},
Expand Down
29 changes: 29 additions & 0 deletions packages/vintl-nuxt/src/schemas/module-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@ import { tSwitch } from '../utils/zod-utils.js'
import { languageTagSchema } from './language-tag.js'
import { localeDescriptorSchema } from './locales.js'
import { seoOptions } from './seo.js'
import type { ParseErrorHandler } from '@vintl/unplugin'

const parseErrorHandingStrategy = t.union([
t.literal('use-message-as-literal'),
t.literal('use-id-as-literal'),
t.literal('use-empty-literal'),
t.literal('log-and-skip'),
t.literal('skip'),
])

const parseErrorHandler = t.custom<ParseErrorHandler>(
(value) => typeof value === 'function',
)

export const parseErrorHandling = tSwitch((input) => {
if (typeof input === 'function') {
return parseErrorHandler
} else if (typeof input === 'string') {
return parseErrorHandingStrategy
}
})

const parselessModeEnumSchema = t.enum(['always', 'only-prod', 'never'])

Expand Down Expand Up @@ -200,6 +221,14 @@ export const moduleOptionsSchema = t
return parselessOptionsSchema
}
}).default('only-prod'),

/**
* Either a literal name of the strategy or a function that handles the
* errors that occur during the parsing of one of the imported files.
*
* @see https://github.com/vintl-dev/unplugin/blob/df9b3be9c77f78eaf5fe7f8d6fde1655f2bc79e1/README.md#onparseerror
*/
onParseError: parseErrorHandling.optional(),
})
.transform((from) => {
if (from.seo === undefined) {
Expand Down
Loading

0 comments on commit 81c23b0

Please sign in to comment.