From 15c0c3b773cd0d35ebfacbeef6c0d37afc1e86f0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 19:14:28 +0200 Subject: [PATCH] i18n - docs translations (#22413) Created by Github action Review in cubic Co-authored-by: github-actions --- packages/twenty-docs/docs.json | 72 ++++++++++ .../extend/apps/translations/overview.mdx | 118 +++++++++++++++++ packages/twenty-docs/l/ar/navigation.json | 3 + .../extend/apps/translations/overview.mdx | 121 +++++++++++++++++ packages/twenty-docs/l/cs/navigation.json | 3 + .../extend/apps/translations/overview.mdx | 125 ++++++++++++++++++ packages/twenty-docs/l/de/navigation.json | 3 + .../extend/apps/translations/overview.mdx | 120 +++++++++++++++++ packages/twenty-docs/l/es/navigation.json | 3 + .../extend/apps/translations/overview.mdx | 125 ++++++++++++++++++ packages/twenty-docs/l/fr/navigation.json | 3 + .../extend/apps/translations/overview.mdx | 124 +++++++++++++++++ packages/twenty-docs/l/it/navigation.json | 3 + .../extend/apps/translations/overview.mdx | 109 +++++++++++++++ packages/twenty-docs/l/ja/navigation.json | 3 + .../extend/apps/translations/overview.mdx | 111 ++++++++++++++++ packages/twenty-docs/l/ko/navigation.json | 3 + .../extend/apps/translations/overview.mdx | 125 ++++++++++++++++++ packages/twenty-docs/l/pt/navigation.json | 3 + .../extend/apps/translations/overview.mdx | 124 +++++++++++++++++ packages/twenty-docs/l/ro/navigation.json | 3 + .../extend/apps/translations/overview.mdx | 113 ++++++++++++++++ packages/twenty-docs/l/tr/navigation.json | 3 + .../extend/apps/translations/overview.mdx | 102 ++++++++++++++ packages/twenty-docs/l/zh/navigation.json | 3 + 25 files changed, 1525 insertions(+) create mode 100644 packages/twenty-docs/l/ar/developers/extend/apps/translations/overview.mdx create mode 100644 packages/twenty-docs/l/cs/developers/extend/apps/translations/overview.mdx create mode 100644 packages/twenty-docs/l/de/developers/extend/apps/translations/overview.mdx create mode 100644 packages/twenty-docs/l/es/developers/extend/apps/translations/overview.mdx create mode 100644 packages/twenty-docs/l/fr/developers/extend/apps/translations/overview.mdx create mode 100644 packages/twenty-docs/l/it/developers/extend/apps/translations/overview.mdx create mode 100644 packages/twenty-docs/l/ja/developers/extend/apps/translations/overview.mdx create mode 100644 packages/twenty-docs/l/ko/developers/extend/apps/translations/overview.mdx create mode 100644 packages/twenty-docs/l/pt/developers/extend/apps/translations/overview.mdx create mode 100644 packages/twenty-docs/l/ro/developers/extend/apps/translations/overview.mdx create mode 100644 packages/twenty-docs/l/tr/developers/extend/apps/translations/overview.mdx create mode 100644 packages/twenty-docs/l/zh/developers/extend/apps/translations/overview.mdx diff --git a/packages/twenty-docs/docs.json b/packages/twenty-docs/docs.json index 21351e52e6..92473df237 100644 --- a/packages/twenty-docs/docs.json +++ b/packages/twenty-docs/docs.json @@ -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" + ] } ] }, diff --git a/packages/twenty-docs/l/ar/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/ar/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..5a87f8520f --- /dev/null +++ b/packages/twenty-docs/l/ar/developers/extend/apps/translations/overview.mdx @@ -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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} + +
+ ); +}; +``` + +### متى تستخدم أيًّا منها + +* **``** — نص ثابت في JSX. استخدم الخاصيتين `message` و`values` + من أجل الاستبدال (interpolation) (``); + لا يمكن استخراج الاستبدال مباشرة في العناصر الأبناء (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' }); +Untitled +``` + +## الاستخراج والترجمة + +شغِّل أمر الاستخراج من دليل تطبيقك: + +```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()`/`\` +من شفرة الواجهة الأمامية (front-component) إلى `locales/\.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) من سياق التنفيذ الخاص به (لغة المضيف الحالية) ويحل كل سلسلة مقابل كتالوجه، مع الرجوع إلى المصدر عندما تكون الترجمة مفقودة. تغيير اللغة في المضيف يعيد تصيير سلاسل `\` و +`useTranslate().t` مباشرة. + +نظرًا إلى أنّ الكتالوجات تُجمَّع في وقت البناء، فإن تحديث ترجمة ما يعني +إعادة تشغيل `twenty dev:build` (وإعادة النشر)، تمامًا مثل أي تغيير آخر. + + +يتم تجميع الترجمات بواسطة `twenty dev:build` (و`twenty apply`). تشغيل المراقبة المستمرة `twenty dev` +يعرض سلاسل المصدر، لذا اختبر المخرجات المترجمة ببناء (build) لمرة واحدة. + + +قد تمتد عناصر النص التابعة لـ `` على عدة أسطر — يتم ضغط المسافات +بنفس الطريقة التي يقوم JSX بضغطها، لذلك كل من `Welcome\n back` +ومفتاح الاستخراج يصبحان `Welcome back`. diff --git a/packages/twenty-docs/l/ar/navigation.json b/packages/twenty-docs/l/ar/navigation.json index 6459fff16c..241bad3391 100644 --- a/packages/twenty-docs/l/ar/navigation.json +++ b/packages/twenty-docs/l/ar/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "العمليات" + }, + "appsTranslations": { + "label": "الترجمات" } } }, diff --git a/packages/twenty-docs/l/cs/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/cs/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..72d2b10aa7 --- /dev/null +++ b/packages/twenty-docs/l/cs/developers/extend/apps/translations/overview.mdx @@ -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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} +
    {STATUSES.map((s) =>
  • {t(s.label)}
  • )}
