Zine
Multilingual Websites
Creating Multilingual Websites
To create a multilingual website, use multilingualWebsite
in your build.zig
, like in the following example.
const std = @import("std");
const zine = @import("zine");
pub fn build(b: *std.Build) !void {
zine.multilingualWebsite(b, .{
.host_url = "https://kristoff.it",
.layouts_dir_path = "layouts",
.assets_dir_path = "assets",
.i18n_dir_path = "i18n",
.localized_variants = &.{
.{
.locale_code = "en-US",
.output_prefix_override = "",
.title = "Loris Cro's Blog",
.content_dir_path = "content/en-US",
},
.{
.locale_code = "it-IT",
.title = "Loris 🤌 Cro's 🤌 Blog",
.content_dir_path = "content/it-IT",
},
},
});
}
Localized variants
Each variant can define the following fields:
locale_code
A language-NATION
string, e.g. en-US
, en-UK
, it-IT
, ja-JP
.
title
Site title for this variant.
content_dir_path
Content directory with localized versions of your content.
host_url_override
(optional)
The default assumption in Zine is that all your localized variants will be deployed on the same host, with each localization made available under a locale_code
prefix:
https://site.com/en-US/about/
https://site.com/it-IT/about/
Some users might want instead to serve each localization from a different hostname:
https://us.site.com/about/
https://it.site.com/about/
Setting host_url_override
for each localized variant will make Zine generate permalinks accordingly.
output_prefix_override
(optional)
This field can be used to override the path prefix for a localized variant. When host_url_override
is set to null, the default prefix for each localized variant is locale_code
. When host_url_override
is set to a non-null value, the default prefix is ""
(empty string).
You can set output_prefix_override
to any string to place a localized variant under an arbitrary prefix. Setting it to an empty string is a good way of creating a "default variant" of the website.
For example by setting ouptput_prefix_override
to empty string in en_US
this is the resulting site layout:
https://site.com/about/
https://site.com/it-IT/about/
Here's a table with more examples:
output prefix override | host url override | resulting url prefix | output prefix |
---|---|---|---|
null | null | /en-US/ | zig-out/en-US/ |
null | "us.site.com" | / | zig-out/en-US/ |
"foo" | null | /foo/ | zig-out/foo/ |
"foo" | "us.site.com" | /foo/ | zig-out/foo/ |
"" | null | / | zig-out/ |
The i18n Directory
When creating a multilingual website, the assumption is that the same layouts and site assets will be reused across all localized variants, while the content folder will vary for each.
NOTE
To have per-variant assets you can both create appropriate subdirectories in your site assets directory and also leverage page-local assets.
Varying the content folder will allow you to create different localizations of your content, but that alone is not enough to provide localizedd versions of your site.
The i18n
directory must contain a Ziggy file for each of your localized variants that will then be made available in order to provide localizations for phrases present in your layouts.
Localized variants and their Ziggy file are matched using the locale_code
field.
$ tree i18n
i18n
├── en-US.ziggy
└── it-IT.ziggy
Each file contains a Ziggy map that can then be accessed from your layouts as $i18n
.
$ cat i18n/it-IT.ziggy
{
"back2top": "Ritorna in cima",
"hello": "Ciao {}!",
}
Normal Scripty builtin functions are perfect for basic access to translations in layouts.
error if phrase is missing
<a href="#top" :text="$i18n.get('back2top')"></a>
default value fallback
<a href="#top" :text="$i18n.getOr('back2top', 'Top')"></a>
render element only if the phrase is present
<div :if="$i18n.get?('back2top')">
<a href="#top" :text="$if"></a>
</div>
format the phrase (fmt is a string function)
<p :text="$i18n.get('hello').fmt($page.author)"></p>
Discovering localizations
To discover other localized variants for the same page, you can use $page.locales()
.
Refer to the SuperHTML Scripty reference to see how to use the resulting value.
Consider the following directory structure:
content
├── en-US
│ ├── about.smd
│ ├── docs
│ │ └── index.smd
│ └── index.smd
└── it-IT
├── about.smd
├── pasta.smd
├── docs.smd
└── index.smd
index.smd
andabout.smd
are both respectively matched with their corresponding variant because they have the same path (i.e.en-US/about.smd
,it-IT/about.smd
).pasta.smd
is not matched with any other page because it has a unique relative path.docs.smd
is not matched with any other page because, even though the resulting url path would be the same asdocs/index.smd
, the content path is different.
That said, it is possible to match any page with any other by setting translation_key
in the Ziggy frontmatter of each page.
This last way of matching pages is meant to be used when URL paths are also localized, for example:
https://site.com/en-US/contact-us/
https://site.com/it-IT/contattaci/
The following frontmatter key must be set in both "contact us" pages:
.translation_key = "contact page"
The translation key can be any string value, as long as it is unique per each localized variant.