ruby-on-railspdffontslocalizationprawn

Prawn PDF support both English and Japenese/Chinese/Thai/Korean in same PDF


I am generating a PDF using ROR and Prawn. The PDF is in both English (the form labels) and Japanese or other FE languages (the data entered by the user).

I have found the related question to this where ipamp.ttf was suggested. I installed that font and it prints Japanese beautifully. The trouble is, it doesn't support English! I need both.

In case it matters, here's how I installed ipamp. I just called font inside the initialize method:

font("lib/assets/ipamp.ttf")

I found Google's Noto fonts, but they are in ttc format, which Prawn can't use.

I'm looking for a solution to support all EU and Far East languages, simultaneously, in one PDF doc, without a bunch of logic to determine whether the text I'm trying to display is EU/Latin or Far East (and switching the font based on that). Seems like that would be pretty brittle.

Size of the font file will not be a concern as the PDF will be rendered on the server and sent to the client as, well, a PDF.

Thanks!


Solution

  • Here's the solution, pieced together from this post (this post) and some trial and error.

    The key is that Prawn supports fallback fonts. You have to download them into your project, then update Prawn's font families to include them, then include a method called "fallback_fonts" for Prawn to use when it realizes it has a unicode character that it doesn't know how to render.

    class ResultsPdf < Prawn::Document
    
      def initialize(device)
        super()
        @device = device
        set_fallback_fonts
        page_title         #typically English
        persons_name       #typically Japanese
      end
    
     def set_fallback_fonts
        ipamp_path = "lib/assets/ipamp.ttf"
        ipamp_spec  = { file: ipamp_path, font: 'IPAPMincho'}
    
        #don't use a symbol to define the name of the font!
        font_families.update("ipamp" => {normal: ipamp_spec,
                                        bold: ipamp_spec,
                                        italic: ipamp_spec,
                                        bold_italic: ipamp_spec})
      end
    
      def fallback_fonts
        ["ipamp"]
      end
    
      def page_title
        # device name is typically in English
        text "#{@device.name}", :size => 15, :style => :bold, :align => :center
      end
    
      def persons_name
        # owner name can be in any language, including Japanese
        # you don't have to specify :fallback_font here.  Prawn will use your method.
        text "Name: #{@device.owner_last_name}"
      end
    
    end