+
+ ); +}; +``` + +### Kdy co použít + +* **``** — statický text v JSX. Použijte props `message` a `values` + pro interpolaci (``); + 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' }); +Untitled +``` + +## 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()`/`\` +z vašeho zdrojového kódu front komponent do `locales/\.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 `\` 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. + + +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. + + +Potomci `` 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 `Welcome\n back` i extrahovaný +klíč se oba stanou `Welcome back`. diff --git a/packages/twenty-docs/l/cs/navigation.json b/packages/twenty-docs/l/cs/navigation.json index 796d5edacb..a9e5c1c8fe 100644 --- a/packages/twenty-docs/l/cs/navigation.json +++ b/packages/twenty-docs/l/cs/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "Operace" + }, + "appsTranslations": { + "label": "Překlady" } } }, diff --git a/packages/twenty-docs/l/de/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/de/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..90cadf7efa --- /dev/null +++ b/packages/twenty-docs/l/de/developers/extend/apps/translations/overview.mdx @@ -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 Quell‑Locale, 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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} +
    {STATUSES.map((s) =>
  • {t(s.label)}
  • )}
+
+ ); +}; +``` + +### Wann Sie was verwenden sollten + +* **``** – statischer Text in JSX. Verwenden Sie die Props `message` und `values` + zur Interpolation (``); + 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' }); +Untitled +``` + +## 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()`-/`\`- +Zeichenketten aus Ihrem Front-Component-Quellcode in `locales/\.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 `\`- 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. + + +Ü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. + + +``-Text-Children können sich über mehrere Zeilen erstrecken – Leerzeichen werden auf dieselbe Weise zusammengefasst, +wie JSX sie zusammenfasst, sodass sowohl `Welcome\n back` als auch der extrahierte +Schlüssel `Welcome back` werden. diff --git a/packages/twenty-docs/l/de/navigation.json b/packages/twenty-docs/l/de/navigation.json index 4593b6dab3..a886e5b507 100644 --- a/packages/twenty-docs/l/de/navigation.json +++ b/packages/twenty-docs/l/de/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "Operationen" + }, + "appsTranslations": { + "label": "Übersetzungen" } } }, diff --git a/packages/twenty-docs/l/es/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/es/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..4d6bccffab --- /dev/null +++ b/packages/twenty-docs/l/es/developers/extend/apps/translations/overview.mdx @@ -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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} +
    {STATUSES.map((s) =>
  • {t(s.label)}
  • )}
