Merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/i18nctag into lp:ubuntu-ui-toolkit/staging

Proposed by Christian Dywan on 2015-02-02
Status: Merged
Approved by: Tim Peeters on 2015-02-05
Approved revision: 1398
Merged at revision: 1398
Proposed branch: lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/i18nctag
Merge into: lp:ubuntu-ui-toolkit/staging
Diff against target: 221 lines (+95/-5)
9 files modified
.bzrignore (+1/-0)
components.api (+7/-0)
modules/Ubuntu/Components/plugin/i18n.cpp (+40/-1)
modules/Ubuntu/Components/plugin/i18n.h (+3/-1)
po/update-pot.sh (+2/-1)
tests/unit/tst_i18n/po/en_US.po (+7/-0)
tests/unit/tst_i18n/src/LocalizedApp.qml (+15/-1)
tests/unit/tst_i18n/src/tst_i18n.cpp (+13/-0)
tests/unit/tst_i18n/tst_i18n.pro (+7/-1)
To merge this branch: bzr merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/i18nctag
Reviewer Review Type Date Requested Status
Tim Peeters 2015-02-02 Approve on 2015-02-05
PS Jenkins bot continuous-integration Approve on 2015-02-04
Review via email: mp+248260@code.launchpad.net

Commit Message

Implement and unit-test i18n.(c)tag

To post a comment you must log in.
Pete Woods (pete-woods) wrote :

Sorry to mess you around, but I think David wanted the function called noop as opposed to tag.

I don't have strong views either way, but it's probably worth checking which one to go for..

Christian Dywan (kalikiana) wrote :

No sweat, nothing is carved in stone yet, I went for this as I only saw the new suggestion after I wrote the unit tests for it :-)

Tim Peeters (tpeeters) wrote :

I will try to figure out the use case for this. It is not immediately clear to me. Perhaps this can be fixed by adding to the documentation of the methods?

1396. By Christian Dywan on 2015-02-03

Add QML example of UserMetrics to i18n.tag documentation

Tim Peeters (tpeeters) wrote :

please use function overloading of tag() for the context instead of tag() and ctag(), as we have in the API proposal for tr() in https://docs.google.com/a/canonical.com/document/d/1qDcfbu9aAj7uU9qzjXCOJn8zGexBnXwZCgO8pLDsO5M/edit#

We currently do have a ctr() implementation, but that should be deprecated as per https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1417680

1397. By Christian Dywan on 2015-02-03

There's no need for a ctag, tag can be overloaded'

Tim Peeters (tpeeters) wrote :

Below I copy&pasted parts of the IRC discussion that cleared up some issues for me:

<timp> in https://code.launchpad.net/~unity-team/music-app/infographics-translations/+merge/248251 why not use the string i18n.tr("Songs played today: ") + "<b>%1</b>"

<ahayzen> timp, RTL and LTR languages
<kalikiana> timp: never ever do string manipulation in context of localization, this is unrelated to tag, tr or plurals
<dpm> timp, as per the question: i18n.tr("Songs played today: ") + "<b>%1</b>" would for example break for RTL languages

-- and --

 <timp> why would i18n.dtr("metric", "Songs played today: %1") instead of i18n.tag("Songs played today: %1") not work?
<kalikiana> timp: because the string is displayed in the lockscreen and the language can be changed when the app isn't running
<timp> kalikiana: ah, so the string does not even exist in the list of translateable strings for the metrics?
<kalikiana> timp: the string is in the app's .mo files, and the domain is set in the metrics API
<timp> kalikiana: so the metrics somewhere call i18n.dtr("music-app", "Songs played today: %1")?
<kalikiana> timp: yes

review: Approve
Tim Peeters (tpeeters) wrote :

How do we ensure the tagged strings are added to the pot files? Is this automatic on launchpad? We did not add it to po/update-pot.sh (but ctr() functions which we have now are not in there either).

review: Needs Information
1398. By Christian Dywan on 2015-02-04

Add tag keyword to update-pot.sh

Tim Peeters (tpeeters) wrote :

