Files
upstream-mirror e7da97194a
Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s
snapshot of https://github.com/twentyhq/twenty.git (main, 2026-09-17; blobs > 131072B omitted)
2026-09-17 23:28:13 +05:00

137 lines
5.7 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Překlady
description: Doručte svou aplikaci v několika jazycích — překládejte popisky manifestu a texty uživatelského rozhraní prostřednictvím jednoho katalogu locales.
icon: language
---
Aplikace Twenty jsou psané v **angličtině**: řetězce ve vašem zdrojovém kódu a manifestu tvoří anglický zdrojový text, `en` je zdrojová locale, ze které překládáte, a jakákoli locale ponechaná bez překladu se na ni automaticky vrátí.
Vaše aplikace má dva druhy přeložitelného textu a oba procházejí stejným
katalogem `locales/`:
* **Popisky manifestu** — názvy objektů a polí, názvy zobrazení, položky nabídky a
další řetězce deklarované v metadatech vaší aplikace.
* **Řetězce front komponent** — text uživatelského rozhraní, který vykreslují vaše React front komponenty.
Označíte přeložitelné řetězce, extrahujete je do katalogů pro jednotlivé jazyky,
přeložíte tyto katalogy a build doručí správný jazyk pro
aktuálního uživatele — bez dalšího zapojování.
## Označování řetězců front komponent
Importujte pomocné překladové funkce z `twenty-sdk/front-component`:
```tsx
import { Trans, t, msg, useTranslate } from 'twenty-sdk/front-component';
const STATUSES = [
{ id: 'draft', label: msg('Draft') },
{ id: 'sent', label: msg('Sent') },
];
const Card = ({ count, name }: { count: number; name: string }) => {
const { t } = useTranslate();
return (
<section>
{/* Static text — reactive to the user's locale */}
<Trans>Loading postcard…</Trans>
{/* Disambiguate identical sources with a context */}
<Trans context="card-title">Untitled</Trans>
{/* Interpolation: pass values explicitly */}
<p>{t('Hi {name}', { name })}</p>
<p>{t('Saved {count} cards', { count })}</p>
{/* Resolve a lazily-declared descriptor */}
<ul>{STATUSES.map((s) => <li key={s.id}>{t(s.label)}</li>)}</ul>
</section>
);
};
```
### Kdy co použít
* **`Trans`** — statický text v JSX. Použijte props `message` a `values` pro
interpolaci, jak je ukázáno v `Trans message="Hi {name}" values={{ name }}`;
interpolace přímo v potomcích není staticky extrahovatelná.
* **`useTranslate().t`** — dynamické řetězce uvnitř komponenty. Znovu se vykreslí, když
uživatel přepne jazyk. Uvnitř renderu tomuto dávejte přednost.
* **`t(...)`** (importované přímo) — okamžitý překlad použitelný **kdekoli**,
včetně obsluh událostí, pomocných funkcí a v modulovém rozsahu — nejen uvnitř renderu.
* **`msg(...)`** — líný deskriptor pro řetězce deklarované jako data (konstanty,
konfigurace). Vyhodnoťte jej později pomocí `t(descriptor)`.
### Kontext
Předejte `context`, abyste odlišili identické zdrojové řetězce, které se překládají
rozdílně:
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
Kontextové řetězce se v jazykových katalozích objevují jako skupina s klíčem podle svého kontextu: `"\<context>": { "\<message>": "\<translation>" }`. Štítky manifestu jsou kontextové již svou konstrukcí — každý z nich nese roli metadat, kterou plní (`objectMetadata.labelSingular`, `fieldMetadata.label`, `view.name`, …), takže stejné slovo se může přeložit odlišně jako název objektu a jako název zobrazení.
## Extrahování a překládání
Spusťte příkaz pro extrakci z adresáře své aplikace:
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
Extrakce shromáždí jak popisky manifestu, tak řetězce `t()`/`msg()`/`Trans`
z vašeho zdrojového kódu front komponent do `locales/\<locale>.json`, kde jsou klíčem
zdrojové řetězce. Doplňte překlady:
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées",
"door": {
"Open": "Ouvrir"
},
"objectMetadata.labelSingular": {
"Postcard": "Carte postale"
}
}
```
Řetězce bez kontextu jsou ploché položky; kontextové řetězce — včetně každého štítku manifestu — jsou vnořené pod svým kontextovým klíčem.
Zástupné symboly jako `{name}` jsou nahrazeny za běhu — ponechejte je v
překladu. Jakýkoli řetězec ponechaný prázdný spadne zpět na zdrojový text.
## Jak to běží
`twenty dev:build` zkompiluje katalogy a doručí správný jazyk pro
aktuálního uživatele: popisky manifestu jsou vyhodnoceny na straně serveru a katalogy
front komponent jsou zabudovány do každého balíčku komponent. Za běhu komponenta čte
jazykovou verzi (locale) z vykonávacího kontextu (aktuální jazyk hostitele) a překládá
každý řetězec podle svého katalogu, přičemž při chybějícím překladu spadne zpět na zdroj. Přepnutí jazyka v hostiteli znovu vykreslí řetězce `Trans` a
`useTranslate().t` v reálném čase.
Popisky manifestu se kompilují při každé synchronizaci — stejně při `twenty dev:build`, `twenty apply`
jako při průběžném sledování pomocí `twenty dev` — takže pro zobrazení nového textu stačí upravit soubor lokalizace a
provést synchronizaci. Katalogy komponent Front se při sestavení začleňují do
každého balíčku komponent, takže změna některého z nich stále znamená
znovu spustit `twenty dev:build` (a znovu nasadit).
Textoví potomci `Trans` mohou být na více řádcích — bílé znaky se slučují
stejně jako je slučuje JSX, takže oba tyto případy se extrahují pod klíčem `Welcome back`:
```tsx
<Trans>Welcome back</Trans>
<Trans>
Welcome
back
</Trans>
```