import re
regex = re.compile(r"(?:\$|jQuery)\.mage\.__\((?s)[^'\"]*?(['\"])(.+?)(?<!\\)\1(?s).*?\)")
test_str = ("/**\n"
" * Copyright © 2013-2017 Magento, Inc. All rights reserved.\n"
" * See COPYING.txt for license details.\n"
" */\n\n"
"define([\n"
" 'jquery',\n"
" 'ko',\n"
" 'module',\n"
" '../template/renderer',\n"
" 'mage/translate'\n"
"], function ($, ko, module, renderer) {\n"
" 'use strict';\n\n"
" var locations = {\n"
" 'legend': 'Caption for the fieldset element',\n"
" 'label': 'Label for an input element.',\n"
" 'button': 'Push button',\n"
" 'a': 'Link label',\n"
" 'b': 'Bold text',\n"
" 'strong': 'Strong emphasized text',\n"
" 'i': 'Italic text',\n"
" 'em': 'Emphasized text',\n"
" 'u': 'Underlined text',\n"
" 'sup': 'Superscript text',\n"
" 'sub': 'Subscript text',\n"
" 'span': 'Span element',\n"
" 'small': 'Smaller text',\n"
" 'big': 'Bigger text',\n"
" 'address': 'Contact information',\n"
" 'blockquote': 'Long quotation',\n"
" 'q': 'Short quotation',\n"
" 'cite': 'Citation',\n"
" 'caption': 'Table caption',\n"
" 'abbr': 'Abbreviated phrase',\n"
" 'acronym': 'An acronym',\n"
" 'var': 'Variable part of a text',\n"
" 'dfn': 'Term',\n"
" 'strike': 'Strikethrough text',\n"
" 'del': 'Deleted text',\n"
" 'ins': 'Inserted text',\n"
" 'h1': 'Heading level 1',\n"
" 'h2': 'Heading level 2',\n"
" 'h3': 'Heading level 3',\n"
" 'h4': 'Heading level 4',\n"
" 'h5': 'Heading level 5',\n"
" 'h6': 'Heading level 6',\n"
" 'center': 'Centered text',\n"
" 'select': 'List options',\n"
" 'img': 'Image',\n"
" 'input': 'Form element'\n"
" },\n\n"
" /**\n"
" * Generates [data-translate] attribute's value\n"
" * @param {Object} translationData\n"
" * @param {String} location\n"
" */\n"
" composeTranslateAttr = function (translationData, location) {\n"
" var obj = [{\n"
" 'shown': translationData.shown,\n"
" 'translated': translationData.translated,\n"
" 'original': translationData.original,\n"
" 'location': locations[location] || 'Text'\n"
" }];\n\n"
" return JSON.stringify(obj);\n"
" },\n\n"
" /**\n"
" * Sets text for the element\n"
" * @param {Object} el\n"
" * @param {String} text\n"
" */\n"
" setText = function (el, text) {\n"
" $(el).text(text);\n"
" },\n\n"
" /**\n"
" * Sets [data-translate] attribute for the element\n"
" * @param {Object} el - The element which is binded\n"
" * @param {String} original - The original value of the element\n"
" */\n"
" setTranslateProp = function (el, original) {\n"
" var location = $(el).prop('tagName').toLowerCase(),\n"
" translated = $.mage.__(original),\n"
" translationData = {\n"
" shown: translated,\n"
" translated: translated,\n"
" original: original\n"
" },\n"
" translateAttr = composeTranslateAttr(translationData, location);\n\n"
" $(el).attr('data-translate', translateAttr);\n\n"
" setText(el, translationData.shown);\n"
" },\n\n"
" /**\n"
" * Checks if node represents ko virtual node (nodeType === 8, nodeName === '#comment').\n"
" *\n"
" * @param {HTMLElement} node\n"
" * @returns {Boolean}\n"
" */\n"
" isVirtualElement = function (node) {\n"
" return node.nodeType === 8;\n"
" },\n\n"
" /**\n"
" * Checks if it's real DOM element\n"
" * in case of virtual element, returns span wrapper\n"
" * @param {Object} el\n"
" * @param {bool} isUpdate\n"
" * @return {Object} el\n"
" */\n"
" getRealElement = function (el, isUpdate) {\n"
" if (isVirtualElement(el)) {\n"
" if (isUpdate) {\n"
" return $(el).next('span');\n"
" }\n\n"
" return $('<span/>').insertAfter(el);\n"
" }\n\n"
" return el;\n"
" },\n\n"
" /**\n"
" * execute i18n binding\n"
" * @param {Object} element\n"
" * @param {Function} valueAccessor\n"
" * @param {bool} isUpdate\n"
" */\n"
" execute = function (element, valueAccessor, isUpdate) {\n"
" var original = ko.unwrap(valueAccessor() || ''),\n"
" el = getRealElement(element, isUpdate),\n"
" inlineTranslation = (module.config() || {}).inlineTranslation;\n\n"
" if (inlineTranslation) {\n"
" setTranslateProp(el, original);\n"
" } else {\n"
" setText(el, $.mage.__(original));\n"
" }\n"
" };\n\n"
" /**\n"
" * i18n binding\n"
" * @property {Function} init\n"
" * @property {Function} update\n"
" */\n"
" ko.bindingHandlers.i18n = {\n\n"
" /**\n"
" * init i18n binding\n"
" * @param {Object} element\n"
" * @param {Function} valueAccessor\n"
" */\n"
" init: function (element, valueAccessor) {\n"
" execute(element, valueAccessor);\n"
" },\n\n"
" /**\n"
" * update i18n binding\n"
" * @param {Object} element\n"
" * @param {Function} valueAccessor\n"
" */\n"
" update: function (element, valueAccessor) {\n"
" execute(element, valueAccessor, true);\n"
" }\n"
" };\n\n"
" ko.virtualElements.allowedBindings.i18n = true;\n\n"
" renderer\n"
" .addNode('translate', {\n"
" binding: 'i18n'\n"
" })\n"
" .addAttribute('translate', {\n"
" binding: 'i18n'\n"
" });\n"
"});\n")
match = regex.search(test_str)
if match:
print(f"Match was found at {match.start()}-{match.end()}: {match.group()}")
for group_num, group in enumerate(match.groups(), start=1):
print(f"Group {group_num} found at {match.start(group_num)}-{match.end(group_num)}: {group}")
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for Python, please visit: https://docs.python.org/3/library/re.html