+
+ ); +}; +``` + +### Cuándo usar qué + +* **``** — texto estático en JSX. Usa los accesorios `message` y `values` + para la interpolación (``); + 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' }); +Untitled +``` + +## 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()`/`\` +cadenas de tu fuente de componentes front-front en `locales/\. 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 `\` 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. + + +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. + + +`` 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 `Bienvenido\n de vuelta` y la clave +extraída se convierten en `Welcome back`. diff --git a/packages/twenty-docs/l/es/navigation.json b/packages/twenty-docs/l/es/navigation.json index fba951d368..a441011ae1 100644 --- a/packages/twenty-docs/l/es/navigation.json +++ b/packages/twenty-docs/l/es/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "Operaciones" + }, + "appsTranslations": { + "label": "Traducciones" } } }, diff --git a/packages/twenty-docs/l/fr/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/fr/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..968ef600c2 --- /dev/null +++ b/packages/twenty-docs/l/fr/developers/extend/apps/translations/overview.mdx @@ -0,0 +1,125 @@ +--- +title: Traductions +description: Publiez votre application en plusieurs langues — traduisez les libellés du manifeste et les chaînes d’interface 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 d’objets 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 d’interface 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 +l’utilisateur 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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} +
    {STATUSES.map((s) =>
  • {t(s.label)}
  • )}
+
+ ); +}; +``` + +### Quand utiliser quoi + +* **``** — texte statique dans JSX. Utilisez les props `message` et `values` + pour l’interpolation (``) ; + l’interpolation directement dans les enfants n’est pas extractible statiquement. +* **`useTranslate().t`** — chaînes dynamiques à l’intérieur d’un composant. Se réaffiche lorsque + l’utilisateur change de langue. À privilégier à l’inté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 l’ambiguïté entre des chaînes source identiques qui se traduisent +différemment : + +```tsx +t({ message: 'Open', context: 'door' }); +t({ message: 'Open', context: 'window' }); +Untitled +``` + +## Extraction et traduction + +Exécutez la commande d’extraction 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 +``` + +L’extraction collecte à la fois les libellés de votre manifeste et les chaînes `t()`/`msg()`/`\` +provenant de votre source front-component dans `locales/\.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 à l’exé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 +l’utilisateur 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 `\` 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. + + +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. + + +Les enfants texte de `` peuvent s’étendre sur plusieurs lignes — les espaces sont compressés de +la même façon que JSX les compresse, donc `Welcome\n back` et la clé extraite +deviendront toutes deux `Welcome back`. diff --git a/packages/twenty-docs/l/fr/navigation.json b/packages/twenty-docs/l/fr/navigation.json index cb5907ec8e..00aaeea21d 100644 --- a/packages/twenty-docs/l/fr/navigation.json +++ b/packages/twenty-docs/l/fr/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "Opérations" + }, + "appsTranslations": { + "label": "Traductions" } } }, diff --git a/packages/twenty-docs/l/it/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/it/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..ce72615183 --- /dev/null +++ b/packages/twenty-docs/l/it/developers/extend/apps/translations/overview.mdx @@ -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 dell’interfaccia 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 l’utente +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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} +
    {STATUSES.map((s) =>
  • {t(s.label)}
  • )}
+
+ ); +}; +``` + +### Quando usare cosa + +* **``** — testo statico in JSX. Usa le prop `message` e `values` + per l’interpolazione (``); + l’interpolazione direttamente nei children non è estraibile staticamente. +* **`useTranslate().t`** — stringhe dinamiche all’interno di un componente. Esegue il re-render quando + l’utente cambia lingua. Preferiscilo all’interno del render. +* **`t(...)`** (importato direttamente) — traduzione eager utilizzabile **ovunque**, + inclusi gestori di eventi, helper e nello scope del modulo — non solo all’interno 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' }); +Untitled +``` + +## 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 +``` + +L’estrazione raccoglie sia le etichette del manifest sia le stringhe `t()`/`msg()`/`\` +dal sorgente dei tuoi front-component in `locales/\.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 l’utente +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 dell’host) e risolve +ogni stringa rispetto al proprio catalogo, facendo fallback alla sorgente quando +una traduzione manca. Il cambio di lingua nell’host esegue il re-render delle stringhe `\` 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. + + +Le traduzioni vengono compilate da `twenty dev:build` (e `twenty apply`). La modalità watch continua di `twenty dev` mostra le stringhe sorgente, quindi testa l’output localizzato +con una build una tantum. + + +I figli di testo di `` possono estendersi su più righe — gli spazi bianchi vengono compressi +nello stesso modo in cui JSX li comprime, quindi `Welcome\n back` e la chiave estratta +diventano entrambi `Welcome back`. diff --git a/packages/twenty-docs/l/it/navigation.json b/packages/twenty-docs/l/it/navigation.json index 4db2cbeb1e..7a4475013b 100644 --- a/packages/twenty-docs/l/it/navigation.json +++ b/packages/twenty-docs/l/it/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "Operazioni" + }, + "appsTranslations": { + "label": "Traduzioni" } } }, diff --git a/packages/twenty-docs/l/ja/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/ja/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..f035835b61 --- /dev/null +++ b/packages/twenty-docs/l/ja/developers/extend/apps/translations/overview.mdx @@ -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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} +
    {STATUSES.map((s) =>
  • {t(s.label)}
  • )}
+
+ ); +}; +``` + +### When to use which + +* **``** — JSX の静的テキスト。 `message` と `values` + プロパティを使用して補間(``); 子要素に直接補間する + は静的に抽出できません。 +* **`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' }); +Untitled +``` + +## 抽出と翻訳 + +アプリディレクトリから抽出コマンドを実行します。 + +```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()`/`\` の文字列の両方が収集され、ソース文字列をキーとして `locales/\.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` はカタログをコンパイルし、現在のユーザーに対して適切な言語を提供します。マニフェストのラベルはサーバー側で解決され、フロントコンポーネントのカタログは各コンポーネントバンドルに組み込まれます。 実行時には、コンポーネントが実行コンテキスト(ホストの現在の言語)からロケールを読み取り、そのカタログに対して各文字列を解決し、翻訳が存在しない場合はソースにフォールバックします。 ホストの再レンダリングで言語を切り替えます。`\` と +`useTranslate().t` 文字列は動作します。 + +カタログはビルド時にコンパイルされるため、翻訳を更新すると、他の変更と同じように、 +`20dev:build` を再実行(および再デプロイ)することになります。 + + +翻訳は `20dev:build` によってコンパイルされています (そして、`20の適用`)。 +連続した `20dev` ウォッチはソース文字列を表示するため、ワンオフビルドでローカライズされた出力 +をテストします。 + + +`` のテキスト子要素は複数行にまたがってもかまいません — 空白は JSX と同じように折りたたまれるため、`Welcome\n back` と抽出されたキーはどちらも `Welcome back` になります。 diff --git a/packages/twenty-docs/l/ja/navigation.json b/packages/twenty-docs/l/ja/navigation.json index 5aa87d0252..f87cd55f91 100644 --- a/packages/twenty-docs/l/ja/navigation.json +++ b/packages/twenty-docs/l/ja/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "オペレーション" + }, + "appsTranslations": { + "label": "翻訳" } } }, diff --git a/packages/twenty-docs/l/ko/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/ko/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..9dcd5286e1 --- /dev/null +++ b/packages/twenty-docs/l/ko/developers/extend/apps/translations/overview.mdx @@ -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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} +
    {STATUSES.map((s) =>
  • {t(s.label)}
  • )}
