Working with UTF-8 in PDF::Writer and Ruby on Rails

Googling for information on how to use PDF::Writer shows that there are many european developers frustrated with the lack of UTF-8 support in PDF::Writer. As Ruby on Rails works great with UTF-8 these days this can be a bit of an issue.

Part of the problem lies in the fact that the PDF specification (at least up to 1.6) does not support UTF-8 (you can use UTF-16 if you like). I had the misfortune of plowing thorugh it a couple of years ago when developing a PDF form filler library for a customer (don’t ask).

In Ruby on Rails, this is easy to solve as long as you only use Latin characters with diacritics. The solution is to switch encoding back to ISO-8859-15 for text strings you feed to PDF::Writer.

A simple extension to the String class will do the trick:

If you are working in Rails you can put this code in the lib folder (I usually call the file string_extensions.rb).

Then, when you call the text method on your PDF::Writer intance you can easily pass a correctly encoded string.

Overriding PDF::Writer text method

A much cleaner approach, as Aníbal describes in the comment below, is to override PDF::Writer’s text method.

Put the following code in a file called pdfwriter_extensions.rb (or whatever you choose to call it) in your lib directory:

In your controller that handles the PDF output you add:

…after which you can use PDF::Writer like in the tutorial:

Comments

  1. OpenIDAníbal says at 2007-06-01 00:06:

    module PDF

    class Writer

    alias :text_old :text

    def text( texto, options = {} )
    text_old( CONVERTER.iconv(texto), options )
    end

    end

    end

  2. OpenIDAníbal says at 2007-06-01 00:06:

    Sorry, I was missing the iconv converter:

    
    CONVERTER = Iconv.new( 'ISO-8859-15//IGNORE//TRANSLIT', 'utf-8')
    
    module PDF
    
      class Writer
    
        alias :text_old :text
         
         def text( texto, options = {} )
          text_old( CONVERTER.iconv(texto), options )
        end
    
      end
    
    end
    

  3. Pete says at 2007-06-01 07:06:

    Aníbal: That was a much nicer solution if you want to change the behaviour aplication wide. Good work!

  4. Johan Lind says at 2007-06-03 15:06:

    What a coincidence - yesterday i did a very similar override of WWW::Mechanize to get values automatically converted into UTF8. Aliasing methods is a really powerful tool to have in your ruby toolbox.

  5. rossnet says at 2007-06-06 14:06:

    Thanks for the helpful code. I’ve tried to post my comment here, but it failed. Don’t want to write everything again. So you can find my addendum to the code here.

  6. slowjack says at 2007-07-23 18:07:

    Don’t forget:

    alias_method :old_add_text, :add_text

    def add_text(x, y, text, *args)
    old_add_text(x,y,ICONV_CONVERTER.iconv(text), *args)
    end

  7. Drew says at 2007-09-26 12:09:

    Everything is ok with Latin characters, but what should I do with Russian??? PDF::Writer does not understand them :( Do you know any solution???

  8. Rel says at 2007-10-02 14:10:

    thank you for the patch, but for the tables, how to proceed?

  9. OpenIDPete says at 2007-11-29 14:11:

    Thank you for this little patch that help me much! :)

  10. OpenIDPete says at 2007-12-06 17:12:

    I have a small question: Why is the converter a constant?

  11. OpenIDPete says at 2007-12-06 19:12:

    I want to add that its better to use the method “add_text” instead of “text” because SimpleTable uses “add_text” and “text” uses “add_text” internally.

  12. Kai says at 2007-12-21 14:12:

    
    def add_text(x, y, text, *args)
      old_add_text(x,y,ICONV_CONVERTER.iconv(text), *args)
    end
    

    does not work with Time objects. The trick is to call iconv with text.to_s instead of just text. Then you are able to print dates (for example to put Time.now in the page footer).

  13. kikito and fjuan says at 2008-03-28 16:03:

    We love you

  14. Erik L. Underbjerg says at 2008-04-23 15:04:

    Brilliant! This was just what I needed :-)

  15. BuGo says at 2008-05-15 16:05:

    Am i the only one who gets :

    stack level too deep

    ?

  16. Boris says at 2008-06-24 14:06:

    I also ran into the recursion error “stack level too deep” and resolved it like this:

    alias_method :old_add_text, :add_text unless method_defined?(:old_add_text)

    This prevents the method to be overridden more often than once.

    Cheers,
    boris

Leave a comment

OpenID

Anonymous

You can use some HTML elements. You know which they are.