Merge lp:~dpm/intltool/add-qtdesigner-support into lp:intltool

Proposed by David Planella
Status: Merged
Merged at revision: 744
Proposed branch: lp:~dpm/intltool/add-qtdesigner-support
Merge into: lp:intltool
Diff against target: 392 lines (+306/-1)
7 files modified
doc/intltool-extract.8 (+2/-0)
intltool-extract.in (+73/-1)
tests/cases/Makefile.am (+2/-0)
tests/cases/extract-qtdesigner.ui (+210/-0)
tests/results/Makefile.am (+1/-0)
tests/results/extract-qtdesigner.ui.h (+13/-0)
tests/selftest.pl.in (+5/-0)
To merge this branch: bzr merge lp:~dpm/intltool/add-qtdesigner-support
Reviewer Review Type Date Requested Status
Данило Шеган Approve
Review via email: mp+145112@code.launchpad.net

Description of the change

This branch adds support for extracting translatable strings from Qt Designer files through a new gettext/qtdesigner type (lp:953342).

Notes: the regexp used to extract the strings from the XML attributes of the <string> tag used by Qt .ui files is similar to the one used to extraxt strings from Glade .ui files in the sense that it relies on those tags being present in a particular order.

To post a comment you must log in.
Revision history for this message
Данило Шеган (danilo) wrote :

Btw, at least the doc links are incorrect in intltool-extract.in:

 - http://qt-project.org/doc/qt-5.0/qtlinguist/linguist-ts-file-format.html
 - http://qt-project.org/doc/qt-5.0/qtdesigner/designer-ui-file-format.html

are currently correct links (I assume they have changed since you started work on this).

Btw, I would prefer if the support was done using the real XML parser: that would ensure that a lot more of the XML syntax is supported, and that we don't accidentally break when eg. the order of attributes changes in the XML file.

A good example is type_gsettings/traverse_gsettings functions.

review: Needs Fixing
739. By David Planella

Updated links to Qt translation format specs

740. By David Planella

Updated test case for Qt Designer extraction: no escapes

741. By David Planella

Added Qt Designer .ui file extraction support using the internal XML parser

742. By David Planella

Updated man page with the new gettext/qtdesigner type for extraction

743. By David Planella

Added files for gettext/qtdesigner testcase and result to the corresponding Makefile.am files

Revision history for this message
David Planella (dpm) wrote :

Ok, addressed the two points above and re-submitted MP.

Revision history for this message
Rohan Garg (rohangarg) wrote :

Any ETA when this is going to land? This also fixes bug 1234106 for Kubuntu so it'll be nice to have it land soon.

Revision history for this message
Данило Шеган (danilo) wrote :

Hi David (and other interested parties): sorry for taking this long to take another look at this. It somehow slipped my radar (so thanks everyone for reminding me).

The branch looks pretty good. Since you are also doing special whitespace handling, it would be good to have at least one of the strings in a test case actually demonstrate that. Since I've taken this long to review it, I'll do this myself.

I'll be merging this branch, but I won't be releasing it until we clarify a few other things. I am most worried about the escaping support. One of the examples in the test case is an HTML string, but ideally, that'd be unescaped in PO files (for translators' benefit). Where's the code that actually reads MO files? Is there any good example code for me to check out to see how would everything fit together?

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'doc/intltool-extract.8'
--- doc/intltool-extract.8 2011-10-08 19:24:23 +0000
+++ doc/intltool-extract.8 2013-05-10 09:59:25 +0000
@@ -54,6 +54,8 @@
54"gettext/scheme" (.scm)54"gettext/scheme" (.scm)
55.br55.br
56"gettext/xml" (Generic XML file)56"gettext/xml" (Generic XML file)
57.br
58"gettext/qtdesigner" (Qt Designer .ui files)
57.IP "\fB\-v\fR" 459.IP "\fB\-v\fR" 4
58.PD 060.PD 0
59.IP "\fB\--version\fR" 461.IP "\fB\--version\fR" 4
6062
=== modified file 'intltool-extract.in'
--- intltool-extract.in 2012-08-23 03:39:02 +0000
+++ intltool-extract.in 2013-05-10 09:59:25 +0000
@@ -165,7 +165,7 @@
165 "gettext/glade", "gettext/ini", "gettext/keys"165 "gettext/glade", "gettext/ini", "gettext/keys"
166 "gettext/rfc822deb", "gettext/schemas",166 "gettext/rfc822deb", "gettext/schemas",
167 "gettext/gsettings", "gettext/xml", "gettext/quoted",167 "gettext/gsettings", "gettext/xml", "gettext/quoted",
168 "gettext/quotedxml", "gettext/tlk"168 "gettext/quotedxml", "gettext/tlk", "gettext/qtdesigner"
169 -l, --local Writes output into current working directory169 -l, --local Writes output into current working directory
170 (conflicts with --update)170 (conflicts with --update)
171 --update Writes output into the same directory the source file171 --update Writes output into the same directory the source file
@@ -225,6 +225,7 @@
225 &type_quoted if $gettext_type eq "quoted";225 &type_quoted if $gettext_type eq "quoted";
226 &type_quotedxml if $gettext_type eq "quotedxml";226 &type_quotedxml if $gettext_type eq "quotedxml";
227 &type_tlk if $gettext_type eq "tlk";227 &type_tlk if $gettext_type eq "tlk";
228 &type_qtdesigner if $gettext_type eq "qtdesigner";
228}229}
229230
230sub entity_decode_minimal231sub entity_decode_minimal
@@ -828,6 +829,77 @@
828 }829 }
829}830}
830831
832# Parse the tree as returned by readXml() for Qt Designer .ui files.
833sub traverse_qtdesigner {
834 my $nodename = shift;
835 my $content = shift;
836 my @list = @{ $content };
837 my $attrs_ref = shift @list;
838 my %attrs = %{ $attrs_ref };
839 if ($nodename eq 'string' and !exists $attrs{"notr"}) {
840 # Preserve whitespace. Deal with it ourselves, below.
841 my $message = getXMLstring($content, 1);
842
843 # We strip leading and trailing whitespace but
844 # preserve whitespace within (e.g. newlines)
845 $message =~ s/^\s+//;
846 $message =~ s/\s+$//;
847
848 my $context = $attrs{'comment'};
849 # Remove enclosing quotes from msgctxt
850 $context =~ s/^["'](.*)["']/$1/ if $context;
851 $message = $context . "\004" . $message if $context;
852 add_message($message);
853 my $comment = $attrs{'extracomment'};
854 # Remove enclosing quotes from developer comments
855 $comment =~ s/^["'](.*)["']/$1/ if $comment;
856 $comments{$message} = $comment if $comment;
857 } else {
858 my $index = 0;
859 while (scalar(@list) > 1) {
860 my $type = shift @list;
861 my $content = shift @list;
862 if (!$type || "$type" eq "1") {
863 next;
864 } else {
865 traverse_qtdesigner($type, $content);
866 }
867 }
868 }
869}
870
871sub type_qtdesigner {
872 ### For translatable Qt Designer XML files ###
873 #
874 # Specs:
875 #
876 # - http://qt-project.org/doc/qt-5.0/qtlinguist/linguist-ts-file-format.html
877 # - http://qt-project.org/doc/qt-5.0/qtdesigner/designer-ui-file-format.html
878 #
879 # <string> tag attributes:
880 #
881 # notr="true" means the string is not translatable
882 # extracomment maps to a developer comment in gettext
883 # comment corresponds to "disambiguation" in the Qt Linguist API, and maps
884 # to msgctxt in gettext
885 #
886 # Example:
887 #
888 # <string comment="Button" extracomment="TRANSLATORS: refers to the
889 # action of accepting something">Ok</string>
890
891 my $tree = readXml($input);
892 my @tree_nodes = @{ $tree };
893 my $node = shift @tree_nodes;
894 while (!$node || "$node" eq "1") {
895 shift @tree_nodes;
896 $node = shift @tree_nodes;
897 }
898 my $content = shift @tree_nodes;
899 traverse_qtdesigner($node, $content);
900
901}
902
831sub type_glade {903sub type_glade {
832 ### For translatable Glade XML files ###904 ### For translatable Glade XML files ###
833905
834906
=== modified file 'tests/cases/Makefile.am'
--- tests/cases/Makefile.am 2011-10-08 18:08:58 +0000
+++ tests/cases/Makefile.am 2013-05-10 09:59:25 +0000
@@ -16,6 +16,7 @@
16 extract8.glade \16 extract8.glade \
17 extract9.po \17 extract9.po \
18 extract9.xml.in \18 extract9.xml.in \
19 extract-qtdesigner.ui \
19 fr.po \20 fr.po \
20 fr_BE.po \21 fr_BE.po \
21 fr_FR.po \22 fr_FR.po \
@@ -58,6 +59,7 @@
58 extract14.xml.in.h \59 extract14.xml.in.h \
59 extract9.xml \60 extract9.xml \
60 extract9.xml.in.h \61 extract9.xml.in.h \
62 extract-qtdesigner.ui.h \
61 gsettings.gschema.xml.h \63 gsettings.gschema.xml.h \
62 iso88591text.xml.in.h \64 iso88591text.xml.in.h \
63 merge-cdata.xml \65 merge-cdata.xml \
6466
=== added file 'tests/cases/extract-qtdesigner.ui'
--- tests/cases/extract-qtdesigner.ui 1970-01-01 00:00:00 +0000
+++ tests/cases/extract-qtdesigner.ui 2013-05-10 09:59:25 +0000
@@ -0,0 +1,210 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>main</class>
4 <widget class="QWidget" name="main">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>640</width>
10 <height>457</height>
11 </rect>
12 </property>
13 <property name="sizePolicy">
14 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
15 <horstretch>0</horstretch>
16 <verstretch>0</verstretch>
17 </sizepolicy>
18 </property>
19 <property name="windowTitle">
20 <string>Form</string>
21 </property>
22 <layout class="QHBoxLayout" name="horizontalLayout">
23 <property name="spacing">
24 <number>0</number>
25 </property>
26 <property name="margin">
27 <number>0</number>
28 </property>
29 <item>
30 <widget class="QTabWidget" name="tabWidget">
31 <property name="currentIndex">
32 <number>0</number>
33 </property>
34 <widget class="QWidget" name="tabWelcome">
35 <attribute name="title">
36 <string notr="true">Do not translate this</string>
37 </attribute>
38 <layout class="QHBoxLayout" name="horizontalLayout_5">
39 <property name="spacing">
40 <number>0</number>
41 </property>
42 <property name="margin">
43 <number>0</number>
44 </property>
45 <item>
46 <layout class="QVBoxLayout" name="verticalLayout_5">
47 <property name="spacing">
48 <number>0</number>
49 </property>
50 <item>
51 <widget class="QWidget" name="welcomeTop" native="true">
52 <property name="sizePolicy">
53 <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
54 <horstretch>0</horstretch>
55 <verstretch>0</verstretch>
56 </sizepolicy>
57 </property>
58 <property name="minimumSize">
59 <size>
60 <width>0</width>
61 <height>100</height>
62 </size>
63 </property>
64 <layout class="QVBoxLayout" name="verticalLayout_6">
65 <property name="spacing">
66 <number>0</number>
67 </property>
68 <property name="margin">
69 <number>0</number>
70 </property>
71 <item>
72 <layout class="QHBoxLayout" name="horizontalLayout_4">
73 <property name="spacing">
74 <number>0</number>
75 </property>
76 <item>
77 <widget class="QWidget" name="welcomeTopText" native="true">
78 <widget class="QLabel" name="welcomeLabel">
79 <property name="geometry">
80 <rect>
81 <x>30</x>
82 <y>20</y>
83 <width>330</width>
84 <height>51</height>
85 </rect>
86 </property>
87 <property name="font">
88 <font>
89 <family>Ubuntu</family>
90 <pointsize>21</pointsize>
91 </font>
92 </property>
93 <property name="text">
94 <string extracomment="TRANSLATORS: this is the main title of the authentication dialog">This is a translatable title</string>
95 </property>
96 </widget>
97 </widget>
98 </item>
99 </layout>
100 </item>
101 </layout>
102 </widget>
103 </item>
104 <item>
105 <widget class="QWidget" name="welcomeBottom" native="true">
106 <property name="sizePolicy">
107 <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
108 <horstretch>0</horstretch>
109 <verstretch>0</verstretch>
110 </sizepolicy>
111 </property>
112 <property name="minimumSize">
113 <size>
114 <width>0</width>
115 <height>0</height>
116 </size>
117 </property>
118 <widget class="QTextEdit" name="welcomeTextBox">
119 <property name="geometry">
120 <rect>
121 <x>30</x>
122 <y>20</y>
123 <width>571</width>
124 <height>181</height>
125 </rect>
126 </property>
127 <property name="frameShape">
128 <enum>QFrame::NoFrame</enum>
129 </property>
130 <property name="frameShadow">
131 <enum>QFrame::Plain</enum>
132 </property>
133 <property name="readOnly">
134 <bool>true</bool>
135 </property>
136 <property name="html">
137 <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
138&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;title&gt;HTML document extraction test&lt;/title&gt;&lt;style type=&quot;text/css&quot;&gt;
139p, li { white-space: pre-wrap; }
140&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
141&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Once upon a time, in a galaxy far, far away... &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
142 </property>
143 </widget>
144 <widget class="QPushButton" name="friendlyTestsButton">
145 <property name="geometry">
146 <rect>
147 <x>30</x>
148 <y>210</y>
149 <width>571</width>
150 <height>31</height>
151 </rect>
152 </property>
153 <property name="font">
154 <font>
155 <pointsize>9</pointsize>
156 </font>
157 </property>
158 <property name="text">
159 <string comment="Button" extracomment="TRANSLATORS: refers to the action of accepting something">Ok</string>
160 </property>
161 </widget>
162 <widget class="QCheckBox" name="checkBox">
163 <property name="geometry">
164 <rect>
165 <x>30</x>
166 <y>280</y>
167 <width>321</width>
168 <height>20</height>
169 </rect>
170 </property>
171 <property name="font">
172 <font>
173 <family>Ubuntu</family>
174 </font>
175 </property>
176 <property name="text">
177 <string comment="WelcomeDialog">Don't show me this message in the future</string>
178 </property>
179 </widget>
180 <widget class="QCheckBox" name="checkBox_2">
181 <property name="geometry">
182 <rect>
183 <x>30</x>
184 <y>260</y>
185 <width>321</width>
186 <height>20</height>
187 </rect>
188 </property>
189 <property name="font">
190 <font>
191 <family>Ubuntu</family>
192 </font>
193 </property>
194 <property name="text">
195 <string extracomment="TRANSLATORS: authentication is required to perform this action">Require authentication</string>
196 </property>
197 </widget>
198 </widget>
199 </item>
200 </layout>
201 </item>
202 </layout>
203 </widget>
204 </widget>
205 </item>
206 </layout>
207 </widget>
208 <resources/>
209 <connections/>
210</ui>
0211
=== modified file 'tests/results/Makefile.am'
--- tests/results/Makefile.am 2011-10-08 18:08:58 +0000
+++ tests/results/Makefile.am 2013-05-10 09:59:25 +0000
@@ -17,6 +17,7 @@
17 extract12.xml.in.h \17 extract12.xml.in.h \
18 extract14.xml.in.h \18 extract14.xml.in.h \
19 extract-gtkbuilder.ui.h \19 extract-gtkbuilder.ui.h \
20 extract-qtdesigner.ui.h \
20 gsettings.gschema.xml.h \21 gsettings.gschema.xml.h \
21 iso88591text.xml.in.h \22 iso88591text.xml.in.h \
22 merge-cdata.xml \23 merge-cdata.xml \
2324
=== added file 'tests/results/extract-qtdesigner.ui.h'
--- tests/results/extract-qtdesigner.ui.h 1970-01-01 00:00:00 +0000
+++ tests/results/extract-qtdesigner.ui.h 2013-05-10 09:59:25 +0000
@@ -0,0 +1,13 @@
1char *s = N_("Form");
2/* TRANSLATORS: this is the main title of the authentication dialog */
3char *s = N_("This is a translatable title");
4char *s = N_("&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;\n"
5 "&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;title&gt;HTML document extraction test&lt;/title&gt;&lt;style type=&quot;text/css&quot;&gt;\n"
6 "p, li { white-space: pre-wrap; }\n"
7 "&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;\n"
8 "&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Once upon a time, in a galaxy far, far away... &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;");
9/* TRANSLATORS: refers to the action of accepting something */
10char *s = C_("Button", "Ok");
11char *s = C_("WelcomeDialog", "Don't show me this message in the future");
12/* TRANSLATORS: authentication is required to perform this action */
13char *s = N_("Require authentication");
014
=== modified file 'tests/selftest.pl.in'
--- tests/selftest.pl.in 2012-08-23 03:39:02 +0000
+++ tests/selftest.pl.in 2013-05-10 09:59:25 +0000
@@ -294,6 +294,11 @@
294system("$INTLTOOL_EXTRACT --type=gettext/glade --quiet --update cases/$case") == 0 or $failed = 1;294system("$INTLTOOL_EXTRACT --type=gettext/glade --quiet --update cases/$case") == 0 or $failed = 1;
295check_extract_result($case);295check_extract_result($case);
296296
297print "40. Extract messages from a Qt Designer UI file: ";
298$case = "extract-qtdesigner.ui";
299system("$INTLTOOL_EXTRACT --type=gettext/qtdesigner --quiet --update cases/$case") == 0 or $failed = 1;
300check_extract_result($case);
301
297302
298system("rm -f cases/*.*") if $srcdir ne ".";303system("rm -f cases/*.*") if $srcdir ne ".";
299system("rm -rf C az extract9 fr fr_BE fr_FR merge6 schemasmerge1 schemasmerge2 spacepreserve test test-quoted merge6.xml");304system("rm -rf C az extract9 fr fr_BE fr_FR merge6 schemasmerge1 schemasmerge2 spacepreserve test test-quoted merge6.xml");

Subscribers

People subscribed via source and target branches