From bc7469643a51e420975375c67dd46200691021a0 Mon Sep 17 00:00:00 2001
From: Namli1 <51393783+Namli1@users.noreply.github.com>
Date: Mon, 18 Oct 2021 00:06:44 +0200
Subject: [PATCH] Adding translations to the toolbar! (#421)

---
 README.md                                     | 14 ++++++
 lib/src/translations/toolbar.i18n.dart        | 37 +++++++++++++++
 lib/src/widgets/link_dialog.dart              |  6 ++-
 lib/src/widgets/toolbar.dart                  | 46 ++++++++++++++-----
 lib/src/widgets/toolbar/color_button.dart     |  3 +-
 .../widgets/toolbar/image_video_utils.dart    |  5 +-
 pubspec.yaml                                  |  1 +
 7 files changed, 95 insertions(+), 17 deletions(-)
 create mode 100644 lib/src/translations/toolbar.i18n.dart

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<LinkDialog> {
       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<LinkDialog> {
         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<ColorButton> {
     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: