bpampuch/pdfmake

Right to left language (RTL)

Opened this issue · 60 comments

Hi,

Is there support for right to left language?
I was able to change the font but the letter are written in the wrong order (LTR).

Requires implementation in the library pdfkit, issue: foliojs/pdfkit#219.

+1

+1

+1

Hi,
any update on this ?

Guys we are shifting to latex for Persian
https://www.latex-project.org/

Good Luck

Hi,
For RTL support you can try to use this code:
var inputString = 'שלום עולם'; //Hello World
inputString = inputString.split(" ").reverse().join(" "); //Str to Arr->Reverse array->toString
var data = { content: [ {text: inputString, alignment: 'right'} ] };
pdfMake.createPdf(data).open();

Please note: inside join( ) you should have 2 spaces " "
Tested for hebrew, I assume it should work for other RTL languages.

P.S don't forget to include fonts for your language https://github.com/bpampuch/pdfmake/wiki/Custom-Fonts---client-side

@kedrovski For Farsi is not working because between some world have space

Could we use some thing like :
defaultStyle: { alignment: 'right', direction: 'rtl', }

? 💯

@liborm85 I find a way to display correct our string in RTL format.
I use this :

var inputString = 'سلام دوستان';
inputString = inputString.replace(" " , " "); //replace space with nbspace char
var data = { content: [ {text: inputString, alignment: 'right'} ] };
pdfMake.createPdf(data).open();

but it has bug with wraping , in tables if I use this function with a large text the table width will be in one big row .

Can we supply nbspace(alt255) char instead of space to wrap text ? (I mean edit this source https://github.com/bpampuch/pdfmake/blob/master/src/textTools.js)

Does it supports "RTL" now?

Any updates on this issue?

Uysim commented

When I can get the good news from this feature?

Is there any updates ?

There is no Update On This Issue????

I was able to manually handle Hebrew with code like:

npm install twitter_cldr

import * as TwitterCldrLoader from "twitter_cldr";

const TwitterCldr = TwitterCldrLoader.load("en");

class ... {
  private isHebrew(text: string) {
    var position = text.search(/[\u0590-\u05FF]/);
    return position >= 0;
  }

  private maybeRtlize(text: string) {
    if (this.isHebrew(text)) {
      var bidiText = TwitterCldr.Bidi.from_string(text, { direction: "RTL" });
      bidiText.reorder_visually();
      return bidiText.toString();
    } else {
      return text;
    }
  }
}

Just pass all text that may be in Hebrew through the maybeRtlize function.

It's not perfect and I only tested it for Hebrew, but it seems to work pretty good. If you also need right alignment, use something like isHebrew(myText) ? { align: "right" } : null for alignment.

Is there any way to pass array of words and tell write from right point or from left point?
It is possible to use 3rd party libraries and custom solutions to get array of characters, words etc but I can't find a way to pass this data properly to the library.

Small update:
if you need a fast solution right now my suggestion is to use this php library https://tcpdf.org/ and create a small micro service for this. Currently I wasn't able to find any js based pdf library that can properly handle rtl languages.

+1 Please :)

+1 2020 !!

+1! It's really critical. Pleeeeeeaaase :)

+1 2020 Please

+1 2020,
It's been 5 years since the first request. Please take care

@jthoenes @andreialecu @soroushm @liborm85 @jihadrhamza did any of you guys find a solution to this, please?

Hi,
For RTL support you can try to use this code:
var inputString = 'שלום עולם'; //Hello World
inputString = inputString.split(" ").reverse().join(" "); //Str to Arr->Reverse array->toString
var data = { content: [ {text: inputString, alignment: 'right'} ] };
pdfMake.createPdf(data).open();

Please note: inside join( ) you should have 2 spaces " "
Tested for hebrew, I assume it should work for other RTL languages.

P.S don't forget to include fonts for your language https://github.com/bpampuch/pdfmake/wiki/Custom-Fonts---client-side

work for me 👍
thanks

work for me 👍
thanks

Just to note, if your text contains: punctuation, english words, have paragraphs etc this method won't work properly

Any updates of any sort, yet. If so please add it in the documentation. Thanks.

+1 almost end of 2020

After almost 6 years, nothing has happened yet? Why?

@mortezakarimi64 @afsheen1 so put your amazing effort here!

Yes, the RTL support is a must-have feature!

+1 Hi, any update on this? This is really important. Please

hi here is my code for persian ltr to rtl this is a function that's can use in datatable to export as pdf :

function buttonForDatatable(columns, margins, prtrait = "portrait",title='',message='') {
            return [
                 {
            extend: 'copy',
            text:"کپی",
            exportOptions: {

                columns: columns.reverse(),

            },

        },  {
            extend: 'csv',
            text:"سی اس وی",
            exportOptions: {

                columns: columns.reverse(),

            },

        },  {
            extend: 'print',
            text:"پرینت",
            exportOptions: {

                columns: columns.reverse(),

            },

        }, {
            extend: 'excel',
            text:"اکسل",
            exportOptions: {

                columns: columns,

            },

        }  ,{
                    extend: 'pdfHtml5',
                    orientation: prtrait,
                    footer: true,
                    alignment: "center",
                    title: title,
                    messageTop:message,
                    text: "PDF",
                    exportOptions: {
                        alignment: "center",
                        orthogonal: "PDF",
                        columns: columns,
                        modifier: {order: 'index', page: 'current'}

                    },
                    customize: function (doc) {
                        doc.styles.message.alignment = "right";
                        doc.styles.tableBodyEven.alignment = "center";
                        doc.styles.tableBodyOdd.alignment = "center";
                        doc.styles.tableFooter.alignment = "center";
                        doc.styles.tableHeader.alignment = "center";
                        doc.content[0]['text'] = doc.content[0]['text'].split(' ').reverse().join(' ');
                        doc.content[1].margin = margins;
                        doc.content[2].margin = margins;
                        for (var i = 0; i < doc.content[2].table.body.length; i++) {
                            // console.log(doc.content[1].table.body[i].length);
                            for (var j = 0; j < doc.content[2].table.body[i].length; j++) {
                                doc.content[2].table.body[i][j]['text'] = doc.content[2].table.body[i][j]['text'].split(' ').reverse().join(' ');
                            }
                        }
                    }
                }
            ];
        }

