]> git.lyx.org Git - lyx.git/blob - po/lyx_pot.py
pt_BR.po: updates by Georger
[lyx.git] / po / lyx_pot.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 # file lyx_pot.py
5 # This file is part of LyX, the document processor.
6 # Licence details can be found in the file COPYING.
7 #
8 # \author Bo Peng
9 #
10 # Full author contact details are available in file CREDITS
11
12 # Usage: use
13 #     lyx_pot.py -h
14 # to get usage message
15
16 # This script will extract translatable strings from input files and write
17 # to output in gettext .pot format.
18 #
19 from __future__ import print_function
20
21 import sys, os, re, getopt
22 import io
23
24 def relativePath(path, base):
25     '''return relative path from top source dir'''
26     # full pathname of path
27     path1 = os.path.normpath(os.path.realpath(path)).split(os.sep)
28     path2 = os.path.normpath(os.path.realpath(base)).split(os.sep)
29     if path1[:len(path2)] != path2:
30         print("Path %s is not under top source directory" % path)
31     path3 = os.path.join(*path1[len(path2):]);
32     # replace all \ by / such that we get the same comments on Windows and *nix
33     path3 = path3.replace('\\', '/')
34     return path3
35
36
37 def writeString(outfile, infile, basefile, lineno, string):
38     string = string.replace('\\', '\\\\').replace('"', '')
39     if string == "":
40         return
41     print(u'#: %s:%d\nmsgid "%s"\nmsgstr ""\n' % \
42         (relativePath(infile, basefile), lineno, string), file=outfile)
43
44
45 def ui_l10n(input_files, output, base):
46     '''Generate pot file from lib/ui/*'''
47     output = io.open(output, 'w', encoding='utf_8')
48     Submenu = re.compile(r'^[^#]*Submenu\s+"([^"]*)"', re.IGNORECASE)
49     Popupmenu = re.compile(r'^[^#]*PopupMenu\s+"[^"]+"\s+"([^"]*)"', re.IGNORECASE)
50     IconPalette = re.compile(r'^[^#]*IconPalette\s+"[^"]+"\s+"([^"]*)"', re.IGNORECASE)
51     Toolbar = re.compile(r'^[^#]*Toolbar\s+"[^"]+"\s+"([^"]*)"', re.IGNORECASE)
52     Item = re.compile(r'[^#]*Item\s+"([^"]*)"', re.IGNORECASE)
53     TableInsert = re.compile(r'[^#]*TableInsert\s+"([^"]*)"', re.IGNORECASE)
54     for src in input_files:
55         input = io.open(src, encoding='utf_8')
56         for lineno, line in enumerate(input.readlines()):
57             if Submenu.match(line):
58                 (string,) = Submenu.match(line).groups()
59                 string = string.replace('_', ' ')
60             elif Popupmenu.match(line):
61                 (string,) = Popupmenu.match(line).groups()
62             elif IconPalette.match(line):
63                 (string,) = IconPalette.match(line).groups()
64             elif Toolbar.match(line):
65                 (string,) = Toolbar.match(line).groups()
66             elif Item.match(line):
67                 (string,) = Item.match(line).groups()
68             elif TableInsert.match(line):
69                 (string,) = TableInsert.match(line).groups()
70             else:
71                 continue
72             string = string.replace('"', '')
73             if string != "":
74                 print(u'#: %s:%d\nmsgid "%s"\nmsgstr ""\n' % \
75                     (relativePath(src, base), lineno+1, string), file=output)
76         input.close()
77     output.close()
78
79
80 def layouts_l10n(input_files, output, base, layouttranslations):
81     '''Generate pot file from lib/layouts/*.{layout,inc,module}'''
82     ClassDescription = re.compile(r'^\s*#\s*\\Declare(LaTeX|DocBook)Class.*\{(.*)\}$', re.IGNORECASE)
83     ClassCategory = re.compile(r'^\s*#\s*\\DeclareCategory\{(.*)\}$', re.IGNORECASE)
84     Style = re.compile(r'^\s*Style\s+(.*\S)\s*$', re.IGNORECASE)
85     # match LabelString, EndLabelString, LabelStringAppendix and maybe others but no comments
86     LabelString = re.compile(r'^[^#]*LabelString\S*\s+(.*\S)\s*$', re.IGNORECASE)
87     MenuString = re.compile(r'^[^#]*MenuString\S*\s+(.*\S)\s*$', re.IGNORECASE)
88     OutlinerName = re.compile(r'^[^#]*OutlinerName\s+(\S+|\"[^\"]*\")\s+(\S+|\"[^\"]*\")\s*$', re.IGNORECASE)
89     Tooltip = re.compile(r'^\s*Tooltip\S*\s+(.*\S)\s*$', re.IGNORECASE)
90     GuiName = re.compile(r'^\s*GuiName\s+(.*\S)\s*$', re.IGNORECASE)
91     ListName = re.compile(r'^\s*ListName\s+(.*\S)\s*$', re.IGNORECASE)
92     CategoryName = re.compile(r'^\s*Category\s+(.*\S)\s*$', re.IGNORECASE)
93     NameRE = re.compile(r'^\s*#\s*\\DeclareLyXModule.*{(.*)}$', re.IGNORECASE)
94     InsetLayout = re.compile(r'^InsetLayout\s+\"?(.*)\"?\s*$', re.IGNORECASE)
95     FlexCheck = re.compile(r'^Flex:(.*)', re.IGNORECASE)
96     CaptionCheck = re.compile(r'^Caption:(.*)', re.IGNORECASE)
97     DescBegin = re.compile(r'^\s*#DescriptionBegin\s*$', re.IGNORECASE)
98     DescEnd = re.compile(r'^\s*#\s*DescriptionEnd\s*$', re.IGNORECASE)
99     Category = re.compile(r'^\s*#\s*Category:\s+(.*\S)\s*$', re.IGNORECASE)
100     I18nPreamble = re.compile(r'^\s*((Lang)|(Babel))Preamble\s*$', re.IGNORECASE)
101     EndI18nPreamble = re.compile(r'^\s*End((Lang)|(Babel))Preamble\s*$', re.IGNORECASE)
102     I18nString = re.compile(r'_\(([^\)]+)\)')
103     CounterFormat = re.compile(r'^\s*PrettyFormat\s+"?(.*)"?\s*$', re.IGNORECASE)
104     CiteFormat = re.compile(r'^\s*CiteFormat', re.IGNORECASE)
105     KeyVal = re.compile(r'^\s*_\w+\s+(.*\S)\s*$')
106     Float = re.compile(r'^\s*Float\s*$', re.IGNORECASE)
107     UsesFloatPkg = re.compile(r'^\s*UsesFloatPkg\s+(.*\S)\s*$', re.IGNORECASE)
108     IsPredefined = re.compile(r'^\s*IsPredefined\s+(.*\S)\s*$', re.IGNORECASE)
109     End = re.compile(r'^\s*End', re.IGNORECASE)
110     Comment = re.compile(r'^(.*)#')
111     Translation = re.compile(r'^\s*Translation\s+(.*\S)\s*$', re.IGNORECASE)
112     KeyValPair = re.compile(r'\s*"(.*)"\s+"(.*)"')
113
114     oldlanguages = []
115     languages = []
116     keyset = set()
117     oldtrans = dict()
118     if layouttranslations:
119         linguas_file = os.path.join(base, 'po/LINGUAS')
120         for line in open(linguas_file).readlines():
121             res = Comment.search(line)
122             if res:
123                 line = res.group(1)
124             if line.strip() != '':
125                 languages.extend(line.split())
126
127         # read old translations if available
128         try:
129             input = io.open(output, encoding='utf_8')
130             lang = ''
131             for line in input.readlines():
132                 res = Comment.search(line)
133                 if res:
134                     line = res.group(1)
135                 if line.strip() == '':
136                     continue
137                 res = Translation.search(line)
138                 if res:
139                     lang = res.group(1)
140                     if lang not in languages:
141                         oldlanguages.append(lang)
142                         languages.append(lang)
143                     oldtrans[lang] = dict()
144                     continue
145                 res = End.search(line)
146                 if res:
147                     lang = ''
148                     continue
149                 res = KeyValPair.search(line)
150                 if res and lang != '':
151                     key = res.group(1)
152                     val = res.group(2)
153                     key = key.replace('\\"', '"').replace('\\\\', '\\')
154                     val = val.replace('\\"', '"').replace('\\\\', '\\')
155                     oldtrans[lang][key] = val
156                     keyset.add(key)
157                     continue
158                 print("Error: Unable to handle line:")
159                 print(line)
160         except IOError:
161             print("Warning: Unable to open %s for reading." % output)
162             print("         Old translations will be lost.")
163
164         # walon is not a known document language
165         # FIXME: Do not hardcode, read from lib/languages!
166         if 'wa' in languages:
167             languages.remove('wa')
168
169     out = io.open(output, 'w', encoding='utf_8')
170     for src in input_files:
171         readingDescription = False
172         readingI18nPreamble = False
173         readingFloat = False
174         readingCiteFormats = False
175         isPredefined = False
176         usesFloatPkg = True
177         listname = ''
178         floatname = ''
179         descStartLine = -1
180         descLines = []
181         lineno = 0
182         for line in io.open(src, encoding='utf_8').readlines():
183             lineno += 1
184             res = ClassDescription.search(line)
185             if res != None:
186                 string = res.group(2)
187                 if not layouttranslations:
188                     writeString(out, src, base, lineno + 1, string)
189                 continue
190             res = ClassCategory.search(line)
191             if res != None:
192                 string = res.group(1)
193                 if not layouttranslations:
194                     writeString(out, src, base, lineno + 1, string)
195                 continue
196             if readingDescription:
197                 res = DescEnd.search(line)
198                 if res != None:
199                     readingDescription = False
200                     desc = " ".join(descLines)
201                     if not layouttranslations:
202                         writeString(out, src, base, lineno + 1, desc)
203                     continue
204                 descLines.append(line[1:].strip())
205                 continue
206             res = DescBegin.search(line)
207             if res != None:
208                 readingDescription = True
209                 descStartLine = lineno
210                 continue
211             if readingI18nPreamble:
212                 res = EndI18nPreamble.search(line)
213                 if res != None:
214                     readingI18nPreamble = False
215                     continue
216                 res = I18nString.search(line)
217                 if res != None:
218                     string = res.group(1)
219                     if layouttranslations:
220                         keyset.add(string)
221                     else:
222                         writeString(out, src, base, lineno, string)
223                 continue
224             res = I18nPreamble.search(line)
225             if res != None:
226                 readingI18nPreamble = True
227                 continue
228             res = NameRE.search(line)
229             if res != None:
230                 string = res.group(1)
231                 if not layouttranslations:
232                     writeString(out, src, base, lineno + 1, string)
233                 continue
234             res = Style.search(line)
235             if res != None:
236                 string = res.group(1)
237                 string = string.replace('_', ' ')
238                 # Style means something else inside a float definition
239                 if not readingFloat:
240                     if not layouttranslations:
241                         writeString(out, src, base, lineno, string)
242                 continue
243             res = LabelString.search(line)
244             if res != None:
245                 string = res.group(1)
246                 if not layouttranslations:
247                     writeString(out, src, base, lineno, string)
248                 continue
249             res = MenuString.search(line)
250             if res != None:
251                 string = res.group(1)
252                 if not layouttranslations:
253                     writeString(out, src, base, lineno, string)
254                 continue
255             res = OutlinerName.search(line)
256             if res != None:
257                 string = res.group(2)
258                 if not layouttranslations:
259                     writeString(out, src, base, lineno, string)
260                 continue
261             res = Tooltip.search(line)
262             if res != None:
263                 string = res.group(1)
264                 if not layouttranslations:
265                     writeString(out, src, base, lineno, string)
266                 continue
267             res = GuiName.search(line)
268             if res != None:
269                 string = res.group(1)
270                 if layouttranslations:
271                     # gui name must only be added for floats
272                     if readingFloat:
273                         floatname = string
274                 else:
275                     writeString(out, src, base, lineno, string)
276                 continue
277             res = CategoryName.search(line)
278             if res != None:
279                 string = res.group(1)
280                 if not layouttranslations:
281                     writeString(out, src, base, lineno, string)
282                 continue
283             res = ListName.search(line)
284             if res != None:
285                 string = res.group(1)
286                 if layouttranslations:
287                     listname = string.strip('"')
288                 else:
289                     writeString(out, src, base, lineno, string)
290                 continue
291             res = InsetLayout.search(line)
292             if res != None:
293                 string = res.group(1)
294                 string = string.replace('_', ' ')
295                 #Flex:xxx is not used in translation
296                 #if not layouttranslations:
297                 #    writeString(out, src, base, lineno, string)
298                 m = FlexCheck.search(string)
299                 if m:
300                     if not layouttranslations:
301                         writeString(out, src, base, lineno, m.group(1))
302                 m = CaptionCheck.search(string)
303                 if m:
304                     if not layouttranslations:
305                         writeString(out, src, base, lineno, m.group(1))
306                 continue
307             res = Category.search(line)
308             if res != None:
309                 string = res.group(1)
310                 if not layouttranslations:
311                     writeString(out, src, base, lineno, string)
312                 continue
313             res = CounterFormat.search(line)
314             if res != None:
315                 string = res.group(1)
316                 if not layouttranslations:
317                     writeString(out, src, base, lineno, string)
318                 continue
319             res = Float.search(line)
320             if res != None:
321                 readingFloat = True
322                 continue
323             res = IsPredefined.search(line)
324             if res != None:
325                 string = res.group(1).lower()
326                 if string == 'true':
327                     isPredefined = True
328                 else:
329                     isPredefined = False
330                 continue
331             res = UsesFloatPkg.search(line)
332             if res != None:
333                 string = res.group(1).lower()
334                 if string == 'true':
335                     usesFloatPkg = True
336                 else:
337                     usesFloatPkg = False
338                 continue
339             res = CiteFormat.search(line)
340             if res != None:
341                 readingCiteFormats = True
342                 continue
343             res = End.search(line)
344             if res != None:
345                 # We have four combinations of the flags usesFloatPkg and isPredefined:
346                 #     usesFloatPkg and     isPredefined: might use standard babel translations
347                 #     usesFloatPkg and not isPredefined: does not use standard babel translations
348                 # not usesFloatPkg and     isPredefined: uses standard babel translations
349                 # not usesFloatPkg and not isPredefined: not supported by LyX
350                 # The third combination is even true for MarginFigure, MarginTable (both from
351                 # tufte-book.layout) and Planotable, Plate (both from aguplus.inc).
352                 if layouttranslations and readingFloat and usesFloatPkg:
353                     if floatname != '':
354                         keyset.add(floatname)
355                     if listname != '':
356                         keyset.add(listname)
357                 isPredefined = False
358                 usesFloatPkg = True
359                 listname = ''
360                 floatname = ''
361                 readingCiteFormats = False
362                 readingFloat = False
363                 continue
364             if readingCiteFormats:
365                 res = KeyVal.search(line)
366                 if res != None:
367                     val = res.group(1)
368                     if not layouttranslations:
369                         writeString(out, src, base, lineno, val)
370
371     if layouttranslations:
372         # Extract translations of layout files
373         import polib
374
375         # Sort languages and key to minimize the diff between different runs
376         # with changed translations
377         languages.sort()
378         keys = []
379         for key in keyset:
380             keys.append(key)
381         keys.sort()
382
383         ContextRe = re.compile(r'(.*)(\[\[.*\]\])')
384
385         print(u'''# This file has been automatically generated by po/lyx_pot.py.
386 # PLEASE MODIFY ONLY THE LAGUAGES HAVING NO .po FILE! If you want to regenerate
387 # this file from the translations, run `make ../lib/layouttranslations' in po.
388 # Python polib library is needed for building the output file.
389 #
390 # This file should remain fixed during minor LyX releases.
391 # For more comments see README.localization file.''', file=out)
392         for lang in languages:
393             print(u'\nTranslation %s' % lang, file=out)
394             if lang in list(oldtrans.keys()):
395                 trans = oldtrans[lang]
396             else:
397                 trans = dict()
398             if not lang in oldlanguages:
399                 poname = os.path.join(base, 'po/' + lang + '.po')
400                 po = polib.pofile(poname)
401                 # Iterate through po entries and not keys for speed reasons.
402                 # FIXME: The code is still too slow
403                 for entry in po:
404                     if not entry.translated():
405                         continue
406                     if entry.msgid in keys:
407                         key = entry.msgid
408                         val = entry.msgstr
409                         # some translators keep untranslated entries
410                         if val != key:
411                             trans[key] = val
412             for key in keys:
413                 if key in list(trans.keys()):
414                     val = trans[key].replace('\\', '\\\\').replace('"', '\\"')
415                     res = ContextRe.search(val)
416                     if res != None:
417                         val = res.group(1)
418                     key = key.replace('\\', '\\\\').replace('"', '\\"')
419                     print(u'\t"%s" "%s"' % (key, val), file=out)
420                 # also print untranslated entries to help translators
421                 elif not lang in oldlanguages:
422                     key = key.replace('\\', '\\\\').replace('"', '\\"')
423                     res = ContextRe.search(key)
424                     if res != None:
425                         val = res.group(1)
426                     else:
427                         val = key
428                     print(u'\t"%s" "%s"' % (key, val), file=out)
429             print(u'End', file=out)
430
431     out.close()
432
433
434 def qt4_l10n(input_files, output, base):
435     '''Generate pot file from src/frontends/qt4/ui/*.ui'''
436     output = io.open(output, 'w', encoding='utf_8')
437     pat = re.compile(r'\s*<string>(.*)</string>')
438     prop = re.compile(r'\s*<property.*name.*=.*shortcut')
439     for src in input_files:
440         input = io.open(src, encoding='utf_8')
441         skipNextLine = False
442         for lineno, line in enumerate(input.readlines()):
443             # skip the line after <property name=shortcut>
444             if skipNextLine:
445                 skipNextLine = False
446                 continue
447             if prop.match(line):
448                 skipNextLine = True
449                 continue
450             # get lines that match <string>...</string>
451             if pat.match(line):
452                 (string,) = pat.match(line).groups()
453                 string = string.replace('&amp;', '&').replace('&quot;', '"')
454                 string = string.replace('&lt;', '<').replace('&gt;', '>')
455                 string = string.replace('\\', '\\\\').replace('"', r'\"')
456                 string = string.replace('&#x0a;', r'\n')
457                 print(u'#: %s:%d\nmsgid "%s"\nmsgstr ""\n' % \
458                     (relativePath(src, base), lineno+1, string), file=output)
459         input.close()
460     output.close()
461
462
463 def languages_l10n(input_files, output, base):
464     '''Generate pot file from lib/languages'''
465     out = io.open(output, 'w', encoding='utf_8')
466     GuiName = re.compile(r'^[^#]*GuiName\s+(.*)', re.IGNORECASE)
467
468     for src in input_files:
469         descStartLine = -1
470         descLines = []
471         lineno = 0
472         for line in io.open(src, encoding='utf_8').readlines():
473             lineno += 1
474             res = GuiName.search(line)
475             if res != None:
476                 string = res.group(1)
477                 writeString(out, src, base, lineno, string)
478                 continue
479
480     out.close()
481
482
483 def latexfonts_l10n(input_files, output, base):
484     '''Generate pot file from lib/latexfonts'''
485     out = io.open(output, 'w', encoding='utf_8')
486     GuiName = re.compile(r'^[^#]*GuiName\s+(.*)', re.IGNORECASE)
487
488     for src in input_files:
489         descStartLine = -1
490         descLines = []
491         lineno = 0
492         for line in io.open(src, encoding='utf_8').readlines():
493             lineno += 1
494             res = GuiName.search(line)
495             if res != None:
496                 string = res.group(1)
497                 writeString(out, src, base, lineno, string)
498                 continue
499
500     out.close()
501
502
503 def external_l10n(input_files, output, base):
504     '''Generate pot file from lib/external_templates'''
505     output = io.open(output, 'w', encoding='utf_8')
506     Template = re.compile(r'^Template\s+(.*)', re.IGNORECASE)
507     GuiName = re.compile(r'\s*GuiName\s+(.*)', re.IGNORECASE)
508     HelpTextStart = re.compile(r'\s*HelpText\s', re.IGNORECASE)
509     HelpTextSection = re.compile(r'\s*(\S.*)\s*$')
510     HelpTextEnd = re.compile(r'\s*HelpTextEnd\s', re.IGNORECASE)
511     i = -1
512     for src in input_files:
513         input = io.open(src, encoding='utf_8')
514         inHelp = False
515         hadHelp = False
516         prev_help_string = ''
517         for lineno, line in enumerate(input.readlines()):
518             if Template.match(line):
519                 (string,) = Template.match(line).groups()
520             elif GuiName.match(line):
521                 (string,) = GuiName.match(line).groups()
522             elif inHelp:
523                 if HelpTextEnd.match(line):
524                     if hadHelp:
525                         print(u'\nmsgstr ""\n', file=output)
526                     inHelp = False
527                     hadHelp = False
528                     prev_help_string = ''
529                 elif HelpTextSection.match(line):
530                     (help_string,) = HelpTextSection.match(line).groups()
531                     help_string = help_string.replace('"', '')
532                     if help_string != "" and prev_help_string == '':
533                         print(u'#: %s:%d\nmsgid ""\n"%s\\n"' % \
534                             (relativePath(src, base), lineno+1, help_string), file=output)
535                         hadHelp = True
536                     elif help_string != "":
537                         print(u'"%s\\n"' % help_string, file=output)
538                     prev_help_string = help_string
539             elif HelpTextStart.match(line):
540                 inHelp = True
541                 prev_help_string = ''
542             else:
543                 continue
544             string = string.replace('"', '')
545             if string != "" and not inHelp:
546                 print(u'#: %s:%d\nmsgid "%s"\nmsgstr ""\n' % \
547                     (relativePath(src, base), lineno+1, string), file=output)
548         input.close()
549     output.close()
550
551
552 def formats_l10n(input_files, output, base):
553     '''Generate pot file from configure.py'''
554     output = io.open(output, 'w', encoding='utf_8')
555     GuiName = re.compile(r'.*\\Format\s+\S+\s+\S+\s+"([^"]*)"\s+(\S*)\s+.*', re.IGNORECASE)
556     GuiName2 = re.compile(r'.*\\Format\s+\S+\s+\S+\s+([^"]\S+)\s+(\S*)\s+.*', re.IGNORECASE)
557     input = io.open(input_files[0], encoding='utf_8')
558     for lineno, line in enumerate(input.readlines()):
559         label = ""
560         labelsc = ""
561         if GuiName.match(line):
562             label = GuiName.match(line).group(1)
563             shortcut = GuiName.match(line).group(2).replace('"', '')
564         elif GuiName2.match(line):
565             label = GuiName2.match(line).group(1)
566             shortcut = GuiName2.match(line).group(2).replace('"', '')
567         else:
568             continue
569         label = label.replace('\\', '\\\\').replace('"', '')
570         if shortcut != "":
571             labelsc = label + "|" + shortcut
572         if label != "":
573             print(u'#: %s:%d\nmsgid "%s"\nmsgstr ""\n' % \
574                 (relativePath(input_files[0], base), lineno+1, label), file=output)
575         if labelsc != "":
576             print(u'#: %s:%d\nmsgid "%s"\nmsgstr ""\n' % \
577                 (relativePath(input_files[0], base), lineno+1, labelsc), file=output)
578     input.close()
579     output.close()
580
581
582 def encodings_l10n(input_files, output, base):
583     '''Generate pot file from lib/encodings'''
584     output = io.open(output, 'w', encoding='utf_8')
585     # assuming only one encodings file
586     #                 Encoding utf8      utf8    "Unicode (utf8)" UTF-8    variable inputenc
587     reg = re.compile('Encoding [\w-]+\s+[\w-]+\s+"([\w \-\(\)]+)"\s+[\w-]+\s+(fixed|variable|variableunsafe)\s+\w+.*')
588     input = io.open(input_files[0], encoding='utf_8')
589     for lineno, line in enumerate(input.readlines()):
590         if not line.startswith('Encoding'):
591             continue
592         if reg.match(line):
593             print(u'#: %s:%d\nmsgid "%s"\nmsgstr ""\n' % \
594                 (relativePath(input_files[0], base), lineno+1, reg.match(line).groups()[0]), file=output)
595         else:
596             print("Error: Unable to handle line:")
597             print(line)
598             # No need to abort if the parsing fails
599             # sys.exit(1)
600     input.close()
601     output.close()
602
603
604
605 Usage = '''
606 lyx_pot.py [-b|--base top_src_dir] [-o|--output output_file] [-h|--help] [-s|src_file filename] -t|--type input_type input_files
607
608 where
609     --base:
610         path to the top source directory. default to '.'
611     --output:
612         output pot file, default to './lyx.pot'
613     --src_file
614         filename that contains a list of input files in each line
615     --input_type can be
616         ui: lib/ui/*
617         layouts: lib/layouts/*
618         layouttranslations: create lib/layouttranslations from po/*.po and lib/layouts/*
619         qt4: qt4 ui files
620         languages: file lib/languages
621         latexfonts: file lib/latexfonts
622         encodings: file lib/encodings
623         external: external templates file
624         formats: formats predefined in lib/configure.py
625 '''
626
627 if __name__ == '__main__':
628     input_type = None
629     output = 'lyx.pot'
630     base = '.'
631     input_files = []
632     #
633     optlist, args = getopt.getopt(sys.argv[1:], 'ht:o:b:s:',
634         ['help', 'type=', 'output=', 'base=', 'src_file='])
635     for (opt, value) in optlist:
636         if opt in ['-h', '--help']:
637             print(Usage)
638             sys.exit(0)
639         elif opt in ['-o', '--output']:
640             output = value
641         elif opt in ['-b', '--base']:
642             base = value
643         elif opt in ['-t', '--type']:
644             input_type = value
645         elif opt in ['-s', '--src_file']:
646             input_files = [f.strip() for f in io.open(value, encoding='utf_8')]
647
648     if input_type not in ['ui', 'layouts', 'layouttranslations', 'qt4', 'languages', 'latexfonts', 'encodings', 'external', 'formats'] or output is None:
649         print('Wrong input type or output filename.')
650         sys.exit(1)
651
652     input_files += args
653
654     # Ensure a unique sorting of input files and ignore the order in which they
655     # are given on the command line. This is important to avoid huge
656     # pseudo-diffs in the generated .pot file which would then end up in the
657     # .po files as well. We had this situation for years with people using
658     # different build systems to remerge .po files.
659     input_files.sort()
660
661     if input_type == 'ui':
662         ui_l10n(input_files, output, base)
663     elif input_type == 'latexfonts':
664         latexfonts_l10n(input_files, output, base)
665     elif input_type == 'layouts':
666         layouts_l10n(input_files, output, base, False)
667     elif input_type == 'layouttranslations':
668         layouts_l10n(input_files, output, base, True)
669     elif input_type == 'qt4':
670         qt4_l10n(input_files, output, base)
671     elif input_type == 'external':
672         external_l10n(input_files, output, base)
673     elif input_type == 'formats':
674         formats_l10n(input_files, output, base)
675     elif input_type == 'encodings':
676         encodings_l10n(input_files, output, base)
677     else:
678         languages_l10n(input_files, output, base)
679
680