如何在python中使用reportlab,rtl和bidi创建包含波斯语(波斯语)文本的PDF

f8rj6qna  于 2023-03-24  发布在  Python
关注(0)|答案(4)|浏览(161)

我一直在尝试创建一个PDF文件的内容,可以是英语,波斯语,数字或它们的组合。
波斯语文本存在一些问题,比如:“ا ل ن ا ل مت ن فارس ا س ت”

  • 文本必须从右向左书写
    2-在单词中不同位置的字符之间存在差异(意味着字符根据其周围的字符改变其形状)
    3-因为句子是从右到左读的,所以普通的textwrap不能正确工作。
oug3syen

oug3syen1#

我使用reportlab创建PDF,但不幸的是reportlab不支持阿拉伯语和波斯语字母表,所以我使用Vahid Mardani的'rtl'库和Meir Kriheli的'pybidi'库来使文本在PDF结果中看起来正确。
首先,我们需要在reportlab中添加一个支持波斯语的字体:
1.在Ubuntu 14.04中:

copy Bahij-Nazanin-Regular.ttf into
/usr/local/lib/python3.4/dist-packages/reportlab/fonts folder

1.将字体和样式添加到reportlab:

from reportlab.lib.enums import TA_RIGHT
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
pdfmetrics.registerFont(TTFont('Persian', 'Bahij-Nazanin-Regular.ttf'))
styles = getSampleStyleSheet()
styles.add(ParagraphStyle(name='Right', alignment=TA_RIGHT, fontName='Persian', fontSize=10))

在下一步中,我们需要重塑波斯语文本字母到正确的形状,并使每个单词的方向从右到左:

from bidi.algorithm import get_display
    from rtl import reshaper
    import textwrap

    def get_farsi_text(text):
        if reshaper.has_arabic_letters(text):
          words = text.split()
          reshaped_words = []
          for word in words:
            if reshaper.has_arabic_letters(word):
              # for reshaping and concating words
              reshaped_text = reshaper.reshape(word)
              # for right to left    
              bidi_text = get_display(reshaped_text)
              reshaped_words.append(bidi_text)
            else:
              reshaped_words.append(word)
          reshaped_words.reverse()
         return ' '.join(reshaped_words)
        return text

而添加项目符号或 Package 文本,我们可以使用以下函数:

def get_farsi_bulleted_text(text, wrap_length=None):
       farsi_text = get_farsi_text(text)
       if wrap_length:
           line_list = textwrap.wrap(farsi_text, wrap_length)
           line_list.reverse()
           line_list[0] = '{} •'.format(line_list[0])
           farsi_text = '<br/>'.join(line_list)
           return '<font>%s</font>' % farsi_text
       return '<font>%s &#x02022;</font>' % farsi_text

为了测试我们可以写的代码:

from reportlab.lib.pagesizes import letter
    from reportlab.platypus import SimpleDocTemplate, Paragraph
    from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle

    doc = SimpleDocTemplate("farsi_wrap.pdf", pagesize=letter,    rightMargin=72, leftMargin=72, topMargin=72,
                    bottomMargin=18)
    Story = []

    text = 'شاید هنوز اندروید نوقا برای تمام گوشی‌های اندرویدی عرضه نشده باشد، ولی اگر صاحب یکی از گوشی‌های نکسوس یا پیک' \
   'سل باشید احتمالا تا الان زمان نسبتا زیادی را با آخرین نسخه‌ی اندروید سپری کرده‌اید. اگر در کار با اندروید نوقا' \
   ' دچار مشکل شده‌اید، با دیجی‌کالا مگ همراه باشید تا با هم برخی از رایج‌ترین مشکلات گزارش شده و راه حل آن‌ها را' \
   ' بررسی کنیم. البته از بسیاری از این روش‌ها در سایر نسخه‌های اندروید هم می‌توانید استفاده کنید. اندروید برخلاف iOS ' \
   'روی گستره‌ی وسیعی از گوشی‌ها با پوسته‌ها و اپلیکیشن‌های اضافی متنوع نصب می‌شود. بنابراین تجویز یک نسخه‌ی مشترک برا' \
   'ی حل مشکلات آن کار چندان ساده‌ای نیست. با این حال برخی روش‌های عمومی وجود دارد که بهتر است پیش از هر چیز آن‌ها را' \
   ' بیازمایید.'
    tw = get_farsi_bulleted_text(text, wrap_length=120)
    p = Paragraph(tw, styles['Right'])
    Story.append(p)
    doc.build(Story)
vnzz0bqm

vnzz0bqm2#

在使用Reportlab工作了一段时间后,我们在组织和格式化它方面遇到了一些问题。这花费了很多时间并且有点复杂。所以我们决定使用pdfkit和jinja2。这样我们就可以用html和CSS来格式化和组织,并且我们不需要重新格式化波斯语文本。
首先,我们可以设计一个HTML模板文件,如下所示:

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

然后我们使用jinja2库将我们的数据渲染到Template中,然后使用pdfkit从渲染结果中创建一个pdf:

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)
xmq68pz9

xmq68pz93#

如果有人想使用Django从html模板生成pdf,这是如何做到的:

template = get_template("app_name/template.html")
context = Context({'something':some_variable})
html = template.render(context)
pdf = pdfkit.from_string(html, False)
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename=output.pdf'
return response
nr9pn0ug

nr9pn0ug4#

将多字节(波斯语,阿拉伯语)字符串作为参数发送到下面的typescript函数,并将返回的字符串放入pdfMaker或任何其他PDF生成器

farsiNew(farsistr){ 
         // because pdfmake display it mirrored by default
        var allText = '';
        var point = 19;
        var words = farsistr.split("\n");
        var newword;
        for(var i=0; i<=words.length-1; i++){
           newword = words[i].split( ' ');
            if (newword.length <point) {
                allText = allText + newword.reverse().join(' ') + "\n";
            }else{
 
                for(var q =0; q<= Math.ceil (newword.length / point); q++) {

                    var s , t;
                    if (q === 0) {
                        s = 0; t = point;
                    }
                    else {
                         s = q * point + q;
                        t = s + point;
                    }
                    for (var v = t; v >= s; v--) {
                        if(!newword[v])
                            continue;
                        allText = allText + ' ' +newword[v]

                    }
                   allText = allText + '\n';
                }
            }
        }
        return allText;

}

相关问题