[Mailman-i18n] Getting started with i18n (was Re: [Mailman-Users] message templates)

Peter Funk pf@artcom-gmbh.de
Sat, 15 Jan 2000 10:30:35 +0100 (MET)


Hi!

Michael Reinsch wrote:
> Is there a way to change (i.e. translate) the message templates (help etc) 
> per mailinglist in the current version of mailman? 
> 
> How about NLS for these message templates? :)

Barry created a special interest group <URI:mailto:mailman-i18n@python.org>
this month, because recently I've written a module called 'fintl.py' to aid the
internationalization of any applications written in pure python.  Together
with the suite of utilities from the GNU gettext package and Barrys
'pygettext' tool it should be fairly easy, to start an internationalization
effort for the mailman software.  

Unfortunately I'm very busy with other projects and can't spend much time
on this one. :-(  Anyone wanting to volunteer could grep the mailman 1.2
sources from the CVS on python.org and start editing... ;-}

To illustrate the idea, of what would have to be done, I've taken
the file 'Mailman/Cgi/listinfo.py' as an example out my running
mailman 1.1 installation and applied some of the needed i18n-patches.
This has taken me only 10 minutes.  See the unified context diff below.

After finishing this rather mechanical editing work on the complete 
source tree of Mailman you have to edit some Makefile to aid the i18n 
process for different foreign languages.  The following Makefile
taken from one of my private Python projects should give you the basic idea:

--------<PRE>
#  Title        : i18n Makefile
#  Created      :       Mon, 04-Oct-99 / 17:34 / (pf)

what:
	@echo "make what?"
	@echo "Choose one of the following:"
	@echo "  make pot       - Generate a new .pot file"
	@echo "  make update-po - Merge new messages from .pot into existing .po files"
	@echo "  make mo        - Generate output files"
	@echo "  make all       - All steps described above, one after the other"

# Choose the message extractor tool:
## XGETTEXT=xgettext
# if you have Barrys pygettext.py, use this instead (must be on your $PATH):
XGETTEXT=pygettext.py
# list of all languages with translations:
LINGUAS = de
# output file directory for binary translation files:
MO_DIR = ../Resources/Messages
# input directory for translated 
PO_DIR = po
# the name of this software package (domain)
DOMAIN = python

# generate a list of all .py-source files containing calls to the gettext 
# alias function _("...") :
POTFILES: ..
	cd .. ; find . -name '*.py' -print | sed 's|^\./||' \
		| xargs grep -l '_(\"' > po/POTFILES

PO_PACKAGE = $(DOMAIN)

# create a portable translation file, which can be used as master file
# for the translation into a new language:
pot: POTFILES
	cd .. ; $(XGETTEXT) -k_ -o po/$(DOMAIN).pot `cat po/POTFILES`

# update existing translation files with new messages:
update-po:
	for po in *.po; do \
		lingua=`basename $$po .po`; \
	        mv $$lingua.po $$lingua.old.po; \
		if msgmerge -o $$lingua.po $$lingua.old.po $(DOMAIN).pot; \
		then rm $$lingua.old.po; \
		else rm -f $$lingua.po; \
		     mv $$lingua.old.po $$lingua.po; \
		fi \
	done

# Generate mo files for all available po files:
mo:
	for po in *.po; do\
		lingua=`basename $$po .po`; \
		install -d $(MO_DIR)/$$lingua/LC_MESSAGES/ ; \
		msgfmt -o $(MO_DIR)/$$lingua/LC_MESSAGES/$(DOMAIN).mo $$po ;\
	done

all: pot update-po mo

# End of this Makefile
--------</PRE>
And now the example diff mentioned above:

--------<PRE>
--- listinfo.py.orig	Sat Jan 15 09:56:12 2000
+++ listinfo.py	Sat Jan 15 10:02:08 2000
@@ -24,6 +24,7 @@
 import sys
 import os, string
 from regsub import gsub
+import fintl; _ = fintl.gettext
 from Mailman import Utils, MailList
 from Mailman import mm_cfg
 from Mailman.htmlformat import *
@@ -48,7 +49,7 @@
         list = None
 
     if not (list and list._ready):
-        FormatListinfoOverview(error="List <em>%s</em> not found." % list_name)
+        FormatListinfoOverview(error=_("List <em>%s</em> not found.") % list_name)
         return
 
     FormatListListinfo(list)
@@ -72,7 +73,7 @@
 	host_name = mm_cfg.DEFAULT_HOST_NAME
 
     doc = Document()
-    legend = "%s mailing lists" % host_name
+    legend = _("%s mailing lists") % host_name
     doc.SetTitle(legend)
 
     table = Table(border=0, width="100%")
@@ -99,41 +100,41 @@
     if error:
 	greeting = FontAttr(error, color="ff5060", size="+1")
     else:
-	greeting = "Welcome!"
+	greeting = _("Welcome!")
 
     if not advertised:
         welcome_items = (greeting,
 			 "<p>"
-			 " There currently are no publicly-advertised ",
+			 _(" There currently are no publicly-advertised "),
 			 Link(mm_cfg.MAILMAN_URL, "mailman"),
-			 " mailing lists on %s." % host_name,
+			 _(" mailing lists on %s.") % host_name,
 			 )
     else:
 
         welcome_items = (
 	    greeting,
             "<p>"
-            " Below is the collection of publicly-advertised ",
+            _(" Below is the collection of publicly-advertised "),
             Link(mm_cfg.MAILMAN_URL, "mailman"),
-            " mailing lists on %s." % host_name,
-            (' Click on a list name to visit the info page'
-             ' for that list.  There you can learn more about the list,'
-             ' subscribe to it, or find the roster of current subscribers.'),
+            _(" mailing lists on %s.") % host_name,
+            (_(' Click on a list name to visit the info page')
+             _(' for that list.  There you can learn more about the list,')
+             _(' subscribe to it, or find the roster of current subscribers.')),
             )
 
     welcome_items = (welcome_items +
-                     (" To visit the info page for an unadvertised list,"
-                      " open a URL similar to this one, but with a '/' and"
+                     (_(" To visit the info page for an unadvertised list,")+
+                      _(" open a URL similar to this one, but with a '/' and")
                       +
-                      (" the %slist name appended."
+                      (_(" the %slist name appended.")
                        % ((error and "right ") or ""))
                       +
-                      '<p> List administrators, you can visit ',
+                      _('<p> List administrators, you can visit '),
                       Link("%sadmin%s/" % ('../' * Utils.GetNestingLevel(),
                                            mm_cfg.CGIEXT),
-                           "the list admin overview page"),
-                      " to find the management interface for your list."
-                      "<p>(Send questions or comments to ",
+                           _("the list admin overview page")),
+                      _(" to find the management interface for your list.")+
+                      _("<p>(Send questions or comments to "),
                       Link("mailto:%s" % mm_cfg.MAILMAN_OWNER,
                            mm_cfg.MAILMAN_OWNER),
                       ".)<p>"))
--------</PRE>
Please excuse the direct inclusion of the code snippets into this mail.
But since mailman has problems dealing with attachments, when creating
the html for the archives, I decided to do it this way.

Regards from Germany, Peter
-- 
Peter Funk, Oldenburger Str.86, 27777 Ganderkesee, Tel: 04222 9502 70, Fax: -60