From 7c216d4b625c9a8db751b7026f27857cce2f9cbb Mon Sep 17 00:00:00 2001 From: ocp1006 <130064802+ocp1006@users.noreply.github.com> Date: Mon, 3 Aug 2026 23:41:57 +0300 Subject: [PATCH 1/3] feat: add code block word wrap --- .../code_block_language_selector_test.dart | 188 +++++++++++++++++- .../presentation/editor_configuration.dart | 4 +- .../code_block/code_block_component.dart | 62 ++++++ .../code_block/code_block_copy_button.dart | 67 ++++++- .../presentation/editor_plugins/plugins.dart | 1 + frontend/resources/translations/en-US.json | 1 + 6 files changed, 315 insertions(+), 8 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_component.dart diff --git a/frontend/appflowy_flutter/integration_test/desktop/uncategorized/code_block_language_selector_test.dart b/frontend/appflowy_flutter/integration_test/desktop/uncategorized/code_block_language_selector_test.dart index e522e2fc73c2c..b906582aacc9e 100644 --- a/frontend/appflowy_flutter/integration_test/desktop/uncategorized/code_block_language_selector_test.dart +++ b/frontend/appflowy_flutter/integration_test/desktop/uncategorized/code_block_language_selector_test.dart @@ -1,8 +1,12 @@ import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/code_block/code_block_component.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/code_block/code_block_copy_button.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/code_block/code_block_language_selector.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; @@ -10,20 +14,20 @@ import 'package:integration_test/integration_test.dart'; import '../../shared/base.dart'; import '../../shared/common_operations.dart'; import '../../shared/document_test_operations.dart'; +import '../../shared/expectation.dart'; import '../document/document_codeblock_paste_test.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); testWidgets('Code Block Language Selector Test', (tester) async { - await tester.initializeAppFlowy(); - await tester.tapAnonymousSignInButton(); + await _initializeCodeBlockTest(tester); /// create a new document - await tester.createNewPageWithNameUnderParent(); + await tester.tapNewPageButton(); /// tap editor to get focus - await tester.tapButton(find.byType(AppFlowyEditor)); + await tester.editor.tapLineOfEditorAt(0); expect(find.byType(CodeBlockLanguageSelector), findsNothing); await insertCodeBlockInDocument(tester); @@ -83,6 +87,182 @@ void main() { .toString(); expect(language.toLowerCase(), 'rust'); }); + + testWidgets('Code blocks wrap independently and persist their state', ( + tester, + ) async { + await _initializeCodeBlockTest(tester); + + const documentName = 'Code block wrap test'; + const otherDocumentName = 'Other document'; + final longText = List.filled(500, 'x').join(); + final longLine = 'final value = "$longText";'; + + await tester.createNewPageWithNameUnderParent(name: documentName); + await tester.tapButton(find.byType(AppFlowyEditor)); + await insertCodeBlockInDocument(tester); + tester.testTextInput.enterText(longLine); + await tester.pumpAndSettle(); + + var editorState = tester.editor.getCurrentEditorState(); + await editorState.apply( + editorState.transaction + ..insertNode( + [1], + codeBlockNode(delta: Delta()..insert(longLine)), + ), + ); + await tester.pumpAndSettle(); + + var codeBlocks = find.byType(CodeBlockComponentWidget); + expect(codeBlocks, findsNWidgets(2)); + expect( + editorState + .getNodeAtPath([0])!.attributes[AppFlowyCodeBlockKeys.wrapLines], + isNull, + ); + expect( + tester + .widget(codeBlocks.first) + .style + ?.wrapLines, + isFalse, + ); + expect( + find.descendant( + of: codeBlocks.first, + matching: find.byType(SingleChildScrollView), + ), + findsOneWidget, + ); + final unwrappedHeight = tester.getSize(codeBlocks.first).height; + + await tester.hoverOnWidget(codeBlocks.first); + final firstWrapButton = find.descendant( + of: codeBlocks.first, + matching: find.byKey(codeBlockWrapButtonKey), + ); + expect(firstWrapButton, findsOneWidget); + expect( + tester.widget(firstWrapButton).tooltipText, + LocaleKeys.document_codeBlock_wrapTooltip.tr(), + ); + expect( + tester.widget(firstWrapButton).isSelected, + isFalse, + ); + await tester.tapButton(firstWrapButton); + await tester.pumpAndSettle(); + + codeBlocks = find.byType(CodeBlockComponentWidget); + expect( + editorState + .getNodeAtPath([0])!.attributes[AppFlowyCodeBlockKeys.wrapLines], + isTrue, + ); + expect( + editorState + .getNodeAtPath([1])!.attributes[AppFlowyCodeBlockKeys.wrapLines], + isNull, + ); + expect( + tester + .widget(codeBlocks.first) + .style + ?.wrapLines, + isTrue, + ); + expect( + tester.widget(firstWrapButton).isSelected, + isTrue, + ); + expect( + tester + .widget(codeBlocks.at(1)) + .style + ?.wrapLines, + isFalse, + ); + expect( + find.descendant( + of: codeBlocks.first, + matching: find.byType(SingleChildScrollView), + ), + findsNothing, + ); + final wrappedHeight = tester.getSize(codeBlocks.first).height; + expect(wrappedHeight, greaterThan(unwrappedHeight)); + + await tester.createNewPageWithNameUnderParent(name: otherDocumentName); + await tester.openPage(documentName); + await tester.pumpAndSettle(); + + editorState = tester.editor.getCurrentEditorState(); + codeBlocks = find.byType(CodeBlockComponentWidget); + expect(codeBlocks, findsNWidgets(2)); + expect( + editorState + .getNodeAtPath([0])!.attributes[AppFlowyCodeBlockKeys.wrapLines], + isTrue, + ); + expect( + tester + .widget(codeBlocks.first) + .style + ?.wrapLines, + isTrue, + ); + + await tester.hoverOnWidget(codeBlocks.first); + await tester.tapButton( + find.descendant( + of: codeBlocks.first, + matching: find.byKey(codeBlockWrapButtonKey), + ), + ); + await tester.pumpAndSettle(); + + codeBlocks = find.byType(CodeBlockComponentWidget); + expect( + editorState + .getNodeAtPath([0])!.attributes[AppFlowyCodeBlockKeys.wrapLines], + isFalse, + ); + expect( + tester + .widget(codeBlocks.first) + .style + ?.wrapLines, + isFalse, + ); + expect( + tester + .widget( + find.descendant( + of: codeBlocks.first, + matching: find.byKey(codeBlockWrapButtonKey), + ), + ) + .isSelected, + isFalse, + ); + expect(tester.getSize(codeBlocks.first).height, lessThan(wrappedHeight)); + }); +} + +Future _initializeCodeBlockTest(WidgetTester tester) async { + await tester.initializeAppFlowy(); + await tester.tapAnonymousSignInButton(); + + final gettingStartedPage = find.textContaining( + gettingStarted, + findRichText: true, + ); + await tester.pumpUntilFound( + gettingStartedPage, + timeout: const Duration(seconds: 30), + ); + expect(gettingStartedPage, findsAtLeastNWidgets(1)); } Future onKey(WidgetTester tester, LogicalKeyboardKey key) async { diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart index 2f7a941836239..77e74ceaa30e2 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart @@ -878,12 +878,12 @@ MathEquationBlockComponentBuilder _buildMathEquationBlockComponentBuilder( ); } -CodeBlockComponentBuilder _buildCodeBlockComponentBuilder( +AppFlowyCodeBlockComponentBuilder _buildCodeBlockComponentBuilder( BuildContext context, BlockComponentConfiguration configuration, EditorStyleCustomizer styleCustomizer, ) { - return CodeBlockComponentBuilder( + return AppFlowyCodeBlockComponentBuilder( styleBuilder: styleCustomizer.codeBlockStyleBuilder, configuration: configuration, padding: const EdgeInsets.only(left: 20, right: 30, bottom: 34), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_component.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_component.dart new file mode 100644 index 0000000000000..12d45899715ae --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_component.dart @@ -0,0 +1,62 @@ +import 'package:appflowy_editor/appflowy_editor.dart'; +import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart'; + +class AppFlowyCodeBlockKeys { + const AppFlowyCodeBlockKeys._(); + + /// Whether long lines should wrap inside the code block. + /// + /// The value is a bool and defaults to false when absent or invalid. + static const String wrapLines = 'wrap_lines'; +} + +extension AppFlowyCodeBlockNodeExtension on Node { + bool get codeBlockWrapLines => + attributes[AppFlowyCodeBlockKeys.wrapLines] == true; +} + +/// Adds AppFlowy-specific, per-node styling to the editor plugin's code block. +class AppFlowyCodeBlockComponentBuilder extends CodeBlockComponentBuilder { + AppFlowyCodeBlockComponentBuilder({ + required CodeBlockStyle Function() styleBuilder, + required super.configuration, + required super.padding, + required CodeBlockLanguagePickerBuilder languagePickerBuilder, + required CodeBlockCopyBuilder copyButtonBuilder, + }) : super( + styleBuilder: styleBuilder, + languagePickerBuilder: languagePickerBuilder, + copyButtonBuilder: copyButtonBuilder, + ); + + @override + BlockComponentWidget build(BlockComponentContext blockComponentContext) { + final node = blockComponentContext.node; + final wrapLines = node.codeBlockWrapLines; + final baseStyle = styleBuilder?.call() ?? const CodeBlockStyle(); + + return CodeBlockComponentWidget( + key: node.key, + node: node, + configuration: configuration, + padding: padding, + showActions: showActions(node), + actionBuilder: (_, state) => actionBuilder( + blockComponentContext, + state, + ), + actionWrapperBuilder: actionWrapperBuilder, + style: CodeBlockStyle( + textStyle: baseStyle.textStyle, + backgroundColor: baseStyle.backgroundColor, + foregroundColor: baseStyle.foregroundColor, + showLineNumbers: wrapLines ? false : baseStyle.showLineNumbers, + wrapLines: wrapLines, + ), + languagePickerBuilder: languagePickerBuilder, + actions: actions, + copyButtonBuilder: copyButtonBuilder, + localizations: localizations, + ); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_copy_button.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_copy_button.dart index 645de3b2f8e74..18ae53236c6ce 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_copy_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_copy_button.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/code_block/code_block_component.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; @@ -12,9 +13,71 @@ import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; import 'package:flutter/material.dart'; +import 'package:universal_platform/universal_platform.dart'; -CodeBlockCopyBuilder codeBlockCopyBuilder = - (_, node) => _CopyButton(node: node); +const codeBlockWrapButtonKey = ValueKey('code_block_wrap_button'); + +CodeBlockCopyBuilder codeBlockCopyBuilder = (editorState, node) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (UniversalPlatform.isDesktopOrWeb) + _WrapCodeButton( + editorState: editorState, + node: node, + ), + _CopyButton(node: node), + ], + ); +}; + +class _WrapCodeButton extends StatelessWidget { + const _WrapCodeButton({ + required this.editorState, + required this.node, + }); + + final EditorState editorState; + final Node node; + + @override + Widget build(BuildContext context) { + final isWrapped = node.codeBlockWrapLines; + final colorScheme = Theme.of(context).colorScheme; + final tooltip = LocaleKeys.document_codeBlock_wrapTooltip.tr(); + + return Padding( + padding: const EdgeInsets.all(4), + child: Semantics( + label: tooltip, + button: true, + toggled: isWrapped, + child: FlowyIconButton( + key: codeBlockWrapButtonKey, + tooltipText: tooltip, + isSelected: isWrapped, + fillColor: + isWrapped ? colorScheme.secondaryContainer : Colors.transparent, + hoverColor: colorScheme.secondaryContainer, + onPressed: () async { + final transaction = editorState.transaction + ..updateNode( + node, + {AppFlowyCodeBlockKeys.wrapLines: !isWrapped}, + ); + await editorState.apply(transaction); + }, + icon: Icon( + Icons.wrap_text_rounded, + color: isWrapped + ? colorScheme.primary + : AFThemeExtension.of(context).textColor, + ), + ), + ), + ); + } +} class _CopyButton extends StatelessWidget { const _CopyButton({required this.node}); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart index 4161036a0839b..c82ccae60e84c 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart @@ -8,6 +8,7 @@ export 'base/cover_title_command.dart'; export 'base/toolbar_extension.dart'; export 'bulleted_list/bulleted_list_icon.dart'; export 'callout/callout_block_component.dart'; +export 'code_block/code_block_component.dart'; export 'code_block/code_block_language_selector.dart'; export 'code_block/code_block_menu_item.dart'; export 'columns/simple_column_block_component.dart'; diff --git a/frontend/resources/translations/en-US.json b/frontend/resources/translations/en-US.json index 56f19a91feabf..29a3790d5ad85 100644 --- a/frontend/resources/translations/en-US.json +++ b/frontend/resources/translations/en-US.json @@ -2176,6 +2176,7 @@ "auto": "Auto" }, "copyTooltip": "Copy", + "wrapTooltip": "Wrap code", "searchLanguageHint": "Search for a language", "codeCopiedSnackbar": "Code copied to clipboard!" }, From adc21369bb5deb58ccef0fc625f9ee04f41745d5 Mon Sep 17 00:00:00 2001 From: ocp1006 <130064802+ocp1006@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:03:11 +0300 Subject: [PATCH 2/3] fix: add code wrap translations --- frontend/resources/translations/ar-SA.json | 3 ++- frontend/resources/translations/ca-ES.json | 5 +++-- frontend/resources/translations/ckb-KU.json | 5 +++-- frontend/resources/translations/cs-CZ.json | 5 +++-- frontend/resources/translations/de-DE.json | 3 ++- frontend/resources/translations/en-GB.json | 3 ++- frontend/resources/translations/es-VE.json | 3 ++- frontend/resources/translations/eu-ES.json | 5 +++-- frontend/resources/translations/fa.json | 5 +++-- frontend/resources/translations/fr-CA.json | 5 +++-- frontend/resources/translations/fr-FR.json | 3 ++- frontend/resources/translations/ga-IE.json | 7 ++++++- frontend/resources/translations/he.json | 3 ++- frontend/resources/translations/hu-HU.json | 5 +++-- frontend/resources/translations/id-ID.json | 5 +++-- frontend/resources/translations/it-IT.json | 5 +++-- frontend/resources/translations/ja-JP.json | 3 ++- frontend/resources/translations/ko-KR.json | 3 ++- frontend/resources/translations/pl-PL.json | 5 +++-- frontend/resources/translations/pt-BR.json | 5 +++-- frontend/resources/translations/pt-PT.json | 5 +++-- frontend/resources/translations/ru-RU.json | 3 ++- frontend/resources/translations/sv-SE.json | 5 +++-- frontend/resources/translations/th-TH.json | 3 ++- frontend/resources/translations/tr-TR.json | 3 ++- frontend/resources/translations/uk-UA.json | 3 ++- frontend/resources/translations/vi-VN.json | 3 ++- frontend/resources/translations/vi.json | 7 ++++++- frontend/resources/translations/zh-CN.json | 5 +++-- frontend/resources/translations/zh-TW.json | 3 ++- 30 files changed, 82 insertions(+), 44 deletions(-) diff --git a/frontend/resources/translations/ar-SA.json b/frontend/resources/translations/ar-SA.json index 7f78ca3ca3863..e90b48db19121 100644 --- a/frontend/resources/translations/ar-SA.json +++ b/frontend/resources/translations/ar-SA.json @@ -2206,6 +2206,7 @@ "auto": "آلي" }, "copyTooltip": "نسخ", + "wrapTooltip": "لف الكود", "searchLanguageHint": "ابحث عن لغة", "codeCopiedSnackbar": "تم نسخ الكود إلى الحافظة!" }, @@ -3428,4 +3429,4 @@ "rewrite": "إعادة كتابة", "insertBelow": "أدخل أدناه" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/ca-ES.json b/frontend/resources/translations/ca-ES.json index 091a8b37871ac..b2f7f76bb609c 100644 --- a/frontend/resources/translations/ca-ES.json +++ b/frontend/resources/translations/ca-ES.json @@ -734,7 +734,8 @@ "language": { "label": "Llenguatge", "placeholder": "Escolliu l'idioma" - } + }, + "wrapTooltip": "Ajusta el codi" }, "inlineLink": { "placeholder": "Enganxeu o escriviu un enllaç", @@ -811,4 +812,4 @@ "deleteContentTitle": "Esteu segur que voleu suprimir {pageType}?", "deleteContentCaption": "si suprimiu aquest {pageType}, podeu restaurar-lo des de la paperera." } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/ckb-KU.json b/frontend/resources/translations/ckb-KU.json index ea90f9c0feac9..ea0bfff83f056 100644 --- a/frontend/resources/translations/ckb-KU.json +++ b/frontend/resources/translations/ckb-KU.json @@ -830,7 +830,8 @@ "language": { "label": "زمان", "placeholder": "هەڵبژاردنی زمان" - } + }, + "wrapTooltip": "پێچانەوەی کۆد" }, "inlineLink": { "placeholder": "ڕێڕەوەکە بلکێنە یان بینووسە", @@ -941,4 +942,4 @@ "frequentlyUsed": "زۆرجار بەکارت هێناوە" } } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/cs-CZ.json b/frontend/resources/translations/cs-CZ.json index 0558ccb52c1da..589c3f514e14c 100644 --- a/frontend/resources/translations/cs-CZ.json +++ b/frontend/resources/translations/cs-CZ.json @@ -1156,7 +1156,8 @@ "language": { "label": "Jazyk", "placeholder": "Vyberte jazyk" - } + }, + "wrapTooltip": "Zalamovat kód" }, "inlineLink": { "placeholder": "Vložte nebo napište odkaz", @@ -1504,4 +1505,4 @@ "font": "Písmo", "actions": "Příkazy" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/de-DE.json b/frontend/resources/translations/de-DE.json index a7dff3048255a..81a8dcd71f713 100644 --- a/frontend/resources/translations/de-DE.json +++ b/frontend/resources/translations/de-DE.json @@ -2031,6 +2031,7 @@ "auto": "Auto" }, "copyTooltip": "Inhalt des Codeblocks kopieren", + "wrapTooltip": "Code umbrechen", "searchLanguageHint": "Nach einer Sprache suchen", "codeCopiedSnackbar": "Code in die Zwischenablage kopiert!" }, @@ -2864,4 +2865,4 @@ "permissionDenied": "Keine Berechtigung zum Öffnen dieser Datei", "unknownError": "Öffnen der Datei fehlgeschlagen" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/en-GB.json b/frontend/resources/translations/en-GB.json index 38025c4fd4499..bc5340238ae16 100644 --- a/frontend/resources/translations/en-GB.json +++ b/frontend/resources/translations/en-GB.json @@ -2086,6 +2086,7 @@ "auto": "Auto" }, "copyTooltip": "Copy", + "wrapTooltip": "Wrap code", "searchLanguageHint": "Search for a language", "codeCopiedSnackbar": "Code copied to clipboard!" }, @@ -3209,4 +3210,4 @@ "rewrite": "Rewrite", "insertBelow": "Insert below" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/es-VE.json b/frontend/resources/translations/es-VE.json index dcf578b50c60a..3be4b552dc575 100644 --- a/frontend/resources/translations/es-VE.json +++ b/frontend/resources/translations/es-VE.json @@ -1099,6 +1099,7 @@ "auto": "Auto" }, "copyTooltip": "Copiar el contenido del bloque de código.", + "wrapTooltip": "Ajustar código", "searchLanguageHint": "Buscar un idioma", "codeCopiedSnackbar": "¡Código copiado al portapapeles!" }, @@ -1587,4 +1588,4 @@ "betaTooltip": "Actualmente solo admitimos la búsqueda de páginas.", "fromTrashHint": "De la papelera" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/eu-ES.json b/frontend/resources/translations/eu-ES.json index 1f3c04239a0d4..8eaab9b8d28c8 100644 --- a/frontend/resources/translations/eu-ES.json +++ b/frontend/resources/translations/eu-ES.json @@ -527,7 +527,8 @@ "language": { "label": "Hizkuntza", "placeholder": "Hautatu hizkuntza" - } + }, + "wrapTooltip": "Egokitu kodea" }, "inlineLink": { "placeholder": "Itsatsi edo idatzi esteka bat", @@ -600,4 +601,4 @@ "deleteContentTitle": "Ziur {pageType} ezabatu nahi duzula?", "deleteContentCaption": "{pageType} hau ezabatzen baduzu, zaborrontzitik leheneratu dezakezu." } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/fa.json b/frontend/resources/translations/fa.json index c988c8f22437a..4f3ce739df7d1 100644 --- a/frontend/resources/translations/fa.json +++ b/frontend/resources/translations/fa.json @@ -593,7 +593,8 @@ "language": { "label": "زبان", "placeholder": "انتخاب زبان" - } + }, + "wrapTooltip": "شکستن خطوط کد" }, "inlineLink": { "placeholder": "پیست کنید یا مسیر را تایپ کنید", @@ -704,4 +705,4 @@ "frequentlyUsed": "استفاده‌شده" } } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/fr-CA.json b/frontend/resources/translations/fr-CA.json index 637c4d5ad1d14..f420b678c6c0a 100644 --- a/frontend/resources/translations/fr-CA.json +++ b/frontend/resources/translations/fr-CA.json @@ -910,7 +910,8 @@ "language": { "label": "Langue", "placeholder": "Choisir la langue" - } + }, + "wrapTooltip": "Envelopper le code" }, "inlineLink": { "placeholder": "Coller ou saisir un lien", @@ -1313,4 +1314,4 @@ "userIcon": "Icône utilisateur" }, "noLogFiles": "Il n'y a pas de log" -} \ No newline at end of file +} diff --git a/frontend/resources/translations/fr-FR.json b/frontend/resources/translations/fr-FR.json index 8f75c0d7d2e1e..cd6f5677d514d 100644 --- a/frontend/resources/translations/fr-FR.json +++ b/frontend/resources/translations/fr-FR.json @@ -2206,6 +2206,7 @@ "auto": "Auto" }, "copyTooltip": "Copier le contenu du bloc de code", + "wrapTooltip": "Envelopper le code", "searchLanguageHint": "Rechercher une langue", "codeCopiedSnackbar": "Code copié dans le presse-papier !" }, @@ -3403,4 +3404,4 @@ "rewrite": "Récrire", "insertBelow": "Insérer ci-dessous" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/ga-IE.json b/frontend/resources/translations/ga-IE.json index a47c5f157ca01..73a51d4734bcb 100644 --- a/frontend/resources/translations/ga-IE.json +++ b/frontend/resources/translations/ga-IE.json @@ -115,5 +115,10 @@ "import": "Iompórtáil", "createdAt": "Cruthaithe: {}", "deleteView": "Scrios" + }, + "document": { + "codeBlock": { + "wrapTooltip": "Timfhilleadh cód" + } } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/he.json b/frontend/resources/translations/he.json index 02c6831c334bb..77636703ebc6e 100644 --- a/frontend/resources/translations/he.json +++ b/frontend/resources/translations/he.json @@ -1490,6 +1490,7 @@ "auto": "אוטו׳" }, "copyTooltip": "העתקת תוכן למקטע קוד", + "wrapTooltip": "גלישת קוד", "searchLanguageHint": "חיפוש אחר שפה", "codeCopiedSnackbar": "הקוד הועתק ללוח הגזירים!" }, @@ -2080,4 +2081,4 @@ "signInError": "שגיאת כניסה", "login": "הרשמה או כניסה" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/hu-HU.json b/frontend/resources/translations/hu-HU.json index 7b948633ee080..0f772f862497b 100644 --- a/frontend/resources/translations/hu-HU.json +++ b/frontend/resources/translations/hu-HU.json @@ -529,7 +529,8 @@ "language": { "label": "Nyelv", "placeholder": "Válasszon nyelvet" - } + }, + "wrapTooltip": "Kód tördelése" }, "inlineLink": { "placeholder": "Illesszen be vagy írjon be egy hivatkozást", @@ -598,4 +599,4 @@ "deleteContentTitle": "Biztosan törli a következőt: {pageType}?", "deleteContentCaption": "ha törli ezt a {pageType} oldalt, visszaállíthatja a kukából." } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/id-ID.json b/frontend/resources/translations/id-ID.json index ee6b006bcc923..296116c19d7c6 100644 --- a/frontend/resources/translations/id-ID.json +++ b/frontend/resources/translations/id-ID.json @@ -738,7 +738,8 @@ "language": { "label": "Bahasa", "placeholder": "Pilih bahasa" - } + }, + "wrapTooltip": "Bungkus kode" }, "inlineLink": { "placeholder": "Tempel atau ketik tautan", @@ -1044,4 +1045,4 @@ "noFavorite": "Tidak ada halaman favorit", "noFavoriteHintText": "Geser halaman ke kiri untuk menambahkannya ke favorit Anda" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/it-IT.json b/frontend/resources/translations/it-IT.json index 417a9c3b2ce9c..de45dfff6969e 100644 --- a/frontend/resources/translations/it-IT.json +++ b/frontend/resources/translations/it-IT.json @@ -1765,7 +1765,8 @@ "language": { "label": "Lingua", "placeholder": "Seleziona la lingua" - } + }, + "wrapTooltip": "Testo del codice a capo" }, "inlineLink": { "placeholder": "Incolla o digita un link", @@ -2160,4 +2161,4 @@ "userIcon": "Icona utente" }, "noLogFiles": "Non ci sono file di log" -} \ No newline at end of file +} diff --git a/frontend/resources/translations/ja-JP.json b/frontend/resources/translations/ja-JP.json index c3127d83461df..a65e98589647e 100644 --- a/frontend/resources/translations/ja-JP.json +++ b/frontend/resources/translations/ja-JP.json @@ -1995,6 +1995,7 @@ "auto": "自動" }, "copyTooltip": "コピー", + "wrapTooltip": "コードを折り返す", "searchLanguageHint": "言語を検索", "codeCopiedSnackbar": "コードがクリップボードにコピーされました!" }, @@ -3047,4 +3048,4 @@ } } } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/ko-KR.json b/frontend/resources/translations/ko-KR.json index 585ce42071981..04c6a08f1a648 100644 --- a/frontend/resources/translations/ko-KR.json +++ b/frontend/resources/translations/ko-KR.json @@ -2071,6 +2071,7 @@ "auto": "자동" }, "copyTooltip": "복사", + "wrapTooltip": "코드 줄 바꿈", "searchLanguageHint": "언어 검색", "codeCopiedSnackbar": "코드가 클립보드에 복사되었습니다!" }, @@ -3184,4 +3185,4 @@ "rewrite": "다시 작성", "insertBelow": "아래에 삽입" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/pl-PL.json b/frontend/resources/translations/pl-PL.json index 2eadf0c7ea405..9025bcef8e3d8 100644 --- a/frontend/resources/translations/pl-PL.json +++ b/frontend/resources/translations/pl-PL.json @@ -805,7 +805,8 @@ "language": { "label": "Język", "placeholder": "Wybierz język" - } + }, + "wrapTooltip": "Zawijaj kod" }, "inlineLink": { "placeholder": "Wklej lub wpisz link", @@ -1145,4 +1146,4 @@ "language": "Język", "font": "Czcionka" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/pt-BR.json b/frontend/resources/translations/pt-BR.json index e7a785373dc46..81febcee12f88 100644 --- a/frontend/resources/translations/pt-BR.json +++ b/frontend/resources/translations/pt-BR.json @@ -1173,7 +1173,8 @@ "language": { "label": "Linguagem", "placeholder": "Selecione o idioma" - } + }, + "wrapTooltip": "Quebrar linhas do código" }, "inlineLink": { "placeholder": "Cole ou digite um link", @@ -1544,4 +1545,4 @@ "addField": "Adicionar campo", "userIcon": "Ícone do usuário" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/pt-PT.json b/frontend/resources/translations/pt-PT.json index e6e12e50131a3..bf718864776ed 100644 --- a/frontend/resources/translations/pt-PT.json +++ b/frontend/resources/translations/pt-PT.json @@ -687,7 +687,8 @@ "language": { "label": "Linguagem", "placeholder": "Selecione o idioma" - } + }, + "wrapTooltip": "Quebrar linhas do código" }, "inlineLink": { "placeholder": "Cole ou digite um link", @@ -856,4 +857,4 @@ "noResult": "Nenhum resultado", "caseSensitive": "Maiúsculas e minúsculas" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/ru-RU.json b/frontend/resources/translations/ru-RU.json index 239b4ecd12779..7bcc244e88cc5 100644 --- a/frontend/resources/translations/ru-RU.json +++ b/frontend/resources/translations/ru-RU.json @@ -2179,6 +2179,7 @@ "auto": "Авто" }, "copyTooltip": "Копировать", + "wrapTooltip": "Переносить код", "searchLanguageHint": "Поиск языка", "codeCopiedSnackbar": "Код скопирован в буфер обмена!" }, @@ -3385,4 +3386,4 @@ "rewrite": "Переписать", "insertBelow": "Вставить ниже" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/sv-SE.json b/frontend/resources/translations/sv-SE.json index d9673f0f1a2ef..904a852453e8c 100644 --- a/frontend/resources/translations/sv-SE.json +++ b/frontend/resources/translations/sv-SE.json @@ -593,7 +593,8 @@ "language": { "label": "Språk", "placeholder": "Välj språk" - } + }, + "wrapTooltip": "Radbryt kod" }, "inlineLink": { "placeholder": "Klistra in eller skriv en länk", @@ -662,4 +663,4 @@ "deleteContentTitle": "Är du säker på att du vill ta bort {pageType}?", "deleteContentCaption": "om du tar bort denna {pageType} kan du återställa den från papperskorgen." } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/th-TH.json b/frontend/resources/translations/th-TH.json index 2b86fff1e3324..5b21aabfff47a 100644 --- a/frontend/resources/translations/th-TH.json +++ b/frontend/resources/translations/th-TH.json @@ -1973,6 +1973,7 @@ "auto": "อัตโนมัติ" }, "copyTooltip": "สำเนา", + "wrapTooltip": "ตัดบรรทัดโค้ด", "searchLanguageHint": "ค้นหาภาษา", "codeCopiedSnackbar": "คัดลอกโค้ดไปยังคลิปบอร์ดแล้ว!" }, @@ -2910,4 +2911,4 @@ "pinTab": "ปักหมุด", "unpinTab": "ยกเลิกการปักหมุด" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/tr-TR.json b/frontend/resources/translations/tr-TR.json index f72a7f6d1399f..4858b1e2d99fb 100644 --- a/frontend/resources/translations/tr-TR.json +++ b/frontend/resources/translations/tr-TR.json @@ -2024,6 +2024,7 @@ "auto": "Otomatik" }, "copyTooltip": "Kopyala", + "wrapTooltip": "Kodu kaydır", "searchLanguageHint": "Bir dil arayın", "codeCopiedSnackbar": "Kod panoya kopyalandı!" }, @@ -3080,4 +3081,4 @@ "ai": { "contentPolicyViolation": "Hassas içerik nedeniyle görsel oluşturma başarısız oldu. Lütfen girdinizi yeniden düzenleyip tekrar deneyin" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/uk-UA.json b/frontend/resources/translations/uk-UA.json index 0feb431436c87..655e14f49768c 100644 --- a/frontend/resources/translations/uk-UA.json +++ b/frontend/resources/translations/uk-UA.json @@ -1778,6 +1778,7 @@ "auto": "Авто" }, "copyTooltip": "Скопіюйте вміст блоку коду", + "wrapTooltip": "Переносити код", "searchLanguageHint": "Пошук мови", "codeCopiedSnackbar": "Код скопійовано в буфер обміну!" }, @@ -2586,4 +2587,4 @@ "uploadFailedDescription": "Не вдалося завантажити файл", "uploadingDescription": "Файл завантажується" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/vi-VN.json b/frontend/resources/translations/vi-VN.json index e71ce37374bff..1c716a1df97be 100644 --- a/frontend/resources/translations/vi-VN.json +++ b/frontend/resources/translations/vi-VN.json @@ -1790,6 +1790,7 @@ "auto": "Tự động" }, "copyTooltip": "Sao chép", + "wrapTooltip": "Ngắt dòng mã", "searchLanguageHint": "Tìm kiếm một ngôn ngữ", "codeCopiedSnackbar": "Đã sao chép mã vào bảng tạm!" }, @@ -2564,4 +2565,4 @@ "zoomIn": "Phóng to", "zoomOut": "Thu nhỏ" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/vi.json b/frontend/resources/translations/vi.json index 4d1716447aa81..e07e0b6ceeda4 100644 --- a/frontend/resources/translations/vi.json +++ b/frontend/resources/translations/vi.json @@ -5,5 +5,10 @@ "showGroupContent": "Bạn có chắc chắn muốn hiển thị nhóm này trên bảng không?", "failedToLoad": "Không tải được chế độ xem bảng" } + }, + "document": { + "codeBlock": { + "wrapTooltip": "Ngắt dòng mã" + } } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/zh-CN.json b/frontend/resources/translations/zh-CN.json index c42166a525c58..7fe9c9f57c715 100644 --- a/frontend/resources/translations/zh-CN.json +++ b/frontend/resources/translations/zh-CN.json @@ -1599,7 +1599,8 @@ "placeholder": "选择语言", "auto": "自动" }, - "copyTooltip": "复制代码块的内容" + "copyTooltip": "复制代码块的内容", + "wrapTooltip": "代码自动换行" }, "inlineLink": { "placeholder": "粘贴或输入链接", @@ -2092,4 +2093,4 @@ "yesterday": "昨天", "today": "今天" } -} \ No newline at end of file +} diff --git a/frontend/resources/translations/zh-TW.json b/frontend/resources/translations/zh-TW.json index 09b332c73629e..b61225360b03f 100644 --- a/frontend/resources/translations/zh-TW.json +++ b/frontend/resources/translations/zh-TW.json @@ -2176,6 +2176,7 @@ "auto": "自動" }, "copyTooltip": "複製", + "wrapTooltip": "程式碼換行", "searchLanguageHint": "搜尋語言", "codeCopiedSnackbar": "程式碼已複製到剪貼簿" }, @@ -3465,4 +3466,4 @@ "shareSection": { "shared": "與我分享" } -} \ No newline at end of file +} From 0a53a50b37bcb49edcf8436025f05130eca396ec Mon Sep 17 00:00:00 2001 From: ocp1006 <130064802+ocp1006@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:05:12 +0300 Subject: [PATCH 3/3] fix: localize British wrap label --- frontend/resources/translations/en-GB.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/resources/translations/en-GB.json b/frontend/resources/translations/en-GB.json index bc5340238ae16..6aeb9e3f339d4 100644 --- a/frontend/resources/translations/en-GB.json +++ b/frontend/resources/translations/en-GB.json @@ -2086,7 +2086,7 @@ "auto": "Auto" }, "copyTooltip": "Copy", - "wrapTooltip": "Wrap code", + "wrapTooltip": "Wrap code lines", "searchLanguageHint": "Search for a language", "codeCopiedSnackbar": "Code copied to clipboard!" },