diff --git a/client/src/app/core/marked-translations.ts b/client/src/app/core/marked-translations.ts index 698b44bcc..76b3ad27f 100644 --- a/client/src/app/core/marked-translations.ts +++ b/client/src/app/core/marked-translations.ts @@ -40,6 +40,7 @@ _('Allow access for anonymous guest users'); _('Show this text on the login page'); _('Export'); _('Separator used for all csv exports and examples'); +_('Default encoding for all csv exports'); _('Page number alignment in PDF'); _('Left'); _('Center'); diff --git a/client/src/app/core/ui-services/base-import.service.ts b/client/src/app/core/ui-services/base-import.service.ts index d223bdad6..f03d0b571 100644 --- a/client/src/app/core/ui-services/base-import.service.ts +++ b/client/src/app/core/ui-services/base-import.service.ts @@ -288,7 +288,7 @@ export abstract class BaseImportService { public onSelectFile(event: any): void { // TODO type if (event.target.files && event.target.files.length === 1) { - if (event.target.files[0].type === 'text/csv') { + if (event.target.files[0].type.startsWith('text/csv')) { this._rawFile = event.target.files[0]; this.readFile(event.target.files[0]); } else { diff --git a/client/src/app/core/ui-services/csv-export.service.ts b/client/src/app/core/ui-services/csv-export.service.ts index a74735abc..ca7329ef9 100644 --- a/client/src/app/core/ui-services/csv-export.service.ts +++ b/client/src/app/core/ui-services/csv-export.service.ts @@ -83,10 +83,12 @@ export class CsvExportService { filename: string, { lineSeparator = '\r\n', - columnSeparator = this.config.instant('general_csv_separator') + columnSeparator = this.config.instant('general_csv_separator'), + encoding = this.config.instant('general_csv_encoding') }: { lineSeparator?: string; columnSeparator?: string; + encoding?: 'utf-8' | 'iso-8859-15'; } = {} ): void { let csvContent = []; // Holds all lines as arrays with each column-value @@ -153,8 +155,12 @@ export class CsvExportService { return line.map(entry => tsList[0] + entry + tsList[0]).join(columnSeparator); }) .join(lineSeparator); - - this.exporter.saveFile(csvContentAsString, filename, 'text/csv'); + const filetype = `text/csv;charset=${encoding}`; + if (encoding === 'iso-8859-15') { + this.exporter.saveFile(this.exporter.convertTo8859_15(csvContentAsString), filename, filetype); + } else { + this.exporter.saveFile(csvContentAsString, filename, filetype); + } } /** diff --git a/client/src/app/core/ui-services/file-export.service.ts b/client/src/app/core/ui-services/file-export.service.ts index 087195429..a42b06c80 100644 --- a/client/src/app/core/ui-services/file-export.service.ts +++ b/client/src/app/core/ui-services/file-export.service.ts @@ -35,4 +35,18 @@ export class FileExportService { const pattern = new RegExp(/^[^\\\/\?%\*:\|\"\<\>]*[^\.]+$/i); return pattern.test(filename); } + + /** + * get an iso-8859-15 - compatible blob part + * + * @param data + * @returns a Blob part + */ + public convertTo8859_15(data: string): BlobPart { + const array = new Uint8Array(new ArrayBuffer(data.length)); + for (let i = 0; i < data.length; i++) { + array[i] = data.charCodeAt(i); + } + return array; + } } diff --git a/openslides/core/config_variables.py b/openslides/core/config_variables.py index a99143aa7..36c73d454 100644 --- a/openslides/core/config_variables.py +++ b/openslides/core/config_variables.py @@ -138,6 +138,20 @@ def get_config_variables(): subgroup="Export", ) + yield ConfigVariable( + name="general_csv_encoding", + default_value="utf-8", + input_type="choice", + label="Default encoding for all csv exports", + choices=( + {"value": "utf-8", "display_name": "UTF-8"}, + {"value": "iso-8859-15", "display_name": "ISO-8859-15"}, + ), + weight=143, + group="General", + subgroup="Export", + ) + yield ConfigVariable( name="general_export_pdf_pagenumber_alignment", default_value="center",