From 936b84403796ac7c87f39ef480c17a9f0813f5a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Guillot?= <fred@kanboard.net>
Date: Sat, 26 Oct 2024 13:55:27 -0700
Subject: [PATCH] feat: add option to add BOM at the beginning of the CSV file
 (required for Excel)

---
 app/Controller/ExportController.php    |  4 ++--
 app/Core/Csv.php                       | 12 +++++++++---
 app/Core/Http/Response.php             |  7 ++++---
 app/Locale/bg_BG/translations.php      |  1 +
 app/Locale/bs_BA/translations.php      |  1 +
 app/Locale/ca_ES/translations.php      |  1 +
 app/Locale/cs_CZ/translations.php      |  1 +
 app/Locale/da_DK/translations.php      |  1 +
 app/Locale/de_DE/translations.php      |  1 +
 app/Locale/de_DE_du/translations.php   |  1 +
 app/Locale/el_GR/translations.php      |  1 +
 app/Locale/es_ES/translations.php      |  1 +
 app/Locale/es_VE/translations.php      |  1 +
 app/Locale/fa_IR/translations.php      |  1 +
 app/Locale/fi_FI/translations.php      |  1 +
 app/Locale/fr_FR/translations.php      |  1 +
 app/Locale/hr_HR/translations.php      |  1 +
 app/Locale/hu_HU/translations.php      |  1 +
 app/Locale/id_ID/translations.php      |  1 +
 app/Locale/it_IT/translations.php      |  1 +
 app/Locale/ja_JP/translations.php      |  1 +
 app/Locale/ko_KR/translations.php      |  1 +
 app/Locale/mk_MK/translations.php      |  1 +
 app/Locale/my_MY/translations.php      |  1 +
 app/Locale/nb_NO/translations.php      |  1 +
 app/Locale/nl_NL/translations.php      |  1 +
 app/Locale/pl_PL/translations.php      |  1 +
 app/Locale/pt_BR/translations.php      |  1 +
 app/Locale/pt_PT/translations.php      |  1 +
 app/Locale/ro_RO/translations.php      |  1 +
 app/Locale/ru_RU/translations.php      |  1 +
 app/Locale/sk_SK/translations.php      |  1 +
 app/Locale/sr_Latn_RS/translations.php |  1 +
 app/Locale/sv_SE/translations.php      |  1 +
 app/Locale/th_TH/translations.php      |  1 +
 app/Locale/tr_TR/translations.php      |  1 +
 app/Locale/uk_UA/translations.php      |  1 +
 app/Locale/vi_VN/translations.php      |  1 +
 app/Locale/zh_CN/translations.php      |  1 +
 app/Locale/zh_TW/translations.php      |  1 +
 app/Template/export/subtasks.php       |  1 +
 app/Template/export/summary.php        |  1 +
 app/Template/export/tasks.php          |  1 +
 app/Template/export/transitions.php    |  1 +
 44 files changed, 56 insertions(+), 8 deletions(-)

