Skip to content

Commit 85aaa55

Browse files
gielwijgergangsoscarotero
authored andcommitted
VueJS HTML tag support in extractor (#205)
* Add VUE js tagname support (vue-gettext) * add vue tag tests * restore formatting
1 parent dc92f65 commit 85aaa55

13 files changed

Lines changed: 185 additions & 17 deletions

File tree

src/Extractors/VueJs.php

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,25 @@ public static function fromString($string, Translations $translations, array $op
2727
'v-bind:',
2828
'v-on:',
2929
],
30+
// HTML Tags to parse
31+
'tagNames' => [
32+
'translate',
33+
],
34+
// HTML tags to parse when attribute exists
35+
'tagAttributes' => [
36+
'v-translate'
37+
],
38+
// Comments
39+
'commentAttributes' => [
40+
'translate-comment'
41+
],
42+
'contextAttributes' => [
43+
'translate-context'
44+
],
45+
// Attribute with plural content
46+
'pluralAttributes' => [
47+
'translate-plural'
48+
]
3049
];
3150

3251
// Ok, this is the weirdest hack, but let me explain:
@@ -67,6 +86,7 @@ public static function fromString($string, Translations $translations, array $op
6786
$template->getLineNo() - 1
6887
);
6988
}
89+
7090
}
7191

7292
/**
@@ -145,6 +165,60 @@ private static function getTemplateTranslations(
145165
// Build a JS string from template element content expressions
146166
$fakeTemplateJs = self::getTemplateFakeJs($dom);
147167
self::getScriptTranslationsFromString($fakeTemplateJs, $translations, $options, $lineOffset);
168+
169+
self::getTagTranslations($options, $dom, $translations);
170+
}
171+
172+
/**
173+
* @param array $options
174+
* @param DOMElement $dom
175+
* @param Translations $translations
176+
*/
177+
private static function getTagTranslations(array $options, DOMElement $dom, Translations $translations)
178+
{
179+
$children = $dom->childNodes;
180+
for ($i = 0; $i < $children->length; $i++) {
181+
$node = $children->item($i);
182+
183+
if (!($node instanceof DOMElement)) {
184+
continue;
185+
}
186+
$translatable = false;
187+
if (\in_array($node->tagName, $options['tagNames'])) {
188+
$translatable = true;
189+
}
190+
$attrList = $node->attributes;
191+
$context = null;
192+
$plural = "";
193+
$comment = null;
194+
for ($j = 0; $j < $attrList->length; $j++) {
195+
/** @var DOMAttr $domAttr */
196+
$domAttr = $attrList->item($j);
197+
// Check if this is a dynamic vue attribute
198+
if (\in_array($domAttr->name, $options['tagAttributes'])) {
199+
$translatable = true;
200+
}
201+
if (\in_array($domAttr->name, $options['contextAttributes'])) {
202+
$context = $domAttr->value;
203+
}
204+
if (\in_array($domAttr->name, $options['pluralAttributes'])) {
205+
$plural = $domAttr->value;
206+
}
207+
if (\in_array($domAttr->name, $options['commentAttributes'])) {
208+
$comment = $domAttr->value;
209+
}
210+
}
211+
if ($translatable) {
212+
$translation = $translations->insert($context, \trim($node->textContent), $plural);
213+
$translation->addReference($options['file'], $node->getLineNo());
214+
if ($comment) {
215+
$translation->addExtractedComment($comment);
216+
}
217+
}
218+
if ($node->hasChildNodes()) {
219+
self::getTagTranslations($options, $node, $translations);
220+
}
221+
}
148222
}
149223