Thanks, happroving.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2015-01-20 11:04:34 +0000
3+++ .bzrignore 2015-02-04 12:11:25 +0000
4@@ -16,3 +16,4 @@
5 tests/unit/tst_i18n/locale/en/LC_MESSAGES/*.mo
6 tests/launcher/launcher
7 build_paths.inc
8+tests/unit/tst_i18n/localizedApp/share/locale/en/LC_MESSAGES/localizedApp.mo
9
10=== modified file 'components.api'
11--- components.api 2015-01-26 22:19:11 +0000
12+++ components.api 2015-02-04 12:11:25 +0000
13@@ -1048,6 +1048,13 @@
14 Parameter { name: "domain"; type: "string" }
15 Parameter { name: "context"; type: "string" }
16 Parameter { name: "text"; type: "string" }
17+ Method {
18+ name: "tag"
19+ Parameter { name: "text"; type: "string" }
20+ Method {
21+ name: "tag"
22+ Parameter { name: "context"; type: "string" }
23+ Parameter { name: "text"; type: "string" }
24 name: "ULConditionalLayout"
25 prototype: "QObject"
26 exports: ["ConditionalLayout 0.1", "ConditionalLayout 1.0"]
27
28=== modified file 'modules/Ubuntu/Components/plugin/i18n.cpp'
29--- modules/Ubuntu/Components/plugin/i18n.cpp 2014-11-21 11:13:54 +0000
30+++ modules/Ubuntu/Components/plugin/i18n.cpp 2015-02-04 12:11:25 +0000
31@@ -1,5 +1,5 @@
32 /*
33- * Copyright 2012 Canonical Ltd.
34+ * Copyright 2012-2015 Canonical Ltd.
35 *
36 * This program is free software; you can redistribute it and/or modify
37 * it under the terms of the GNU Lesser General Public License as published by
38@@ -213,3 +213,42 @@
39 return QString::fromUtf8(C::g_dpgettext2(domain.toUtf8(), context.toUtf8(), text.toUtf8()));
40 }
41 }
42+
43+/*!
44+ * \qmlmethod string i18n::tag(string text)
45+ * Mark \a text for translation at a later point. Typically this allows an API
46+ * to take the original string and pass it to dtr (or dgettext).
47+ *
48+ * \qml
49+ * import QtQuick 2.0
50+ * import UserMetrics 0.1
51+ *
52+ * Metric {
53+ * name: "distance"
54+ * format: i18n.tag("Distance covered today: %1 km")
55+ * emptyFormat: i18n.tag("No running today")
56+ * domain: "runner.forest"
57+ * }
58+ * \endqml
59+ *
60+ * The strings tagged for localzation above are passed to the implementation
61+ * of UserMetrics verbatim, as well as the domain of the app. Display and
62+ * translation of the strings will happen in the lockscreen, where the same
63+ * strings will be passed to i18n.tr.
64+ */
65+QString UbuntuI18n::tag(const QString& text)
66+{
67+ return text;
68+}
69+
70+/*!
71+ * \qmlmethod string i18n::tag(string context, string text)
72+ * Mark \a text for translation at a later point. Typically this allows an API
73+ * to take the original string and pass it to dctr (or g_dpgettext2).
74+ * \a context is only visible to the translator and helps disambiguating for very short texts
75+ */
76+QString UbuntuI18n::tag(const QString& context, const QString& text)
77+{
78+ Q_UNUSED(context);
79+ return text;
80+}
81
82=== modified file 'modules/Ubuntu/Components/plugin/i18n.h'
83--- modules/Ubuntu/Components/plugin/i18n.h 2014-11-21 10:48:24 +0000
84+++ modules/Ubuntu/Components/plugin/i18n.h 2015-02-04 12:11:25 +0000
85@@ -1,5 +1,5 @@
86 /*
87- * Copyright 2012 Canonical Ltd.
88+ * Copyright 2012-2015 Canonical Ltd.
89 *
90 * This program is free software; you can redistribute it and/or modify
91 * it under the terms of the GNU Lesser General Public License as published by
92@@ -48,6 +48,8 @@
93 Q_INVOKABLE QString dtr(const QString& domain, const QString& singular, const QString& plural, int n);
94 Q_INVOKABLE QString ctr(const QString& context, const QString& text);
95 Q_INVOKABLE QString dctr(const QString& domain, const QString& context, const QString& text);
96+ Q_INVOKABLE QString tag(const QString& text);
97+ Q_INVOKABLE QString tag(const QString& context, const QString& text);
98
99 // getter
100 QString domain() const;
101
102=== modified file 'po/update-pot.sh'
103--- po/update-pot.sh 2014-09-01 17:02:40 +0000
104+++ po/update-pot.sh 2015-02-04 12:11:25 +0000
105@@ -50,7 +50,8 @@
106 --keyword=tr:1,2 \
107 --keyword=dtr:2 \
108 --keyword=dtr:2,3 \
109- --package-name $DOMAIN \
110+ --keyword=tag \
111+ --keyword=tag:1,2 \
112 --package-name $DOMAIN \
113 --copyright-holder "Canonical Ltd"
114
115
116=== modified file 'tests/unit/tst_i18n/po/en_US.po'
117--- tests/unit/tst_i18n/po/en_US.po 2014-11-21 10:48:24 +0000
118+++ tests/unit/tst_i18n/po/en_US.po 2015-02-04 12:11:25 +0000
119@@ -16,6 +16,9 @@
120 msgid "Count the kilometres"
121 msgstr "Count the clicks"
122
123+msgid "Count the kittens"
124+msgstr "Contar los gatitos"
125+
126 msgctxt "All Contacts"
127 msgid "All"
128 msgstr "Todos"
129@@ -23,3 +26,7 @@
130 msgctxt "All Calls"
131 msgid "All"
132 msgstr "Todas"
133+
134+msgctxt "All Cats"
135+msgid "All"
136+msgstr "Cada"
137
138=== modified file 'tests/unit/tst_i18n/src/LocalizedApp.qml'
139--- tests/unit/tst_i18n/src/LocalizedApp.qml 2014-11-21 10:48:24 +0000
140+++ tests/unit/tst_i18n/src/LocalizedApp.qml 2015-02-04 12:11:25 +0000
141@@ -32,10 +32,17 @@
142 text: i18n.tr('Count the kilometres')
143 width: units.gu(15)
144 }
145+ Button {
146+ id: button2
147+ objectName: 'button2'
148+ anchors.top: button.bottom
149+ text: i18n.tag('Count the kittens')
150+ width: units.gu(15)
151+ }
152 Label {
153 id: all1
154 objectName: 'all1'
155- anchors.top: button.bottom
156+ anchors.top: button2.bottom
157 anchors.horizontalCenter: button.horizontalCenter
158 text: i18n.ctr('All Contacts', 'All')
159 }
160@@ -46,5 +53,12 @@
161 anchors.horizontalCenter: all1.horizontalCenter
162 text: i18n.ctr('All Calls', 'All')
163 }
164+ Label {
165+ id: all3
166+ objectName: 'all3'
167+ anchors.top: all2.bottom
168+ anchors.horizontalCenter: all2.horizontalCenter
169+ text: i18n.tag('All Cats', 'All')
170+ }
171 }
172 }
173
174=== modified file 'tests/unit/tst_i18n/src/tst_i18n.cpp'
175--- tests/unit/tst_i18n/src/tst_i18n.cpp 2014-12-01 11:03:48 +0000
176+++ tests/unit/tst_i18n/src/tst_i18n.cpp 2015-02-04 12:11:25 +0000
177@@ -169,12 +169,25 @@
178 QCOMPARE(button->property("text").toString(), QString("Count the clicks"));
179 QCOMPARE(all1->property("text").toString(), QString("Todos"));
180 QCOMPARE(all2->property("text").toString(), QString("Todas"));
181+ // Only tagged, not actually translated
182+ QQuickItem* button2(testItem(page, "button2"));
183+ QVERIFY(button2);
184+ QCOMPARE(button2->property("text").toString(), QString("Count the kittens"));
185+ QQuickItem* all3(testItem(page, "all3"));
186+ QVERIFY(all3);
187+ QCOMPARE(all3->property("text").toString(), QString("All"));
188
189 // Translate in C++
190 QCOMPARE(i18n->dtr(i18n->domain(), QString("Welcome")), QString("Greets"));
191 QCOMPARE(i18n->tr(QString("Count the kilometres")), QString("Count the clicks"));
192 QCOMPARE(i18n->ctr(QString("All Contacts"), QString("All")), QString("Todos"));
193 QCOMPARE(i18n->ctr(QString("All Calls"), QString("All")), QString("Todas"));
194+ // Only tagged, not actually translated
195+ QCOMPARE(i18n->tag(QString("All kittens")), QString("All kittens"));
196+ QCOMPARE(i18n->tag(QString("All Cats"), QString("All")), QString("All"));
197+ // Sanity-check that the test strings would otherwise work and not no-op by accident
198+ QCOMPARE(i18n->tr(QString("Count the kittens")), QString("Contar los gatitos"));
199+ QCOMPARE(i18n->ctr(QString("All Cats"), QString("All")), QString("Cada"));
200 }
201 };
202
203
204=== modified file 'tests/unit/tst_i18n/tst_i18n.pro'
205--- tests/unit/tst_i18n/tst_i18n.pro 2014-11-25 09:58:33 +0000
206+++ tests/unit/tst_i18n/tst_i18n.pro 2015-02-04 12:11:25 +0000
207@@ -2,7 +2,13 @@
208 QT += gui
209 DEFINES += SRCDIR=\\\"$$PWD/\\\"
210
211-system(msgfmt po/en_US.po -o localizedApp/share/locale/en/LC_MESSAGES/localizedApp.mo)
212+DOMAIN = localizedApp
213+mo.target = mo
214+mo.commands = set -e;
215+mo.commands += echo Generating localization for $$DOMAIN;
216+mo.commands += msgfmt po/en_US.po -o $${DOMAIN}/share/locale/en/LC_MESSAGES/$${DOMAIN}.mo;
217+QMAKE_EXTRA_TARGETS += mo
218+PRE_TARGETDEPS += mo
219
220 SOURCES += \
221 src/tst_i18n.cpp

Subscribers

People subscribed via source and target branches