# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License or (at your option) version 3 or any later version
# accepted by the membership of KDE e.V. (or its successor appro-
# ved by the membership of KDE e.V.), which shall act as a proxy
# defined in Section 14 of version 3 of the license.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/.
#
# Copyright (C) 2011 Eike Hein


"""
This module provides i18n support for Konversation scripts written in Python,
via gettext.

Call the init() function to install the various functions that may be used to
mark up translatable strings in the builtins namespace, and optionally specify
a gettext .mo filename to use. See the function's documentation for more
details.

This module is considered EXPERIMENTAL at this time and not part of the public,
stable scripting interface.

"""

import gettext
import os
import subprocess

try:
    # Python 2.x.
    import __builtin__ as builtins
except ImportError:
    # Python 3.x.
    import builtins


def init(domain='konversation'):

    """
    Initializes gettext and installs the following functions in the builtins
    namespace:

    i18n(message[, arg1, arg2, ...])
    i18np(singular, plural, num[, arg1, arg2, ...])
    i18nc(context, message[, arg1, arg2, ...])
    i18ncp(context, singular, plural, num[, arg1, arg2, ...])

    Third-party scripts may want to provide the 'domain' keyword argument to
    specify the name of their own gettext .mo file, which has to be installed
    in one of the directories that KDE considers for this type of resource.

    Keyword arguments:
    domain -- The gettext domain to use (default 'konversation').

    """

    dirs = locale_directories()

    for dir in dirs:
        try:
            t = gettext.translation(domain=domain,
                                    localedir=dir,
                                    languages=(current_language(),),
                                    fallback=False)
        except IOError:
            if dir is dirs[-1]:
                t = gettext.NullTranslations()

            continue
        else:
            break

    def i18n(msg, *args):
        return _insert_args(t.gettext(msg), args)

    def i18np(smsg, pmsg, num, *args):
        return _insert_args(t.ngettext(smsg, pmsg, num), args)

    # Context is part of the gettext msgid. Sadly Python's gettext API currently
    # doesn't have a convenient way to hand over both context and message, hence
    # the trick using string formatting here. Python bug 2504 indicates the API
    # may be extended to support context in Python 3.3.
    s = '{0}\x04{1}'

    def i18nc(ctxt, msg, *args):
        translated = t.gettext(s.format(ctxt, msg))
        
        if '\x04' in translated:
            translated = msg

        return _insert_args(translated, args)

    def i18ncp(ctxt, smsg, pmsg, num, *args):
        translated = t.ngettext(s.format(ctxt, smsg), s.format(ctxt, pmsg), num)

        if '\x04' in translated:
            # "If no message catalog is found msgid1 is returned if n == 1, otherwise msgid2."
            # (Source: GNU gettext v0.18 docs, 11.2.6 Additional functions for plural forms)
            translated = smsg if num == 1 else pmsg

        return _insert_args(translated, args)

    for func in (i18n, i18np, i18nc, i18ncp):
        builtins.__dict__[func.__name__] = func

def _insert_args(msg, args):
    for i in range(len(args)):
        msg = msg.replace('%' + str(i + 1), str(args[i]))

    return msg

def current_language():

    """
    Returns the language code for the language currently used by Konversation's
    user interface (e.g. en_US).

    """

    return os.environ['KONVERSATION_LANG']

def locale_directories():

    """
    Returns the list of directory paths searched for gettext .mo files, using
    KDE's normal lookup logic for this type of resource.

    """

    dirs = subprocess.Popen(('kde4-config', '--path', 'locale'),
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE).communicate()

    return dirs[0].rstrip().decode().split(':')