150224
/**
@@ -197,7 +271,6 @@ private static function getVueAttributeExpressions(
197271
if (!($node instanceof DOMElement)) {
198272
continue;
199273
}
200-
201274
$attrList = $node->attributes;
202275

203276
for ($j = 0; $j < $attrList->length; $j++) {

tests/AssetsTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ public function testTwig()
421421
public function testVueJs()
422422
{
423423
$translations = static::get('vuejs/input', 'VueJs');
424-
$countTranslations = 28;
424+
$countTranslations = 31;
425425
$countTranslated = 0;
426426
$countHeaders = 8;
427427

tests/assets/vuejs/Csv.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ context,t-action,
3535
,t-spaces-expr2,
3636
,t-p1(parentheses),
3737
context2,t-action2,
38+
,t-tag-2,
39+
,v-translate-attribute,
40+
,v-translate-attribute-single,

tests/assets/vuejs/CsvDictionary.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ t-spaces-expr,
2626
t-spaces-expr2,
2727
t-p1(parentheses),
2828
t-action2,
29+
t-tag-2,
30+
v-translate-attribute,
31+
v-translate-attribute-single,

tests/assets/vuejs/Jed.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,15 @@
8888
],
8989
"context2\\u0004t-action2": [
9090
""
91+
],
92+
"t-tag-2": [
93+
""
94+
],
95+
"v-translate-attribute": [
96+
""
97+
],
98+
"v-translate-attribute-single": [
99+
""
91100
]
92101
}
93102
}

tests/assets/vuejs/Json.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@
8080
],
8181
"t-p1(parentheses)": [
8282
""
83+
],
84+
"t-tag-2": [
85+
""
86+
],
87+
"v-translate-attribute": [
88+
""
89+
],
90+
"v-translate-attribute-single": [
91+
""
8392
]
8493
},
8594
"some-context": {

tests/assets/vuejs/JsonDictionary.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,8 @@
2626
"t-spaces-expr": "",
2727
"t-spaces-expr2": "",
2828
"t-p1(parentheses)": "",
29-
"t-action2": ""
29+
"t-action2": "",
30+
"t-tag-2": "",
31+
"v-translate-attribute": "",
32+
"v-translate-attribute-single": ""
3033
}

tests/assets/vuejs/PhpArray.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,18 @@
117117
array (
118118
0 => '',
119119
),
120+
't-tag-2' =>
121+
array (
122+
0 => '',
123+
),
124+
'v-translate-attribute' =>
125+
array (
126+
0 => '',
127+
),
128+
'v-translate-attribute-single' =>
129+
array (
130+
0 => '',
131+
),
120132
),
121133
'some-context' =>
122134
array (

tests/assets/vuejs/Po.po

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,34 @@ msgstr ""
99
"Project-Id-Version: \n"
1010
"Report-Msgid-Bugs-To: \n"
1111

12-
#: ./tests/assets/vuejs/input.vue:42
12+
#: ./tests/assets/vuejs/input.vue:49
1313
msgid "js-expr1"
1414
msgstr ""
1515

16-
#: ./tests/assets/vuejs/input.vue:42
16+
#: ./tests/assets/vuejs/input.vue:49
1717
msgid "js-expr2"
1818
msgstr ""
1919

20-
#: ./tests/assets/vuejs/input.vue:44
20+
#: ./tests/assets/vuejs/input.vue:51
2121
msgid "js-alert"
2222
msgstr ""
2323

24-
#: ./tests/assets/vuejs/input.vue:47
24+
#: ./tests/assets/vuejs/input.vue:54
2525
msgid "js-single"
2626
msgid_plural "js-plural"
2727
msgstr[0] ""
2828

29-
#: ./tests/assets/vuejs/input.vue:51
29+
#: ./tests/assets/vuejs/input.vue:58
3030
msgid "js-obj-single"
3131
msgid_plural "js-obj-plural"
3232
msgstr[0] ""
3333

34-
#: ./tests/assets/vuejs/input.vue:54
34+
#: ./tests/assets/vuejs/input.vue:61
3535
msgctxt "some-context"
3636
msgid "js-action"
3737
msgstr ""
3838

39-
#: ./tests/assets/vuejs/input.vue:56
39+
#: ./tests/assets/vuejs/input.vue:63
4040
msgid "<span>js-return</span><br>"
4141
msgstr ""
4242

@@ -131,3 +131,16 @@ msgstr[0] ""
131131
msgctxt "context2"
132132
msgid "t-action2"
133133
msgstr ""
134+
135+
#: ./tests/assets/vuejs/input.vue:37
136+
msgid "t-tag-2"
137+
msgstr ""
138+
139+
#: ./tests/assets/vuejs/input.vue:39
140+
msgid "v-translate-attribute"
141+
msgstr ""
142+
143+
#: ./tests/assets/vuejs/input.vue:41
144+
msgid "v-translate-attribute-single"
145+
msgid_plural "v-translate-attribute-plural"
146+
msgstr[0] ""

tests/assets/vuejs/Xliff.xlf

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<unit id="38dbba24eb02d64da6159a778a36d73a">
1515
<notes>
1616
<note category="context"></note>
17-
<note category="reference">./tests/assets/vuejs/input.vue:42</note>
17+
<note category="reference">./tests/assets/vuejs/input.vue:49</note>
1818
</notes>
1919
<segment>
2020
<source>js-expr1</source>
@@ -24,7 +24,7 @@
2424
<unit id="e8955f4e596af6cbcdfb35f22ba26dbd">
2525
<notes>
2626
<note category="context"></note>
27-
<note category="reference">./tests/assets/vuejs/input.vue:42</note>
27+
<note category="reference">./tests/assets/vuejs/input.vue:49</note>
2828
</notes>
2929
<segment>
3030
<source>js-expr2</source>
@@ -34,7 +34,7 @@
3434
<unit id="4819d163f4b26023f7ba7d6a20d8473e">
3535
<notes>
3636
<note category="context"></note>
37-
<note category="reference">./tests/assets/vuejs/input.vue:44</note>
37+
<note category="reference">./tests/assets/vuejs/input.vue:51</note>
3838
</notes>
3939
<segment>
4040
<source>js-alert</source>
@@ -44,7 +44,7 @@
4444
<unit id="8a33b4fd199bcbc69fbdf4c7bce48b90">
4545
<notes>
4646
<note category="context"></note>
47-
<note category="reference">./tests/assets/vuejs/input.vue:47</note>
47+
<note category="reference">./tests/assets/vuejs/input.vue:54</note>
4848
</notes>
4949
<segment>
5050
<source>js-single</source>
@@ -54,7 +54,7 @@
5454
<unit id="b81ee1ffb034bd2cf1ec589349c4d069">
5555
<notes>
5656
<note category="context"></note>
57-
<note category="reference">./tests/assets/vuejs/input.vue:51</note>
57+
<note category="reference">./tests/assets/vuejs/input.vue:58</note>
5858
</notes>
5959
<segment>
6060
<source>js-obj-single</source>
@@ -64,7 +64,7 @@
6464
<unit id="db5923b843960d8cc6e2064bb2d4fbc2">
6565
<notes>
6666
<note category="context">some-context</note>
67-
<note category="reference">./tests/assets/vuejs/input.vue:54</note>
67+
<note category="reference">./tests/assets/vuejs/input.vue:61</note>
6868
</notes>
6969
<segment>
7070
<source>js-action</source>
@@ -74,7 +74,7 @@
7474
<unit id="165738b03fc41d793cf080ad7f3bf5e3">
7575
<notes>
7676
<note category="context"></note>
77-
<note category="reference">./tests/assets/vuejs/input.vue:56</note>
77+
<note category="reference">./tests/assets/vuejs/input.vue:63</note>
7878
</notes>
7979
<segment>
8080
<source><![CDATA[<span>js-return</span><br>]]></source>
@@ -293,5 +293,35 @@
293293
<target></target>
294294
</segment>
295295
</unit>
296+
<unit id="366e5ec376b0ffdf583eeb223e42ff79">
297+
<notes>
298+
<note category="context"></note>
299+
<note category="reference">./tests/assets/vuejs/input.vue:37</note>
300+
</notes>
301+
<segment>
302+
<source>t-tag-2</source>
303+
<target></target>
304+
</segment>
305+
</unit>
306+
<unit id="1326b21a1daa0935a04ae1abe5204028">
307+
<notes>
308+
<note category="context"></note>
309+
<note category="reference">./tests/assets/vuejs/input.vue:39</note>
310+
</notes>
311+
<segment>
312+
<source>v-translate-attribute</source>
313+
<target></target>
314+
</segment>
315+
</unit>
316+
<unit id="6d605b588286108b6b7271ffad83c1ba">
317+
<notes>
318+
<note category="context"></note>
319+
<note category="reference">./tests/assets/vuejs/input.vue:41</note>
320+
</notes>
321+
<segment>
322+
<source>v-translate-attribute-single</source>
323+
<target></target>
324+
</segment>
325+
</unit>
296326
</file>
297327
</xliff>

0 commit comments

Comments
 (0)