Pleawe write the full English test in article in Russian language translation and later write all the difficult vocabulary words in a list with their translation in Russian language . Create a handbook colorful pdf.
~/
Russian translation smokejumper English vocabulary
~/attachments/9b1916c3-fa3e-4543-a3f6-7f124bb677d7
~/
mkdir -p "/tmp/workspace/smokejumper-handbook/src" "/tmp/workspace/smokejumper-handbook/output" "/tmp/workspace/smokejumper-handbook/assets" && fc-list | grep -i 'DejaVuSans.ttf' | head -1
cp "/tmp/workspace/attachments/9b1916c3-fa3e-4543-a3f6-7f124bb677d7/1000294721.jpg" "/tmp/workspace/smokejumper-handbook/assets/source.jpg" && python -c "import reportlab; print(reportlab.Version)"
~/smokejumper-handbook/src/create_handbook.py
from reportlab.lib import colors
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
PageBreak, Image, KeepTogether)
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.utils import ImageReader
from PIL import Image as PILImage
import os
ROOT = '/tmp/workspace/smokejumper-handbook'
OUT = os.path.join(ROOT, 'output', 'Smokejumper_English_Russian_Handbook.pdf')
SRC = os.path.join(ROOT, 'assets', 'source.jpg')
FONT = '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'
BOLD = '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf'
pdfmetrics.registerFont(TTFont('DV', FONT))
pdfmetrics.registerFont(TTFont('DVB', BOLD))
NAVY = colors.HexColor('#102A43')
RED = colors.HexColor('#D84A3A')
ORANGE = colors.HexColor('#F7A51B')
CREAM = colors.HexColor('#FFF7E6')
TEAL = colors.HexColor('#16827A')
PALE = colors.HexColor('#EEF7F6')
GREY = colors.HexColor('#4A5568')
styles = getSampleStyleSheet()
styles.add(ParagraphStyle(name='TitleRus', fontName='DVB', fontSize=25, leading=30, textColor=NAVY, alignment=TA_CENTER, spaceAfter=7))
styles.add(ParagraphStyle(name='Sub', fontName='DV', fontSize=11.5, leading=15, textColor=GREY, alignment=TA_CENTER))
styles.add(ParagraphStyle(name='Heading', fontName='DVB', fontSize=16, leading=20, textColor=colors.white, spaceBefore=8, spaceAfter=8))
styles.add(ParagraphStyle(name='BodyEng', fontName='DV', fontSize=10.1, leading=14.1, textColor=NAVY, spaceAfter=7))
styles.add(ParagraphStyle(name='BodyRus', fontName='DV', fontSize=10.2, leading=14.3, textColor=NAVY, spaceAfter=8))
styles.add(ParagraphStyle(name='Small', fontName='DV', fontSize=8.2, leading=10.5, textColor=GREY))
styles.add(ParagraphStyle(name='Word', fontName='DVB', fontSize=9.2, leading=11, textColor=NAVY))
styles.add(ParagraphStyle(name='Trans', fontName='DV', fontSize=9.1, leading=11, textColor=NAVY))
styles.add(ParagraphStyle(name='Quote', fontName='DV', fontSize=10.3, leading=14.4, textColor=TEAL, leftIndent=10, rightIndent=10, spaceAfter=8))
def P(text, style='BodyEng'):
return Paragraph(text, styles[style])
def banner(text, bg=RED):
t=Table([[P(text, 'Heading')]], colWidths=[17.2*cm])
t.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,-1),bg),('LEFTPADDING',(0,0),(-1,-1),13),('RIGHTPADDING',(0,0),(-1,-1),13),('TOPPADDING',(0,0),(-1,-1),6),('BOTTOMPADDING',(0,0),(-1,-1),6),('VALIGN',(0,0),(-1,-1),'MIDDLE')]))
return t
def footer(canvas, doc):
canvas.saveState()
canvas.setStrokeColor(ORANGE); canvas.setLineWidth(2)
canvas.line(1.4*cm, 1.2*cm, 19.6*cm, 1.2*cm)
canvas.setFont('DV', 8)
canvas.setFillColor(GREY)
canvas.drawString(1.4*cm, 0.75*cm, 'English-Russian learning handbook | Smokejumper')
canvas.drawRightString(19.6*cm, 0.75*cm, f'Page {doc.page}')
canvas.restoreState()
doc = SimpleDocTemplate(OUT, pagesize=A4, rightMargin=1.4*cm, leftMargin=1.4*cm, topMargin=1.35*cm, bottomMargin=1.65*cm)
story=[]
# Cover
story += [Spacer(1, .45*cm), P('АНГЛИЙСКИЙ + РУССКИЙ', 'Sub'), Spacer(1,.25*cm), P('SMOKEJUMPER', 'TitleRus'), P('Парашютист-пожарный', 'TitleRus'), Spacer(1,.3*cm)]
# image crop
im = PILImage.open(SRC); w,h=im.size
cover = os.path.join(ROOT,'assets','cover_crop.jpg')
im.crop((0, int(h*.06), w, int(h*.88))).save(cover, quality=92)
image = Image(cover, width=17.2*cm, height=10.4*cm, kind='proportional')
story += [image, Spacer(1,.35*cm)]
box = Table([[P('<b>Учебный мини-справочник</b><br/>Полный английский текст, точный перевод на русский язык и словарь сложной лексики.', 'BodyRus')]], colWidths=[17.2*cm])
box.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,-1),CREAM),('BOX',(0,0),(-1,-1),1,ORANGE),('LEFTPADDING',(0,0),(-1,-1),14),('RIGHTPADDING',(0,0),(-1,-1),14),('TOPPADDING',(0,0),(-1,-1),10),('BOTTOMPADDING',(0,0),(-1,-1),10)]))
story += [box, Spacer(1,.35*cm), P('Тема: опасная работа лесных пожарных, которые прыгают с парашютом в зоны лесных пожаров.', 'Sub'), PageBreak()]
# English article
story += [banner('1. ORIGINAL ENGLISH TEXT', NAVY), Spacer(1,.25*cm)]
story += [P('<b>When it comes to tough jobs, nothing beats being a smokejumper!</b>', 'Quote')]
english = [
'Smokejumpers are elite firefighters who risk their lives fighting forest fires in remote areas. They bravely parachute out of aeroplanes into burning forests, where they quickly get to work putting the fire out.',
"A smokejumper's duties are not easy. They have to do long, tough training before they can become part of a team. Smokejumpers need to be very good parachutists and know how to read maps to get out of a forest safely. <i>\"To be a smokejumper you need to be very fit, and able to work for long hours in difficult conditions,\"</i> says Zach Meyers, a smokejumper at West Yellowstone. <i>\"We train all the time and we're always trying to improve.\"</i>",
'When they parachute into a fire zone they wear a padded jump jacket and trousers, boots, gloves, a face mask and a helmet. They also carry a backpack with some food and water, and a fire shelter. The aeroplane drops the tools and equipment they need to fight the fire.',
'<i>\"People think that smokejumpers have a very dangerous job, but we don\'t see it like that,\"</i> says Zach with a smile. <i>\"This job keeps me happy. I love the feeling I get when I jump out of the aeroplane and fly through the air. I wouldn\'t want any other job in the world.\"</i>'
]
for x in english: story.append(P(x))
story += [Spacer(1,.2*cm)]
tip=Table([[P('<b>Reading tip:</b> Notice the present simple: <i>risk, parachute, wear, carry</i>. It describes what smokejumpers do as part of their usual work.', 'BodyEng')]], colWidths=[17.2*cm])
tip.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,-1),PALE),('LINEBEFORE',(0,0),(0,-1),4,TEAL),('LEFTPADDING',(0,0),(-1,-1),12),('RIGHTPADDING',(0,0),(-1,-1),12),('TOPPADDING',(0,0),(-1,-1),8),('BOTTOMPADDING',(0,0),(-1,-1),8)]))
story += [tip, PageBreak()]
# translation
story += [banner('2. ПОЛНЫЙ ПЕРЕВОД НА РУССКИЙ ЯЗЫК', TEAL), Spacer(1,.25*cm)]
story += [P('<b>Когда речь идёт о тяжёлой работе, ничто не сравнится с работой парашютиста-пожарного!</b>', 'Quote')]
russian = [
'Парашютисты-пожарные - это элитные пожарные, которые рискуют жизнью, борясь с лесными пожарами в отдалённых районах. Они смело прыгают с парашютом из самолётов в горящие леса, где сразу приступают к тушению огня.',
'Обязанности парашютиста-пожарного нелегки. Прежде чем стать частью команды, им нужно пройти длительную и тяжёлую подготовку. Парашютисты-пожарные должны быть очень хорошими парашютистами и уметь читать карты, чтобы безопасно выбраться из леса. «Чтобы быть парашютистом-пожарным, нужно быть в очень хорошей физической форме и уметь работать долгие часы в трудных условиях», - говорит Зак Майерс, парашютист-пожарный из Уэст-Йеллоустона. «Мы постоянно тренируемся и всегда стараемся стать лучше».',
'Когда они прыгают с парашютом в зону пожара, на них надеты утеплённая куртка для прыжков и брюки, ботинки, перчатки, защитная маска и шлем. Они также несут рюкзак с едой, водой и противопожарным укрытием. Самолёт сбрасывает инструменты и снаряжение, необходимые им для борьбы с огнём.',
'«Люди считают, что у парашютистов-пожарных очень опасная работа, но мы не воспринимаем её так», - с улыбкой говорит Зак. «Эта работа делает меня счастливым. Мне нравится чувство, которое я испытываю, когда выпрыгиваю из самолёта и лечу по воздуху. Я не хотел бы никакой другой работы в мире». '
]
for x in russian: story.append(P(x,'BodyRus'))
story += [Spacer(1,.2*cm), banner('3. DIFFICULT VOCABULARY | СЛОЖНАЯ ЛЕКСИКА', ORANGE), Spacer(1,.22*cm)]
vocab = [
('tough job','тяжёлая / трудная работа'),('nothing beats ...','ничто не сравнится с ...'),('smokejumper','парашютист-пожарный'),('elite','элитный; высококвалифицированный'),('firefighter','пожарный'),('to risk one’s life','рисковать жизнью'),('remote areas','отдалённые районы'),('bravely','смело, храбро'),('to parachute','прыгать с парашютом'),('aeroplane','самолёт'),('burning forest','горящий лес'),('to put a fire out','потушить пожар'),('duty','обязанность'),('training','подготовка; тренировка'),('to become part of a team','стать частью команды'),('parachutist','парашютист'),('to read maps','читать карты'),('safely','безопасно'),('fit','в хорошей физической форме'),('long hours','долгие часы'),('difficult conditions','трудные условия'),('fire zone','зона пожара'),('padded','утеплённый; с мягкой подкладкой'),('trousers','брюки'),('face mask','защитная маска'),('helmet','шлем'),('backpack','рюкзак'),('fire shelter','противопожарное укрытие'),('to drop','сбрасывать'),('tools and equipment','инструменты и снаряжение'),('to fight a fire','бороться с пожаром'),('to improve','улучшаться; становиться лучше'),('to fly through the air','лететь по воздуху'),("wouldn't want",'не хотел(а) бы')
]
# split vocab across next pages
chunks = [vocab[:17], vocab[17:]]
for ci,chunk in enumerate(chunks):
data=[[P('<b>English</b>','Word'), P('<b>Русский перевод</b>','Word')]] + [[P(a,'Word'),P(b,'Trans')] for a,b in chunk]
table=Table(data,colWidths=[7.2*cm,10.0*cm], repeatRows=1)
table.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,0),CREAM),('TEXTCOLOR',(0,0),(-1,0),NAVY),('GRID',(0,0),(-1,-1),.35,colors.HexColor('#B9D9D4')),('VALIGN',(0,0),(-1,-1),'MIDDLE'),('LEFTPADDING',(0,0),(-1,-1),7),('RIGHTPADDING',(0,0),(-1,-1),7),('TOPPADDING',(0,0),(-1,-1),5),('BOTTOMPADDING',(0,0),(-1,-1),5)] + [('BACKGROUND',(0,r),(-1,r),colors.white if r%2 else PALE) for r in range(1,len(data))]))
story.append(table)
if ci == 0:
story += [PageBreak(), banner('3. DIFFICULT VOCABULARY | СЛОЖНАЯ ЛЕКСИКА', ORANGE), Spacer(1,.22*cm)]
story += [Spacer(1,.22*cm)]
review = Table([[P('<b>Повторение:</b> Попробуйте перевести без подсказки: <i>remote areas, fire shelter, padded jacket, to put the fire out</i>. Затем перечитайте текст и найдите эти выражения.', 'BodyRus')]], colWidths=[17.2*cm])
review.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,-1),CREAM),('LINEBEFORE',(0,0),(0,-1),4,RED),('LEFTPADDING',(0,0),(-1,-1),12),('RIGHTPADDING',(0,0),(-1,-1),12),('TOPPADDING',(0,0),(-1,-1),8),('BOTTOMPADDING',(0,0),(-1,-1),8)]))
story.append(review)
doc.build(story, onFirstPage=footer, onLaterPages=footer)
print(OUT)
python "/tmp/workspace/smokejumper-handbook/src/create_handbook.py" && python -c "from pypdf import PdfReader; p='/tmp/workspace/smokejumper-handbook/output/Smokejumper_English_Russian_Handbook.pdf'; r=PdfReader(p); print('pages=',len(r.pages)); print('text_chars=',sum(len(x.extract_text() or '') for x in r.pages))"
/usr/share/fonts
/usr/share/fonts/google-noto-vf
~/smokejumper-handbook/src/create_handbook.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/smokejumper-handbook/src/create_handbook.py'
python "/tmp/workspace/smokejumper-handbook/src/create_handbook.py" && python -c "from pypdf import PdfReader; p='/tmp/workspace/smokejumper-handbook/output/Smokejumper_English_Russian_Handbook.pdf'; r=PdfReader(p); print('pages=',len(r.pages)); print('text_chars=',sum(len(x.extract_text() or '') for x in r.pages)); print((r.pages[1].extract_text() or '')[:180])"
python -c "import fitz; p='/tmp/workspace/smokejumper-handbook/output/Smokejumper_English_Russian_Handbook.pdf'; d=fitz.open(p); pix=d[2].get_pixmap(matrix=fitz.Matrix(1,1), alpha=False); pix.save('/tmp/workspace/smokejumper-handbook/output/page_3_preview.png'); print('rendered', pix.width, pix.height)" && ls -lh "/tmp/workspace/smokejumper-handbook/output/Smokejumper_English_Russian_Handbook.pdf" "/tmp/workspace/smokejumper-handbook/output/page_3_preview.png"
~/smokejumper-handbook/output
Smokejumper English Russian Handbook
PDF Document · PDF
Write the list of words under heading "check these words" from English to Russian translation in pdf form
~/
~/smokejumper-handbook/src/create_check_these_words_pdf.py
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER
from reportlab.lib.units import cm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
import os
ROOT = '/tmp/workspace/smokejumper-handbook'
OUT = os.path.join(ROOT, 'output', 'Check_These_Words_English_Russian.pdf')
FONT = '/usr/share/fonts/google-noto-vf/NotoSans[wght].ttf'
pdfmetrics.registerFont(TTFont('Noto', FONT))
pdfmetrics.registerFont(TTFont('NotoBold', FONT))
NAVY = colors.HexColor('#153B5B')
ORANGE = colors.HexColor('#F28C28')
RED = colors.HexColor('#D94141')
PALE = colors.HexColor('#FFF6E9')
MINT = colors.HexColor('#E8F5F2')
TEXT = colors.HexColor('#1F2933')
styles = getSampleStyleSheet()
styles.add(ParagraphStyle(name='TitleR', fontName='NotoBold', fontSize=24, leading=29, alignment=TA_CENTER, textColor=NAVY, spaceAfter=6))
styles.add(ParagraphStyle(name='SubR', fontName='Noto', fontSize=11.5, leading=15, alignment=TA_CENTER, textColor=colors.HexColor('#52606D'), spaceAfter=14))
styles.add(ParagraphStyle(name='Cell', fontName='Noto', fontSize=11.3, leading=15, textColor=TEXT))
styles.add(ParagraphStyle(name='Note', fontName='Noto', fontSize=9.4, leading=13, textColor=colors.HexColor('#52606D'), alignment=TA_CENTER))
words = [
('tough job', 'тяжёлая, трудная работа'),
('beat', 'превосходить; быть лучше'),
('elite', 'элитный, высококвалифицированный'),
('risk', 'рисковать; риск'),
('remote areas', 'отдалённые районы'),
('bravely', 'храбро, смело'),
('parachute', 'парашют; прыгать с парашютом'),
('put out', 'тушить, гасить'),
('duty', 'обязанность, служебный долг'),
('training', 'подготовка, обучение, тренировка'),
('fit', 'в хорошей физической форме'),
('fire zone', 'зона пожара'),
('padded', 'с мягкой прокладкой; утеплённый'),
('face mask', 'маска для лица'),
('helmet', 'шлем, каска'),
('backpack', 'рюкзак'),
('drop', 'сбрасывать; высаживать; падение'),
]
def p(text, style='Cell'):
return Paragraph(text, styles[style])
def footer(canvas, doc):
canvas.saveState()
canvas.setStrokeColor(ORANGE)
canvas.setLineWidth(2)
canvas.line(1.6*cm, 1.2*cm, A4[0]-1.6*cm, 1.2*cm)
canvas.setFont('Noto', 8)
canvas.setFillColor(colors.HexColor('#52606D'))
canvas.drawCentredString(A4[0]/2, 0.75*cm, 'Smokejumper | English-Russian vocabulary')
canvas.restoreState()
story = []
story.append(Spacer(1, 0.45*cm))
story.append(Paragraph('CHECK THESE WORDS', styles['TitleR']))
story.append(Paragraph('Слова из статьи <b>“Smokejumper”</b>: английский - русский', styles['SubR']))
data = [[p('<b>№</b>'), p('<b>English</b>'), p('<b>Русский перевод</b>')]]
for i, (eng, rus) in enumerate(words, 1):
data.append([p(str(i)), p('<b>%s</b>' % eng), p(rus)])
table = Table(data, colWidths=[1.25*cm, 6.6*cm, 9.6*cm], repeatRows=1, hAlign='CENTER')
table.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), NAVY),
('TEXTCOLOR', (0,0), (-1,0), colors.white),
('ALIGN', (0,0), (0,-1), 'CENTER'),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('GRID', (0,0), (-1,-1), 0.45, colors.HexColor('#C8D8E5')),
('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.white, MINT]),
('TOPPADDING', (0,0), (-1,-1), 7),
('BOTTOMPADDING', (0,0), (-1,-1), 7),
('LEFTPADDING', (0,0), (-1,-1), 8),
('RIGHTPADDING', (0,0), (-1,-1), 8),
('LINEBELOW', (0,0), (-1,0), 1.3, ORANGE),
]))
story.append(table)
story.append(Spacer(1, 0.35*cm))
story.append(Paragraph('Совет: прочитайте английское слово вслух, закройте перевод и попробуйте вспомнить его самостоятельно.', styles['Note']))
doc = SimpleDocTemplate(OUT, pagesize=A4, rightMargin=1.6*cm, leftMargin=1.6*cm, topMargin=1.25*cm, bottomMargin=1.65*cm, title='Check These Words - English Russian')
doc.build(story, onFirstPage=footer, onLaterPages=footer)
print(OUT)
python "/tmp/workspace/smokejumper-handbook/src/create_check_these_words_pdf.py" && python -c "from pypdf import PdfReader; p='/tmp/workspace/smokejumper-handbook/output/Check_These_Words_English_Russian.pdf'; r=PdfReader(p); print('pages:',len(r.pages)); t=''.join(x.extract_text() or '' for x in r.pages); print('has_words:', all(x in t for x in ['tough job','backpack','тяжёлая']))" && ls -lh "/tmp/workspace/smokejumper-handbook/output/Check_These_Words_English_Russian.pdf"
Check These Words English Russian
PDF Document · PDF