Jazyky, skutecny snimek v heru a opravene titulky

Prepinani jazyku (web/src/i18n/). Vybrany jazyk je jedna hodnota pro celou
aplikaci drzena mimo React - tentyz vzorec jako u vybrane firmy, a ze
stejneho duvodu: musi byt dostupny i mimo komponenty a prepnuti nesmi byt
stav jedne stranky. Volba prezije obnoveni a prepisuje <html lang>.

Anglicky slovnik je Partial: co v nem neni, spadne na cestinu. Kdyby musel
byt uplny, znamenal by kazdy novy cesky text rozbity build, dokud ho nekdo
neprelozi - a vysledkem by bylo, ze se texty nepridavaji. Prelozena je
hlavicka, hero vcetne snimku, pas s logy, cisla, zaverecna vyzva a cast
paticky; zbytek je mechanicky a popsany v 23-jazyky.md.

Snimek v heru vypada jako portal doopravdy. Byl svetly a ukazoval obrazovku,
ktera v produktu neexistuje. Ted ma tmavy podklad, tytez zalozky vcetne
prepinace firmy, tytez sloupce tabulky i tytez odznaky stavu jako stranka
Tickety. Kdyz se navstevnik prihlasi a uvidi neco jineho, prvni dojem
z produktu je, ze web lhal.

Jmeno znacky si sklada usePageMeta, ne stranky. Bylo napsane natvrdo ve
dvaceti ctyrech titulcich, takze prejmenovani zmenilo brand.ts a titulky ne:
hlavicka rikala nove jmeno a zalozka v prohlizeci stare.

