Add new android strings format

Julien LepillerSat Nov 09 11:43:00+0100 2019

a164c3e

Add new android strings format

guix.scm

179179
    (description "Interact with GitLab API")
180180
    (license license:lgpl3+)))
181181
182+
(define-public python-android-stringslib
183+
  (package
184+
    (name "python-android-stringslib")
185+
    (version "0.1.1.1")
186+
    (source
187+
      (origin
188+
        (method git-fetch)
189+
        (uri (git-reference
190+
	       (url "https://framagit.org/tyreunom/python-android-strings-lib")
191+
	       (commit "0415535b125a64eb6da20a6b15ad92456e73ca8d")))
192+
	(file-name (git-file-name name version))
193+
        (sha256
194+
          (base32
195+
            "0icalva7a5w8a6qcrgkxkywckdqv8r5j5y9d5m6ln8bbk9s9fbls"))))
196+
    (build-system python-build-system)
197+
    (arguments
198+
     `(#:tests? #f))
199+
    (home-page
200+
      "https://framagit.org/tyreunom/python-android-strings-lib")
201+
    (synopsis
202+
      "Android Strings Lib provides support for android's strings.xml files.  These files are used to translate strings in android apps.")
203+
    (description
204+
      "Android Strings Lib provides support for android's strings.xml files.  These files are used to translate strings in android apps.")
205+
    (license license:expat)))
206+
182207
(define-public python-altgraph
183208
  (package
184209
    (name "python-altgraph")

241266
   ;; No tests
242267
   `(#:tests? #f))
243268
  (propagated-inputs
244-
    `(("python-dateutil" ,python-dateutil)
269+
    `(("python-android-stringslib" ,python-android-stringslib)
270+
      ("python-dateutil" ,python-dateutil)
245271
      ("python-gitlab" ,python-gitlab)
246272
      ("python-lxml" ,python-lxml)
247273
      ("python-polib" ,python-polib)

offlate/formats/androidstrings.py unknown status 1

1+
#   Copyright (c) 2019 Julien Lepiller <julien@lepiller.eu>
2+
#
3+
#   This program is free software: you can redistribute it and/or modify
4+
#   it under the terms of the GNU Affero General Public License as
5+
#   published by the Free Software Foundation, either version 3 of the
6+
#   License, or (at your option) any later version.
7+
#
8+
#   This program is distributed in the hope that it will be useful,
9+
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11+
#   GNU Affero General Public License for more details.
12+
#
13+
#   You should have received a copy of the GNU Affero General Public License
14+
#   along with this program.  If not, see <https://www.gnu.org/licenses/>.
15+
####
16+
""" The strings.xml format for Android translations. """
17+
18+
import androidstringslib
19+
import os
20+
from pathlib import Path
21+
22+
from .entry import AndroidStringsEntry
23+
24+
class AndroidStringsFormat:
25+
    def __init__(self, conf):
26+
        self.translationfilename = conf["file"]
27+
        self.enfilename = conf["template"]
28+
        if not os.path.isfile(self.translationfilename):
29+
            # Create an empty initial file if none exists yet
30+
            Path(self.translationfilename).parent.mkdir(parents=True, exist_ok=True)
31+
            with open(self.translationfilename, 'w') as f:
32+
                f.write('<resource></resource>')
33+
        self.translation = androidstringslib.android(conf["template"], conf["file"])
34+
        self.conf = conf
35+
36+
    def content(self):
37+
        aresources = []
38+
        for entry in self.translation:
39+
            if entry.type == 'string-array':
40+
                index = 0
41+
                for item in entry.orig:
42+
                    aresources.append(
43+
                            AndroidStringsEntry(
44+
                                androidstringslib.parser.entry(
45+
                                    'string', entry.id + ':' + index, entry.orig[index], entry.dst[index]),
46+
                                entry, index))
47+
                    index += 1
48+
            else:
49+
                aresources.append(AndroidStringsEntry(entry))
50+
        return aresources
51+
52+
    def save(self):
53+
        self.translation.save()
54+
55+
    def merge(self, older, callback):
56+
        for entry in self.translation:
57+
            key = entry.id
58+
            envalue = entry.orig
59+
            ntranslated = entry.dst
60+
            oentry = older.translation.getValuesById(key)
61+
            oenvalue = oentry[0]
62+
            otranslated = oentry[1]
63+
            if otranslated == ntranslated:
64+
                continue
65+
            if otranslated == "":
66+
                continue
67+
            if ntranslated == "":
68+
                entry.dst = otranslated
69+
                continue
70+
            # otherwise, ntranslated and otranslated have a different value
71+
            entry.dst = callback(envalue, otranslated, ntranslated)
72+
        self.translation.save()
73+

offlate/formats/entry.py

1-
#   Copyright (c) 2018 Julien Lepiller <julien@lepiller.eu>
1+
#   Copyright (c) 2018, 2019 Julien Lepiller <julien@lepiller.eu>
22
#
33
#   This program is free software: you can redistribute it and/or modify
44
#   it under the terms of the GNU Affero General Public License as

6060
        else:
6161
            self.entry.msgstr = content
6262
63+
class AndroidStringsEntry(Entry):
64+
    def __init__(self, entry, parent=None, index=None):
65+
        if entry.type == 'string':
66+
            msgids = [entry.orig]
67+
            msgstrs = [entry.dst]
68+
        elif entry.type == 'plurals':
69+
            msgid = entry.orig
70+
            msgstrs = entry.dst
71+
        Entry.__init__(self, msgids, msgstrs, False, False)
72+
        self.entry = entry
73+
        self.parent = parent
74+
        self.index = index
75+
76+
    def update(self, index, content):
77+
        Entry.update(self, index, content)
78+
        self.fuzzy = False
79+
        if self.entry.type == 'plurals':
80+
            self.entry.dst[index] = content
81+
        else:
82+
            self.entry.dst = content
83+
            if self.parent is not None:
84+
                self.parent.dst[self.index] = content
85+
6386
class JSONEntry(Entry):
6487
    def __init__(self, entry):
6588
        Entry.__init__(self, [entry['source_string']], [entry['translation']], False, False)

offlate/systems/git.py

1-
#   Copyright (c) 2018 Julien Lepiller <julien@lepiller.eu>
1+
#   Copyright (c) 2018, 2019 Julien Lepiller <julien@lepiller.eu>
22
#
33
#   This program is free software: you can redistribute it and/or modify
44
#   it under the terms of the GNU Affero General Public License as

2323
from ..formats.gettext import GettextFormat
2424
from ..formats.ts import TSFormat
2525
from ..formats.yaml import YamlFormat
26+
from ..formats.androidstrings import AndroidStringsFormat
2627
from ..formats.formatException import UnsupportedFormatException
2728
from .systemException import ProjectNotFoundSystemException
2829

103104
                    template = Path(path).glob(resource['filemask'])[0]
104105
                translationfiles.append({'filename': yamlpath,
105106
                    'format': TSFormat({'file': path + yamlpath, 'lang': self.lang, 'template': template})})
107+
            elif resource['file_format'] == 'aresource':
108+
                translationpath = resource['filemask'].replace('*', self.lang)
109+
                enpath = resource['template']
110+
                translationfiles.append({'filename': translationpath,
111+
                    'format': AndroidStringsFormat({'file': path + translationpath, 'lang': self.lang,
112+
                                                    'template': path + enpath})})
106113
            else:
107114
                raise UnsupportedFormatException(resource['file_format'])
108115
        return translationfiles

setup.py

1313
    packages=find_packages(exclude=['.guix-profile*']),
1414
    python_requires = '>=3',
1515
    install_requires=['polib', 'ruamel.yaml', 'python-dateutil', 'PyQt5', 'pygit2',
16-
        'python-gitlab', 'translation-finder'],
16+
        'python-gitlab', 'translation-finder', 'android-stringslib'],
1717
    entry_points={
1818
        'gui_scripts': [
1919
            'offlate=offlate.ui.main:main',