waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

intltool.py (6784B)


      1 #!/usr/bin/env python
      2 # encoding: utf-8
      3 # Thomas Nagy, 2006-2018 (ita)
      4 
      5 """
      6 Support for translation tools such as msgfmt and intltool
      7 
      8 Usage::
      9 
     10 	def configure(conf):
     11 		conf.load('gnu_dirs intltool')
     12 
     13 	def build(bld):
     14 		# process the .po files into .gmo files, and install them in LOCALEDIR
     15 		bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}")
     16 
     17 		# process an input file, substituting the translations from the po dir
     18 		bld(
     19 			features  = "intltool_in",
     20 			podir     = "../po",
     21 			style     = "desktop",
     22 			flags     = ["-u"],
     23 			source    = 'kupfer.desktop.in',
     24 			install_path = "${DATADIR}/applications",
     25 		)
     26 
     27 Usage of the :py:mod:`waflib.Tools.gnu_dirs` is recommended, but not obligatory.
     28 """
     29 
     30 from __future__ import with_statement
     31 
     32 import os, re
     33 from waflib import Context, Task, Utils, Logs
     34 import waflib.Tools.ccroot
     35 from waflib.TaskGen import feature, before_method, taskgen_method
     36 from waflib.Logs import error
     37 from waflib.Configure import conf
     38 
     39 _style_flags = {
     40 	'ba': '-b',
     41 	'desktop': '-d',
     42 	'keys': '-k',
     43 	'quoted': '--quoted-style',
     44 	'quotedxml': '--quotedxml-style',
     45 	'rfc822deb': '-r',
     46 	'schemas': '-s',
     47 	'xml': '-x',
     48 }
     49 
     50 @taskgen_method
     51 def ensure_localedir(self):
     52 	"""
     53 	Expands LOCALEDIR from DATAROOTDIR/locale if possible, or falls back to PREFIX/share/locale
     54 	"""
     55 	# use the tool gnu_dirs to provide options to define this
     56 	if not self.env.LOCALEDIR:
     57 		if self.env.DATAROOTDIR:
     58 			self.env.LOCALEDIR = os.path.join(self.env.DATAROOTDIR, 'locale')
     59 		else:
     60 			self.env.LOCALEDIR = os.path.join(self.env.PREFIX, 'share', 'locale')
     61 
     62 @before_method('process_source')
     63 @feature('intltool_in')
     64 def apply_intltool_in_f(self):
     65 	"""
     66 	Creates tasks to translate files by intltool-merge::
     67 
     68 		def build(bld):
     69 			bld(
     70 				features  = "intltool_in",
     71 				podir     = "../po",
     72 				style     = "desktop",
     73 				flags     = ["-u"],
     74 				source    = 'kupfer.desktop.in',
     75 				install_path = "${DATADIR}/applications",
     76 			)
     77 
     78 	:param podir: location of the .po files
     79 	:type podir: string
     80 	:param source: source files to process
     81 	:type source: list of string
     82 	:param style: the intltool-merge mode of operation, can be one of the following values:
     83 	  ``ba``, ``desktop``, ``keys``, ``quoted``, ``quotedxml``, ``rfc822deb``, ``schemas`` and ``xml``.
     84 	  See the ``intltool-merge`` man page for more information about supported modes of operation.
     85 	:type style: string
     86 	:param flags: compilation flags ("-quc" by default)
     87 	:type flags: list of string
     88 	:param install_path: installation path
     89 	:type install_path: string
     90 	"""
     91 	try:
     92 		self.meths.remove('process_source')
     93 	except ValueError:
     94 		pass
     95 
     96 	self.ensure_localedir()
     97 
     98 	podir = getattr(self, 'podir', '.')
     99 	podirnode = self.path.find_dir(podir)
    100 	if not podirnode:
    101 		error("could not find the podir %r" % podir)
    102 		return
    103 
    104 	cache = getattr(self, 'intlcache', '.intlcache')
    105 	self.env.INTLCACHE = [os.path.join(str(self.path.get_bld()), podir, cache)]
    106 	self.env.INTLPODIR = podirnode.bldpath()
    107 	self.env.append_value('INTLFLAGS', getattr(self, 'flags', self.env.INTLFLAGS_DEFAULT))
    108 
    109 	if '-c' in self.env.INTLFLAGS:
    110 		self.bld.fatal('Redundant -c flag in intltool task %r' % self)
    111 
    112 	style = getattr(self, 'style', None)
    113 	if style:
    114 		try:
    115 			style_flag = _style_flags[style]
    116 		except KeyError:
    117 			self.bld.fatal('intltool_in style "%s" is not valid' % style)
    118 
    119 		self.env.append_unique('INTLFLAGS', [style_flag])
    120 
    121 	for i in self.to_list(self.source):
    122 		node = self.path.find_resource(i)
    123 
    124 		task = self.create_task('intltool', node, node.change_ext(''))
    125 		inst = getattr(self, 'install_path', None)
    126 		if inst:
    127 			self.add_install_files(install_to=inst, install_from=task.outputs)
    128 
    129 @feature('intltool_po')
    130 def apply_intltool_po(self):
    131 	"""
    132 	Creates tasks to process po files::
    133 
    134 		def build(bld):
    135 			bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}")
    136 
    137 	The relevant task generator arguments are:
    138 
    139 	:param podir: directory of the .po files
    140 	:type podir: string
    141 	:param appname: name of the application
    142 	:type appname: string
    143 	:param install_path: installation directory
    144 	:type install_path: string
    145 
    146 	The file LINGUAS must be present in the directory pointed by *podir* and list the translation files to process.
    147 	"""
    148 	try:
    149 		self.meths.remove('process_source')
    150 	except ValueError:
    151 		pass
    152 
    153 	self.ensure_localedir()
    154 
    155 	appname = getattr(self, 'appname', getattr(Context.g_module, Context.APPNAME, 'set_your_app_name'))
    156 	podir = getattr(self, 'podir', '.')
    157 	inst = getattr(self, 'install_path', '${LOCALEDIR}')
    158 
    159 	linguas = self.path.find_node(os.path.join(podir, 'LINGUAS'))
    160 	if linguas:
    161 		# scan LINGUAS file for locales to process
    162 		with open(linguas.abspath()) as f:
    163 			langs = []
    164 			for line in f.readlines():
    165 				# ignore lines containing comments
    166 				if not line.startswith('#'):
    167 					langs += line.split()
    168 		re_linguas = re.compile('[-a-zA-Z_@.]+')
    169 		for lang in langs:
    170 			# Make sure that we only process lines which contain locales
    171 			if re_linguas.match(lang):
    172 				node = self.path.find_resource(os.path.join(podir, re_linguas.match(lang).group() + '.po'))
    173 				task = self.create_task('po', node, node.change_ext('.mo'))
    174 
    175 				if inst:
    176 					filename = task.outputs[0].name
    177 					(langname, ext) = os.path.splitext(filename)
    178 					inst_file = inst + os.sep + langname + os.sep + 'LC_MESSAGES' + os.sep + appname + '.mo'
    179 					self.add_install_as(install_to=inst_file, install_from=task.outputs[0],
    180 						chmod=getattr(self, 'chmod', Utils.O644))
    181 
    182 	else:
    183 		Logs.pprint('RED', "Error no LINGUAS file found in po directory")
    184 
    185 class po(Task.Task):
    186 	"""
    187 	Compiles .po files into .gmo files
    188 	"""
    189 	run_str = '${MSGFMT} -o ${TGT} ${SRC}'
    190 	color   = 'BLUE'
    191 
    192 class intltool(Task.Task):
    193 	"""
    194 	Calls intltool-merge to update translation files
    195 	"""
    196 	run_str = '${INTLTOOL} ${INTLFLAGS} ${INTLCACHE_ST:INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}'
    197 	color   = 'BLUE'
    198 
    199 @conf
    200 def find_msgfmt(conf):
    201 	"""
    202 	Detects msgfmt and sets the ``MSGFMT`` variable
    203 	"""
    204 	conf.find_program('msgfmt', var='MSGFMT')
    205 
    206 @conf
    207 def find_intltool_merge(conf):
    208 	"""
    209 	Detects intltool-merge
    210 	"""
    211 	if not conf.env.PERL:
    212 		conf.find_program('perl', var='PERL')
    213 	conf.env.INTLCACHE_ST = '--cache=%s'
    214 	conf.env.INTLFLAGS_DEFAULT = ['-q', '-u']
    215 	conf.find_program('intltool-merge', interpreter='PERL', var='INTLTOOL')
    216 
    217 def configure(conf):
    218 	"""
    219 	Detects the program *msgfmt* and set *conf.env.MSGFMT*.
    220 	Detects the program *intltool-merge* and set *conf.env.INTLTOOL*.
    221 	It is possible to set INTLTOOL in the environment, but it must not have spaces in it::
    222 
    223 		$ INTLTOOL="/path/to/the program/intltool" waf configure
    224 
    225 	If a C/C++ compiler is present, execute a compilation test to find the header *locale.h*.
    226 	"""
    227 	conf.find_msgfmt()
    228 	conf.find_intltool_merge()
    229 	if conf.env.CC or conf.env.CXX:
    230 		conf.check(header_name='locale.h')
    231