Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*.pyc
.DS_Store
.*
.mo
po/messages.pot
61 changes: 61 additions & 0 deletions TRANSLATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# 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 ..

# when testing, make sure LC_ALL is set to your locale e.g.
LC_ALL=fr_FR.utf8

## 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 `<lang>.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.
5 changes: 5 additions & 0 deletions bin/kano-init-flow
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,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.insert(1, dir_path)
LOCALE_PATH = '/usr/share/locale'
else:
LOCALE_PATH = None

import kano_i18n.init
kano_i18n.init.install('kano-init-flow', LOCALE_PATH)

import docopt
from gi.repository import Gtk, GObject
Expand Down
4 changes: 2 additions & 2 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ Maintainer: Team Kano <dev@kano.me>
Section: x11
Priority: optional
Standards-Version: 3.9.4
Build-Depends: debhelper (>=9.0.0), python-setuptools
Build-Depends: debhelper (>=9.0.0), python-setuptools, gettext

Package: kano-init-flow
Architecture: all
Depends: ${misc:Depends}, gir1.2-gtk-3.0, kano-toolset (>=1.2-2),
kano-profile (>=2.2.0-5), kano-settings (>=2.2-1),
kano-connect (>=2.0-1), kano-peripherals
kano-connect (>=2.0-1), kano-peripherals, kano-i18n
Description: Kanux initial boot
1 change: 1 addition & 0 deletions debian/rules
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/make -f

%:
cd po && make
dh $@ --with python2
18 changes: 9 additions & 9 deletions kano_init_flow/kw_slideshow/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@ def slide1(self):
678
)
image = Gtk.Image.new_from_pixbuf(pixbuf)
title1 = Gtk.Label("Get Started")
title1 = Gtk.Label(_("Get Started"))
title1.get_style_context().add_class("title")
title2 = Gtk.Label("Apps")
title2 = Gtk.Label(_("Apps"))
title2.get_style_context().add_class("title")
desc = Gtk.Label(
desc = Gtk.Label(_(
"Create and play with\n" +
"Kano's Apps to make and save your\n" +
"own code masterpieces, from games\n" +
"and minecraft world, to art and music pieces..."
)
))
desc.get_style_context().add_class("description")

next_button = KanoButton("NEXT")
next_button = KanoButton(_("NEXT"))
next_button.connect("clicked", self.slide2_wrapper)

fixed.put(image, 0, 0)
Expand All @@ -66,17 +66,17 @@ def slide2(self):
678
)
image = Gtk.Image.new_from_pixbuf(pixbuf)
title = Gtk.Label("Kano World")
title = Gtk.Label(_("Kano World"))
title.get_style_context().add_class("title")
desc = Gtk.Label(
desc = Gtk.Label(_(
"Show off and share your creations to friends\n" +
"family and other Kano users on Kano World.\n\n" +
"Why not check it out now by clicking on the\n" +
"icon to see what people have made today."
)
))
desc.get_style_context().add_class("description")

next_button = KanoButton("LET'S GO")
next_button = KanoButton(_("LET'S GO"))
next_button.connect("clicked", Gtk.main_quit)

fixed.put(image, 0, 0)
Expand Down
36 changes: 18 additions & 18 deletions kano_init_flow/stages/audio_lab/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def _setup_first_scene(self):
Placement(0.95, 0.9)
)

