Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
test:
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.57.0-noble
image: mcr.microsoft.com/playwright:v1.58.0-noble
services:
db:
image: postgres:15
Expand Down
238 changes: 119 additions & 119 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,33 @@
"@eslint/js": "^9.39.2",
"@fontsource/fira-mono": "^5.2.7",
"@neoconfetti/svelte": "^2.2.2",
"@playwright/test": "^1.57.0",
"@playwright/test": "^1.58.0",
"@sveltejs/adapter-auto": "^7.0.0",
"@sveltejs/adapter-node": "^5.5.0",
"@sveltejs/kit": "^2.49.4",
"@sveltejs/adapter-node": "^5.5.2",
"@sveltejs/kit": "^2.50.1",
"@sveltejs/vite-plugin-svelte": "^6.2.4",
"@types/node": "^25.0.8",
"@types/node": "^25.0.10",
"@types/rss": "^0.0.32",
"@types/validator": "^13.15.10",
"date-picker-svelte": "^2.17.0",
"drizzle-kit": "^0.31.8",
"eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-svelte": "^3.14.0",
"globals": "^17.0.0",
"prettier": "^3.7.4",
"globals": "^17.1.0",
"prettier": "^3.8.1",
"prettier-plugin-svelte": "^3.4.1",
"svelte": "^5.46.3",
"svelte": "^5.48.2",
"svelte-check": "^4.3.5",
"typescript": "^5.9.3",
"typescript-eslint": "^8.53.0",
"typescript-eslint": "^8.53.1",
"vite": "^7.3.1"
},
"dependencies": {
"@fontsource/courier-prime": "^5.2.8",
"@fortawesome/free-solid-svg-icons": "^7.1.0",
"@friendofsvelte/toggle": "^0.0.4-svelte.5",
"@inlang/paraglide-js": "^2.8.0",
"@inlang/paraglide-js": "^2.9.1",
"@node-rs/argon2": "^2.0.2",
"@oslojs/crypto": "^1.0.1",
"@oslojs/encoding": "^1.1.0",
Expand All @@ -59,12 +59,12 @@
"postgres": "^3.4.8",
"rehype-raw": "^7.0.0",
"remark-youtube": "^1.3.3",
"remove-markdown": "^0.6.2",
"remove-markdown": "^0.6.3",
"rss": "^1.2.2",
"svelte-exmarkdown": "^5.0.2",
"svelte-fa": "^4.0.4",
"svelte-relative-time": "^0.0.6",
"validator": "^13.15.26",
"zod": "^4.3.5"
"zod": "^4.3.6"
}
}
3 changes: 3 additions & 0 deletions project.inlang/.meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"highestSdkVersion": "2.6.0"
}
103 changes: 103 additions & 0 deletions project.inlang/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@

## What is this folder?