Opraveno: odkaz "Prohlednout si to" vedl na koren domeny misto
/apps/<app-id>/sluzby, protoze to byl <a href> a ne Link z routeru. Byl to
jediny takovy odkaz v celem webu.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
JiriUhlir
2026-08-26 10:37:58 +02:00
co-authored by Claude Opus 5
parent 33b4a3fdd6
commit d71c111cf3
37 changed files with 807 additions and 232 deletions
+84
View File
@@ -0,0 +1,84 @@
# 23 - Jazyky
Rozdelane. Mechanismus je hotovy a overeny, prevod obsahu bezi po castech.
## Jak to funguje
| Co | Kde |
| ------------------- | ---------------------------------------------- |
| Vrstva, prepinani | `web/src/i18n/index.ts` |
| Ceske texty | `web/src/i18n/cs.ts` |
| Anglicke texty | `web/src/i18n/en.ts` |
| Prepinac v rozhrani | `web/src/components/layout/LanguageSwitch.tsx` |
Vybrany jazyk je **jedna hodnota pro celou aplikaci**, drzena v modulu mimo
React. Je to tentyz vzorec jako u vybrane firmy (`lib/tenant.ts`) a ze stejneho
duvodu: hodnota musi byt dostupna i mimo komponenty a prepnuti nesmi byt stav
jedne stranky.
Volba se uklada a prezije obnoveni stranky. Pri prvnim nacteni rozhoduje
ulozena volba, pak jazyk prohlizece, pak cestina.
Pri kazde zmene se prepisuje i `<html lang>`. Ctecky a prohlizece podle nej
poznaji jazyk stranky a nenabizeji preklad textu, ktery uz prelozeny je.
## Klice jsou ploche
```ts
t('hero.titleAccent') // ne t('hero').titleAccent
```
Ploche klice jdou vygrepovat: `grep "hero.titleAccent"` najde definici
i vsechna pouziti. U zanorenych objektu to nejde a prave tohle clovek pri
prekladu dela nejcasteji.
## Chybejici preklad nespadne
`en.ts` je `Partial`, takze **nemusi byt uplny**. Co v nem neni, spadne
na cestinu:
```ts
const text = dictionaries[locale][key] ?? cs[key] ?? key;
```
Diky tomu jde preklad doplnovat po castech. Kdyby anglictina musela byt uplna,
znamenal by kazdy novy cesky text rozbity build, dokud ho nekdo neprelozi -
a vysledkem by bylo, ze se texty nepridavaji.
Cestina je zaroven zaloha, takze nedokoncena anglictina znamena misty cestinu.
To je horsi nez hotovy preklad, ale lepsi nez prazdno nebo `hero.title`
v nadpisu.
## Co uz je prelozene
| Cast | Stav |
| ----------------------------------- | ------------------------------------ |
| Hlavicka a mobilni menu | hotovo |
| Hero vcetne snimku portalu | hotovo |
| Pas s logy klientu | hotovo |
| Cisla | hotovo |
| Zaverecna vyzva | hotovo |
| Paticka | castecne, sloupce odkazu zatim cesky |
| Sekce Produkty, Reference, Postup | ne |
| Stranky O nas, Sluzby, Kontakt, 404 | ne |
| Portal za prihlasenim | ne |
Prevod zbytku je mechanicky: text ven do `cs.ts`, klic do `en.ts`, v komponente
`const t = useT()` a `{t('klic')}`. Zadna dalsi prace na vrstve uz potreba neni.
## Co se neprekada
Jmeno znacky, kontakty, ICO a adresa zustavaji v `config/brand.ts`. Nemeni se
s jazykem a mit je ve slovniku dvakrat by znamenalo, ze se jednou zmeni jen
jedno misto.
Claim se **prekada** (`brand.claim`), protoze to je text, ne udaj.
## Co chybi
| Chybi | Poznamka |
| ---------------------- | ----------------------------------------------------------------- |
| Prevod zbytku obsahu | viz tabulka vys |
| Jazyk v adrese | `/en/sluzby` misto volby v prohlizeci. Chce to kvuli vyhledavacum |
| Preklad dat ze serveru | nazvy sluzeb, stavu a chybovych hlasek chodi z API cesky |
| Format cisel a datumu | `toLocaleString` se zatim vola natvrdo s `cs-CZ` |
+30
View File
@@ -2,6 +2,36 @@
Nejnovejsi nahore.
## 2026-08-26 - jazyky, skutecny snimek v heru a opravene titulky
### Pridano
- **Prepinani jazyku** (`web/src/i18n/`). Vybrany jazyk je jedna hodnota pro
celou aplikaci, drzena mimo React - tentyz vzorec jako u vybrane firmy.
Volba prezije obnoveni stranky a prepisuje `<html lang>`. Anglicky slovnik
je `Partial`: co v nem neni, spadne na cestinu, takze preklad jde doplnovat
po castech misto jednoho velkeho skoku. Podrobnosti
v [23-jazyky.md](23-jazyky.md).
- **Prepinac jazyka** v hlavicce a v mobilnim menu.
### Zmeneno
- **Snimek v heru vypada jako portal doopravdy.** Byl svetly a ukazoval
obrazovku, ktera v produktu neexistuje. Ted ma tmavy podklad, tytez zalozky
vcetne prepinace firmy, tytez sloupce tabulky i tytez odznaky stavu jako
stranka Tickety. Kdyz se navstevnik prihlasi a uvidi neco jineho, prvni
dojem z produktu je, ze web lhal.
- **Jmeno znacky si sklada `usePageMeta`, ne stranky.** Bylo napsane natvrdo
ve dvaceti ctyrech titulcich, takze prejmenovani produktu zmenilo
`brand.ts` a titulky ne - hlavicka rikala nove jmeno a zalozka v prohlizeci
stare.
### Opraveno
- **Odkaz "Prohlednout si to" vedl mimo proxy.** Byl to `<a href="/sluzby">`,
tedy koren domeny, ne `/apps/<app-id>/sluzby`. Ted je to `Link` z routeru
jako vsude jinde. Byl to jediny takovy odkaz v celem webu.
## 2026-08-26 - na aplikaci je videt, ktery build to je
Nasazena aplikace o dva commity pozadu funguje a vypada skoro stejne jako