{"id":16199944,"url":"https://github.com/agateau/linguaj","last_synced_at":"2025-03-19T05:30:53.461Z","repository":{"id":15221606,"uuid":"17950181","full_name":"agateau/linguaj","owner":"agateau","description":"Simple way to use gettext to translate user visible strings from Java code","archived":false,"fork":false,"pushed_at":"2023-05-08T10:18:51.000Z","size":78,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-17T04:21:17.549Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/agateau.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-03-20T16:40:13.000Z","updated_at":"2023-04-16T14:25:24.000Z","dependencies_parsed_at":"2024-10-27T20:18:36.578Z","dependency_job_id":"2581bd0c-a8c2-4933-be53-86251d7cb8d7","html_url":"https://github.com/agateau/linguaj","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agateau%2Flinguaj","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agateau%2Flinguaj/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agateau%2Flinguaj/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agateau%2Flinguaj/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/agateau","download_url":"https://codeload.github.com/agateau/linguaj/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244364703,"owners_count":20441458,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-10T09:28:47.368Z","updated_at":"2025-03-19T05:30:53.118Z","avatar_url":"https://github.com/agateau.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"Linguaj\n=======\n\nLinguaj provides a simple way to use [gettext][] to translate user visible\nstrings in Java code.\n\n[gettext]: http://www.gnu.org/software/gettext/\n\n## License\n\nLinguaj is licensed under the Apache v2.0 license.\n\n## How It Works\n\nLinguaj makes use of gettext string extraction tool (xgettext) and gettext .po\nfile format, but does not use gettext Java support. Instead it provides a tool\nnamed po-compile to turn .po files into .java files, which can then be used with\nthe provided Translator Java class.\n\n## Dependencies\n\nYou need to have gettext installed, or at least access to the xgettext tool.\n\nOne of Linguaj components (scripts/po-compile) is written in Python and requires\nthe [jinja2][] and [polib][] modules. Those can be installed with:\n\n    pip install -r requirements.txt\n\nIf you are running Linux, they should be available as packages as well.\n\n[jinja2]: http://jinja.pocoo.org/docs/\n[polib]: http://polib.readthedocs.org/en/latest/index.html\n\n## Using Linguaj in Your Code\n\n### Build With Linguaj\n\nEither create a `./gradlew build`, or add a reference in your project to the\n`:linguaj` folder from this repository.\n\n### Mark Your Text as Translatable\n\nAdd this import line to each Java class which contains text to be translated:\n\n    import static com.greenyetilab.linguaj.Translator.tr;\n\nThen wrap translatable text in `tr()` calls. This line:\n\n    System.out.println(\"Hello\");\n\nBecomes:\n\n    System.out.println(tr(\"Hello\"));\n\n### Extract Translatable Texts\n\nGettext provides the xgettext tool to extract translatable texts from the source\ncode. To get it to work with Linguaj, invoke it like this:\n\n    xgettext --keyword=tr --keyword=trn:1,2 -o po/messages.pot *.java\n\nThis will go through all .java files in the current folder and create a file\nnamed messages.pot in the po folder. The messages.pot file is a \"message\ntemplate\". It is a text file which contains all the translatable texts.\n\n### Translate Texts\n\nCreate a .po for your language. For example to translate your texts to French,\neither copy messages.pot to fr.po and adjust the header fields, or run:\n\n    msginit -i messages.pot -l fr -o fr.po\n\nYou can now translate strings in fr.po, using either your text editor or,\npreferably, a tool such as [poedit][] or [lokalize][].\n\n[poedit]: http://poedit.net/\n[lokalize]: http://userbase.kde.org/Lokalize\n\n### Compile Texts\n\nOnce your .po files are ready, compile them into .java files using the scripts\nin the scripts/ folder. The easiest way is to run:\n\n    scripts/po-compile-all \u003cpath/to/po/dir\u003e \u003cwhere/to/generate/java/files\u003e\n\nMake sure the folder where the generated .java files is in the class path. Now\nrun your code again, your texts should be translated.\n\n### Plural Handling\n\nOne of the benefits of gettext is advanced plural handling. To translate a\nplural string, use trn() instead of tr(). It works like this:\n\n    import static com.greenyetilab.linguaj.Translator.trn;\n\n    ...\n\n    class Backup {\n        ...\n        void work(String[] files) {\n            ...\n            System.out.println(trn(\"%# file saved\", \"%# files saved\", files.length));\n        }\n    }\n\nThe syntax is `trn(\"singular form\", \"plural form\", number)`. Depending on the\nvalue of number and of the current locale, trn() will return the appropriate\nstring. All occurrences of \"%#\" in the string will be replaced with `number`.\n\nThis is much better than using code like that:\n\n    if (files.length == 1) {\n        System.out.println(tr(\"1 file saved\"));\n    } else {\n        System.out.println(tr(\"%d files saved\", files.length));\n    }\n\nBecause that code fails for languages with different grammar rules for plural.\nFor example French does not use an 's' when `number` is 0, Polish uses one\nplural form when `number` is between 2 and 4, and another form when it is\nbetween 5 and 9.\n\nLinguaj comes with an example which demonstrates these different plural forms.\nYou can try it by running `ant example-run`.\n\n### String Formatting\n\nLinguaj API supports string formatting, based on String.format(). This means\nthat instead of writing this:\n\n    String msg = String.format(tr(\"Hello %s, how are you?\"), name);\n\nYou can write:\n\n    String msg = tr(\"Hello %s, how are you?\", name);\n\nThis works with trn() as well.\n\n### Switching Languages\n\nBy default, Linguaj will load the most appropriate translation based on the\ncurrent locale, but you can force it to use a different locale by calling\n`init()` with an argument, like this:\n\n    import com.greenyetilab.linguaj.Translator;\n    ...\n\n    // Let's speak French\n    Translator.init(\"fr\");\n    ...\n\n    // Now switch to Brazilian Portuguese. If there is no Brazilian Portuguese\n    // translation available, Linguaj falls back to Portuguese.\n    Translator.init(\"pt_BR\");\n\n## Why Linguaj?\n\nWhen I realized I needed translations for my [Burger Party][bp] Android game, I\nlooked at existing solutions for Java. I was not happy with the Java way of\nusing string constants: I find it nicer to work with English sentences than with\nstring constants. I also wanted to have good plural support, something which I\nknow is tricky.\n\nHaving past experience with gettext, I looked into using it. gettext is a\nwidespread, robust tool. There are many tools to work with it. I saw it had\nJava support so I started using it, but bumped into a legal issue.\n\nJava code can make use of gettext plural support, but to do so one has to use\nthe libintl.jar library provided by gettext. This is where the issue appears:\nthe code for libintl.jar is licensed under LGPL 2.1 or later. It is not clear\nwhether it is legal to use LGPL code in a proprietary .apk file, because the\n.jar is not shipped as is in the .apk: it must be converted to work on the\nAndroid VM (Dalvik), which does not use the same byte-code as the JVM.\n\nI am quite confident that the spirit of the LGPL would allow LGPL code to be\nused in a proprietary .apk, but I don't want to take a decision in the field of\nlicensing based on gut feeling. I reached out to the gettext maintainers, who\nredirected me to the FSF lawyers, but the FSF lawyers ask for a $150 fee to\nanswer any question which implies proprietary software. I am not even sure I am\ngoing to make that much money with my game, so I'd rather use Linguaj API for\nnow. Linguaj is licensed under the Apache 2.0 license so it does not have that\nproblem.\n\n## Users\n\nAs I mentioned above, I am using Linguaj in Burger Party. It would be great to\nhear from you if you use Linguaj in your projects!\n\n[bp]: http://greenyetilab.com/burgerparty\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagateau%2Flinguaj","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fagateau%2Flinguaj","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagateau%2Flinguaj/lists"}