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:
Gijs Kruitbosch 2023-06-19 16:30:15 +00:00
parent c7f8be9d20
commit cdede3735a
9 changed files with 121 additions and 8 deletions

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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):

View 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

View file

@ -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()