and after that you are can use same as here and you are must to know for buttonForDatatable first parameter is index of column and second parameter is margin from right left top bottom :

 table = $('#mydatatable').DataTable({
                language: language,
                "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "all"]],
                dom: 'Blfrtip',
                buttons: buttonForDatatable([2, 3, 4], [0, 0, 0, 0]),
                processing: true,
                serverSide: true,
.....

Great plugin, but in the absence of RTL support, I used jspdf-autotable that is based on jsPDF. The only catch is to apply a font that supports RTL language.
Note: The reverse method will just miss with the displayed text content if it's multi line.

Please pin this issue

@liborm85 @bpampuch @blikblum @devongovett

https://imanmh.github.io/persianRex/

This link contains RegExp Persian and Arabic Unicode and Numbers and Punctuations


CONTRIBUTING.md

Not clearly explained about ways to contributing

"scripts": {
    "test": "run-s build mocha lint",
    "build": "run-s build:clean build:3rdparty build:node build:browser build:standard-fonts build:fonts build:vfs",
    "build:clean": "shx rm -rf js build",
    "build:3rdparty": "shx cp node_modules/svg-to-pdfkit/source.js src/3rd-party/svg-to-pdfkit/source.js && shx cp node_modules/svg-to-pdfkit/LICENSE src/3rd-party/svg-to-pdfkit/LICENSE",
    "build:node": "babel src --out-dir js",
    "build:browser": "webpack",
    "build:vfs": "node build-vfs.js \"./examples/fonts\"",
    "build:examples": "node build-examples.js",
    "build:standard-fonts": "shx mkdir -p build/standard-fonts && brfs \"./src/browser-extensions/standard-fonts/Courier.js\" > build/standard-fonts/Courier.js && brfs \"./src/browser-extensions/standard-fonts/Helvetica.js\" > build/standard-fonts/Helvetica.js && brfs \"./src/browser-extensions/standard-fonts/Times.js\" > build/standard-fonts/Times.js && brfs \"./src/browser-extensions/standard-fonts/Symbol.js\" > build/standard-fonts/Symbol.js && brfs \"./src/browser-extensions/standard-fonts/ZapfDingbats.js\" > build/standard-fonts/ZapfDingbats.js",
    "build:fonts": "shx mkdir -p build/fonts && shx mkdir -p build/fonts/Roboto && shx cp -r fonts/Roboto/*.* build/fonts/Roboto && brfs \"./src/browser-extensions/fonts/Roboto.js\" > build/fonts/Roboto.js",
    "lint": "eslint \"./src/**/*.js\" \"./tests/**/*.js\" \"./examples/**/*.js\" \"./standard-fonts/**/*.js\" \"./fonts/**/*.js\"",
    "mocha": "mocha --reporter spec \"./tests/**/*.spec.js\"",
    "playground": "node dev-playground/server.js"
  },
  • After installing pdfmake dev|dependency what script should I have to run
  • In CONTRIBUTING.md you should explain each of these scripts...

This package is using pdfkit underhood we have to contribute code in pdfmake or pdfkit


https://datatables.net/forums/discussion/62636/pdfmake-rtl

PS: \n => line break

to solve this RTL issue partialy|relatively:

  1. Reverse order of header - body - footer ::: [0,1,2,3,4] ===> [4,3,2,1,0]
  2. Split and Reverse text inside each of header body and footer ::: تست تکس در پی دی اف ===> a اف دی پی در تکس تست
  3. These ways work good but if text has a Line Break ===> Text with incorrect placement
    3.1 for example think this as Persian or rtl text: Hello\n How are you ===> How are you\n Hello 😐

any update @liborm85??

2022, any updates?!

so when exactly?

For God's sake, when this issue is going to be resolved?

Although pdfmake-to-excel is using pdfmake payload to load the content into excel, Arabic is being rendered in pdfmake-to-excel correctly from right to left but pdfmake still got the RTL issue!!

Any updates about this issue?

My Solution is

Create a helper function that takes a text and return it formatted while reversing the rtl language
Arabic:
`export function handleArabicCharacters(message: string) {
let arabic = [];
let english = [];

var regex = new RegExp(
"[\u0600-\u06ff]|[\u0750-\u077f]|[\ufb50-\ufc3f]|[\ufe70-\ufefc]"
);

arabic = message.split(" ").filter((e) => regex.test(e));
english = message.split(" ").filter((e) => !regex.test(e));
return ${english.join(" ")} ${arabic.reverse().join(" ")};
}`

then import it and use it inside the docDefinition obj like this

columns: [ { text: 'Remarks:', style: { alignment: 'left', bold: true, fontSize: 11 }, margin: [0, 6, 0, 3], width: 70, }, { text: ${handleArabicCharacters(orderData?.order_remarks)}, style: { alignment: 'right', font: 'Arial', fontSize: 10 }, margin: [0, 6, 0, 3], }, ],

Change the regex to match the language needed. I hope this can help

It's working fine for string but still facing issue in layout direction .
Capture

I have been facing this problem for two years and it has not been resolved yet. Do I have to search for another tool? The problem has existed since 2015. This is very bad. Why don't you solve the problem? @liborm85

+1

why this issue is not fixed ?

@itaisir Try read my post above.

Wow. About 9 years since the start of topic, still no update for RTL layouts and language.
It would be great if this option added.