From e4c8ed5be1d544415cc63f013afb5e70d96ff0f2 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Tue, 1 Jul 2003 09:48:16 +0000 Subject: [PATCH] Add gettext support. [SVN r18902] --- new/virtual-target.jam | 12 +++ tools/gettext.jam | 183 ++++++++++++++++++++++++++++++++++++ v2/build/virtual-target.jam | 12 +++ v2/tools/gettext.jam | 183 ++++++++++++++++++++++++++++++++++++ 4 files changed, 390 insertions(+) create mode 100644 tools/gettext.jam create mode 100644 v2/tools/gettext.jam diff --git a/new/virtual-target.jam b/new/virtual-target.jam index c6dbdfe76..568d0f4a4 100644 --- a/new/virtual-target.jam +++ b/new/virtual-target.jam @@ -506,6 +506,18 @@ rule file-target ( class file-target : abstract-file-target ; +rule notfile-target ( name : project ) +{ + abstract-file-target.__init__ $(name) : : $(project) ; + + rule actualize-location ( target ) + { + NOTFILE $(target) ; + ALWAYS $(target) ; + } +} +class notfile-target : abstract-file-target ; + # Returns the binding for the given actual target. # CONSIDER: not sure this rule belongs here. diff --git a/tools/gettext.jam b/tools/gettext.jam new file mode 100644 index 000000000..492969c0b --- /dev/null +++ b/tools/gettext.jam @@ -0,0 +1,183 @@ +# Copyright (C) Vladimir Prus 2003. Permission to copy, use, modify, sell and +# distribute this software is granted provided this copyright notice appears in +# all copies. This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. + +# This module support GNU gettext internationalization utilities. +# +# It provides two main target rules: 'gettext.catalog', used for +# creating machine-readable catalogs from translations files, and +# 'gettext.update', used for update translation files from modified +# sources. +# +# To add i18n support to your application you should follow these +# steps. +# +# - Decide on a file name which will contain translations and +# what main target name will be used to update it. For example:: +# +# gettext.update update-russian : russian.po a.cpp b.cpp ; +# +# - Create the initial translation file by running +# +# bjam update-russian +# +# - Edit russian.po. For example, you might change fields like LastTranslator. +# +# - Create a main target for final message catalog:: +# +# gettext.catalog russian : russian.po ; +# +# The machine-readable catalog will be updated whenever you update +# "russian.po". The "russian.po" file will be updated only on explicit +# request. When you're ready to update translations, you should +# +# - Run:: +# +# bjam update-russian +# +# - Edit "russian.po" in appropriate editor. +# +# The next bjam run will convert "russian.po" into machine-readable form. +# +# By default, translations are marked by 'i18n' call. The 'gettext.keyword' +# feature can be used to alter this. + + +import targets ; +import property-set ; +import virtual-target ; +import class : class new ; +import project ; +import type ; +import generators ; +import errors ; +import feature : feature ; +import toolset : flags ; + +.path = "" ; + +# Initializes the gettext module. +rule init ( path ? # Path where all tools are located. If not specified, + # they should be in PATH. + ) +{ + if $(.initialized) && $(.path) != $(path) + { + errors.error "Attempt to reconfigure with different path" ; + } + .initialized = true ; + if $(path) + { + .path = $(path)/ ; + } +} + +# Creates a main target 'name', which, when updated, will cause +# file 'existing-translation' to be updated with translations +# extracted from 'sources' --- which, for now, must be names +# of source files. +# +# The target will be updated only if explicitly requested on the +# command line. +rule update ( name : existing-translation sources + ) +{ + local project = [ CALLER_MODULE ] ; + + targets.main-target-alternative + [ new update-translations-class $(name) : $(project) : + $(existing-translation) $(sources) + ] ; + local project-target = [ project.target $(project) ] ; + $(project-target).mark-target-as-explicit $(name) ; +} + + +# The human editable source, containing translation. +type.register gettext.PO : po ; +# The machine readable message catalog. +type.register gettext.catalog : mo : : main ; +# Intermediate type produce by extracting translations from +# sources. +type.register gettext.POT : pot ; + +feature gettext.keyword : : free ; + +generators.register-standard gettext.compile : gettext.PO : gettext.catalog ; + +rule update-translations-class ( name : project : sources * ) +{ + basic-target.__init__ $(name) : $(project) : $(sources) : $(requirements) + : $(default-build) ; + + rule construct ( source-targets * : property-set ) + { + property-set = [ property-set.empty ] ; + + if ! $(.constructed) + { + local new-messages = [ new file-target $(self.name) : gettext.POT : $(self.project) ] ; + local extract = + [ new action $(new-messages) : $(source-targets[2-]) : gettext.extract ] ; + $(new-messages).action $(extract) ; + + local r = [ new notfile-target $(self.name) : $(self.project) ] ; + local a = [ new action $(r) : $(source-targets[1]) $(new-messages) + : gettext.update-po-dispatch ] ; + $(r).action $(a) ; + .constructed = [ virtual-target.register $(r) ] ; + } + return $(.constructed) ; + } +} +class update-translations-class : basic-target ; + +flags gettext.extract KEYWORD ; +actions extract +{ + $(.path)xgettext -k$(KEYWORD:E=i18n) -o $(<) $(>) +} + +# Does realy updating of po file. The tricky part is that +# we're actually updating one of the sources: +# $(<) is the NOTFILE target we're updating +# $(>[1]) is the PO file to be really updated. +# $(>[2]) is the PO file created from sources. +# +# When file to be updated does not exist (during the +# first run), we need to copy the file created from sources. +# In all other cases, we need to update the file. +local rule update-po-dispatch +{ + NOCARE $(>[1]) ; + gettext.create-po $(<) : $(>) ; + gettext.update-po $(<) : $(>) ; + _ on $(<) = " " ; + ok on $(<) = "" ; + EXISTING_PO on $(<) = $(>[1]) ; +} + +# Due to fancy interaction of existing and updated, this rule +# can be called with with one source, in which case we copy +# the lonely source into EXISTING_PO, or with two sources, +# in which case the action body expands to nothing. +# I'd really like to have "missing" action modifier. +actions quietly existing updated create-po bind EXISTING_PO +{ + cp$(_)"$(>[1])"$(_)"$(EXISTING_PO)"$($(>[2]:E=ok)) +} + +actions updated update-po +{ + $(.path)msgmerge$(_)-U$(_)"$(>[1])"$(_)"$(>[2])" +} + +actions gettext.compile +{ + $(.path)msgfmt -o $(<) $(>) +} + +IMPORT $(__name__) : update : : gettext.update ; + + + \ No newline at end of file diff --git a/v2/build/virtual-target.jam b/v2/build/virtual-target.jam index c6dbdfe76..568d0f4a4 100644 --- a/v2/build/virtual-target.jam +++ b/v2/build/virtual-target.jam @@ -506,6 +506,18 @@ rule file-target ( class file-target : abstract-file-target ; +rule notfile-target ( name : project ) +{ + abstract-file-target.__init__ $(name) : : $(project) ; + + rule actualize-location ( target ) + { + NOTFILE $(target) ; + ALWAYS $(target) ; + } +} +class notfile-target : abstract-file-target ; + # Returns the binding for the given actual target. # CONSIDER: not sure this rule belongs here. diff --git a/v2/tools/gettext.jam b/v2/tools/gettext.jam new file mode 100644 index 000000000..492969c0b --- /dev/null +++ b/v2/tools/gettext.jam @@ -0,0 +1,183 @@ +# Copyright (C) Vladimir Prus 2003. Permission to copy, use, modify, sell and +# distribute this software is granted provided this copyright notice appears in +# all copies. This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. + +# This module support GNU gettext internationalization utilities. +# +# It provides two main target rules: 'gettext.catalog', used for +# creating machine-readable catalogs from translations files, and +# 'gettext.update', used for update translation files from modified +# sources. +# +# To add i18n support to your application you should follow these +# steps. +# +# - Decide on a file name which will contain translations and +# what main target name will be used to update it. For example:: +# +# gettext.update update-russian : russian.po a.cpp b.cpp ; +# +# - Create the initial translation file by running +# +# bjam update-russian +# +# - Edit russian.po. For example, you might change fields like LastTranslator. +# +# - Create a main target for final message catalog:: +# +# gettext.catalog russian : russian.po ; +# +# The machine-readable catalog will be updated whenever you update +# "russian.po". The "russian.po" file will be updated only on explicit +# request. When you're ready to update translations, you should +# +# - Run:: +# +# bjam update-russian +# +# - Edit "russian.po" in appropriate editor. +# +# The next bjam run will convert "russian.po" into machine-readable form. +# +# By default, translations are marked by 'i18n' call. The 'gettext.keyword' +# feature can be used to alter this. + + +import targets ; +import property-set ; +import virtual-target ; +import class : class new ; +import project ; +import type ; +import generators ; +import errors ; +import feature : feature ; +import toolset : flags ; + +.path = "" ; + +# Initializes the gettext module. +rule init ( path ? # Path where all tools are located. If not specified, + # they should be in PATH. + ) +{ + if $(.initialized) && $(.path) != $(path) + { + errors.error "Attempt to reconfigure with different path" ; + } + .initialized = true ; + if $(path) + { + .path = $(path)/ ; + } +} + +# Creates a main target 'name', which, when updated, will cause +# file 'existing-translation' to be updated with translations +# extracted from 'sources' --- which, for now, must be names +# of source files. +# +# The target will be updated only if explicitly requested on the +# command line. +rule update ( name : existing-translation sources + ) +{ + local project = [ CALLER_MODULE ] ; + + targets.main-target-alternative + [ new update-translations-class $(name) : $(project) : + $(existing-translation) $(sources) + ] ; + local project-target = [ project.target $(project) ] ; + $(project-target).mark-target-as-explicit $(name) ; +} + + +# The human editable source, containing translation. +type.register gettext.PO : po ; +# The machine readable message catalog. +type.register gettext.catalog : mo : : main ; +# Intermediate type produce by extracting translations from +# sources. +type.register gettext.POT : pot ; + +feature gettext.keyword : : free ; + +generators.register-standard gettext.compile : gettext.PO : gettext.catalog ; + +rule update-translations-class ( name : project : sources * ) +{ + basic-target.__init__ $(name) : $(project) : $(sources) : $(requirements) + : $(default-build) ; + + rule construct ( source-targets * : property-set ) + { + property-set = [ property-set.empty ] ; + + if ! $(.constructed) + { + local new-messages = [ new file-target $(self.name) : gettext.POT : $(self.project) ] ; + local extract = + [ new action $(new-messages) : $(source-targets[2-]) : gettext.extract ] ; + $(new-messages).action $(extract) ; + + local r = [ new notfile-target $(self.name) : $(self.project) ] ; + local a = [ new action $(r) : $(source-targets[1]) $(new-messages) + : gettext.update-po-dispatch ] ; + $(r).action $(a) ; + .constructed = [ virtual-target.register $(r) ] ; + } + return $(.constructed) ; + } +} +class update-translations-class : basic-target ; + +flags gettext.extract KEYWORD ; +actions extract +{ + $(.path)xgettext -k$(KEYWORD:E=i18n) -o $(<) $(>) +} + +# Does realy updating of po file. The tricky part is that +# we're actually updating one of the sources: +# $(<) is the NOTFILE target we're updating +# $(>[1]) is the PO file to be really updated. +# $(>[2]) is the PO file created from sources. +# +# When file to be updated does not exist (during the +# first run), we need to copy the file created from sources. +# In all other cases, we need to update the file. +local rule update-po-dispatch +{ + NOCARE $(>[1]) ; + gettext.create-po $(<) : $(>) ; + gettext.update-po $(<) : $(>) ; + _ on $(<) = " " ; + ok on $(<) = "" ; + EXISTING_PO on $(<) = $(>[1]) ; +} + +# Due to fancy interaction of existing and updated, this rule +# can be called with with one source, in which case we copy +# the lonely source into EXISTING_PO, or with two sources, +# in which case the action body expands to nothing. +# I'd really like to have "missing" action modifier. +actions quietly existing updated create-po bind EXISTING_PO +{ + cp$(_)"$(>[1])"$(_)"$(EXISTING_PO)"$($(>[2]:E=ok)) +} + +actions updated update-po +{ + $(.path)msgmerge$(_)-U$(_)"$(>[1])"$(_)"$(>[2])" +} + +actions gettext.compile +{ + $(.path)msgfmt -o $(<) $(>) +} + +IMPORT $(__name__) : update : : gettext.update ; + + + \ No newline at end of file