po-mode.el is a major mode for editing Gettext .po message files. The mode is included in the Gettext package,


po-mode is used by translators working on writing translations for the messages. The mode has many facilities for jumping around as-yet untranslated messages or “unfuzzying” messages when the program source changes. The mode is described in detail in the Gettext manual,


See also po-mode+.el by GauteHvoslefKvalnes, it adds extra features to po-mode. And also see MoMode for viewing compiled message files (using po-mode).

Also, see gb-po-mode.el by GeorgBrandl, which (among other things) improves the behavior of the edit window and automatically rewraps message strings after edit, similar to what ‘po-wrap’ below does.

Line Wrapping

It is a good idea to have all lines in PO files not exceed 80 characters limit. Calling fill-paragraph while editing a message string makes every line end with \n like gettext multi-line string convention requires, which is usually not the desirable result. To wrap all long lines in msgstr contents of PO file currently being edited, use this function instead (shamelessly taken from GNUnited Nations manual):

     (defun po-wrap ()
       "Filter current po-mode buffer through `msgcat' tool to wrap all lines."
       (if (eq major-mode 'po-mode)
           (let ((tmp-file (make-temp-file "po-wrap."))
     	    (tmp-buf (generate-new-buffer "*temp*")))
     	      (write-region (point-min) (point-max) tmp-file nil 1)
     	      (if (zerop
     		    "msgcat" nil tmp-buf t (shell-quote-argument tmp-file)))
     		  (let ((saved (point))
     			(inhibit-read-only t))
     		    (delete-region (point-min) (point-max))
     		    (insert-buffer tmp-buf)
     		    (goto-char (min saved (point-max))))
     		(with-current-buffer tmp-buf
     		  (error (buffer-string)))))
     	  (kill-buffer tmp-buf)
     	  (delete-file tmp-file)))))

If you want auto-fill feature in the sub edit window, try longlines-mode. Please turn off auto-fill-mode on the sub edit window, or po-mode will add \n to your translated string which is usually not what you want. Add this code to your ~/.emacs to enable longlines-mode automatically on sub edit window.

    (add-hook 'po-subedit-mode-hook '(lambda () (longlines-mode 1)))
    (add-hook 'po-subedit-exit-hook '(lambda () (longlines-mode 0)))

This code is also used in po-mode+.el.

Spell Checking

You can use the following code to automatically spell check translated message strings using a dictionary appropriate for the language of the PO file.

    (defun po-guess-language ()
      "Return the language related to this PO file."
        (goto-char (point-min))
        (re-search-forward po-any-msgstr-block-regexp)
        (goto-char (match-beginning 0))
        (if (re-search-forward
             "\n\"Language: +\\(.+\\)\\\\n\"$"
             (match-end 0) t)
            (po-match-string 1))))
    (defadvice po-edit-string (around setup-spell-checking (string type expand-tabs) activate)
      "Set up spell checking in subedit buffer."
      (let ((po-language (po-guess-language)))
        (if po-language
              (ispell-change-dictionary po-language)

Is it possible make po-mode remember last keyboard layout?

Keyboard layout always switched to english when msgstr editor is opened. This is inconvenient because translation typically uses non-english language. How to force po-mode to remember last used keyboard layout in msgstr editor window (or maybe to guess it from po header)?

Gettext CategoryModes