@@ -16,6 +16,8 @@ export const rule = createRule({
1616 } ,
1717 messages : {
1818 default : 'Should be ${variable}, not ${object.property} or ${myFunction()}' ,
19+ multiplePlaceholders :
20+ 'Invalid placeholder: Expected an object with a single key-value pair, but found multiple keys' ,
1921 } ,
2022 schema : [
2123 {
@@ -29,27 +31,43 @@ export const rule = createRule({
2931
3032 defaultOptions : [ ] ,
3133 create : function ( context ) {
32- const linguiMacroFunctionNames = [ 'plural' , 'select' , 'selectOrdinal' ]
34+ const linguiMacroFunctionNames = [ 'plural' , 'select' , 'selectOrdinal' , 'ph' ]
3335
3436 function checkExpressionsInTplLiteral ( node : TSESTree . TemplateLiteral ) {
35- node . expressions . forEach ( ( expression ) => {
36- if ( expression . type === TSESTree . AST_NODE_TYPES . Identifier ) {
37- return
38- }
37+ node . expressions . forEach ( ( expression ) => checkExpression ( expression ) )
38+ }
39+
40+ function checkExpression ( expression : TSESTree . Expression ) {
41+ if ( expression . type === TSESTree . AST_NODE_TYPES . Identifier ) {
42+ return
43+ }
44+
45+ const isCallToLinguiMacro =
46+ expression . type === TSESTree . AST_NODE_TYPES . CallExpression &&
47+ expression . callee . type === TSESTree . AST_NODE_TYPES . Identifier &&
48+ linguiMacroFunctionNames . includes ( expression . callee . name )
49+
50+ if ( isCallToLinguiMacro ) {
51+ return
52+ }
3953
40- const isCallToLinguiMacro =
41- expression . type === TSESTree . AST_NODE_TYPES . CallExpression &&
42- expression . callee . type === TSESTree . AST_NODE_TYPES . Identifier &&
43- linguiMacroFunctionNames . includes ( expression . callee . name )
54+ const isExplicitLabel = expression . type === TSESTree . AST_NODE_TYPES . ObjectExpression
4455
45- if ( isCallToLinguiMacro ) {
56+ if ( isExplicitLabel ) {
57+ // there can be only one key in the object
58+ if ( expression . properties . length === 1 ) {
4659 return
4760 }
48-
4961 context . report ( {
5062 node : expression ,
51- messageId : 'default ' ,
63+ messageId : 'multiplePlaceholders ' ,
5264 } )
65+ return
66+ }
67+
68+ context . report ( {
69+ node : expression ,
70+ messageId : 'default' ,
5371 } )
5472 }
5573
@@ -76,6 +94,16 @@ export const rule = createRule({
7694 return checkExpressionsInTplLiteral ( node )
7795 }
7896
97+ if ( node . type === TSESTree . AST_NODE_TYPES . ObjectExpression ) {
98+ // <Trans>Hello {{name: obj.prop}}</Trans>
99+ return checkExpression ( node )
100+ }
101+
102+ if ( node . type === TSESTree . AST_NODE_TYPES . CallExpression ) {
103+ // <Trans>Hello {ph({name: obj.prop})}</Trans>
104+ return checkExpression ( node )
105+ }
106+
79107 if ( node . type !== TSESTree . AST_NODE_TYPES . Identifier ) {
80108 context . report ( {
81109 node,
0 commit comments