Merge lp:~aacid/ubuntu-ui-toolkit/i18n-RelativeDateTime into lp:ubuntu-ui-toolkit/staging
- i18n-RelativeDateTime
- Merge into staging
Status: | Merged |
---|---|
Approved by: | Zsombor Egri |
Approved revision: | 1611 |
Merged at revision: | 1604 |
Proposed branch: | lp:~aacid/ubuntu-ui-toolkit/i18n-RelativeDateTime |
Merge into: | lp:ubuntu-ui-toolkit/staging |
Prerequisite: | lp:~aacid/ubuntu-ui-toolkit/LiveTimer |
Diff against target: |
679 lines (+512/-24) 12 files modified
components.api (+1/-0) src/Ubuntu/Components/plugin/i18n.cpp (+74/-0) src/Ubuntu/Components/plugin/i18n.h (+1/-0) src/Ubuntu/Components/plugin/timeutils_p.h (+24/-0) tests/unit/tst_i18n/tst_i18n.pro (+3/-18) tests/unit/tst_i18n/tst_i18n_LocalizedApp/src/LocalizedApp.qml (+43/-1) tests/unit/tst_i18n/tst_i18n_LocalizedApp/src/tst_i18n_LocalizedApp.cpp (+5/-5) tests/unit/tst_i18n/tst_i18n_LocalizedApp/tst_i18n_LocalizedApp.pro (+17/-0) tests/unit/tst_i18n/tst_i18n_RelativeTime/po/en_US.po (+54/-0) tests/unit/tst_i18n/tst_i18n_RelativeTime/src/RelativeTime.qml (+71/-0) tests/unit/tst_i18n/tst_i18n_RelativeTime/src/tst_i18n_RelativeTime.cpp (+202/-0) tests/unit/tst_i18n/tst_i18n_RelativeTime/tst_i18n_RelativeTime.pro (+17/-0) |
To merge this branch: | bzr merge lp:~aacid/ubuntu-ui-toolkit/i18n-RelativeDateTime |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lukáš Tinkl (community) | code-review | Needs Fixing | |
PS Jenkins bot | continuous-integration | Approve | |
Zsombor Egri | Approve | ||
Review via email: mp+267788@code.launchpad.net |
Commit message
Added relative date time i18n
Description of the change
Added relative date time i18n
- 1608. By Nick Dedekind
-
i18n.relativeDa
teTime - 1609. By Nick Dedekind
-
review comments
- 1610. By Nick Dedekind
-
split relative time i18n
- 1611. By Nick Dedekind
-
split relative time i18n from localizedApp
Albert Astals Cid (aacid) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1213
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Lukáš Tinkl (lukas-kde) wrote : | # |
One small optimization comment
Preview Diff
1 | === modified file 'components.api' |
2 | --- components.api 2015-08-12 10:11:43 +0000 |
3 | +++ components.api 2015-08-12 10:11:44 +0000 |
4 | @@ -1405,3 +1405,4 @@ |
5 | function string dctr(string domain, string context, string text) |
6 | function string tag(string text) |
7 | function string tag(string context, string text) |
8 | + function string relativeDateTime(QDateTime datetime) |
9 | |
10 | === modified file 'src/Ubuntu/Components/plugin/i18n.cpp' |
11 | --- src/Ubuntu/Components/plugin/i18n.cpp 2015-03-03 13:47:48 +0000 |
12 | +++ src/Ubuntu/Components/plugin/i18n.cpp 2015-08-12 10:11:44 +0000 |
13 | @@ -17,6 +17,7 @@ |
14 | */ |
15 | |
16 | #include "i18n.h" |
17 | +#include "timeutils_p.h" |
18 | #include <QtCore/QDir> |
19 | |
20 | namespace C { |
21 | @@ -252,3 +253,76 @@ |
22 | Q_UNUSED(context); |
23 | return text; |
24 | } |
25 | +/*! |
26 | + * \qmlmethod string i18n::relativeDateTime(datetime dateTime) |
27 | + * Translate a datetime based on proximity to current time. |
28 | + */ |
29 | +QString UbuntuI18n::relativeDateTime(const QDateTime& datetime) |
30 | +{ |
31 | + QDateTime relativeTo(QDateTime::currentDateTime()); |
32 | + const date_proximity_t prox = getDateProximity(relativeTo, datetime); |
33 | + |
34 | + switch (prox) { |
35 | + case DATE_PROXIMITY_NOW: |
36 | + /* TRANSLATORS: Time based "this is happening/happened now" */ |
37 | + return dtr("ubuntu-ui-toolkit", "Now"); |
38 | + |
39 | + case DATE_PROXIMITY_HOUR: |
40 | + { |
41 | + qint64 diff = datetime.toMSecsSinceEpoch() - relativeTo.toMSecsSinceEpoch(); |
42 | + qint64 minutes = qRound(float(diff) / 60000); |
43 | + if (minutes < 0) { |
44 | + return dtr("ubuntu-ui-toolkit", "%1 minute ago", "%1 minutes ago", qAbs(minutes)).arg(qAbs(minutes)); |
45 | + } |
46 | + return dtr("ubuntu-ui-toolkit", "%1 minute", "%1 minutes", minutes).arg(minutes); |
47 | + } |
48 | + |
49 | + case DATE_PROXIMITY_TODAY: |
50 | + /* en_US example: "1:00 PM" */ |
51 | + /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by |
52 | + https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ |
53 | + return datetime.toString(isLocale12h() ? dtr("ubuntu-ui-toolkit", "h:mm ap"): |
54 | + /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by |
55 | + https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ |
56 | + dtr("ubuntu-ui-toolkit", "HH:mm")); |
57 | + |
58 | + case DATE_PROXIMITY_YESTERDAY: |
59 | + /* en_US example: "Yesterday 13:00" */ |
60 | + /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by |
61 | + https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ |
62 | + return datetime.toString(isLocale12h() ? dtr("ubuntu-ui-toolkit", "'Yesterday\u2003'h:mm ap") : |
63 | + /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by |
64 | + https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ |
65 | + dtr("ubuntu-ui-toolkit", "'Yesterday\u2003'HH:mm")); |
66 | + |
67 | + case DATE_PROXIMITY_TOMORROW: |
68 | + /* en_US example: "Tomorrow 1:00 PM" */ |
69 | + /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by |
70 | + https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ |
71 | + return datetime.toString(isLocale12h() ? dtr("ubuntu-ui-toolkit", "'Tomorrow\u2003'h:mm ap") : |
72 | + /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by |
73 | + https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ |
74 | + dtr("ubuntu-ui-toolkit", "'Tomorrow\u2003'HH:mm")); |
75 | + |
76 | + case DATE_PROXIMITY_LAST_WEEK: |
77 | + case DATE_PROXIMITY_NEXT_WEEK: |
78 | + /* en_US example: "Fri 1:00 PM" */ |
79 | + /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by |
80 | + https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ |
81 | + return datetime.toString(isLocale12h() ? dtr("ubuntu-ui-toolkit", "ddd'\u2003'h:mm ap") : |
82 | + /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by |
83 | + https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ |
84 | + dtr("ubuntu-ui-toolkit", "ddd'\u2003'HH:mm")); |
85 | + |
86 | + case DATE_PROXIMITY_FAR_BACK: |
87 | + case DATE_PROXIMITY_FAR_FORWARD: |
88 | + default: |
89 | + /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by |
90 | + https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ |
91 | + return datetime.toString(isLocale12h() ? dtr("ubuntu-ui-toolkit", "ddd d MMM'\u2003'h:mm ap") : |
92 | + /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by |
93 | + https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ |
94 | + dtr("ubuntu-ui-toolkit", "ddd d MMM'\u2003'HH:mm")); |
95 | + } |
96 | + return datetime.toString(Qt::DefaultLocaleShortDate); |
97 | +} |
98 | |
99 | === modified file 'src/Ubuntu/Components/plugin/i18n.h' |
100 | --- src/Ubuntu/Components/plugin/i18n.h 2015-02-03 18:11:32 +0000 |
101 | +++ src/Ubuntu/Components/plugin/i18n.h 2015-08-12 10:11:44 +0000 |
102 | @@ -50,6 +50,7 @@ |
103 | Q_INVOKABLE QString dctr(const QString& domain, const QString& context, const QString& text); |
104 | Q_INVOKABLE QString tag(const QString& text); |
105 | Q_INVOKABLE QString tag(const QString& context, const QString& text); |
106 | + Q_INVOKABLE QString relativeDateTime(const QDateTime& datetime); |
107 | |
108 | // getter |
109 | QString domain() const; |
110 | |
111 | === modified file 'src/Ubuntu/Components/plugin/timeutils_p.h' |
112 | --- src/Ubuntu/Components/plugin/timeutils_p.h 2015-08-12 10:11:43 +0000 |
113 | +++ src/Ubuntu/Components/plugin/timeutils_p.h 2015-08-12 10:11:44 +0000 |
114 | @@ -20,9 +20,33 @@ |
115 | #include "livetimer.h" |
116 | |
117 | #include <QDateTime> |
118 | +#include <QLocale> |
119 | #include <QObject> |
120 | #include <QTimer> |
121 | |
122 | +/* Check the system locale setting to see if the format is 24-hour |
123 | + time or 12-hour time */ |
124 | +inline bool isLocale12h(void) |
125 | +{ |
126 | + QString strTimeFormat = QLocale::system().timeFormat(); |
127 | + QStringList includes; includes << "AP"; includes << "ap"; |
128 | + QStringList excludes; excludes << "H"; excludes << "HH"; |
129 | + |
130 | + Q_FOREACH(const QString& exclude, excludes) { |
131 | + if (strTimeFormat.contains(exclude)) { |
132 | + return false; |
133 | + } |
134 | + } |
135 | + |
136 | + Q_FOREACH(const QString& include, includes) { |
137 | + if (strTimeFormat.contains(include)) { |
138 | + return true; |
139 | + } |
140 | + } |
141 | + |
142 | + return false; |
143 | +} |
144 | + |
145 | typedef enum |
146 | { |
147 | DATE_PROXIMITY_NOW, |
148 | |
149 | === modified file 'tests/unit/tst_i18n/tst_i18n.pro' |
150 | --- tests/unit/tst_i18n/tst_i18n.pro 2015-05-18 09:53:55 +0000 |
151 | +++ tests/unit/tst_i18n/tst_i18n.pro 2015-08-12 10:11:44 +0000 |
152 | @@ -1,18 +1,3 @@ |
153 | -include(../test-include.pri) |
154 | -QT += gui |
155 | -DEFINES += SRCDIR=\\\"$$PWD/\\\" |
156 | - |
157 | -DOMAIN = localizedApp |
158 | -mo.target = mo |
159 | -mo.commands = set -e; |
160 | -mo.commands += echo Generating localization for $$DOMAIN; |
161 | -mo.commands += mkdir -p $${DOMAIN}/share/locale/en/LC_MESSAGES; |
162 | -mo.commands += msgfmt $$PWD/po/en_US.po -o $${DOMAIN}/share/locale/en/LC_MESSAGES/$${DOMAIN}.mo; |
163 | -QMAKE_EXTRA_TARGETS += mo |
164 | -PRE_TARGETDEPS += mo |
165 | - |
166 | -SOURCES += \ |
167 | - src/tst_i18n.cpp |
168 | - |
169 | -OTHER_FILES += \ |
170 | - src/LocalizedApp.qml |
171 | +TEMPLATE = subdirs |
172 | +SUBDIRS += tst_i18n_LocalizedApp |
173 | +SUBDIRS += tst_i18n_RelativeTime |
174 | |
175 | === added directory 'tests/unit/tst_i18n/tst_i18n_LocalizedApp' |
176 | === added file 'tests/unit/tst_i18n/tst_i18n_LocalizedApp.o' |
177 | Binary files tests/unit/tst_i18n/tst_i18n_LocalizedApp.o 1970-01-01 00:00:00 +0000 and tests/unit/tst_i18n/tst_i18n_LocalizedApp.o 2015-08-12 10:11:44 +0000 differ |
178 | === renamed directory 'tests/unit/tst_i18n/localizedApp' => 'tests/unit/tst_i18n/tst_i18n_LocalizedApp/localizedApp' |
179 | === renamed directory 'tests/unit/tst_i18n/po' => 'tests/unit/tst_i18n/tst_i18n_LocalizedApp/po' |
180 | === renamed directory 'tests/unit/tst_i18n/src' => 'tests/unit/tst_i18n/tst_i18n_LocalizedApp/src' |
181 | === modified file 'tests/unit/tst_i18n/tst_i18n_LocalizedApp/src/LocalizedApp.qml' |
182 | --- tests/unit/tst_i18n/src/LocalizedApp.qml 2015-03-03 13:20:06 +0000 |
183 | +++ tests/unit/tst_i18n/tst_i18n_LocalizedApp/src/LocalizedApp.qml 2015-08-12 10:11:44 +0000 |
184 | @@ -28,7 +28,7 @@ |
185 | Button { |
186 | id: button |
187 | objectName: 'button' |
188 | - anchors.centerIn: parent |
189 | + anchors.horizontalCenter: parent.horizontalCenter |
190 | text: i18n.tr('Count the kilometres') |
191 | width: units.gu(15) |
192 | } |
193 | @@ -60,5 +60,47 @@ |
194 | anchors.horizontalCenter: all2.horizontalCenter |
195 | text: i18n.tag('All Cats', 'All') |
196 | } |
197 | + Label { |
198 | + id: timeNow |
199 | + objectName: 'timeNow' |
200 | + anchors.top: all3.bottom |
201 | + anchors.horizontalCenter: all3.horizontalCenter |
202 | + text: i18n.relativeDateTime(new Date()) |
203 | + } |
204 | + Label { |
205 | + id: timeMinuteBefore |
206 | + objectName: 'timeMinuteBefore' |
207 | + anchors.top: timeNow.bottom |
208 | + anchors.horizontalCenter: timeNow.horizontalCenter |
209 | + text: i18n.relativeDateTime(new Date(new Date().getTime() - 60000)) |
210 | + } |
211 | + Label { |
212 | + id: timeMinuteAfter |
213 | + objectName: 'timeMinuteAfter' |
214 | + anchors.top: timeMinuteBefore.bottom |
215 | + anchors.horizontalCenter: timeMinuteBefore.horizontalCenter |
216 | + text: i18n.relativeDateTime(new Date(new Date().getTime() + 60000)) |
217 | + } |
218 | + Label { |
219 | + id: tenMinutesBefore |
220 | + objectName: 'tenMinutesBefore' |
221 | + anchors.top: timeMinuteAfter.bottom |
222 | + anchors.horizontalCenter: timeMinuteAfter.horizontalCenter |
223 | + text: i18n.relativeDateTime(new Date(new Date().getTime() - 600000)) |
224 | + } |
225 | + Label { |
226 | + id: tenMinutesAfter |
227 | + objectName: 'tenMinutesAfter' |
228 | + anchors.top: tenMinutesBefore.bottom |
229 | + anchors.horizontalCenter: tenMinutesBefore.horizontalCenter |
230 | + text: i18n.relativeDateTime(new Date(new Date().getTime() + 600000)) |
231 | + } |
232 | + Label { |
233 | + id: timeFarAway |
234 | + objectName: 'timeFarAway' |
235 | + anchors.top: tenMinutesAfter.bottom |
236 | + anchors.horizontalCenter: tenMinutesAfter.horizontalCenter |
237 | + text: i18n.relativeDateTime(new Date(2000, 0, 1, 0, 0, 0, 0)) |
238 | + } |
239 | } |
240 | } |
241 | |
242 | === renamed file 'tests/unit/tst_i18n/src/tst_i18n.cpp' => 'tests/unit/tst_i18n/tst_i18n_LocalizedApp/src/tst_i18n_LocalizedApp.cpp' |
243 | --- tests/unit/tst_i18n/src/tst_i18n.cpp 2015-02-03 18:11:32 +0000 |
244 | +++ tests/unit/tst_i18n/tst_i18n_LocalizedApp/src/tst_i18n_LocalizedApp.cpp 2015-08-12 10:11:44 +0000 |
245 | @@ -39,7 +39,7 @@ |
246 | #include "ucunits.h" |
247 | #include "i18n.h" |
248 | |
249 | -class tst_I18n : public QObject |
250 | +class tst_I18n_LocalizedApp : public QObject |
251 | { |
252 | Q_OBJECT |
253 | |
254 | @@ -47,7 +47,7 @@ |
255 | QQuickView *view; |
256 | |
257 | public: |
258 | - tst_I18n() : |
259 | + tst_I18n_LocalizedApp() : |
260 | view(0) |
261 | { |
262 | } |
263 | @@ -191,7 +191,7 @@ |
264 | } |
265 | }; |
266 | |
267 | -// The C++ equivalent of QTEST_MAIN(tst_I18n) with added initialization |
268 | +// The C++ equivalent of QTEST_MAIN(tst_I18n_LocalizedApp) with added initialization |
269 | int main(int argc, char *argv[]) |
270 | { |
271 | // LC_ALL would fail the test case; it must be unset before execution |
272 | @@ -199,8 +199,8 @@ |
273 | |
274 | QGuiApplication app(argc, argv); |
275 | app.setAttribute(Qt::AA_Use96Dpi, true); |
276 | - tst_I18n* testObject = new tst_I18n(); |
277 | + tst_I18n_LocalizedApp* testObject = new tst_I18n_LocalizedApp(); |
278 | return QTest::qExec(static_cast<QObject*>(testObject), argc, argv); |
279 | } |
280 | |
281 | -#include "tst_i18n.moc" |
282 | +#include "tst_i18n_LocalizedApp.moc" |
283 | |
284 | === added file 'tests/unit/tst_i18n/tst_i18n_LocalizedApp/tst_i18n_LocalizedApp.pro' |
285 | --- tests/unit/tst_i18n/tst_i18n_LocalizedApp/tst_i18n_LocalizedApp.pro 1970-01-01 00:00:00 +0000 |
286 | +++ tests/unit/tst_i18n/tst_i18n_LocalizedApp/tst_i18n_LocalizedApp.pro 2015-08-12 10:11:44 +0000 |
287 | @@ -0,0 +1,17 @@ |
288 | +include(../../test-include.pri) |
289 | +QT += gui |
290 | +DEFINES += SRCDIR=\\\"$$PWD/\\\" |
291 | + |
292 | +DOMAIN = localizedApp |
293 | +mo.target = mo |
294 | +mo.commands = set -e; |
295 | +mo.commands += echo Generating localization; |
296 | +mo.commands += msgfmt po/en_US.po -o $${DOMAIN}/share/locale/en/LC_MESSAGES/$${DOMAIN}.mo; |
297 | +QMAKE_EXTRA_TARGETS += mo |
298 | +PRE_TARGETDEPS += mo |
299 | + |
300 | +SOURCES += \ |
301 | + src/tst_i18n_LocalizedApp.cpp |
302 | + |
303 | +OTHER_FILES += \ |
304 | + src/LocalizedApp.qml |
305 | |
306 | === added directory 'tests/unit/tst_i18n/tst_i18n_RelativeTime' |
307 | === added file 'tests/unit/tst_i18n/tst_i18n_RelativeTime.o' |
308 | Binary files tests/unit/tst_i18n/tst_i18n_RelativeTime.o 1970-01-01 00:00:00 +0000 and tests/unit/tst_i18n/tst_i18n_RelativeTime.o 2015-08-12 10:11:44 +0000 differ |
309 | === added directory 'tests/unit/tst_i18n/tst_i18n_RelativeTime/po' |
310 | === added file 'tests/unit/tst_i18n/tst_i18n_RelativeTime/po/en_US.po' |
311 | --- tests/unit/tst_i18n/tst_i18n_RelativeTime/po/en_US.po 1970-01-01 00:00:00 +0000 |
312 | +++ tests/unit/tst_i18n/tst_i18n_RelativeTime/po/en_US.po 2015-08-12 10:11:44 +0000 |
313 | @@ -0,0 +1,54 @@ |
314 | +msgid "" |
315 | +msgstr "" |
316 | +"Project-Id-Version: \n" |
317 | +"POT-Creation-Date: \n" |
318 | +"PO-Revision-Date: \n" |
319 | +"Last-Translator: Christian Dywan <christian.dywan@canonical.com>\n" |
320 | +"Language-Team: \n" |
321 | +"Language: \n" |
322 | +"MIME-Version: 1.0\n" |
323 | +"Content-Type: text/plain; charset=iso-8859-1\n" |
324 | +"Content-Transfer-Encoding: 8bit\n" |
325 | + |
326 | +msgid "Now" |
327 | +msgstr "tr:Now" |
328 | + |
329 | +msgid "%1 minute ago" |
330 | +msgid_plural "%1 minutes ago" |
331 | +msgstr[0] "tr:%1 minute ago" |
332 | +msgstr[1] "tr:%1 minutes ago" |
333 | + |
334 | +msgid "%1 minute" |
335 | +msgid_plural "%1 minutes" |
336 | +msgstr[0] "tr:%1 minute" |
337 | +msgstr[1] "tr:%1 minutes" |
338 | + |
339 | +msgid "h:mm ap" |
340 | +msgstr "'tr:'h:mm ap" |
341 | + |
342 | +msgid "HH:mm" |
343 | +msgstr "'tr:'HH:mm" |
344 | + |
345 | +msgid "'Yesterday 'h:mm ap" |
346 | +msgstr "'tr:Yesterday 'h:mm ap" |
347 | + |
348 | +msgid "'Yesterday 'HH:mm" |
349 | +msgstr "'tr:Yesterday 'HH:mm" |
350 | + |
351 | +msgid "'Tomorrow 'h:mm ap" |
352 | +msgstr "'tr:Tomorrow 'h:mm ap" |
353 | + |
354 | +msgid "'Tomorrow 'HH:mm" |
355 | +msgstr "'tr:Tomorrow 'HH:mm" |
356 | + |
357 | +msgid "ddd' 'h:mm ap" |
358 | +msgstr "'tr:'ddd' 'h:mm ap" |
359 | + |
360 | +msgid "ddd' 'HH:mm" |
361 | +msgstr "'tr:'ddd' 'HH:mm" |
362 | + |
363 | +msgid "ddd d MMM' 'h:mm ap" |
364 | +msgstr "'tr:FarAway'" |
365 | + |
366 | +msgid "ddd d MMM' 'HH:mm" |
367 | +msgstr "'tr:FarAway'" |
368 | |
369 | === added directory 'tests/unit/tst_i18n/tst_i18n_RelativeTime/src' |
370 | === added file 'tests/unit/tst_i18n/tst_i18n_RelativeTime/src/RelativeTime.qml' |
371 | --- tests/unit/tst_i18n/tst_i18n_RelativeTime/src/RelativeTime.qml 1970-01-01 00:00:00 +0000 |
372 | +++ tests/unit/tst_i18n/tst_i18n_RelativeTime/src/RelativeTime.qml 2015-08-12 10:11:44 +0000 |
373 | @@ -0,0 +1,71 @@ |
374 | +/* |
375 | + * Copyright 2013 Canonical Ltd. |
376 | + * |
377 | + * This program is free software; you can redistribute it and/or modify |
378 | + * it under the terms of the GNU Lesser General Public License as published by |
379 | + * the Free Software Foundation; version 3. |
380 | + * |
381 | + * This program is distributed in the hope that it will be useful, |
382 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
383 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
384 | + * GNU Lesser General Public License for more details. |
385 | + * |
386 | + * You should have received a copy of the GNU Lesser General Public License |
387 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
388 | + */ |
389 | + |
390 | +import QtQuick 2.0 |
391 | +import Ubuntu.Components 1.3 |
392 | + |
393 | +MainView { |
394 | + width: units.gu(48) |
395 | + height: units.gu(60) |
396 | + applicationName: "ubuntu-ui-toolkit" |
397 | + |
398 | + Page { |
399 | + objectName: 'page' |
400 | + |
401 | + Label { |
402 | + id: timeNow |
403 | + objectName: 'timeNow' |
404 | + anchors.top: parent.top |
405 | + anchors.horizontalCenter: parent.horizontalCenter |
406 | + text: i18n.relativeDateTime(new Date()) |
407 | + } |
408 | + Label { |
409 | + id: timeMinuteBefore |
410 | + objectName: 'timeMinuteBefore' |
411 | + anchors.top: timeNow.bottom |
412 | + anchors.horizontalCenter: timeNow.horizontalCenter |
413 | + text: i18n.relativeDateTime(new Date(new Date().getTime() - 60000)) |
414 | + } |
415 | + Label { |
416 | + id: timeMinuteAfter |
417 | + objectName: 'timeMinuteAfter' |
418 | + anchors.top: timeMinuteBefore.bottom |
419 | + anchors.horizontalCenter: timeMinuteBefore.horizontalCenter |
420 | + text: i18n.relativeDateTime(new Date(new Date().getTime() + 60000)) |
421 | + } |
422 | + Label { |
423 | + id: tenMinutesBefore |
424 | + objectName: 'tenMinutesBefore' |
425 | + anchors.top: timeMinuteAfter.bottom |
426 | + anchors.horizontalCenter: timeMinuteAfter.horizontalCenter |
427 | + text: i18n.relativeDateTime(new Date(new Date().getTime() - 600000)) |
428 | + } |
429 | + Label { |
430 | + id: tenMinutesAfter |
431 | + objectName: 'tenMinutesAfter' |
432 | + anchors.top: tenMinutesBefore.bottom |
433 | + anchors.horizontalCenter: tenMinutesBefore.horizontalCenter |
434 | + text: i18n.relativeDateTime(new Date(new Date().getTime() + 600000)) |
435 | + } |
436 | + Label { |
437 | + id: timeFarAway |
438 | + objectName: 'timeFarAway' |
439 | + anchors.top: tenMinutesAfter.bottom |
440 | + anchors.horizontalCenter: tenMinutesAfter.horizontalCenter |
441 | + text: i18n.relativeDateTime(new Date(2000, 0, 1, 0, 0, 0, 0)) |
442 | + } |
443 | + } |
444 | +} |
445 | |
446 | === added file 'tests/unit/tst_i18n/tst_i18n_RelativeTime/src/tst_i18n_RelativeTime.cpp' |
447 | --- tests/unit/tst_i18n/tst_i18n_RelativeTime/src/tst_i18n_RelativeTime.cpp 1970-01-01 00:00:00 +0000 |
448 | +++ tests/unit/tst_i18n/tst_i18n_RelativeTime/src/tst_i18n_RelativeTime.cpp 2015-08-12 10:11:44 +0000 |
449 | @@ -0,0 +1,202 @@ |
450 | + |
451 | +/* |
452 | + * Copyright 2015 Canonical Ltd. |
453 | + * |
454 | + * This program is free software; you can redistribute it and/or modify |
455 | + * it under the terms of the GNU Lesser General Public License as published by |
456 | + * the Free Software Foundation; version 3. |
457 | + * |
458 | + * This program is distributed in the hope that it will be useful, |
459 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
460 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
461 | + * GNU Lesser General Public License for more details. |
462 | + * |
463 | + * You should have received a copy of the GNU Lesser General Public License |
464 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
465 | + * |
466 | + * Author: Nick Dedekind <nick.dedekind@gmail.com> |
467 | + */ |
468 | + |
469 | +#include <QtCore/QString> |
470 | +#include <QtCore/QTextCodec> |
471 | +#include <QtCore/QStandardPaths> |
472 | +#include <QtCore/QDir> |
473 | +#include <QtCore/QProcessEnvironment> |
474 | +#include <QtTest/QTest> |
475 | +#include <QtTest/QSignalSpy> |
476 | +#include <QtCore/QCoreApplication> |
477 | +#include <QtQml/QQmlEngine> |
478 | +#include <QtQuick/QQuickView> |
479 | +#include <QtQuick/QQuickItem> |
480 | +#include <QtCore/QThread> |
481 | +#include <QtCore/QFileInfo> |
482 | +#include <QtCore/QDir> |
483 | +#include <QtTest/qtest_gui.h> |
484 | + |
485 | +namespace C { |
486 | +#include <libintl.h> |
487 | +} |
488 | + |
489 | +#include "ucunits.h" |
490 | +#include "i18n.h" |
491 | + |
492 | +class tst_I18n_RelativeTime : public QObject |
493 | +{ |
494 | + Q_OBJECT |
495 | + |
496 | +private: |
497 | + QQuickView *view; |
498 | + |
499 | +public: |
500 | + tst_I18n_RelativeTime() : |
501 | + view(0) |
502 | + { |
503 | + } |
504 | + |
505 | + QQuickItem *loadTest(const QString &document) |
506 | + { |
507 | + // load the document |
508 | + view->setSource(QUrl::fromLocalFile(document)); |
509 | + QTest::waitForEvents(); |
510 | + |
511 | + return view->rootObject(); |
512 | + } |
513 | + |
514 | + QQuickItem *testItem(QQuickItem *that, const QString &identifier) |
515 | + { |
516 | + if (that->property(identifier.toLocal8Bit()).isValid()) |
517 | + return that->property(identifier.toLocal8Bit()).value<QQuickItem*>(); |
518 | + |
519 | + QList<QQuickItem*> children = that->findChildren<QQuickItem*>(identifier); |
520 | + return (children.count() > 0) ? children[0] : 0; |
521 | + } |
522 | + |
523 | +private Q_SLOTS: |
524 | + |
525 | + void initTestCase() |
526 | + { |
527 | + // Set test locale folder in the environment |
528 | + // Using setenv because QProcessEnvironment ignores changes |
529 | + QString testAppDir(QDir::currentPath() + "/ubuntu-ui-toolkit"); |
530 | + setenv("APP_DIR", testAppDir.toUtf8(), 1); |
531 | + |
532 | + // Verify that we set it correctly |
533 | + QVERIFY(QFileInfo(testAppDir + "/share/locale/en/LC_MESSAGES/ubuntu-ui-toolkit.mo").exists()); |
534 | + |
535 | + QString modules(UBUNTU_QML_IMPORT_PATH); |
536 | + QVERIFY(QDir(modules).exists()); |
537 | + |
538 | + view = new QQuickView; |
539 | + QQmlEngine *quickEngine = view->engine(); |
540 | + |
541 | + view->setGeometry(0,0, UCUnits::instance().gu(40), UCUnits::instance().gu(30)); |
542 | + //add modules folder so we have access to the plugin from QML |
543 | + QStringList imports = quickEngine->importPathList(); |
544 | + imports.prepend(QDir(modules).absolutePath()); |
545 | + quickEngine->setImportPathList(imports); |
546 | + } |
547 | + |
548 | + void cleanupTestCase() |
549 | + { |
550 | + delete view; |
551 | + } |
552 | + |
553 | + void testCase_RelativeTime() |
554 | + { |
555 | + UbuntuI18n* i18n = &UbuntuI18n::instance(); |
556 | + // By default no domain is set |
557 | + QCOMPARE(i18n->domain(), QString("")); |
558 | + |
559 | + // Start out with no localization |
560 | + i18n->setLanguage("C"); |
561 | + // Load the app which should pick up the locale we prepared |
562 | + QQuickItem *root = loadTest("src/RelativeTime.qml"); |
563 | + QVERIFY(root); |
564 | + QQuickItem *mainView = root; |
565 | + |
566 | + // There no translation happens |
567 | + QQuickItem* page(testItem(mainView, "page")); |
568 | + QVERIFY(page); |
569 | + |
570 | + QQuickItem* timeFarAway(testItem(page, "timeFarAway")); |
571 | + QVERIFY(timeFarAway); |
572 | + QCOMPARE(timeFarAway->property("text").toString(), |
573 | + QDateTime(QDate(2000,1,1), QTime(0,0,0,0)).toString("ddd d MMM'\u2003'HH:mm")); |
574 | + QQuickItem* timeNow(testItem(page, "timeNow")); |
575 | + QVERIFY(timeNow); |
576 | + QCOMPARE(timeNow->property("text").toString(), QString("Now")); |
577 | + QQuickItem* timeMinuteBefore(testItem(page, "timeMinuteBefore")); |
578 | + QVERIFY(timeMinuteBefore); |
579 | + QCOMPARE(timeMinuteBefore->property("text").toString(), QString("1 minute ago")); |
580 | + QQuickItem* timeMinuteAfter(testItem(page, "timeMinuteAfter")); |
581 | + QVERIFY(timeMinuteAfter); |
582 | + QCOMPARE(timeMinuteAfter->property("text").toString(), QString("1 minute")); |
583 | + QQuickItem* tenMinutesBefore(testItem(page, "tenMinutesBefore")); |
584 | + QVERIFY(tenMinutesBefore); |
585 | + QCOMPARE(tenMinutesBefore->property("text").toString(), QString("10 minutes ago")); |
586 | + QQuickItem* tenMinutesAfter(testItem(page, "tenMinutesAfter")); |
587 | + QVERIFY(tenMinutesAfter); |
588 | + QCOMPARE(tenMinutesAfter->property("text").toString(), QString("10 minutes")); |
589 | + |
590 | + // There no translation happens in C++ either |
591 | + QCOMPARE(i18n->relativeDateTime(QDateTime::currentDateTime()), QString("Now")); |
592 | + QCOMPARE(i18n->relativeDateTime(QDateTime(QDate(2000,1,1), QTime(0,0,0,0))), |
593 | + QDateTime(QDate(2000,1,1), QTime(0,0,0,0)).toString("ddd d MMM'\u2003'HH:mm")); |
594 | + QCOMPARE(i18n->relativeDateTime(QDateTime::currentDateTime().addSecs(-60)), QString("1 minute ago")); |
595 | + QCOMPARE(i18n->relativeDateTime(QDateTime::currentDateTime().addSecs(60)), QString("1 minute")); |
596 | + QCOMPARE(i18n->relativeDateTime(QDateTime::currentDateTime().addSecs(-600)), QString("10 minutes ago")); |
597 | + QCOMPARE(i18n->relativeDateTime(QDateTime::currentDateTime().addSecs(600)), QString("10 minutes")); |
598 | + |
599 | + // Was the locale folder detected and set? |
600 | + QString boundDomain(C::bindtextdomain(i18n->domain().toUtf8(), ((const char*)0))); |
601 | + QString testAppDir(QDir::currentPath() + "/ubuntu-ui-toolkit"); |
602 | + QString expectedLocalePath(QDir(testAppDir).filePath("share/locale")); |
603 | + QCOMPARE(boundDomain, expectedLocalePath); |
604 | + // Is the domain gettext uses correct? |
605 | + QString gettextDomain(C::textdomain(((const char*)0))); |
606 | + QCOMPARE(gettextDomain, i18n->domain()); |
607 | + // Is the compiled en_US message catalog in the right location? |
608 | + QString messageCatalog(boundDomain + "/en/LC_MESSAGES/ubuntu-ui-toolkit.mo"); |
609 | + QVERIFY(QFileInfo(messageCatalog).exists()); |
610 | + |
611 | + // Check if system has en_US locale, otherwise gettext won't work |
612 | + QProcess localeA; |
613 | + localeA.start("locale -a"); |
614 | + QVERIFY(localeA.waitForFinished()); |
615 | + QVERIFY(QString(localeA.readAll()).split("\n").contains("en_US.utf8")); |
616 | + |
617 | + i18n->setLanguage("en_US.utf8"); |
618 | + QSignalSpy spy(i18n, SIGNAL(languageChanged())); |
619 | + spy.wait(); |
620 | + |
621 | + // Inspect translated strings in QML |
622 | + QCOMPARE(timeNow->property("text").toString(), QString("tr:Now")); |
623 | + QCOMPARE(timeMinuteBefore->property("text").toString(), QString("tr:1 minute ago")); |
624 | + QCOMPARE(timeMinuteAfter->property("text").toString(), QString("tr:1 minute")); |
625 | + QCOMPARE(tenMinutesBefore->property("text").toString(), QString("tr:10 minutes ago")); |
626 | + QCOMPARE(tenMinutesAfter->property("text").toString(), QString("tr:10 minutes")); |
627 | + QCOMPARE(timeFarAway->property("text").toString(), QString("tr:FarAway")); |
628 | + |
629 | + // Translate in C++ |
630 | + QCOMPARE(i18n->relativeDateTime(QDateTime::currentDateTime()), QString("tr:Now")); |
631 | + QCOMPARE(i18n->relativeDateTime(QDateTime(QDate(2000,1,1), QTime(0,0,0,0))), QString("tr:FarAway")); |
632 | + QCOMPARE(i18n->relativeDateTime(QDateTime::currentDateTime().addSecs(-60)), QString("tr:1 minute ago")); |
633 | + QCOMPARE(i18n->relativeDateTime(QDateTime::currentDateTime().addSecs(60)), QString("tr:1 minute")); |
634 | + QCOMPARE(i18n->relativeDateTime(QDateTime::currentDateTime().addSecs(-600)), QString("tr:10 minutes ago")); |
635 | + QCOMPARE(i18n->relativeDateTime(QDateTime::currentDateTime().addSecs(600)), QString("tr:10 minutes")); |
636 | + } |
637 | +}; |
638 | + |
639 | +// The C++ equivalent of QTEST_MAIN(tst_I18n_RelativeTime) with added initialization |
640 | +int main(int argc, char *argv[]) |
641 | +{ |
642 | + // LC_ALL would fail the test case; it must be unset before execution |
643 | + unsetenv("LC_ALL"); |
644 | + |
645 | + QGuiApplication app(argc, argv); |
646 | + app.setAttribute(Qt::AA_Use96Dpi, true); |
647 | + tst_I18n_RelativeTime* testObject = new tst_I18n_RelativeTime(); |
648 | + return QTest::qExec(static_cast<QObject*>(testObject), argc, argv); |
649 | +} |
650 | + |
651 | +#include "tst_i18n_RelativeTime.moc" |
652 | |
653 | === added file 'tests/unit/tst_i18n/tst_i18n_RelativeTime/tst_i18n_RelativeTime.pro' |
654 | --- tests/unit/tst_i18n/tst_i18n_RelativeTime/tst_i18n_RelativeTime.pro 1970-01-01 00:00:00 +0000 |
655 | +++ tests/unit/tst_i18n/tst_i18n_RelativeTime/tst_i18n_RelativeTime.pro 2015-08-12 10:11:44 +0000 |
656 | @@ -0,0 +1,17 @@ |
657 | +include(../../test-include.pri) |
658 | +QT += gui |
659 | +DEFINES += SRCDIR=\\\"$$PWD/\\\" |
660 | + |
661 | +DOMAIN = ubuntu-ui-toolkit |
662 | +mo.target = mo |
663 | +mo.commands = set -e; |
664 | +mo.commands += echo Generating localization; |
665 | +mo.commands += msgfmt po/en_US.po -o $${DOMAIN}/share/locale/en/LC_MESSAGES/$${DOMAIN}.mo; |
666 | +QMAKE_EXTRA_TARGETS += mo |
667 | +PRE_TARGETDEPS += mo |
668 | + |
669 | +SOURCES += \ |
670 | + src/tst_i18n_RelativeTime.cpp |
671 | + |
672 | +OTHER_FILES += \ |
673 | + src/RelativeTime.qml |
674 | |
675 | === added directory 'tests/unit/tst_i18n/tst_i18n_RelativeTime/ubuntu-ui-toolkit' |
676 | === added directory 'tests/unit/tst_i18n/tst_i18n_RelativeTime/ubuntu-ui-toolkit/share' |
677 | === added directory 'tests/unit/tst_i18n/tst_i18n_RelativeTime/ubuntu-ui-toolkit/share/locale' |
678 | === added directory 'tests/unit/tst_i18n/tst_i18n_RelativeTime/ubuntu-ui-toolkit/share/locale/en' |
679 | === added directory 'tests/unit/tst_i18n/tst_i18n_RelativeTime/ubuntu-ui-toolkit/share/locale/en/LC_MESSAGES' |
It's just a re-merged version of https:/ /code.launchpad .net/~nick- dedekind/ ubuntu- ui-toolkit/ i18n-RelativeDa teTime/ +merge/ 265282