Source code for univention.l10n.message_catalogs

#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2016-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only
"""
This module collects utilities for installing and building message catalogs
while applying Univention specific options.
"""

import os

import polib

from .helper import Error, call, make_parent_dir


def _clean_header(po_path: str) -> None:
    pof = polib.pofile(po_path)
    pof.header = ""
    pof.metadata.update({
        'Content-Type': 'text/plain; charset=utf-8',
    })
    pof.metadata_is_fuzzy = None
    pof.save(po_path)


[docs] def concatenate_po(src_po_path: str, dest_po_path: str) -> None: """ Append first to second `.po` file. :param src_po_path: File to merge. :param dest_po_path: File to merge into. """ call( 'msgcat', '--unique', '--output', dest_po_path, src_po_path, dest_po_path, ) _clean_header(dest_po_path)
[docs] def create_empty_po(binary_pkg_name: str, new_po_path: str) -> None: """ Create a new empty `.po` file. :param binary_pkg_name: Package name. :param new_po_path: File name for new file. """ make_parent_dir(new_po_path) call( 'xgettext', '--force-po', '--add-comments=i18n', '--from-code=UTF-8', '--sort-output', f'--package-name={binary_pkg_name}', '--msgid-bugs-address=packages@univention.de', '--copyright-holder=Univention GmbH', # Suppress warning about /dev/null being an unknown source type '--language', 'C', '-o', new_po_path, '/dev/null') _clean_header(new_po_path)
[docs] def merge_po(template: str, translation: str) -> None: """ Merge old translation with new template file. :param template: New template `.pot` file. :param translation: Old translation `.po` file. """ call( 'msgmerge', '--update', '--sort-output', '--backup=off', translation, template)
[docs] def join_existing(language: str, output_file: str, input_files: str | list[str], cwd: str = os.getcwd()) -> None: """ Extract strings from source code and merge into existing translation file. :param language: Source code language, e.g. `JavaScript`, `Python`, `Shell`. :param output_file: Template file name. :param input_files: Sequence of input files. :param cwd: Base directory used as new woring directory. """ if not os.path.isfile(output_file): raise Error(f"Can't join input files into {output_file}. File does not exist.") if not isinstance(input_files, list): input_files = [input_files] # make input_files relative so the location lines in the resulting po # will be relative to cwd input_files = [os.path.relpath(p, start=cwd) for p in input_files] call( 'xgettext', '--from-code=UTF-8', '--join-existing', '--omit-header', '--language', language, '--keyword=N_:1', '-o', output_file, *input_files, cwd=cwd)
[docs] def univention_location_lines(pot_path: str, abs_path_source_pkg: str) -> None: """ Convert absolute paths to relative paths. :param pot_path: Path to :file:`.pot` file. :param abs_path_source_pkg: Source package base path. """ po_file = polib.pofile(pot_path) for entry in po_file: entry.occurrences = [ ((os.path.relpath(path, start=abs_path_source_pkg), linenum)) for path, linenum in entry.occurrences ] po_file.save(pot_path)