DevTools: Add devtools localizability check to presubmit

This PR adds devtools frontend localizability check to the presubmit
script as reqeusted in
https://chromium-review.googlesource.com/c/chromium/src/+/1504254.

The new script, check_localizability.js, which run on frontend files
changed as part of the devtools presubmit check. In addition, you can
run $ npm run check-loc inside devtools/ to run the check on all
frontend js files.

**Note: Errors identified will be fixed and submitted as a separate
PR. **

check_localizability.js usage:

$ node check_localizability.js [-a | <.js file path>*]

-a: scan all devtools frontend js files
<.js file path>*: List of .js files with space-separated absolute paths

Localizability violations that it scans for:

- First argument to Common.UIString / UI.formatLocalized is not a string
- Conditional argument (e.g. cond ? trueCase : falseCase) found in
  Common.UIString / UI.formatLocalized / ls tagged template literal
- String concatenation is used with
  Common.UIString / UI.formatLocalized / ls``
- A specific argument to function is not localized (i.e. not wrapped in
  Common.UIString / UI.formatLocalized / ls``)
  - Currently, the script checks the third argument to createInput()

Here are a few examples of errors the script can output:

third_party\blink\renderer\devtools\front_end\resources\IndexedDBViews.js
 Line 1456: string concatenation should be changed to variable
substitution with ls: ' (' + Common.UIString('Key path: ')

third_party\blink\renderer\devtools\front_end\timeline\TimelineUIUtils.js
 Line 559-560: conditional(s) found in Common.UIString(
'%s [%s\u2026%s]', url, event.args['beginData']['startLine'] + 1,
endLine >= 0 ? endLine + 1 : ''). Please extract conditional(s) out
of the localization call.

Change-Id: I3243787ad5920b9b873f2feac7ed50a9c69bbe7e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1524993
Reviewed-by: Dmitry Gozman <dgozman@chromium.org>
Reviewed-by: Joel Einbinder <einbinder@chromium.org>
Commit-Queue: Mandy Chen <mandy.chen@microsoft.com>
Cr-Original-Commit-Position: refs/heads/master@{#643161}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: f1c8d4f5752ed8ab43babb602fa86121f8b14dbb
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 5ecc368..5fadb7a 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -94,6 +94,18 @@
     ]
 
 
+def _CheckDevtoolsLocalization(input_api, output_api):  # pylint: disable=invalid-name
+    affected_front_end_files = _getAffectedFrontEndFiles(input_api)
+    if len(affected_front_end_files) == 0:
+        return []
+    else:
+        affected_front_end_files = [
+            input_api.os_path.join(input_api.PresubmitLocalPath(), file_path) for file_path in affected_front_end_files
+        ]
+        script_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "check_localizability.js")
+        return _checkWithNodeScript(input_api, output_api, script_path, affected_front_end_files)
+
+
 def _CheckDevtoolsStyle(input_api, output_api):
     affected_front_end_files = _getAffectedFrontEndFiles(input_api)
     if len(affected_front_end_files) > 0:
@@ -190,6 +202,7 @@
     results = []
     results.extend(_CheckBuildGN(input_api, output_api))
     results.extend(_CheckFormat(input_api, output_api))
+    # results.extend(_CheckDevtoolsLocalization(input_api, output_api))
     results.extend(_CheckDevtoolsStyle(input_api, output_api))
     results.extend(_CompileDevtoolsFrontend(input_api, output_api))
     results.extend(_CheckConvertSVGToPNGHashes(input_api, output_api))
@@ -224,7 +237,7 @@
     return [input_api.os_path.relpath(file_name, devtools_root) for file_name in affected_js_files]
 
 
-def _checkWithNodeScript(input_api, output_api, script_path):
+def _checkWithNodeScript(input_api, output_api, script_path, files=None):  # pylint: disable=invalid-name
     original_sys_path = sys.path
     try:
         sys.path = sys.path + [input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts")]
@@ -234,8 +247,11 @@
 
     node_path = local_node.node_path()
 
+    if files is None:
+        files = []
+
     process = input_api.subprocess.Popen(
-        [node_path, script_path], stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.STDOUT)
+        [node_path, script_path] + files, stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.STDOUT)
     out, _ = process.communicate()
 
     if process.returncode != 0: