Languages
Teddy Version: LatestCreating and accessing localised metadata.
Site Languages
For the purposes of this guide, we will hereafter refer to your site directory, for example $TEDDY_BASE/sites/travelbook, as $SITE_BASE. As described in the site configuration guide, an array of language codes representing the languages that are supported by your site must be defined in site.languages.enabled in your $SITE_BASE/site.json site configuration file. The first language specified in this array, for example 'en' (English), is considered the default language for your site. For every language specified in this array, a language directory named with the same language code must exist in $SITE_BASE/languages, for example $SITE_BASE/languages/en. Within each language directory will exist localised metadata that can be easily accessed by both your site pages and your theme templates.
Localised Site Metadata
The following localised JSON-based metadata files must exist as a minimum in each language directory.
metadata.json
The $SITE_BASE/languages/{language}/metadata.json file contains the language-specific common metadata for your site, including the site title, description and comma-delimited keywords. For example, the English language version of the demo TravelBook site contains the following common metadata in $TEDDY_BASE/sites/travelbook/languages/en/metadata.json.
{
"metadata": {
"applicationName": "TravelBook",
"author": "Jillur Quddus",
"description": "Around the world with Teddy.",
"keywords": "africa, america, asia, australia, europe, holiday, flying, travel",
"title": "TravelBook"
}
}
contributors.json
The $SITE_BASE/languages/{language}/contributors.json file contains the language-specific metadata associated with the primary contributors to your site, including contributor ID, name and profile URL. Each contributor should be defined in their own JSON object with the schema authorId: { name: string, url: string, role: string, description: string, avatar: string }, where url, role, description and avatar (URL to an avatar image of the author) are all optional. For example, the English language version of the demo TravelBook site contains the following contributor metadata in $TEDDY_BASE/sites/travelbook/languages/en/contributors.json.
{
"contributors": {
"default": "teddy",
"teddy": {
"name": "Teddy",
"url": "https://demo.teddyful.com/about"
}
}
}
taxonomy.json
If site.languages.enabled is set to true in the site configuration, and site.collection.taxonomy.categories is a non-empty array, then the $SITE_BASE/languages/{language}/taxonomy.json file must exist and must contain language-specific translations of the category keys defined in the site.collection.taxonomy.categories array. For example, the demo TravelBook site defines the following collection category keys in $TEDDY_BASE/sites/travelbook/site.json:
"collection": {
"enabled": true,
"pagesDir": "blog",
...
"taxonomy": {
"categories": [
"africa",
"asia",
"australia",
"europe",
"north-america",
"south-america"
]
},
...
}
Consequently, the English language version of the demo TravelBook site contains the following taxonomy metadata in $TEDDY_BASE/sites/travelbook/languages/en/taxonomy.json.
{
"taxonomy": {
"categories": {
"africa": "Africa",
"asia": "Asia",
"australia": "Australia",
"europe": "Europe",
"north-america": "North America",
"south-america": "South America"
}
}
}
Additional Metadata
In addition to the mandatory localised metadata files described above, you may create an arbitrary number of other localised metadata files, using arbitrary JSON schema, based on your site content requirements and the nature of your theme templates. For example, the English language version of the demo TravelBook site contains the following additional localised metadata files in $TEDDY_BASE/sites/travelbook/languages/en.
content.json
This localised metadata file contains translations of common labels and text shared across multiple pages in the demo TravelBook site, as follows.
{
"content": {
"labels": {
"categories": "Categories",
"continueReading": "Continue Reading",
"languages": "Languages",
"loadMore": "Load More",
"notification": "No results found. Please try again.",
"recent": "Recent Articles",
"reset": "Reset Filters",
"search": "Search",
"searchPlaceholder": "Type and hit enter..."
},
"messages": {
"filters": {
"search": {
"results": "Found ${searchResults.length} posts containing the phrase '${searchQuery}'.",
"invalid": "Invalid search query - please try again."
},
"categories": {
"results": "Found ${searchResults.length} posts in the category '${category.name}'."
},
"combined": {
"results": "Found ${searchResults.length} posts containing the phrase '${searchQuery}' in the category '${category.name}'."
}
}
}
}
}
menu.json
This localised metadata file contains translations of the main menu and footer menu items common to all pages across the demo TravelBook site, as follows.
{
"menus": {
"main": [
{
"name": "Home",
"url": "${pages.urls.home}"
},
{
"name": "About",
"url": "${pages.urls.about}"
},
{
"name": "Blog",
"url": "${pages.urls.blog}"
}
],
"footer": {
"quickLinks": {
"title": "Quick Links",
"links": [
{
"name": "Home",
"url": "${pages.urls.home}"
},
{
"name": "About",
"url": "${pages.urls.about}"
},
{
"name": "Blog",
"url": "${pages.urls.blog}"
}
]
},
"socialLinks": {
"title": "Social Links",
"links": [
{
"name": "Facebook",
"url": "{{{ urls.external.facebook }}}"
},
{
"name": "GitHub",
"url": "{{{ urls.external.github }}}"
},
{
"name": "Instagram",
"url": "{{{ urls.external.instagram }}}"
},
{
"name": "Twitter",
"url": "{{{ urls.external.twitter }}}"
}
]
}
},
"languages": [
{
"name": "English",
"url": "/en"
},
{
"name": "Japanese 日本語",
"url": "/ja"
},
{
"name": "Chinese 中文",
"url": "/zh-tw"
}
]
}
}
Aggregated Localised Site Metadata
During the build of your static site, all the localised JSON-based metadata files are aggregated together, per language. The aggregated localised metadata is then merged with both localised URLs from the site.urls namespace defined in the site.json site configuration file, and localised collection metadata including page metadata from the first N language-specific pages in the collection (where N is the specified pagination size defined in site.collection.pagination.size), the collection size and unique page counts per category. The final aggregated localised metadata is then written to $SITE_BASE/build/{env}/{site.version}/languages/{language}.json. For example, the English language version of the demo TravelBook site will generate the following aggregated localised JSON-based metadata file in $TEDDY_BASE/sites/travelbook/build/{env}/{site.version}/languages/en.json during the build. As described in the build guide, the contents of the $SITE_BASE/build directory are automatically deleted by default at the end of each build. To prevent this directory from being emptied, please provide the --skip-post-build-cleanup command line argument to the build command. Please read the build guide for further details.
{
"content": {
"labels": {
"categories": "Categories",
"continueReading": "Continue Reading",
"languages": "Languages",
"loadMore": "Load More",
"notification": "No results found. Please try again.",
"recent": "Recent Articles",
"reset": "Reset Filters",
"search": "Search",
"searchPlaceholder": "Type and hit enter..."
},
"messages": {
"filters": {
"search": {
"results": "Found ${searchResults.length} posts containing the phrase '${searchQuery}'.",
"invalid": "Invalid search query - please try again."
},
"categories": {
"results": "Found ${searchResults.length} posts in the category '${category.name}'."
},
"combined": {
"results": "Found ${searchResults.length} posts containing the phrase '${searchQuery}' in the category '${category.name}'."
}
}
}
},
"contributors": {
"default": "teddy",
"teddy": {
"name": "Teddy",
"url": "${pages.urls.about}"
}
},
"menus": {
"main": [
{
"name": "Home",
"url": "${pages.urls.home}"
},
{
"name": "About",
"url": "${pages.urls.about}"
},
{
"name": "Blog",
"url": "${pages.urls.blog}"
}
],
"footer": {
"quickLinks": {
"title": "Quick Links",
"links": [
{
"name": "Home",
"url": "${pages.urls.home}"
},
{
"name": "About",
"url": "${pages.urls.about}"
},
{
"name": "Blog",
"url": "${pages.urls.blog}"
}
]
},
"socialLinks": {
"title": "Social Links",
"links": [
{
"name": "Facebook",
"url": "{{{ urls.external.facebook }}}"
},
{
"name": "GitHub",
"url": "{{{ urls.external.github }}}"
},
{
"name": "Instagram",
"url": "{{{ urls.external.instagram }}}"
},
{
"name": "Twitter",
"url": "{{{ urls.external.twitter }}}"
}
]
}
},
"languages": [
{
"name": "English",
"url": "/en"
},
{
"name": "Japanese 日本語",
"url": "/ja"
},
{
"name": "Chinese 中文",
"url": "/zh-tw"
}
]
},
"metadata": {
"applicationName": "TravelBook",
"author": "Jillur Quddus",
"description": "Around the world with Teddy.",
"keywords": "africa, america, asia, australia, europe, holiday, flying, travel",
"title": "TravelBook"
},
"taxonomy": {
"categories": {
"africa": "Africa",
"asia": "Asia",
"australia": "Australia",
"europe": "Europe",
"north-america": "North America",
"south-america": "South America"
}
},
"urls": {
"external": {
"facebook": "https://www.facebook.com",
"github": "https://github.com",
"instagram": "https://www.instagram.com",
"themefisher": "https://github.com/themefisher/logbook-bootstrap",
"twitter": "https://x.com"
},
"assets": "/assets/0.0.1"
},
"collection": {
"metadata": {
"size": 15,
"pagination": {
"size": 10
},
"sort": {
"key": "date",
"order": "desc"
},
"pages": {
"head": [
{
"id": 0,
"name": "Serengeti National Park",
"description": "Tanzania is an East African country known for its vast wilderness areas. They include the plains of Serengeti National Park, a safari mecca populated by the 'big five' game (elephant, lion, leopard, buffalo, rhino), and Kilimanjaro National Park, home to Africa’s highest mountain. Offshore lie the tropical islands of Zanzibar, with Arabic influences, and Mafia, with a marine park home to whale sharks and coral reefs.",
"categoryLanguages": [
{
"id": "africa",
"name": "Africa"
}
],
"tags": [
"africa",
"serengeti",
"safari",
"Kilimanjaro",
"Zanzibar"
],
"date": "2025-03-04T12:00:00.000Z",
"displayDate": "4 March 2025",
"relUrl": "africa/tanzania",
"coverExists": true,
"cover": "assets/serengeti.jpg",
"author": "Teddy",
"authorUrl": "/about",
"content": "Lorem ipsum dolor sit amet consectetur..."
},
{
"id": 1,
"name": "Namib Desert",
"description": "Namibia, a country in southwest Africa, is distinguished by the Namib Desert along its Atlantic Ocean coast. The country is home to diverse wildlife, including a significant cheetah population. The capital, Windhoek, and coastal town Swakopmund contain German colonial-era buildings such as Windhoek's Christuskirche, built in 1907. In the north, Etosha National Park’s salt pan draws game including rhinos and giraffes.",
"categoryLanguages": [
{
"id": "africa",
"name": "Africa"
}
],
"tags": [
"africa",
"cheetah",
"Windhoek",
"Swakopmund",
"salt"
],
"date": "2025-03-03T12:00:00.000Z",
"displayDate": "3 March 2025",
"relUrl": "africa/namibia",
"coverExists": true,
"cover": "assets/desert.jpg",
"author": "Teddy",
"authorUrl": "/about",
"content": "Lorem ipsum dolor sit amet consectetur..."
},
{
"id": 2,
"name": "Mosi-oa-Tunya",
"description": "Zambia, in southern Africa, is a landlocked country of rugged terrain and diverse wildlife, with many parks and safari areas. On its border with Zimbabwe is famed Victoria Falls – indigenously called Mosi-oa-Tunya, or 'Smoke That Thunders' – plunging a misty 108m into narrow Batoka Gorge. Spanning the Zambezi River just below the falls is Victoria Falls Bridge, a spectacular viewpoint.",
"categoryLanguages": [
{
"id": "africa",
"name": "Africa"
}
],
"tags": [
"africa",
"Zambezi",
"Victoria",
"Mosi-oa-Tunya",
"Batoka"
],
"date": "2025-03-02T12:00:00.000Z",
"displayDate": "2 March 2025",
"relUrl": "africa/zambia",
"coverExists": true,
"cover": "assets/victoria-falls.jpg",
"author": "Teddy",
"authorUrl": "/about",
"content": "Lorem ipsum dolor sit amet consectetur..."
},
{
"id": 3,
"name": "Savannah Grasslands",
"description": "Kenya is a country in East Africa with coastline on the Indian Ocean. It encompasses savannah, lakelands, the dramatic Great Rift Valley and mountain highlands. It is also home to wildlife like lions, elephants and rhinos. From Nairobi, the capital, safaris visit the Maasai Mara Reserve, known for its annual wildebeest migrations, and Amboseli National Park, offering views of Tanzania's 5,895m Mt. Kilimanjaro.",
"categoryLanguages": [
{
"id": "africa",
"name": "Africa"
}
],
"tags": [
"africa",
"savannah",
"lakelands",
"lion",
"elephant"
],
"date": "2025-03-01T12:00:00.000Z",
"displayDate": "1 March 2025",
"relUrl": "africa/kenya",
"coverExists": true,
"cover": "assets/savannah.jpg",
"author": "Teddy",
"authorUrl": "/about",
"content": "Lorem ipsum dolor sit amet consectetur..."
},
{
"id": 4,
"name": "Kyoto Temples",
"description": "Japan is an island country in East Asia. Located in the Pacific Ocean off the northeast coast of the Asian mainland, it is bordered on the west by the Sea of Japan and extends from the Sea of Okhotsk in the north to the East China Sea in the south.",
"categoryLanguages": [
{
"id": "asia",
"name": "Asia"
}
],
"tags": [
"asia",
"sushi",
"samurai",
"hokkaido",
"kyushu",
"honshu",
"anime",
"kyoto",
"temple",
"fuji",
"onsen",
"kanji"
],
"date": "2025-02-04T12:00:00.000Z",
"displayDate": "4 February 2025",
"relUrl": "asia/japan",
"coverExists": true,
"cover": "assets/kyoto.jpg",
"author": "Teddy",
"authorUrl": "/about",
"content": "Lorem ipsum dolor sit amet consectetur..."
},
{
"id": 5,
"name": "Bustling Hong Kong",
"description": "Hong Kong is a special administrative region of China. With 7.4 million residents of various nationalities in a 1,104-square-kilometre territory, Hong Kong is the fourth most densely populated region in the world.",
"categoryLanguages": [
{
"id": "asia",
"name": "Asia"
}
],
"tags": [
"asia",
"china",
"sar"
],
"date": "2025-02-03T12:00:00.000Z",
"displayDate": "3 February 2025",
"relUrl": "asia/hong-kong",
"coverExists": true,
"cover": "assets/hk.jpg",
"author": "Teddy",
"authorUrl": "/about",
"content": "Lorem ipsum dolor sit amet consectetur..."
},
{
"id": 6,
"name": "Kuala Lumpur",
"description": "Malaysia is a Southeast Asian country occupying parts of the Malay Peninsula and the island of Borneo. It's known for its beaches, rainforests and mix of Malay, Chinese, Indian and European cultural influences. The capital, Kuala Lumpur, is home to colonial buildings, busy shopping districts such as Bukit Bintang and skyscrapers such as the iconic, 451m-tall Petronas Twin Towers.",
"categoryLanguages": [
{
"id": "asia",
"name": "Asia"
}
],
"tags": [
"asia",
"petronas",
"malay",
"borneo"
],
"date": "2025-02-02T12:00:00.000Z",
"displayDate": "2 February 2025",
"relUrl": "asia/malaysia",
"coverExists": true,
"cover": "assets/kuala-lumpur.jpg",
"author": "Teddy",
"authorUrl": "/about",
"content": "Lorem ipsum dolor sit amet consectetur..."
},
{
"id": 7,
"name": "Sizzling Singapore",
"description": "Singapore, officially the Republic of Singapore, is an island country and city-state in Southeast Asia. The country's territory comprises one main island, 63 satellite islands and islets, and one outlying islet.",
"categoryLanguages": [
{
"id": "asia",
"name": "Asia"
}
],
"tags": [
"asia",
"strait",
"republic",
"island"
],
"date": "2025-02-01T12:00:00.000Z",
"displayDate": "1 February 2025",
"relUrl": "asia/singapore",
"coverExists": true,
"cover": "assets/singapore.jpg",
"author": "Teddy",
"authorUrl": "/about",
"content": "Lorem ipsum dolor sit amet consectetur..."
},
{
"id": 8,
"name": "Hobbiton",
"description": "New Zealand is an island country in the southwestern Pacific Ocean. It consists of two main landmasses—the North Island and the South Island —and over 700 smaller islands.",
"categoryLanguages": [
{
"id": "australia",
"name": "Australia"
}
],
"tags": [
"australia",
"lotr",
"hobbits",
"wellington",
"auckland"
],
"date": "2025-01-01T12:00:00.000Z",
"displayDate": "1 January 2025",
"relUrl": "australia/new-zealand",
"coverExists": true,
"cover": "assets/hobbiton.jpg",
"author": "Teddy",
"authorUrl": "/about",
"content": "Lorem ipsum dolor sit amet consectetur..."
},
{
"id": 9,
"name": "Northern Lights",
"description": "Finland is a Northern European nation bordering Sweden, Norway and Russia. Its capital, Helsinki, occupies a peninsula and surrounding islands in the Baltic Sea. Helsinki is home to the 18th-century sea fortress Suomenlinna, the fashionable Design District and diverse museums. The Northern Lights can be seen from the country's Arctic Lapland province, a vast wilderness with national parks and ski resorts.",
"categoryLanguages": [
{
"id": "europe",
"name": "Europe"
}
],
"tags": [
"europe",
"helsinki",
"baltic",
"Suomenlinna",
"Lapland"
],
"date": "2024-12-02T12:00:00.000Z",
"displayDate": "2 December 2024",
"relUrl": "europe/finland",
"coverExists": true,
"cover": "assets/northern-lights.jpg",
"author": "Teddy",
"authorUrl": "/about",
"content": "Lorem ipsum dolor sit amet consectetur..."
}
]
},
"categories": [
{
"id": "africa",
"name": "Africa",
"count": 4
},
{
"id": "asia",
"name": "Asia",
"count": 4
},
{
"id": "australia",
"name": "Australia",
"count": 1
},
{
"id": "europe",
"name": "Europe",
"count": 2
},
{
"id": "north-america",
"name": "North America",
"count": 1
},
{
"id": "south-america",
"name": "South America",
"count": 3
}
]
}
}
}
Client-side Aggregation
The build pipeline will also assign the aggregated localised metadata, minus the page metadata from the first N language-specific pages in the collection, to a constant JavaScript object named site which is written to a JavaScript file in the assets folder of the public distribution directory to enable client-side access to the site metadata. This JavaScript file may be found at $SITE_BASE/public/{env}/assets/js/site/site.js. This is particularly useful if you are using component-based JavaScript frameworks in your site and/or theme, and wish to access the aggregated localised site metadata when developing components. For example, the demo TravelBook site will generate the following aggregated localised JavaScript-based metadata file in $TEDDY_BASE/sites/travelbook/public/${env}/assets/js/site/site.js during the build. Note that if site.html.inject.systemAssets is set to true in the site.json site configuration, then the site.js JavaScript file will automatically be included in the generated HTML for all pages via the HTML <script> tag.
const site = {
"en": {
"content": {
"labels": {
"categories": "Categories",
"continueReading": "Continue Reading",
"languages": "Languages",
"loadMore": "Load More",
"notification": "No results found. Please try again.",
"recent": "Recent Articles",
"reset": "Reset Filters",
"search": "Search",
"searchPlaceholder": "Type and hit enter..."
},
"messages": {
"filters": {
"search": {
"results": "Found ${searchResults.length} posts containing the phrase '${searchQuery}'.",
"invalid": "Invalid search query - please try again."
},
"categories": {
"results": "Found ${searchResults.length} posts in the category '${category.name}'."
},
"combined": {
"results": "Found ${searchResults.length} posts containing the phrase '${searchQuery}' in the category '${category.name}'."
}
}
}
},
"contributors": {
"default": "teddy",
"teddy": {
"name": "Teddy",
"url": "/about/"
}
},
"menus": {
"main": [
{
"name": "Home",
"url": "/"
},
{
"name": "About",
"url": "/about/"
},
{
"name": "Blog",
"url": "/blog/"
}
],
"footer": {
"quickLinks": {
"title": "Quick Links",
"links": [
{
"name": "Home",
"url": "/"
},
{
"name": "About",
"url": "/about/"
},
{
"name": "Blog",
"url": "/blog/"
}
]
},
"socialLinks": {
"title": "Social Links",
"links": [
{
"name": "Facebook",
"url": ""
},
{
"name": "GitHub",
"url": "[object Object]"
},
{
"name": "Instagram",
"url": ""
},
{
"name": "Twitter",
"url": ""
}
]
}
},
"languages": [
{
"name": "English",
"url": "/en"
},
{
"name": "Japanese 日本語",
"url": "/ja"
},
{
"name": "Chinese 中文",
"url": "/zh-tw"
}
]
},
"metadata": {
"applicationName": "TravelBook",
"author": "Jillur Quddus",
"description": "Around the world with Teddy.",
"keywords": "africa, america, asia, australia, europe, holiday, flying, travel",
"title": "TravelBook"
},
"taxonomy": {
"categories": {
"africa": "Africa",
"asia": "Asia",
"australia": "Australia",
"europe": "Europe",
"north-america": "North America",
"south-america": "South America"
}
},
"urls": {
"external": {
"facebook": "https://www.facebook.com",
"github": "https://github.com",
"instagram": "https://www.instagram.com",
"themefisher": "https://github.com/themefisher/logbook-bootstrap",
"twitter": "https://x.com"
},
"collection": "/blog",
"assets": "/assets/0.0.1"
},
"collection": {
"metadata": {
"size": 15,
"pagination": {
"size": 10
},
"sort": {
"key": "date",
"order": "desc"
},
"search": {
"minQueryLength": 2
},
"categories": [
{
"id": "africa",
"name": "Africa",
"count": 4
},
{
"id": "asia",
"name": "Asia",
"count": 4
},
{
"id": "australia",
"name": "Australia",
"count": 1
},
{
"id": "europe",
"name": "Europe",
"count": 2
},
{
"id": "north-america",
"name": "North America",
"count": 1
},
{
"id": "south-america",
"name": "South America",
"count": 3
}
]
}
}
},
"ja": {
"content": {
"labels": {
"categories": "カテゴリー",
"continueReading": "続きを読む",
"languages": "言語",
"loadMore": "さらに読み込む",
"notification": "結果が見つかりませんでした。もう一度お試しください。",
"recent": "最近の記事",
"reset": "フィルターをリセット",
"search": "検索",
"searchPlaceholder": "検索..."
},
"messages": {
"filters": {
"search": {
"results": "「${searchQuery}」 というフレーズを含む投稿が ${searchResults.length} 件見つかりました。",
"invalid": "検索クエリが無効です。もう一度お試しください。"
},
"categories": {
"results": "「${category.name}」 カテゴリに ${searchResults.length} 件の投稿が見つかりました。"
},
"combined": {
"results": "「${category.name}」 カテゴリに 「${searchQuery}」 というフレーズを含む ${searchResults.length} 件の投稿が見つかりました。"
}
}
}
},
"contributors": {
"default": "teddy",
"teddy": {
"name": "Teddy",
"url": "/about/"
}
},
"menus": {
"main": [
{
"name": "ホーム",
"url": "/"
},
{
"name": "情報",
"url": "/about/"
},
{
"name": "ブログ",
"url": "/blog/"
}
],
"footer": {
"quickLinks": {
"title": "リンク",
"links": [
{
"name": "ホーム",
"url": "/"
},
{
"name": "情報",
"url": "/about/"
},
{
"name": "ブログ",
"url": "/blog/"
}
]
},
"socialLinks": {
"title": "ソーシャルメディア",
"links": [
{
"name": "フェイスブック",
"url": ""
},
{
"name": "ギットハブ",
"url": "[object Object]"
},
{
"name": "インスタグラム",
"url": ""
},
{
"name": "ツイッター",
"url": ""
}
]
}
},
"languages": [
{
"name": "English",
"url": "/en"
},
{
"name": "Japanese 日本語",
"url": "/ja"
},
{
"name": "Chinese 中文",
"url": "/zh-tw"
}
]
},
"metadata": {
"applicationName": "TravelBook",
"author": "Jillur Quddus",
"description": "テディと一緒に世界中を旅する",
"keywords": "アフリカ, アメリカ, アジア, オーストラリア, ヨーロッパ, 休日, フライング, 旅行",
"title": "TravelBook"
},
"taxonomy": {
"categories": {
"africa": "アフリカ",
"asia": "アジア",
"australia": "オーストラリア",
"europe": "ヨーロッパ",
"north-america": "北アメリカ",
"south-america": "南アメリカ"
}
},
"urls": {
"external": {
"facebook": "https://www.facebook.com",
"github": "https://github.com",
"instagram": "https://www.instagram.com",
"themefisher": "https://github.com/themefisher/logbook-bootstrap",
"twitter": "https://x.com"
},
"collection": "/ja/blog",
"assets": "/assets/0.0.1"
},
"collection": {
"metadata": {
"size": 15,
"pagination": {
"size": 10
},
"sort": {
"key": "date",
"order": "desc"
},
"search": {
"minQueryLength": 2
},
"categories": [
{
"id": "asia",
"name": "アジア",
"count": 4
},
{
"id": "africa",
"name": "アフリカ",
"count": 4
},
{
"id": "australia",
"name": "オーストラリア",
"count": 1
},
{
"id": "europe",
"name": "ヨーロッパ",
"count": 2
},
{
"id": "north-america",
"name": "北アメリカ",
"count": 1
},
{
"id": "south-america",
"name": "南アメリカ",
"count": 3
}
]
}
}
},
"zh-tw": {
"content": {
"labels": {
"categories": "類別",
"continueReading": "繼續閱讀",
"languages": "語言",
"loadMore": "加載更多",
"notification": "未找到結果。請重試。",
"recent": "最近的文章",
"reset": "重置過濾器",
"search": "搜尋",
"searchPlaceholder": "搜尋..."
},
"messages": {
"filters": {
"search": {
"results": "找到 ${searchResults.length} 個包含短語 「${searchQuery}」 的貼文。",
"invalid": "無效的搜尋查詢。請重試。"
},
"categories": {
"results": "在 「${category.name}」 類別中找到 ${searchResults.length} 個貼文。"
},
"combined": {
"results": "在 「${category.name」 類別中找到 ${searchResults.length} 個包含短語 「${searchQuery}」 的貼文。"
}
}
}
},
"contributors": {
"default": "teddy",
"teddy": {
"name": "Teddy",
"url": "/about/"
}
},
"menus": {
"main": [
{
"name": "首頁",
"url": "/"
},
{
"name": "資訊",
"url": "/about/"
},
{
"name": "部落格",
"url": "/blog/"
}
],
"footer": {
"quickLinks": {
"title": "連結",
"links": [
{
"name": "首頁",
"url": "/"
},
{
"name": "資訊",
"url": "/about/"
},
{
"name": "部落格",
"url": "/blog/"
}
]
},
"socialLinks": {
"title": "社群媒體",
"links": [
{
"name": "Facebook",
"url": ""
},
{
"name": "GitHub",
"url": "[object Object]"
},
{
"name": "Instagram",
"url": ""
},
{
"name": "Twitter",
"url": ""
}
]
}
},
"languages": [
{
"name": "English",
"url": "/en"
},
{
"name": "Japanese 日本語",
"url": "/ja"
},
{
"name": "Chinese 中文",
"url": "/zh-tw"
}
]
},
"metadata": {
"applicationName": "TravelBook",
"author": "Jillur Quddus",
"description": "和 Teddy 一起環遊世界",
"keywords": "非洲, 美國, 亞洲, 澳洲, 歐洲, 假期, 飛行, 旅行",
"title": "TravelBook"
},
"taxonomy": {
"categories": {
"africa": "非洲",
"asia": "亞洲",
"australia": "澳洲",
"europe": "歐洲",
"north-america": "北美洲",
"south-america": "南美洲"
}
},
"urls": {
"external": {
"facebook": "https://www.facebook.com",
"github": "https://github.com",
"instagram": "https://www.instagram.com",
"themefisher": "https://github.com/themefisher/logbook-bootstrap",
"twitter": "https://x.com"
},
"collection": "/zh-tw/blog",
"assets": "/assets/0.0.1"
},
"collection": {
"metadata": {
"size": 15,
"pagination": {
"size": 10
},
"sort": {
"key": "date",
"order": "desc"
},
"search": {
"minQueryLength": 2
},
"categories": [
{
"id": "asia",
"name": "亞洲",
"count": 4
},
{
"id": "north-america",
"name": "北美洲",
"count": 1
},
{
"id": "south-america",
"name": "南美洲",
"count": 3
},
{
"id": "europe",
"name": "歐洲",
"count": 2
},
{
"id": "australia",
"name": "澳洲",
"count": 1
},
{
"id": "africa",
"name": "非洲",
"count": 4
}
]
}
}
}
}
Accessing Localised Site Metadata
The aggregated localised site metadata values may be accessed by your markdown-based pages, HTML-based theme templates, and even the JSON-based localised metadata files themselves, by using the Mustache template syntax. Mustache uses tags to lookup and then render the value of specified property keys. For example, given the aggregated localised JSON-based metadata generated for the English language version of the demo TravelBook site provided above, the following Mustache tags will render the following values.
- {{ metadata.title }} will render
TravelBook. - {{ taxonomy.categories.south-america }} will render
South America. - {{{ urls.assets }}} will render
/assets. - {{{ urls.external.github }}} will render
https://github.com. - {{ collection.metadata.size }} will render
15.
All variables are HTML-escaped by default. To render unescaped HTML, for example URLs in the urls namespace, use the triple mustache which uses three pairs of curly braces, for example {{{ urls.external.github }}}.
Render Lists
Mustache also supports the ability to iterate over lists/arrays and render each object in the list. For example, the default Bear theme utilises the following Mustache syntax, found in $TEDDY_BASE/themes/bear/templates/partials/body/body-menu.html, to iterate over the list of main menu items to create main menu HTML elements.
{{ #menus.main }}
<li class="nav-item">
<a class="nav-link" href="{{{ url }}}">{{ name }}</a>
</li>
{{ /menus.main }}
Client-side Access
The aggregated localised site metadata values may also be accessed by client-side JavaScript. As described above, the constant site JavaScript object contains the per-language aggregated site metadata and is written to the site.js JavaScript file which is automatically included in the generated HTML for all pages via the HTML <script> tag. Furthermore, a constant JavaScript object named PAGE_LANGUAGE is also automatically injected into the generated HTML for all pages based on the language of the original markdown page, for example const PAGE_LANGUAGE = 'en';. Therefore, client-side JavaScript can access the site metadata by simply referencing the site object and providing the relevant nested keys to the metadata value required. For example, the default Bear template uses the Mithril.js client-side JavaScript framework in $TEDDY_BASE/themes/bear/assets/js/blog.js to build a component-based blog listing page, where the component labels are rendered by referencing the site JavaScript object. In the following snippet from blog.js, the "Load More" button label is rendered using site[PAGE_LANGUAGE].content.labels.loadMore.
const LoadMore = {
view: () => {
return searchResultsDelta.length < COLLECTION_PAGINATION_SIZE ? null :
m('button', {
type: 'button',
class: 'btn btn-primary',
onclick: async function(e) {
await doSearch(true);
m.redraw();
}
}, site[PAGE_LANGUAGE].content.labels.loadMore);
}
}
Localised Page Metadata
In addition to the aggregated localised metadata, page-specific metadata values may also be accessed by your markdown-based pages and HTML-based theme templates. For example, the demo TravelBook site contains the following English language markdown-based blog post page found in $TEDDY_BASE/sites/travelbook/pages/blog/zambia/post.en.md.
---
name: Mosi-oa-Tunya
enabled: true
description: Zambia, in southern Africa, is a landlocked country of rugged terrain and diverse wildlife, with many parks and safari areas. On its border with Zimbabwe is famed Victoria Falls – indigenously called Mosi-oa-Tunya, or 'Smoke That Thunders' – plunging a misty 108m into narrow Batoka Gorge. Spanning the Zambezi River just below the falls is Victoria Falls Bridge, a spectacular viewpoint.
categories: africa
tags: Zambezi, Victoria, Mosi-oa-Tunya, Batoka
authorId: teddy
date: 2025-03-02 12:00:00
cover: assets/victoria-falls.jpg
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit...
The page metadata values stored in the markdown frontmatter, i.e. the metadata enclosed between the --- separators at the head of the markdown document, can be accessed by your markdown-based pages and HTML-based theme templates by referencing the page.metadata object using JavaScript-based string interpolation. Using the example markdown-based blog post page provided above, the following JavaScript placeholders will resolve to the following values.
- ${page.metadata.name} will resolve to
Mosi-oa-Tunya. - ${page.metadata.description} will resolve to
Zambia, in southern Africa, is a landlocked country.... - ${page.metadata.date} will resolve to
2 March 2025.
To access the page content itself, you can use the ${page.content} placeholder as follows.
- ${page.content} will resolve to
Lorem ipsum dolor sit amet, consectetur adipiscing elit....
Please read the pages guide for further details including a complete list of reserved markdown frontmatter keys and helpful placeholder resolvers.
Localised Page URLs
Teddy also provides a convenient way for your markdown-based pages, HTML-based theme templates and JSON-based localised metadata files to access localised page URLs. As described in the sites guide, the directory structure in $SITE_BASE/pages will reflect the page structure of your static site when it is built. To avoid hardcoding localised page URLs in your markdown-based pages, HTML-based theme templates and JSON-based localised metadata files, you can reference the pages.urls object using JavaScript-based string interpolation. For example, using the demo TravelBook site, the following placeholders will resolve to the following URL values dependent upon the active language.
- ${pages.urls.home} will resolve to
/for the default language of the site (English),/jafor the Japanese language version of the site, and/zh-twfor the Traditional Chinese language version of the site. - ${pages.urls.about} will resolve to
/aboutfor the default language of the site (English),/ja/aboutfor the Japanese language version of the site, and/zh-tw/aboutfor the Traditional Chinese language version of the site. - ${pages.urls.blog} will resolve to
/blogfor the default language of the site (English),/ja/blogfor the Japanese language version of the site, and/zh-tw/blogfor the Traditional Chinese language version of the site. - ${pages.urls.blog.africa.zambia} will resolve to
/blog/africa/zambiafor the default language of the site (English),/ja/blog/africa/zambiafor the Japanese language version of the site, and/zh-tw/blog/africa/zambiafor the Traditional Chinese language version of the site.
