i18n - docs translations (#22413)

Created by Github action

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22413?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->

Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
github-actions[bot]
2026-07-01 19:14:28 +02:00
committed by GitHub
parent d8cc81cb91
commit 15c0c3b773
25 changed files with 1525 additions and 0 deletions
+72
View File
@@ -874,6 +874,12 @@
"l/fr/developers/extend/apps/operations/testing",
"l/fr/developers/extend/apps/operations/publishing"
]
},
{
"group": "Traductions",
"pages": [
"l/fr/developers/extend/apps/translations/overview"
]
}
]
},
@@ -1308,6 +1314,12 @@
"l/ar/developers/extend/apps/operations/testing",
"l/ar/developers/extend/apps/operations/publishing"
]
},
{
"group": "الترجمات",
"pages": [
"l/ar/developers/extend/apps/translations/overview"
]
}
]
},
@@ -1742,6 +1754,12 @@
"l/cs/developers/extend/apps/operations/testing",
"l/cs/developers/extend/apps/operations/publishing"
]
},
{
"group": "Překlady",
"pages": [
"l/cs/developers/extend/apps/translations/overview"
]
}
]
},
@@ -2176,6 +2194,12 @@
"l/de/developers/extend/apps/operations/testing",
"l/de/developers/extend/apps/operations/publishing"
]
},
{
"group": "Übersetzungen",
"pages": [
"l/de/developers/extend/apps/translations/overview"
]
}
]
},
@@ -2610,6 +2634,12 @@
"l/es/developers/extend/apps/operations/testing",
"l/es/developers/extend/apps/operations/publishing"
]
},
{
"group": "Traducciones",
"pages": [
"l/es/developers/extend/apps/translations/overview"
]
}
]
},
@@ -3044,6 +3074,12 @@
"l/it/developers/extend/apps/operations/testing",
"l/it/developers/extend/apps/operations/publishing"
]
},
{
"group": "Traduzioni",
"pages": [
"l/it/developers/extend/apps/translations/overview"
]
}
]
},
@@ -3478,6 +3514,12 @@
"l/ja/developers/extend/apps/operations/testing",
"l/ja/developers/extend/apps/operations/publishing"
]
},
{
"group": "翻訳",
"pages": [
"l/ja/developers/extend/apps/translations/overview"
]
}
]
},
@@ -3912,6 +3954,12 @@
"l/ko/developers/extend/apps/operations/testing",
"l/ko/developers/extend/apps/operations/publishing"
]
},
{
"group": "번역",
"pages": [
"l/ko/developers/extend/apps/translations/overview"
]
}
]
},
@@ -4346,6 +4394,12 @@
"l/pt/developers/extend/apps/operations/testing",
"l/pt/developers/extend/apps/operations/publishing"
]
},
{
"group": "Traduções",
"pages": [
"l/pt/developers/extend/apps/translations/overview"
]
}
]
},
@@ -4780,6 +4834,12 @@
"l/ro/developers/extend/apps/operations/testing",
"l/ro/developers/extend/apps/operations/publishing"
]
},
{
"group": "Traduceri",
"pages": [
"l/ro/developers/extend/apps/translations/overview"
]
}
]
},
@@ -5648,6 +5708,12 @@
"l/tr/developers/extend/apps/operations/testing",
"l/tr/developers/extend/apps/operations/publishing"
]
},
{
"group": "Çeviriler",
"pages": [
"l/tr/developers/extend/apps/translations/overview"
]
}
]
},
@@ -6082,6 +6148,12 @@
"l/zh/developers/extend/apps/operations/testing",
"l/zh/developers/extend/apps/operations/publishing"
]
},
{
"group": "翻译",
"pages": [
"l/zh/developers/extend/apps/translations/overview"
]
}
]
},
@@ -0,0 +1,118 @@
---
title: الترجمات
description: قم بشحن تطبيقك بعدة لغات — ترجم تسميات ملف manifest وسلاسل واجهة المستخدم من خلال كتالوج محليات واحد.
icon: language
---
Twenty تطبيقًا مكتوبًا باللغة **English**: السلاسل في المصدر وملف manifest
هي نص المصدر باللغة الإنجليزية، و `en` هي لغة المصدر التي تترجم *منها*، وأي
إعداد محلي لا تتم ترجمته يعود إليها افتراضيًا.
يحتوي تطبيقك على نوعين من النصوص القابلة للترجمة، وكلاهما يمر عبر نفس
كتالوج `locales/`:
* **Manifest labels** — أسماء الكائنات والحقول، وعناوين العروض، وعناصر القوائم، و
السلاسل الأخرى المصرّح بها في بيانات التعريف لتطبيقك.
* **سلاسل الواجهة الأمامية (front-component)** — نص واجهة المستخدم الذي تقوم مكوّنات React الأمامية لديك بعرضه.
أنت تقوم بوضع علامة على السلاسل القابلة للترجمة، واستخراجها إلى كتالوجات لكل لغة (locale)، ثم تترجم هذه الكتالوجات، ويقوم البناء (build) بتقديم اللغة الصحيحة للمستخدم الحالي — بدون أي توصيل إضافي.
## وضع علامات على سلاسل الواجهة الأمامية (front-component)
قم باستيراد أدوات الترجمة من `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>
);
};
```
### متى تستخدم أيًّا منها
* **`<Trans>…</Trans>`** — نص ثابت في JSX. استخدم الخاصيتين `message` و`values`
من أجل الاستبدال (interpolation) (`<Trans message="Hi {name}" values={{ name }} />`);
لا يمكن استخراج الاستبدال مباشرة في العناصر الأبناء (children) بشكل ثابت.
* **`useTranslate().t`** — سلاسل ديناميكية داخل المكوّن. يُعيد التصيير عندما يغيّر المستخدم اللغة. يفضّل استخدامه داخل التصيير (render).
* **`t(...)`** (مستوردة مباشرة) — ترجمة فورية (eager) يمكن استخدامها **في أي مكان**،
بما في ذلك معالجات الأحداث (event handlers)، والبرامج المساعدة (helpers)، ونطاق الوحدة (module scope) — وليس فقط داخل التصيير.
* **`msg(...)`** — واصف كسول (lazy descriptor) للسلاسل المصرّح بها كبيانات (ثوابت،
إعدادات config). قم بحلّه لاحقًا باستخدام `t(descriptor)`.
### السياق
مرِّر `context` لتمييز سلاسل المصدر المتطابقة التي تُترجَم بشكل مختلف:
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
## الاستخراج والترجمة
شغِّل أمر الاستخراج من دليل تطبيقك:
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
يقوم الاستخراج بجمع كل من تسميات ملف البيان (manifest labels) وسلاسل `t()`/`msg()`/`\<Trans>`
من شفرة الواجهة الأمامية (front-component) إلى `locales/\<locale>.json`، مفهرسة حسب
سلسلة المصدر. املأ الترجمات:
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées"
}
```
العناصر النائبة مثل `{name}` تُستبدَل وقت التشغيل — احتفظ بها في
الترجمة. أي سلسلة تُترَك فارغة تعود إلى نص المصدر.
## كيفية التشغيل
يقوم `twenty dev:build` بتجميع الكتالوجات وتقديم اللغة الصحيحة للمستخدم
الحالي: يتم حل تسميات ملف البيان (manifest labels) على جانب الخادم، ويتم تضمين كتالوجات الواجهة الأمامية (front-component)
داخل كل حزمة مكوّن. وقت التشغيل يقرأ المكوّن
اللغة (locale) من سياق التنفيذ الخاص به (لغة المضيف الحالية) ويحل كل سلسلة مقابل كتالوجه، مع الرجوع إلى المصدر عندما تكون الترجمة مفقودة. تغيير اللغة في المضيف يعيد تصيير سلاسل `\<Trans>` و
`useTranslate().t` مباشرة.
نظرًا إلى أنّ الكتالوجات تُجمَّع في وقت البناء، فإن تحديث ترجمة ما يعني
إعادة تشغيل `twenty dev:build` (وإعادة النشر)، تمامًا مثل أي تغيير آخر.
<Note>
يتم تجميع الترجمات بواسطة `twenty dev:build` (و`twenty apply`). تشغيل المراقبة المستمرة `twenty dev`
يعرض سلاسل المصدر، لذا اختبر المخرجات المترجمة ببناء (build) لمرة واحدة.
</Note>
قد تمتد عناصر النص التابعة لـ `<Trans>` على عدة أسطر — يتم ضغط المسافات
بنفس الطريقة التي يقوم JSX بضغطها، لذلك كل من `<Trans>Welcome\n back</Trans>`
ومفتاح الاستخراج يصبحان `Welcome back`.
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "العمليات"
},
"appsTranslations": {
"label": "الترجمات"
}
}
},
@@ -0,0 +1,121 @@
---
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>…</Trans>`** — statický text v JSX. Použijte props `message` a `values`
pro interpolaci (`<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>
```
## 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"
}
```
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.
Protože katalogy jsou kompilovány v době buildu, aktualizace překladu znamená
znovu spustit `twenty dev:build` (a znovu nasadit) stejně jako jakoukoli jinou změnu.
<Note>
Překlady jsou kompilovány příkazy `twenty dev:build` (a `twenty apply`). Nepřetržité sledování `twenty dev` zobrazuje zdrojové řetězce, takže lokalizovaný výstup
otestujte pomocí jednorázového buildu.
</Note>
Potomci `<Trans>` s textem mohou být rozloženi na více řádků — prázdné znaky jsou zpracovány
stejně, jako je zpracovává JSX, takže `<Trans>Welcome\n back</Trans>` i extrahovaný
klíč se oba stanou `Welcome back`.
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "Operace"
},
"appsTranslations": {
"label": "Překlady"
}
}
},
@@ -0,0 +1,125 @@
---
title: Übersetzungen
description: Veröffentlichen Sie Ihre App in mehreren Sprachen  übersetzen Sie Manifest-Labels und UI-Zeichenketten über einen einzigen Locale-Katalog.
icon: language
---
Twenty-Apps werden auf **Englisch** erstellt: Die Zeichenketten in Ihrem Quellcode und im Manifest
sind der englische Ausgangstext, `en` ist das QuellLocale, aus dem Sie übersetzen, und
jedes Locale, das unübersetzt bleibt, fällt darauf zurück.
Ihre App enthält zwei Arten von übersetzbarem Text, und beide laufen durch denselben
`locales/`-Katalog:
* **Manifest-Labels** Objekt- und Feldnamen, Sichtetitel, Menüpunkte und
andere Zeichenketten, die in den Metadaten Ihrer App deklariert sind.
* **Front-Component-Zeichenketten** der UI-Text, den Ihre React-Front-Components rendern.
Sie markieren die übersetzbaren Zeichenketten, extrahieren sie in sprachspezifische Kataloge,
übersetzen diese Kataloge, und der Build stellt die richtige Sprache für den
aktuellen Benutzer bereit ohne zusätzlichen Aufwand.
## Markieren von Front-Component-Zeichenketten
Importieren Sie die Übersetzungs-Helfer aus `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>
);
};
```
### Wann Sie was verwenden sollten
* **`<Trans>…</Trans>`** statischer Text in JSX. Verwenden Sie die Props `message` und `values`
zur Interpolation (`<Trans message="Hi {name}" values={{ name }} />`);
eine direkte Interpolation in den Children ist nicht statisch extrahierbar.
* **`useTranslate().t`** dynamische Zeichenketten innerhalb einer Komponente. Wird neu gerendert, wenn der
Benutzer die Sprache wechselt. Bevorzugen Sie dies innerhalb von Render-Funktionen.
* **`t(...)`** (direkt importiert) sofortige Übersetzung, die **überall** verwendet werden kann,
einschließlich Event-Handlern, Helfern und im Modul-Scope nicht nur innerhalb von Render-Funktionen.
* **`msg(...)`** ein Lazy-Descriptor für Zeichenketten, die als Daten (Konstanten,
Konfiguration) deklariert werden. Lösen Sie ihn später mit `t(descriptor)` auf.
### Kontext
Übergeben Sie `context`, um identische Quellzeichenketten zu unterscheiden,
die sich unterschiedlich übersetzen lassen:
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
## Extrahieren und Übersetzen
Führen Sie den Extract-Befehl aus Ihrem App-Verzeichnis aus:
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
Die Extraktion sammelt sowohl Ihre Manifest-Labels als auch die `t()`-/`msg()`-/`\<Trans>`-
Zeichenketten aus Ihrem Front-Component-Quellcode in `locales/\<locale>.json`, indiziert nach der
Quellzeichenkette. Füllen Sie die Übersetzungen aus:
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées"
}
```
Platzhalter wie `{name}` werden zur Laufzeit ersetzt behalten Sie sie in der
Übersetzung bei. Jede Zeichenkette, die leer bleibt, fällt auf den Quelltext zurück.
## Wie sie ausgeführt wird
`twenty dev:build` kompiliert die Kataloge und stellt die richtige Sprache für den
aktuellen Benutzer bereit: Manifest-Labels werden serverseitig aufgelöst und Front-Component-
Kataloge werden in jedes Komponenten-Bundle eingebunden. Zur Laufzeit liest eine Komponente die
Locale aus ihrem Ausführungskontext (der aktuellen Sprache des Hosts) und löst
jede Zeichenkette gegen ihren Katalog auf, wobei auf die Quelle zurückgegriffen
wird, wenn eine Übersetzung fehlt. Das Umschalten der Sprache im Host rendert `\<Trans>`- und
`useTranslate().t`-Zeichenketten live neu.
Da Kataloge zur Build-Zeit kompiliert werden, bedeutet das Aktualisieren einer Übersetzung,
`twenty dev:build` erneut auszuführen (und erneut bereitzustellen), genau wie bei jeder anderen Änderung.
<Note>
Übersetzungen werden durch `twenty dev:build` (und `twenty apply`) kompiliert. Der
kontinuierliche `twenty dev`-Watch zeigt Quellzeichenketten an, daher sollten Sie die lokalisierte Ausgabe
mit einem einmaligen Build testen.
</Note>
`<Trans>`-Text-Children können sich über mehrere Zeilen erstrecken Leerzeichen werden auf dieselbe Weise zusammengefasst,
wie JSX sie zusammenfasst, sodass sowohl `<Trans>Welcome\n back</Trans>` als auch der extrahierte
Schlüssel `Welcome back` werden.
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "Operationen"
},
"appsTranslations": {
"label": "Übersetzungen"
}
}
},
@@ -0,0 +1,120 @@
---
title: Traducciones
description: "Lanza tu aplicación en varios idiomas: traduce las etiquetas del manifiesto y las cadenas de la interfaz de usuario mediante un único catálogo de configuraciones regionales (locales)."
icon: language
---
Twenty aplicaciones están creadas en **English**: las cadenas de tu código fuente y del manifiesto son el texto fuente en inglés, `en` es la configuración regional de origen desde la que traduces, y cualquier configuración regional que quede sin traducir recurrirá a ella como copia de seguridad.
Tu aplicación tiene dos tipos de texto traducible, y ambos pasan por el mismo catálogo `locales/`:
* **Etiquetas del manifiesto**: nombres de objetos y campos, títulos de vistas, elementos de menú y otras cadenas declaradas en los metadatos de tu aplicación.
* **Cadenas de componentes delanteros** — la interfaz de texto de tus componentes frontales de React.
Marcas las cadenas traducibles, extralas en catálogos por localidad,
traduce esos catálogos, y la construcción sirve el idioma adecuado para el usuario
actual — no hay cableado extra.
## Marcando cadenas de componentes frontales
Importar los ayudantes de traducción de `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>
);
};
```
### Cuándo usar qué
* **`<Trans>…</Trans>`** — texto estático en JSX. Usa los accesorios `message` y `values`
para la interpolación (`<Trans message="Hi {name}" values={{ name }} />`);
interpolar directamente en los hijos no es extraíble estáticamente.
* **`useTranslate().t`** — cadenas dinámicas dentro de un componente. Se vuelve a procesar cuando el usuario
cambia de idioma. Preferir esto dentro del render.
* **`t(...)`** (importado directamente) — una traducción entera utilizable **en cualquier lugar**,
incluyendo controladores de eventos, ayudantes y ámbito del módulo — no solo dentro del render.
* **`msg(...)`** — un descriptor perezoso para cadenas declaradas como datos (constantes, configuración
). Resuelva más tarde con `t(descriptor)`.
### Contexto
Pase `context` para desambiguar cadenas de origen idénticas que traduzcan
de forma diferente:
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
## Extrayendo y traduciendo
Ejecutar el comando de extracción desde el directorio de la aplicación:
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
La extracción recolecta tanto tus etiquetas de manifiesto como las de `t()`/`msg()`/`\<Trans>`
cadenas de tu fuente de componentes front-front en `locales/\<locale>. son`, keyed by
source string. Rellena las traducciones:
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées"
}
```
Los marcadores de posición como `{name}` se sustituyen en tiempo de ejecución — manténgalos en la traducción
. Cualquier cadena que quede vacía regresa al texto original.
## Cómo funciona
`twenty dev:build` compila los catálogos y sirve el idioma correcto para el
usuario actual: las etiquetas del manifiesto se resuelven del lado del servidor y los catálogos de front-component se incluyen en cada paquete de componente. En tiempo de ejecución, un componente lee la configuración regional
desde su contexto de ejecución (el idioma actual del host) y resuelve
cada cadena contra su catálogo, volviendo a la fuente cuando falta una traducción
. Cambiando idioma en el host vuelve a renderizar cadenas `\<Trans>` y
`useTranslate().t` en directo.
Debido a que los catálogos se compilan en tiempo de construcción, actualizar una traducción significa
volver a ejecutar `twenty dev:build` (y redesplegar), lo mismo que cualquier otro cambio.
<Note>
Las traducciones son compiladas por `twenty dev:build` (y `veinte aplicaciones`). El reloj
continuo `veinte dev` muestra las cadenas de origen, así que prueba la salida localizada
con una compilación única.
</Note>
`<Trans>` los hijos de texto pueden expandir múltiples líneas — el espacio en blanco está colapsado el
de la misma manera que JSX lo colapsa, así que `<Trans>Bienvenido\n de vuelta</Trans>` y la clave
extraída se convierten en `Welcome back`.
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "Operaciones"
},
"appsTranslations": {
"label": "Traducciones"
}
}
},
@@ -0,0 +1,125 @@
---
title: Traductions
description: Publiez votre application en plusieurs langues — traduisez les libellés du manifeste et les chaînes dinterface utilisateur via un seul catalogue de locales.
icon: language
---
Les applications Twenty sont rédigées en **anglais** : les chaînes de vos sources et de votre manifeste
sont le texte source en anglais, `en` est la locale source à partir de laquelle vous traduisez, et
toute locale laissée non traduite revient à celle-ci par défaut.
Votre application comporte deux types de textes traduisibles, et tous deux transitent par le même
catalogue `locales/` :
* **Libellés du manifeste** — noms dobjets et de champs, titres de vues, éléments de menu et
autres chaînes déclarées dans les métadonnées de votre application.
* **Chaînes de front-component** — le texte dinterface utilisateur que vos composants React front affichent.
Vous marquez les chaînes traduisibles, vous les extrayez dans des catalogues par locale,
vous traduisez ces catalogues, et la build sert la bonne langue pour
lutilisateur actuel — sans câblage supplémentaire.
## Marquer les chaînes de front-component
Importez les helpers de traduction depuis `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>
);
};
```
### Quand utiliser quoi
* **`<Trans>…</Trans>`** — texte statique dans JSX. Utilisez les props `message` et `values`
pour linterpolation (`<Trans message="Hi {name}" values={{ name }} />`) ;
linterpolation directement dans les enfants nest pas extractible statiquement.
* **`useTranslate().t`** — chaînes dynamiques à lintérieur dun composant. Se réaffiche lorsque
lutilisateur change de langue. À privilégier à lintérieur du rendu.
* **`t(...)`** (importé directement) — traduction immédiate utilisable **partout**,
y compris dans les gestionnaires d’événements, helpers et dans la portée du module — pas seulement dans le rendu.
* **`msg(...)`** — un descripteur paresseux pour les chaînes déclarées comme données (constantes,
configuration). Résolvez-le plus tard avec `t(descriptor)`.
### Contexte
Passez `context` pour lever lambiguïté entre des chaînes source identiques qui se traduisent
différemment :
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
## Extraction et traduction
Exécutez la commande dextraction depuis le répertoire de votre application :
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
Lextraction collecte à la fois les libellés de votre manifeste et les chaînes `t()`/`msg()`/`\<Trans>`
provenant de votre source front-component dans `locales/\<locale>.json`, indexées par
chaîne source. Renseignez les traductions :
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées"
}
```
Les espaces réservés comme `{name}` sont substitués à lexécution — conservez-les dans la
traduction. Toute chaîne laissée vide revient au texte source.
## Comment ça marche
`twenty dev:build` compile les catalogues et sert la bonne langue pour
lutilisateur actuel : les libellés du manifeste sont résolus côté serveur, et les catalogues
front-component sont intégrés à chaque bundle de composant. Lors de l'exécution, un composant lit la locale
depuis son contexte d'exécution (la langue courante de l'hôte) et résout
chaque chaîne de caractères par rapport à son catalogue, retour à la source lorsqu'une traduction
est manquante. Changement de langue dans les chaînes de re-rendu d'hôte `\<Trans>` et
`useTranslate().t` en direct.
Parce que les catalogues sont compilés au moment de la compilation, mettre à jour une traduction signifie
réexécute `vingt dev:build` (et redéploiement), la même chose que tout autre changement.
<Note>
Les traductions sont compilées par `twenty dev:build` (et `twenty apply`). La
surveillance continue `twenty dev` affiche les chaînes source, donc testez la sortie localisée
avec une build ponctuelle.
</Note>
Les enfants texte de `<Trans>` peuvent s’étendre sur plusieurs lignes — les espaces sont compressés de
la même façon que JSX les compresse, donc `<Trans>Welcome\n back</Trans>` et la clé extraite
deviendront toutes deux `Welcome back`.
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "Opérations"
},
"appsTranslations": {
"label": "Traductions"
}
}
},
@@ -0,0 +1,124 @@
---
title: Traduzioni
description: Distribuisci la tua app in più lingue — traduci le etichette del manifest e le stringhe dell'interfaccia utente tramite un unico catalogo delle localizzazioni.
icon: language
---
Le app di Twenty sono scritte in **inglese**: le stringhe nel tuo sorgente e nel manifest
sono il testo sorgente in inglese, `en` è la locale di origine da cui traduci e
qualsiasi locale lasciato non tradotto usa quella come fallback.
La tua app ha due tipi di testo traducibile, e entrambi passano attraverso lo stesso
catalogo `locales/`:
* **Etichette del manifest** — nomi di oggetti e campi, titoli delle viste, voci di menu e
altre stringhe dichiarate nei metadati della tua app.
* **String dei front-component** — il testo dellinterfaccia utente renderizzato dai tuoi front component React.
Contrassegni le stringhe traducibili, le estrai in cataloghi per locale,
traduci tali cataloghi e la build serve la lingua corretta per lutente
corrente — senza cablaggi aggiuntivi.
## Contrassegnare le stringhe dei front-component
Importa gli helper di traduzione da `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>
);
};
```
### Quando usare cosa
* **`<Trans>…</Trans>`** — testo statico in JSX. Usa le prop `message` e `values`
per linterpolazione (`<Trans message="Hi {name}" values={{ name }} />`);
linterpolazione direttamente nei children non è estraibile staticamente.
* **`useTranslate().t`** — stringhe dinamiche allinterno di un componente. Esegue il re-render quando
lutente cambia lingua. Preferiscilo allinterno del render.
* **`t(...)`** (importato direttamente) — traduzione eager utilizzabile **ovunque**,
inclusi gestori di eventi, helper e nello scope del modulo — non solo allinterno del render.
* **`msg(...)`** — un descrittore lazy per stringhe dichiarate come dati (costanti,
configurazione). Risolvilo in un secondo momento con `t(descriptor)`.
### Contesto
Passa `context` per distinguere stringhe sorgente identiche che si traducono
in modo diverso:
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
## Estrazione e traduzione
Esegui il comando di estrazione dalla directory della tua app:
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
Lestrazione raccoglie sia le etichette del manifest sia le stringhe `t()`/`msg()`/`\<Trans>`
dal sorgente dei tuoi front-component in `locales/\<locale>.json`, con chiave
la stringa sorgente. Compila le traduzioni:
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées"
}
```
I segnaposto come `{name}` vengono sostituiti a runtime — mantienili nella
traduzione. Qualsiasi stringa lasciata vuota fa fallback al testo sorgente.
## Come viene eseguito
`twenty dev:build` compila i cataloghi e serve la lingua corretta per lutente
corrente: le etichette del manifest vengono risolte lato server e i cataloghi dei
front-component vengono inclusi in ogni bundle di componente. A runtime un componente legge la
locale dal proprio contesto di esecuzione (la lingua corrente dellhost) e risolve
ogni stringa rispetto al proprio catalogo, facendo fallback alla sorgente quando
una traduzione manca. Il cambio di lingua nellhost esegue il re-render delle stringhe `\<Trans>` e
`useTranslate().t` in tempo reale.
Poiché i cataloghi vengono compilati in fase di build, aggiornare una traduzione significa
eseguire nuovamente `twenty dev:build` (e ridistribuire), come per qualsiasi altra modifica.
<Note>
Le traduzioni vengono compilate da `twenty dev:build` (e `twenty apply`). La modalità watch continua di `twenty dev` mostra le stringhe sorgente, quindi testa loutput localizzato
con una build una tantum.
</Note>
I figli di testo di `<Trans>` possono estendersi su più righe — gli spazi bianchi vengono compressi
nello stesso modo in cui JSX li comprime, quindi `<Trans>Welcome\n back</Trans>` e la chiave estratta
diventano entrambi `Welcome back`.
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "Operazioni"
},
"appsTranslations": {
"label": "Traduzioni"
}
}
},
@@ -0,0 +1,109 @@
---
title: 翻訳
description: 複数の言語でアプリを提供できます — 単一の locales カタログで、マニフェストのラベルと UI 文字列を翻訳します。
icon: language
---
Twenty のアプリは **英語** で作成されています。ソースやマニフェスト内の文字列は英語のソーステキストであり、`en` は翻訳の元となるソースロケールです。未翻訳のロケールは `en` にフォールバックします。
アプリには 2 種類の翻訳可能なテキストがあり、どちらも同じ `locales/` カタログを通じて処理されます。
* **Manifest labels** — オブジェクト名とフィールド名、ビュータイトル、メニュー項目、その他アプリのメタデータで宣言される文字列。
* **Front-component strings** — React のフロントコンポーネントがレンダリングするUIテキスト。
翻訳可能な文字列にマークを付けてロケールごとのカタログに抽出し、それらのカタログを翻訳すれば、ビルドが現在のユーザーに適切な言語を提供します — 追加の設定は不要です。
## フロントコンポーネント文字列のマーク
`20-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>
);
};
```
### When to use which
* **`<Trans>…</Trans>`** — JSX の静的テキスト。 `message` と `values`
プロパティを使用して補間(`<Trans message="Hi {name}" values={{ name }} />`); 子要素に直接補間する
は静的に抽出できません。
* **`useTranslate().t`** — コンポーネント内の動的文字列。
ユーザーが言語を切り替えたときに再レンダリングします。 これをレンダリング内で好みます。
* **`t(...)`** (imported directly) — eager translation used **anywhere** ,
including event handlers, helpers, module scope — だけでなく、render内だけでなく。
* **`msg(...)`** — dataとして宣言された文字列の遅延記述子 (定数、
config)。 後で`t(descriptor)`で解決します。
### コンテキスト
異なる変換元文字列を曖昧にするために `context` を渡します。
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
## 抽出と翻訳
アプリディレクトリから抽出コマンドを実行します。
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
抽出処理では、マニフェストのラベルとフロントコンポーネントのソース内にある `t()`/`msg()`/`\<Trans>` の文字列の両方が収集され、ソース文字列をキーとして `locales/\<locale>.json` にまとめられます。 翻訳を入力:
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées"
}
```
`{name}`のようなプレースホルダは、実行時に置き換えられます —
翻訳でそれらを維持します。 空の文字列はすべて元のテキストに戻ります。
## 動作方法
`twenty dev:build` はカタログをコンパイルし、現在のユーザーに対して適切な言語を提供します。マニフェストのラベルはサーバー側で解決され、フロントコンポーネントのカタログは各コンポーネントバンドルに組み込まれます。 実行時には、コンポーネントが実行コンテキスト(ホストの現在の言語)からロケールを読み取り、そのカタログに対して各文字列を解決し、翻訳が存在しない場合はソースにフォールバックします。 ホストの再レンダリングで言語を切り替えます。`\<Trans>` と
`useTranslate().t` 文字列は動作します。
カタログはビルド時にコンパイルされるため、翻訳を更新すると、他の変更と同じように、
`20dev:build` を再実行(および再デプロイ)することになります。
<Note>
翻訳は `20dev:build` によってコンパイルされています (そして、`20の適用`)。
連続した `20dev` ウォッチはソース文字列を表示するため、ワンオフビルドでローカライズされた出力
をテストします。
</Note>
`<Trans>` のテキスト子要素は複数行にまたがってもかまいません — 空白は JSX と同じように折りたたまれるため、`<Trans>Welcome\n back</Trans>` と抽出されたキーはどちらも `Welcome back` になります。
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "オペレーション"
},
"appsTranslations": {
"label": "翻訳"
}
}
},
@@ -0,0 +1,111 @@
---
title: 번역
description: 여러 언어로 앱을 출시하세요 — 단일 로케일 카탈로그에서 매니페스트 레이블과 UI 문자열을 번역하세요.
icon: language
---
Twenty 앱은 **영어**로 작성됩니다. 소스와 매니페스트의 문자열은 영어 원문이며, `en`은 번역의 기준이 되는 소스 로케일입니다. 번역되지 않은 로케일은 `en`을 기본값으로 사용합니다.
앱에는 두 가지 유형의 번역 가능한 텍스트가 있으며, 둘 다 동일한 `locales/` 카탈로그를 통해 처리됩니다.
* **매니페스트 레이블** — 오브젝트와 필드 이름, 뷰 제목, 메뉴 항목 및 앱 메타데이터에 선언된 기타 문자열.
* **Front-component 문자열** — React 프론트 컴포넌트가 렌더링하는 UI 텍스트입니다.
번역 가능한 문자열에 표시를 하고, 이를 로캘별 카탈로그로 추출한 뒤,
그 카탈로그들을 번역하면, 빌드가 현재 사용자에게 맞는 언어를 제공하므로
별도의 추가 작업이 필요 없습니다.
## Front-component 문자열 표시하기
`twenty-sdk/front-component`에서 번역 헬퍼를 import 하세요:
```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>
);
};
```
### 언제 무엇을 사용할지
* **`<Trans>…</Trans>`** — JSX 안의 정적 텍스트입니다. 보간을 위해 `message` 및 `values`
props를 사용하세요 (`<Trans message="Hi {name}" values={{ name }} />`);
children 안에서 직접 보간하는 것은 정적으로 추출할 수 없습니다.
* **`useTranslate().t`** — 컴포넌트 내부에서 사용하는 동적 문자열입니다. 사용자가 언어를 전환하면
다시 렌더링됩니다. render 내부에서는 이것을 사용하는 것을 권장합니다.
* **`t(...)`** (직접 import) — 이벤트 핸들러, 헬퍼, 모듈 스코프 등
render 내부뿐만 아니라 **어디서든** 사용할 수 있는 즉시 번역 함수입니다.
* **`msg(...)`** — 데이터(상수, 설정)로 선언된 문자열을 위한 지연 평가용 서술자입니다. 나중에 `t(descriptor)`로 이를 해석하세요.
### 컨텍스트
서로 다른 방식으로 번역되는 동일한 소스 문자열을 구분하기 위해 `context`를 전달하세요:
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
## 추출 및 번역
앱 디렉터리에서 extract 명령을 실행하세요:
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
추출 과정에서는 manifest 레이블과 front-component 소스의 `t()`/`msg()`/`\<Trans>`
문자열을 모두 `locales/\<locale>.json` 파일에 소스 문자열을 키로 하여 수집합니다. 번역을 채워 넣으세요:
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées"
}
```
`{name}`과 같은 플레이스홀더는 런타임에 치환되므로 — 번역문에도 그대로 유지해야 합니다. 비워 둔 문자열은 소스 텍스트를 그대로 사용합니다.
## 실행 방식
`twenty dev:build`는 카탈로그를 컴파일하고 현재 사용자에게 맞는 언어를 제공합니다.
manifest 레이블은 서버 측에서 처리되고, front-component 카탈로그는 각 컴포넌트 번들에 내장됩니다. 런타임에는 컴포넌트가 실행 컨텍스트(호스트의 현재 언어)에서 로케일을 읽고, 각 문자열을 해당 카탈로그에서 찾아 해석하며, 번역이 없으면 소스 텍스트로 대체합니다. 호스트에서 언어를 전환하면 `\<Trans>`와
`useTranslate().t` 문자열이 실시간으로 다시 렌더링됩니다.
카탈로그는 빌드 시점에 컴파일되므로, 번역을 업데이트하려면
`twenty dev:build`를 다시 실행하고(및 재배포) 다른 변경 사항과 마찬가지로 처리해야 합니다.
<Note>
번역은 `twenty dev:build`(및 `twenty apply`)에 의해 컴파일됩니다. 연속 실행되는 `twenty dev` watch에서는 소스 문자열이 표시되므로,
로컬라이즈된 출력을 테스트하려면 일회성 빌드를 수행하세요.
</Note>
`<Trans>`의 텍스트 children은 여러 줄에 걸쳐 있을 수 있으며 — 공백은 JSX에서와 동일한 방식으로
축약되므로, `<Trans>Welcome\n back</Trans>`과 추출된 key는 모두 `Welcome back`이 됩니다.
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "작업"
},
"appsTranslations": {
"label": "번역"
}
}
},
@@ -0,0 +1,125 @@
---
title: Traduções
description: Publique seu aplicativo em vários idiomas — traduza rótulos do manifesto e strings da interface do usuário por meio de um único catálogo de localidades.
icon: language
---
Os aplicativos Twenty são escritos em **inglês**: as strings no seu código-fonte e no manifesto
são o texto-fonte em inglês, `en` é a localidade de origem a partir da qual você traduz, e
qualquer localidade deixada sem tradução reverte para essa localidade.
Seu aplicativo tem dois tipos de texto traduzível, e ambos passam pelo mesmo
catálogo `locales/`:
* **Rótulos do manifesto** — nomes de objetos e campos, títulos de exibição, itens de menu e
outras strings declaradas nos metadados do seu aplicativo.
* **Front-component strings** — A interface do usuário que processa seus componentes frontais do React.
Você marca as strings traduzíveis, extraa-as em catálogos por localidade,
traduza os catálogos, e a compilação serve a linguagem certa para o usuário atual
— sem asas extras.
## Marcando strings front-component
Importe os auxiliares de tradução de `vinte e 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>
);
};
```
### Quando usar qual
* **`<Trans>…</Trans>`** — texto estático em JSX. Use as propriedades `message` e`values`
para interpolação (`<Trans message="Hi {name}" values={{ name }} />`);
interpolar diretamente nos filhos não é estaticamente extracurável.
* **`useTranslate().t`** — strings dinâmicas dentro de um componente. Rerenderiza quando o usuário
muda de linguagem. Prefere isso dentro de renderização.
* **`t(...)`** (importado diretamente) — tradução ávida utilizável **em qualquer lugar**,
incluindo manipuladores de eventos, auxiliares e escopo de módulo — não apenas dentro de renderização.
* **`msg(...)`** — um descritor preguiçoso para frases declaradas como dados (constantes,
config). Resolva-o mais tarde com `t(descriptor)`.
### Contexto
Passe `context` para desambiguar sequências de caracteres de origem idênticas que traduzem
de forma diferente:
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
## Extraindo e traduzindo
Execute o comando extracto a partir do diretório do seu aplicativo:
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
Extração coleta as duas strings do seu manifesto e `t()`/`msg()`/`\<Trans>
do código do seu front-component em `locales/\<locale>. son\`, chave por
string de origem. Preencha as traduções:
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées"
}
```
Espaços reservados como `{name}` são substituídos no tempo de execução — mantenha-os na tradução
. Qualquer cadeia de caracteres deixada vazia retorna ao texto de origem.
## Como ele funciona
`twenty dev:build` compila os catálogos e fornece o idioma correto para o
usuário atual: os rótulos do manifesto são resolvidos no lado do servidor e os catálogos de componentes de front-end
são incorporados em cada pacote de componente. No tempo de execução, um componente lê a localidade
de seu contexto de execução (o idioma atual do host) e resolve
cada seqüência de caracteres contra seu catálogo, voltando à fonte quando uma tradução
estiver faltando. Mudar idioma no host renderiza novamente as strings `\<Trans>e
`useTranslate().t\` ao vivo.
Como os catálogos são compilados no tempo de construção, atualizar uma tradução significa
reexecutar `vinte dev:build` (e redistribuir), o mesmo que qualquer outra mudança.
<Note>
As traduções são compiladas por `vinte dev:build` (e `vinte aplicam`). O relógio
contínuo `vinte dev` mostra strings de origem, então teste saída localizada
com uma compilação única.
</Note>
`<Trans>` Crianças de texto podem span várias linhas — espaço em branco é recolhido o
da mesma forma que JSX o colapsa, so `<Trans>Bem-vindo\n de volta</Trans>` e a chave extraída
ambas se tornam `Bem-vindo de volta`.
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "Operações"
},
"appsTranslations": {
"label": "Traduções"
}
}
},
@@ -0,0 +1,124 @@
---
title: Traduceri
description: Lansează-ți aplicația în mai multe limbi — tradu etichetele din manifest și șirurile UI printr-un singur catalog de locale.
icon: language
---
Aplicațiile Twenty sunt create în **engleză**: șirurile din sursă și din manifest
sunt textul sursă în engleză, `en` este localizarea sursă din care traduci, iar
orice localizare lăsată netradusă revine implicit la aceasta.
Aplicația ta are două tipuri de text traducibil și ambele trec prin același
catalog `locales/`:
* **Etichete de manifest** — nume de obiecte și câmpuri, titluri de vizualizări, elemente de meniu și
alte șiruri declarate în metadatele aplicației tale.
* **Șiruri componentă-față** - textul UI al componentelor dvs. React din față.
Marchează șirurile traduse, le extrag în cataloage per-localizare,
traduce acele cataloage, iar clădirea servește limba corectă pentru utilizatorul curent* fără cableri suplimentare.
## Marcarea sirurilor componentei frontale
Importă ajutătoarele de traducere din `douăzeci de aplicații/front-componente`:
```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>
);
};
```
### Când să utilizaţi care
* **`<Trans>…</Trans>`** — text static în JSX. Utilizaţi `message` şi `values`
props pentru interpolare (`<Trans message="Hi {name}" values={{ name }} />`);
interpolând direct la copii nu poate fi extras static.
* **`useTranslate().t`** - șiruri dinamice în interiorul unei componente. Re-randează atunci când utilizatorul
schimbă limba. Preferă acest lucru în redare.
* **`t(...)`** (importat direct) - traducerea mai ușoară **oriunde**,
inclusiv manipulatorii de evenimente, ajutoarele și domeniul de aplicare al modulului - nu numai în randare.
* **`msg(...)`** — un descriptor leneș pentru șiruri declarate ca date (constante,
config). Rezolvați-l mai târziu cu `t(descriptor)`.
### Context
Treceți `context` pentru a disambigua șirurile sursă identice care traduc
în mod diferit:
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
## Extragerea și traducerea
Rulează comanda de extragere din directorul aplicației:
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
Extragerea colectează atât etichetele manifestului cât şi `t()`/`msg()`/`\<Trans>`
din sursa componentei front-line în `locales/\<locale>. son`, keyed by
source string. Completează traducerile:
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées"
}
```
Localnicii ca `{name}` sunt substituiți la timp - țineți-le în traducerea
. Orice şir rămas gol se întoarce la textul sursă.
## Cum rulează
`douăzeci de dev:build` compilează cataloagele şi serveşte limba corectă pentru utilizatorul curent
: etichetele manifest sunt rezolvate pe server, iar cataloagele de tip front-component
sunt copite în fiecare pachet de componente. La runtime, o componentă citește localizarea
din contextul de execuție (limba curentă a gazdei) și rezolvă
fiecare șir din catalog, revenind la sursă atunci când lipsește o traducere
. Schimbarea limbii în șir rerandează `\<Trans>` și
șirurile `useTranslate().t` live.
Deoarece cataloagele sunt compilate la ora de construcție, actualizarea unei traduceri înseamnă
repornirea `douăzeci dev:build` (și redistribuirea), la fel ca orice altă schimbare.
<Note>
Traducerile sunt compilate de `douăzeci dev:build` (și `douăzeci apply`).
ceasul continuu `douăzeci de dev` arată șirurile sursă, așa că testează rezultatul localizat
cu o singură construcție.
</Note>
`<Trans>` text copii pot parcurge mai multe linii - spațiul alb este prăbușit
la fel cum JSX o destramă, Așa că '<Trans>Bun venit\n înapoi</Trans>' iar cheia
a fost extrasă devin 'Bine ați revenit'.
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "Operațiuni"
},
"appsTranslations": {
"label": "Traduceri"
}
}
},
@@ -0,0 +1,113 @@
---
title: Çeviriler
description: Uygulamanızı birden çok dilde yayınlayın — manifest etiketlerini ve kullanıcı arayüzü (UI) dizelerini tek bir yerel ayar kataloğu üzerinden çevirin.
icon: language
---
Twenty uygulamaları **İngilizce** olarak oluşturulur: kaynak ve manifestinizdeki dizeler İngilizce kaynak metindir, `en` çevirdiğiniz kaynak yerel ayarıdır ve çevrilmeden bırakılan herhangi bir yerel ayar buna geri döner.
Uygulamanızda iki tür çevrilebilir metin vardır ve her ikisi de aynı `locales/` kataloğundan geçer:
* **Manifest etiketleri** — nesne ve alan adları, görünüm başlıkları, menü öğeleri ve uygulamanızın üst verilerinde (metadata) tanımlanan diğer dizeler.
* **Ön bileşen dizeleri** — React ön bileşenlerinizin render ettiği UI metni.
Çevrilebilir dizeleri işaretlersiniz, bunları yerel başına kataloglara çıkarırsınız,
bu katalogları çevirirsiniz ve build, geçerli kullanıcı için
herhangi bir ek bağlantıya gerek kalmadan doğru dili sunar.
## Ön bileşen dizelerini işaretleme
Çeviri yardımcılarını `twenty-sdk/front-component` içinden içe aktarın:
```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>
);
};
```
### Ne zaman hangisi kullanılmalı
* **`<Trans>…</Trans>`** — JSX içindeki statik metin. Değişkelerin (`<Trans message="Hi {name}" values={{ name }} />`) yerleştirilmesi için `message` ve `values`
prop'larını kullanın;
çocukların içine doğrudan yerleştirme statik olarak çıkarılamaz.
* **`useTranslate().t`** — bir bileşen içindeki dinamik dizeler. Kullanıcı dili değiştirdiğinde
yeniden render edilir. Render içinde bunu tercih edin.
* **`t(...)`** (doğrudan içe aktarılır) — bileşen render'ının içinde olmasına gerek olmadan,
event handler'lar, yardımcı fonksiyonlar ve modül kapsamı dahil **her yerde** kullanılabilen erken çeviri.
* **`msg(...)`** — veri olarak (sabitler, yapılandırma) bildirilen dizeler için ertelenmiş bir tanımlayıcı. Bunu daha sonra `t(descriptor)` ile çözün.
### Bağlam
Aynı kaynak dize farklı şekilde çevrildiğinde bunları ayırt etmek için `context` geçirin:
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
## Çıkarma ve çeviri
extract komutunu uygulama dizininizden çalıştırın:
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
Çıkarma işlemi, manifest etiketlerinizi ve ön bileşen kaynaklarınızdan gelen `t()`/`msg()`/`\<Trans>`
dizelerini, kaynak dizeyi anahtar olarak kullanarak `locales/\<locale>.json` içine toplar. Çevirileri doldurun:
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées"
}
```
`{name}` gibi yer tutucular çalışma zamanında değiştirilir — bunları çeviride koruyun. Boş bırakılan herhangi bir dize, kaynak metne geri döner.
## Nasıl çalışır
`twenty dev:build`, katalogları derler ve geçerli kullanıcı için doğru dili sunar:
manifest etiketleri sunucu tarafında çözülür ve ön bileşen
katalogları her bileşen paketine gömülür. Çalışma zamanında bir bileşen, yereli yürütme bağlamından (ana makinenin geçerli dili) okur
ve her dizeyi kataloğuna göre çözer; bir çeviri eksik olduğunda
kaynak metne geri döner. Ana makinede dilin değiştirilmesi, `\<Trans>` ve
`useTranslate().t` dizelerini canlı olarak yeniden render eder.
Kataloglar build zamanında derlendiği için, bir çeviriyi güncellemek
`twenty dev:build`'i yeniden çalıştırmayı (ve yeniden dağıtmayı) gerektirir; bu, diğer herhangi bir değişiklikle aynıdır.
<Note>
Çeviriler `twenty dev:build` (ve `twenty apply`) tarafından derlenir. Sürekli
`twenty dev` izlemesi kaynak dizeleri gösterir, bu yüzden yerelleştirilmiş çıktıyı tek seferlik bir build ile test edin.
</Note>
`<Trans>` metin alt öğeleri birden fazla satıra yayılabilir — boşluklar, JSX'in boşlukları daraltma biçimiyle aynı şekilde daraltılır; bu nedenle hem `<Trans>Welcome\n back</Trans>` hem de çıkarılan anahtar `Welcome back` olur.
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "İşlemler"
},
"appsTranslations": {
"label": "Çeviriler"
}
}
},
@@ -0,0 +1,102 @@
---
title: 翻译
description: 以多种语言发布你的应用——通过一个 locales 目录翻译 manifest 标签和 UI 字符串。
icon: language
---
Twenty 应用均以**英文**编写:你的源码和 manifest 中的字符串
是英文源文本,`en` 是你进行翻译时的源语言环境,任何未被翻译的语言环境都会回退到它。
你的应用有两类可翻译文本,并且它们都通过同一个
`locales/` 目录:
* **Manifest labels** —— 对象和字段名称、视图标题、菜单项,以及
在应用元数据中声明的其他字符串。
* **前端组件字符串** —— 你的 React 前端组件渲染的 UI 文本。
你标记可翻译字符串,将它们提取到按语言环境划分的目录中,翻译这些目录,然后构建过程会为当前用户提供正确的语言——不需要额外的接线。
## 标记前端组件字符串
从 `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>
);
};
```
### 何时使用哪一种
* **`<Trans>…</Trans>`** —— JSX 中的静态文本。 使用 `message` 和 `values` 属性进行插值(`<Trans message="Hi {name}" values={{ name }} />`);直接在子节点中插值无法被静态提取。
* **`useTranslate().t`** —— 组件内部的动态字符串。 当用户切换语言时会重新渲染。 在渲染逻辑中优先使用这个。
* **`t(...)`**(直接导入)—— 可在**任何地方**使用的即时翻译,包括事件处理函数、辅助函数和模块作用域——不仅仅在渲染逻辑中。
* **`msg(...)`** —— 以数据形式(常量、配置)声明字符串的惰性描述符。 在之后通过 `t(descriptor)` 来解析它。
### 上下文
传入 `context` 以区分那些来源字符串相同但翻译不同的情况:
```tsx
t({ message: 'Open', context: 'door' });
t({ message: 'Open', context: 'window' });
<Trans context="card-title">Untitled</Trans>
```
## 提取和翻译
在你的应用目录中运行提取命令:
```bash
twenty dev:translations-extract # collect strings into locales/en.json
twenty dev:translations-extract --locale fr-FR # also scaffold a target locale
```
提取会收集你的 manifest 标签以及前端组件源码中的 `t()`/`msg()`/`\<Trans>` 字符串,并将它们放入 `locales/\<locale>.json` 中,以源字符串作为键。 填写翻译:
```json
// locales/fr-FR.json
{
"Loading postcard…": "Chargement de la carte…",
"Hi {name}": "Bonjour {name}",
"Saved {count} cards": "{count} cartes enregistrées"
}
```
像 `{name}` 这样的占位符会在运行时被替换——请在翻译中保留它们。 任何留空的字符串都会回退到源文本。
## 运行方式
`twenty dev:build` 会编译目录并为当前用户提供正确的语言:manifest 标签在服务端解析,前端组件目录被打包进每个组件 bundle 中。 在运行时,组件会从其执行上下文(宿主的当前语言)中读取语言环境,并将每个字符串在其目录中解析,当翻译缺失时回退到源文本。 在宿主中切换语言会实时重新渲染 `\<Trans>` 和 `useTranslate().t` 的字符串。
由于目录在构建时被编译,更新翻译意味着需要重新运行 `twenty dev:build`(并重新部署),这和其他任何更改一样。
<Note>
翻译由 `twenty dev:build`(以及 `twenty apply`)编译。 持续运行的 `twenty dev` 监视会显示源字符串,因此请使用一次性构建来测试本地化输出。
</Note>
`<Trans>` 的文本子节点可以跨多行——空白会以与 JSX 相同的方式被折叠,因此 `<Trans>Welcome\n back</Trans>` 和提取出的键都会变成 `Welcome back`。
@@ -174,6 +174,9 @@
},
"appsOperations": {
"label": "操作"
},
"appsTranslations": {
"label": "翻译"
}
}
},