Changelog

Kolofon · 11 września 2026

0.13.0 — dwa języki, jedno wdrożenie

gdy wersja angielska przestała być osobnym serwisem

0.13.0 — dwa języki, jedno wdrożenie

Tekst: Kolofon

Przez miesiąc wersja angielska tej strony żyła obok polskiej jak sąsiad zza ściany: osobna subdomena, osobne repozytorium, osobna baza, osobne wdrożenie. Każda poprawka szła dwa razy, a każdy nowy wpis wymagał dwóch pushy i dwóch weryfikacji. 0.13.0 kończy ten układ. Obie wersje stoją teraz w jednym wdrożeniu, a angielska mieszka pod `/en`.

Co decyduje o języku

Dwie rzeczy i żadna nie jest nowym polem konfiguracji. **O języku wpisu decyduje folder**: `src/content/posts` to wersja domyślna, `src/content/en/posts` to angielska. **O języku strony decyduje adres**: wersja zarejestrowana z adresem `https://…/en` dostaje przedrostek `/en`, bo tak wynika z jej `url`. Wszystkie polskie adresy zostały dokładnie tam, gdzie były.

locales: {
  en: {
    config: enConfig,  // url: "https://…/en"
    posts: import.meta.glob("./en/posts/*/*.json", { eager: true }),
    authors: enAuthors,
  },
},
src/content/instance.ts — wersja angielska w tym samym wdrożeniu

Język jako stan żądania

Trudniejsza połowa nie była w routingu, tylko w tym, że `cfg()` woła się w setkach miejsc i dotąd zawsze zwracało to samo. Teraz musi wiedzieć, w której wersji jest żądanie. Zmienna globalna odpadła od razu: jeden izolat Workera obsługuje żądania równolegle, a dwa renderowania przeplatają się na każdym `await`. Na serwerze język niesie AsyncLocalStorage, w przeglądarce przedrostek w pasku adresu. Test: osiemdziesiąt równoległych żądań po polsku i po angielsku, zero napisów z niewłaściwej wersji.

Pierwszy pomysł na przedrostek, `basepath` routera, nie przeżył zderzenia z TanStack Start: serwer nadpisuje go przy każdym żądaniu wartością z czasu budowania. Przeżył `rewrite` — router widzi adresy bez przedrostka, przeglądarka z przedrostkiem. Server functions idą pod wspólny adres bez przedrostka, więc język dokleja im nagłówek z przeglądarki.

Baza

Rzeczy wspólne dla języków — oceny, komentarze, głosy — już wcześniej były kluczowane kluczem wpisu. Poprawić trzeba było to, co dotyczy strony: odsłony trafiają teraz do `page_views` z kolumną `lang`, zdarzenia dostają `page_lang`, subskrypcje powiadomień swój język. Stara tabela odsłon zostaje nietknięta. Przepisanie danych robi migracja zapisywana w nowym rejestrze `schema_migrations`, a dane dawnej bazy angielskiej przenosi osobny skrypt, który staje przed pierwszym zapisem, gdy trafi na tabelę, której nie zna.

Przy okazji wyszło, że dziennik zdarzeń tej strony nie zapisał niczego od 14 sierpnia. Zapis szedł do kolumny `browser_id`, której nic nie zakładało, a błąd ginął w cichym `catch`. Kolumna jest zakładana, a nieudany zapis trafia teraz do dziennika Workera.

Czego to nie zmienia

Instancja jednojęzyczna nie deklaruje `locales` i działa co do znaku tak, jak w 0.12 — z jednym wyjątkiem: jej liczniki odsłon przechodzą jednorazowo do nowej tabeli z językiem domyślnym. Adres dawnej wersji angielskiej na razie odpowiada dalej; przekierowanie na `/en` przyjdzie osobno.