MakingYourAppSpeakLanguageswithLaunchpadTranslations
App Developer Week -- Making Your App Speak Languages with Launchpad Translations -- dpm -- Tue, Sep 6th, 2011
1 [15:57] <dpm> is everyone ready for another day of cool app developer sessions?
2 [15:57] <dpm> day 2 of ubuntu app developer week is about to start!
3 [15:58] <Andy80> yeeeeeaaahh
4 [15:58] <dpm> :)
5 [16:00] <dpm> ok, let's wait for Classbot to kick off and then get started
6 [16:00] <dpm> oh, there it is... :)
7 [16:01] <dpm> allright, let's roll
8 [16:01] <dpm> Welcome to this session on setting up your project for translations in Launchpad
9 [16:02] <dpm> My name is David Planella I work as the Ubuntu Translations Coordinator in the Community team at Canonical,
10 [16:02] <dpm> where I work with our translations community to bring you a localized Operating System.
11 [16:03] <dpm> I also tend to help with any topics related to translations and Launchpad, and that's what we're going to talk about today :)
12 [16:03] <dpm> That's a really exciting topic to me, as Launchpad makes it really easy to make your applications translatable and available to everyone in almost any language, and I hope you enjoy it as much as I do.
13 [16:03] <dpm> Translators are really awesome people!
14 [16:04] <dpm> I'll leave some time for questions at the end, but feel free to ask them throughout the session
15 [16:05] <dpm> Anyway, let's get started, shall we?
16 [16:05] <dpm> Assumptions
17 [16:05] <dpm> -----------
18 [16:05] <dpm>
19 [16:05] <dpm> I will start with an application ready set up for translations, so I'm not going to go into much detail there.
20 [16:06] <dpm> (I'll take questions, though, if there are any)
21 [16:06] <dpm> My intention is to focus in getting you started with exposing your project's translations to everyone for translation.
22 [16:06] <dpm> We're going to be using these tools:
23 [16:07] <dpm> bzr
24 [16:07] <dpm> quickly
25 [16:07] <dpm> python-distutils-extra
26 [16:07] <dpm> In particular quickly, which we'll use to start with a nearly ready-made project with translations set up
27 [16:08] <dpm> (You can install it by running the 'sudo apt-get install quickly' command or you can get it from the Ubuntu Software Centre)
28 [16:08] <dpm>
29 [16:08] <dpm> Creating the project and setting it up for translations
30 [16:08] <dpm> -------------------------------------------------------
31 [16:08] <dpm>
32 [16:08] <dpm> We'll use quickly to create a project called 'fooby', and then we'll set up the last touches needed to configure translations.
33 [16:09] <dpm> As I said, we won't go into the detail of setting up the application for translation, as quickly will do the heavy lifting for you,
34 [16:09] <dpm> but here's a high level overview of what needs to be done to add internationalization support to an app, in case you need to do it outside of quickly:
35 [16:10] <dpm> Generic Steps to Internationalize an Application
36 [16:10] <dpm> ================================================
37 [16:10] <dpm>
38 [16:11] <dpm> * Integrate gettext (http://www.gnu.org/s/gettext/) into the application. Initialize gettext in your main function
39 [16:11] <dpm> * Integrate gettext into the build system. There are generally gettext rules in the most common build systems. Use them.
40 [16:12] <dpm> * Mark translatable messages. Use the _() gettext call to mark all translatable messages in your application
41 [16:12] <dpm> * Care for your translation community. Not necessarily a step related to adding i18n support, but you'll want an active and healthy translation community around your project. Keep the templates with translatable messages up to date. Announce these updates and give translators time to do their work before a release. Be responsive to feedback.
42 [16:12] <dpm> anyway, going back to the subject
43 [16:13] <dpm> So if you've got all those tools installed, you can simply fire up a terminal window (Ctrl + Alt + T) and run the following command:
44 [16:13] <dpm> quickly create ubuntu-application fooby
45 [16:13] <dpm> This will create an application named 'fooby'
46 [16:13] <dpm> and give you some information about it on the first run
47 [16:14] <dpm> then change to the fooby folder:
48 [16:14] <dpm> cd fooby
49 [16:14] <dpm> And finally run:
50 [16:14] <dpm> python setup.py build_i18n
51 [16:15] <dpm> That should have finished the last bits to set up translations, so that you can already link up your application with Launchpad Translations
52 [16:16] <dpm> in particular, what that last command did was to created the po folder in your project, to contain what it's called the translations template and the translations files themselves
53 [16:16] <dpm> you can see the template there by running:
54 [16:16] <dpm> ls po
55 [16:16] <dpm> have a look at it:
56 [16:16] <dpm> gedit po/fooby.pot
57 [16:17] <dpm> It's important to get a bit familiar with it, but you don't have to remember the whole format
58 [16:17] <dpm> you should simply know what it is for now :)
59 [16:17] <dpm> and that Launchpad needs it to be in your project
60 [16:18] <dpm> A few bits and pieces on translation templates:
61 [16:18] <dpm> * Gettext: They follow the gettext format: http://is.gd/fC8p6
62 [16:19] <dpm> * Name: They are generally named after your project, with a .pot extension. E.g. fooby.pot
63 [16:19] <dpm> * One template per app: Generally applications need only one template
64 [16:19] <dpm> * Layout: They generally live in the po/ folder, along with the translations
65 [16:19] <dpm> * Content: They are text files which contain:
66 [16:19] <dpm> * A header with metadata
67 [16:20] <dpm> * A set of message pairs: msgid are the original strings extracted from the code and exposed to translators, and msgstr are the placeholders for the translations, which are always empty in the templates.
68 [16:20] <dpm> * Launchpad import: They are imported into Launchpad and exposed for translations for all languages in https://translations.launchpad.net/$YOUR_PROJECT
69 [16:20] <dpm> * Updates: You update the template whenever you have new strings in your app and you think they are stable for translation (generally shortly before release)
70 [16:21] <dpm> * Tools: you update templates with gettext based tools:
71 [16:21] <dpm> * generally intltool -> 'cd po && intltool-update -p'
72 [16:21] <dpm> * or increasingly python-distutils-extra for python projects -> 'python setup.py build_i18n -p'
73 [16:22] <dpm> You don't have to remember all of this
74 [16:22] <dpm> But hopefully these points will give you some insight on translation templates
75 [16:22] <dpm> At least you should know how that you must update the template from time to time
76 [16:23] <dpm> and the command to do it
77 [16:23] <dpm> Repeat it with me - "I _will_ update the translation from time to time, at least once before a release"
78 [16:23] <dpm> :-)
79 [16:24] <dpm> You'll see that your project still does not contain any translations, but again, let me give you a quick overview on translations, so you know what we're talking about:
80 [16:24] <dpm> So here we go, a few words on translations:
81 [16:26] <dpm> * Template-based: They are created from the template and share the same gettext format
82 [16:26] <dpm> * Name: They are named after the $CODE.po scheme, where $CODE is an ISO 639-2 code. E.g. ca.po for Catalan, de.po for German. Some have an optional country specifier. E.g. pt_BR.po (Portuguese from Brazil)
83 [16:27] <dpm> * Layout: they are all in the same directory as the POT template. So:
84 [16:27] <dpm> * po/fooby.pot
85 [16:27] <dpm> * po/ca.po
86 [16:27] <dpm> * po/pt_BR.po
87 [16:27] <dpm> * ...
88 [16:27] <dpm> * Creation: Launchpad creates them for you the minute someone translates the first message online
89 [16:27] <dpm> * Code integration: you can let Launchpad commit them to a branch of your choice or you can export a tarball containing them all (more on that later)
90 [16:28] <dpm> Anyway, let's continue. Now that you've added the template to your code, you can commit it by running the following commands:
91 [16:28] <dpm> bzr add po
92 [16:28] <dpm> bzr commit -m 'Created my first ever awesome .pot template. Go translators, go!'
93 [16:29] <dpm> And let's publish it in Launchpad (note that you'll have to change the Launchpad URL to your user name instead of 'dpm'):
94 [16:29] <dpm> bzr push lp:~dpm/fooby/translations
95 [16:29] <dpm> Nothing particularly hard to understand on the naming scheme above: dpm is my user name, fooby is the project and translations is the bzr branch name in Launchpad
96 [16:29] <dpm> Ok, so that completed the first step!
97 [16:29] <dpm> Next:
98 [16:30] <dpm> ah, forgot to ask, any questions so far?
99 [16:30] <ClassBot> Andy80 asked: what about Qt application? They don't use gettext. They have their own method to be translatable (basically it's just a matter of tr("This is a message") ) and I noticed that in Unity-2D we're using a sort of macro. Why don't we improve the launchpad integration even for Qt applications?
100 [16:30] <dpm> good question
101 [16:31] <dpm> as Unity 2D is an Ubuntu project, it has to integrate well with Launchpad and the way Ubuntu translators translate, which is again Launchpad Translations
102 [16:32] <dpm> in short, in the Unity 2D project there is some code that intercepts the Qt tr() calls and converts them to gettext() calls
103 [16:33] <dpm> so effectively Unity 2D, despite being a Qt project, uses gettext for translations
104 [16:33] <dpm> I agree that it'd be nice for Launchpad to support the Qt format
105 [16:33] <dpm> but as you see, you can easily use gettext from Qt-based apps too
106 [16:34] <dpm> Ok, let's continue
107 [16:34] <dpm> Setting up code hosting
108 [16:34] <dpm> -----------------------
109 [16:34] <dpm>
110 [16:34] <dpm> We want our project to be available to everyone to translate, so we'll need to publish it in Launchpad first.
111 [16:34] <dpm> That's beyond the scope of this session, so we'll continue from the already registered fooby project in Launchpad:
112 [16:34] <dpm> https://code.launchpad.net/fooby
113 [16:35] <dpm> In case you are interested, though, registering a new project in Launchpad is as easy as going to https://launchpad.net/projects/+new
114 [16:35] <dpm> Some of the URLs I'll post to set up your project will not allow you to open some of the pages due to permissions, so if you have your own project in Launchpad, just substitute the 'fooby' part in the URL with your project's Launchpad id
115 [16:36] <dpm> The first thing we'll have to do in our project is registering a bzr branch,
116 [16:36] <dpm> so we'll simply go to the Code tab in Launchpad, choose the "Configure code hosting" link
117 [16:36] <dpm> and then on the "Link to a Bazaar branch already on Launchpad" you can enter the branch we published earlier on (~dpm/fooby/translations)
118 [16:36] <dpm> A shortcut is to simply go to:
119 [16:36] <dpm> https://code.launchpad.net/fooby/trunk/+setbranch
120 [16:36] <dpm> to do this
121 [16:37] <dpm> So now we have all we need to start setting up translations.
122 [16:37] <dpm> You see that all components in Launchpad are integrated, so you set up a branch to be linked to translations
123 [16:37] <dpm> Just as a recap, you can see and explore the resulting code from here:
124 [16:37] <dpm> https://code.launchpad.net/fooby
125 [16:37] <dpm> Feel free to browse it (http://bazaar.launchpad.net/~dpm/fooby/translations/files)
126 [16:37] <dpm> or download it (bzr branch lp:fooby) and play with it
127 [16:38] <dpm> Ok, so code hosting setup: (./) Finished!
128 [16:38] <dpm>
129 [16:38] <dpm> Setting up translations in Launchpad
130 [16:38] <dpm> ------------------------------------
131 [16:38] <dpm>
132 [16:38] <dpm> Now we come to the most interesting part
133 [16:38] <dpm> Let's divide this in 4 steps
134 [16:38] <dpm> 1. Telling Launchpad where translations are hosted
135 [16:38] <dpm> The first step it to tell Launchpad that we want to host translations there.
136 [16:39] <dpm> On your Launchpad's project, just click on the Translations tab, or go to this URL:
137 [16:39] <dpm> (remember to change 'fooby' to your project's name!)
138 [16:39] <dpm> https://translations.launchpad.net/fooby/+configure-translations
139 [16:39] <dpm> Then choose the "Launchpad" option to tell Launchpad translations will be done there, and click on "Change"
140 [16:39] <dpm> That was an easy one, wasn't it?
141 [16:39] <dpm> 2. Configuring permissions
142 [16:39] <dpm> Now we are going to tell Launchpad how we want our translations permissions to be (i.e. who and how can translate it),
143 [16:40] <dpm> and which branch translators should focus on.
144 [16:40] <dpm> Simply go to the Translations tab again and click on the "Change permissions link"
145 [16:40] <dpm> Or here's the direct link: https://translations.launchpad.net/fooby/+settings :)
146 [16:40] <dpm> I recommend the following setup:
147 [16:40] <dpm> Translations group: Launchpad Translators
148 [16:40] <dpm> Translations permissions policy: Structured
149 [16:40] <dpm> Translation focus: trunk (or choose your branch here)
150 [16:40] <dpm> Assigning the translations to a translation group will make sure a team for each language will review translations before they are submitted, ensuring the quality of translations
151 [16:41] <dpm> A translations group is simply a set of teams, one per language, that takes care of translations in that language
152 [16:41] <dpm> They can be specific to a project or generic.
153 [16:41] <dpm> I recommend the Launchpad Translators group because it contains a set of already established and experienced teams:
154 [16:41] <dpm> https://translations.launchpad.net/+groups/launchpad-translators
155 [16:41] <dpm> as per the Structured policy
156 [16:42] <dpm> it gives you a good balance between openness and quality control:
157 [16:42] <dpm> only the team members of an established team will be able to translate your project
158 [16:42] <dpm> And for languages without a team it will allow everyone to translate, facilitating the barrier of entry to translators at the expense of QA
159 [16:42] <dpm> The other ends of the permissions spectrum are Open or Restricted
160 [16:42] <dpm> You can learn more about these here:
161 [16:42] <dpm> https://help.launchpad.net/Translations/YourProject/PermissionPolicies
162 [16:43] <dpm> It's the project maintainer's call, but I personally discourage them to use Open
163 [16:43] <dpm> Ok, we're nearly there, next step:
164 [16:43] <dpm> 3. Setting up what needs to be translated
165 [16:43] <dpm> You need to also tell Launchpad what needs to be translated. That's again quite easy. On the Translations tab again, choose the trunk series and specify your branch there
166 [16:43] <dpm> Direct link: https://launchpad.net/fooby/trunk/+linkbranch
167 [16:43] <dpm> Another easy one done :)
168 [16:44] <dpm> 4. Configuring imports and exports
169 [16:44] <dpm> That's for me the most interesting bit
170 [16:44] <dpm> The settings on this section basically enable Launchpad to do the work of managing translations for you
171 [16:44] <dpm> You can tell Launchpad to import your translation templates automatically whenever you do a commit in your branch
172 [16:44] <dpm> So you don't have to upload them manually
173 [16:44] <dpm> If you are migrating a project with existing translations, you can tell it to import them too
174 [16:44] <dpm> And finally, you can let Launchpad commit translations automatically to a branch of your choice
175 [16:45] <dpm> I find that just awesome
176 [16:45] <dpm> So for the imports, on the Launchpad page, on the "Import translations from branch" section:
177 [16:45] <dpm> I recommend choosing "Import template files" and then "Save settings"
178 [16:45] <dpm> For exports: look at the "Export translations to branch" section and then click on the "Choose exports branch" link
179 [16:45] <dpm> So that was it!
180 [16:46] <dpm> 4 easy steps that should not take you more than a few minutes to set up, and your app is ready for the world to translate!
181 [16:46] <dpm> Just a few final words:
182 [16:46] <dpm> Play with translations
183 [16:46] <dpm> ----------------------
184 [16:46] <dpm> As a developer, it might be interesting to see how translators do their work.
185 [16:46] <dpm> Exceptionally for this project (remember how I advised not to use Open permissions, tough :) I've set the translations permissions on the fooby project to Open
186 [16:47] <dpm> So you can submit translations online
187 [16:47] <dpm> and get a feel for the work that translators do
188 [16:47] <dpm> As a developer, it will give you an understanding on how they work. It is always interesting to get to know other workflows
189 [16:47] <dpm> and it's always good to have an insight on all areas of contribution related to your project
190 [16:47] <dpm> You can start translating fooby here:
191 [16:47] <dpm> https://translations.launchpad.net/fooby
192 [16:48] <dpm> So that was it really, it wasn't that hard, was it?
193 [16:48] <dpm> Let me give you a quick summary of what we've talked about and then take questions
194 [16:48] <dpm> Summary
195 [16:48] <dpm> -------
196 [16:49] <dpm> Most of the steps described here today you'll only need to do once, unless you need to change the settings. They were:
197 [16:49] <dpm> 1. Setting up code hosting (in case you hadn't already)
198 [16:49] <dpm> 2. Setting up translations in Launchpad
199 [16:49] <dpm> 2.1. Telling Launchpad that it's hosting your translations (https://translations.launchpad.net/fooby/+configure-translations)
200 [16:49] <dpm> 2.2. Configuring permissions: recommended -> Structured, Launchpad Translators (https://translations.launchpad.net/fooby/+settings)
201 [16:49] <dpm> 2.3. Setting up the translations branch (https://launchpad.net/fooby/trunk/+linkbranch)
202 [16:49] <dpm> 2.4. Configuring imports and exports (https://translations.launchpad.net/fooby/trunk/+translations-settings)
203 [16:49] <dpm> So really, once your project is set up for translation, the only things you'll have to remember are:
204 [16:49] <dpm> to update the template before a release,
205 [16:50] <dpm> announce to translators that they can start their work,
206 [16:50] <dpm> and merge the translations to your main branch.
207 [16:50] <dpm> If you are using the same branch for translation imports and exports, you won't even have to do that!
208 [16:50] <ClassBot> There are 10 minutes remaining in the current session.
209 [16:50] <dpm> ok, so we've got 10 minutes left - if you've got any questions, bring them on! :)
210 [16:50] <ClassBot> jsjgruber_natty_ asked: ​ How can an application bring up a translation for a particular local "on-demand"? Now get the spanish version, now french version?
211 [16:51] <dpm> I'm guessing you're asking this for test purposes
212 [16:52] <dpm> in normal usage, the application will automatically load the translation for the right locale defined in the system
213 [16:52] <dpm> so if my desktop's language is set to Catalan, the app, assuming gettext has been correctly initialised in the code, will automatically load the Catalan translation
214 [16:53] <dpm> but if you want an app to load another language, you can call the app on the command line specifying the language code, e.g.
215 [16:53] <dpm> $ LANGUAGE=de myapp
216 [16:54] <dpm> Running that command would load the German translation of myapp ('de' is the ISO code for German)
217 [16:54] <dpm> other questions?
218 [16:55] <ClassBot> matteonardi asked: how does translations get into users machines? Is there 1 (and only 1) package for each language? What if my application comes from a ppa?
219 [16:55] <ClassBot> There are 5 minutes remaining in the current session.
220 [16:56] <dpm> translations get distributed and installed along with the application. On the technical level, translations are .mo files, one for each available translation in your app
221 [16:56] <dpm> It does not matter if your application comes from a PPA
222 [16:57] <dpm> the PPA will contain all the necessary .mo files, which means the translations will be installed on the system of everyone who installs the PPA
223 [16:57] <dpm> ok, 3 minutes left, I can probably take another one if there is any
224 [16:58] <dpm> ok, if there aren't any, the only thing remaining is to thank everyone for listening in and asking interesting questions, and I'll see you next time!
MeetingLogs/appdevweek1109/MakingYourAppSpeakLanguageswithLaunchpadTranslations (last edited 2011-09-06 17:48:54 by ABTS-KK-Dynamic-249)