@@ -20,6 +20,14 @@ class VueJs extends JsCode implements ExtractorInterface
2020 public static function fromString ($ string , Translations $ translations , array $ options = [])
2121 {
2222 $ options += self ::$ options ;
23+ $ options += [
24+ // HTML attribute prefixes we parse as JS which could contain translations (are JS expressions)
25+ 'attributePrefixes ' => [
26+ ': ' ,
27+ 'v-bind: ' ,
28+ 'v-on: ' ,
29+ ],
30+ ];
2331
2432 // Ok, this is the weirdest hack, but let me explain:
2533 // On Linux (Mac is fine), when converting HTML to DOM, new lines get trimmed after the first tag.
@@ -111,7 +119,7 @@ private static function getTemplateTranslations(
111119 $ lineOffset = 0
112120 ) {
113121 // Build a JS string from all template attribute expressions
114- $ fakeAttributeJs = self ::getTemplateAttributeFakeJs ($ dom );
122+ $ fakeAttributeJs = self ::getTemplateAttributeFakeJs ($ options , $ dom );
115123
116124 // 1 line offset is necessary because parent template element was ignored when converting to DOM
117125 self ::getScriptTranslationsFromString ($ fakeAttributeJs , $ translations , $ options , $ lineOffset );
@@ -125,12 +133,13 @@ private static function getTemplateTranslations(
125133 * Extract JS expressions from element attribute bindings (excluding text within elements)
126134 * For example: <span :title="__('extract this')"> skip element content </span>
127135 *
136+ * @param array $options
128137 * @param DOMElement $dom
129138 * @return string JS code
130139 */
131- private static function getTemplateAttributeFakeJs (DOMElement $ dom )
140+ private static function getTemplateAttributeFakeJs (array $ options , DOMElement $ dom )
132141 {
133- $ expressionsByLine = self ::getVueAttributeExpressions ($ dom );
142+ $ expressionsByLine = self ::getVueAttributeExpressions ($ options [ ' attributePrefixes ' ], $ dom );
134143
135144 $ maxLines = max (array_keys ($ expressionsByLine ));
136145 $ fakeJs = '' ;
@@ -148,12 +157,16 @@ private static function getTemplateAttributeFakeJs(DOMElement $dom)
148157 /**
149158 * Loop DOM element recursively and parse out all dynamic vue attributes which are basically JS expressions
150159 *
160+ * @param array $attributePrefixes List of attribute prefixes we parse as JS (may contain translations)
151161 * @param DOMElement $dom
152162 * @param array $expressionByLine [lineNumber => [jsExpression, ..], ..]
153163 * @return array [lineNumber => [jsExpression, ..], ..]
154164 */
155- private static function getVueAttributeExpressions (DOMElement $ dom , array &$ expressionByLine = [])
156- {
165+ private static function getVueAttributeExpressions (
166+ array $ attributePrefixes ,
167+ DOMElement $ dom ,
168+ array &$ expressionByLine = []
169+ ) {
157170 $ children = $ dom ->childNodes ;
158171
159172 for ($ i = 0 ; $ i < $ children ->length ; $ i ++) {
@@ -170,21 +183,38 @@ private static function getVueAttributeExpressions(DOMElement $dom, array &$expr
170183 $ domAttr = $ attrList ->item ($ j );
171184
172185 // Check if this is a dynamic vue attribute
173- if (strpos ( $ domAttr -> name , ' : ' ) === 0 || strpos ($ domAttr ->name , ' v-bind: ' ) === 0 ) {
186+ if (self :: isAttributeMatching ($ domAttr ->name , $ attributePrefixes ) ) {
174187 $ line = $ domAttr ->getLineNo ();
175188 $ expressionByLine += [$ line => []];
176189 $ expressionByLine [$ line ][] = $ domAttr ->value ;
177190 }
178191 }
179192
180193 if ($ node ->hasChildNodes ()) {
181- $ expressionByLine = self ::getVueAttributeExpressions ($ node , $ expressionByLine );
194+ $ expressionByLine = self ::getVueAttributeExpressions ($ attributePrefixes , $ node , $ expressionByLine );
182195 }
183196 }
184197
185198 return $ expressionByLine ;
186199 }
187200
201+ /**
202+ * Check if this attribute name should be parsed for translations
203+ *
204+ * @param string $attributeName
205+ * @param string[] $attributePrefixes
206+ * @return bool
207+ */
208+ private static function isAttributeMatching ($ attributeName , $ attributePrefixes )
209+ {
210+ foreach ($ attributePrefixes as $ prefix ) {
211+ if (strpos ($ attributeName , $ prefix ) === 0 ) {
212+ return true ;
213+ }
214+ }
215+ return false ;
216+ }
217+
188218 /**
189219 * Extract JS expressions from within template elements (excluding attributes)
190220 * For example: <span :title="skip attributes"> {{__("extract element content")}} </span>
0 commit comments