lupdate.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. # Copyright (c) 2026 Riverbank Computing Limited <info@riverbankcomputing.com>
  2. #
  3. # This file is part of PyQt6.
  4. #
  5. # This file may be used under the terms of the GNU General Public License
  6. # version 3.0 as published by the Free Software Foundation and appearing in
  7. # the file LICENSE included in the packaging of this file. Please review the
  8. # following information to ensure the GNU General Public License version 3.0
  9. # requirements will be met: http://www.gnu.org/copyleft/gpl.html.
  10. #
  11. # If you do not wish to use this file under the terms of the GPL version 3.0
  12. # then you may purchase a commercial license. For more information contact
  13. # info@riverbankcomputing.com.
  14. #
  15. # This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
  16. # WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  17. import fnmatch
  18. import os
  19. from .designer_source import DesignerSource
  20. from .python_source import PythonSource
  21. from .translation_file import TranslationFile
  22. from .user import UserException
  23. def lupdate(sources, translation_files, no_obsolete=False, no_summary=True,
  24. verbose=False, excludes=None):
  25. """ Update a sequence of translation (.ts) files from a sequence of Python
  26. source (.py) files, Designer source (.ui) files or directories containing
  27. source files.
  28. """
  29. if excludes is None:
  30. excludes = ()
  31. # Read the .ts files.
  32. translations = [TranslationFile(ts, no_obsolete=no_obsolete,
  33. no_summary=no_summary, verbose=verbose)
  34. for ts in translation_files]
  35. # Read the sources.
  36. source_files = []
  37. for source in sources:
  38. if os.path.isdir(source):
  39. for dirpath, dirnames, filenames in os.walk(source):
  40. _remove_excludes(dirnames, excludes)
  41. _remove_excludes(filenames, excludes)
  42. for fn in filenames:
  43. filename = os.path.join(dirpath, fn)
  44. if filename.endswith('.py'):
  45. source_files.append(
  46. PythonSource(filename=filename,
  47. verbose=verbose))
  48. elif filename.endswith('.ui'):
  49. source_files.append(
  50. DesignerSource(filename=filename,
  51. verbose=verbose))
  52. elif verbose:
  53. print("Ignoring", filename)
  54. elif source.endswith('.py'):
  55. source_files.append(
  56. PythonSource(filename=source, verbose=verbose))
  57. elif source.endswith('.ui'):
  58. source_files.append(
  59. DesignerSource(filename=source, verbose=verbose))
  60. else:
  61. raise UserException(
  62. "{0} must be a directory or a .py or a .ui file".format(
  63. source))
  64. # Update each translation for each source.
  65. for t in translations:
  66. for s in source_files:
  67. t.update(s)
  68. t.write()
  69. def _remove_excludes(names, excludes):
  70. """ Remove all implicitly and explicitly excluded names from a list. """
  71. for name in list(names):
  72. if name.startswith('.'):
  73. names.remove(name)
  74. else:
  75. for exclude in excludes:
  76. if fnmatch.fnmatch(name, exclude):
  77. names.remove(name)
  78. break