+
+ ); +}; +``` + +### 언제 무엇을 사용할지 + +* **``** — JSX 안의 정적 텍스트입니다. 보간을 위해 `message` 및 `values` + props를 사용하세요 (``); + children 안에서 직접 보간하는 것은 정적으로 추출할 수 없습니다. +* **`useTranslate().t`** — 컴포넌트 내부에서 사용하는 동적 문자열입니다. 사용자가 언어를 전환하면 + 다시 렌더링됩니다. render 내부에서는 이것을 사용하는 것을 권장합니다. +* **`t(...)`** (직접 import) — 이벤트 핸들러, 헬퍼, 모듈 스코프 등 + render 내부뿐만 아니라 **어디서든** 사용할 수 있는 즉시 번역 함수입니다. +* **`msg(...)`** — 데이터(상수, 설정)로 선언된 문자열을 위한 지연 평가용 서술자입니다. 나중에 `t(descriptor)`로 이를 해석하세요. + +### 컨텍스트 + +서로 다른 방식으로 번역되는 동일한 소스 문자열을 구분하기 위해 `context`를 전달하세요: + +```tsx +t({ message: 'Open', context: 'door' }); +t({ message: 'Open', context: 'window' }); +Untitled +``` + +## 추출 및 번역 + +앱 디렉터리에서 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()`/`\` +문자열을 모두 `locales/\.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 카탈로그는 각 컴포넌트 번들에 내장됩니다. 런타임에는 컴포넌트가 실행 컨텍스트(호스트의 현재 언어)에서 로케일을 읽고, 각 문자열을 해당 카탈로그에서 찾아 해석하며, 번역이 없으면 소스 텍스트로 대체합니다. 호스트에서 언어를 전환하면 `\`와 +`useTranslate().t` 문자열이 실시간으로 다시 렌더링됩니다. + +카탈로그는 빌드 시점에 컴파일되므로, 번역을 업데이트하려면 +`twenty dev:build`를 다시 실행하고(및 재배포) 다른 변경 사항과 마찬가지로 처리해야 합니다. + + +번역은 `twenty dev:build`(및 `twenty apply`)에 의해 컴파일됩니다. 연속 실행되는 `twenty dev` watch에서는 소스 문자열이 표시되므로, +로컬라이즈된 출력을 테스트하려면 일회성 빌드를 수행하세요. + + +``의 텍스트 children은 여러 줄에 걸쳐 있을 수 있으며 — 공백은 JSX에서와 동일한 방식으로 +축약되므로, `Welcome\n back`과 추출된 key는 모두 `Welcome back`이 됩니다. diff --git a/packages/twenty-docs/l/ko/navigation.json b/packages/twenty-docs/l/ko/navigation.json index 1f013466e4..33f25d4bb3 100644 --- a/packages/twenty-docs/l/ko/navigation.json +++ b/packages/twenty-docs/l/ko/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "작업" + }, + "appsTranslations": { + "label": "번역" } } }, diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..44c4a38c7c --- /dev/null +++ b/packages/twenty-docs/l/pt/developers/extend/apps/translations/overview.mdx @@ -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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} +
    {STATUSES.map((s) =>
  • {t(s.label)}
  • )}
+
+ ); +}; +``` + +### Quando usar qual + +* **``** — texto estático em JSX. Use as propriedades `message` e`values` + para interpolação (``); + 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' }); +Untitled +``` + +## 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()`/`\ +do código do seu front-component em `locales/\. 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 `\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. + + +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. + + +`` Crianças de texto podem span várias linhas — espaço em branco é recolhido o +da mesma forma que JSX o colapsa, so `Bem-vindo\n de volta` e a chave extraída +ambas se tornam `Bem-vindo de volta`. diff --git a/packages/twenty-docs/l/pt/navigation.json b/packages/twenty-docs/l/pt/navigation.json index 44a268ee89..7c08118627 100644 --- a/packages/twenty-docs/l/pt/navigation.json +++ b/packages/twenty-docs/l/pt/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "Operações" + }, + "appsTranslations": { + "label": "Traduções" } } }, diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..37a479fcf6 --- /dev/null +++ b/packages/twenty-docs/l/ro/developers/extend/apps/translations/overview.mdx @@ -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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} +
    {STATUSES.map((s) =>
  • {t(s.label)}
  • )}
+
+ ); +}; +``` + +### Când să utilizaţi care + +* **``** — text static în JSX. Utilizaţi `message` şi `values` + props pentru interpolare (``); + 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' }); +Untitled +``` + +## 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()`/`\` +din sursa componentei front-line în `locales/\. 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ă `\` ș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. + + +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. + + +`` text copii pot parcurge mai multe linii - spațiul alb este prăbușit +la fel cum JSX o destramă, Așa că 'Bun venit\n înapoi' iar cheia +a fost extrasă devin 'Bine ați revenit'. diff --git a/packages/twenty-docs/l/ro/navigation.json b/packages/twenty-docs/l/ro/navigation.json index bdefb40a85..d5102765d6 100644 --- a/packages/twenty-docs/l/ro/navigation.json +++ b/packages/twenty-docs/l/ro/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "Operațiuni" + }, + "appsTranslations": { + "label": "Traduceri" } } }, diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..93cc8ceefd --- /dev/null +++ b/packages/twenty-docs/l/tr/developers/extend/apps/translations/overview.mdx @@ -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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} +
    {STATUSES.map((s) =>
  • {t(s.label)}
  • )}
+
+ ); +}; +``` + +### Ne zaman hangisi kullanılmalı + +* **``** — JSX içindeki statik metin. Değişkelerin (``) 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' }); +Untitled +``` + +## Çı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()`/`\` +dizelerini, kaynak dizeyi anahtar olarak kullanarak `locales/\.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, `\` 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. + + +Ç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. + + +`` 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 `Welcome\n back` hem de çıkarılan anahtar `Welcome back` olur. diff --git a/packages/twenty-docs/l/tr/navigation.json b/packages/twenty-docs/l/tr/navigation.json index ff91be914a..052061b3b6 100644 --- a/packages/twenty-docs/l/tr/navigation.json +++ b/packages/twenty-docs/l/tr/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "İşlemler" + }, + "appsTranslations": { + "label": "Çeviriler" } } }, diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/translations/overview.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/translations/overview.mdx new file mode 100644 index 0000000000..9a59eda4ab --- /dev/null +++ b/packages/twenty-docs/l/zh/developers/extend/apps/translations/overview.mdx @@ -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 ( +
+ {/* Static text — reactive to the user's locale */} + Loading postcard… + + {/* Disambiguate identical sources with a context */} + Untitled + + {/* Interpolation: pass values explicitly */} +

{t('Hi {name}', { name })}

+

{t('Saved {count} cards', { count })}

+ + {/* Resolve a lazily-declared descriptor */} +
    {STATUSES.map((s) =>
  • {t(s.label)}
  • )}
+
+ ); +}; +``` + +### 何时使用哪一种 + +* **``** —— JSX 中的静态文本。 使用 `message` 和 `values` 属性进行插值(``);直接在子节点中插值无法被静态提取。 +* **`useTranslate().t`** —— 组件内部的动态字符串。 当用户切换语言时会重新渲染。 在渲染逻辑中优先使用这个。 +* **`t(...)`**(直接导入)—— 可在**任何地方**使用的即时翻译,包括事件处理函数、辅助函数和模块作用域——不仅仅在渲染逻辑中。 +* **`msg(...)`** —— 以数据形式(常量、配置)声明字符串的惰性描述符。 在之后通过 `t(descriptor)` 来解析它。 + +### 上下文 + +传入 `context` 以区分那些来源字符串相同但翻译不同的情况: + +```tsx +t({ message: 'Open', context: 'door' }); +t({ message: 'Open', context: 'window' }); +Untitled +``` + +## 提取和翻译 + +在你的应用目录中运行提取命令: + +```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()`/`\` 字符串,并将它们放入 `locales/\.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 中。 在运行时,组件会从其执行上下文(宿主的当前语言)中读取语言环境,并将每个字符串在其目录中解析,当翻译缺失时回退到源文本。 在宿主中切换语言会实时重新渲染 `\` 和 `useTranslate().t` 的字符串。 + +由于目录在构建时被编译,更新翻译意味着需要重新运行 `twenty dev:build`(并重新部署),这和其他任何更改一样。 + + +翻译由 `twenty dev:build`(以及 `twenty apply`)编译。 持续运行的 `twenty dev` 监视会显示源字符串,因此请使用一次性构建来测试本地化输出。 + + +`` 的文本子节点可以跨多行——空白会以与 JSX 相同的方式被折叠,因此 `Welcome\n back` 和提取出的键都会变成 `Welcome back`。 diff --git a/packages/twenty-docs/l/zh/navigation.json b/packages/twenty-docs/l/zh/navigation.json index 82946eb3d3..e437c9477a 100644 --- a/packages/twenty-docs/l/zh/navigation.json +++ b/packages/twenty-docs/l/zh/navigation.json @@ -174,6 +174,9 @@ }, "appsOperations": { "label": "操作" + }, + "appsTranslations": { + "label": "翻译" } } },