copy = 'Press the TAB key to play a song!'
copy = _('Press the TAB key to play a song!')
scene.add_widget(
SpeechBubble(text=copy, source=SpeechBubble.BOTTOM,
source_align=0.8, scale=scene.scale_factor),
Expand Down Expand Up @@ -151,9 +151,9 @@ def _setup_help_jack(self, scene):
Notebook(
self,
self.media_path('jack.png'), 1.0, 0.5,
'Plug in the blue cable',
['Check you\'ve plugged in the audio'],
[{'label': 'NEXT',
_('Plug in the blue cable'),
[_('Check you\'ve plugged in the audio')],
[{'label': _('NEXT'),
'callback': self.help_leds,
'color': 'green'}]
),
Expand All @@ -168,11 +168,11 @@ def _setup_help_leds(self, scene):
Notebook(
self,
self.media_path('troubleshooting-sound.png'), 0.5, 0.3,
'Can you see the blue light?',
['If the power plugs are connected correctly,',
'you should see a blue light.'],
[{'label': 'YES', 'callback': self.remove_overlays, 'color': 'green'},
{'label': 'NO', 'callback': self.help_power, 'color': 'red'}]
_('Can you see the blue light?'),
[_('If the power plugs are connected correctly,'),
_('you should see a blue light.')],
[{'label': _('YES'), 'callback': self.remove_overlays, 'color': 'green'},
{'label': _('NO'), 'callback': self.help_power, 'color': 'red'}]
),
Placement(0.5, 0.5, 0.0),
Placement(0.5, 0.5, 0.0),
Expand All @@ -182,16 +182,16 @@ def _setup_help_leds(self, scene):

def _setup_help_power(self, scene):
buttons = [{
'label': 'TRY AGAIN',
'label': _('TRY AGAIN'),
'callback': self.remove_overlays,
'color': 'green'},
{'label': 'SKIP',
{'label': _('SKIP'),
'callback': self._ctl.next_stage,
'color': 'grey'}
]
if hdmi_supported:
buttons.insert(1, {
'label': 'USE TV SPEAKERS',
'label': _('USE TV SPEAKERS'),
'callback': self._set_to_hdmi,
'color': 'blue'
})
Expand All @@ -200,9 +200,9 @@ def _setup_help_power(self, scene):
Notebook(
self,
self.media_path('power.png'), 0.8, 0.5,
'No light? Check the GPIO',
['The cable has to be connected to these',
'pins exactly.'],
_('No light? Check the GPIO'),
[_('The cable has to be connected to these'),
_('pins exactly.')],
buttons
),
Placement(0.5, 0.5, 0.0),
Expand Down Expand Up @@ -232,7 +232,7 @@ def __init__(self, stage, scene, yes_cb, no_cb):
vbox = Gtk.VBox(False, 0)
vbox.set_halign(Gtk.Align.CENTER)

question = Gtk.Label('Can you hear a sound?')
question = Gtk.Label(_('Can you hear a sound?'))
question.set_line_wrap(True)
question.set_justify(Gtk.Justification.CENTER)
question.set_valign(Gtk.Align.CENTER)
Expand All @@ -244,10 +244,10 @@ def __init__(self, stage, scene, yes_cb, no_cb):
hbox.set_halign(Gtk.Align.CENTER)
hbox.set_valign(Gtk.Align.CENTER)

yes = KanoButton('YES')
yes = KanoButton(_('YES'))
yes.connect('clicked', cb_wrapper, yes_cb)

no = KanoButton('NO', color='red')
no = KanoButton(_('NO'), color='red')
no.connect('clicked', cb_wrapper, no_cb)

hbox.pack_start(yes, False, False, 0)
Expand Down
14 changes: 7 additions & 7 deletions kano_init_flow/stages/blocks/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ def _setup_first_scene(self):
scene = self._setup_base_temple_scene()

copy = [
'Oh no, there\'s a boulder',
'in the way!'
_('Oh no, there\'s a boulder'),
_('in the way!')
]
scene.add_widget(
SpeechBubble(
Expand Down Expand Up @@ -112,10 +112,10 @@ def _setup_second_scene(self):
scene = self._setup_base_temple_scene()

copy = [
'But don\'t worry, you can',
'use Kano blocks to create code',
'to change what\'s around you.\n',
'Looks like there\'s one over there!'
_('But don\'t worry, you can'),
_('use Kano blocks to create code'),
_('to change what\'s around you.\n'),
_('Looks like there\'s one over there!')
]
scene.add_widget(
SpeechBubble(
Expand Down Expand Up @@ -230,7 +230,7 @@ def _setup_fifth_scene(self):

scene.add_widget(
SpeechBubble(
text="Awesome, now we can escape!",
text=_("Awesome, now we can escape!"),
source=SpeechBubble.BOTTOM,
source_align=0.5,
scale=scene.scale_factor
Expand Down
4 changes: 2 additions & 2 deletions kano_init_flow/stages/bugs/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ def _setup_first_scene(self):

def _place_judoka_into_scene(self, scene, happy=False):
image = 'judoka-scared.png'
copy = "Oh no bugs!\nClick on them quick to remove them."
copy = _("Oh no bugs!\nClick on them quick to remove them.")
if happy:
image = 'judoka.png'
copy = 'Phew, thanks for cleaning up!'
copy = _('Phew, thanks for cleaning up!')

scene.add_widget(
Gtk.Image.new_from_file(self.media_path(image)),
Expand Down
Loading