diff --git a/app/Controller/ExportController.php b/app/Controller/ExportController.php
index a76896731..a405a461c 100644
--- a/app/Controller/ExportController.php
+++ b/app/Controller/ExportController.php
@@ -32,7 +32,7 @@ class ExportController extends BaseController
             if ($from && $to) {
                 $data = $this->$model->$method($project['id'], $from, $to);
                 $this->response->withFileDownload($filename.'.csv');
-                $this->response->csv($data);
+                $this->response->csv($data, $this->request->getRawValue('bom') === '1');
             }
         } else {
             $this->response->html($this->template->render('export/'.$action, array(
@@ -86,7 +86,7 @@ class ExportController extends BaseController
                 $to = $this->dateParser->getIsoDate($to);
                 $data = $this->projectDailyColumnStatsModel->getAggregatedMetrics($project['id'], $from, $to);
                 $this->response->withFileDownload(t('Summary').'.csv');
-                $this->response->csv($data);
+                $this->response->csv($data, $this->request->getRawValue('bom') === '1');
             }
         } else {
             $this->response->html($this->template->render('export/summary', array(
diff --git a/app/Core/Csv.php b/app/Core/Csv.php
index fdff9fe04..f93e9781f 100644
--- a/app/Core/Csv.php
+++ b/app/Core/Csv.php
@@ -106,11 +106,12 @@ class Csv
      * @static
      * @access public
      * @param  array  $rows
+     * @param  bool   $addBOM
      */
-    public static function output(array $rows)
+    public static function output(array $rows, $addBOM = false)
     {
         $csv = new static;
-        $csv->write('php://output', $rows);
+        $csv->write('php://output', $rows, $addBOM);
     }
 
     /**
@@ -160,13 +161,18 @@ class Csv
      * @access public
      * @param  string    $filename
      * @param  array     $rows
+     * @param  bool      $addBOM
      * @return Csv
      */
-    public function write($filename, array $rows)
+    public function write($filename, array $rows, $addBOM = false)
     {
         $fp = fopen($filename, 'w');
 
         if (is_resource($fp)) {
+            if ($addBOM) {
+                fwrite($fp, "\xEF\xBB\xBF");
+            }
+
             foreach ($rows as $row) {
                 fputcsv($fp, $row, $this->delimiter, $this->enclosure);
             }
diff --git a/app/Core/Http/Response.php b/app/Core/Http/Response.php
index 0af763a6c..720dfaef6 100644
--- a/app/Core/Http/Response.php
+++ b/app/Core/Http/Response.php
@@ -291,14 +291,15 @@ class Response extends Base
      * Send a CSV response
      *
      * @access public
-     * @param  array  $data  Data to serialize in csv
+     * @param  array  $data    Data to serialize in csv
+     * @param  bool   $addBOM  Add BOM header
      */
-    public function csv(array $data)
+    public function csv(array $data, $addBOM = false)
     {
         $this->withoutCache();
         $this->withContentType('text/csv; charset=utf-8');
         $this->send();
-        Csv::output($data);
+        Csv::output($data, $addBOM);
     }
 
     /**
diff --git a/app/Locale/bg_BG/translations.php b/app/Locale/bg_BG/translations.php
index 57d2b1ab9..52ba53610 100755
--- a/app/Locale/bg_BG/translations.php
+++ b/app/Locale/bg_BG/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/bs_BA/translations.php b/app/Locale/bs_BA/translations.php
index 732211990..192cb089d 100644
--- a/app/Locale/bs_BA/translations.php
+++ b/app/Locale/bs_BA/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/ca_ES/translations.php b/app/Locale/ca_ES/translations.php
index dc6458fe1..a237d861a 100644
--- a/app/Locale/ca_ES/translations.php
+++ b/app/Locale/ca_ES/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php
index 95295a839..63d44f88c 100644
--- a/app/Locale/cs_CZ/translations.php
+++ b/app/Locale/cs_CZ/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php
index bedc52d18..7d55a6222 100644
--- a/app/Locale/da_DK/translations.php
+++ b/app/Locale/da_DK/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php
index d8d327bac..6fb4c5555 100644
--- a/app/Locale/de_DE/translations.php
+++ b/app/Locale/de_DE/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/de_DE_du/translations.php b/app/Locale/de_DE_du/translations.php
index ab119009b..19763da59 100644
--- a/app/Locale/de_DE_du/translations.php
+++ b/app/Locale/de_DE_du/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/el_GR/translations.php b/app/Locale/el_GR/translations.php
index 01c68736d..b1513c0fe 100644
--- a/app/Locale/el_GR/translations.php
+++ b/app/Locale/el_GR/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php
index 3991a6642..5c8c8d32e 100644
--- a/app/Locale/es_ES/translations.php
+++ b/app/Locale/es_ES/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/es_VE/translations.php b/app/Locale/es_VE/translations.php
index 19f530ac7..ad1ff4c7a 100644
--- a/app/Locale/es_VE/translations.php
+++ b/app/Locale/es_VE/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/fa_IR/translations.php b/app/Locale/fa_IR/translations.php
index b98a05874..84e0b64a3 100644
--- a/app/Locale/fa_IR/translations.php
+++ b/app/Locale/fa_IR/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php
index bdb0899fe..f7d5ae70b 100644
--- a/app/Locale/fi_FI/translations.php
+++ b/app/Locale/fi_FI/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php
index 94be45000..01d9c7650 100644
--- a/app/Locale/fr_FR/translations.php
+++ b/app/Locale/fr_FR/translations.php
@@ -1462,4 +1462,5 @@ return array(
     'Invalid Mail transport' => 'Transport de courrier invalide',
     'Color invalid' => 'Couleur invalide',
     'This value must be greater or equal to %d' => 'Cette valeur doit être supérieure ou égale à %d',
+    'Add a BOM at the beginning of the file (required for Microsoft Excel)' => 'Ajouter un BOM au début du fichier (requis pour Microsoft Excel)',
 );
diff --git a/app/Locale/hr_HR/translations.php b/app/Locale/hr_HR/translations.php
index 05cf24a74..d2f3c1d55 100644
--- a/app/Locale/hr_HR/translations.php
+++ b/app/Locale/hr_HR/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php
index f043646bf..c6155f8d5 100644
--- a/app/Locale/hu_HU/translations.php
+++ b/app/Locale/hu_HU/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php
index 79d2f815d..97cef2d5b 100644
--- a/app/Locale/id_ID/translations.php
+++ b/app/Locale/id_ID/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php
index 2895b56a0..0182c833f 100644
--- a/app/Locale/it_IT/translations.php
+++ b/app/Locale/it_IT/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php
index 1f6fe5259..74db1e50d 100644
--- a/app/Locale/ja_JP/translations.php
+++ b/app/Locale/ja_JP/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/ko_KR/translations.php b/app/Locale/ko_KR/translations.php
index 9c855d3ca..98220a040 100644
--- a/app/Locale/ko_KR/translations.php
+++ b/app/Locale/ko_KR/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/mk_MK/translations.php b/app/Locale/mk_MK/translations.php
index 54bfce427..456eaac6d 100644
--- a/app/Locale/mk_MK/translations.php
+++ b/app/Locale/mk_MK/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/my_MY/translations.php b/app/Locale/my_MY/translations.php
index 4c6c40c43..da2554485 100644
--- a/app/Locale/my_MY/translations.php
+++ b/app/Locale/my_MY/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php
index bf4f69a29..803d06037 100644
--- a/app/Locale/nb_NO/translations.php
+++ b/app/Locale/nb_NO/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php
index 1b8339bec..a1ef7cbed 100644
--- a/app/Locale/nl_NL/translations.php
+++ b/app/Locale/nl_NL/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php
index e6da67d8d..857dee7ba 100644
--- a/app/Locale/pl_PL/translations.php
+++ b/app/Locale/pl_PL/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php
index e76ff50a6..53a72f213 100644
--- a/app/Locale/pt_BR/translations.php
+++ b/app/Locale/pt_BR/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php
index a2a618dc9..11f6f06ad 100644
--- a/app/Locale/pt_PT/translations.php
+++ b/app/Locale/pt_PT/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/ro_RO/translations.php b/app/Locale/ro_RO/translations.php
index b3d285688..4fed36dec 100644
--- a/app/Locale/ro_RO/translations.php
+++ b/app/Locale/ro_RO/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php
index 513db75e5..6fb385ec8 100644
--- a/app/Locale/ru_RU/translations.php
+++ b/app/Locale/ru_RU/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/sk_SK/translations.php b/app/Locale/sk_SK/translations.php
index b712df29b..63b262e61 100644
--- a/app/Locale/sk_SK/translations.php
+++ b/app/Locale/sk_SK/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php
index b86837b32..a9b9e1541 100644
--- a/app/Locale/sr_Latn_RS/translations.php
+++ b/app/Locale/sr_Latn_RS/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php
index 31e95d5cf..616292206 100644
--- a/app/Locale/sv_SE/translations.php
+++ b/app/Locale/sv_SE/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php
index 5b867bc4c..5692938ca 100644
--- a/app/Locale/th_TH/translations.php
+++ b/app/Locale/th_TH/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php
index 0cc2c19bc..6b27f8c2c 100644
--- a/app/Locale/tr_TR/translations.php
+++ b/app/Locale/tr_TR/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/uk_UA/translations.php b/app/Locale/uk_UA/translations.php
index d280a4277..64c85f759 100644
--- a/app/Locale/uk_UA/translations.php
+++ b/app/Locale/uk_UA/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/vi_VN/translations.php b/app/Locale/vi_VN/translations.php
index 87d621c78..d8cab548a 100644
--- a/app/Locale/vi_VN/translations.php
+++ b/app/Locale/vi_VN/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php
index 1cfe1bb4c..332657981 100644
--- a/app/Locale/zh_CN/translations.php
+++ b/app/Locale/zh_CN/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Locale/zh_TW/translations.php b/app/Locale/zh_TW/translations.php
index 817579113..75ebfd5f1 100644
--- a/app/Locale/zh_TW/translations.php
+++ b/app/Locale/zh_TW/translations.php
@@ -1462,4 +1462,5 @@ return array(
     // 'Invalid Mail transport' => '',
     // 'Color invalid' => '',
     // 'This value must be greater or equal to %d' => '',
+    // 'Add a BOM at the beginning of the file (required for Microsoft Excel)' => '',
 );
diff --git a/app/Template/export/subtasks.php b/app/Template/export/subtasks.php
index 0e47772bf..ea80af2e3 100644
--- a/app/Template/export/subtasks.php
+++ b/app/Template/export/subtasks.php
@@ -7,6 +7,7 @@
     <?= $this->form->hidden('project_id', $values) ?>
     <?= $this->form->date(t('Start date'), 'from', $values) ?>
     <?= $this->form->date(t('End date'), 'to', $values) ?>
+    <?= $this->form->checkbox('bom', t('Add a BOM at the beginning of the file (required for Microsoft Excel)'), 1, isset($values['bom']) && $values['bom'] == 1) ?>
 
     <div class="form-actions">
         <button type="submit" class="btn btn-blue js-form-export"><?= t('Export') ?></button>
diff --git a/app/Template/export/summary.php b/app/Template/export/summary.php
index 7dc7482fb..7273100ec 100644
--- a/app/Template/export/summary.php
+++ b/app/Template/export/summary.php
@@ -7,6 +7,7 @@
     <?= $this->form->hidden('project_id', $values) ?>
     <?= $this->form->date(t('Start date'), 'from', $values) ?>
     <?= $this->form->date(t('End date'), 'to', $values) ?>
+    <?= $this->form->checkbox('bom', t('Add a BOM at the beginning of the file (required for Microsoft Excel)'), 1, isset($values['bom']) && $values['bom'] == 1) ?>
 
     <div class="form-actions">
         <button type="submit" class="btn btn-blue js-form-export"><?= t('Export') ?></button>
diff --git a/app/Template/export/tasks.php b/app/Template/export/tasks.php
index 232ff8ebc..36926e2fb 100644
--- a/app/Template/export/tasks.php
+++ b/app/Template/export/tasks.php
@@ -7,6 +7,7 @@
     <?= $this->form->hidden('project_id', $values) ?>
     <?= $this->form->date(t('Start date'), 'from', $values) ?>
     <?= $this->form->date(t('End date'), 'to', $values) ?>
+    <?= $this->form->checkbox('bom', t('Add a BOM at the beginning of the file (required for Microsoft Excel)'), 1, isset($values['bom']) && $values['bom'] == 1) ?>
 
     <div class="form-actions">
         <button type="submit" class="btn btn-blue js-form-export"><?= t('Export') ?></button>
diff --git a/app/Template/export/transitions.php b/app/Template/export/transitions.php
index 4f3749b8c..a21f8e31b 100644
--- a/app/Template/export/transitions.php
+++ b/app/Template/export/transitions.php
@@ -7,6 +7,7 @@
     <?= $this->form->hidden('project_id', $values) ?>
     <?= $this->form->date(t('Start date'), 'from', $values) ?>
     <?= $this->form->date(t('End date'), 'to', $values) ?>
+    <?= $this->form->checkbox('bom', t('Add a BOM at the beginning of the file (required for Microsoft Excel)'), 1, isset($values['bom']) && $values['bom'] == 1) ?>
 
     <div class="form-actions">
         <button type="submit" class="btn btn-blue js-form-export"><?= t('Export') ?></button>
-- 
GitLab