diff --git a/apps/www/next.config.ts b/apps/www/next.config.ts index 4c4c433235..6c9430f735 100644 --- a/apps/www/next.config.ts +++ b/apps/www/next.config.ts @@ -74,6 +74,14 @@ const nextConfig = async (phase: string) => { destination: '/:path*?locale=cn', // Rewrite it to the corresponding path without /cn source: '/cn/:path*', // Match any path under /cn }, + { + destination: '/?locale=pt-br', + source: '/pt-br', + }, + { + destination: '/:path*?locale=pt-br', // Rewrite it to the corresponding path without /pt-br + source: '/pt-br/:path*', // Match any path under /pt-br + }, ]; }, diff --git a/apps/www/src/app/(app)/_components/announcement-button.tsx b/apps/www/src/app/(app)/_components/announcement-button.tsx index 6c78a86e24..690f4a6011 100644 --- a/apps/www/src/app/(app)/_components/announcement-button.tsx +++ b/apps/www/src/app/(app)/_components/announcement-button.tsx @@ -13,6 +13,9 @@ const i18n = { en: { description: 'MCP, AI, Upload, and more', }, + 'pt-br': { + description: 'MCP, IA, Upload, e mais', + }, }; export function AnnouncementButton() { diff --git a/apps/www/src/app/(app)/_components/potion-lazy-block.tsx b/apps/www/src/app/(app)/_components/potion-lazy-block.tsx index 920498cb3a..b57cb5c780 100644 --- a/apps/www/src/app/(app)/_components/potion-lazy-block.tsx +++ b/apps/www/src/app/(app)/_components/potion-lazy-block.tsx @@ -24,6 +24,13 @@ const i18n = { github: 'GitHub', potionDescription: 'A Notion-like AI template.', }, + 'pt-br': { + buildYourRichTextEditor: 'Construa seu editor de texto', + description: 'Framework · Plugins · Componentes · Temas', + getStarted: 'Começar', + github: 'GitHub', + potionDescription: 'Um template de IA similar ao Notion.', + }, }; export function PotionLazyBlock() { diff --git a/apps/www/src/app/(app)/docs/[[...slug]]/page.tsx b/apps/www/src/app/(app)/docs/[[...slug]]/page.tsx index 63e03f9559..abcfb0d7d6 100644 --- a/apps/www/src/app/(app)/docs/[[...slug]]/page.tsx +++ b/apps/www/src/app/(app)/docs/[[...slug]]/page.tsx @@ -43,23 +43,23 @@ async function getDocFromParams({ params, searchParams }: DocPageProps) { let slug = slugParam?.join('/') || ''; - // For Chinese docs, look for .cn.mdx files - if (locale === 'cn') { - // First try to find the Chinese version with .cn.mdx - const cnDoc = allDocs.find( + // For non-default locales (e.g. cn, pt-br), look for .locale.mdx files + if (locale) { + // First try to find the localized version with .locale.mdx + const localizedDoc = allDocs.find( (doc) => - doc.slugAsParams === `docs/${slug || 'index'}.cn` && - doc._raw.sourceFileName?.endsWith('.cn.mdx') + doc.slugAsParams === `docs/${slug || 'index'}.${locale}` && + doc._raw.sourceFileName?.endsWith(`.${locale}.mdx`) ); - if (cnDoc) { + if (localizedDoc) { const path = slugParam?.join('/') || ''; - cnDoc.slug = `/docs${path ? `/${path}` : ''}?locale=cn`; - return cnDoc; + localizedDoc.slug = `/docs${path ? `/${path}` : ''}?locale=${locale}`; + return localizedDoc; } } - // Default behavior for non-Chinese or fallback + // Default behavior for non-localized or fallback slug = `docs${slug ? `/${slug}` : ''}`; const doc = allDocs.find((doc) => doc.slugAsParams === slug); @@ -70,9 +70,9 @@ async function getDocFromParams({ params, searchParams }: DocPageProps) { const path = slugParam?.join('/') || ''; doc.slug = `/docs${path ? `/${path}` : ''}`; - // Only add locale param for Chinese - if (locale === 'cn') { - doc.slug += '?locale=cn'; + // Only add locale param if present + if (locale) { + doc.slug += `?locale=${locale}`; } return doc; diff --git a/apps/www/src/app/(app)/editors/editor-description.tsx b/apps/www/src/app/(app)/editors/editor-description.tsx index 5fb98e6ad0..b95f502fdd 100644 --- a/apps/www/src/app/(app)/editors/editor-description.tsx +++ b/apps/www/src/app/(app)/editors/editor-description.tsx @@ -19,6 +19,11 @@ const i18n = { description: 'Beautifully designed. Copy and paste into your apps.', title: 'Building Editors for the Web', }, + 'pt-br': { + browseEditors: 'Navegar por Editores', + description: 'Desenhado elegantemente. Copie e cole em suas aplicações.', + title: 'Construindo Editores para a Web', + }, }; export function EditorDescription() { diff --git a/apps/www/src/app/(app)/page.tsx b/apps/www/src/app/(app)/page.tsx index f9dd0c64d6..3cfe251213 100644 --- a/apps/www/src/app/(app)/page.tsx +++ b/apps/www/src/app/(app)/page.tsx @@ -34,6 +34,13 @@ const i18n = { github: 'GitHub', potionDescription: 'A Notion-like AI template.', }, + 'pt-br': { + buildYourRichTextEditor: 'Construa seu editor de texto', + description: 'Framework · Plugins · Componentes · Temas', + getStarted: 'Começar', + github: 'GitHub', + potionDescription: 'Um template de IA similar ao Notion.', + }, }; const title = 'Build your rich-text editor'; diff --git a/apps/www/src/components/languages-dropdown-menu.tsx b/apps/www/src/components/languages-dropdown-menu.tsx index 4a733334c4..9bd9ccdef0 100644 --- a/apps/www/src/components/languages-dropdown-menu.tsx +++ b/apps/www/src/components/languages-dropdown-menu.tsx @@ -16,23 +16,26 @@ export function LanguagesDropdownMenu() { const handleClick = (locale?: string) => { const url = new URL(window.location.href); + const supportedLocales = ['cn', 'pt-br']; - if (locale) { - if (pathname?.includes(locale)) { - return; - } + if (!pathname) return; + + const segments = pathname.split('/').filter((p) => !!p); + const currentLocale = supportedLocales.includes(segments[0]) + ? segments[0] + : undefined; + + // If the target locale is the same as the current, do nothing + if (locale === currentLocale) return; + + // Remove the current locale from the segments if it exists + const newSegments = currentLocale ? segments.slice(1) : segments; - url.pathname = `/${locale}${pathname}`; + if (locale) { + url.pathname = `/${locale}/${newSegments.join('/')}`; url.searchParams.set('locale', locale); } else { - if (!pathname?.includes('cn')) return; - if (pathname) { - const segments = pathname.split('/').filter((p) => !!p); - const newSegments = segments.filter((segment) => segment !== 'cn'); - url.pathname = - newSegments.length > 0 ? `/${newSegments.join('/')}` : '/'; - } - + url.pathname = `/${newSegments.join('/')}`; url.searchParams.delete('locale'); } @@ -66,6 +69,16 @@ export function LanguagesDropdownMenu() { 中文 + + + ); diff --git a/apps/www/src/components/main-nav.tsx b/apps/www/src/components/main-nav.tsx index 353df915d2..3091f66d73 100644 --- a/apps/www/src/components/main-nav.tsx +++ b/apps/www/src/components/main-nav.tsx @@ -27,6 +27,12 @@ const i18n = { editors: 'Editors', templates: 'Templates', }, + 'pt-br': { + components: 'Componentes', + docs: 'Documentação', + editors: 'Editores', + templates: 'Templates', + }, }; export function MainNav({ diff --git a/apps/www/src/components/open-in-plus.tsx b/apps/www/src/components/open-in-plus.tsx index 8b6ac58b1f..126fb47ea9 100644 --- a/apps/www/src/components/open-in-plus.tsx +++ b/apps/www/src/components/open-in-plus.tsx @@ -17,6 +17,12 @@ const i18n = { getAccess: 'Get all-access', productionReady: 'Production-ready AI template and reusable components.', }, + 'pt-br': { + buildYourEditor: 'Construa seu editor', + getAccess: 'Obtenha acesso completo', + productionReady: + 'Template de IA pronto para produção e componentes reutilizáveis.', + }, }; export function OpenInPlus({ className }: { className?: string }) { diff --git a/apps/www/src/components/playground-preview.tsx b/apps/www/src/components/playground-preview.tsx index 8a8f0625db..2c0bab55f2 100644 --- a/apps/www/src/components/playground-preview.tsx +++ b/apps/www/src/components/playground-preview.tsx @@ -25,6 +25,9 @@ const i18n = { en: { description: 'An AI editor', }, + 'pt-br': { + description: 'Um editor de IA', + }, }; // TODO: sync diff --git a/apps/www/src/hooks/useLocale.ts b/apps/www/src/hooks/useLocale.ts index 8de81716d1..94eb42afdf 100644 --- a/apps/www/src/hooks/useLocale.ts +++ b/apps/www/src/hooks/useLocale.ts @@ -8,4 +8,6 @@ export const useLocale = () => { }; export const getLocalizedPath = (locale: string, href: string) => - locale === 'cn' ? `/cn${href}?locale=cn` : href; + locale === 'cn' || locale === 'pt-br' + ? `/${locale}${href}?locale=${locale}` + : href; diff --git a/apps/www/src/i18n/getI18nValues.ts b/apps/www/src/i18n/getI18nValues.ts index 710d66a9ac..609c79f06d 100644 --- a/apps/www/src/i18n/getI18nValues.ts +++ b/apps/www/src/i18n/getI18nValues.ts @@ -1,3 +1,4 @@ +// #region en import { aiValue as aiValueEn } from '@/registry/examples/values/ai-value'; import { alignValue as alignValueEn } from '@/registry/examples/values/align-value'; import { autoformatValue as autoformatValueEn } from '@/registry/examples/values/autoformat-value'; @@ -6,6 +7,46 @@ import { basicMarksValue as basicMarksValueEn } from '@/registry/examples/values import { basicNodesValue as basicNodesValueEn } from '@/registry/examples/values/basic-nodes-value'; import { blockMenuValue as blockMenuValueEn } from '@/registry/examples/values/block-menu-value'; import { blockSelectionValue as blockSelectionValueEn } from '@/registry/examples/values/block-selection-value'; +import { columnValue as columnValueEn } from '@/registry/examples/values/column-value'; +import { copilotValue as copilotValueEn } from '@/registry/examples/values/copilot-value'; +import { cursorOverlayValue as cursorOverlayValueEn } from '@/registry/examples/values/cursor-overlay-value'; +import { dateValue as dateValueEn } from '@/registry/examples/values/date-value'; +import { deserializeCsvValue as deserializeCsvValueEn } from '@/registry/examples/values/deserialize-csv-value'; +import { deserializeDocxValue as deserializeDocxValueEn } from '@/registry/examples/values/deserialize-docx-value'; +import { deserializeHtmlValue as deserializeHtmlValueEn } from '@/registry/examples/values/deserialize-html-value'; +import { deserializeMdValue as deserializeMdValueEn } from '@/registry/examples/values/deserialize-md-value'; +import { discussionValue as commentValueEn } from '@/registry/examples/values/discussion-value'; +import { dndValue as dndValueEn } from '@/registry/examples/values/dnd-value'; +import { editableVoidsValue as editableVoidsValueEn } from '@/registry/examples/values/editable-voids-value'; +import { emojiValue as emojiValueEn } from '@/registry/examples/values/emoji-value'; +import { equationValue as equationValueEn } from '@/registry/examples/values/equation-value'; +import { excalidrawValue as excalidrawValueEn } from '@/registry/examples/values/excalidraw-value'; +import { + exitBreakValue as exitBreakValueEn, + trailingBlockValue as trailingBlockValueEn, +} from '@/registry/examples/values/exit-break-value'; +import { findReplaceValue as findReplaceValueEn } from '@/registry/examples/values/find-replace-value'; +import { floatingToolbarValue as floatingToolbarValueEn } from '@/registry/examples/values/floating-toolbar-value'; +import { fontValue as fontValueEn } from '@/registry/examples/values/font-value'; +import { iframeValue as iframeValueEn } from '@/registry/examples/values/iframe-value'; +import { indentValue as indentValueEn } from '@/registry/examples/values/indent-value'; +import { lineHeightValue as lineHeightValueEn } from '@/registry/examples/values/line-height-value'; +import { linkValue as linkValueEn } from '@/registry/examples/values/link-value'; +import { listValue as listValueEn } from '@/registry/examples/values/list-value'; +import { mediaValue as mediaValueEn } from '@/registry/examples/values/media-value'; +import { mentionValue as mentionValueEn } from '@/registry/examples/values/mention-value'; +import { blockPlaceholderValue as placeholderValueEn } from '@/registry/examples/values/placeholder-value'; +import { playgroundValue as playgroundValueEn } from '@/registry/examples/values/playground-value'; +import { pluginRulesValue as pluginRulesValueEn } from '@/registry/examples/values/plugin-rules-value'; +import { previewMdValue as previewMdValueEn } from '@/registry/examples/values/preview-md-value'; +import { slashCommandValue as slashCommandValueEn } from '@/registry/examples/values/slash-command-value'; +import { tabbableValue as tabbableValueEn } from '@/registry/examples/values/tabbable-value'; +import { tableValue as tableValueEn } from '@/registry/examples/values/table-value'; +import { tocValue as tocValueEn } from '@/registry/examples/values/toc-value'; +import { toggleValue as toggleValueEn } from '@/registry/examples/values/toggle-value'; +// #endregion + +// #region cn import { aiValue as aiValueCn } from '@/registry/examples/values/cn/ai-value'; import { alignValue as alignValueCn } from '@/registry/examples/values/cn/align-value'; import { autoformatValue as autoformatValueCn } from '@/registry/examples/values/cn/autoformat-value'; @@ -51,43 +92,54 @@ import { tabbableValue as tabbableValueCn } from '@/registry/examples/values/cn/ import { tableValue as tableValueCn } from '@/registry/examples/values/cn/table-value'; import { tocValue as tocValueCn } from '@/registry/examples/values/cn/toc-value'; import { toggleValue as toggleValueCn } from '@/registry/examples/values/cn/toggle-value'; -import { columnValue as columnValueEn } from '@/registry/examples/values/column-value'; -import { copilotValue as copilotValueEn } from '@/registry/examples/values/copilot-value'; -import { cursorOverlayValue as cursorOverlayValueEn } from '@/registry/examples/values/cursor-overlay-value'; -import { dateValue as dateValueEn } from '@/registry/examples/values/date-value'; -import { deserializeCsvValue as deserializeCsvValueEn } from '@/registry/examples/values/deserialize-csv-value'; -import { deserializeDocxValue as deserializeDocxValueEn } from '@/registry/examples/values/deserialize-docx-value'; -import { deserializeHtmlValue as deserializeHtmlValueEn } from '@/registry/examples/values/deserialize-html-value'; -import { deserializeMdValue as deserializeMdValueEn } from '@/registry/examples/values/deserialize-md-value'; -import { discussionValue as commentValueEn } from '@/registry/examples/values/discussion-value'; -import { dndValue as dndValueEn } from '@/registry/examples/values/dnd-value'; -import { editableVoidsValue as editableVoidsValueEn } from '@/registry/examples/values/editable-voids-value'; -import { emojiValue as emojiValueEn } from '@/registry/examples/values/emoji-value'; -import { equationValue as equationValueEn } from '@/registry/examples/values/equation-value'; -import { excalidrawValue as excalidrawValueEn } from '@/registry/examples/values/excalidraw-value'; +// #endregion + +// #region pt-br +import { aiValue as aiValuePt } from '@/registry/examples/values/pt-br/ai-value'; +import { alignValue as alignValuePt } from '@/registry/examples/values/pt-br/align-value'; +import { autoformatValue as autoformatValuePt } from '@/registry/examples/values/pt-br/autoformat-value'; +import { basicBlocksValue as basicBlocksValuePt } from '@/registry/examples/values/pt-br/basic-blocks-value'; +import { basicMarksValue as basicMarksValuePt } from '@/registry/examples/values/pt-br/basic-marks-value'; +import { basicNodesValue as basicNodesValuePt } from '@/registry/examples/values/pt-br/basic-nodes-value'; +import { blockMenuValue as blockMenuValuePt } from '@/registry/examples/values/pt-br/block-menu-value'; +import { blockSelectionValue as blockSelectionValuePt } from '@/registry/examples/values/pt-br/block-selection-value'; +import { columnValue as columnValuePt } from '@/registry/examples/values/pt-br/column-value'; +import { copilotValue as copilotValuePt } from '@/registry/examples/values/pt-br/copilot-value'; +import { cursorOverlayValue as cursorOverlayValuePt } from '@/registry/examples/values/pt-br/cursor-overlay-value'; +import { dateValue as dateValuePt } from '@/registry/examples/values/pt-br/date-value'; +import { deserializeCsvValue as deserializeCsvValuePt } from '@/registry/examples/values/pt-br/deserialize-csv-value'; +import { deserializeDocxValue as deserializeDocxValuePt } from '@/registry/examples/values/pt-br/deserialize-docx-value'; +import { deserializeHtmlValue as deserializeHtmlValuePt } from '@/registry/examples/values/pt-br/deserialize-html-value'; +import { deserializeMdValue as deserializeMdValuePt } from '@/registry/examples/values/pt-br/deserialize-md-value'; +import { discussionValue as discussionValuePt } from '@/registry/examples/values/pt-br/discussion-value'; +import { dndValue as dndValuePt } from '@/registry/examples/values/pt-br/dnd-value'; +import { editableVoidsValue as editableVoidsValuePt } from '@/registry/examples/values/pt-br/editable-voids-value'; +import { emojiValue as emojiValuePt } from '@/registry/examples/values/pt-br/emoji-value'; +import { equationValue as equationValuePt } from '@/registry/examples/values/pt-br/equation-value'; +import { excalidrawValue as excalidrawValuePt } from '@/registry/examples/values/pt-br/excalidraw-value'; import { - exitBreakValue as exitBreakValueEn, - trailingBlockValue as trailingBlockValueEn, -} from '@/registry/examples/values/exit-break-value'; -import { findReplaceValue as findReplaceValueEn } from '@/registry/examples/values/find-replace-value'; -import { floatingToolbarValue as floatingToolbarValueEn } from '@/registry/examples/values/floating-toolbar-value'; -import { fontValue as fontValueEn } from '@/registry/examples/values/font-value'; -import { iframeValue as iframeValueEn } from '@/registry/examples/values/iframe-value'; -import { indentValue as indentValueEn } from '@/registry/examples/values/indent-value'; -import { lineHeightValue as lineHeightValueEn } from '@/registry/examples/values/line-height-value'; -import { linkValue as linkValueEn } from '@/registry/examples/values/link-value'; -import { listValue as listValueEn } from '@/registry/examples/values/list-value'; -import { mediaValue as mediaValueEn } from '@/registry/examples/values/media-value'; -import { mentionValue as mentionValueEn } from '@/registry/examples/values/mention-value'; -import { blockPlaceholderValue as placeholderValueEn } from '@/registry/examples/values/placeholder-value'; -import { playgroundValue as playgroundValueEn } from '@/registry/examples/values/playground-value'; -import { pluginRulesValue as pluginRulesValueEn } from '@/registry/examples/values/plugin-rules-value'; -import { previewMdValue as previewMdValueEn } from '@/registry/examples/values/preview-md-value'; -import { slashCommandValue as slashCommandValueEn } from '@/registry/examples/values/slash-command-value'; -import { tabbableValue as tabbableValueEn } from '@/registry/examples/values/tabbable-value'; -import { tableValue as tableValueEn } from '@/registry/examples/values/table-value'; -import { tocValue as tocValueEn } from '@/registry/examples/values/toc-value'; -import { toggleValue as toggleValueEn } from '@/registry/examples/values/toggle-value'; + exitBreakValue as exitBreakValuePt, + trailingBlockValue as trailingBlockValuePt, +} from '@/registry/examples/values/pt-br/exit-break-value'; +import { findReplaceValue as findReplaceValuePt } from '@/registry/examples/values/pt-br/find-replace-value'; +import { floatingToolbarValue as floatingToolbarValuePt } from '@/registry/examples/values/pt-br/floating-toolbar-value'; +import { fontValue as fontValuePt } from '@/registry/examples/values/pt-br/font-value'; +import { iframeValue as iframeValuePt } from '@/registry/examples/values/pt-br/iframe-value'; +import { indentValue as indentValuePt } from '@/registry/examples/values/pt-br/indent-value'; +import { lineHeightValue as lineHeightValuePt } from '@/registry/examples/values/pt-br/line-height-value'; +import { linkValue as linkValuePt } from '@/registry/examples/values/pt-br/link-value'; +import { listValue as listValuePt } from '@/registry/examples/values/pt-br/list-value'; +import { mediaValue as mediaValuePt } from '@/registry/examples/values/pt-br/media-value'; +import { mentionValue as mentionValuePt } from '@/registry/examples/values/pt-br/mention-value'; +import { blockPlaceholderValue as placeholderValuePt } from '@/registry/examples/values/pt-br/placeholder-value'; +import { playgroundValue as playgroundValuePt } from '@/registry/examples/values/pt-br/playground-value'; +import { previewMdValue as previewMdValuePt } from '@/registry/examples/values/pt-br/preview-md-value'; +import { slashCommandValue as slashCommandValuePt } from '@/registry/examples/values/pt-br/slash-command-value'; +import { tabbableValue as tabbableValuePt } from '@/registry/examples/values/pt-br/tabbable-value'; +import { tableValue as tableValuePt } from '@/registry/examples/values/pt-br/table-value'; +import { tocValue as tocValuePt } from '@/registry/examples/values/pt-br/toc-value'; +import { toggleValue as toggleValuePt } from '@/registry/examples/values/pt-br/toggle-value'; +// #endregion const i18n = { cn: { @@ -180,6 +232,50 @@ const i18n = { toggle: toggleValueEn, trailingBlock: trailingBlockValueEn, }, + 'pt-br': { + ai: aiValuePt, + autoformat: autoformatValuePt, + basicBlocks: basicBlocksValuePt, + basicMarks: basicMarksValuePt, + basicNodes: basicNodesValuePt, + blockMenu: blockMenuValuePt, + blockSelection: blockSelectionValuePt, + column: columnValuePt, + copilot: copilotValuePt, + cursorOverlay: cursorOverlayValuePt, + date: dateValuePt, + deserializeCsv: deserializeCsvValuePt, + deserializeDocx: deserializeDocxValuePt, + deserializeHtml: deserializeHtmlValuePt, + deserializeMd: deserializeMdValuePt, + discussion: discussionValuePt, + dnd: dndValuePt, + editableVoids: editableVoidsValuePt, + emoji: emojiValuePt, + equation: equationValuePt, + excalidraw: excalidrawValuePt, + exitBreak: exitBreakValuePt, + findReplace: findReplaceValuePt, + floatingToolbar: floatingToolbarValuePt, + font: fontValuePt, + iframe: iframeValuePt, + indent: indentValuePt, + lineHeight: lineHeightValuePt, + link: linkValuePt, + list: listValuePt, + media: mediaValuePt, + mention: mentionValuePt, + placeholder: placeholderValuePt, + playground: playgroundValuePt, + previewMd: previewMdValuePt, + slashCommand: slashCommandValuePt, + tabbable: tabbableValuePt, + table: tableValuePt, + 'text-align': alignValuePt, + toc: tocValuePt, + toggle: toggleValuePt, + trailingBlock: trailingBlockValuePt, + }, }; export const getI18nValues = (locale: string) => diff --git a/apps/www/src/lib/withLocale.ts b/apps/www/src/lib/withLocale.ts index 39a71b1536..082d1a1b4d 100644 --- a/apps/www/src/lib/withLocale.ts +++ b/apps/www/src/lib/withLocale.ts @@ -1,6 +1,6 @@ export const hrefWithLocale = (href: string, locale: string) => { - if (locale === 'cn') { - return `/cn${href}?locale=${locale}`; + if (locale === 'cn' || locale === 'pt-br') { + return `/${locale}${href}?locale=${locale}`; } return href; diff --git a/apps/www/src/registry/examples/values/pt-br/ai-value.tsx b/apps/www/src/registry/examples/values/pt-br/ai-value.tsx new file mode 100644 index 0000000000..7b342e319d --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/ai-value.tsx @@ -0,0 +1,100 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const aiValue: any = ( + + Menu de IA + Gere e refine conteúdo com IA. + Acesse o menu de IA de várias maneiras: + + Pressione "⌘ + J". + + + + Selecione o texto e clique em "Perguntar à IA" na barra de ferramentas + flutuante + + + + + Clique com o botão direito em um bloco e selecione "Perguntar à IA" + + + + Pressione espaço em um bloco vazio. Experimente: + + + + + Uma vez aberto, você pode: + + Pesquisar comandos no campo de entrada: + + + Use as setas para navegar, Enter para selecionar + + + Comandos de geração: + + + Continuar escrevendo + + + Adicionar um resumo + + + Explicar + + + Sugestões de geração: + + + Aceitar + + + Descartar + + + Tentar novamente + + + Comandos de edição: + + + Melhorar a escrita + + + Adicionar emojis + + + Tornar mais longo ou mais curto + + + Corrigir ortografia e gramática + + + Simplificar a linguagem + + Sugestões de edição: + + Substituir a seleção + + + Inserir abaixo + + + Descartar + + + Tentar novamente + + + + Nota: o histórico do chat é preservado até que o menu seja fechado. + + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/align-value.tsx b/apps/www/src/registry/examples/values/pt-br/align-value.tsx new file mode 100644 index 0000000000..a15a87efbd --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/align-value.tsx @@ -0,0 +1,20 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const alignValue: any = ( + + Alinhamento + + Alinhe o texto dentro dos blocos para criar layouts visualmente atraentes + e equilibrados. + + Centralizado + + Crie layouts limpos e equilibrados justificando o texto do bloco, + proporcionando uma aparência profissional e polida. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/autoformat-value.tsx b/apps/www/src/registry/examples/values/pt-br/autoformat-value.tsx new file mode 100644 index 0000000000..1859d84e18 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/autoformat-value.tsx @@ -0,0 +1,93 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const autoformatValue: any = ( + + Formatação Automática + + Potencialize sua experiência de escrita habilitando recursos de formatação + automática. Adicione atalhos estilo Markdown que aplicam formatação + automaticamente enquanto você digita. + + Enquanto digita, experimente estas regras de marcação: + + Digite ** ou __ em ambos os lados + do seu texto para adicionar **negrito*. + + + Digite * ou _ em ambos os lados do + seu texto para adicionar *itálico. + + + + Digite ` em ambos os lados do seu texto para adicionar + `código inline. + + + + Digite ~~ em ambos os lados do seu texto para + adicionar ~~tachado~. + + + Note que nada acontece quando há um caractere antes, tente em:*negrito + + + Nós até suportamos aspas inteligentes, tente digitar{' '} + "olá" 'mundo'. + + + + No início de qualquer novo bloco ou bloco existente, tente estes (regras + de bloco): + + + + Digite *, - ou{' '} + + + seguido de espaço para criar uma lista com marcadores. + + + Digite 1. ou 1) seguido de{' '} + espaço + para criar uma lista numerada. + + + Digite [] ou [x] + seguido de espaço para criar uma lista de tarefas. + + + Digite > seguido de espaço para + criar uma citação em bloco. + + + Digite ``` para criar um bloco de código. + + + Digite --- para criar uma linha horizontal. + + + + Digite # seguido de espaço para + criar um título H1. + + + Digite ### seguido de espaço para + criar um subtítulo H3. + + + Digite #### seguido de espaço para + criar um subtítulo H4. + + + Digite ##### seguido de espaço{' '} + para criar um subtítulo H5. + + + Digite ###### seguido de espaço{' '} + para criar um subtítulo H6. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/basic-blocks-value.tsx b/apps/www/src/registry/examples/values/pt-br/basic-blocks-value.tsx new file mode 100644 index 0000000000..d9c013b658 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/basic-blocks-value.tsx @@ -0,0 +1,42 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; +import { KEYS } from 'platejs'; + +jsx; + +export const basicBlocksValue: any = ( + + Título 1 + + Este é um título de nível superior, geralmente usado para títulos + principais e cabeçalhos de seções maiores. + + Título 2 + + Títulos secundários ajudam a organizar o conteúdo em seções e subseções + claras. + + Título 3 + + Títulos de terceiro nível fornecem mais estrutura e hierarquia ao + conteúdo. + + + "Citações em bloco são perfeitas para destacar informações importantes, + citações de fontes externas ou enfatizar pontos-chave no seu conteúdo." + + + Use títulos para criar uma estrutura de documento clara que ajude os + leitores a navegar pelo seu conteúdo de forma eficaz. Combine-os com + citações em bloco para enfatizar informações importantes. + + + + + + Linhas horizontais ajudam a separar visualmente diferentes seções do seu + conteúdo, criando pausas claras entre tópicos ou ideias. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/basic-marks-value.tsx b/apps/www/src/registry/examples/values/pt-br/basic-marks-value.tsx new file mode 100644 index 0000000000..c94676b865 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/basic-marks-value.tsx @@ -0,0 +1,36 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const basicMarksValue: any = ( + + Formatação de Texto + + Adicione estilo e ênfase ao seu texto usando várias opções de formatação. + + + Faça o texto negrito, itálico,{' '} + sublinhado, ou aplique uma{' '} + + combinação + {' '} + desses estilos para ênfase. + + + Adicione tachado para indicar conteúdo + excluído, use código inline para termos técnicos, ou{' '} + destaque informações importantes. + + + Formate expressões matemáticas com texto{' '} + subscrito e{' '} + sobrescrito. + + + Mostre atalhos de teclado como ⌘ + B para negrito ou{' '} + ⌘ + I para formatação em itálico. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/basic-nodes-value.tsx b/apps/www/src/registry/examples/values/pt-br/basic-nodes-value.tsx new file mode 100644 index 0000000000..3463996c2e --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/basic-nodes-value.tsx @@ -0,0 +1,4 @@ +import { basicBlocksValue } from '@/registry/examples/values/pt-br/basic-blocks-value'; +import { basicMarksValue } from '@/registry/examples/values/pt-br/basic-marks-value'; + +export const basicNodesValue = [...basicBlocksValue, ...basicMarksValue]; diff --git a/apps/www/src/registry/examples/values/pt-br/block-menu-value.tsx b/apps/www/src/registry/examples/values/pt-br/block-menu-value.tsx new file mode 100644 index 0000000000..ca4a01fb40 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/block-menu-value.tsx @@ -0,0 +1,33 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const blockMenuValue: any = ( + + Menu de Bloco + + Abrir o menu de bloco: + + + Clique com o botão direito em qualquer bloco não selecionado para abrir + o menu de contexto. Se você clicar com o botão direito dentro de um + bloco selecionado, verá o menu de contexto nativo do navegador. + + + Opções disponíveis no menu de bloco: + + Pedir à IA para editar o bloco. + + + Excluir o bloco. + + + Duplicar o bloco. + + + Transformar o tipo de bloco em outro tipo de bloco. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/block-selection-value.tsx b/apps/www/src/registry/examples/values/pt-br/block-selection-value.tsx new file mode 100644 index 0000000000..cf3e124853 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/block-selection-value.tsx @@ -0,0 +1,29 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const blockSelectionValue: any = ( + + Seleção de Bloco + + + A seleção de bloco permite selecionar vários blocos de uma vez. Você + pode iniciar uma seleção clicando e arrastando a partir do preenchimento + do editor. + + + Principais recursos da seleção de bloco: + + Selecionar múltiplos blocos. + + + Mantenha Shift pressionado para manter a seleção anterior. Dessa forma, + você pode selecionar blocos não contíguos. + + + Executar ações em massa nos blocos selecionados + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/callout-value.tsx b/apps/www/src/registry/examples/values/pt-br/callout-value.tsx new file mode 100644 index 0000000000..ee8eb8c830 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/callout-value.tsx @@ -0,0 +1,32 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const calloutValue: any = ( + + Destaques (Callouts) + + Use destaques para chamar a atenção para informações importantes e + organizar o conteúdo com ênfase visual. + + + Dica: Destaques ajudam a chamar a atenção para + informações chave sem interromper o fluxo do conteúdo. + + + Aviso: Considerações importantes ou problemas + potenciais dos quais os usuários devem estar cientes. + + + Sucesso: Celebre conquistas ou destaque resultados + positivos. + + + Clique em qualquer ícone de destaque para personalizá-lo com o seletor de + emojis. Destaques suportam formatação rica e podem conter qualquer + conteúdo. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/code-block-value.tsx b/apps/www/src/registry/examples/values/pt-br/code-block-value.tsx new file mode 100644 index 0000000000..0797aed5b8 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/code-block-value.tsx @@ -0,0 +1,78 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const codeBlockValue: any = ( + + Blocos de Código + + Exiba seu código com destaque de sintaxe. Suporta múltiplas linguagens de + programação com formatação e indentação adequadas. + + + // Exemplo JavaScript com async/await + {'async function fetchUserData(userId) {'} + {' try {'} + + {' const response = await fetch(`/api/users/${userId}`);'} + + {' const userData = await response.json();'} + {' return userData;'} + {' } catch (error) {'} + {` console.error('Falha ao buscar dados do usuário:', error);`} + {' throw error;'} + {' }'} + {'}'} + + Exemplo Python com definição de classe: + + # Classe Python com dicas de tipo + from typing import List, Optional + + class GerenciadorTarefas: + {' def __init__(self) -> None:'} + {' self.tasks: List[str] = []'} + + + {' def adicionar_tarefa(self, task: str) -> None:'} + + {` """Adicionar uma nova tarefa à lista."""`} + {' self.tasks.append(task)'} + + + {' def obter_tarefa(self, index: int) -> Optional[str]:'} + + {` """Obter uma tarefa pelo índice, retornar None se não encontrada."""`} + + { + ' return self.tasks[index] if 0 <= index < len(self.tasks) else None' + } + + + Exemplo de estilo CSS: + + /* CSS Moderno com propriedades personalizadas */ + {':root {'} + {' --primary-color: #3b82f6;'} + {' --secondary-color: #64748b;'} + {' --border-radius: 0.5rem;'} + {'}'} + + {'.card {'} + {' background: white;'} + {' border-radius: var(--border-radius);'} + + {' box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);'} + + {' padding: 1.5rem;'} + {' transition: transform 0.2s ease-in-out;'} + {'}'} + + {'.card:hover {'} + {' transform: translateY(-2px);'} + {'}'} + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/column-value.tsx b/apps/www/src/registry/examples/values/pt-br/column-value.tsx new file mode 100644 index 0000000000..6df3451ba4 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/column-value.tsx @@ -0,0 +1,22 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const columnValue: any = ( + + Coluna + Crie colunas e a borda ficará oculta durante a visualização + + + esquerda 1 + esquerda 2 + + + direita 1 + direita 2 + + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/copilot-value.tsx b/apps/www/src/registry/examples/values/pt-br/copilot-value.tsx new file mode 100644 index 0000000000..5e6ce0d14a --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/copilot-value.tsx @@ -0,0 +1,38 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const copilotValue: any = ( + + Copilot + + Posicione seu cursor no + final de um parágrafo + onde você deseja adicionar ou modificar texto. + + + Pressione Control + Espaço para acionar o Copilot + + + O Copilot irá + automaticamente + sugerir conclusões enquanto você digita. + + + Escolha entre as conclusões sugeridas: + + + Tab:Aceita toda a conclusão sugerida + + + Command + Seta Direita + : Completa um caractere de cada vez + + + Esc + : Cancela o Copilot + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/cursor-overlay-value.tsx b/apps/www/src/registry/examples/values/pt-br/cursor-overlay-value.tsx new file mode 100644 index 0000000000..75c20f6eef --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/cursor-overlay-value.tsx @@ -0,0 +1,20 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const cursorOverlayValue: any = ( + + Sobreposição de Cursor + + Tente arrastar sobre o texto: você verá um cursor colorido no alvo de + soltura: a cor e outros estilos são personalizáveis! + + + Você também pode tentar clicar no botão "Perguntar à IA" - a seleção + permanecerá visível enquanto foca em outra entrada, e será atualizada + durante o streaming. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/date-value.tsx b/apps/www/src/registry/examples/values/pt-br/date-value.tsx new file mode 100644 index 0000000000..142aea66aa --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/date-value.tsx @@ -0,0 +1,29 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +const today = new Date().toISOString().split('T')[0]; + +export const dateValue: any = ( + + Data + + Insira e exiba datas em seu texto usando elementos de data inline. Essas + datas podem ser facilmente selecionadas e modificadas usando uma interface + de calendário. + + + Tente selecionar{' '} + + + {' '} + ou{' '} + + + + . + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/demo-values.tsx b/apps/www/src/registry/examples/values/pt-br/demo-values.tsx new file mode 100644 index 0000000000..fd7cf03016 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/demo-values.tsx @@ -0,0 +1,109 @@ +import { calloutValue } from '@/registry/examples/values/pt-br/callout-value'; +import { playgroundValue } from '@/registry/examples/values/playground-value'; + +import { aiValue } from './ai-value'; +import { alignValue } from './align-value'; +import { autoformatValue } from './autoformat-value'; +import { basicBlocksValue } from './basic-blocks-value'; +import { basicMarksValue } from './basic-marks-value'; +import { basicNodesValue } from './basic-nodes-value'; +import { blockMenuValue } from './block-menu-value'; +import { blockSelectionValue } from './block-selection-value'; +import { codeBlockValue } from './code-block-value'; +import { columnValue } from './column-value'; +import { copilotValue } from './copilot-value'; +import { cursorOverlayValue } from './cursor-overlay-value'; +import { dateValue } from './date-value'; +import { deserializeCsvValue } from './deserialize-csv-value'; +import { deserializeDocxValue } from './deserialize-docx-value'; +import { deserializeHtmlValue } from './deserialize-html-value'; +import { deserializeMdValue } from './deserialize-md-value'; +import { discussionValue } from './discussion-value'; +import { dndValue } from './dnd-value'; +import { editableVoidsValue } from './editable-voids-value'; +import { emojiValue } from './emoji-value'; +import { equationValue } from './equation-value'; +import { excalidrawValue } from './excalidraw-value'; +import { exitBreakValue } from './exit-break-value'; +import { findReplaceValue } from './find-replace-value'; +import { floatingToolbarValue } from './floating-toolbar-value'; +import { fontValue } from './font-value'; +import { iframeValue } from './iframe-value'; +import { indentValue } from './indent-value'; +import { lineHeightValue } from './line-height-value'; +import { linkValue } from './link-value'; +import { listValue as listClassicValue } from './list-classic-value'; +import { listValue } from './list-value'; +import { mediaValue } from './media-value'; +import { mentionValue } from './mention-value'; +import { blockPlaceholderValue } from './placeholder-value'; +import { pluginRulesValue } from './plugin-rules-value'; +import { previewMdValue } from './preview-md-value'; +import { slashCommandValue } from './slash-command-value'; +import { tabbableValue } from './tabbable-value'; +import { tableValue } from './table-value'; +import { tocValue } from './toc-value'; +import { toggleValue } from './toggle-value'; + +const values = { + ai: aiValue, + autoformat: autoformatValue, + 'basic-blocks': basicBlocksValue, + 'basic-marks': basicMarksValue, + 'basic-nodes': basicNodesValue, + 'block-menu': blockMenuValue, + // 'multi-editors': multiEditorsValue, + 'block-placeholder': blockPlaceholderValue, + 'block-selection': blockSelectionValue, + callout: calloutValue, + 'code-block': codeBlockValue, + column: columnValue, + copilot: copilotValue, + csv: deserializeCsvValue, + 'cursor-overlay': cursorOverlayValue, + date: dateValue, + discussion: discussionValue, + dnd: dndValue, + docx: deserializeDocxValue, + 'editable-voids': editableVoidsValue, + emoji: emojiValue, + // upload: uploadValue, + equation: equationValue, + // equation: equationValue, + excalidraw: excalidrawValue, + 'exit-break': exitBreakValue, + 'find-replace': findReplaceValue, + 'floating-toolbar': floatingToolbarValue, + font: fontValue, + html: deserializeHtmlValue, + // 'huge-document': hugeDocumentValue, + iframe: iframeValue, + indent: indentValue, + 'line-height': lineHeightValue, + link: linkValue, + list: listValue, + 'list-classic': listClassicValue, + markdown: deserializeMdValue, + media: mediaValue, + // 'media-toolbar': mediaToolbarValue, + mention: mentionValue, + playground: playgroundValue, + 'plugin-rules': pluginRulesValue, + 'preview-markdown': previewMdValue, + 'slash-command': slashCommandValue, + tabbable: tabbableValue, + table: tableValue, + 'text-align': alignValue, + toc: tocValue, + toggle: toggleValue, +}; + +export const DEMO_VALUES = Object.entries(values).reduce( + (acc, [key, value]) => { + const demoKey = key.replace('Value', ''); + acc[demoKey] = value; + + return acc; + }, + {} as Record +); diff --git a/apps/www/src/registry/examples/values/pt-br/deserialize-csv-value.tsx b/apps/www/src/registry/examples/values/pt-br/deserialize-csv-value.tsx new file mode 100644 index 0000000000..f856e0b2b3 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/deserialize-csv-value.tsx @@ -0,0 +1,12 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const deserializeCsvValue: any = ( + + CSV + Copie e cole conteúdo CSV em uma tabela. + +); diff --git a/apps/www/src/registry/examples/values/pt-br/deserialize-docx-value.tsx b/apps/www/src/registry/examples/values/pt-br/deserialize-docx-value.tsx new file mode 100644 index 0000000000..00d20cac01 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/deserialize-docx-value.tsx @@ -0,0 +1,15 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const deserializeDocxValue: any = ( + + Docx + + Importe facilmente conteúdo de documentos Microsoft Word simplesmente + copiando e colando o conteúdo Docx no editor. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/deserialize-html-value.tsx b/apps/www/src/registry/examples/values/pt-br/deserialize-html-value.tsx new file mode 100644 index 0000000000..e0730e4148 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/deserialize-html-value.tsx @@ -0,0 +1,25 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const deserializeHtmlValue: any = ( + + HTML + + Por padrão, quando você cola conteúdo no editor Slate, ele utiliza os + dados + 'text/plain' + da área de transferência. Embora isso seja adequado para certos cenários, + há momentos em que você quer que os usuários possam colar conteúdo + preservando sua formatação. Para conseguir isso, seu editor deve ser capaz + de manipular dados 'text/html'. + + + Para experimentar a preservação perfeita da formatação, simplesmente copie + e cole conteúdo renderizado em HTML (não o código-fonte) de outro site + neste editor. Você notará que a formatação do conteúdo colado é mantida. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/deserialize-md-value.tsx b/apps/www/src/registry/examples/values/pt-br/deserialize-md-value.tsx new file mode 100644 index 0000000000..d6de547f11 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/deserialize-md-value.tsx @@ -0,0 +1,16 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const deserializeMdValue: any = ( + + Markdown + + Copie e cole conteúdo Markdown de editores Markdown populares como{' '} + markdown-it.github.io/ no + editor para fácil conversão e edição. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/discussion-value.tsx b/apps/www/src/registry/examples/values/pt-br/discussion-value.tsx new file mode 100644 index 0000000000..48a7cdf45f --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/discussion-value.tsx @@ -0,0 +1,88 @@ +import type { Value } from 'platejs'; + +export const discussionValue: Value = [ + { + children: [{ text: 'Discussões' }], + type: 'h2', + }, + { + children: [ + { text: 'Revise e refine o conteúdo perfeitamente. Use ' }, + { + children: [ + { + suggestion: true, + suggestion_playground1: { + id: 'playground1', + createdAt: Date.now(), + type: 'insert', + userId: 'alice', + }, + text: 'sugestões', + }, + ], + type: 'a', + url: '/docs/suggestion', + }, + { + suggestion: true, + suggestion_playground1: { + id: 'playground1', + createdAt: Date.now(), + type: 'insert', + userId: 'alice', + }, + text: ' ', + }, + { + suggestion: true, + suggestion_playground1: { + id: 'playground1', + createdAt: Date.now(), + type: 'insert', + userId: 'alice', + }, + text: 'como este texto adicionado', + }, + { text: ' ou para ' }, + { + suggestion: true, + suggestion_playground2: { + id: 'playground2', + createdAt: Date.now(), + type: 'remove', + userId: 'bob', + }, + text: 'marcar texto para remoção', + }, + { text: '. Discuta alterações usando ' }, + { + children: [ + { comment: true, comment_discussion1: true, text: 'comentários' }, + ], + type: 'a', + url: '/docs/comment', + }, + { + comment: true, + comment_discussion1: true, + text: ' em muitos segmentos de texto', + }, + { text: '. Você pode até ter ' }, + { + comment: true, + comment_discussion2: true, + suggestion: true, + suggestion_playground3: { + id: 'playground3', + createdAt: Date.now(), + type: 'insert', + userId: 'charlie', + }, + text: 'anotações', + }, + { text: ' sobrepostas!' }, + ], + type: 'p', + }, +]; diff --git a/apps/www/src/registry/examples/values/pt-br/dnd-value.tsx b/apps/www/src/registry/examples/values/pt-br/dnd-value.tsx new file mode 100644 index 0000000000..62b33460ae --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/dnd-value.tsx @@ -0,0 +1,40 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const dndValue: any = ( + + Arrastar e Soltar + + Reorganize facilmente o conteúdo do seu documento usando arrastar e + soltar. + + Como usar: + + + Passe o mouse sobre o lado esquerdo de um bloco para ver a alça de + arrasto (seis pontos). + + + + + Clique e segure a alça, depois arraste o bloco para um novo local. + + + + Solte para colocar o bloco em sua nova posição. + + Experimente! Arraste estes itens para reordená-los: + + Primeiro item + + + Segundo item + + + Terceiro item + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/editable-voids-value.tsx b/apps/www/src/registry/examples/values/pt-br/editable-voids-value.tsx new file mode 100644 index 0000000000..c93a38566d --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/editable-voids-value.tsx @@ -0,0 +1,21 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const editableVoidsValue: any = ( + + + Além de nós que contêm texto editável, você pode inserir nós vazios (void + nodes), que também podem conter elementos editáveis, entradas ou até mesmo + outro editor Slate inteiro. + + + + + + + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/emoji-value.tsx b/apps/www/src/registry/examples/values/pt-br/emoji-value.tsx new file mode 100644 index 0000000000..14b7f7d6c9 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/emoji-value.tsx @@ -0,0 +1,16 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const emojiValue: any = ( + + Emoji + Expresse-se com um toque de diversão 🎉 e emoção 😃. + + Escolha na barra de ferramentas ou digite dois pontos para abrir a lista + suspensa. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/equation-value.tsx b/apps/www/src/registry/examples/values/pt-br/equation-value.tsx new file mode 100644 index 0000000000..7573afb468 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/equation-value.tsx @@ -0,0 +1,95 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const equationValue: any = ( + + + Equação + + + + Equações permitem que você expresse conceitos matemáticos complexos em + formatos inline e bloco. + + + + Principais características: + + + Suporte à sintaxe LaTeX + + + Formatos de equação inline e bloco + + + Exemplo de equação inline: + + + + (Famosa equação de Einstein) + + + Exemplos de equação em bloco: + + + + + + A fórmula quadrática para resolver + + + + . + + + + + + O teorema fundamental do cálculo. + + + Tente estas ações: + + + + Clique em qualquer equação para editá-la. Pressione Esc para fechar o + menu sem editar. + + + + Você pode navegar pela equação usando as teclas de seta + + + + Use o comando de barra (/equation) para inserir uma nova equação + + + + + Use o comando de barra (/inline equation) para equações inline + + + + + Uso avançado: Combine equações com outros elementos como tabelas ou + blocos de código para documentação científica abrangente. Por exemplo: + + + + A equação de Schrödinger, + + + + , é fundamental na mecânica quântica. + + + + Experimente diferentes tipos de equações e formatações para criar + conteúdo matemático rico em seus documentos. + + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/excalidraw-value.tsx b/apps/www/src/registry/examples/values/pt-br/excalidraw-value.tsx new file mode 100644 index 0000000000..31e4511304 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/excalidraw-value.tsx @@ -0,0 +1,71 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +import type { TExcalidrawElement } from '@platejs/excalidraw'; +import type { NodeProps } from 'platejs'; + +export const excalidrawInitialData: NodeProps = { + data: { + elements: [ + { + id: 'oDVXy8D6rom3H1-LLH2-f', + angle: 0, + backgroundColor: 'transparent', + fillStyle: 'hachure', + groupIds: [], + height: 141.976_562_5, + isDeleted: false, + opacity: 100, + roughness: 1, + seed: 1_968_410_350, + strokeColor: '#000000', + strokeStyle: 'solid', + strokeWidth: 1, + type: 'rectangle', + version: 141, + versionNonce: 361_174_001, + width: 186.472_656_25, + x: 100.503_906_25, + y: 93.675_781_25, + }, + { + id: '-xMIs_0jIFqvpx-R9UnaG', + angle: 0, + backgroundColor: 'transparent', + fillStyle: 'hachure', + groupIds: [], + height: 129.511_718_75, + isDeleted: false, + opacity: 100, + roughness: 1, + seed: 957_947_807, + strokeColor: '#000000', + strokeStyle: 'solid', + strokeWidth: 1, + type: 'ellipse', + version: 47, + versionNonce: 1_128_618_623, + width: 198.218_75, + x: 300.570_312_5, + y: 190.691_406_25, + }, + ], + state: { currentItemFontFamily: 1, viewBackgroundColor: '#AFEEEE' }, + }, +}; + +export const excalidrawValue: any = ( + + Excalidraw + + Liberte sua criatividade com o plugin Excalidraw, que permite que você + incorpore e desenhe diagramas diretamente no seu editor. + + + + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/exit-break-value.tsx b/apps/www/src/registry/examples/values/pt-br/exit-break-value.tsx new file mode 100644 index 0000000000..cf8b3d1c9f --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/exit-break-value.tsx @@ -0,0 +1,48 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +import { createTable } from './table-value'; + +jsx; + +export const trailingBlockValue: any = ( + + Bloco Final + Sempre tenha um parágrafo final no fim do seu editor. + +); + +export const exitBreakValue: any = ( + + Quebra de Saída + + Saia de estruturas de blocos aninhados usando atalhos de teclado. O plugin + determina automaticamente o ponto de saída apropriado: + + + + ⌘⏎ – Sair e inserir um novo bloco após a estrutura atual + + + ⌘⇧⏎ – Sair e inserir um novo bloco antes da estrutura atual + + + Automático – Encontra o ancestral mais próximo que permite irmãos de + parágrafo + + + + Quebras de saída funcionam de forma inteligente em estruturas aninhadas + como tabelas: + + + {createTable()} + + + Tente ⌘⏎ para sair deste bloco de código. + + + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/find-replace-value.tsx b/apps/www/src/registry/examples/values/pt-br/find-replace-value.tsx new file mode 100644 index 0000000000..f503b30423 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/find-replace-value.tsx @@ -0,0 +1,16 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const findReplaceValue: any = ( + + + Este é um texto editável que você pode pesquisar. Enquanto você pesquisa, + ele procura por sequências de texto correspondentes e adiciona{' '} + decorações a elas em tempo real. + + Experimente você mesmo digitando na caixa de pesquisa acima! + +); diff --git a/apps/www/src/registry/examples/values/pt-br/floating-toolbar-value.tsx b/apps/www/src/registry/examples/values/pt-br/floating-toolbar-value.tsx new file mode 100644 index 0000000000..1f7da2c6c5 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/floating-toolbar-value.tsx @@ -0,0 +1,55 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const floatingToolbarValue: any = ( + + Barra de Ferramentas Flutuante + + A barra de ferramentas flutuante fornece acesso rápido a opções de + formatação e ações para o texto selecionado. + + Como usar a barra de ferramentas flutuante: + + + Selecione qualquer texto para invocar a barra de ferramentas flutuante. + + + Com a barra de ferramentas flutuante, você pode: + + Pedir ajuda à IA + + + Adicionar um comentário ao texto selecionado + + + Transformar um tipo de bloco em outro + + + + Aplicar formatação de texto: negrito, itálico, sublinhado, tachado, + código + + + + + Tente selecionar algum texto abaixo para ver a barra de ferramentas + flutuante em ação: + + + + Texto em negrito + , + texto em itálico + , + texto sublinhado + , e + + formatação combinada + + . + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/font-value.tsx b/apps/www/src/registry/examples/values/pt-br/font-value.tsx new file mode 100644 index 0000000000..a8da372eee --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/font-value.tsx @@ -0,0 +1,43 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const fontValue: any = ( + + Cores + + Adicione{' '} + + m + + + ú + + + l + + + t + + + i + + + p + + + l + + + a + {' '} + fonte e cores de{' '} + + fundo + {' '} + para criar texto vibrante e atraente. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/huge-document-value.tsx b/apps/www/src/registry/examples/values/pt-br/huge-document-value.tsx new file mode 100644 index 0000000000..980e6e14d5 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/huge-document-value.tsx @@ -0,0 +1,42 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import type { Descendant, Value } from 'platejs'; + +import { jsx } from '@platejs/test-utils'; + +jsx; + +const HEADINGS = 300; +const PARAGRAPHS = 10; + +export const createHugeDocumentValue = () => { + const hugeDocument: Descendant[] = []; + + for (let h = 0; h < HEADINGS; h++) { + hugeDocument.push( + ( + Do voluptate enim commodo quis ad aliqua dolore enim eu nisi. + ) as any + ); + + for (let p = 0; p < PARAGRAPHS; p++) { + hugeDocument.push( + ( + + Ex est consequat anim ad deserunt sint. Ea excepteur consequat amet + amet excepteur culpa nulla. Voluptate exercitation pariatur enim. + Excepteur ea nulla nostrud est ex sunt anim. Sunt laborum et et ea + aliquip excepteur sint nulla amet. Sunt sit cillum amet. Anim esse + ut irure ipsum irure proident consectetur eu velit esse. Laborum + minim laborum laborum sunt eiusmod aliqua fugiat adipisicing. Cillum + aliqua exercitation ex aliquip aliquip amet aliquip est eiusmod + tempor pariatur veniam adipisicing ad. Officia sunt ipsum + adipisicing eu quis laborum do cupidatat officia dolor. + + ) as any + ); + } + } + + return hugeDocument as Value; +}; diff --git a/apps/www/src/registry/examples/values/pt-br/iframe-value.tsx b/apps/www/src/registry/examples/values/pt-br/iframe-value.tsx new file mode 100644 index 0000000000..ab09e5bdfa --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/iframe-value.tsx @@ -0,0 +1,21 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const iframeValue: any = ( + + + Neste exemplo, o documento é renderizado em um iframe{' '} + controlado. Isso é particularmente útil quando você + precisa separar os estilos do conteúdo do editor daqueles que endereçam + sua interface de usuário. + + + Este também é o único método confiável para visualizar quaisquer{' '} + consultas de mídia (media queries) + em seu CSS. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/indent-value.tsx b/apps/www/src/registry/examples/values/pt-br/indent-value.tsx new file mode 100644 index 0000000000..81b3e414da --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/indent-value.tsx @@ -0,0 +1,18 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const indentValue: any = ( + + Indentação + + Controle facilmente a indentação de blocos específicos para destacar + informações importantes e melhorar a estrutura visual. + + + Por exemplo, este parágrafo parece pertencer ao anterior. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/line-height-value.tsx b/apps/www/src/registry/examples/values/pt-br/line-height-value.tsx new file mode 100644 index 0000000000..29e0719869 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/line-height-value.tsx @@ -0,0 +1,19 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const lineHeightValue: any = ( + + Altura da Linha + + Controle a altura da linha do seu texto para melhorar a legibilidade e + ajustar o espaçamento entre as linhas. + + + Escolha a altura de linha ideal para garantir uma leitura confortável e um + documento esteticamente agradável. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/link-value.tsx b/apps/www/src/registry/examples/values/pt-br/link-value.tsx new file mode 100644 index 0000000000..d5d3025cbc --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/link-value.tsx @@ -0,0 +1,23 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const linkValue: any = ( + + Link + + Adicione{' '} + + hiperlinks + {' '} + ao seu texto para referenciar fontes externas ou fornecer informações + adicionais usando o plugin Link. + + + Crie hiperlinks facilmente usando a barra de ferramentas ou colando uma + URL enquanto seleciona o texto desejado. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/list-classic-value.tsx b/apps/www/src/registry/examples/values/pt-br/list-classic-value.tsx new file mode 100644 index 0000000000..43b72e90b6 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/list-classic-value.tsx @@ -0,0 +1,69 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; +import { KEYS } from 'platejs'; + +jsx; + +export const listValue: any = ( + + ✍️ Lista + + + + + + Gatos + + + Cães + + + Pássaros + + + Papagaios + + + Corujas + + + Corujas-das-torres + + + Corujas-das-neves + + + + + + + + + Vermelho + + + Azul + + + Azul claro + + + Azul escuro + + + Azul marinho + + + Azul turquesa + + + + + + + Verde + + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/list-value.tsx b/apps/www/src/registry/examples/values/pt-br/list-value.tsx new file mode 100644 index 0000000000..63e2ce5751 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/list-value.tsx @@ -0,0 +1,62 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const listValue: any = ( + + Lista + + + Crie listas indentadas com múltiplos níveis de indentação e personalize o + tipo de estilo de lista para cada nível. + + + Tarefa 1 + + + + Disco 1 + + + Disco 2 + + + Tarefa 2 + + + Romano 1 + + + Decimal 11 + + + Decimal 111 + + + Decimal 112 + + + Decimal 12 + + + Decimal 13 + + + Romano 2 + + + Decimal 11 + + + Decimal 12 + + + Romano 3 + + + Romano 4 + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/media-value.tsx b/apps/www/src/registry/examples/values/pt-br/media-value.tsx new file mode 100644 index 0000000000..102e2dcbe7 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/media-value.tsx @@ -0,0 +1,85 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const imageValue: any = ( + + Imagem + Adicione imagens fazendo upload ou fornecendo a URL da imagem: + + + + Personalize legendas de imagens e redimensione imagens. + +); + +export const mediaPlaceholderValue: any = ( + + Upload + + Nosso editor suporta vários tipos de mídia para upload, incluindo imagens, + vídeos, áudio e arquivos. + + + + + + Status de upload em tempo real e rastreamento de progresso + + + + + + Limites de tamanho de arquivo configuráveis e configurações de upload em + lote + + + + + + Mensagens de erro claras para quaisquer problemas de upload + + + Experimente agora - arraste uma imagem da sua área de trabalho ou clique + no botão de upload na barra de ferramentas + + +); + +export const mediaValue: any = ( + + {imageValue} + {mediaPlaceholderValue} + + Incorporar (Embed) + Incorpore vários tipos de conteúdo, como vídeos e tweets: + + + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/mention-value.tsx b/apps/www/src/registry/examples/values/pt-br/mention-value.tsx new file mode 100644 index 0000000000..bd88e6f189 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/mention-value.tsx @@ -0,0 +1,26 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const mentionValue: any = ( + + Menção + + Mencione e referencie outros usuários ou entidades em seu texto usando + @-menções. + + + Tente mencionar{' '} + + + {' '} + ou{' '} + + + + . + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/multi-editors-value.tsx b/apps/www/src/registry/examples/values/pt-br/multi-editors-value.tsx new file mode 100644 index 0000000000..639736e472 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/multi-editors-value.tsx @@ -0,0 +1,43 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import type { Descendant } from 'platejs'; + +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const createMultiEditorsValue = () => { + const multiEditors: Descendant[][] = []; + + for (let h = 0; h < 300; h++) { + const multiEditor: Descendant[] = []; + multiEditor.push( + (Amet duis nisi ea enim laborum laboris.) as any + ); + + for (let p = 0; p < 2; p++) { + multiEditor.push( + ( + + Laborum dolor et tempor consectetur amet ullamco consectetur ullamco + irure incididunt reprehenderit ullamco nulla tempor. Laboris veniam + commodo id in ex ullamco incididunt nulla eu Lorem adipisicing + deserunt duis ad. Mollit magna enim exercitation amet proident + reprehenderit magna nulla officia ad in non. Magna magna adipisicing + fugiat cillum do esse eu adipisicing. Culpa dolor non Lorem. Dolore + non voluptate velit in eu culpa velit. Exercitation fugiat cupidatat + adipisicing duis veniam proident irure ea excepteur aliqua esse ad + cupidatat adipisicing id. Ut exercitation proident ea eiusmod enim + non minim proident Lorem aliqua officia voluptate ullamco culpa + Lorem. Exercitation eiusmod dolor nostrud qui excepteur. Dolor + commodo duis reprehenderit excepteur laboris do minim qui. + + ) as any + ); + } + + multiEditors.push(multiEditor); + } + + return multiEditors; +}; diff --git a/apps/www/src/registry/examples/values/pt-br/placeholder-value.tsx b/apps/www/src/registry/examples/values/pt-br/placeholder-value.tsx new file mode 100644 index 0000000000..e59b80dbd0 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/placeholder-value.tsx @@ -0,0 +1,18 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const blockPlaceholderValue: any = ( + + Placeholder + + Mostre um placeholder ao selecionar um bloco vazio. Experimente no próximo + bloco: + + + + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/playground-value.tsx b/apps/www/src/registry/examples/values/pt-br/playground-value.tsx new file mode 100644 index 0000000000..5780693fe9 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/playground-value.tsx @@ -0,0 +1,545 @@ +import type { Value } from 'platejs'; + +export const playgroundValue: Value = [ + // Intro + { + children: [{ text: 'Bem-vindo ao Plate Playground!' }], + type: 'h1', + }, + { + children: [ + { text: 'Experimente um editor de rich-text moderno construído com ' }, + { children: [{ text: 'Slate' }], type: 'a', url: 'https://slatejs.org' }, + { text: ' e ' }, + { children: [{ text: 'React' }], type: 'a', url: 'https://reactjs.org' }, + { + text: '. Este playground mostra apenas uma parte das capacidades do Plate. ', + }, + { + children: [{ text: 'Explore a documentação' }], + type: 'a', + url: '/docs', + }, + { text: ' para descobrir mais.' }, + ], + type: 'p', + }, + // Suggestions & Comments Section + { + children: [{ text: 'Edição Colaborativa' }], + type: 'h2', + }, + { + children: [ + { text: 'Revise e refine o conteúdo perfeitamente. Use ' }, + { + children: [ + { + suggestion: true, + suggestion_playground1: { + id: 'playground1', + createdAt: Date.now(), + type: 'insert', + userId: 'alice', + }, + text: 'sugestões', + }, + ], + type: 'a', + url: '/docs/suggestion', + }, + { + suggestion: true, + suggestion_playground1: { + id: 'playground1', + createdAt: Date.now(), + type: 'insert', + userId: 'alice', + }, + text: ' ', + }, + { + suggestion: true, + suggestion_playground1: { + id: 'playground1', + createdAt: Date.now(), + type: 'insert', + userId: 'alice', + }, + text: 'como este texto adicionado', + }, + { text: ' ou para ' }, + { + suggestion: true, + suggestion_playground2: { + id: 'playground2', + createdAt: Date.now(), + type: 'remove', + userId: 'bob', + }, + text: 'marcar texto para remoção', + }, + { text: '. Discuta alterações usando ' }, + { + children: [ + { comment: true, comment_discussion1: true, text: 'comentários' }, + ], + type: 'a', + url: '/docs/comment', + }, + { + comment: true, + comment_discussion1: true, + text: ' em muitos segmentos de texto', + }, + { text: '. Você pode até ter ' }, + { + comment: true, + comment_discussion2: true, + suggestion: true, + suggestion_playground3: { + id: 'playground3', + createdAt: Date.now(), + type: 'insert', + userId: 'charlie', + }, + text: 'anotações', + }, + { text: ' sobrepostas!' }, + ], + type: 'p', + }, + // AI Section + { + children: [{ text: 'Edição com IA' }], + type: 'h2', + }, + { + children: [ + { text: 'Aumente sua produtividade com o ' }, + { + children: [{ text: 'AI SDK' }], + type: 'a', + url: '/docs/ai', + }, + { text: ' integrado. Pressione ' }, + { kbd: true, text: '⌘+J' }, + { text: ' ou ' }, + { kbd: true, text: 'Espaço' }, + { text: ' em uma linha vazia para:' }, + ], + type: 'p', + }, + { + children: [ + { text: 'Gerar conteúdo (continuar escrevendo, resumir, explicar)' }, + ], + indent: 1, + listStyleType: 'disc', + type: 'p', + }, + { + children: [ + { + text: 'Editar texto existente (melhorar, corrigir gramática, mudar tom)', + }, + ], + indent: 1, + listStyleType: 'disc', + type: 'p', + }, + // Core Features Section (Combined) + { + children: [{ text: 'Edição de Conteúdo Rico' }], + type: 'h2', + }, + { + children: [ + { text: 'Estruture seu conteúdo com ' }, + { + children: [{ text: 'títulos' }], + type: 'a', + url: '/docs/heading', + }, + { text: ', ' }, + { + children: [{ text: 'listas' }], + type: 'a', + url: '/docs/list', + }, + { text: ', e ' }, + { + children: [{ text: 'citações' }], + type: 'a', + url: '/docs/blockquote', + }, + { text: '. Aplique ' }, + { + children: [{ text: 'marcas' }], + type: 'a', + url: '/docs/basic-marks', + }, + { text: ' como ' }, + { bold: true, text: 'negrito' }, + { text: ', ' }, + { italic: true, text: 'itálico' }, + { text: ', ' }, + { text: 'sublinhado', underline: true }, + { text: ', ' }, + { strikethrough: true, text: 'tachado' }, + { text: ', e ' }, + { code: true, text: 'código' }, + { text: '. Use ' }, + { + children: [{ text: 'formatação automática' }], + type: 'a', + url: '/docs/autoformat', + }, + { text: ' para atalhos tipo ' }, + { + children: [{ text: 'Markdown' }], + type: 'a', + url: '/docs/markdown', + }, + { text: ' (ex: ' }, + { kbd: true, text: '* ' }, + { text: ' para listas, ' }, + { kbd: true, text: '# ' }, + { text: ' para H1).' }, + ], + type: 'p', + }, + { + children: [ + { + text: 'Citações em bloco são ótimas para destacar informações importantes.', + }, + ], + type: 'blockquote', + }, + { + children: [ + { children: [{ text: 'function hello() {' }], type: 'code_line' }, + { + children: [ + { text: " console.info('Blocos de código são suportados!');" }, + ], + type: 'code_line', + }, + { children: [{ text: '}' }], type: 'code_line' }, + ], + lang: 'javascript', + type: 'code_block', + }, + { + children: [ + { text: 'Crie ' }, + { + children: [{ text: 'links' }], + type: 'a', + url: '/docs/link', + }, + { text: ', ' }, + { + children: [{ text: '@menção' }], + type: 'a', + url: '/docs/mention', + }, + { text: ' usuários como ' }, + { children: [{ text: '' }], type: 'mention', value: 'Alice' }, + { text: ', ou insira ' }, + { + children: [{ text: 'emojis' }], + type: 'a', + url: '/docs/emoji', + }, + { text: ' ✨. Use o ' }, + { + children: [{ text: 'comando de barra' }], + type: 'a', + url: '/docs/slash-command', + }, + { text: ' (/) para acesso rápido aos elementos.' }, + ], + type: 'p', + }, + // Table Section + { + children: [{ text: 'Como o Plate se Compara' }], + type: 'h3', + }, + { + children: [ + { + text: 'O Plate oferece muitos recursos prontos para uso como plugins gratuitos e de código aberto.', + }, + ], + type: 'p', + }, + { + children: [ + { + children: [ + { + children: [ + { children: [{ bold: true, text: 'Recurso' }], type: 'p' }, + ], + type: 'th', + }, + { + children: [ + { + children: [{ bold: true, text: 'Plate (Grátis & OSS)' }], + type: 'p', + }, + ], + type: 'th', + }, + { + children: [ + { children: [{ bold: true, text: 'Tiptap' }], type: 'p' }, + ], + type: 'th', + }, + ], + type: 'tr', + }, + { + children: [ + { + children: [{ children: [{ text: 'IA' }], type: 'p' }], + type: 'td', + }, + { + children: [ + { + attributes: { align: 'center' }, + children: [{ text: '✅' }], + type: 'p', + }, + ], + type: 'td', + }, + { + children: [{ children: [{ text: 'Extensão Paga' }], type: 'p' }], + type: 'td', + }, + ], + type: 'tr', + }, + { + children: [ + { + children: [{ children: [{ text: 'Comentários' }], type: 'p' }], + type: 'td', + }, + { + children: [ + { + attributes: { align: 'center' }, + children: [{ text: '✅' }], + type: 'p', + }, + ], + type: 'td', + }, + { + children: [{ children: [{ text: 'Extensão Paga' }], type: 'p' }], + type: 'td', + }, + ], + type: 'tr', + }, + { + children: [ + { + children: [{ children: [{ text: 'Sugestões' }], type: 'p' }], + type: 'td', + }, + { + children: [ + { + attributes: { align: 'center' }, + children: [{ text: '✅' }], + type: 'p', + }, + ], + type: 'td', + }, + { + children: [ + { children: [{ text: 'Pago (Comments Pro)' }], type: 'p' }, + ], + type: 'td', + }, + ], + type: 'tr', + }, + { + children: [ + { + children: [{ children: [{ text: 'Seletor de Emoji' }], type: 'p' }], + type: 'td', + }, + { + children: [ + { + attributes: { align: 'center' }, + children: [{ text: '✅' }], + type: 'p', + }, + ], + type: 'td', + }, + { + children: [{ children: [{ text: 'Extensão Paga' }], type: 'p' }], + type: 'td', + }, + ], + type: 'tr', + }, + { + children: [ + { + children: [{ children: [{ text: 'Índice (TOC)' }], type: 'p' }], + type: 'td', + }, + { + children: [ + { + attributes: { align: 'center' }, + children: [{ text: '✅' }], + type: 'p', + }, + ], + type: 'td', + }, + { + children: [{ children: [{ text: 'Extensão Paga' }], type: 'p' }], + type: 'td', + }, + ], + type: 'tr', + }, + { + children: [ + { + children: [{ children: [{ text: 'Alça de Arrastar' }], type: 'p' }], + type: 'td', + }, + { + children: [ + { + attributes: { align: 'center' }, + children: [{ text: '✅' }], + type: 'p', + }, + ], + type: 'td', + }, + { + children: [{ children: [{ text: 'Extensão Paga' }], type: 'p' }], + type: 'td', + }, + ], + type: 'tr', + }, + { + children: [ + { + children: [ + { children: [{ text: 'Colaboração (Yjs)' }], type: 'p' }, + ], + type: 'td', + }, + { + children: [ + { + attributes: { align: 'center' }, + children: [{ text: '✅' }], + type: 'p', + }, + ], + type: 'td', + }, + { + children: [ + { children: [{ text: 'Hocuspocus (OSS/Pago)' }], type: 'p' }, + ], + type: 'td', + }, + ], + type: 'tr', + }, + ], + + colSizes: [160, 170, 200], + type: 'table', + }, + // Media Section + { + children: [{ text: 'Imagens e Mídia' }], + type: 'h3', + }, + { + children: [ + { + text: 'Incorpore mídia rica como imagens diretamente em seu conteúdo. Suporta ', + }, + { + children: [{ text: 'Uploads de mídia' }], + type: 'a', + url: '/docs/media', + }, + { + text: ' e ', + }, + { + children: [{ text: 'arrastar e soltar' }], + type: 'a', + url: '/docs/dnd', + }, + { + text: ' para uma experiência suave.', + }, + ], + type: 'p', + }, + { + attributes: { align: 'center' }, + caption: [ + { + children: [{ text: 'Imagens com legendas fornecem contexto.' }], + type: 'p', + }, + ], + children: [{ text: '' }], + type: 'img', + url: 'https://images.unsplash.com/photo-1712688930249-98e1963af7bd?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D', + width: '75%', + }, + { + children: [{ text: '' }], + isUpload: true, + name: 'exemplo.pdf', + type: 'file', + url: 'https://s26.q4cdn.com/900411403/files/doc_downloads/test.pdf', + }, + { + children: [{ text: '' }], + type: 'audio', + url: 'https://samplelib.com/lib/preview/mp3/sample-3s.mp3', + }, + { + children: [{ text: 'Índice' }], + type: 'h3', + }, + { + children: [{ text: '' }], + type: 'toc', + }, + { + children: [{ text: '' }], + type: 'p', + }, +]; diff --git a/apps/www/src/registry/examples/values/pt-br/plugin-rules-value.tsx b/apps/www/src/registry/examples/values/pt-br/plugin-rules-value.tsx new file mode 100644 index 0000000000..6e67552aa8 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/plugin-rules-value.tsx @@ -0,0 +1,100 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const pluginRulesValue: any = ( + + Regras de Plugin + + Regras de plugin controlam como os blocos respondem a Enter, Backspace, + seleção e normalização. + + + Regras de Quebra (Break) + + + Divisão e Redefinição de Título (splitReset):{' '} + Pressione Enter no meio do título para dividir e redefinir o novo bloco + para parágrafo. + + + Pressione Enter após "Pressione" para ver o comportamento de splitReset + + + + Citação em bloco com quebras de linha: Enter adiciona + quebras de linha, Enter em linhas vazias redefine para parágrafo. + + + Esta citação em bloco usa regras de quebra de linha. Pressione Enter aqui + para quebras de linha. + + + Regras de Exclusão (Delete) + + + Redefinição de bloco de código: Backspace em bloco de + código vazio redefine para parágrafo. + + + console.info('Olá mundo'); + + + + + + + Itens de lista: Backspace no início remove a + formatação de lista. + + + Pressione Backspace no início para remover a formatação de lista + + + Regras de Seleção + + + Afinidade rígida (código): Use as setas ao redor de{' '} + marcas de código - requer dois pressionamentos de + tecla para cruzar fronteiras. + + + + Afinidade direcional: Use as setas ao redor de texto{' '} + sobrescrito - a afinidade do cursor depende da + direção do movimento. + + + + Link direcional: Navegue com as setas ao redor{' '} + deste link para testar o comportamento + direcional. + + + Regras de Normalização + + + Remoção de link vazio: Exclua todo o texto{' '} + deste link - o elemento de link será + removido automaticamente. + + + Regras de Mesclagem (Merge) + + + Elementos vazios (Void): + + + + Pressione Backspace no início - o elemento vazio é selecionado em vez de + excluído. + + + + + + Backspace no início remove o parágrafo vazio acima + +); diff --git a/apps/www/src/registry/examples/values/pt-br/preview-md-value.tsx b/apps/www/src/registry/examples/values/pt-br/preview-md-value.tsx new file mode 100644 index 0000000000..aa6301cc7e --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/preview-md-value.tsx @@ -0,0 +1,22 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const previewMdValue: any = ( + + 👀 Pré-visualização Markdown + + O Slate é flexível o suficiente para adicionar **decorações** que podem + formatar texto com base em seu conteúdo. Por exemplo, este editor tem + decorações de pré-visualização **Markdown** nele, para tornar _muito_ + simples fazer um editor com pré-visualização de `Markdown` integrada. + + - Lista. + Citação em bloco. + --- + ## Experimente! + Experimente você mesmo! + +); diff --git a/apps/www/src/registry/examples/values/pt-br/slash-command-value.tsx b/apps/www/src/registry/examples/values/pt-br/slash-command-value.tsx new file mode 100644 index 0000000000..edc91767c6 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/slash-command-value.tsx @@ -0,0 +1,46 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const slashCommandValue: any = ( + + + Comando de Barra + + + + O menu de barra fornece acesso rápido a várias opções de formatação e + tipos de conteúdo. + + + + + Digite '/' em qualquer lugar do seu documento para abrir o menu de + barra. + + + + + Comece a digitar para filtrar opções ou use as setas para navegar. + + + + Pressione Enter ou clique para selecionar uma opção. + + + Pressione Esc para fechar o menu sem selecionar. + + Opções disponíveis incluem: + + Títulos: Título 1, Título 2, Título 3 + + + Listas: Lista com marcadores, Lista numerada + + + Elementos Inline: Data + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/soft-break-value.tsx b/apps/www/src/registry/examples/values/pt-br/soft-break-value.tsx new file mode 100644 index 0000000000..6454d84444 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/soft-break-value.tsx @@ -0,0 +1,27 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const softBreakValue: any = ( + + Quebra Suave + + Personalize como quebras suaves (quebras de linha dentro de um parágrafo) + são tratadas usando regras configuráveis + + + hotkey – Use teclas de atalho como ⇧⏎ para inserir uma quebra suave em + qualquer lugar dentro de um parágrafo. + + + query – Defina regras personalizadas para limitar quebras suaves a tipos + de blocos específicos. + + Tente aqui ⏎ + + E aqui ⏎ também. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/tabbable-value.tsx b/apps/www/src/registry/examples/values/pt-br/tabbable-value.tsx new file mode 100644 index 0000000000..025a6e75d9 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/tabbable-value.tsx @@ -0,0 +1,55 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const tabbableValue: any = ( + + Tabbable (Navegação por Tab) + + Garanta uma experiência de navegação por tab suave dentro do seu editor + com o plugin Tabbable. + + + Lide corretamente com ordens de tabulação para nós vazios (void nodes), + permitindo navegação e interação contínuas. Sem este plugin, elementos DOM + dentro de nós vazios vêm após o editor na ordem de tabulação. + + + + + + + + Coloque seu cursor aqui e tente pressionar tab ou shift+tab. + + Item de lista 1 + + + Item de lista 2 + + + Item de lista 3 + + + if (true) {'{'} + + {'// <-'} Coloque o cursor no início da linha e pressione tab + + {'}'} + + + Neste exemplo, o plugin está desativado quando o cursor está dentro de uma + lista ou um bloco de código. Você pode personalizar isso usando a opção{' '} + query. + + + + + + Quando você pressiona tab no final do editor, o foco deve ir para o botão + abaixo. + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/table-value.tsx b/apps/www/src/registry/examples/values/pt-br/table-value.tsx new file mode 100644 index 0000000000..bf81607be7 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/table-value.tsx @@ -0,0 +1,119 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const createTable = (spanning?: boolean): any => ( + + + {spanning ? ( + + + + Plugin + + + + ) : ( + + + + Plugin + + + + + Elemento + + + + + Inline + + + + + Void + + + + )} + + + + + Título + + + + + + + + + + + + + + Não + + + + + + Imagem + + + + Sim + + + Não + + + Sim + + + + + + Menção + + + + Sim + + + Sim + + + Sim + + + + +); + +export const tableValue: any = ( + + Tabela + + Crie tabelas personalizáveis com colunas e linhas redimensionáveis, + permitindo que você projete layouts estruturados. + + {createTable()} + +); + +export const tableMergeValue: any = ( + + Mesclagem de Tabela + + Você pode desativar a mesclagem usando a opção{' '} + disableMerge: true. Experimente: + + {createTable(true)} + +); diff --git a/apps/www/src/registry/examples/values/pt-br/toc-value.tsx b/apps/www/src/registry/examples/values/pt-br/toc-value.tsx new file mode 100644 index 0000000000..c23400db4c --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/toc-value.tsx @@ -0,0 +1,66 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const tocValue: any = ( + + + Índice (Table of Contents) + + + + O recurso de Índice (TOC) permite que você crie uma visão geral + atualizada automaticamente da estrutura do seu documento. + + + Como usar o Índice: + + Digite "/toc" e pressione Enter para criar o TOC. + + + + O TOC é atualizado automaticamente quando você modifica títulos no + documento. + + + + + + Conteúdo de Exemplo + + + Este é um exemplo de conteúdo que seria refletido no Índice. + + + Subseção + + + Adicionar ou modificar títulos em seu documento atualizará + automaticamente o TOC. + + + Benefícios de Usar TOC + + + Um Índice melhora a navegação do documento e fornece uma rápida visão + geral da estrutura do seu conteúdo. + + + +); + +export const tocPlaygroundValue: any = ( + + + + + + + Clique em qualquer título no índice para rolar suavemente para essa + seção. + + + +); diff --git a/apps/www/src/registry/examples/values/pt-br/toggle-value.tsx b/apps/www/src/registry/examples/values/pt-br/toggle-value.tsx new file mode 100644 index 0000000000..6e8f155f99 --- /dev/null +++ b/apps/www/src/registry/examples/values/pt-br/toggle-value.tsx @@ -0,0 +1,19 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@platejs/test-utils'; + +jsx; + +export const toggleValue: any = ( + + Alternância (Toggle) + Crie alternâncias com múltiplos níveis de indentação + Alternância nível 1 + Dentro da alternância nível 1 + + Alternância nível 2 + + Dentro da alternância nível 2 + Após alternâncias + +); diff --git a/languine.json b/languine.json index b5f03842ae..858fa35001 100644 --- a/languine.json +++ b/languine.json @@ -1,12 +1,16 @@ { "language": { "source": "en", - "targets": ["cn"] + "targets": ["cn", "pt-br"] }, "content": [ { "source": "docs/*.mdx", "target": "docs/*.cn.mdx" + }, + { + "source": "docs/*.mdx", + "target": "docs/*.pt-br.mdx" } ] } diff --git a/tooling/scripts/translate.mjs b/tooling/scripts/translate.mjs index 24f2cb483b..7d337db450 100644 --- a/tooling/scripts/translate.mjs +++ b/tooling/scripts/translate.mjs @@ -14,6 +14,22 @@ import path from 'node:path'; // Load environment variables import OpenAI from 'openai'; +// Read languine configuration +const readConfig = () => { + try { + const configPath = path.resolve(process.cwd(), 'languine.json'); + const configContent = fs.readFileSync(configPath, 'utf8'); + return JSON.parse(configContent); + } catch (error) { + console.error('Error reading languine.json:', error); + process.exit(1); + } +}; + +const config = readConfig(); +const { content: contentConfig, language } = config; +const targets = language?.targets || []; + const TARGET_DIR = 'docs'; const DAYS = Number(process.argv[2]) || 60; // 默认 60 天 const CUTOFF = Date.now() - DAYS * 24 * 60 * 60 * 1000; @@ -33,7 +49,7 @@ console.error(`Scanning ${files.length} files… (cutoff = ${DAYS} days)`); // 2) 查询最后提交时间并过滤 const results = files - .filter((f) => !f.endsWith('.cn.mdx')) // 过滤掉以.cn.mdx结尾的文件 + .filter((f) => !targets.some((target) => f.endsWith(`.${target}.mdx`))) // 过滤掉翻译文件 .flatMap((f) => { const out = spawnSync('git', ['log', '-1', '--format=%ci', '--', f], { encoding: 'utf8', @@ -55,32 +71,34 @@ const openai = new OpenAI({ baseURL: 'https://api.deepseek.com', }); -// Read languine configuration -const readConfig = () => { - try { - const configPath = path.resolve(process.cwd(), 'languine.json'); - const configContent = fs.readFileSync(configPath, 'utf8'); - return JSON.parse(configContent); - } catch (error) { - console.error('Error reading languine.json:', error); - process.exit(1); - } -}; - // Translate content using OpenAI async function translateContent(content, targetLanguage) { try { - const response = await openai.chat.completions.create({ - messages: [ - { - content: `You are a professional translator. Translate the following MDX content from English to ${targetLanguage}. + let systemPrompt = `You are a professional translator. Translate the following MDX content from English to ${targetLanguage}. Preserve all Markdown formatting, code blocks, and component tags. Do not translate code inside code blocks or component names. - The content is in .mdx format, which combines Markdown with JSX components. + The content is in .mdx format, which combines Markdown with JSX components.`; + + if (targetLanguage === 'cn') { + systemPrompt += ` - Do not translate the provider as 提供者, just keep it as provider. - Do not translate the entry as 条目, just keep it as entry. - Do not translate the leaf as 叶子, just keep it as leaf. - Do not translate the element as 元素, just keep it as element. - `, + `; + } + + if (targetLanguage === 'pt-br') { + systemPrompt += ` + - Do not translate the provider as Provedor, just keep it as provider. + - Do not translate the entry as Entrada, just keep it as entry. + - Do not translate the leaf as Folha, just keep it as leaf. + `; + } + + const response = await openai.chat.completions.create({ + messages: [ + { + content: systemPrompt, role: 'system', }, { @@ -100,9 +118,6 @@ async function translateContent(content, targetLanguage) { // Process files for translation async function processTranslation() { - const config = readConfig(); - const { content: contentConfig, language } = config; - if (!language?.source || !language.targets || !contentConfig) { console.error('Invalid configuration in languine.json'); process.exit(1); @@ -113,8 +128,8 @@ async function processTranslation() { const sourceContent = fs.readFileSync(sourceFile, 'utf8'); for (const targetLanguage of language.targets) { - // Add .cn.mdx suffix to the source file path - const targetFile = sourceFile.replace('.mdx', '.cn.mdx'); + // Add target suffix to the source file path + const targetFile = sourceFile.replace('.mdx', `.${targetLanguage}.mdx`); console.info( `Translating ${sourceFile} to ${targetLanguage} (${targetFile})`