The web framework for content-driven websites. ⭐️ Star to support our work!
OTHER License
Published by astrobot-houston about 1 month ago
#11982 d84e444
Thanks @Princesseuh! - Adds a default exclude and include value to the tsconfig presets. {projectDir}/dist
is now excluded by default, and {projectDir}/.astro/types.d.ts
and {projectDir}/**/*
are included by default.
Both of these options can be overridden by setting your own values to the corresponding settings in your tsconfig.json
file.
#11987 bf90a53
Thanks @florian-lefebvre! - The locals
object can no longer be overridden
Middleware, API endpoints, and pages can no longer override the locals
object in its entirety. You can still append values onto the object, but you can not replace the entire object and delete its existing values.
If you were previously overwriting like so:
ctx.locals = {
one: 1,
two: 2,
};
This can be changed to an assignment on the existing object instead:
Object.assign(ctx.locals, {
one: 1,
two: 2,
});
#11980 a604a0c
Thanks @matthewp! - ViewTransitions component renamed to ClientRouter
The <ViewTransitions />
component has been renamed to <ClientRouter />
. There are no other changes than the name. The old name will continue to work in Astro 5.x, but will be removed in 6.0.
This change was done to clarify the role of the component within Astro's View Transitions support. Astro supports View Transitions APIs in a few different ways, and renaming the component makes it more clear that the features you get from the ClientRouter component are slightly different from what you get using the native CSS-based MPA router.
We still intend to maintain the ClientRouter as before, and it's still important for use-cases that the native support doesn't cover, such as persisting state between pages.
#11987 bf90a53
Thanks @florian-lefebvre! - render()
signature now takes renderOptions
as 2nd argument
The signature for app.render()
has changed, and the second argument is now an options object called renderOptions
with more options for customizing rendering.
The renderOptions
are:
addCookieHeader
: Determines whether Astro will set the Set-Cookie
header, otherwise the adapter is expected to do so itself.clientAddress
: The client IP address used to set Astro.clientAddress
.locals
: An object of locals that's set to Astro.locals
.routeData
: An object specifying the route to use.#11991 d7a396c
Thanks @matthewp! - Update error link to on-demand rendering guide
Published by astrobot-houston about 1 month ago
3e70853
Thanks @florian-lefebvre! - Updates the type from RouteData
to IntegrationRouteData
Published by astrobot-houston about 1 month ago
Published by astrobot-houston about 1 month ago
#11864 ee38b3a
Thanks @ematipico! - ### [changed]: entryPoint
type inside the hook astro:build:ssr
In Astro v4.x, the entryPoint
type was RouteData
.
Astro v5.0 the entryPoint
type is IntegrationRouteData
, which contains a subset of the RouteData
type. The fields isIndex
and fallbackRoutes
were removed.
Update your adapter to change the type of entryPoint
from RouteData
to IntegrationRouteData
.
-import type {RouteData} from 'astro';
+import type {IntegrationRouteData} from "astro"
-function useRoute(route: RouteData) {
+function useRoute(route: IntegrationRouteData) {
}
#11908 518433e
Thanks @Princesseuh! - The image.endpoint
config now allow customizing the route of the image endpoint in addition to the entrypoint. This can be useful in niche situations where the default route /_image
conflicts with an existing route or your local server setup.
import { defineConfig } from 'astro/config';
defineConfig({
image: {
endpoint: {
route: '/image',
entrypoint: './src/image_endpoint.ts',
},
},
});
#11806 f7f2338
Thanks @Princesseuh! - Removes the assets
property on supportedAstroFeatures
for adapters, as it did not reflect reality properly in many cases.
Now, relating to assets, only a single sharpImageService
property is available, determining if the adapter is compatible with the built-in sharp image service.
#11864 ee38b3a
Thanks @ematipico! - ### [changed]: routes
type inside the hook astro:build:done
In Astro v4.x, the routes
type was RouteData
.
Astro v5.0 the routes
type is IntegrationRouteData
, which contains a subset of the RouteData
type. The fields isIndex
and fallbackRoutes
were removed.
Update your adapter to change the type of routes
from RouteData
to IntegrationRouteData
.
-import type {RouteData} from 'astro';
+import type {IntegrationRouteData} from "astro"
-function useRoute(route: RouteData) {
+function useRoute(route: IntegrationRouteData) {
}
#11864 ee38b3a
Thanks @ematipico! - ### [changed]: RouteData.distURL
is now an array
In Astro v4.x, RouteData.distURL
was undefined
or a URL
Astro v5.0, RouteData.distURL
is undefined
or an array of URL
. This was a bug, because a route can generate multiple files on disk, especially when using dynamic routes such as [slug]
or [...slug]
.
Update your code to handle RouteData.distURL
as an array.
if (route.distURL) {
- if (route.distURL.endsWith('index.html')) {
- // do something
- }
+ for (const url of route.distURL) {
+ if (url.endsWith('index.html')) {
+ // do something
+ }
+ }
}
#11806 f7f2338
Thanks @Princesseuh! - The value of the different properties on supportedAstroFeatures
for adapters can now be objects, with a support
and message
properties. The content of the message
property will be shown in the Astro CLI when the adapter is not compatible with the feature, allowing one to give a better informational message to the user.
This is notably useful with the new limited
value, to explain to the user why support is limited.
#11955 d813262
Thanks @matthewp! - Server Islands introduced behind an experimental flag in v4.12.0 is no longer experimental and is available for general use.
Server islands are Astro's solution for highly cacheable pages of mixed static and dynamic content. They allow you to specify components that should run on the server, allowing the rest of the page to be more aggressively cached, or even generated statically.
Turn any .astro
component into a server island by adding the server:defer
directive and optionally, fallback placeholder content. It will be rendered dynamically at runtime outside the context of the rest of the page, allowing you to add longer cache headers for the pages, or even prerender them.
---
import Avatar from '../components/Avatar.astro';
import GenericUser from '../components/GenericUser.astro';
---
<header>
<h1>Page Title</h1>
<div class="header-right">
<Avatar server:defer>
<GenericUser slot="fallback" />
</Avatar>
</div>
</header>
If you were previously using this feature, please remove the experimental flag from your Astro config:
import { defineConfig } from 'astro/config';
export default defineConfig({
experimental {
- serverIslands: true,
},
});
If you have been waiting for stabilization before using server islands, you can now do so.
Please see the server island documentation for more about this feature.
#11806 f7f2338
Thanks @Princesseuh! - Adds a new limited
value for the different properties of supportedAstroFeatures
for adapters, which indicates that the adapter is compatible with the feature, but with some limitations. This is useful for adapters that support a feature, but not in all cases or with all options.
#11925 74722cb
Thanks @florian-lefebvre! - Updates astro/config
import to reference astro/client
types
When importing astro/config
, types from astro/client
will be made automatically available to your project. If your project tsconfig.json
changes how references behave, you'll still have access to these types after running astro sync
.
#11974 60211de
Thanks @ascorbic! - Exports the RenderResult
type
#11939 7b09c62
Thanks @bholmesdev! - Adds support for Zod discriminated unions on Action form inputs. This allows forms with different inputs to be submitted to the same action, using a given input to decide which object should be used for validation.
This example accepts either a create
or update
form submission, and uses the type
field to determine which object to validate against.
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
export const server = {
changeUser: defineAction({
accept: 'form',
input: z.discriminatedUnion('type', [
z.object({
type: z.literal('create'),
name: z.string(),
email: z.string().email(),
}),
z.object({
type: z.literal('update'),
id: z.number(),
name: z.string(),
email: z.string().email(),
}),
]),
async handler(input) {
if (input.type === 'create') {
// input is { type: 'create', name: string, email: string }
} else {
// input is { type: 'update', id: number, name: string, email: string }
}
},
}),
};
The corresponding create
and update
forms may look like this:
---
import { actions } from 'astro:actions';
---
<!--Create-->
<form action={actions.changeUser} method="POST">
<input type="hidden" name="type" value="create" />
<input type="text" name="name" required />
<input type="email" name="email" required />
<button type="submit">Create User</button>
</form>
<!--Update-->
<form action={actions.changeUser} method="POST">
<input type="hidden" name="type" value="update" />
<input type="hidden" name="id" value="user-123" />
<input type="text" name="name" required />
<input type="email" name="email" required />
<button type="submit">Update User</button>
</form>
Published by astrobot-houston about 1 month ago
#11939 7b09c62
Thanks @bholmesdev! - Adds support for Zod discriminated unions on Action form inputs. This allows forms with different inputs to be submitted to the same action, using a given input to decide which object should be used for validation.
This example accepts either a create
or update
form submission, and uses the type
field to determine which object to validate against.
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
export const server = {
changeUser: defineAction({
accept: 'form',
input: z.discriminatedUnion('type', [
z.object({
type: z.literal('create'),
name: z.string(),
email: z.string().email(),
}),
z.object({
type: z.literal('update'),
id: z.number(),
name: z.string(),
email: z.string().email(),
}),
]),
async handler(input) {
if (input.type === 'create') {
// input is { type: 'create', name: string, email: string }
} else {
// input is { type: 'update', id: number, name: string, email: string }
}
},
}),
};
The corresponding create
and update
forms may look like this:
---
import { actions } from 'astro:actions';
---
<!--Create-->
<form action={actions.changeUser} method="POST">
<input type="hidden" name="type" value="create" />
<input type="text" name="name" required />
<input type="email" name="email" required />
<button type="submit">Create User</button>
</form>
<!--Update-->
<form action={actions.changeUser} method="POST">
<input type="hidden" name="type" value="update" />
<input type="hidden" name="id" value="user-123" />
<input type="text" name="name" required />
<input type="email" name="email" required />
<button type="submit">Update User</button>
</form>
#11968 86ad1fd
Thanks @NikolaRHristov! - Fixes a typo in the server island JSDoc
#11983 633eeaa
Thanks @uwej711! - Remove dependency on path-to-regexp
Published by astrobot-houston about 1 month ago
Published by astrobot-houston about 2 months ago
#11941 b6a5f39
Thanks @Princesseuh! - Merges the output: 'hybrid'
and output: 'static'
configurations into one single configuration (now called 'static'
) that works the same way as the previous hybrid
option.
It is no longer necessary to specify output: 'hybrid'
in your Astro config to use server-rendered pages. The new output: 'static'
has this capability included. Astro will now automatically provide the ability to opt out of prerendering in your static site with no change to your output
configuration required. Any page route or endpoint can include export const prerender = false
to be server-rendered, while the rest of your site is statically-generated.
If your project used hybrid rendering, you must now remove the output: 'hybrid'
option from your Astro config as it no longer exists. However, no other changes to your project are required, and you should have no breaking changes. The previous 'hybrid'
behavior is now the default, under a new name 'static'
.
If you were using the output: 'static'
(default) option, you can continue to use it as before. By default, all of your pages will continue to be prerendered and you will have a completely static site. You should have no breaking changes to your project.
import { defineConfig } from "astro/config";
export default defineConfig({
- output: 'hybrid',
});
An adapter is still required to deploy an Astro project with any server-rendered pages. Failure to include an adapter will result in a warning in development and an error at build time.
#11941 b6a5f39
Thanks @Princesseuh! - Adapters can now specify the build output type they're intended for using the adapterFeatures.buildOutput
property. This property can be used to always generate a server output, even if the project doesn't have any server-rendered pages.
{
'astro:config:done': ({ setAdapter, config }) => {
setAdapter({
name: 'my-adapter',
adapterFeatures: {
buildOutput: 'server',
},
});
},
}
If your adapter specifies buildOutput: 'static'
, and the user's project contains server-rendered pages, Astro will warn in development and error at build time. Note that a hybrid output, containing both static and server-rendered pages, is considered to be a server
output, as a server is required to serve the server-rendered pages.
#11941 b6a5f39
Thanks @Princesseuh! - Adds a new buildOutput
property to the astro:config:done
hook returning the build output type.
This can be used to know if the user's project will be built as a static site (HTML files), or a server-rendered site (whose exact output depends on the adapter).
#11960 4410130
Thanks @ascorbic! - Fixes an issue where the refresh context data was not passed correctly to content layer loaders
#11952 50a0146
Thanks @ascorbic! - Adds support for array patterns in the built-in glob()
content collections loader
The glob loader can now accept an array of multiple patterns as well as string patterns. This allows you to more easily combine multiple patterns into a single collection, and also means you can use negative matches to exclude files from the collection.
const probes = defineCollection({
// Load all markdown files in the space-probes directory, except for those that start with "voyager-"
loader: glob({ pattern: ['*.md', '!voyager-*'], base: 'src/data/space-probes' }),
schema: z.object({
name: z.string(),
type: z.enum(['Space Probe', 'Mars Rover', 'Comet Lander']),
launch_date: z.date(),
status: z.enum(['Active', 'Inactive', 'Decommissioned']),
destination: z.string(),
operator: z.string(),
notable_discoveries: z.array(z.string()),
}),
});
Published by astrobot-houston about 2 months ago
#11916 46ea29f
Thanks @bluwy! - Updates how the build.client
and build.server
option values get resolved to match existing documentation. With this fix, the option values will now correctly resolve relative to the outDir
option. So if outDir
is set to ./dist/nested/
, then by default:
build.client
will resolve to <root>/dist/nested/client/
build.server
will resolve to <root>/dist/nested/server/
Previously the values were incorrectly resolved:
build.client
was resolved to <root>/dist/nested/dist/client/
build.server
was resolved to <root>/dist/nested/dist/server/
If you were relying on the previous build paths, make sure that your project code is updated to the new build paths.
#11875 a8a3d2c
Thanks @florian-lefebvre! - Adds a new property isPrerendered
to the globals Astro
and APIContext
. This boolean value represents whether or not the current page is prerendered:
---
// src/pages/index.astro
export const prerender = true;
---
// src/middleware.js
export const onRequest = (ctx, next) => {
console.log(ctx.isPrerendered); // it will log true
return next();
};
#11927 5b4e3ab
Thanks @florian-lefebvre! - Updates the env
configuration reference docs to include a full API reference for envField
.
#11943 fa4671c
Thanks @sarah11918! - Updates error messages that assume content collections are located in src/content/
with more generic language
Published by astrobot-houston about 2 months ago
#11879 bd1d4aa
Thanks @matthewp! - Allow passing a cryptography key via ASTRO_KEY
For Server islands Astro creates a cryptography key in order to hash props for the islands, preventing accidental leakage of secrets.
If you deploy to an environment with rolling updates then there could be multiple instances of your app with different keys, causing potential key mismatches.
To fix this you can now pass the ASTRO_KEY
environment variable to your build in order to reuse the same key.
To generate a key use:
astro create-key
This will print out an environment variable to set like:
ASTRO_KEY=PIAuyPNn2aKU/bviapEuc/nVzdzZPizKNo3OqF/5PmQ=
#11935 c58193a
Thanks @Princesseuh! - Fixes astro add
not using the proper export point when adding certain adapters
Published by astrobot-houston about 2 months ago
7d70ba3
Thanks @florian-lefebvre! - Updates the default Astro config with // @ts-check
if the Typescript preset is strict
or strictest
Published by astrobot-houston about 2 months ago
4a44e82
Thanks @lukasbachlechner! - Preact components no longer throw an error if a property is null.Published by astrobot-houston about 2 months ago
#11902 d63bc50
Thanks @ascorbic! - Fixes case where content layer did not update during clean dev builds on Linux and Windows
#11886 7ff7134
Thanks @matthewp! - Fixes a missing error message when actions throws during astro sync
#11904 ca54e3f
Thanks @wtchnm! - perf(assets): avoid downloading original image when using cache
Published by astrobot-houston about 2 months ago
#11894 cc820c5
Thanks @Fryuni! - Fixes mixed environment variable for app token when using DB commands with libSQL remote.
Updated dependencies []:
Published by astrobot-houston about 2 months ago
#11859 3804711
Thanks @florian-lefebvre! - Changes the default tsconfig.json
with better defaults, and makes src/env.d.ts
optional
Astro's default tsconfig.json
in starter examples has been updated to include generated types and exclude your build output. This means that src/env.d.ts
is only necessary if you have added custom type declarations or if you're not using a tsconfig.json
file.
Additionally, running astro sync
no longer creates, nor updates, src/env.d.ts
as it is not required for type-checking standard Astro projects.
To update your project to Astro's recommended TypeScript settings, please add the following include
and exclude
properties to tsconfig.json
:
{
"extends": "astro/tsconfigs/base",
+ "include": ["**/*", ".astro/types.d.ts"],
+ "exclude": ["dist"]
}
#11911 c3dce83
Thanks @ascorbic! - The Content Layer API introduced behind a flag in 4.14.0 is now stable and ready for use in Astro v5.0.
The new Content Layer API builds upon content collections, taking them beyond local files in src/content/
and allowing you to fetch content from anywhere, including remote APIs. These new collections work alongside your existing content collections, and you can migrate them to the new API at your own pace. There are significant improvements to performance with large collections of local files. For more details, see the Content Layer RFC.
If you previously used this feature, you can now remove the experimental.contentLayer
flag from your Astro config:
// astro.config.mjs
import { defineConfig } from 'astro'
export default defineConfig({
- experimental: {
- contentLayer: true
- }
})
The core of the new Content Layer API is the loader, a function that fetches content from a source and caches it in a local data store. Astro 4.14 ships with built-in glob()
and file()
loaders to handle your local Markdown, MDX, Markdoc, and JSON files:
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const blog = defineCollection({
// The ID is a slug generated from the path of the file relative to `base`
loader: glob({ pattern: '**/*.md', base: './src/data/blog' }),
schema: z.object({
title: z.string(),
description: z.string(),
publishDate: z.coerce.date(),
}),
});
export const collections = { blog };
You can then query using the existing content collections functions, and use a simplified render()
function to display your content:
---
import { getEntry, render } from 'astro:content';
const post = await getEntry('blog', Astro.params.slug);
const { Content } = await render(entry);
---
<Content />
You're not restricted to the built-in loaders – we hope you'll try building your own. You can fetch content from anywhere and return an array of entries:
// src/content/config.ts
const countries = defineCollection({
loader: async () => {
const response = await fetch('https://restcountries.com/v3.1/all');
const data = await response.json();
// Must return an array of entries with an id property,
// or an object with IDs as keys and entries as values
return data.map((country) => ({
id: country.cca3,
...country,
}));
},
// optionally add a schema to validate the data and make it type-safe for users
// schema: z.object...
});
export const collections = { countries };
For more advanced loading logic, you can define an object loader. This allows incremental updates and conditional loading, and gives full access to the data store. It also allows a loader to define its own schema, including generating it dynamically based on the source API. See the the Content Layer API RFC for more details.
Loaders are better when they're shared. You can create a package that exports a loader and publish it to npm, and then anyone can use it on their site. We're excited to see what the community comes up with! To get started, take a look at some examples. Here's how to load content using an RSS/Atom feed loader:
// src/content/config.ts
import { defineCollection } from 'astro:content';
import { feedLoader } from '@ascorbic/feed-loader';
const podcasts = defineCollection({
loader: feedLoader({
url: 'https://feeds.99percentinvisible.org/99percentinvisible',
}),
});
export const collections = { podcasts };
To learn more, see the Content Layer RFC.
#11902 d63bc50
Thanks @ascorbic! - Fixes case where content layer did not update during clean dev builds on Linux and Windows
#11914 b5d827b
Thanks @ascorbic! - Exports types for all LoaderContext
properties from astro/loaders
to make it easier to use them in custom loaders.
The ScopedDataStore
interface (which was previously internal) is renamed to DataStore
, to reflect the fact that it's the only public API for the data store.
Published by astrobot-houston about 2 months ago
#11894 cc820c5
Thanks @Fryuni! - Fixes mixed environment variable for app token when using DB commands with libSQL remote.
Updated dependencies []:
Published by astrobot-houston about 2 months ago
#11861 3ab3b4e
Thanks @bluwy! - Cleans up Astro-specfic metadata attached to vfile.data
in Remark and Rehype plugins. Previously, the metadata was attached in different locations with inconsistent names. The metadata is now renamed as below:
vfile.data.__astroHeadings
-> vfile.data.astro.headings
vfile.data.imagePaths
-> vfile.data.astro.imagePaths
The types of imagePaths
has also been updated from Set<string>
to string[]
. The vfile.data.astro.frontmatter
metadata is left unchanged.
While we don't consider these APIs public, they can be accessed by Remark and Rehype plugins that want to re-use Astro's metadata. If you are using these APIs, make sure to access them in the new locations.
#11825 560ef15
Thanks @bluwy! - Updates internal Shiki rehype plugin to highlight code blocks as hast (using Shiki's codeToHast()
API). This allows a more direct Markdown and MDX processing, and improves the performance when building the project, but may cause issues with existing Shiki transformers.
If you are using Shiki transformers passed to markdown.shikiConfig.transformers
, you must make sure they do not use the postprocess
hook as it no longer runs on code blocks in .md
and .mdx
files. (See the Shiki documentation on transformer hooks for more information).
Code blocks in .mdoc
files and <Code />
component do not use the internal Shiki rehype plugin and are unaffected.
#11819 2bdde80
Thanks @bluwy! - Updates the Astro config loading flow to ignore processing locally-linked dependencies with Vite (e.g. npm link
, in a monorepo, etc). Instead, they will be normally imported by the Node.js runtime the same way as other dependencies from node_modules
.
Previously, Astro would process locally-linked dependencies which were able to use Vite features like TypeScript when imported by the Astro config file.
However, this caused confusion as integration authors may test against a package that worked locally, but not when published. This method also restricts using CJS-only dependencies because Vite requires the code to be ESM. Therefore, Astro's behaviour is now changed to ignore processing any type of dependencies by Vite.
In most cases, make sure your locally-linked dependencies are built to JS before running the Astro project, and the config loading should work as before.
#11878 334948c
Thanks @ascorbic! - Adds a new function refreshContent
to the astro:server:setup
hook that allows integrations to refresh the content layer. This can be used, for example, to register a webhook endpoint during dev, or to open a socket to a CMS to listen for changes.
By default, refreshContent
will refresh all collections. You can optionally pass a loaders
property, which is an array of loader names. If provided, only collections that use those loaders will be refreshed. For example, A CMS integration could use this property to only refresh its own collections.
You can also pass a context
object to the loaders. This can be used to pass arbitrary data, such as the webhook body, or an event from the websocket.
{
name: 'my-integration',
hooks: {
'astro:server:setup': async ({ server, refreshContent }) => {
server.middlewares.use('/_refresh', async (req, res) => {
if(req.method !== 'POST') {
res.statusCode = 405
res.end('Method Not Allowed');
return
}
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', async () => {
try {
const webhookBody = JSON.parse(body);
await refreshContent({
context: { webhookBody },
loaders: ['my-loader']
});
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Content refreshed successfully' }));
} catch (error) {
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Failed to refresh content: ' + error.message }));
}
});
});
}
}
}
Updated dependencies [3ab3b4e
, 560ef15
, 3ab3b4e
]:
Published by astrobot-houston about 2 months ago
#11861 3ab3b4e
Thanks @bluwy! - Cleans up Astro-specfic metadata attached to vfile.data
in Remark and Rehype plugins. Previously, the metadata was attached in different locations with inconsistent names. The metadata is now renamed as below:
vfile.data.__astroHeadings
-> vfile.data.astro.headings
vfile.data.imagePaths
-> vfile.data.astro.imagePaths
The types of imagePaths
has also been updated from Set<string>
to string[]
. The vfile.data.astro.frontmatter
metadata is left unchanged.
While we don't consider these APIs public, they can be accessed by Remark and Rehype plugins that want to re-use Astro's metadata. If you are using these APIs, make sure to access them in the new locations.
#11825 560ef15
Thanks @bluwy! - Updates return object of createShikiHighlighter
as codeToHast
and codeToHtml
to allow generating either the hast or html string directly
#11861 3ab3b4e
Thanks @bluwy! - Removes InvalidAstroDataError
, safelyGetAstroData
, and setVfileFrontmatter
APIs in favour of isFrontmatterValid
Published by astrobot-houston about 2 months ago
Published by astrobot-houston about 2 months ago
Published by astrobot-houston about 2 months ago
#11870 8e5257a
Thanks @ArmandPhilippot! - Fixes typo in documenting the fallbackType
property in i18n routing
#11884 e450704
Thanks @ascorbic! - Correctly handles content layer data where the transformed value does not match the input schema
#11900 80b4a18
Thanks @delucis! - Fixes the user-facing type of the new i18n.routing.fallbackType
option to be optional