mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 06:41:23 +00:00
[ruff
] Avoid f-string false positives in gettext
calls (RUF027
) (#10118)
## Summary It is a convention to use the `_()` alias for `gettext()`. We want to avoid statement expressions and assignments related to aliases of the gettext API. See https://docs.python.org/3/library/gettext.html for details. When one uses `_() to mark a string for translation, the tools look for these markers and replace the original string with its translated counterpart. If the string contains variable placeholders or formatting, it can complicate the translation process, lead to errors or incorrect translations. ## Test Plan * Test file `RUF027_1.py` was extended such that the test reproduces the false-positive Closes https://github.com/astral-sh/ruff/issues/10023. --------- Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
This commit is contained in:
parent
1711bca4a0
commit
fc8738f52a
2 changed files with 29 additions and 0 deletions
|
@ -25,6 +25,10 @@ def negative_cases():
|
||||||
json3 = "{ 'positive': 'false' }"
|
json3 = "{ 'positive': 'false' }"
|
||||||
alternative_formatter("{a}", a=5)
|
alternative_formatter("{a}", a=5)
|
||||||
formatted = "{a}".fmt(a=7)
|
formatted = "{a}".fmt(a=7)
|
||||||
|
partial = "partial sentence"
|
||||||
|
a = _("formatting of {partial} in a translation string is bad practice")
|
||||||
|
_("formatting of {partial} in a translation string is bad practice")
|
||||||
|
print(_("formatting of {partial} in a translation string is bad practice"))
|
||||||
print(do_nothing("{a}".format(a=3)))
|
print(do_nothing("{a}".format(a=3)))
|
||||||
print(do_nothing(alternative_formatter("{a}", a=5)))
|
print(do_nothing(alternative_formatter("{a}", a=5)))
|
||||||
print(format(do_nothing("{a}"), a=5))
|
print(format(do_nothing("{a}"), a=5))
|
||||||
|
|
|
@ -70,6 +70,11 @@ pub(crate) fn missing_fstring_syntax(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We also want to avoid expressions that are intended to be translated.
|
||||||
|
if semantic.current_expressions().any(is_gettext) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if should_be_fstring(literal, locator, semantic) {
|
if should_be_fstring(literal, locator, semantic) {
|
||||||
let diagnostic = Diagnostic::new(MissingFStringSyntax, literal.range())
|
let diagnostic = Diagnostic::new(MissingFStringSyntax, literal.range())
|
||||||
.with_fix(fix_fstring_syntax(literal.range()));
|
.with_fix(fix_fstring_syntax(literal.range()));
|
||||||
|
@ -77,6 +82,26 @@ pub(crate) fn missing_fstring_syntax(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if an expression appears to be a `gettext` call.
|
||||||
|
///
|
||||||
|
/// We want to avoid statement expressions and assignments related to aliases
|
||||||
|
/// of the gettext API.
|
||||||
|
///
|
||||||
|
/// See <https://docs.python.org/3/library/gettext.html> for details. When one
|
||||||
|
/// uses `_` to mark a string for translation, the tools look for these markers
|
||||||
|
/// and replace the original string with its translated counterpart. If the
|
||||||
|
/// string contains variable placeholders or formatting, it can complicate the
|
||||||
|
/// translation process, lead to errors or incorrect translations.
|
||||||
|
fn is_gettext(expr: &ast::Expr) -> bool {
|
||||||
|
let ast::Expr::Call(ast::ExprCall { func, .. }) = expr else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let ast::Expr::Name(ast::ExprName { id, .. }) = func.as_ref() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
matches!(id.as_str(), "_" | "gettext" | "ngettext")
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if `literal` is likely an f-string with a missing `f` prefix.
|
/// Returns `true` if `literal` is likely an f-string with a missing `f` prefix.
|
||||||
/// See [`MissingFStringSyntax`] for the validation criteria.
|
/// See [`MissingFStringSyntax`] for the validation criteria.
|
||||||
fn should_be_fstring(
|
fn should_be_fstring(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue