InkStone

Multilingual & UI Translations

Contents

InkStone has two independent translation mechanisms: content translation for publishing notes in multiple languages, and UI string translation for localising all fixed labels in templates.


Content Translation — _LANG filename suffix

Add a two-letter ISO language code as a suffix to any note filename to mark it as a translation:

blog/My Post.md        → /blog/my-post          (default language)
blog/My Post_RU.md     → /blog/my-post/ru
blog/My Post_FR.md     → /blog/my-post/fr
blog/My Post_DE.md     → /blog/my-post/de

The suffix is case-insensitive. You can also set the language explicitly in frontmatter instead of (or in addition to) the suffix:

---
website: true
lang: ru
title: Мой Пост
---

Setting the default language

The site's default language is read from language: in the root homepage's frontmatter:

---
website: true
type: homepage
language: en
---

If omitted, en is used. Notes without a language suffix are treated as the default language.

What the engine does automatically


UI String Translations — type: translations note

Every fixed string baked into the templates can be translated without editing any HTML. Create a vault note with two parts.

Frontmatter — just the type and language code:

---
type: translations
lang: ru
---

Note body — a fenced yaml block with the string pairs:

```yaml
Search: Поиск
Tags: Теги
"All tags": Все теги
"No results": Нет результатов
for: для
result: Результат
results: Результаты
tagged: с тегом
"min read": мин чтения
Featured: Избранное
"All Posts": Все Посты
"No posts yet.": Пока нет записей.
"No tags yet.": Пока нет тегов.
"built with": создано с помощью
Home: Главная
Contents: Содержание
"See also": Смотрите также
Updated: Обновлено
by: автор
date_format: "{day} {month} {year}"
January: января
February: февраля
March: марта
April: апреля
May: мая
June: июня
July: июля
August: августа
September: сентября
October: октября
November: ноября
December: декабря
"Not yet translated": Ещё не переведено
"Translation unavailable": Перевод недоступен
"This page is not yet available in": Эта страница ещё не доступна на языке
"Read it in": Читать на
```

The strings live in the note body rather than nested in frontmatter — much easier to edit in Obsidian's editor.

No `website: true` needed

Translation notes are loaded automatically regardless of website: status. Place them anywhere in the vault.

Rules: - One note per language. Two notes with the same lang: log a warning; the last one loaded wins. - Only keys that exist in the block are translated. Missing keys fall back to the English default. - Strings that contain a colon must be quoted (standard YAML rule).


Date localisation

Dates are rendered using date_format and individual month name keys. The default format is {month} {day}, {year} (e.g. "April 25, 2026"). To use a different order or separator, set date_format and translate each month name:

date_format: "{day} {month} {year}"
January: января
February: февраля
# … all 12 months

The placeholders {day}, {month}, and {year} are always available. Month names are looked up by their English name (January, February, …) so you only need to include the languages you're adding.


The Search and Tags nav links automatically append ?lang=<code> when the visitor is on a non-default language page, so /search and /tags load with the correct UI language. The search form also preserves the language across submissions.


Translating section index pages

Section listing pages (type: listing) and homepage files (type: homepage) can also be translated:

blog/Blog Index.md      → /blog          (default)
blog/Blog Index_RU.md   → /blog/ru

The translated listing page will show only posts that have a _RU variant.


Example vault structure

My Vault/
  homepage.md              → /
  homepage_RU.md           → /ru
  _UI Translations_RU.md   → (loaded for UI labels, no URL)
  blog/
    Blog Index.md          → /blog
    Blog Index_RU.md       → /blog/ru
    My Post.md             → /blog/my-post
    My Post_RU.md          → /blog/my-post/ru