diff --git a/README.md b/README.md index 4d5a2756..8386a922 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,20 @@ Define `mobileWidth`, `mobileHeight`, `mobileMargin`, `mobileAlignment` as follo } ``` +## Translation of toolbar +The package offers translations for the quill toolbar, it will follow the system locale unless you set your own locale with: +``` +QuillToolbar(locale: Locale('fr'), ...) +``` +Currently, translations are available for these locales: +* `Locale('en')` +* `Locale('de')` +* `Locale('fr')` +* `Locale('zh', 'CN')` + +### Contributing to translations +The translation file is located at [lib/src/translations/toolbar.i18n.dart](lib/src/translations/toolbar.i18n.dart). Feel free to contribute your own translations, just copy the English translations map and replace the values with your translations. Then open a pull request so everyone can benefit from your translations! + ## Migrate Zefyr Data Check out [code](https://github.com/jwehrle/zefyr_quill_convert) and [doc](https://docs.google.com/document/d/1FUSrpbarHnilb7uDN5J5DDahaI0v1RMXBjj4fFSpSuY/edit?usp=sharing). diff --git a/lib/src/translations/toolbar.i18n.dart b/lib/src/translations/toolbar.i18n.dart new file mode 100644 index 00000000..137f6ee4 --- /dev/null +++ b/lib/src/translations/toolbar.i18n.dart @@ -0,0 +1,37 @@ +import 'package:i18n_extension/i18n_extension.dart'; + +extension Localization on String { + static final _t = Translations.byLocale('en') + + { + 'en': { + 'Paste a link': 'Paste a link', + 'Ok': 'Ok', + 'Select Color': 'Select Color', + 'Gallery': 'Gallery', + 'Link': 'Link', + }, + 'de': { + 'Paste a link': 'Link hinzufügen', + 'Ok': 'Ok', + 'Select Color': 'Farbe auswählen', + 'Gallery': 'Gallerie', + 'Link': 'Link', + }, + 'fr': { + 'Paste a link': 'Coller un lien', + 'Ok': 'Ok', + 'Select Color': 'Choisir une couleur', + 'Gallery': 'Galerie', + 'Link': 'Lien', + }, + 'zh_CN': { + 'Paste a link': '粘贴链接', + 'Ok': '好', + 'Select Color': '选择颜色', + 'Gallery': '相簿', + 'Link': '链接', + } + }; + + String get i18n => localize(this, _t); +} diff --git a/lib/src/widgets/link_dialog.dart b/lib/src/widgets/link_dialog.dart index 9df89e69..e6173402 100644 --- a/lib/src/widgets/link_dialog.dart +++ b/lib/src/widgets/link_dialog.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; + import '../models/themes/quill_dialog_theme.dart'; +import '../translations/toolbar.i18n.dart'; class LinkDialog extends StatefulWidget { const LinkDialog({this.dialogTheme, Key? key}) : super(key: key); @@ -20,7 +22,7 @@ class LinkDialogState extends State { content: TextField( style: widget.dialogTheme?.inputTextStyle, decoration: InputDecoration( - labelText: 'Paste a link', + labelText: 'Paste a link'.i18n, labelStyle: widget.dialogTheme?.labelTextStyle, floatingLabelStyle: widget.dialogTheme?.labelTextStyle), autofocus: true, @@ -30,7 +32,7 @@ class LinkDialogState extends State { TextButton( onPressed: _link.isNotEmpty ? _applyLink : null, child: Text( - 'Ok', + 'Ok'.i18n, style: widget.dialogTheme?.labelTextStyle, ), ), diff --git a/lib/src/widgets/toolbar.dart b/lib/src/widgets/toolbar.dart index 586b7dee..a574d418 100644 --- a/lib/src/widgets/toolbar.dart +++ b/lib/src/widgets/toolbar.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:i18n_extension/i18n_widget.dart'; import '../models/documents/attribute.dart'; import '../models/themes/quill_dialog_theme.dart'; @@ -61,6 +62,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { this.color, this.filePickImpl, this.multiRowsDisplay, + this.locale, Key? key, }) : super(key: key); @@ -104,6 +106,14 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { ///The theme to use for the theming of the [LinkDialog()], ///shown when embedding an image, for example QuillDialogTheme? dialogTheme, + + ///The locale to use for the editor toolbar, defaults to system locale + ///Currently the supported locales are: + /// * Locale('en') + /// * Locale('de') + /// * Locale('fr') + /// * Locale('zh') + Locale? locale, Key? key, }) { final isButtonGroupShown = [ @@ -130,6 +140,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { key: key, toolBarHeight: toolbarIconSize * 2, multiRowsDisplay: multiRowsDisplay, + locale: locale, children: [ if (showHistory) HistoryButton( @@ -395,23 +406,34 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { final FilePickImpl? filePickImpl; + ///The locale to use for the editor toolbar, defaults to system locale + ///Currently the supported locales are: + /// * Locale('en') + /// * Locale('de') + /// * Locale('fr') + /// * Locale('zh', 'CN') + final Locale? locale; + @override Size get preferredSize => Size.fromHeight(toolBarHeight); @override Widget build(BuildContext context) { - if (multiRowsDisplay ?? true) { - return Wrap( - alignment: WrapAlignment.center, - runSpacing: 4, - spacing: 4, - children: children, - ); - } - return Container( - constraints: BoxConstraints.tightFor(height: preferredSize.height), - color: color ?? Theme.of(context).canvasColor, - child: ArrowIndicatedButtonList(buttons: children), + return I18n( + initialLocale: locale, + child: multiRowsDisplay ?? true + ? Wrap( + alignment: WrapAlignment.center, + runSpacing: 4, + spacing: 4, + children: children, + ) + : Container( + constraints: + BoxConstraints.tightFor(height: preferredSize.height), + color: color ?? Theme.of(context).canvasColor, + child: ArrowIndicatedButtonList(buttons: children), + ), ); } } diff --git a/lib/src/widgets/toolbar/color_button.dart b/lib/src/widgets/toolbar/color_button.dart index 59bd3bcd..c0d323bf 100644 --- a/lib/src/widgets/toolbar/color_button.dart +++ b/lib/src/widgets/toolbar/color_button.dart @@ -4,6 +4,7 @@ import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import '../../models/documents/attribute.dart'; import '../../models/documents/style.dart'; import '../../models/themes/quill_icon_theme.dart'; +import '../../translations/toolbar.i18n.dart'; import '../../utils/color.dart'; import '../controller.dart'; import '../toolbar.dart'; @@ -143,7 +144,7 @@ class _ColorButtonState extends State { showDialog( context: context, builder: (context) => AlertDialog( - title: const Text('Select Color'), + title: Text('Select Color'.i18n), backgroundColor: Theme.of(context).canvasColor, content: SingleChildScrollView( child: MaterialPicker( diff --git a/lib/src/widgets/toolbar/image_video_utils.dart b/lib/src/widgets/toolbar/image_video_utils.dart index 0305378b..74820c7f 100644 --- a/lib/src/widgets/toolbar/image_video_utils.dart +++ b/lib/src/widgets/toolbar/image_video_utils.dart @@ -6,6 +6,7 @@ import 'package:image_picker/image_picker.dart'; import '../../models/documents/nodes/embed.dart'; import '../../utils/media_pick_setting.dart'; +import '../../translations/toolbar.i18n.dart'; import '../controller.dart'; import '../toolbar.dart'; @@ -26,7 +27,7 @@ class ImageVideoUtils { Icons.collections, color: Colors.orangeAccent, ), - label: const Text('Gallery'), + label: Text('Gallery'.i18n), onPressed: () => Navigator.pop(ctx, MediaPickSetting.Gallery), ), TextButton.icon( @@ -34,7 +35,7 @@ class ImageVideoUtils { Icons.link, color: Colors.cyanAccent, ), - label: const Text('Link'), + label: Text('Link'.i18n), onPressed: () => Navigator.pop(ctx, MediaPickSetting.Link), ) ], diff --git a/pubspec.yaml b/pubspec.yaml index 430e2076..c183026c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -26,6 +26,7 @@ dependencies: characters: ^1.1.0 youtube_player_flutter: ^8.0.0 diff_match_patch: ^0.4.1 + i18n_extension: ^4.1.3 dev_dependencies: flutter_test: