forked from mirrors/gecko-dev
Bug 1838632 - make fluent-lint complain about unknown attributes, r=flod,fluent-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D181228
This commit is contained in:
parent
c7f8be9d20
commit
cdede3735a
9 changed files with 121 additions and 8 deletions
|
|
@ -124,18 +124,24 @@ addressbar-best-match-learn-more = Learn more
|
|||
|
||||
# First Firefox Suggest toggle button main label and description. This toggle
|
||||
# controls non-sponsored suggestions related to the user's search string.
|
||||
# .description is transferred into a separate paragraph by the moz-toggle
|
||||
# custom element code.
|
||||
addressbar-firefox-suggest-nonsponsored =
|
||||
.label = Suggestions from the web
|
||||
.description = Get suggestions from { -brand-product-name } related to your search.
|
||||
|
||||
# Second Firefox Suggest toggle button main label and description. This toggle
|
||||
# controls sponsored suggestions related to the user's search string.
|
||||
# .description is transferred into a separate paragraph by the moz-toggle
|
||||
# custom element code.
|
||||
addressbar-firefox-suggest-sponsored =
|
||||
.label = Suggestions from sponsors
|
||||
.description = Support the development of { -brand-short-name } with occasional sponsored suggestions.
|
||||
|
||||
# Third Firefox Suggest toggle button main label and description. This toggle
|
||||
# controls data collection related to the user's search string.
|
||||
# .description is transferred into a separate paragraph by the moz-toggle
|
||||
# custom element code.
|
||||
addressbar-firefox-suggest-data-collection =
|
||||
.label = Improve the { -firefox-suggest-brand-name } experience
|
||||
.description = Help create a richer search experience by allowing { -vendor-short-name } to process your search queries.
|
||||
|
|
|
|||
|
|
@ -24,5 +24,6 @@ error-long-desc4 = Robots have shiny metal posteriors which should not be bitten
|
|||
# TV: Battlestar Galactica (2004 series). From the opening text.
|
||||
error-trailer-desc-text = And they have a plan.
|
||||
# Book: Hitchhiker's Guide To The Galaxy. Arthur presses a button and it warns him.
|
||||
# Note: .label2 replaces this label after pressing the button the first time.
|
||||
error-try-again = Try Again
|
||||
.label2 = Please do not press this button again.
|
||||
|
|
|
|||
|
|
@ -4,13 +4,15 @@
|
|||
|
||||
## The main browser window's title
|
||||
|
||||
# These are the default window titles everywhere except macOS. The first two
|
||||
# attributes are used when the web content opened has no title:
|
||||
# These are the default window titles everywhere except macOS.
|
||||
# .data-title-default and .data-title-private are used when the web content
|
||||
# opened has no title:
|
||||
#
|
||||
# default - "Mozilla Firefox"
|
||||
# private - "Mozilla Firefox (Private Browsing)"
|
||||
#
|
||||
# The last two are for use when there *is* a content title.
|
||||
# .data-content-title-default and .data-content-title-private are for use when
|
||||
# there *is* a content title.
|
||||
# Variables:
|
||||
# $content-title (String): the title of the web content.
|
||||
browser-main-window-window-titles =
|
||||
|
|
@ -19,14 +21,17 @@ browser-main-window-window-titles =
|
|||
.data-content-title-default = { $content-title } — { -brand-full-name }
|
||||
.data-content-title-private = { $content-title } — { -brand-full-name } Private Browsing
|
||||
|
||||
# These are the default window titles on macOS. The first two are for use when
|
||||
# there is no content title:
|
||||
# These are the default window titles on macOS.
|
||||
# .data-title-default and .data-title-private are used when the web content
|
||||
# opened has no title:
|
||||
#
|
||||
#
|
||||
# "default" - "Mozilla Firefox"
|
||||
# "private" - "Mozilla Firefox — (Private Browsing)"
|
||||
#
|
||||
# The last two are for use when there *is* a content title.
|
||||
# Do not use the brand name in the last two attributes, as we do on non-macOS.
|
||||
# .data-content-title-default and .data-content-title-private are for use when
|
||||
# there *is* a content title.
|
||||
# Do not use the brand name in these, as we do on non-macOS.
|
||||
#
|
||||
# Also note the other subtle difference here: we use a `-` to separate the
|
||||
# brand name from `(Private Browsing)`, which does not happen on other OSes.
|
||||
|
|
|
|||
|
|
@ -34,12 +34,14 @@ cfr-doorhanger-extension-author = by { $name }
|
|||
# This is a notification displayed in the address bar.
|
||||
# When clicked it opens a panel with a message for the user.
|
||||
cfr-doorhanger-extension-notification = Recommendation
|
||||
# .a11y-announcement is extracted in JS and announced via A11y.announce.
|
||||
cfr-doorhanger-extension-notification2 = Recommendation
|
||||
.tooltiptext = Extension recommendation
|
||||
.a11y-announcement = Extension recommendation available
|
||||
|
||||
# This is a notification displayed in the address bar.
|
||||
# When clicked it opens a panel with a message for the user.
|
||||
# .a11y-announcement is extracted in JS and announced via A11y.announce.
|
||||
cfr-doorhanger-feature-notification = Recommendation
|
||||
.tooltiptext = Feature recommendation
|
||||
.a11y-announcement = Feature recommendation available
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ videocontrols-exitfullscreen-button =
|
|||
.aria-label = Exit Full Screen
|
||||
videocontrols-casting-button-label =
|
||||
.aria-label = Cast to Screen
|
||||
# .offlabel is processed by the video control custom element to be used
|
||||
# as a text-track label
|
||||
videocontrols-closed-caption-off =
|
||||
.offlabel = Off
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@
|
|||
|
||||
pictureinpicture-player-title = Picture-in-Picture
|
||||
|
||||
## Note that this uses .tooltip rather than the standard '.title'
|
||||
## or '.tooltiptext' - but it has the same effect. Code in the
|
||||
## picture-in-picture window will read and copy this to an in-document
|
||||
## DOM node that then shows the tooltip.
|
||||
##
|
||||
## Variables:
|
||||
## $shortcut (String) - Keyboard shortcut to execute the command.
|
||||
|
||||
|
|
@ -47,6 +52,11 @@ pictureinpicture-exit-fullscreen-btn2 =
|
|||
pictureinpicture-toggle-fullscreen-shortcut =
|
||||
.key = F
|
||||
|
||||
## Note that this uses .tooltip rather than the standard '.title'
|
||||
## or '.tooltiptext' - but it has the same effect. Code in the
|
||||
## picture-in-picture window will read and copy this to an in-document
|
||||
## DOM node that then shows the tooltip.
|
||||
|
||||
pictureinpicture-seekbackward-btn =
|
||||
.aria-label = Backward
|
||||
.tooltip = Backward (←)
|
||||
|
|
@ -55,6 +65,8 @@ pictureinpicture-seekforward-btn =
|
|||
.aria-label = Forward
|
||||
.tooltip = Forward (→)
|
||||
|
||||
##
|
||||
|
||||
# This string is never displayed on the window. Is intended to be announced by
|
||||
# a screen reader whenever a user opens the subtitles settings panel
|
||||
# after selecting the subtitles button.
|
||||
|
|
|
|||
|
|
@ -75,6 +75,44 @@ class Linter(visitor.Visitor):
|
|||
"variables": [],
|
||||
}
|
||||
|
||||
attributes = [
|
||||
"label",
|
||||
"value",
|
||||
"accesskey",
|
||||
"alt",
|
||||
"title",
|
||||
"tooltiptext",
|
||||
"placeholder",
|
||||
"aria-label",
|
||||
"aria-description",
|
||||
"aria-valuetext",
|
||||
"style",
|
||||
# For XUL key/command setup.
|
||||
"key",
|
||||
"keycode",
|
||||
# For download filenames:
|
||||
"download",
|
||||
# Used in the Firefox prefs
|
||||
"searchkeywords",
|
||||
# Used by search-textbox.js
|
||||
"searchbuttonlabel",
|
||||
# Used in toolbar customization.
|
||||
"toolbarname",
|
||||
# Used in dialogs (should be moved to using fluent IDs though)
|
||||
"buttonlabelaccept",
|
||||
"buttonaccesskeyaccept",
|
||||
"buttonlabelcancel",
|
||||
"buttonaccesskeycancel",
|
||||
"buttonlabelextra2",
|
||||
"buttonaccesskeyextra2",
|
||||
# Used in app menu notifications (should be moved to use fluent IDs)
|
||||
"buttonlabel",
|
||||
"buttonaccesskey",
|
||||
"secondarybuttonlabel",
|
||||
"secondarybuttonaccesskey",
|
||||
]
|
||||
self.known_attribute_list = [a.lower() for a in attributes]
|
||||
|
||||
# Set this to true to debug print the root node's json. This is useful for
|
||||
# writing new lint rules, or debugging existing ones.
|
||||
self.debug_print_json = False
|
||||
|
|
@ -117,6 +155,21 @@ class Linter(visitor.Visitor):
|
|||
|
||||
super().generic_visit(node)
|
||||
|
||||
# Do this here instead as visit_Attribute doesn't have access to the
|
||||
# message's comment.
|
||||
for attr in node.attributes:
|
||||
if not attr.id.name.lower() in self.known_attribute_list:
|
||||
comment = self.state["comment"] + self.state["group_comment"]
|
||||
if not f".{attr.id.name}" in comment:
|
||||
self.add_error(
|
||||
attr,
|
||||
"VA01",
|
||||
"Use attributes designed for localized content directly."
|
||||
" If script-based processing is necessary, add a comment"
|
||||
f" explaining why. The linter didn't recognize: .{attr.id.name}",
|
||||
"warning",
|
||||
)
|
||||
|
||||
# Check if variables are referenced in comments
|
||||
if self.state["variables"]:
|
||||
comments = self.state["comment"] + self.state["group_comment"]
|
||||
|
|
@ -349,7 +402,7 @@ class Linter(visitor.Visitor):
|
|||
if node.id.name not in self.state["variables"]:
|
||||
self.state["variables"].append(node.id.name)
|
||||
|
||||
def add_error(self, node, rule, msg):
|
||||
def add_error(self, node, rule, msg, level=None):
|
||||
(col, line) = self.span_to_line_and_col(node.span)
|
||||
res = {
|
||||
"path": self.path,
|
||||
|
|
@ -358,6 +411,9 @@ class Linter(visitor.Visitor):
|
|||
"rule": rule,
|
||||
"message": msg,
|
||||
}
|
||||
if level:
|
||||
res["level"] = level
|
||||
|
||||
self.results.append(result.from_config(self.config, **res))
|
||||
|
||||
def span_to_line_and_col(self, span):
|
||||
|
|
|
|||
21
tools/lint/test/files/fluent-lint/valid-attributes.ftl
Normal file
21
tools/lint/test/files/fluent-lint/valid-attributes.ftl
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
### Test for valid attributes.
|
||||
|
||||
message-with-known-attribute =
|
||||
.label = Foo
|
||||
|
||||
# String has a known label but with different case, not a warning
|
||||
message-with-known-attribute-case =
|
||||
.Label = Foo
|
||||
|
||||
# Warning: unknown attribute
|
||||
message-with-unknown-attribute =
|
||||
.extralabel = Foo
|
||||
|
||||
# NO warning: unknown attribute, but commented
|
||||
# .extralabel is known
|
||||
message-with-unknown-attribute-commented =
|
||||
.extralabel = Foo
|
||||
|
|
@ -152,5 +152,13 @@ def test_comment_variables(lint, paths):
|
|||
assert "$term-message" in results[0].message
|
||||
|
||||
|
||||
def test_valid_attributes(lint, paths):
|
||||
results = lint(paths("valid-attributes.ftl"))
|
||||
print(results)
|
||||
assert len(results) == 1
|
||||
assert results[0].rule == "VA01"
|
||||
assert ".extralabel" in results[0].message
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
mozunit.main()
|
||||
|
|
|
|||
Loading…
Reference in a new issue