{ "info": { "author": "Michael Elsdoerfer", "author_email": "michael@elsdoerfer.com", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Topic :: Software Development :: Localization" ], "description": "android2po\n==========\n\n.. image:: https://travis-ci.org/miracle2k/android2po.svg?branch=master\n :target: https://travis-ci.org/miracle2k/android2po\n\n.. image:: https://coveralls.io/repos/miracle2k/android2po/badge.svg?branch=master&service=github\n :target: https://coveralls.io/github/miracle2k/android2po?branch=master\n\nConvert Android string resources to gettext .po files, and import them\nright back.\n\nThe goal is to remove as many syntax elements required by the Android\nstring resource files when exporting, to present the text to translators\nin as easy a format as possible; and correctly writing everything back\nto Android on import while keeping the generated XML files easily\nreadable as well (i.e. no unnecessary escaping).\n\n\nRequirements\n------------\n\nThe following Python modules are required, and will mostly be\nauto-installed. See ``Installation`` below.\n\nbabel\n http://babel.pocoo.org/\n\nlxml\n http://codespeak.net/lxml/\n\nargparse\n http://argparse.googlecode.com/\n\nSince the .po files this script generates use contexts (``msgctx``),\nthat's what you're gettext software will have to support as well.\n\n\nInstallation\n------------\n\nTo install the current release, you can simply do:\n\n $ easy_install android2po\n\nThat's it!\n\nIf you want to install the current development version of\n``android2po`` instead, get the source code, then run:\n\n $ python setup.py install\n\n``setup.py`` should automatically install all the dependencies.\nAlternatively, you can also use pip if you prefer:\n\n $ pip install -r requirements.pip\n\nUsage\n~~~~~\n\nThe basic idea is that:\n\n* ``values/strings.xml`` holds the reference strings in their\n original language (the gettext ``msgid`` fields).\n\n* The gettext .po files generated and updated by this script contain\n the reference version of the translations.\n\n* The ``values-XX/strings.xml`` files are fully generated based on\n your ``.po`` files, and should not be modified manually.\n\nIn addition to your authoritative strings.xml file, you will usually \nalso want to keep your .po files in source control; The generated \nlanguage-specific ``strings.xml`` files then contain no additional \ninformation, and do not need to be source controlled, though you are \nfree to if you like.\n\nThe environment\n~~~~~~~~~~~~~~~\n\nTo be able to run, the script necessarily needs to know about two\nfilesystem locations: The directory where your Android resources are\nlocated, and the directory where the gettext .po files should be stored:\n\n $ a2po COMMAND --android myproject/res --gettext myproject/locale\n\nHowever, to simplify usage, the program will automatically try to\ndetect the location of these folders, as follows:\n\n* It will search the directory hierarchy, starting with the your working\n directory, for a ``AndroidManifest.xml`` or ``.android2po`` file.\n* As soon as it finds either of those files, it will stop, and consider\n the it's location the **project directory**.\n* Unless explicitly overriden by you, it will place the .po files in\n a subdirectory ``./locale`` of that project directory.\n* Only if a ``AndroidManifest.xml`` file is in the project directory\n will it assume that the Android resources are located in a subfolder\n named ``./res``.\n* If a ``.android2po`` file is in the project directory, it automatically\n will be loaded as a configuration file. See the section below on the\n format of the configuration file, and possible values.\n* The script automatically processes all the languages it can find. It\n will normally look at the existing .po files to determine the list of\n languages, with the exception of the ``init`` command, in which case\n the list of languages inside the Android resource directory will be\n used.\n\nInitial setup\n~~~~~~~~~~~~~\n\nWhen switching to ``android2po``, you will first want to create an\ninitial export of your current translations.\n\n $ a2po init\n\nThis will ignore any languages for which a ``.po`` file already exists.\n\nFor testing purposes, you may want to immediately import the generated\nfiles back in, to compare with what you originally had, and make sure\nthe script was able to process your files correctly.\nAt this point, make sure you have a backup, since your language-specific\n``strings.xml`` files are going to be replaced (you are using source\ncontrol, right?!)::\n\n $ a2po import\n $ git diff --ignore-all-space res/values-XX/strings.xml\n\nIn the example above, ``git`` is used for source control. ``git``\nprovides a nice option to show a diff while ignoring whitespace\nchanges, which will make it much easier to spot problems with the\nimport. If you use a different tool, see if there is a comparable\nfeature.\n\nHopefully, your translated XML files at this point hold the same\ninformation as before. The whitespace will probably have changed,\ncomments will have been removed, and some strings may have changed\nvisually (i.e. use different escaping). However, their *meaning*\nshould not have changed. If it has, please report a bug.\n\nUpdating\n~~~~~~~~\n\nAfter hacking on your code for a while, you have changed some\nstrings (in your authoritative ``values/strings.xml`` file), and now\nyou need to pass those on to your translators through your .po files.\n\nSimply do:\n\n $ a2po export\n\nThis will update your ``.po files`` with your changes.\n\nImporting\n~~~~~~~~~\n\nYour translators have come back to you with their changes, and you\nwant to include them in the next build. Simply do:\n\n $ a2po import\n\nThis will fully regenerate your language-specific ``strings.xml``\nbased on the gettext ``.po`` files.\n\nYou can do this step manually, or add it to your build process.\n\nAdding a new language\n~~~~~~~~~~~~~~~~~~~~~\n\nAs noted above, ``android2po`` will automatically process all the\nlanguages it can find, based on the .po files that exist. To add a\nnew language, simply run\n\n $ a2po init {LANGUAGE CODES}\n\nFor example:\n\n $ a2po init de fr\n\nThis will create both new .po and strings.xml files for German and French.\n\nYou are also free to simply create the appropriate ``strings.xml`` files\nyourself, and let\n\n $ a2po init\n\ninitialize their proper .po counterparts (in case of the ``init`` command,\nthe languages found in the Android resource directory will be processed).\n\n\nConfiguration file\n~~~~~~~~~~~~~~~~~~\n\nA configuration file can be used to avoid manually specifying all the\nrequired options. The format of the file is simply a list of command\nline option, each specified on a line of it's own. For example::\n\n --no-template\n # Paths - don't specify --android, default location is used.\n --gettext ../locale\n\nAs you can see, comments are supported by using ``#``, and the mechanism\nto automatically try to detect the directories for .po files and Android\n``strings.xml`` files is still in place if you don't specify locations\nexplicitly.\n\nThe configuration file may be specified by using the ``--config`` option.\nAlternatively, if a ``.android2po`` file is found in the project directory,\nit will be used.\n\nSee ``--help`` for a list of possible configuration options. There's also\nan example configuration file in ``example.config`` that you can have a\nlook at, or use as a template for your own.\n\n\nPlurals support\n~~~~~~~~~~~~~~~\n\n```` are supported, but merit some additional explanation.\n\nAndroid's plural support is based on CLDR_ keywords like ``\"one\"`` and\n``\"many\"``. The rules specifying which quantity ``n`` maps to which keyword\nare built into Android itself, by way of the CLDR database. It is important to\nunderstand that a keyword like \"one\" may be used for quantities other then\n``1``.\n\nIn the gettext system, on the other hand, each catalog has the ability to\ndefine the plural rules it wants to use itself, via an expression like\n``nplurals=2; plural=((n == 1) ? 0 : 1)``. The expression returns the index\nof the string to use for the quantity ``n``.\n\nandroid2po converts between those two system in the following way:\n\n* When writing .po files, it will generate a plural rule expression like\n above based on the CLDR data, custom-fit for the language in question.\n The result is a .po file that defines as many plural forms as required\n for the language, and your translation tool will ask for a different\n string for each plural form.\n\n* During import, it will generate a ```` tag with the correct quantity\n keywords based on it's knowledge (CLDR) about which such keywords the\n language supports.\n\n* The ``init`` command, having to convert existing ```` tags to\n gettext, will pick those quantity keywords the language supports, and ignore\n others (and display a warning in those cases).\n\n* The ``export`` command will ensure that the catalog uses the correct plural\n definition, but it otherwise does not have to deal with individual plural\n forms / quantities.\n\nIf this is confusing, consider the issue: Android lets you define a number\nof different quantity keywords for each ```` element, but ignores all\nkeywords that are not supported by the language (see `this erroneous bug\nreport `_).\ngettext only allows you to define a fixed number of plural rules, as many\nas the language purports to require via the catalog's plural rule expression.\n\nTo cleanly convert between the two systems, we are forced to ignore keywords\nin an Android XML resource that are really not supported - but only if Android\nitself would also ignore them. So view this as essentially a validation\nfeature.\n\nA final note: plurals can be complex (and there are many languages) and the\nCLDR database is regularly updated. In French, whether 0 is treated as plural\nor singular possibly even `depends on the dialect\n`_. As\nsuch, you may find that different plural rules for the same languages are in\nuse in the wild. ``android2po`` uses the CLDR rules, but not necessarily the\nsame version as Android does, and Android presumably will upgrade their CLDR\nversion over time as well. I think the goal here would be to always make\n``android2po`` use a reasonably recent version of the CLDR data, and accept\nthat old Android versions with outdated plural information might not be able\nto correctly internationalize some plural strings into into those languages\nwhere the data is incorrect.\n\nFurther reading:\n\nThe CLDR plural system and rules\n http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html\n http://cldr.unicode.org/index/cldr-spec/plural-rules\n\nPlural information about various languages:\n http://translate.sourceforge.net/wiki/l10n/pluralforms\n https://translations.launchpad.net/+languages\n https://developer.mozilla.org/en/Localization_and_Plurals\n\n.. _CLDR: http://cldr.unicode.org/index/cldr-spec/plural-rules\n\n\n\nUnderstanding / Debugging the android2po\n----------------------------------------\n\nIf something doesn't work as expected, it may be helpful to understand\nwhich files are processed how and when:\n\nOn ``init``, ``android2po`` will take your language-neutral (English)\n``values/strings.xml`` file and convert it to a .pot template.\n\nFurther on ``init``, if there are existing ``values-{lang}/strings.xml`` files,\nit will take the strings from there, match them with the strings in the\nlanguage-neutral ``values/strings.xml`` file, and generate .po files for these\nlanguages which already contain translations, in addition to the template.\nThis is the **only** time that the ``values-{lang}/strings.xml`` files will\nbe looked at and considered.\n\nOn ``export``, ``android2po`` will take the language-neutral\n``values/strings.xml`` file, generate a new .pot template, and then merge the\nnew template into any existing .po catalogs, i.e. update the .po catalogs for\neach language with the changes. This is how gettext normally works\n(``msgmerge``). The ``values-{lang}/strings.xml`` files do not play a role here.\n\nOn 'import', ``android2po`` will only look at the .po catalogs for each\nlanguage and generate ``values-{lang}/strings.xml`` files, without looking at\nanything else.\n\n\n\nNotes\n-----\n\nInitially based on:\n http://code.google.com/p/openintents/source/browse/tools/Androidxml2po/androidxml2po.bash\n\n\nLinks of interest:\n~~~~~~~~~~~~~~~~~~\n\nhttp://www.gnu.org/software/hello/manual/gettext/PO-Files.html\n GNU PO file format docs.\n\nhttp://docs.oasis-open.org/xliff/v1.2/xliff-profile-po/xliff-profile-po-1.2.html\n Explains the gettext format according to how xliff interprets it.\n\nhttp://www.artfulbits.com/Android/aiLocalizer.aspx\n App to localize Android xml string files directly. They seems to be\n involved with the Ukrainian translation of Android itself.\n\nhttp://groups.google.com/group/android-platform/browse_thread/thread/a2626195205e8543\n Notes that Google internally manages Android translations in their\n own system.\n\n There is a converter from and to XLIFF in ``frameworks/base/tools/localize``,\n which might be what they are using. It looks pretty decent too. Why\n isn't this promoted more?\n\nhttps://launchpad.net/intltool\n Converts to and from .po und \"can be extended to support other types\n of XML\" - sounds like something we could've used? It's Perl though,\n ugh.\n", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/miracle2k/android2po", "keywords": null, "license": "BSD", "maintainer": null, "maintainer_email": null, "name": "android2po", "package_url": "https://pypi.org/project/android2po/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/android2po/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/miracle2k/android2po" }, "release_url": "https://pypi.org/project/android2po/1.5.0/", "requires_dist": null, "requires_python": null, "summary": "Convert between Android string resources and gettext .po files.", "version": "1.5.0" }, "last_serial": 1904312, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "a1dccc1608da13100d82c2bae8d35eb3", "sha256": "0e2e72cdce278eead86d396d0124a6690355f875d552fa8230e3535234292e86" }, "downloads": -1, "filename": "android2po-1.0.zip", "has_sig": false, "md5_digest": "a1dccc1608da13100d82c2bae8d35eb3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21786, "upload_time": "2009-12-04T17:09:40", "url": "https://files.pythonhosted.org/packages/16/cc/3a74e903c6421a09d7999f286faa2c19303c13a03e21a92db61f53972f57/android2po-1.0.zip" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "3a2f889a7ec9c635dfd69e27c6a83886", "sha256": "b8d3ceb921942b0ca3868dbc045e711869902801478734131615fc40c6e26d2a" }, "downloads": -1, "filename": "android2po-1.0.1.zip", "has_sig": false, "md5_digest": "3a2f889a7ec9c635dfd69e27c6a83886", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24567, "upload_time": "2009-12-04T17:51:09", "url": "https://files.pythonhosted.org/packages/15/f4/17a6b07b70a15a1ccf3464caa39419ee8d476fbba3b188c2b5d2c4fb8f40/android2po-1.0.1.zip" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "daac1acdd5c28c331f8dc28860b0c8fa", "sha256": "0218cb4e65dbf1edf84aaf3731fe4511721da7ce5d8a6e2c6507fb85f7e286b4" }, "downloads": -1, "filename": "android2po-1.1.0.tar.gz", "has_sig": false, "md5_digest": "daac1acdd5c28c331f8dc28860b0c8fa", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 53728, "upload_time": "2010-04-07T23:50:07", "url": "https://files.pythonhosted.org/packages/48/48/f9360cbec3223ceb1dd9addff96746a456c54f7fd7f710c9a1e816a85a0f/android2po-1.1.0.tar.gz" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "794c3470d2dbe7622313f1272ac5ff7f", "sha256": "c66addc44cd1e6c573633beefa5247184c2bb374242c3fb886a90798014e99d5" }, "downloads": -1, "filename": "android2po-1.2.0.tar.gz", "has_sig": false, "md5_digest": "794c3470d2dbe7622313f1272ac5ff7f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 80164, "upload_time": "2012-03-18T12:28:14", "url": "https://files.pythonhosted.org/packages/9f/cc/9bf9a47ed5780ab7583da591f1344eb882526d16aea8f670c61ed12e3f7d/android2po-1.2.0.tar.gz" } ], "1.5.0": [ { "comment_text": "", "digests": { "md5": "f7afde781da3f04f3d204f929852d6b7", "sha256": "efa3ded826fa2634fe6479eaacb4766f0329c0619c1d2c176741fc6ad8b38664" }, "downloads": -1, "filename": "android2po-1.5.0.tar.gz", "has_sig": false, "md5_digest": "f7afde781da3f04f3d204f929852d6b7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 58015, "upload_time": "2016-01-14T13:57:05", "url": "https://files.pythonhosted.org/packages/44/da/62cd8da2db3e01ec7de88fdb54270c90fddc194db7e5001f51174c15689c/android2po-1.5.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "f7afde781da3f04f3d204f929852d6b7", "sha256": "efa3ded826fa2634fe6479eaacb4766f0329c0619c1d2c176741fc6ad8b38664" }, "downloads": -1, "filename": "android2po-1.5.0.tar.gz", "has_sig": false, "md5_digest": "f7afde781da3f04f3d204f929852d6b7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 58015, "upload_time": "2016-01-14T13:57:05", "url": "https://files.pythonhosted.org/packages/44/da/62cd8da2db3e01ec7de88fdb54270c90fddc194db7e5001f51174c15689c/android2po-1.5.0.tar.gz" } ] }