Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create PDF containing Persian(Farsi) text with reportlab, rtl and bidi in python

I've been trying to create a PDF file from content that can be English, Persian, digits or a combination of them.

there is some problems with Persian texts like: "این یک متن فارسی است"

۱- the text must be written from right to left

2- there is a difference between characters in different positions in the word (meaning that characters change their shape according to their surrounding characters)

3- because the sentence is read from right to left then the normal textwrap doesn't work correctly.

like image 823
r.aj Avatar asked Dec 27 '16 12:12

r.aj


1 Answers

After working for a while with Reportlab, we had some problems with organizing and formatting it. It took a lot of time and was kind of complicated. So we decided to work with pdfkit and jinja2. This way we can format and organize in html and CSS and we don't need to reformat Persian text too.

first we can design an html template file like the one below:

    &lt!DOCTYPE html&gt
        &lthtml&gt
        &lthead lang="fa-IR"&gt
            &ltmeta charset="UTF-8"&gt
            &lttitle&gt&lt/title&gt
        &lt/head&gt
        &ltbody &gt
            &ltp dir="rtl"&gtسوابق کاری&lt/p&gt
            &ltul dir="rtl"&gt
                {% for experience in experiences %}
                &ltli&gt&lta href="{{ experience.url }}"&gt{{ experience.title }}&lt/a&gt&lt/li&gt
                {% endfor %}
            &lt/ul&gt
        &lt/body&gt
        &lt/html&gt

and then we use jinja2 library to render our data into Template, and then use pdfkit to create a pdf from render result:

    from jinja2 import Template
    from pdfkit import pdfkit

    sample_data = [{'url': 'http://www.google.com/', 'title': 'گوگل'},
                   {'url': 'http://www.yahoo.com/fa/', 'title': 'یاهو'},
                   {'url': 'http://www.amazon.com/', 'title': 'آمازون'}]

    with open('template.html', 'r') as template_file:
        template_str = template_file.read()
        template = Template(template_str)
        resume_str = template.render({'experiences': sample_data})

        options = {'encoding': "UTF-8", 'quiet': ''}
        bytes_array = pdfkit.PDFKit(resume_str, 'string', options=options).to_pdf()
        with open('result.pdf', 'wb') as output:
            output.write(bytes_array)
like image 121
r.aj Avatar answered Nov 08 '22 15:11

r.aj