This is an [unpacked (git-friendly)](https://inlang.com/docs/unpacked-project) inlang project.

## At a glance

Purpose:
- This folder stores inlang project configuration and plugin cache data.
- Translation files live outside this folder and are referenced from `settings.json`.

Safe to edit:
- `settings.json`

Do not edit:
- `cache/`
- `.gitignore`

Key files:
- `settings.json` — locales, plugins, file patterns (source of truth)
- `cache/` — plugin caches (safe to delete)
- `.gitignore` — generated

```
*.inlang/
├── settings.json # Locales, plugins, and file patterns (source of truth)
├── cache/ # Plugin caches (gitignored)
└── .gitignore # Ignores everything except settings.json
```

Translation files (like `messages/en.json`) live **outside** this folder and are referenced via plugins in `settings.json`.

## What is inlang?

[Inlang](https://inlang.com) is an open file format for building custom localization (i18n) tooling. It provides:

- **CRUD API** — Read and write translations programmatically via SQL
- **Plugin system** — Import/export any format (JSON, XLIFF, etc.)
- **Version control** — Built-in version control via [lix](https://lix.dev)

```
┌──────────┐ ┌───────────┐ ┌────────────┐
│ i18n lib │ │Translation│ │ CI/CD │
│ │ │ Tool │ │ Automation │
└────┬─────┘ └─────┬─────┘ └─────┬──────┘
│ │ │
└─────────┐ │ ┌──────────┘
▼ ▼ ▼
┌──────────────────────────────────┐
│ *.inlang file │
└──────────────────────────────────┘
```

## Quick start

```bash
npm install @inlang/sdk
```

```ts
import { loadProjectFromDirectory, saveProjectToDirectory } from "@inlang/sdk";

const project = await loadProjectFromDirectory({ path: "./project.inlang" });
// Query messages with SQLite + [Kysely](https://kysely.dev/) under the hood.
const messages = await project.db.selectFrom("message").selectAll().execute();

// Use project.db to update messages.
await saveProjectToDirectory({ path: "./project.inlang", project });
```

## Ideas for custom tooling

- Translation health dashboard (missing/empty/stale messages)
- Locale coverage report in CI
- Auto-PR for new keys with placeholders
- Migration tool between file formats via plugins
- Glossary/term consistency checker

## Data model ([docs](https://inlang.com/docs/data-model))

```
bundle (a concept, e.g., "welcome_header")
└── message (per locale, e.g., "en", "de")
└── variant (plural forms, gender, etc.)
```

- **bundle**: Groups messages by ID (e.g., `welcome_header`)
- **message**: A translation for a specific locale
- **variant**: Handles pluralization/selectors (most messages have one variant)

## Common tasks

- List bundles: `project.db.selectFrom("bundle").selectAll().execute()`
- List messages for locale: `project.db.selectFrom("message").where("locale", "=", "en").selectAll().execute()`
- Find missing translations: compare message counts across locales
- Update a message: `project.db.updateTable("message").set({ ... }).where("id", "=", "...").execute()`

## Links

- [SDK documentation](https://inlang.com/docs)
- [inlang.com](https://inlang.com)
- [List of plugins](https://inlang.com/c/plugins)
- [List of tools](https://inlang.com/c/tools)
2 changes: 1 addition & 1 deletion src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
:root {
--font-body: "Fira Mono", "Courier New", "Courier Prime", monospace;
--font-mono: "Fira Mono", "Courier Prime", monospace;
--color-bg: #070709;
--color-bg: #040204;
--column-width: 42rem;
--column-margin-top: 4rem;
font-family: var(--font-body);
Expand Down
10 changes: 9 additions & 1 deletion src/lib/components/common/BackgroundImage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

{#key backgroundImage}
<div
class="background-image"
class={backgroundImage ? "background-image" : "background-image blank"}
style={backgroundImage
? `background-image: url('../images/${backgroundImage}')`
: undefined}
Expand Down Expand Up @@ -39,4 +39,12 @@
var(--color-bg)
);
}

div.background-image.blank {
filter: none;
}

div.background-image.blank:after {
background: none;
}
</style>
34 changes: 27 additions & 7 deletions src/lib/components/common/Header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

<header>
<a href={resolve("/")} aria-label="Vilnius Hardcore">
<img src={Logo} alt={description} />
<figlet
><pre> .__ .___ .__ __
| |__ _____ _______ __| _/____ ___________ ____ | |_/ |_
Expand All @@ -19,8 +20,7 @@
<div class="site-description">
<span>{description}</span><span class="cursor">&nbsp;</span>
</div>
<img src={Logo} alt={description} /></a
>
</a>
</header>

<style>
Expand All @@ -34,7 +34,7 @@
}

:global(html) figlet,
:global(html) header .site-description {
:global(html):not(.dark) span.cursor {
display: none;
}

Expand Down Expand Up @@ -75,6 +75,11 @@
text-transform: uppercase;
}

:global(html):not(.dark) .site-description {
color: #f2f3f1;
position: absolute;
}

.cursor {
display: inline-block;
background: var(--color-bg);
Expand Down Expand Up @@ -111,16 +116,31 @@
}
}

@media screen and (max-width: 500px) {
@media screen and (max-width: 780px) {
header img {
width: 100%;
height: auto;
}
}

@media screen and (max-width: 450px) {
header .site-description {
font-size: 3vw;
@media screen and (min-width: 781px) {
:global(html):not(.dark) header .site-description {
padding-top: 13.37rem;
padding-left: 3.5em;
}
}

@media screen and (max-width: 780px) {
:global(html):not(.dark) header .site-description {
padding-top: 27.5%;
font-size: 2vw;
padding-left: 3.5em;
}
}

@media screen and (max-width: 780px) {
:global(html.dark) header .site-description {
font-size: 2vw;
}
}
</style>
Binary file modified src/lib/images/logo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading