From 67209fe344e71badfe2d37145ebdca6ed6fb2adf Mon Sep 17 00:00:00 2001 From: Antoine Choppin Date: Thu, 2 Jun 2016 00:20:19 +0900 Subject: [PATCH 01/10] Initial i18n support --- .gitignore | 2 + TRANSLATION.md | 60 +++++++++++++ debian/control | 4 +- debian/rules | 1 + kano_apps/AppGrid.py | 46 +++++----- kano_apps/AppInstaller.py | 28 +++--- kano_apps/AppManage.py | 8 +- kano_apps/MainWindow.py | 12 +-- kano_apps/UIElements.py | 10 +-- po/Makefile | 36 ++++++++ po/PYPOTFILES | 6 ++ po/ja.po | 173 ++++++++++++++++++++++++++++++++++++++ 12 files changed, 332 insertions(+), 54 deletions(-) create mode 100644 TRANSLATION.md create mode 100644 po/Makefile create mode 100644 po/PYPOTFILES create mode 100644 po/ja.po diff --git a/.gitignore b/.gitignore index 30a71a4..2341819 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ *.swp *.swo .* +*.mo +po/messages.pot diff --git a/TRANSLATION.md b/TRANSLATION.md new file mode 100644 index 0000000..064c10f --- /dev/null +++ b/TRANSLATION.md @@ -0,0 +1,60 @@ +# Translation + +Translation files are found in the `po/` directory. + +## i18n not released yet + +Kano OS is not fully i18n-aware and locales are not installed for end users, yet. You can translate this application, but as of now, users will still see the default English message strings. + +## How to add a new translation + +In this example, we're going to add a French translation: + + # install your target locale `fr_FR.utf8` with: + sudo dpkg-reconfigure locales + + cd po/ + # create messages.pot + make messages + + # create fr.po from messages.pot: + msginit -l fr_FR.utf8 + + # now use your favourite editor to translate fr.po + + # build locale files: + make + + cd .. + + # run test + +## How to make sure your code is i18n-aware + +Add the gettext `_()` macro to all the user-visible message strings in your Python. List the Python source files that contain message strings in `PYPOTFILES`. + +If you added new message strings or made changes to existing ones, do `make messages` to keep the template file up-to-date. + +After that, merge the existing translations with `make update` and ask your translators to update their translations. + +## gettext explained (in 20 seconds) + +* User-visible strings in the source are marked with a macro of your choice. Usually, it's `_()`. +* `xgettext` extracts these message strings from your sources and puts them into a template file. +* This template file, usually named `messages.pot`, contains all user-visible strings of the project, but no translations. +* Translators use `msginit` to copy the template file into a new *portable object* file for their language (explained above). +* The translations are put into `.po`. It's a plain-text file format, you can use any text editor. +* More convenient, specialized `.po`-editors and web-based tools such as Pootle exist, as well. +* If your template file changes, use `msgmerge` to merge your existing translations with the new template, then re-translate the updated messages. Beware of `msgmerge`'s "fuzzy" matches. +* `msgfmt` converts a `.po` file into a binary *message object* file. +* You don't link these `.mo` files with your application binary. +* The `.mo` files are bundled alongside with your software as part of the distribution package. +* During installation, the `.mo` files are copied into the system's locale directory, usually `/usr/share/locale`. +* On startup, your application will look for the message object file that it needs for the current system locale. +* The locale even allows you to provide region-specific translations, e.g. "colour" for en_UK vs "color" for en_US. +* At runtime, all user-visible strings are being replaced with the translations. +* If no message object was found for the system locale, the original strings will be shown. + +## To-Do + +Pootle or Transifex integration. diff --git a/debian/control b/debian/control index 6c8cbac..c4d1f00 100644 --- a/debian/control +++ b/debian/control @@ -3,12 +3,12 @@ Maintainer: Team Kano Section: misc Priority: optional Standards-Version: 3.9.4 -Build-Depends: debhelper (>=9.0.0), python +Build-Depends: debhelper (>=9.0.0), python, gettext Package: kano-apps Architecture: all Depends: ${misc:Depends}, python, python-gi, kano-toolset (>= 1.2-5), - kano-themes, kano-profile (>=1.3-6) + kano-themes, kano-profile (>=1.3-6), kano-i18n Replaces: kano-desktop (<< 1.0-60) Breaks: kano-desktop (<< 1.0-60) Conflicts: kano-extras diff --git a/debian/rules b/debian/rules index 4647c9c..8bf5e42 100755 --- a/debian/rules +++ b/debian/rules @@ -1,4 +1,5 @@ #!/usr/bin/make -f %: + cd po && make dh $@ --with python2 diff --git a/kano_apps/AppGrid.py b/kano_apps/AppGrid.py index c3cb7f5..26268f9 100644 --- a/kano_apps/AppGrid.py +++ b/kano_apps/AppGrid.py @@ -1,6 +1,6 @@ # AppGrid.py # -# Copyright (C) 2014 Kano Computing Ltd. +# Copyright (C) 2014-2016 Kano Computing Ltd. # License: http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2 # @@ -29,8 +29,8 @@ def __init__(self, apps, main_win): want_more_app = { "type": "app", - "title": "Want more apps?", - "tagline": "Go to Kano World to install more", + "title": _("Want more apps?"), + "tagline": _("Go to Kano World to install more"), "slug": "want-more", "origin": "-", @@ -244,10 +244,10 @@ def refresh(self): if self._is_on_desktop(): self.set_image(Gtk.Image.new_from_file(self._RM_IMG_PATH)) - self.set_tooltip_text("Remove from desktop") + self.set_tooltip_text(_("Remove from desktop")) else: self.set_image(Gtk.Image.new_from_file(self._ADD_IMG_PATH)) - self.set_tooltip_text("Add to desktop") + self.set_tooltip_text(_("Add to desktop")) self.show_all() @@ -415,10 +415,10 @@ def _launch_app(self, cmd, args): # The execvp should not return, so if we reach this point, # there was an error. message = KanoDialog( - "Error", - "Unable to start the application.", + _("Error"), + _("Unable to start the application."), { - "OK": { + _("OK"): { "return_value": 0, "color": "red" } @@ -437,7 +437,7 @@ def _setup_desc_button(self): more_btn.props.margin_right = 21 more_btn.get_style_context().add_class('more-button') more_btn.connect("clicked", self._show_more_cb) - more_btn.set_tooltip_text("More information") + more_btn.set_tooltip_text(_("More information")) more_btn.connect("realize", self._set_cursor_to_hand_cb) self._entry.pack_start(more_btn, False, False, 0) @@ -459,7 +459,7 @@ def _setup_remove_button(self): remove_btn.props.margin_right = 21 remove_btn.get_style_context().add_class('more-button') remove_btn.connect("clicked", self._uninstall_cb) - remove_btn.set_tooltip_text("Remove") + remove_btn.set_tooltip_text(_("Remove")) remove_btn.connect("realize", self._set_cursor_to_hand_cb) remove_btn.connect("enter-notify-event", self._open_bin_cb) remove_btn.connect("leave-notify-event", self._close_bin_cb) @@ -490,7 +490,7 @@ def _setup_update_button(self): update_btn.props.margin_right = 21 update_btn.get_style_context().add_class('more-button') update_btn.connect("clicked", self._update_cb) - update_btn.set_tooltip_text("Update app") + update_btn.set_tooltip_text(_("Update app")) update_btn.connect("realize", self._set_cursor_to_hand_cb) self._entry.pack_start(update_btn, False, False, 0) self._entry.reorder_child(update_btn, 2) @@ -509,7 +509,7 @@ def _show_more_cb(self, widget): self._app["title"], self._app['description'] if "description" in self._app else self._app['tagline'], { - "OK, GOT IT": { + _("OK, GOT IT"): { "return_value": 0, "color": "green" } @@ -532,14 +532,14 @@ def _entry_click_cb(self, ebox, event): def _uninstall_cb(self, event): confirmation = KanoDialog( - title_text="Removing {}".format(self._app["title"]), - description_text="This application will be uninstalled and " + - "removed from apps. Do you wish to proceed?", + title_text=_("Removing {}").format(self._app["title"]), + description_text=_("This application will be uninstalled and " + + "removed from apps. Do you wish to proceed?"), button_dict={ - "YES": { + _("YES"): { "return_value": 0 }, - "NO": { + _("NO"): { "return_value": -1, "color": "red" } @@ -553,7 +553,7 @@ def _uninstall_cb(self, event): if rv < 0: return - prompt = "Uninstalling {}".format(self._app["title"]) + prompt = _("Uninstalling {}").format(self._app["title"]) pw = get_sudo_password(prompt, self._window) if pw is None: return @@ -578,14 +578,14 @@ def _install_cb(self): def _update_cb(self, widget): confirmation = KanoDialog( - title_text="Updating {}".format(self._app["title"]), - description_text="This application will be updated " + - "Do you wish to proceed?", + title_text=_("Updating {}").format(self._app["title"]), + description_text=_("This application will be updated " + + "Do you wish to proceed?"), button_dict={ - "YES": { + _("YES"): { "return_value": 0 }, - "NO": { + _("NO"): { "return_value": -1, "color": "red" } diff --git a/kano_apps/AppInstaller.py b/kano_apps/AppInstaller.py index 74faa12..22b2c25 100644 --- a/kano_apps/AppInstaller.py +++ b/kano_apps/AppInstaller.py @@ -91,11 +91,11 @@ def _download_app(self): self._tmp_data_file = app_data_file self._tmp_icon_file = app_icon_file except AppDownloadError as err: - head = "Unable to download the application" + head = _("Unable to download the application") dialog = KanoDialog( head, str(err), { - "OK": { + _("OK"): { "return_value": 0 }, }, @@ -111,15 +111,15 @@ def _download_app(self): def _installed_check(self): if is_app_installed(self._app): - head = "{} is already installed".format(self._app["title"]) - desc = "Would you like to update it?" + head = _("{} is already installed").format(self._app["title"]) + desc = _("Would you like to update it?") dialog = KanoDialog( head, desc, { - "YES": { + _("YES"): { "return_value": 0 }, - "NO": { + _("NO"): { "return_value": -1 } }, @@ -137,7 +137,7 @@ def _installed_check(self): def _get_sudo_pw(self): if self._pw is None: - self._pw = get_sudo_password("Installing {}".format(self._app["title"])) + self._pw = get_sudo_password(_("Installing {}").format(self._app["title"])) return self._pw is not None return True @@ -160,21 +160,21 @@ def _install(self): if not self._icon_only and self._add_to_desktop: add_to_desktop(self._app) - head = "Done!" - message = self._app["title"] + " installed successfully! " + \ - "Look for it in the Apps launcher." + head = _("Done!") + message = _("%s installed successfully! " + \ + "Look for it in the Apps launcher.") % self._app["title"] else: - head = "Installation failed" - message = self._app["title"] + " cannot be installed at " + \ + head = _("Installation failed") + message = _("%s cannot be installed at " + \ "the moment. Please make sure your kit is connected " + \ "to the internet and there is enough space left on " + \ - "your card." + "your card.") % self._app["title"] dialog = KanoDialog( head, message, { - "OK": { + _("OK"): { "return_value": 0 }, }, diff --git a/kano_apps/AppManage.py b/kano_apps/AppManage.py index 2f624ca..985acdd 100644 --- a/kano_apps/AppManage.py +++ b/kano_apps/AppManage.py @@ -67,7 +67,7 @@ def uninstall_packages(app, sudo_pwd=None): pkgs = " ".join(app["packages"]) - cmd = "rxvt -title 'Uninstalling {}' -e bash -c ".format(app["title"]) + cmd = ("rxvt -title " + _("'Uninstalling {}'") + " -e bash -c ").format(app["title"]) if sudo_pwd: cmd += "'echo {} | sudo -S apt-get purge -y {}'".format(sudo_pwd, pkgs) else: @@ -118,15 +118,15 @@ def download_app(app_id_or_slug): icon_path = '/tmp/{}.{}'.format(app_id_or_slug, icon_file_type) rv, err = download_url(data['icon_url'], icon_path) if not rv: - msg = "Unable to download the application ({})".format(err) + msg = _("Unable to download the application ({})").format(err) raise AppDownloadError(msg) # Check if the app is going to run well on the hardware if 'min_performance_score' in data and \ has_min_performance(data['min_performance_score']): - msg = "{} won't be downloaded ".format(data['title']) + \ - "because the hardware is not performant enough" + msg = _("{} won't be downloaded " + \ + "because the hardware is not performant enough").format(data['title']) raise AppDownloadError(msg) # Cleanup the JSON file diff --git a/kano_apps/MainWindow.py b/kano_apps/MainWindow.py index d28c7df..43c2daa 100644 --- a/kano_apps/MainWindow.py +++ b/kano_apps/MainWindow.py @@ -57,7 +57,7 @@ def __init__(self, install=None, icon_only=False, tutorial=False): # Setup widgets self.set_decorated(True) - self._top_bar = TopBar("Apps", self._win_width, False) + self._top_bar = TopBar(_("Apps"), self._win_width, False) self._top_bar.set_close_callback(Gtk.main_quit) self.set_titlebar(self._top_bar) @@ -101,12 +101,12 @@ def _show_icon_tutorial(self): save_app_state_variable('kano-apps', 'icon-tutorial-shown', True) kdialog = KanoDialog( - "Add more apps to the desktop", - "Click the '+' button to the right of the app name to " - "make it appear on the desktop. You can remove it again " - "by clicking on 'x'.", + _("Add more apps to the desktop"), + _("Click the '+' button to the right of the app name to " +\ + "make it appear on the desktop. You can remove it again " +\ + "by clicking on 'x'."), { - "OK, GOT IT": { + _("OK, GOT IT"): { "return_value": 0, "color": "green" } diff --git a/kano_apps/UIElements.py b/kano_apps/UIElements.py index ea1f1d0..c04cf72 100644 --- a/kano_apps/UIElements.py +++ b/kano_apps/UIElements.py @@ -43,7 +43,7 @@ def get_sudo_password(heading, parent=None): entry.set_visibility(False) kdialog = KanoDialog( title_text=heading, - description_text="Enter your system password - default is kano:", + description_text=_("Enter your system password - default is kano:"), widget=entry, has_entry=True, global_style=True, @@ -57,12 +57,12 @@ def get_sudo_password(heading, parent=None): while not pam.authenticate(getpass.getuser(), pw): fail = KanoDialog( title_text=heading, - description_text="The password was incorrect. Try again?", + description_text=_("The password was incorrect. Try again?"), button_dict={ - "YES": { + _("YES"): { "return_value": 0 }, - "CANCEL": { + _("CANCEL"): { "return_value": -1, "color": "red" } @@ -79,7 +79,7 @@ def get_sudo_password(heading, parent=None): entry.set_visibility(False) kdialog = KanoDialog( title_text=heading, - description_text="Re-enter your system password - default is kano:", + description_text=_("Re-enter your system password - default is kano:"), widget=entry, has_entry=True, global_style=True, diff --git a/po/Makefile b/po/Makefile new file mode 100644 index 0000000..80be09c --- /dev/null +++ b/po/Makefile @@ -0,0 +1,36 @@ +APPNAME=kano-apps +ORG="Kano Computing Ltd." + +MSGLANGS=$(notdir $(wildcard *po)) +MSGOBJS=$(addprefix ../locale/,$(MSGLANGS:.po=/LC_MESSAGES/$(APPNAME).mo)) + +.PHONY: clean_locales messages + +build: $(MSGOBJS) + +update: $(MSGLANGS) + +clean_locales: + rm -rf ../locale + +clean: clean_locales + rm -f messages.pot + +define run-xgettext +xgettext -f PYPOTFILES -L Python --force-po -o messages.pot \ + --package-name=$(APPNAME) --copyright-holder=$(ORG) +endef + +messages: + $(run-xgettext) + +messages.pot: + $(run-xgettext) + +%.po: messages.pot + msgmerge -N -U $*.po messages.pot + touch $*.po + +../locale/%/LC_MESSAGES/$(APPNAME).mo: clean_locales + mkdir -p $(dir $@) + msgfmt -c -o $@ $*.po diff --git a/po/PYPOTFILES b/po/PYPOTFILES new file mode 100644 index 0000000..6d84d13 --- /dev/null +++ b/po/PYPOTFILES @@ -0,0 +1,6 @@ +../kano_apps/AppGrid.py +../kano_apps/AppInstaller.py +../kano_apps/AppManage.py +../kano_apps/MainWindow.py +../kano_apps/UIElements.py + diff --git a/po/ja.po b/po/ja.po new file mode 100644 index 0000000..8b5b44c --- /dev/null +++ b/po/ja.po @@ -0,0 +1,173 @@ +# Japanese translations for kano-apps package. +# Copyright (C) 2016 Kano Computing Ltd. +# This file is distributed under the same license as the kano-apps package. +# Choppin Antoine , 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: kano-apps\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-06-02 00:15+0900\n" +"PO-Revision-Date: 2016-06-02 00:15+0900\n" +"Last-Translator: Choppin Antoine \n" +"Language-Team: Japanese\n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../kano_apps/AppGrid.py:32 +msgid "Want more apps?" +msgstr "" + +#: ../kano_apps/AppGrid.py:33 +msgid "Go to Kano World to install more" +msgstr "" + +#: ../kano_apps/AppGrid.py:247 +msgid "Remove from desktop" +msgstr "" + +#: ../kano_apps/AppGrid.py:250 +msgid "Add to desktop" +msgstr "" + +#: ../kano_apps/AppGrid.py:418 +msgid "Error" +msgstr "" + +#: ../kano_apps/AppGrid.py:419 +msgid "Unable to start the application." +msgstr "" + +#: ../kano_apps/AppGrid.py:421 ../kano_apps/AppInstaller.py:98 +#: ../kano_apps/AppInstaller.py:177 +msgid "OK" +msgstr "" + +#: ../kano_apps/AppGrid.py:440 +msgid "More information" +msgstr "" + +#: ../kano_apps/AppGrid.py:462 +msgid "Remove" +msgstr "" + +#: ../kano_apps/AppGrid.py:493 +msgid "Update app" +msgstr "" + +#: ../kano_apps/AppGrid.py:512 ../kano_apps/MainWindow.py:109 +msgid "OK, GOT IT" +msgstr "" + +#: ../kano_apps/AppGrid.py:535 +msgid "Removing {}" +msgstr "" + +#: ../kano_apps/AppGrid.py:536 +msgid "" +"This application will be uninstalled and removed from apps. Do you wish to " +"proceed?" +msgstr "" + +#: ../kano_apps/AppGrid.py:539 ../kano_apps/AppGrid.py:585 +#: ../kano_apps/AppInstaller.py:119 ../kano_apps/UIElements.py:62 +msgid "YES" +msgstr "" + +#: ../kano_apps/AppGrid.py:542 ../kano_apps/AppGrid.py:588 +#: ../kano_apps/AppInstaller.py:122 +msgid "NO" +msgstr "" + +#: ../kano_apps/AppGrid.py:556 +msgid "Uninstalling {}" +msgstr "" + +#: ../kano_apps/AppGrid.py:581 +msgid "Updating {}" +msgstr "" + +#: ../kano_apps/AppGrid.py:582 +msgid "This application will be updated Do you wish to proceed?" +msgstr "" + +#: ../kano_apps/AppInstaller.py:94 +msgid "Unable to download the application" +msgstr "" + +#: ../kano_apps/AppInstaller.py:114 +msgid "{} is already installed" +msgstr "" + +#: ../kano_apps/AppInstaller.py:115 +msgid "Would you like to update it?" +msgstr "" + +#: ../kano_apps/AppInstaller.py:140 +msgid "Installing {}" +msgstr "" + +#: ../kano_apps/AppInstaller.py:163 +msgid "Done!" +msgstr "" + +#: ../kano_apps/AppInstaller.py:164 +#, python-format +msgid "%s installed successfully! Look for it in the Apps launcher." +msgstr "" + +#: ../kano_apps/AppInstaller.py:167 +msgid "Installation failed" +msgstr "" + +#: ../kano_apps/AppInstaller.py:168 +#, python-format +msgid "" +"%s cannot be installed at the moment. Please make sure your kit is connected " +"to the internet and there is enough space left on your card." +msgstr "" + +#: ../kano_apps/AppManage.py:70 +msgid "'Uninstalling {}'" +msgstr "" + +#: ../kano_apps/AppManage.py:121 +msgid "Unable to download the application ({})" +msgstr "" + +#: ../kano_apps/AppManage.py:128 +msgid "{} won't be downloaded because the hardware is not performant enough" +msgstr "" + +#: ../kano_apps/MainWindow.py:60 +msgid "Apps" +msgstr "" + +#: ../kano_apps/MainWindow.py:104 +msgid "Add more apps to the desktop" +msgstr "" + +#: ../kano_apps/MainWindow.py:105 +msgid "" +"Click the '+' button to the right of the app name to make it appear on the " +"desktop. You can remove it again by clicking on 'x'." +msgstr "" + +#: ../kano_apps/UIElements.py:46 +msgid "Enter your system password - default is kano:" +msgstr "" + +#: ../kano_apps/UIElements.py:60 +msgid "The password was incorrect. Try again?" +msgstr "" + +#: ../kano_apps/UIElements.py:65 +msgid "CANCEL" +msgstr "" + +#: ../kano_apps/UIElements.py:82 +msgid "Re-enter your system password - default is kano:" +msgstr "" From f507b2ffcb13f60e73553fd5e0d1c6d51cd8981d Mon Sep 17 00:00:00 2001 From: Antoine Choppin Date: Thu, 2 Jun 2016 00:33:14 +0900 Subject: [PATCH 02/10] Allow to translate categories --- .gitignore | 1 + kano_apps/AppGrid.py | 6 +++--- po/Makefile | 2 +- po/ja.po | 30 +++++++++++++++++++++++++++++- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 2341819..cc56eea 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ *.swo .* *.mo +*~ po/messages.pot diff --git a/kano_apps/AppGrid.py b/kano_apps/AppGrid.py index 26268f9..f4f2c5c 100644 --- a/kano_apps/AppGrid.py +++ b/kano_apps/AppGrid.py @@ -51,8 +51,8 @@ def __init__(self, apps, main_win): last_page = 0 - self._cat_names = ["latest", "code", "games", "media", "tools", - "others", "experimental"] + self._cat_names = [N_("latest"), N_("code"), N_("games"), N_("media"), N_("tools"), + N_("others"), N_("experimental")] self._categories = {} self._apps = {} @@ -73,7 +73,7 @@ def __init__(self, apps, main_win): # Prepare tabs for the apps for cat in sorted_categories: self._categories[cat] = AppGrid(main_win, self) - label = Gtk.Label(cat.upper()) + label = Gtk.Label(_(cat).upper()) ebox = Gtk.EventBox() ebox.add(label) ebox.connect("realize", self._set_cursor_to_hand_cb) diff --git a/po/Makefile b/po/Makefile index 80be09c..c7abe4b 100644 --- a/po/Makefile +++ b/po/Makefile @@ -18,7 +18,7 @@ clean: clean_locales define run-xgettext xgettext -f PYPOTFILES -L Python --force-po -o messages.pot \ - --package-name=$(APPNAME) --copyright-holder=$(ORG) + --keyword=N_ --package-name=$(APPNAME) --copyright-holder=$(ORG) endef messages: diff --git a/po/ja.po b/po/ja.po index 8b5b44c..0e76497 100644 --- a/po/ja.po +++ b/po/ja.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: kano-apps\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-06-02 00:15+0900\n" +"POT-Creation-Date: 2016-06-02 00:32+0900\n" "PO-Revision-Date: 2016-06-02 00:15+0900\n" "Last-Translator: Choppin Antoine \n" "Language-Team: Japanese\n" @@ -25,6 +25,34 @@ msgstr "" msgid "Go to Kano World to install more" msgstr "" +#: ../kano_apps/AppGrid.py:54 +msgid "latest" +msgstr "" + +#: ../kano_apps/AppGrid.py:54 +msgid "code" +msgstr "" + +#: ../kano_apps/AppGrid.py:54 +msgid "games" +msgstr "" + +#: ../kano_apps/AppGrid.py:54 +msgid "media" +msgstr "" + +#: ../kano_apps/AppGrid.py:54 +msgid "tools" +msgstr "" + +#: ../kano_apps/AppGrid.py:55 +msgid "others" +msgstr "" + +#: ../kano_apps/AppGrid.py:55 +msgid "experimental" +msgstr "" + #: ../kano_apps/AppGrid.py:247 msgid "Remove from desktop" msgstr "" From 6de0faeb416d42d7c5bb8b0adef78e840275a35d Mon Sep 17 00:00:00 2001 From: Antoine Choppin Date: Thu, 2 Jun 2016 08:19:21 +0900 Subject: [PATCH 03/10] Add setup script --- setup.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 setup.py diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..526fce8 --- /dev/null +++ b/setup.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +from distutils.core import setup +import setuptools +import os + +def get_locales(): + locale_dir = 'locale' + locales = [] + + for dirpath, dirnames, filenames in os.walk(locale_dir): + for filename in filenames: + locales.append( + (os.path.join('/usr/share', dirpath), + [os.path.join(dirpath, filename)]) + ) + + return locales + + +setup(name='Kano Apps', + version='1.0', + description='A simple app to launch various program', + author='Team Kano', + author_email='dev@kano.me', + url='https://github.com/KanoComputing/kano-apps', + packages=['kano_apps', 'kano_world.hook'], + package_dir={'kano_apps': 'kano_apps', 'kano_world.hook': 'kano-world-hook'}, + package_data={'kano_apps': ['media/*']}, + scripts=['bin/kano-apps', 'bin/update-app-dir'], + data_files=[ + ('/usr/share/applications', setuptools.findall('apps')), # *.app + ('/usr/share/icons/Kano/66x66/apps', setuptools.findall('apps/icons')), + ('/usr/share/kano-apps', setuptools.findall('books')), + ('/usr/share/kano-desktop/kdesk/kdesktop', ['kdesk-icon/Apps.lnk']), + ('/usr/share/kano-desktop/icons', setuptools.findall('kdesk-icon')) # *.png + ] + get_locales() + ) + From c960d96629b38622e49175797f2ac9e75405873a Mon Sep 17 00:00:00 2001 From: Antoine Choppin Date: Fri, 3 Jun 2016 02:43:49 +0900 Subject: [PATCH 04/10] Fix initialization and add Japanese translations --- bin/kano-apps | 8 ++++- po/ja.po | 86 +++++++++++++++++++++++++++------------------------ 2 files changed, 53 insertions(+), 41 deletions(-) diff --git a/bin/kano-apps b/bin/kano-apps index c02956e..be07e04 100755 --- a/bin/kano-apps +++ b/bin/kano-apps @@ -2,7 +2,7 @@ # kano-apps # -# Copyright (C) 2014, 2015 Kano Computing Ltd. +# Copyright (C) 2014-2016 Kano Computing Ltd. # License: http://www.gnu.org/licenses/gpl-2.0.txt GNU GPL v2 # @@ -15,6 +15,12 @@ if __name__ == '__main__' and __package__ is None: dir_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) if dir_path != '/usr': sys.path = [dir_path] + sys.path + locale_path = os.path.join(dir_path, 'locale') + else: + locale_path = None + +import kano_i18n.init +kano_i18n.init.install('kano-apps', locale_path) from kano.gtk3.kano_dialog import KanoDialog from kano.logging import logger diff --git a/po/ja.po b/po/ja.po index 0e76497..8b856cc 100644 --- a/po/ja.po +++ b/po/ja.po @@ -19,137 +19,139 @@ msgstr "" #: ../kano_apps/AppGrid.py:32 msgid "Want more apps?" -msgstr "" +msgstr "他のアプリ欲しい?" #: ../kano_apps/AppGrid.py:33 msgid "Go to Kano World to install more" -msgstr "" +msgstr "Kanoワールドで他のアプリをゲットしよう" #: ../kano_apps/AppGrid.py:54 msgid "latest" -msgstr "" +msgstr "最新" #: ../kano_apps/AppGrid.py:54 msgid "code" -msgstr "" +msgstr "コード" #: ../kano_apps/AppGrid.py:54 msgid "games" -msgstr "" +msgstr "ゲーム" #: ../kano_apps/AppGrid.py:54 msgid "media" -msgstr "" +msgstr "メディア" #: ../kano_apps/AppGrid.py:54 msgid "tools" -msgstr "" +msgstr "ツール" #: ../kano_apps/AppGrid.py:55 msgid "others" -msgstr "" +msgstr "その他" #: ../kano_apps/AppGrid.py:55 msgid "experimental" -msgstr "" +msgstr "実験中" #: ../kano_apps/AppGrid.py:247 msgid "Remove from desktop" -msgstr "" +msgstr "デスクトップから削除" #: ../kano_apps/AppGrid.py:250 msgid "Add to desktop" -msgstr "" +msgstr "デスクトップに追加" #: ../kano_apps/AppGrid.py:418 msgid "Error" -msgstr "" +msgstr "エラー" #: ../kano_apps/AppGrid.py:419 msgid "Unable to start the application." -msgstr "" +msgstr "アプリを起動できません。" #: ../kano_apps/AppGrid.py:421 ../kano_apps/AppInstaller.py:98 #: ../kano_apps/AppInstaller.py:177 msgid "OK" -msgstr "" +msgstr "了解" #: ../kano_apps/AppGrid.py:440 msgid "More information" -msgstr "" +msgstr "追加情報" #: ../kano_apps/AppGrid.py:462 msgid "Remove" -msgstr "" +msgstr "削除" #: ../kano_apps/AppGrid.py:493 msgid "Update app" -msgstr "" +msgstr "アプリをアップデート" #: ../kano_apps/AppGrid.py:512 ../kano_apps/MainWindow.py:109 msgid "OK, GOT IT" -msgstr "" +msgstr "はい、了解" #: ../kano_apps/AppGrid.py:535 msgid "Removing {}" -msgstr "" +msgstr "{}を削除中" #: ../kano_apps/AppGrid.py:536 msgid "" "This application will be uninstalled and removed from apps. Do you wish to " "proceed?" msgstr "" +"このアプリをアンインストールし、アップスから削除されます。" +"続けますか?" #: ../kano_apps/AppGrid.py:539 ../kano_apps/AppGrid.py:585 #: ../kano_apps/AppInstaller.py:119 ../kano_apps/UIElements.py:62 msgid "YES" -msgstr "" +msgstr "はい" #: ../kano_apps/AppGrid.py:542 ../kano_apps/AppGrid.py:588 #: ../kano_apps/AppInstaller.py:122 msgid "NO" -msgstr "" +msgstr "いいえ" #: ../kano_apps/AppGrid.py:556 msgid "Uninstalling {}" -msgstr "" +msgstr "{}をアンインストール" #: ../kano_apps/AppGrid.py:581 msgid "Updating {}" -msgstr "" +msgstr "{}をアップデート" #: ../kano_apps/AppGrid.py:582 msgid "This application will be updated Do you wish to proceed?" -msgstr "" +msgstr "このアプリがアップデートされます。続けますか?" #: ../kano_apps/AppInstaller.py:94 msgid "Unable to download the application" -msgstr "" +msgstr "アプリのダウンロードが失敗しました" #: ../kano_apps/AppInstaller.py:114 msgid "{} is already installed" -msgstr "" +msgstr "{}はすでにインストール済みです" #: ../kano_apps/AppInstaller.py:115 msgid "Would you like to update it?" -msgstr "" +msgstr "アップデートしますか?" #: ../kano_apps/AppInstaller.py:140 msgid "Installing {}" -msgstr "" +msgstr "{}をインストール中" #: ../kano_apps/AppInstaller.py:163 msgid "Done!" -msgstr "" +msgstr "完了!" #: ../kano_apps/AppInstaller.py:164 #, python-format msgid "%s installed successfully! Look for it in the Apps launcher." -msgstr "" +msgstr "%sは無事にインストールされました!アップラウンチャーから起動できます。" #: ../kano_apps/AppInstaller.py:167 msgid "Installation failed" -msgstr "" +msgstr "インストールの失敗" #: ../kano_apps/AppInstaller.py:168 #, python-format @@ -157,45 +159,49 @@ msgid "" "%s cannot be installed at the moment. Please make sure your kit is connected " "to the internet and there is enough space left on your card." msgstr "" +"現在、%sをインストールすることが出来ません。インターネットに接続していることと" +"SDカードの空き容量を確認してください。" #: ../kano_apps/AppManage.py:70 msgid "'Uninstalling {}'" -msgstr "" +msgstr "'{}をアンインストール中'" #: ../kano_apps/AppManage.py:121 msgid "Unable to download the application ({})" -msgstr "" +msgstr "アプリ({})をダウンロード出来ません" #: ../kano_apps/AppManage.py:128 msgid "{} won't be downloaded because the hardware is not performant enough" -msgstr "" +msgstr "ハードウェアのスペックが不十分な為、{}がダウンロード出来ません" #: ../kano_apps/MainWindow.py:60 msgid "Apps" -msgstr "" +msgstr "アップス" #: ../kano_apps/MainWindow.py:104 msgid "Add more apps to the desktop" -msgstr "" +msgstr "デスクトップに他のアプリを追加しよう" #: ../kano_apps/MainWindow.py:105 msgid "" "Click the '+' button to the right of the app name to make it appear on the " "desktop. You can remove it again by clicking on 'x'." msgstr "" +"アプリの右側の'+'ボタンでアプリをデスクトップに追加できます。" +"'x'をクリックして、デスクトップから削除できます。" #: ../kano_apps/UIElements.py:46 msgid "Enter your system password - default is kano:" -msgstr "" +msgstr "システムパスワードを入力してください(初期パスワードはkanoです):" #: ../kano_apps/UIElements.py:60 msgid "The password was incorrect. Try again?" -msgstr "" +msgstr "パスワードが間違っています。やり直す?" #: ../kano_apps/UIElements.py:65 msgid "CANCEL" -msgstr "" +msgstr "キャンセル" #: ../kano_apps/UIElements.py:82 msgid "Re-enter your system password - default is kano:" -msgstr "" +msgstr "システムパスワードを再度入力してください(初期パスワードはkanoです):" From 6631bd402e67ef035dae6c4e9d1315cb4d39da88 Mon Sep 17 00:00:00 2001 From: Antoine Choppin Date: Fri, 3 Jun 2016 02:56:04 +0900 Subject: [PATCH 05/10] Fix a few issues in setup.py --- setup.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 526fce8..988c7b3 100644 --- a/setup.py +++ b/setup.py @@ -17,6 +17,16 @@ def get_locales(): return locales +def get_files_in_dir(dir_name, suffix=None): + files = [] + + for dirpath, dirnames, filenames in os.walk(dir_name): + for filename in filenames: + if suffix is None or filename.endswith(suffix): + files.append(filename) + + return files + setup(name='Kano Apps', version='1.0', @@ -24,16 +34,16 @@ def get_locales(): author='Team Kano', author_email='dev@kano.me', url='https://github.com/KanoComputing/kano-apps', - packages=['kano_apps', 'kano_world.hook'], - package_dir={'kano_apps': 'kano_apps', 'kano_world.hook': 'kano-world-hook'}, + packages=['kano_apps'], package_data={'kano_apps': ['media/*']}, scripts=['bin/kano-apps', 'bin/update-app-dir'], data_files=[ - ('/usr/share/applications', setuptools.findall('apps')), # *.app + ('/usr/share/applications', get_files_in_dir('apps', '.app')), ('/usr/share/icons/Kano/66x66/apps', setuptools.findall('apps/icons')), ('/usr/share/kano-apps', setuptools.findall('books')), ('/usr/share/kano-desktop/kdesk/kdesktop', ['kdesk-icon/Apps.lnk']), - ('/usr/share/kano-desktop/icons', setuptools.findall('kdesk-icon')) # *.png + ('/usr/share/kano-desktop/icons', get_files_in_dir('kdesk-icon', '.png')), + ('/usr/lib/python2.7/dist-packages/kano_world/hooks', setuptools.findall('kano-world-hook/')) ] + get_locales() ) From 2794c5c2db7a1d52b068783771739ab5955b484b Mon Sep 17 00:00:00 2001 From: Antoine Choppin Date: Fri, 3 Jun 2016 21:17:31 +0900 Subject: [PATCH 06/10] Add missing translations --- bin/kano-apps | 28 +++++++++++------------ po/PYPOTFILES | 1 + po/ja.po | 63 ++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 70 insertions(+), 22 deletions(-) diff --git a/bin/kano-apps b/bin/kano-apps index be07e04..4970ae7 100755 --- a/bin/kano-apps +++ b/bin/kano-apps @@ -56,18 +56,18 @@ def check_for_expand_partition(): # Check if partition has been expanded if not is_partition_expanded(device): # Show dialogue - head = "Do you want to reboot now?" - msg = "A reboot is required to complete the installation of Kano" \ - " OS so it can access all the space on the SD card." + head = _("Do you want to reboot now?") + msg = _("A reboot is required to complete the installation of Kano" +\ + " OS so it can access all the space on the SD card.") kdialog = KanoDialog( head, msg, { - "LATER": { + _("LATER"): { "return_value": False, "color": "red" }, - "REBOOT": { + _("REBOOT"): { "return_value": True, "color": "green" }, @@ -113,29 +113,29 @@ def batch_install(apps, icon_only=False): def args_parse(): if len(sys.argv) >= 2: - desc = "An application hub for Kano OS." + desc = _("An application hub for Kano OS.") parser = argparse.ArgumentParser(description=desc) parser.set_defaults(cmd=None) subparsers = parser.add_subparsers(dest="cmd") - install_help = "Use this to install applications" + install_help = _("Use this to install applications") install = subparsers.add_parser("install", help=install_help) install.add_argument("--no-gui", dest="gui", action="store_const", const=False, default=True, - help="Run without the GUI") + help=_("Run without the GUI")) install.add_argument("--icon-only", dest="icon_only", action="store_const", const=True, default=False, - help="Install just the app icon") + help=_("Install just the app icon")) install.add_argument("apps", metavar="APP", type=str, nargs="+", - help="A list of applications to install") + help=_("A list of applications to install")) - update_help = "Check for possible updates of all installed " \ - "applications" + update_help = _("Check for possible updates of all installed " +\ + "applications") subparsers.add_parser("check-for-updates", help=update_help) - tutorial_help = "Shows a tutorial that explains how to add icons to" \ - "the desktop" + tutorial_help = _("Shows a tutorial that explains how to add icons to " +\ + "the desktop") subparsers.add_parser("icon-tutorial", help=tutorial_help) return parser.parse_args() diff --git a/po/PYPOTFILES b/po/PYPOTFILES index 6d84d13..c619503 100644 --- a/po/PYPOTFILES +++ b/po/PYPOTFILES @@ -1,3 +1,4 @@ +../bin/kano-apps ../kano_apps/AppGrid.py ../kano_apps/AppInstaller.py ../kano_apps/AppManage.py diff --git a/po/ja.po b/po/ja.po index 8b856cc..9eeef29 100644 --- a/po/ja.po +++ b/po/ja.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: kano-apps\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-06-02 00:32+0900\n" +"POT-Creation-Date: 2016-06-03 21:15+0900\n" "PO-Revision-Date: 2016-06-02 00:15+0900\n" "Last-Translator: Choppin Antoine \n" "Language-Team: Japanese\n" @@ -17,6 +17,54 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" +#: ../bin/kano-apps:59 +msgid "Do you want to reboot now?" +msgstr "今再起動しますか?" + +#: ../bin/kano-apps:60 +msgid "" +"A reboot is required to complete the installation of Kano OS so it can " +"access all the space on the SD card." +msgstr "" +"Kano OSのインストールを完了するには、SDカード容量の全てが利用できるよう、再起" +"動が必要です。" + +#: ../bin/kano-apps:66 +msgid "LATER" +msgstr "後で" + +#: ../bin/kano-apps:70 +msgid "REBOOT" +msgstr "再起動" + +#: ../bin/kano-apps:116 +msgid "An application hub for Kano OS." +msgstr "Kano OSアプリのハブ" + +#: ../bin/kano-apps:121 +msgid "Use this to install applications" +msgstr "アプリをインストールする" + +#: ../bin/kano-apps:126 +msgid "Run without the GUI" +msgstr "GUI無しで起動" + +#: ../bin/kano-apps:129 +msgid "Install just the app icon" +msgstr "アプリのアイコンのみインストール" + +#: ../bin/kano-apps:131 +msgid "A list of applications to install" +msgstr "インストール可能なアプリ一覧" + +#: ../bin/kano-apps:133 +msgid "Check for possible updates of all installed applications" +msgstr "インストール済みアプリのアップデート確認" + +#: ../bin/kano-apps:137 +msgid "Shows a tutorial that explains how to add icons to the desktop" +msgstr "デスクトップにアイコンを追加する為のチュートリアル" + #: ../kano_apps/AppGrid.py:32 msgid "Want more apps?" msgstr "他のアプリ欲しい?" @@ -98,9 +146,7 @@ msgstr "{}を削除中" msgid "" "This application will be uninstalled and removed from apps. Do you wish to " "proceed?" -msgstr "" -"このアプリをアンインストールし、アップスから削除されます。" -"続けますか?" +msgstr "このアプリをアンインストールし、アップスから削除されます。続けますか?" #: ../kano_apps/AppGrid.py:539 ../kano_apps/AppGrid.py:585 #: ../kano_apps/AppInstaller.py:119 ../kano_apps/UIElements.py:62 @@ -159,8 +205,8 @@ msgid "" "%s cannot be installed at the moment. Please make sure your kit is connected " "to the internet and there is enough space left on your card." msgstr "" -"現在、%sをインストールすることが出来ません。インターネットに接続していることと" -"SDカードの空き容量を確認してください。" +"現在、%sをインストールすることが出来ません。インターネットに接続していること" +"とSDカードの空き容量を確認してください。" #: ../kano_apps/AppManage.py:70 msgid "'Uninstalling {}'" @@ -187,8 +233,8 @@ msgid "" "Click the '+' button to the right of the app name to make it appear on the " "desktop. You can remove it again by clicking on 'x'." msgstr "" -"アプリの右側の'+'ボタンでアプリをデスクトップに追加できます。" -"'x'をクリックして、デスクトップから削除できます。" +"アプリの右側の'+'ボタンでアプリをデスクトップに追加できます。'x'をクリックし" +"て、デスクトップから削除できます。" #: ../kano_apps/UIElements.py:46 msgid "Enter your system password - default is kano:" @@ -205,3 +251,4 @@ msgstr "キャンセル" #: ../kano_apps/UIElements.py:82 msgid "Re-enter your system password - default is kano:" msgstr "システムパスワードを再度入力してください(初期パスワードはkanoです):" + From 485e34d1db779dac802ee69b8fc685735557715e Mon Sep 17 00:00:00 2001 From: Antoine Choppin Date: Fri, 3 Jun 2016 21:49:33 +0900 Subject: [PATCH 07/10] Fix setup.py --- setup.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/setup.py b/setup.py index 988c7b3..502be56 100644 --- a/setup.py +++ b/setup.py @@ -3,6 +3,7 @@ from distutils.core import setup import setuptools import os +import glob def get_locales(): locale_dir = 'locale' @@ -17,16 +18,6 @@ def get_locales(): return locales -def get_files_in_dir(dir_name, suffix=None): - files = [] - - for dirpath, dirnames, filenames in os.walk(dir_name): - for filename in filenames: - if suffix is None or filename.endswith(suffix): - files.append(filename) - - return files - setup(name='Kano Apps', version='1.0', @@ -38,11 +29,11 @@ def get_files_in_dir(dir_name, suffix=None): package_data={'kano_apps': ['media/*']}, scripts=['bin/kano-apps', 'bin/update-app-dir'], data_files=[ - ('/usr/share/applications', get_files_in_dir('apps', '.app')), + ('/usr/share/applications', glob.glob('apps/*.app')), ('/usr/share/icons/Kano/66x66/apps', setuptools.findall('apps/icons')), ('/usr/share/kano-apps', setuptools.findall('books')), ('/usr/share/kano-desktop/kdesk/kdesktop', ['kdesk-icon/Apps.lnk']), - ('/usr/share/kano-desktop/icons', get_files_in_dir('kdesk-icon', '.png')), + ('/usr/share/kano-desktop/icons', glob.glob('kdesk-icon/*.png')), ('/usr/lib/python2.7/dist-packages/kano_world/hooks', setuptools.findall('kano-world-hook/')) ] + get_locales() ) From 9607be61f67665d4d7fe7ec56cc24cd74df80bee Mon Sep 17 00:00:00 2001 From: Antoine Choppin Date: Fri, 3 Jun 2016 22:14:33 +0900 Subject: [PATCH 08/10] Set default script install directory --- setup.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setup.py b/setup.py index 988c7b3..4c56f9c 100644 --- a/setup.py +++ b/setup.py @@ -3,6 +3,10 @@ from distutils.core import setup import setuptools import os +import sys + +if '--install-scripts' not in sys.argv: + sys.argv.push('--install-scripts=/usr/bin') def get_locales(): locale_dir = 'locale' From c14f80612c5d003604c0534b5770610eedfc9cdc Mon Sep 17 00:00:00 2001 From: Antoine Choppin Date: Fri, 3 Jun 2016 22:21:48 +0900 Subject: [PATCH 09/10] Fix install dir --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 91f283d..400e85c 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ import sys if '--install-scripts' not in sys.argv: - sys.argv.push('--install-scripts=/usr/bin') + sys.argv.append('--install-scripts=/usr/bin') def get_locales(): locale_dir = 'locale' From 64b2c023ec578fa8f97ae92c4aa4f32db8c0fe5d Mon Sep 17 00:00:00 2001 From: Antoine Choppin Date: Fri, 3 Jun 2016 22:23:10 +0900 Subject: [PATCH 10/10] Remove setup.py --- setup.py | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 setup.py diff --git a/setup.py b/setup.py deleted file mode 100644 index 91f283d..0000000 --- a/setup.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python - -from distutils.core import setup -import setuptools -import glob -import os -import sys - -if '--install-scripts' not in sys.argv: - sys.argv.push('--install-scripts=/usr/bin') - -def get_locales(): - locale_dir = 'locale' - locales = [] - - for dirpath, dirnames, filenames in os.walk(locale_dir): - for filename in filenames: - locales.append( - (os.path.join('/usr/share', dirpath), - [os.path.join(dirpath, filename)]) - ) - - return locales - - -setup(name='Kano Apps', - version='1.0', - description='A simple app to launch various program', - author='Team Kano', - author_email='dev@kano.me', - url='https://github.com/KanoComputing/kano-apps', - packages=['kano_apps'], - package_data={'kano_apps': ['media/*']}, - scripts=['bin/kano-apps', 'bin/update-app-dir'], - data_files=[ - ('/usr/share/applications', glob.glob('apps/*.app')), - ('/usr/share/icons/Kano/66x66/apps', setuptools.findall('apps/icons')), - ('/usr/share/kano-apps', setuptools.findall('books')), - ('/usr/share/kano-desktop/kdesk/kdesktop', ['kdesk-icon/Apps.lnk']), - ('/usr/share/kano-desktop/icons', glob.glob('kdesk-icon/*.png')), - ('/usr/lib/python2.7/dist-packages/kano_world/hooks', setuptools.findall('kano-world-hook/')) - ] + get_locales() - ) -