diff --git a/src/rules/valid-key.spec.ts b/src/rules/valid-key.spec.ts
index e8c9e73..b5fb7d5 100644
--- a/src/rules/valid-key.spec.ts
+++ b/src/rules/valid-key.spec.ts
@@ -39,6 +39,14 @@ ruleTester.run("valid-key", rule, {
code: ``,
settings: NESTED_SETTINGS,
},
+ {
+ code: `t("valid")`,
+ settings: FLAT_SETTINGS,
+ },
+ {
+ code: `t("nested.valid")`,
+ settings: NESTED_SETTINGS,
+ },
],
invalid: [
{
@@ -110,5 +118,64 @@ ruleTester.run("valid-key", rule, {
},
],
},
+ {
+ code: `t(dynamicKey)`,
+ settings: FLAT_SETTINGS,
+ errors: [
+ {
+ messageId: "dynamic-key",
+ data: { filePath: "test/fixtures/flat/en-US.json" },
+ },
+ ],
+ },
+ {
+ code: `t(42)`,
+ settings: FLAT_SETTINGS,
+ errors: [
+ {
+ messageId: "wrong-key-type",
+ data: { filePath: "test/fixtures/flat/en-US.json" },
+ },
+ ],
+ },
+ {
+ code: `t("invalid")`,
+ settings: FLAT_SETTINGS,
+ errors: [
+ {
+ messageId: "non-existing-key",
+ data: {
+ key: "invalid",
+ closestKey: "valid",
+ },
+ },
+ ],
+ },
+ {
+ code: `t("nested.invalid")`,
+ settings: NESTED_SETTINGS,
+ errors: [
+ {
+ messageId: "non-existing-key",
+ data: {
+ key: "nested.invalid",
+ closestKey: "nested.valid",
+ },
+ },
+ ],
+ },
+ {
+ code: `t("onlyInEn")`,
+ settings: FLAT_SETTINGS,
+ errors: [
+ {
+ messageId: "missing-key-in-file",
+ data: {
+ key: "onlyInEn",
+ filePath: "test/fixtures/flat/es-ES.json",
+ },
+ },
+ ],
+ },
],
});
diff --git a/src/rules/valid-key.ts b/src/rules/valid-key.ts
index 040a126..2d0293a 100644
--- a/src/rules/valid-key.ts
+++ b/src/rules/valid-key.ts
@@ -54,6 +54,62 @@ export default createRule({
);
const keysArray = Array.from(keys);
+ const validateStaticValue = (
+ node: TSESTree.Node,
+ staticValue: {
+ value: unknown;
+ } | null
+ ) => {
+ if (!staticValue) {
+ context.report({
+ messageId: "dynamic-key",
+ node,
+ });
+ return;
+ }
+
+ if (typeof staticValue.value !== "string") {
+ context.report({
+ messageId: "wrong-key-type",
+ node,
+ });
+ return;
+ }
+
+ const key = staticValue.value;
+
+ if (!keys.has(key)) {
+ context.report({
+ messageId: "non-existing-key",
+ node,
+ data: {
+ key,
+ closestKey: closest(key, keysArray),
+ },
+ });
+ return;
+ }
+
+ for (const [filePath, translation] of Object.entries(translations)) {
+ if (
+ !hasKeyInTranslation(
+ settings.translationFiles.format,
+ translation,
+ key
+ )
+ ) {
+ context.report({
+ messageId: "missing-key-in-file",
+ node,
+ data: {
+ key,
+ filePath,
+ },
+ });
+ }
+ }
+ };
+
return {
JSXElement: (element) => {
if (isTransElement(element)) {
@@ -79,54 +135,23 @@ export default createRule({
context.getScope()
);
- if (!staticValue) {
- context.report({
- messageId: "dynamic-key",
- node: attribute,
- });
- return;
- }
-
- if (typeof staticValue.value !== "string") {
- context.report({
- messageId: "wrong-key-type",
- node: attribute,
- });
- return;
- }
-
- const key = staticValue.value;
-
- if (!keys.has(key)) {
- context.report({
- messageId: "non-existing-key",
- node: attribute,
- data: {
- key,
- closestKey: closest(key, keysArray),
- },
- });
+ validateStaticValue(attribute, staticValue);
+ }
+ },
+ CallExpression: (expression) => {
+ if (
+ ASTUtils.isIdentifier(expression.callee) &&
+ expression.callee.name === "t"
+ ) {
+ if (!expression.arguments.length) {
return;
}
-
- for (const [filePath, translation] of Object.entries(translations)) {
- if (
- !hasKeyInTranslation(
- settings.translationFiles.format,
- translation,
- key
- )
- ) {
- context.report({
- messageId: "missing-key-in-file",
- node: attribute,
- data: {
- key,
- filePath,
- },
- });
- }
- }
+ const [firstArgument] = expression.arguments;
+ const staticValue = ASTUtils.getStaticValue(
+ firstArgument,
+ context.getScope()
+ );
+ validateStaticValue(firstArgument, staticValue);
}
},
};