Esempio n. 1
0
def prepare():
    """ Backup the catalogs for usage while merging
    
    When lingui scans the code, it comments out any messages of the catalog that are not in the js code.
    This requires special care in order not to lose any already translated content for non-default locales,
    something that is made worse by the fact that 
    commented out messages do not support context (neither in lingui nor in pybabel)
    
    This will not be required in version 3 of lingui: 
    it will give the ability to define multiple message catalogs 
    that will be merged during its compilation step,
    some of which can be managed externally.
    In that case, we would keep two separate message catalogs for source messages
    (one for messages parsed by lingui and one for messages parsed by pybabel) 
    and compile them both for js (with lingui)
    and for babel (just merge its own source catalog with the source catalog of lingui).
    
    Moreover, we want to mark messages whose default value has changed as fuzzy.
    This requires to know their previous default value (in the default locale message file)
    as well as their current one.
    """
    print("Preparing extraction of python files")
    for locale in supported_locales:
        copyfile(
            catalog_path(locale, CATALOG_FILENAME),
            catalog_path(locale, MID_EXTRACT_CATALOG_FILENAME),
        )
Esempio n. 2
0
def _merge_catalog(locale, source_catalog, default={}):
    """ Add the messages of `source_catalog` in the catalog for `locale`.

    If `default` is not empty, message strings will be populated using the data in `default` 
    TODO: make `default` support context
    else, message strings will be populated using backup catalogs.
    
    The intention is that the default locale will take strings from special comments in the template catalog,
    while the other locales will take their strings from the backup.    
    """
    target_catalog_path = catalog_path(locale, CATALOG_FILENAME)
    print("Merging catalog for %s at %s" % (locale, target_catalog_path))
    with open(target_catalog_path, "r") as target_catalog_file:
        catalog = read_po(target_catalog_file)
    if not default:
        with open(
            catalog_path(locale, MID_EXTRACT_CATALOG_FILENAME), "r"
        ) as target_catalog_file:
            old = read_po(target_catalog_file)
    for message in source_catalog:
        if message.id:  # ignore header
            string = ""
            key = message.id if not message.context else (message.id, message.context)
            if default and key in default:
                message.string = default[key]
            elif old and old.get(message.id, context=message.context):
                message.string = old.get(message.id, context=message.context).string
            catalog[message.id] = message
    with open(target_catalog_path, "wb") as target_catalog_file:
        write_po(target_catalog_file, catalog, ignore_obsolete=True)
Esempio n. 3
0
def clean():
    """ Remove backup catalogs created by `prepare` and convert the catalog of the default locale to a template catalog

    The strings of messages in the catalog of the default locale are added to the template catalog as special comments.
    """
    print("Cleaning up")
    # Remove temp files for non-default locales
    for locale in supported_locales:
        if locale != default_locale:
            remove(catalog_path(locale, MID_EXTRACT_CATALOG_FILENAME))

    # Update template file for default locale
    with open(catalog_path(default_locale, CATALOG_FILENAME)) as catalog_file:
        catalog = read_po(catalog_file)
    for message in catalog:
        message.auto_comments.append(
            COMMENT_TAG_FOR_DEFAULT_MESSAGE + ": " + message.string
        )
        message.string = ""
    with open(
        catalog_path(default_locale, TEMPLATE_CATALOG_FILENAME), "wb"
    ) as source_catalog_file:
        write_po(
            source_catalog_file,
            catalog,
            ignore_obsolete=True,
            width=10000000,  # we set a huge value for width, so that special comments do not wrap
            omit_header=True,
        )
Esempio n. 4
0
def clean():
    """Remove backup catalogs created by `prepare` and convert the catalog of the default locale to a template catalog

    The strings of messages in the catalog of the default locale are added to the template catalog as special comments.
    """
    print("Cleaning up")
    # Remove temp files
    for locale in supported_locales:
        remove(catalog_path(locale, MID_EXTRACT_CATALOG_FILENAME))

    # Update template file for default locale
    catalog = read_po_catalog(catalog_path(default_locale, CATALOG_FILENAME))
    move_strings_to_comments(catalog, comment_tag=COMMENT_TAG_FOR_DEFAULT_MESSAGE)
    write_po_catalog(
        catalog_path(default_locale, TEMPLATE_CATALOG_FILENAME),
        catalog,
        ignore_obsolete=True,
        width=10000000,  # we set a huge value for width, so that special comments do not wrap
        omit_header=True,
    )
Esempio n. 5
0
def merge():
    """ Merge the messages found in the template catalog of the default locale into the catalogs of all locales.
    
    The template catalog is searched for special comments that indicate default messages.
    These messages are added to the catalog for the default locale.
    
    We compare the old and new default messages.
    If they are (non-empty and) different, we will mark them as fuzzy in message catalogs (of non-default locales).
    """
    # First, merge the js and python catalogs for the default locale and find fuzzy messages
    print("Merging catalog for %s at %s" %
          (default_locale, catalog_path(default_locale, CATALOG_FILENAME)))
    old_source_catalog = read_po_catalog(
        catalog_path(default_locale, MID_EXTRACT_CATALOG_FILENAME))
    js_catalog = read_po_catalog(catalog_path(default_locale,
                                              CATALOG_FILENAME))

    python_catalog = read_po_catalog(
        catalog_path(default_locale, TEMPLATE_CATALOG_FILENAME))

    (catalog, python_source_catalog,
     fuzzy) = _merge_source_catalog(js_catalog, python_catalog,
                                    old_source_catalog)

    write_po_catalog(catalog_path(default_locale, CATALOG_FILENAME),
                     catalog,
                     ignore_obsolete=True)
    print("Found %s new fuzzy messages" % len(fuzzy))

    # Then, add the new python messages to the catalogs for the other locales and mark fuzzy messages
    for locale in supported_locales:
        if locale != default_locale:
            target_catalog_path = catalog_path(locale, CATALOG_FILENAME)
            print("Merging catalog for %s at %s" %
                  (locale, target_catalog_path))
            js_catalog = read_po_catalog(target_catalog_path)
            old = read_po_catalog(
                catalog_path(locale, MID_EXTRACT_CATALOG_FILENAME))

            catalog = _merge_catalogs([js_catalog, python_source_catalog], old,
                                      fuzzy)

            write_po_catalog(target_catalog_path,
                             catalog,
                             ignore_obsolete=True)
Esempio n. 6
0
def merge():
    """ Merge the messages found in the template catalog of the default locale into the catalogs of all locales.
    
    The template catalog is searched for special comments that indicate default messages.
    These messages are added to the catalog for the default locale.
    """
    source_catalog_path = catalog_path(default_locale, TEMPLATE_CATALOG_FILENAME)
    with open(source_catalog_path) as source_catalog_file:
        source_catalog = read_po(source_catalog_file)
    default_messages = {}
    print("Reading source locale pot file at %s" % source_catalog_path)
    for message in source_catalog:
        for comment in message.auto_comments:
            match = _default_message_re.match(comment)
            if match:
                key = (
                    message.id if not message.context else (message.id, message.context)
                )
                default_messages[key] = match.group(1).strip()
                message.auto_comments.remove(comment)
    for locale in supported_locales:
        if locale != default_locale:
            _merge_catalog(locale, source_catalog)
    _merge_catalog(default_locale, source_catalog, default_messages)
Esempio n. 7
0
 def _for_application(self) -> MessageLocalizer:
     """Return a `MessageLocalizer` for the application messages"""
     catalogs = {}
     for locale_id in supported_locales:
         catalogs[locale_id] = read_po_catalog(catalog_path(locale_id))
     return MessageLocalizer(catalogs)