Merge lp:~bzoltan/ubuntu-ui-toolkit/restructure_i18n into lp:ubuntu-ui-toolkit/staging
- restructure_i18n
- Merge into staging
Status: | Work in progress |
---|---|
Proposed branch: | lp:~bzoltan/ubuntu-ui-toolkit/restructure_i18n |
Merge into: | lp:ubuntu-ui-toolkit/staging |
Diff against target: |
1154 lines (+1114/-2) 4 files modified
src/UbuntuToolkit/UbuntuToolkit.pro (+19/-2) src/UbuntuToolkit/i18n-android.cpp (+365/-0) src/UbuntuToolkit/i18n-macx.cpp (+365/-0) src/UbuntuToolkit/i18n-windows.cpp (+365/-0) |
To merge this branch: | bzr merge lp:~bzoltan/ubuntu-ui-toolkit/restructure_i18n |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
ubuntu-sdk-build-bot | continuous-integration | Needs Fixing | |
Ubuntu SDK team | Pending | ||
Review via email: mp+306424@code.launchpad.net |
Commit message
Restructure i18n API implementation for non Ubuntu platforms
Description of the change
Restructure i18n API implementation for non Ubuntu platforms
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2121
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2121
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2121
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2121
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2121
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 2122. By Zoltan Balogh
-
Missed backslash
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2122
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2122
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2122
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:2122
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2122
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2122
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2122
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2122
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2122
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:2122
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2122
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:2122
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Cris Dywan (kalikiana) wrote : | # |
Just to clear up the review queue: this needs a rationale as to what the split is trying to achieve. From the current code I barely see a difference in the implementations and no platform-specific code.
Unmerged revisions
- 2122. By Zoltan Balogh
-
Missed backslash
- 2121. By Zoltan Balogh
-
Restructure i18n API implementation for non Ubuntu platforms
Preview Diff
1 | === modified file 'src/UbuntuToolkit/UbuntuToolkit.pro' | |||
2 | --- src/UbuntuToolkit/UbuntuToolkit.pro 2016-09-12 14:56:56 +0000 | |||
3 | +++ src/UbuntuToolkit/UbuntuToolkit.pro 2016-09-22 08:32:15 +0000 | |||
4 | @@ -2,7 +2,7 @@ | |||
5 | 2 | QT = core-private gui-private qml-private quick-private testlib dbus svg organizer \ | 2 | QT = core-private gui-private qml-private quick-private testlib dbus svg organizer \ |
6 | 3 | UbuntuGestures-private UbuntuMetrics | 3 | UbuntuGestures-private UbuntuMetrics |
7 | 4 | 4 | ||
9 | 5 | unix { | 5 | linux { |
10 | 6 | CONFIG += link_pkgconfig | 6 | CONFIG += link_pkgconfig |
11 | 7 | PKGCONFIG += gio-2.0 dbus-1 libnih libnih-dbus | 7 | PKGCONFIG += gio-2.0 dbus-1 libnih libnih-dbus |
12 | 8 | } | 8 | } |
13 | @@ -142,7 +142,6 @@ | |||
14 | 142 | $$PWD/colorutils.cpp \ | 142 | $$PWD/colorutils.cpp \ |
15 | 143 | $$PWD/exclusivegroup.cpp \ | 143 | $$PWD/exclusivegroup.cpp \ |
16 | 144 | $$PWD/filterbehavior.cpp \ | 144 | $$PWD/filterbehavior.cpp \ |
17 | 145 | $$PWD/i18n.cpp \ | ||
18 | 146 | $$PWD/inversemouseareatype.cpp \ | 145 | $$PWD/inversemouseareatype.cpp \ |
19 | 147 | $$PWD/listener.cpp \ | 146 | $$PWD/listener.cpp \ |
20 | 148 | $$PWD/livetimer.cpp \ | 147 | $$PWD/livetimer.cpp \ |
21 | @@ -237,4 +236,22 @@ | |||
22 | 237 | $$PWD/privates/shaders/frame.vert \ | 236 | $$PWD/privates/shaders/frame.vert \ |
23 | 238 | $$PWD/privates/shaders/frame.frag | 237 | $$PWD/privates/shaders/frame.frag |
24 | 239 | 238 | ||
25 | 239 | macx { | ||
26 | 240 | # OSX and iOS specific | ||
27 | 241 | SOURCES += \ | ||
28 | 242 | $$PWD/i18n-osx.cpp | ||
29 | 243 | } else:android { | ||
30 | 244 | # Android specific | ||
31 | 245 | SOURCES += \ | ||
32 | 246 | $$PWD/i18n-android.cpp | ||
33 | 247 | } else:windows { | ||
34 | 248 | # Windows specific | ||
35 | 249 | SOURCES += \ | ||
36 | 250 | $$PWD/i18n-windows.cpp | ||
37 | 251 | } else { | ||
38 | 252 | # Ubuntu specific | ||
39 | 253 | SOURCES += \ | ||
40 | 254 | $$PWD/i18n-ubuntu.cpp | ||
41 | 255 | } | ||
42 | 256 | |||
43 | 240 | load(ubuntu_qt_module) | 257 | load(ubuntu_qt_module) |
44 | 241 | 258 | ||
45 | === added file 'src/UbuntuToolkit/i18n-android.cpp' | |||
46 | --- src/UbuntuToolkit/i18n-android.cpp 1970-01-01 00:00:00 +0000 | |||
47 | +++ src/UbuntuToolkit/i18n-android.cpp 2016-09-22 08:32:15 +0000 | |||
48 | @@ -0,0 +1,365 @@ | |||
49 | 1 | /* | ||
50 | 2 | * Copyright 2012-2015 Canonical Ltd. | ||
51 | 3 | * | ||
52 | 4 | * This program is free software; you can redistribute it and/or modify | ||
53 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
54 | 6 | * the Free Software Foundation; version 3. | ||
55 | 7 | * | ||
56 | 8 | * This program is distributed in the hope that it will be useful, | ||
57 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
58 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
59 | 11 | * GNU Lesser General Public License for more details. | ||
60 | 12 | * | ||
61 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
62 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
63 | 15 | * | ||
64 | 16 | * Author: Tim Peeters <tim.peeters@canonical.om> | ||
65 | 17 | */ | ||
66 | 18 | |||
67 | 19 | #include "i18n_p.h" | ||
68 | 20 | |||
69 | 21 | namespace C { | ||
70 | 22 | #include <libintl.h> | ||
71 | 23 | #include <glib.h> | ||
72 | 24 | #include <glib/gi18n.h> | ||
73 | 25 | } | ||
74 | 26 | #include <stdlib.h> | ||
75 | 27 | #include <locale.h> | ||
76 | 28 | |||
77 | 29 | #include <QtCore/QDir> | ||
78 | 30 | |||
79 | 31 | #include "timeutils_p.h" | ||
80 | 32 | |||
81 | 33 | UT_NAMESPACE_BEGIN | ||
82 | 34 | /*! | ||
83 | 35 | * \qmltype i18n | ||
84 | 36 | * \inqmlmodule Ubuntu.Components | ||
85 | 37 | * \ingroup ubuntu | ||
86 | 38 | * \brief i18n is a context property that provides internationalization support. | ||
87 | 39 | * | ||
88 | 40 | * i18n cannot be instantiated, and is already available as a context property. | ||
89 | 41 | * It is based on \l {https://www.gnu.org/software/gettext/} {gettext}, and thus the standard gettext tools can be used for translating | ||
90 | 42 | * a project. Example: | ||
91 | 43 | * \qml | ||
92 | 44 | * import QtQuick 2.4 | ||
93 | 45 | * import Ubuntu.Components 0.1 | ||
94 | 46 | * | ||
95 | 47 | * Item { | ||
96 | 48 | * width: units.gu(40) | ||
97 | 49 | * height: units.gu(50) | ||
98 | 50 | * | ||
99 | 51 | * Button { | ||
100 | 52 | * anchors.centerIn: parent | ||
101 | 53 | * text: i18n.tr("Press me") | ||
102 | 54 | * } | ||
103 | 55 | * } | ||
104 | 56 | * \endqml | ||
105 | 57 | */ | ||
106 | 58 | UbuntuI18n *UbuntuI18n::m_i18 = nullptr; | ||
107 | 59 | |||
108 | 60 | UbuntuI18n::UbuntuI18n(QObject* parent) : QObject(parent) | ||
109 | 61 | { | ||
110 | 62 | /* | ||
111 | 63 | * setlocale | ||
112 | 64 | * category = LC_ALL: All types of i18n: LC_MESSAGES, LC_NUMERIC, LC_TIME | ||
113 | 65 | * locale = "": Lookup the environment for $LC_ALL, $LC_* and $LANG in that order | ||
114 | 66 | * Returns: for example en_US.utf8, da_DK or POSIX | ||
115 | 67 | * | ||
116 | 68 | * Note: $LANGUAGE is implicitly respected by gettext() calls and | ||
117 | 69 | * defines the order of multiple locales | ||
118 | 70 | */ | ||
119 | 71 | m_language = QString::fromLocal8Bit(setlocale(LC_ALL, "")); | ||
120 | 72 | } | ||
121 | 73 | |||
122 | 74 | UbuntuI18n::~UbuntuI18n() | ||
123 | 75 | { | ||
124 | 76 | m_i18 = nullptr; | ||
125 | 77 | } | ||
126 | 78 | |||
127 | 79 | /*! | ||
128 | 80 | * \qmlproperty string i18n::domain | ||
129 | 81 | * The gettext domain to be used for the translation. The default domain | ||
130 | 82 | * is the applicationName specified in the application's \l MainView, or the empty string "" if | ||
131 | 83 | * no applicationName was given or no \l MainView is used. | ||
132 | 84 | * Use dtr() functions instead of tr() to use a different domain for a single translation | ||
133 | 85 | * that ignores i18n.domain. | ||
134 | 86 | */ | ||
135 | 87 | QString UbuntuI18n::domain() const { | ||
136 | 88 | return m_domain; | ||
137 | 89 | } | ||
138 | 90 | |||
139 | 91 | /*! | ||
140 | 92 | * \qmlproperty string i18n::language | ||
141 | 93 | * The language that is used for the translation. The default value is | ||
142 | 94 | * the user's locale dending on $LC_ALL, $LC_MESSAGES and $LANG at the time | ||
143 | 95 | * of running the application. See the gettext manual for details. | ||
144 | 96 | */ | ||
145 | 97 | QString UbuntuI18n::language() const { | ||
146 | 98 | return m_language; | ||
147 | 99 | } | ||
148 | 100 | |||
149 | 101 | /** | ||
150 | 102 | * \qmlmethod void i18n::bindtextdomain(string domain_name, string dir_name) | ||
151 | 103 | * Specify that the domain_name message catalog can be found | ||
152 | 104 | * in dir_name rather than in the system locale data base. | ||
153 | 105 | */ | ||
154 | 106 | void UbuntuI18n::bindtextdomain(const QString& domain_name, const QString& dir_name) { | ||
155 | 107 | C::bindtextdomain(domain_name.toUtf8(), dir_name.toUtf8()); | ||
156 | 108 | Q_EMIT domainChanged(); | ||
157 | 109 | } | ||
158 | 110 | |||
159 | 111 | void UbuntuI18n::setDomain(const QString &domain) { | ||
160 | 112 | if (m_domain == domain) | ||
161 | 113 | return; | ||
162 | 114 | |||
163 | 115 | m_domain = domain; | ||
164 | 116 | C::textdomain(domain.toUtf8()); | ||
165 | 117 | /* | ||
166 | 118 | The default is /usr/share/locale if we don't set a folder | ||
167 | 119 | For click we use APP_DIR/share/locale | ||
168 | 120 | e.g. /usr/share/click/preinstalled/com.example.foo/current/share/locale | ||
169 | 121 | */ | ||
170 | 122 | QString appDir = QString::fromLocal8Bit(getenv("APP_DIR")); | ||
171 | 123 | if (!QDir::isAbsolutePath (appDir)) { | ||
172 | 124 | appDir = QStringLiteral("/usr"); | ||
173 | 125 | } | ||
174 | 126 | QString localePath(QDir(appDir).filePath(QStringLiteral("share/locale"))); | ||
175 | 127 | C::bindtextdomain(domain.toUtf8(), localePath.toUtf8()); | ||
176 | 128 | Q_EMIT domainChanged(); | ||
177 | 129 | } | ||
178 | 130 | |||
179 | 131 | void UbuntuI18n::setLanguage(const QString &lang) { | ||
180 | 132 | if (m_language == lang) | ||
181 | 133 | return; | ||
182 | 134 | |||
183 | 135 | m_language = lang; | ||
184 | 136 | |||
185 | 137 | /* | ||
186 | 138 | This is needed for LP: #1263163. | ||
187 | 139 | |||
188 | 140 | LANGUAGE may be set to one or more languages for example "fi" or | ||
189 | 141 | "sv:de". gettext prioritizes LANGUAGE over LC_ALL, LC_*, and | ||
190 | 142 | LANG, so if the session has already set LANGUAGE, calls to | ||
191 | 143 | gettext will only use that. We must override it here so that | ||
192 | 144 | future calls to gettext are done in the new language. | ||
193 | 145 | |||
194 | 146 | This only affects the current process. It does not override the | ||
195 | 147 | user's session LANGUAGE. | ||
196 | 148 | */ | ||
197 | 149 | setenv("LANGUAGE", lang.toUtf8().constData(), 1); | ||
198 | 150 | |||
199 | 151 | /* | ||
200 | 152 | The inverse form of setlocale as used in the constructor, passing | ||
201 | 153 | a valid locale string updates all category type defaults. | ||
202 | 154 | */ | ||
203 | 155 | setlocale(LC_ALL, lang.toUtf8()); | ||
204 | 156 | Q_EMIT languageChanged(); | ||
205 | 157 | } | ||
206 | 158 | |||
207 | 159 | /*! | ||
208 | 160 | * \qmlmethod string i18n::tr(string text) | ||
209 | 161 | * Translate \a text using gettext and return the translation. | ||
210 | 162 | */ | ||
211 | 163 | QString UbuntuI18n::tr(const QString& text) | ||
212 | 164 | { | ||
213 | 165 | return QString::fromUtf8(C::gettext(text.toUtf8())); | ||
214 | 166 | } | ||
215 | 167 | |||
216 | 168 | /*! | ||
217 | 169 | * \qmlmethod string i18n::tr(string singular, string plural, int n) | ||
218 | 170 | * Translate the given input string \a singular or \a plural (depending on the number of items \a n) | ||
219 | 171 | * using gettext. | ||
220 | 172 | * Note that tr() does not automatically insert the values in the QString, | ||
221 | 173 | * so it should be called like this: | ||
222 | 174 | * tr("%1 file", "%1 files", count).arg(count) | ||
223 | 175 | */ | ||
224 | 176 | QString UbuntuI18n::tr(const QString &singular, const QString &plural, int n) | ||
225 | 177 | { | ||
226 | 178 | return QString::fromUtf8(C::ngettext(singular.toUtf8(), plural.toUtf8(), n)); | ||
227 | 179 | } | ||
228 | 180 | |||
229 | 181 | /*! | ||
230 | 182 | * \qmlmethod string i18n::dtr(string domain, string text) | ||
231 | 183 | * Translate \a text using gettext. Uses the specified domain \a domain instead of i18n.domain. | ||
232 | 184 | */ | ||
233 | 185 | QString UbuntuI18n::dtr(const QString& domain, const QString& text) | ||
234 | 186 | { | ||
235 | 187 | if (domain.isNull()) { | ||
236 | 188 | return QString::fromUtf8(C::dgettext(NULL, text.toUtf8())); | ||
237 | 189 | } else { | ||
238 | 190 | return QString::fromUtf8(C::dgettext(domain.toUtf8(), text.toUtf8())); | ||
239 | 191 | } | ||
240 | 192 | } | ||
241 | 193 | |||
242 | 194 | /*! | ||
243 | 195 | * \qmlmethod string i18n::dtr(string domain, string singular, string plural, int n) | ||
244 | 196 | * Translate the given text using gettext. Should be called like this: | ||
245 | 197 | * tr(domain, "%1 file", "%1 files", count).arg(count) | ||
246 | 198 | * Uses \a domain for the domain instead of i18n.domain, and \a singular or \a plural | ||
247 | 199 | * as input for the translation depending on the number of items \a n. | ||
248 | 200 | */ | ||
249 | 201 | QString UbuntuI18n::dtr(const QString& domain, const QString& singular, const QString& plural, int n) | ||
250 | 202 | { | ||
251 | 203 | if (domain.isNull()) { | ||
252 | 204 | return QString::fromUtf8(C::dngettext(NULL, singular.toUtf8(), plural.toUtf8(), n)); | ||
253 | 205 | } else { | ||
254 | 206 | return QString::fromUtf8(C::dngettext(domain.toUtf8(), singular.toUtf8(), plural.toUtf8(), n)); | ||
255 | 207 | } | ||
256 | 208 | } | ||
257 | 209 | |||
258 | 210 | /*! | ||
259 | 211 | * \qmlmethod string i18n::ctr(string context, string text) | ||
260 | 212 | * Translate \a text using gettext and return the translation. | ||
261 | 213 | * \a context is only visible to the translator and helps disambiguating for very short texts | ||
262 | 214 | */ | ||
263 | 215 | QString UbuntuI18n::ctr(const QString& context, const QString& text) | ||
264 | 216 | { | ||
265 | 217 | return dctr(QString(), context, text); | ||
266 | 218 | } | ||
267 | 219 | |||
268 | 220 | /*! | ||
269 | 221 | * \qmlmethod string i18n::dctr(string domain, string context, string text) | ||
270 | 222 | * Translate \a text using gettext. Uses the specified domain \a domain instead of i18n.domain. | ||
271 | 223 | * \a context is only visible to the translator and helps disambiguating for very short texts | ||
272 | 224 | */ | ||
273 | 225 | QString UbuntuI18n::dctr(const QString& domain, const QString& context, const QString& text) | ||
274 | 226 | { | ||
275 | 227 | if (domain.isNull()) { | ||
276 | 228 | return QString::fromUtf8(C::g_dpgettext2(NULL, context.toUtf8(), text.toUtf8())); | ||
277 | 229 | } else { | ||
278 | 230 | return QString::fromUtf8(C::g_dpgettext2(domain.toUtf8(), context.toUtf8(), text.toUtf8())); | ||
279 | 231 | } | ||
280 | 232 | } | ||
281 | 233 | |||
282 | 234 | /*! | ||
283 | 235 | * \qmlmethod string i18n::tag(string text) | ||
284 | 236 | * Mark \a text for translation at a later point. Typically this allows an API | ||
285 | 237 | * to take the original string and pass it to dtr (or dgettext). | ||
286 | 238 | * | ||
287 | 239 | * \qml | ||
288 | 240 | * import QtQuick 2.4 | ||
289 | 241 | * import UserMetrics 0.1 | ||
290 | 242 | * | ||
291 | 243 | * Metric { | ||
292 | 244 | * name: "distance" | ||
293 | 245 | * format: i18n.tag("Distance covered today: %1 km") | ||
294 | 246 | * emptyFormat: i18n.tag("No running today") | ||
295 | 247 | * domain: "runner.forest" | ||
296 | 248 | * } | ||
297 | 249 | * \endqml | ||
298 | 250 | * | ||
299 | 251 | * The strings tagged for localzation above are passed to the implementation | ||
300 | 252 | * of UserMetrics verbatim, as well as the domain of the app. Display and | ||
301 | 253 | * translation of the strings will happen in the lockscreen, where the same | ||
302 | 254 | * strings will be passed to i18n.tr. | ||
303 | 255 | */ | ||
304 | 256 | QString UbuntuI18n::tag(const QString& text) | ||
305 | 257 | { | ||
306 | 258 | return text; | ||
307 | 259 | } | ||
308 | 260 | |||
309 | 261 | /*! | ||
310 | 262 | * \qmlmethod string i18n::tag(string context, string text) | ||
311 | 263 | * Mark \a text for translation at a later point. Typically this allows an API | ||
312 | 264 | * to take the original string and pass it to dctr (or g_dpgettext2). | ||
313 | 265 | * \a context is only visible to the translator and helps disambiguating for very short texts | ||
314 | 266 | */ | ||
315 | 267 | QString UbuntuI18n::tag(const QString& context, const QString& text) | ||
316 | 268 | { | ||
317 | 269 | Q_UNUSED(context); | ||
318 | 270 | return text; | ||
319 | 271 | } | ||
320 | 272 | /*! | ||
321 | 273 | * \qmlmethod string i18n::relativeDateTime(datetime dateTime) | ||
322 | 274 | * Translate a datetime based on proximity to current time. | ||
323 | 275 | */ | ||
324 | 276 | QString UbuntuI18n::relativeDateTime(const QDateTime& datetime) | ||
325 | 277 | { | ||
326 | 278 | static const QString ubuntuUiToolkit = QStringLiteral("ubuntu-ui-toolkit"); | ||
327 | 279 | |||
328 | 280 | QDateTime relativeTo(QDateTime::currentDateTime()); | ||
329 | 281 | const date_proximity_t prox = getDateProximity(relativeTo, datetime); | ||
330 | 282 | |||
331 | 283 | switch (prox) { | ||
332 | 284 | case DATE_PROXIMITY_NOW: | ||
333 | 285 | /* TRANSLATORS: Time based "this is happening/happened now" */ | ||
334 | 286 | return dtr(ubuntuUiToolkit, QStringLiteral("Now")); | ||
335 | 287 | |||
336 | 288 | case DATE_PROXIMITY_HOUR: | ||
337 | 289 | { | ||
338 | 290 | qint64 diff = datetime.toMSecsSinceEpoch() - relativeTo.toMSecsSinceEpoch(); | ||
339 | 291 | qint64 minutes = qRound(float(diff) / 60000); | ||
340 | 292 | if (minutes < 0) { | ||
341 | 293 | return dtr(ubuntuUiToolkit, QStringLiteral("%1 minute ago"), | ||
342 | 294 | QStringLiteral("%1 minutes ago"), qAbs(minutes)).arg(qAbs(minutes)); | ||
343 | 295 | } | ||
344 | 296 | return dtr(ubuntuUiToolkit, QStringLiteral("%1 minute"), | ||
345 | 297 | QStringLiteral("%1 minutes"), minutes).arg(minutes); | ||
346 | 298 | } | ||
347 | 299 | |||
348 | 300 | case DATE_PROXIMITY_TODAY: | ||
349 | 301 | /* en_US example: "1:00 PM" */ | ||
350 | 302 | /* TRANSLATORS: Please translate these to your locale datetime | ||
351 | 303 | format using the format specified by | ||
352 | 304 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
353 | 305 | return datetime.toString(isLocale12h() | ||
354 | 306 | ? dtr(ubuntuUiToolkit, QStringLiteral("h:mm ap")) | ||
355 | 307 | /* TRANSLATORS: Please translate these to your locale datetime | ||
356 | 308 | format using the format specified by | ||
357 | 309 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
358 | 310 | : dtr(ubuntuUiToolkit, QStringLiteral("HH:mm"))); | ||
359 | 311 | |||
360 | 312 | case DATE_PROXIMITY_YESTERDAY: | ||
361 | 313 | /* en_US example: "Yesterday 13:00" */ | ||
362 | 314 | /* TRANSLATORS: Please translate these to your locale datetime | ||
363 | 315 | format using the format specified by | ||
364 | 316 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
365 | 317 | return datetime.toString(isLocale12h() | ||
366 | 318 | ? dtr(ubuntuUiToolkit, QStringLiteral("'Yesterday\u2003'h:mm ap")) | ||
367 | 319 | /* TRANSLATORS: Please translate these to your locale datetime | ||
368 | 320 | format using the format specified by | ||
369 | 321 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
370 | 322 | : dtr(ubuntuUiToolkit, QStringLiteral("'Yesterday\u2003'HH:mm"))); | ||
371 | 323 | |||
372 | 324 | case DATE_PROXIMITY_TOMORROW: | ||
373 | 325 | /* en_US example: "Tomorrow 1:00 PM" */ | ||
374 | 326 | /* TRANSLATORS: Please translate these to your locale datetime | ||
375 | 327 | format using the format specified by | ||
376 | 328 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
377 | 329 | return datetime.toString(isLocale12h() | ||
378 | 330 | ? dtr(ubuntuUiToolkit, QStringLiteral("'Tomorrow\u2003'h:mm ap")) | ||
379 | 331 | /* TRANSLATORS: Please translate these to your locale datetime | ||
380 | 332 | format using the format specified by | ||
381 | 333 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
382 | 334 | : dtr(ubuntuUiToolkit, QStringLiteral("'Tomorrow\u2003'HH:mm"))); | ||
383 | 335 | |||
384 | 336 | case DATE_PROXIMITY_LAST_WEEK: | ||
385 | 337 | case DATE_PROXIMITY_NEXT_WEEK: | ||
386 | 338 | /* en_US example: "Fri 1:00 PM" */ | ||
387 | 339 | /* TRANSLATORS: Please translate these to your locale datetime | ||
388 | 340 | format using the format specified by | ||
389 | 341 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
390 | 342 | return datetime.toString(isLocale12h() | ||
391 | 343 | ? dtr(ubuntuUiToolkit, QStringLiteral("ddd'\u2003'h:mm ap")) | ||
392 | 344 | /* TRANSLATORS: Please translate these to your locale datetime | ||
393 | 345 | format using the format specified by | ||
394 | 346 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
395 | 347 | : dtr(ubuntuUiToolkit, QStringLiteral("ddd'\u2003'HH:mm"))); | ||
396 | 348 | |||
397 | 349 | case DATE_PROXIMITY_FAR_BACK: | ||
398 | 350 | case DATE_PROXIMITY_FAR_FORWARD: | ||
399 | 351 | default: | ||
400 | 352 | /* TRANSLATORS: Please translate these to your locale datetime | ||
401 | 353 | format using the format specified by | ||
402 | 354 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
403 | 355 | return datetime.toString(isLocale12h() | ||
404 | 356 | ? dtr(ubuntuUiToolkit, QStringLiteral("ddd d MMM'\u2003'h:mm ap")) | ||
405 | 357 | /* TRANSLATORS: Please translate these to your locale datetime | ||
406 | 358 | format using the format specified by | ||
407 | 359 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
408 | 360 | : dtr(ubuntuUiToolkit, QStringLiteral("ddd d MMM'\u2003'HH:mm"))); | ||
409 | 361 | } | ||
410 | 362 | return datetime.toString(Qt::DefaultLocaleShortDate); | ||
411 | 363 | } | ||
412 | 364 | |||
413 | 365 | UT_NAMESPACE_END | ||
414 | 0 | 366 | ||
415 | === added file 'src/UbuntuToolkit/i18n-macx.cpp' | |||
416 | --- src/UbuntuToolkit/i18n-macx.cpp 1970-01-01 00:00:00 +0000 | |||
417 | +++ src/UbuntuToolkit/i18n-macx.cpp 2016-09-22 08:32:15 +0000 | |||
418 | @@ -0,0 +1,365 @@ | |||
419 | 1 | /* | ||
420 | 2 | * Copyright 2012-2015 Canonical Ltd. | ||
421 | 3 | * | ||
422 | 4 | * This program is free software; you can redistribute it and/or modify | ||
423 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
424 | 6 | * the Free Software Foundation; version 3. | ||
425 | 7 | * | ||
426 | 8 | * This program is distributed in the hope that it will be useful, | ||
427 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
428 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
429 | 11 | * GNU Lesser General Public License for more details. | ||
430 | 12 | * | ||
431 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
432 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
433 | 15 | * | ||
434 | 16 | * Author: Tim Peeters <tim.peeters@canonical.om> | ||
435 | 17 | */ | ||
436 | 18 | |||
437 | 19 | #include "i18n_p.h" | ||
438 | 20 | |||
439 | 21 | namespace C { | ||
440 | 22 | #include <libintl.h> | ||
441 | 23 | #include <glib.h> | ||
442 | 24 | #include <glib/gi18n.h> | ||
443 | 25 | } | ||
444 | 26 | #include <stdlib.h> | ||
445 | 27 | #include <locale.h> | ||
446 | 28 | |||
447 | 29 | #include <QtCore/QDir> | ||
448 | 30 | |||
449 | 31 | #include "timeutils_p.h" | ||
450 | 32 | |||
451 | 33 | UT_NAMESPACE_BEGIN | ||
452 | 34 | /*! | ||
453 | 35 | * \qmltype i18n | ||
454 | 36 | * \inqmlmodule Ubuntu.Components | ||
455 | 37 | * \ingroup ubuntu | ||
456 | 38 | * \brief i18n is a context property that provides internationalization support. | ||
457 | 39 | * | ||
458 | 40 | * i18n cannot be instantiated, and is already available as a context property. | ||
459 | 41 | * It is based on \l {https://www.gnu.org/software/gettext/} {gettext}, and thus the standard gettext tools can be used for translating | ||
460 | 42 | * a project. Example: | ||
461 | 43 | * \qml | ||
462 | 44 | * import QtQuick 2.4 | ||
463 | 45 | * import Ubuntu.Components 0.1 | ||
464 | 46 | * | ||
465 | 47 | * Item { | ||
466 | 48 | * width: units.gu(40) | ||
467 | 49 | * height: units.gu(50) | ||
468 | 50 | * | ||
469 | 51 | * Button { | ||
470 | 52 | * anchors.centerIn: parent | ||
471 | 53 | * text: i18n.tr("Press me") | ||
472 | 54 | * } | ||
473 | 55 | * } | ||
474 | 56 | * \endqml | ||
475 | 57 | */ | ||
476 | 58 | UbuntuI18n *UbuntuI18n::m_i18 = nullptr; | ||
477 | 59 | |||
478 | 60 | UbuntuI18n::UbuntuI18n(QObject* parent) : QObject(parent) | ||
479 | 61 | { | ||
480 | 62 | /* | ||
481 | 63 | * setlocale | ||
482 | 64 | * category = LC_ALL: All types of i18n: LC_MESSAGES, LC_NUMERIC, LC_TIME | ||
483 | 65 | * locale = "": Lookup the environment for $LC_ALL, $LC_* and $LANG in that order | ||
484 | 66 | * Returns: for example en_US.utf8, da_DK or POSIX | ||
485 | 67 | * | ||
486 | 68 | * Note: $LANGUAGE is implicitly respected by gettext() calls and | ||
487 | 69 | * defines the order of multiple locales | ||
488 | 70 | */ | ||
489 | 71 | m_language = QString::fromLocal8Bit(setlocale(LC_ALL, "")); | ||
490 | 72 | } | ||
491 | 73 | |||
492 | 74 | UbuntuI18n::~UbuntuI18n() | ||
493 | 75 | { | ||
494 | 76 | m_i18 = nullptr; | ||
495 | 77 | } | ||
496 | 78 | |||
497 | 79 | /*! | ||
498 | 80 | * \qmlproperty string i18n::domain | ||
499 | 81 | * The gettext domain to be used for the translation. The default domain | ||
500 | 82 | * is the applicationName specified in the application's \l MainView, or the empty string "" if | ||
501 | 83 | * no applicationName was given or no \l MainView is used. | ||
502 | 84 | * Use dtr() functions instead of tr() to use a different domain for a single translation | ||
503 | 85 | * that ignores i18n.domain. | ||
504 | 86 | */ | ||
505 | 87 | QString UbuntuI18n::domain() const { | ||
506 | 88 | return m_domain; | ||
507 | 89 | } | ||
508 | 90 | |||
509 | 91 | /*! | ||
510 | 92 | * \qmlproperty string i18n::language | ||
511 | 93 | * The language that is used for the translation. The default value is | ||
512 | 94 | * the user's locale dending on $LC_ALL, $LC_MESSAGES and $LANG at the time | ||
513 | 95 | * of running the application. See the gettext manual for details. | ||
514 | 96 | */ | ||
515 | 97 | QString UbuntuI18n::language() const { | ||
516 | 98 | return m_language; | ||
517 | 99 | } | ||
518 | 100 | |||
519 | 101 | /** | ||
520 | 102 | * \qmlmethod void i18n::bindtextdomain(string domain_name, string dir_name) | ||
521 | 103 | * Specify that the domain_name message catalog can be found | ||
522 | 104 | * in dir_name rather than in the system locale data base. | ||
523 | 105 | */ | ||
524 | 106 | void UbuntuI18n::bindtextdomain(const QString& domain_name, const QString& dir_name) { | ||
525 | 107 | C::bindtextdomain(domain_name.toUtf8(), dir_name.toUtf8()); | ||
526 | 108 | Q_EMIT domainChanged(); | ||
527 | 109 | } | ||
528 | 110 | |||
529 | 111 | void UbuntuI18n::setDomain(const QString &domain) { | ||
530 | 112 | if (m_domain == domain) | ||
531 | 113 | return; | ||
532 | 114 | |||
533 | 115 | m_domain = domain; | ||
534 | 116 | C::textdomain(domain.toUtf8()); | ||
535 | 117 | /* | ||
536 | 118 | The default is /usr/share/locale if we don't set a folder | ||
537 | 119 | For click we use APP_DIR/share/locale | ||
538 | 120 | e.g. /usr/share/click/preinstalled/com.example.foo/current/share/locale | ||
539 | 121 | */ | ||
540 | 122 | QString appDir = QString::fromLocal8Bit(getenv("APP_DIR")); | ||
541 | 123 | if (!QDir::isAbsolutePath (appDir)) { | ||
542 | 124 | appDir = QStringLiteral("/usr"); | ||
543 | 125 | } | ||
544 | 126 | QString localePath(QDir(appDir).filePath(QStringLiteral("share/locale"))); | ||
545 | 127 | C::bindtextdomain(domain.toUtf8(), localePath.toUtf8()); | ||
546 | 128 | Q_EMIT domainChanged(); | ||
547 | 129 | } | ||
548 | 130 | |||
549 | 131 | void UbuntuI18n::setLanguage(const QString &lang) { | ||
550 | 132 | if (m_language == lang) | ||
551 | 133 | return; | ||
552 | 134 | |||
553 | 135 | m_language = lang; | ||
554 | 136 | |||
555 | 137 | /* | ||
556 | 138 | This is needed for LP: #1263163. | ||
557 | 139 | |||
558 | 140 | LANGUAGE may be set to one or more languages for example "fi" or | ||
559 | 141 | "sv:de". gettext prioritizes LANGUAGE over LC_ALL, LC_*, and | ||
560 | 142 | LANG, so if the session has already set LANGUAGE, calls to | ||
561 | 143 | gettext will only use that. We must override it here so that | ||
562 | 144 | future calls to gettext are done in the new language. | ||
563 | 145 | |||
564 | 146 | This only affects the current process. It does not override the | ||
565 | 147 | user's session LANGUAGE. | ||
566 | 148 | */ | ||
567 | 149 | setenv("LANGUAGE", lang.toUtf8().constData(), 1); | ||
568 | 150 | |||
569 | 151 | /* | ||
570 | 152 | The inverse form of setlocale as used in the constructor, passing | ||
571 | 153 | a valid locale string updates all category type defaults. | ||
572 | 154 | */ | ||
573 | 155 | setlocale(LC_ALL, lang.toUtf8()); | ||
574 | 156 | Q_EMIT languageChanged(); | ||
575 | 157 | } | ||
576 | 158 | |||
577 | 159 | /*! | ||
578 | 160 | * \qmlmethod string i18n::tr(string text) | ||
579 | 161 | * Translate \a text using gettext and return the translation. | ||
580 | 162 | */ | ||
581 | 163 | QString UbuntuI18n::tr(const QString& text) | ||
582 | 164 | { | ||
583 | 165 | return QString::fromUtf8(C::gettext(text.toUtf8())); | ||
584 | 166 | } | ||
585 | 167 | |||
586 | 168 | /*! | ||
587 | 169 | * \qmlmethod string i18n::tr(string singular, string plural, int n) | ||
588 | 170 | * Translate the given input string \a singular or \a plural (depending on the number of items \a n) | ||
589 | 171 | * using gettext. | ||
590 | 172 | * Note that tr() does not automatically insert the values in the QString, | ||
591 | 173 | * so it should be called like this: | ||
592 | 174 | * tr("%1 file", "%1 files", count).arg(count) | ||
593 | 175 | */ | ||
594 | 176 | QString UbuntuI18n::tr(const QString &singular, const QString &plural, int n) | ||
595 | 177 | { | ||
596 | 178 | return QString::fromUtf8(C::ngettext(singular.toUtf8(), plural.toUtf8(), n)); | ||
597 | 179 | } | ||
598 | 180 | |||
599 | 181 | /*! | ||
600 | 182 | * \qmlmethod string i18n::dtr(string domain, string text) | ||
601 | 183 | * Translate \a text using gettext. Uses the specified domain \a domain instead of i18n.domain. | ||
602 | 184 | */ | ||
603 | 185 | QString UbuntuI18n::dtr(const QString& domain, const QString& text) | ||
604 | 186 | { | ||
605 | 187 | if (domain.isNull()) { | ||
606 | 188 | return QString::fromUtf8(C::dgettext(NULL, text.toUtf8())); | ||
607 | 189 | } else { | ||
608 | 190 | return QString::fromUtf8(C::dgettext(domain.toUtf8(), text.toUtf8())); | ||
609 | 191 | } | ||
610 | 192 | } | ||
611 | 193 | |||
612 | 194 | /*! | ||
613 | 195 | * \qmlmethod string i18n::dtr(string domain, string singular, string plural, int n) | ||
614 | 196 | * Translate the given text using gettext. Should be called like this: | ||
615 | 197 | * tr(domain, "%1 file", "%1 files", count).arg(count) | ||
616 | 198 | * Uses \a domain for the domain instead of i18n.domain, and \a singular or \a plural | ||
617 | 199 | * as input for the translation depending on the number of items \a n. | ||
618 | 200 | */ | ||
619 | 201 | QString UbuntuI18n::dtr(const QString& domain, const QString& singular, const QString& plural, int n) | ||
620 | 202 | { | ||
621 | 203 | if (domain.isNull()) { | ||
622 | 204 | return QString::fromUtf8(C::dngettext(NULL, singular.toUtf8(), plural.toUtf8(), n)); | ||
623 | 205 | } else { | ||
624 | 206 | return QString::fromUtf8(C::dngettext(domain.toUtf8(), singular.toUtf8(), plural.toUtf8(), n)); | ||
625 | 207 | } | ||
626 | 208 | } | ||
627 | 209 | |||
628 | 210 | /*! | ||
629 | 211 | * \qmlmethod string i18n::ctr(string context, string text) | ||
630 | 212 | * Translate \a text using gettext and return the translation. | ||
631 | 213 | * \a context is only visible to the translator and helps disambiguating for very short texts | ||
632 | 214 | */ | ||
633 | 215 | QString UbuntuI18n::ctr(const QString& context, const QString& text) | ||
634 | 216 | { | ||
635 | 217 | return dctr(QString(), context, text); | ||
636 | 218 | } | ||
637 | 219 | |||
638 | 220 | /*! | ||
639 | 221 | * \qmlmethod string i18n::dctr(string domain, string context, string text) | ||
640 | 222 | * Translate \a text using gettext. Uses the specified domain \a domain instead of i18n.domain. | ||
641 | 223 | * \a context is only visible to the translator and helps disambiguating for very short texts | ||
642 | 224 | */ | ||
643 | 225 | QString UbuntuI18n::dctr(const QString& domain, const QString& context, const QString& text) | ||
644 | 226 | { | ||
645 | 227 | if (domain.isNull()) { | ||
646 | 228 | return QString::fromUtf8(C::g_dpgettext2(NULL, context.toUtf8(), text.toUtf8())); | ||
647 | 229 | } else { | ||
648 | 230 | return QString::fromUtf8(C::g_dpgettext2(domain.toUtf8(), context.toUtf8(), text.toUtf8())); | ||
649 | 231 | } | ||
650 | 232 | } | ||
651 | 233 | |||
652 | 234 | /*! | ||
653 | 235 | * \qmlmethod string i18n::tag(string text) | ||
654 | 236 | * Mark \a text for translation at a later point. Typically this allows an API | ||
655 | 237 | * to take the original string and pass it to dtr (or dgettext). | ||
656 | 238 | * | ||
657 | 239 | * \qml | ||
658 | 240 | * import QtQuick 2.4 | ||
659 | 241 | * import UserMetrics 0.1 | ||
660 | 242 | * | ||
661 | 243 | * Metric { | ||
662 | 244 | * name: "distance" | ||
663 | 245 | * format: i18n.tag("Distance covered today: %1 km") | ||
664 | 246 | * emptyFormat: i18n.tag("No running today") | ||
665 | 247 | * domain: "runner.forest" | ||
666 | 248 | * } | ||
667 | 249 | * \endqml | ||
668 | 250 | * | ||
669 | 251 | * The strings tagged for localzation above are passed to the implementation | ||
670 | 252 | * of UserMetrics verbatim, as well as the domain of the app. Display and | ||
671 | 253 | * translation of the strings will happen in the lockscreen, where the same | ||
672 | 254 | * strings will be passed to i18n.tr. | ||
673 | 255 | */ | ||
674 | 256 | QString UbuntuI18n::tag(const QString& text) | ||
675 | 257 | { | ||
676 | 258 | return text; | ||
677 | 259 | } | ||
678 | 260 | |||
679 | 261 | /*! | ||
680 | 262 | * \qmlmethod string i18n::tag(string context, string text) | ||
681 | 263 | * Mark \a text for translation at a later point. Typically this allows an API | ||
682 | 264 | * to take the original string and pass it to dctr (or g_dpgettext2). | ||
683 | 265 | * \a context is only visible to the translator and helps disambiguating for very short texts | ||
684 | 266 | */ | ||
685 | 267 | QString UbuntuI18n::tag(const QString& context, const QString& text) | ||
686 | 268 | { | ||
687 | 269 | Q_UNUSED(context); | ||
688 | 270 | return text; | ||
689 | 271 | } | ||
690 | 272 | /*! | ||
691 | 273 | * \qmlmethod string i18n::relativeDateTime(datetime dateTime) | ||
692 | 274 | * Translate a datetime based on proximity to current time. | ||
693 | 275 | */ | ||
694 | 276 | QString UbuntuI18n::relativeDateTime(const QDateTime& datetime) | ||
695 | 277 | { | ||
696 | 278 | static const QString ubuntuUiToolkit = QStringLiteral("ubuntu-ui-toolkit"); | ||
697 | 279 | |||
698 | 280 | QDateTime relativeTo(QDateTime::currentDateTime()); | ||
699 | 281 | const date_proximity_t prox = getDateProximity(relativeTo, datetime); | ||
700 | 282 | |||
701 | 283 | switch (prox) { | ||
702 | 284 | case DATE_PROXIMITY_NOW: | ||
703 | 285 | /* TRANSLATORS: Time based "this is happening/happened now" */ | ||
704 | 286 | return dtr(ubuntuUiToolkit, QStringLiteral("Now")); | ||
705 | 287 | |||
706 | 288 | case DATE_PROXIMITY_HOUR: | ||
707 | 289 | { | ||
708 | 290 | qint64 diff = datetime.toMSecsSinceEpoch() - relativeTo.toMSecsSinceEpoch(); | ||
709 | 291 | qint64 minutes = qRound(float(diff) / 60000); | ||
710 | 292 | if (minutes < 0) { | ||
711 | 293 | return dtr(ubuntuUiToolkit, QStringLiteral("%1 minute ago"), | ||
712 | 294 | QStringLiteral("%1 minutes ago"), qAbs(minutes)).arg(qAbs(minutes)); | ||
713 | 295 | } | ||
714 | 296 | return dtr(ubuntuUiToolkit, QStringLiteral("%1 minute"), | ||
715 | 297 | QStringLiteral("%1 minutes"), minutes).arg(minutes); | ||
716 | 298 | } | ||
717 | 299 | |||
718 | 300 | case DATE_PROXIMITY_TODAY: | ||
719 | 301 | /* en_US example: "1:00 PM" */ | ||
720 | 302 | /* TRANSLATORS: Please translate these to your locale datetime | ||
721 | 303 | format using the format specified by | ||
722 | 304 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
723 | 305 | return datetime.toString(isLocale12h() | ||
724 | 306 | ? dtr(ubuntuUiToolkit, QStringLiteral("h:mm ap")) | ||
725 | 307 | /* TRANSLATORS: Please translate these to your locale datetime | ||
726 | 308 | format using the format specified by | ||
727 | 309 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
728 | 310 | : dtr(ubuntuUiToolkit, QStringLiteral("HH:mm"))); | ||
729 | 311 | |||
730 | 312 | case DATE_PROXIMITY_YESTERDAY: | ||
731 | 313 | /* en_US example: "Yesterday 13:00" */ | ||
732 | 314 | /* TRANSLATORS: Please translate these to your locale datetime | ||
733 | 315 | format using the format specified by | ||
734 | 316 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
735 | 317 | return datetime.toString(isLocale12h() | ||
736 | 318 | ? dtr(ubuntuUiToolkit, QStringLiteral("'Yesterday\u2003'h:mm ap")) | ||
737 | 319 | /* TRANSLATORS: Please translate these to your locale datetime | ||
738 | 320 | format using the format specified by | ||
739 | 321 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
740 | 322 | : dtr(ubuntuUiToolkit, QStringLiteral("'Yesterday\u2003'HH:mm"))); | ||
741 | 323 | |||
742 | 324 | case DATE_PROXIMITY_TOMORROW: | ||
743 | 325 | /* en_US example: "Tomorrow 1:00 PM" */ | ||
744 | 326 | /* TRANSLATORS: Please translate these to your locale datetime | ||
745 | 327 | format using the format specified by | ||
746 | 328 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
747 | 329 | return datetime.toString(isLocale12h() | ||
748 | 330 | ? dtr(ubuntuUiToolkit, QStringLiteral("'Tomorrow\u2003'h:mm ap")) | ||
749 | 331 | /* TRANSLATORS: Please translate these to your locale datetime | ||
750 | 332 | format using the format specified by | ||
751 | 333 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
752 | 334 | : dtr(ubuntuUiToolkit, QStringLiteral("'Tomorrow\u2003'HH:mm"))); | ||
753 | 335 | |||
754 | 336 | case DATE_PROXIMITY_LAST_WEEK: | ||
755 | 337 | case DATE_PROXIMITY_NEXT_WEEK: | ||
756 | 338 | /* en_US example: "Fri 1:00 PM" */ | ||
757 | 339 | /* TRANSLATORS: Please translate these to your locale datetime | ||
758 | 340 | format using the format specified by | ||
759 | 341 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
760 | 342 | return datetime.toString(isLocale12h() | ||
761 | 343 | ? dtr(ubuntuUiToolkit, QStringLiteral("ddd'\u2003'h:mm ap")) | ||
762 | 344 | /* TRANSLATORS: Please translate these to your locale datetime | ||
763 | 345 | format using the format specified by | ||
764 | 346 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
765 | 347 | : dtr(ubuntuUiToolkit, QStringLiteral("ddd'\u2003'HH:mm"))); | ||
766 | 348 | |||
767 | 349 | case DATE_PROXIMITY_FAR_BACK: | ||
768 | 350 | case DATE_PROXIMITY_FAR_FORWARD: | ||
769 | 351 | default: | ||
770 | 352 | /* TRANSLATORS: Please translate these to your locale datetime | ||
771 | 353 | format using the format specified by | ||
772 | 354 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
773 | 355 | return datetime.toString(isLocale12h() | ||
774 | 356 | ? dtr(ubuntuUiToolkit, QStringLiteral("ddd d MMM'\u2003'h:mm ap")) | ||
775 | 357 | /* TRANSLATORS: Please translate these to your locale datetime | ||
776 | 358 | format using the format specified by | ||
777 | 359 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
778 | 360 | : dtr(ubuntuUiToolkit, QStringLiteral("ddd d MMM'\u2003'HH:mm"))); | ||
779 | 361 | } | ||
780 | 362 | return datetime.toString(Qt::DefaultLocaleShortDate); | ||
781 | 363 | } | ||
782 | 364 | |||
783 | 365 | UT_NAMESPACE_END | ||
784 | 0 | 366 | ||
785 | === renamed file 'src/UbuntuToolkit/i18n.cpp' => 'src/UbuntuToolkit/i18n-ubuntu.cpp' | |||
786 | === added file 'src/UbuntuToolkit/i18n-windows.cpp' | |||
787 | --- src/UbuntuToolkit/i18n-windows.cpp 1970-01-01 00:00:00 +0000 | |||
788 | +++ src/UbuntuToolkit/i18n-windows.cpp 2016-09-22 08:32:15 +0000 | |||
789 | @@ -0,0 +1,365 @@ | |||
790 | 1 | /* | ||
791 | 2 | * Copyright 2012-2015 Canonical Ltd. | ||
792 | 3 | * | ||
793 | 4 | * This program is free software; you can redistribute it and/or modify | ||
794 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
795 | 6 | * the Free Software Foundation; version 3. | ||
796 | 7 | * | ||
797 | 8 | * This program is distributed in the hope that it will be useful, | ||
798 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
799 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
800 | 11 | * GNU Lesser General Public License for more details. | ||
801 | 12 | * | ||
802 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
803 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
804 | 15 | * | ||
805 | 16 | * Author: Tim Peeters <tim.peeters@canonical.om> | ||
806 | 17 | */ | ||
807 | 18 | |||
808 | 19 | #include "i18n_p.h" | ||
809 | 20 | |||
810 | 21 | namespace C { | ||
811 | 22 | #include <libintl.h> | ||
812 | 23 | #include <glib.h> | ||
813 | 24 | #include <glib/gi18n.h> | ||
814 | 25 | } | ||
815 | 26 | #include <stdlib.h> | ||
816 | 27 | #include <locale.h> | ||
817 | 28 | |||
818 | 29 | #include <QtCore/QDir> | ||
819 | 30 | |||
820 | 31 | #include "timeutils_p.h" | ||
821 | 32 | |||
822 | 33 | UT_NAMESPACE_BEGIN | ||
823 | 34 | /*! | ||
824 | 35 | * \qmltype i18n | ||
825 | 36 | * \inqmlmodule Ubuntu.Components | ||
826 | 37 | * \ingroup ubuntu | ||
827 | 38 | * \brief i18n is a context property that provides internationalization support. | ||
828 | 39 | * | ||
829 | 40 | * i18n cannot be instantiated, and is already available as a context property. | ||
830 | 41 | * It is based on \l {https://www.gnu.org/software/gettext/} {gettext}, and thus the standard gettext tools can be used for translating | ||
831 | 42 | * a project. Example: | ||
832 | 43 | * \qml | ||
833 | 44 | * import QtQuick 2.4 | ||
834 | 45 | * import Ubuntu.Components 0.1 | ||
835 | 46 | * | ||
836 | 47 | * Item { | ||
837 | 48 | * width: units.gu(40) | ||
838 | 49 | * height: units.gu(50) | ||
839 | 50 | * | ||
840 | 51 | * Button { | ||
841 | 52 | * anchors.centerIn: parent | ||
842 | 53 | * text: i18n.tr("Press me") | ||
843 | 54 | * } | ||
844 | 55 | * } | ||
845 | 56 | * \endqml | ||
846 | 57 | */ | ||
847 | 58 | UbuntuI18n *UbuntuI18n::m_i18 = nullptr; | ||
848 | 59 | |||
849 | 60 | UbuntuI18n::UbuntuI18n(QObject* parent) : QObject(parent) | ||
850 | 61 | { | ||
851 | 62 | /* | ||
852 | 63 | * setlocale | ||
853 | 64 | * category = LC_ALL: All types of i18n: LC_MESSAGES, LC_NUMERIC, LC_TIME | ||
854 | 65 | * locale = "": Lookup the environment for $LC_ALL, $LC_* and $LANG in that order | ||
855 | 66 | * Returns: for example en_US.utf8, da_DK or POSIX | ||
856 | 67 | * | ||
857 | 68 | * Note: $LANGUAGE is implicitly respected by gettext() calls and | ||
858 | 69 | * defines the order of multiple locales | ||
859 | 70 | */ | ||
860 | 71 | m_language = QString::fromLocal8Bit(setlocale(LC_ALL, "")); | ||
861 | 72 | } | ||
862 | 73 | |||
863 | 74 | UbuntuI18n::~UbuntuI18n() | ||
864 | 75 | { | ||
865 | 76 | m_i18 = nullptr; | ||
866 | 77 | } | ||
867 | 78 | |||
868 | 79 | /*! | ||
869 | 80 | * \qmlproperty string i18n::domain | ||
870 | 81 | * The gettext domain to be used for the translation. The default domain | ||
871 | 82 | * is the applicationName specified in the application's \l MainView, or the empty string "" if | ||
872 | 83 | * no applicationName was given or no \l MainView is used. | ||
873 | 84 | * Use dtr() functions instead of tr() to use a different domain for a single translation | ||
874 | 85 | * that ignores i18n.domain. | ||
875 | 86 | */ | ||
876 | 87 | QString UbuntuI18n::domain() const { | ||
877 | 88 | return m_domain; | ||
878 | 89 | } | ||
879 | 90 | |||
880 | 91 | /*! | ||
881 | 92 | * \qmlproperty string i18n::language | ||
882 | 93 | * The language that is used for the translation. The default value is | ||
883 | 94 | * the user's locale dending on $LC_ALL, $LC_MESSAGES and $LANG at the time | ||
884 | 95 | * of running the application. See the gettext manual for details. | ||
885 | 96 | */ | ||
886 | 97 | QString UbuntuI18n::language() const { | ||
887 | 98 | return m_language; | ||
888 | 99 | } | ||
889 | 100 | |||
890 | 101 | /** | ||
891 | 102 | * \qmlmethod void i18n::bindtextdomain(string domain_name, string dir_name) | ||
892 | 103 | * Specify that the domain_name message catalog can be found | ||
893 | 104 | * in dir_name rather than in the system locale data base. | ||
894 | 105 | */ | ||
895 | 106 | void UbuntuI18n::bindtextdomain(const QString& domain_name, const QString& dir_name) { | ||
896 | 107 | C::bindtextdomain(domain_name.toUtf8(), dir_name.toUtf8()); | ||
897 | 108 | Q_EMIT domainChanged(); | ||
898 | 109 | } | ||
899 | 110 | |||
900 | 111 | void UbuntuI18n::setDomain(const QString &domain) { | ||
901 | 112 | if (m_domain == domain) | ||
902 | 113 | return; | ||
903 | 114 | |||
904 | 115 | m_domain = domain; | ||
905 | 116 | C::textdomain(domain.toUtf8()); | ||
906 | 117 | /* | ||
907 | 118 | The default is /usr/share/locale if we don't set a folder | ||
908 | 119 | For click we use APP_DIR/share/locale | ||
909 | 120 | e.g. /usr/share/click/preinstalled/com.example.foo/current/share/locale | ||
910 | 121 | */ | ||
911 | 122 | QString appDir = QString::fromLocal8Bit(getenv("APP_DIR")); | ||
912 | 123 | if (!QDir::isAbsolutePath (appDir)) { | ||
913 | 124 | appDir = QStringLiteral("/usr"); | ||
914 | 125 | } | ||
915 | 126 | QString localePath(QDir(appDir).filePath(QStringLiteral("share/locale"))); | ||
916 | 127 | C::bindtextdomain(domain.toUtf8(), localePath.toUtf8()); | ||
917 | 128 | Q_EMIT domainChanged(); | ||
918 | 129 | } | ||
919 | 130 | |||
920 | 131 | void UbuntuI18n::setLanguage(const QString &lang) { | ||
921 | 132 | if (m_language == lang) | ||
922 | 133 | return; | ||
923 | 134 | |||
924 | 135 | m_language = lang; | ||
925 | 136 | |||
926 | 137 | /* | ||
927 | 138 | This is needed for LP: #1263163. | ||
928 | 139 | |||
929 | 140 | LANGUAGE may be set to one or more languages for example "fi" or | ||
930 | 141 | "sv:de". gettext prioritizes LANGUAGE over LC_ALL, LC_*, and | ||
931 | 142 | LANG, so if the session has already set LANGUAGE, calls to | ||
932 | 143 | gettext will only use that. We must override it here so that | ||
933 | 144 | future calls to gettext are done in the new language. | ||
934 | 145 | |||
935 | 146 | This only affects the current process. It does not override the | ||
936 | 147 | user's session LANGUAGE. | ||
937 | 148 | */ | ||
938 | 149 | setenv("LANGUAGE", lang.toUtf8().constData(), 1); | ||
939 | 150 | |||
940 | 151 | /* | ||
941 | 152 | The inverse form of setlocale as used in the constructor, passing | ||
942 | 153 | a valid locale string updates all category type defaults. | ||
943 | 154 | */ | ||
944 | 155 | setlocale(LC_ALL, lang.toUtf8()); | ||
945 | 156 | Q_EMIT languageChanged(); | ||
946 | 157 | } | ||
947 | 158 | |||
948 | 159 | /*! | ||
949 | 160 | * \qmlmethod string i18n::tr(string text) | ||
950 | 161 | * Translate \a text using gettext and return the translation. | ||
951 | 162 | */ | ||
952 | 163 | QString UbuntuI18n::tr(const QString& text) | ||
953 | 164 | { | ||
954 | 165 | return QString::fromUtf8(C::gettext(text.toUtf8())); | ||
955 | 166 | } | ||
956 | 167 | |||
957 | 168 | /*! | ||
958 | 169 | * \qmlmethod string i18n::tr(string singular, string plural, int n) | ||
959 | 170 | * Translate the given input string \a singular or \a plural (depending on the number of items \a n) | ||
960 | 171 | * using gettext. | ||
961 | 172 | * Note that tr() does not automatically insert the values in the QString, | ||
962 | 173 | * so it should be called like this: | ||
963 | 174 | * tr("%1 file", "%1 files", count).arg(count) | ||
964 | 175 | */ | ||
965 | 176 | QString UbuntuI18n::tr(const QString &singular, const QString &plural, int n) | ||
966 | 177 | { | ||
967 | 178 | return QString::fromUtf8(C::ngettext(singular.toUtf8(), plural.toUtf8(), n)); | ||
968 | 179 | } | ||
969 | 180 | |||
970 | 181 | /*! | ||
971 | 182 | * \qmlmethod string i18n::dtr(string domain, string text) | ||
972 | 183 | * Translate \a text using gettext. Uses the specified domain \a domain instead of i18n.domain. | ||
973 | 184 | */ | ||
974 | 185 | QString UbuntuI18n::dtr(const QString& domain, const QString& text) | ||
975 | 186 | { | ||
976 | 187 | if (domain.isNull()) { | ||
977 | 188 | return QString::fromUtf8(C::dgettext(NULL, text.toUtf8())); | ||
978 | 189 | } else { | ||
979 | 190 | return QString::fromUtf8(C::dgettext(domain.toUtf8(), text.toUtf8())); | ||
980 | 191 | } | ||
981 | 192 | } | ||
982 | 193 | |||
983 | 194 | /*! | ||
984 | 195 | * \qmlmethod string i18n::dtr(string domain, string singular, string plural, int n) | ||
985 | 196 | * Translate the given text using gettext. Should be called like this: | ||
986 | 197 | * tr(domain, "%1 file", "%1 files", count).arg(count) | ||
987 | 198 | * Uses \a domain for the domain instead of i18n.domain, and \a singular or \a plural | ||
988 | 199 | * as input for the translation depending on the number of items \a n. | ||
989 | 200 | */ | ||
990 | 201 | QString UbuntuI18n::dtr(const QString& domain, const QString& singular, const QString& plural, int n) | ||
991 | 202 | { | ||
992 | 203 | if (domain.isNull()) { | ||
993 | 204 | return QString::fromUtf8(C::dngettext(NULL, singular.toUtf8(), plural.toUtf8(), n)); | ||
994 | 205 | } else { | ||
995 | 206 | return QString::fromUtf8(C::dngettext(domain.toUtf8(), singular.toUtf8(), plural.toUtf8(), n)); | ||
996 | 207 | } | ||
997 | 208 | } | ||
998 | 209 | |||
999 | 210 | /*! | ||
1000 | 211 | * \qmlmethod string i18n::ctr(string context, string text) | ||
1001 | 212 | * Translate \a text using gettext and return the translation. | ||
1002 | 213 | * \a context is only visible to the translator and helps disambiguating for very short texts | ||
1003 | 214 | */ | ||
1004 | 215 | QString UbuntuI18n::ctr(const QString& context, const QString& text) | ||
1005 | 216 | { | ||
1006 | 217 | return dctr(QString(), context, text); | ||
1007 | 218 | } | ||
1008 | 219 | |||
1009 | 220 | /*! | ||
1010 | 221 | * \qmlmethod string i18n::dctr(string domain, string context, string text) | ||
1011 | 222 | * Translate \a text using gettext. Uses the specified domain \a domain instead of i18n.domain. | ||
1012 | 223 | * \a context is only visible to the translator and helps disambiguating for very short texts | ||
1013 | 224 | */ | ||
1014 | 225 | QString UbuntuI18n::dctr(const QString& domain, const QString& context, const QString& text) | ||
1015 | 226 | { | ||
1016 | 227 | if (domain.isNull()) { | ||
1017 | 228 | return QString::fromUtf8(C::g_dpgettext2(NULL, context.toUtf8(), text.toUtf8())); | ||
1018 | 229 | } else { | ||
1019 | 230 | return QString::fromUtf8(C::g_dpgettext2(domain.toUtf8(), context.toUtf8(), text.toUtf8())); | ||
1020 | 231 | } | ||
1021 | 232 | } | ||
1022 | 233 | |||
1023 | 234 | /*! | ||
1024 | 235 | * \qmlmethod string i18n::tag(string text) | ||
1025 | 236 | * Mark \a text for translation at a later point. Typically this allows an API | ||
1026 | 237 | * to take the original string and pass it to dtr (or dgettext). | ||
1027 | 238 | * | ||
1028 | 239 | * \qml | ||
1029 | 240 | * import QtQuick 2.4 | ||
1030 | 241 | * import UserMetrics 0.1 | ||
1031 | 242 | * | ||
1032 | 243 | * Metric { | ||
1033 | 244 | * name: "distance" | ||
1034 | 245 | * format: i18n.tag("Distance covered today: %1 km") | ||
1035 | 246 | * emptyFormat: i18n.tag("No running today") | ||
1036 | 247 | * domain: "runner.forest" | ||
1037 | 248 | * } | ||
1038 | 249 | * \endqml | ||
1039 | 250 | * | ||
1040 | 251 | * The strings tagged for localzation above are passed to the implementation | ||
1041 | 252 | * of UserMetrics verbatim, as well as the domain of the app. Display and | ||
1042 | 253 | * translation of the strings will happen in the lockscreen, where the same | ||
1043 | 254 | * strings will be passed to i18n.tr. | ||
1044 | 255 | */ | ||
1045 | 256 | QString UbuntuI18n::tag(const QString& text) | ||
1046 | 257 | { | ||
1047 | 258 | return text; | ||
1048 | 259 | } | ||
1049 | 260 | |||
1050 | 261 | /*! | ||
1051 | 262 | * \qmlmethod string i18n::tag(string context, string text) | ||
1052 | 263 | * Mark \a text for translation at a later point. Typically this allows an API | ||
1053 | 264 | * to take the original string and pass it to dctr (or g_dpgettext2). | ||
1054 | 265 | * \a context is only visible to the translator and helps disambiguating for very short texts | ||
1055 | 266 | */ | ||
1056 | 267 | QString UbuntuI18n::tag(const QString& context, const QString& text) | ||
1057 | 268 | { | ||
1058 | 269 | Q_UNUSED(context); | ||
1059 | 270 | return text; | ||
1060 | 271 | } | ||
1061 | 272 | /*! | ||
1062 | 273 | * \qmlmethod string i18n::relativeDateTime(datetime dateTime) | ||
1063 | 274 | * Translate a datetime based on proximity to current time. | ||
1064 | 275 | */ | ||
1065 | 276 | QString UbuntuI18n::relativeDateTime(const QDateTime& datetime) | ||
1066 | 277 | { | ||
1067 | 278 | static const QString ubuntuUiToolkit = QStringLiteral("ubuntu-ui-toolkit"); | ||
1068 | 279 | |||
1069 | 280 | QDateTime relativeTo(QDateTime::currentDateTime()); | ||
1070 | 281 | const date_proximity_t prox = getDateProximity(relativeTo, datetime); | ||
1071 | 282 | |||
1072 | 283 | switch (prox) { | ||
1073 | 284 | case DATE_PROXIMITY_NOW: | ||
1074 | 285 | /* TRANSLATORS: Time based "this is happening/happened now" */ | ||
1075 | 286 | return dtr(ubuntuUiToolkit, QStringLiteral("Now")); | ||
1076 | 287 | |||
1077 | 288 | case DATE_PROXIMITY_HOUR: | ||
1078 | 289 | { | ||
1079 | 290 | qint64 diff = datetime.toMSecsSinceEpoch() - relativeTo.toMSecsSinceEpoch(); | ||
1080 | 291 | qint64 minutes = qRound(float(diff) / 60000); | ||
1081 | 292 | if (minutes < 0) { | ||
1082 | 293 | return dtr(ubuntuUiToolkit, QStringLiteral("%1 minute ago"), | ||
1083 | 294 | QStringLiteral("%1 minutes ago"), qAbs(minutes)).arg(qAbs(minutes)); | ||
1084 | 295 | } | ||
1085 | 296 | return dtr(ubuntuUiToolkit, QStringLiteral("%1 minute"), | ||
1086 | 297 | QStringLiteral("%1 minutes"), minutes).arg(minutes); | ||
1087 | 298 | } | ||
1088 | 299 | |||
1089 | 300 | case DATE_PROXIMITY_TODAY: | ||
1090 | 301 | /* en_US example: "1:00 PM" */ | ||
1091 | 302 | /* TRANSLATORS: Please translate these to your locale datetime | ||
1092 | 303 | format using the format specified by | ||
1093 | 304 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
1094 | 305 | return datetime.toString(isLocale12h() | ||
1095 | 306 | ? dtr(ubuntuUiToolkit, QStringLiteral("h:mm ap")) | ||
1096 | 307 | /* TRANSLATORS: Please translate these to your locale datetime | ||
1097 | 308 | format using the format specified by | ||
1098 | 309 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
1099 | 310 | : dtr(ubuntuUiToolkit, QStringLiteral("HH:mm"))); | ||
1100 | 311 | |||
1101 | 312 | case DATE_PROXIMITY_YESTERDAY: | ||
1102 | 313 | /* en_US example: "Yesterday 13:00" */ | ||
1103 | 314 | /* TRANSLATORS: Please translate these to your locale datetime | ||
1104 | 315 | format using the format specified by | ||
1105 | 316 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
1106 | 317 | return datetime.toString(isLocale12h() | ||
1107 | 318 | ? dtr(ubuntuUiToolkit, QStringLiteral("'Yesterday\u2003'h:mm ap")) | ||
1108 | 319 | /* TRANSLATORS: Please translate these to your locale datetime | ||
1109 | 320 | format using the format specified by | ||
1110 | 321 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
1111 | 322 | : dtr(ubuntuUiToolkit, QStringLiteral("'Yesterday\u2003'HH:mm"))); | ||
1112 | 323 | |||
1113 | 324 | case DATE_PROXIMITY_TOMORROW: | ||
1114 | 325 | /* en_US example: "Tomorrow 1:00 PM" */ | ||
1115 | 326 | /* TRANSLATORS: Please translate these to your locale datetime | ||
1116 | 327 | format using the format specified by | ||
1117 | 328 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
1118 | 329 | return datetime.toString(isLocale12h() | ||
1119 | 330 | ? dtr(ubuntuUiToolkit, QStringLiteral("'Tomorrow\u2003'h:mm ap")) | ||
1120 | 331 | /* TRANSLATORS: Please translate these to your locale datetime | ||
1121 | 332 | format using the format specified by | ||
1122 | 333 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
1123 | 334 | : dtr(ubuntuUiToolkit, QStringLiteral("'Tomorrow\u2003'HH:mm"))); | ||
1124 | 335 | |||
1125 | 336 | case DATE_PROXIMITY_LAST_WEEK: | ||
1126 | 337 | case DATE_PROXIMITY_NEXT_WEEK: | ||
1127 | 338 | /* en_US example: "Fri 1:00 PM" */ | ||
1128 | 339 | /* TRANSLATORS: Please translate these to your locale datetime | ||
1129 | 340 | format using the format specified by | ||
1130 | 341 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
1131 | 342 | return datetime.toString(isLocale12h() | ||
1132 | 343 | ? dtr(ubuntuUiToolkit, QStringLiteral("ddd'\u2003'h:mm ap")) | ||
1133 | 344 | /* TRANSLATORS: Please translate these to your locale datetime | ||
1134 | 345 | format using the format specified by | ||
1135 | 346 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
1136 | 347 | : dtr(ubuntuUiToolkit, QStringLiteral("ddd'\u2003'HH:mm"))); | ||
1137 | 348 | |||
1138 | 349 | case DATE_PROXIMITY_FAR_BACK: | ||
1139 | 350 | case DATE_PROXIMITY_FAR_FORWARD: | ||
1140 | 351 | default: | ||
1141 | 352 | /* TRANSLATORS: Please translate these to your locale datetime | ||
1142 | 353 | format using the format specified by | ||
1143 | 354 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
1144 | 355 | return datetime.toString(isLocale12h() | ||
1145 | 356 | ? dtr(ubuntuUiToolkit, QStringLiteral("ddd d MMM'\u2003'h:mm ap")) | ||
1146 | 357 | /* TRANSLATORS: Please translate these to your locale datetime | ||
1147 | 358 | format using the format specified by | ||
1148 | 359 | https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */ | ||
1149 | 360 | : dtr(ubuntuUiToolkit, QStringLiteral("ddd d MMM'\u2003'HH:mm"))); | ||
1150 | 361 | } | ||
1151 | 362 | return datetime.toString(Qt::DefaultLocaleShortDate); | ||
1152 | 363 | } | ||
1153 | 364 | |||
1154 | 365 | UT_NAMESPACE_END |
FAILED: Continuous integration, rev:2121 /jenkins. ubuntu. com/ubuntu- sdk/job/ ubuntu- ui-toolkit- ci-i386- gles-stable/ 1227/ /jenkins. ubuntu. com/ubuntu- sdk/job/ generic- update- mp/6681/ console
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild: /jenkins. ubuntu. com/ubuntu- sdk/job/ ubuntu- ui-toolkit- ci-i386- gles-stable/ 1227/rebuild
https:/