Skip to content

Commit

Permalink
feat: support aliased t functions from useTranslation hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
masnormen authored and gilbsgilbs committed Dec 7, 2024
1 parent 1a4820d commit 5f47b46
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 9 deletions.
44 changes: 44 additions & 0 deletions src/extractors/commons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,47 @@ export function isCustomImportedNode(
return referencesImport(name, sourceModule, importName);
});
}

/**
* Find the aliased t function name (after being destructured).
* If the destructure `t` function is not aliased, will return the identifier name as it is.
*
* For instance, given the following code:
* const { t: tCommon } = useTranslation('common');
* return <p>{tCommon('key1')}<p>
*
* // or with pluginOptions.tFunctionNames = ["myT"]
* const { myT: tCommon } = useTranslation('common');
* return <p>{tCommon('key1')}<p>
*
* getAliasedTBindingName(nodePath) should return 'tCommon' instead of t or myT
*
* @param nodePath: node path to resolve
* @param tFunctionNames: possible names for the (unaliased) t function
* @return the resolved t binding name, returning the alias if needed
*/
export function getAliasedTBindingName(
path: BabelCore.NodePath,
tFunctionNames: string[],
): string | undefined {
const properties = path.get('properties');
const propertiesArray = Array.isArray(properties)
? properties
: [properties];

for (const property of propertiesArray) {
if (property.isObjectProperty()) {
const key = property.node.key;
const value = property.node.value;
if (
key.type === 'Identifier' &&
value.type === 'Identifier' &&
tFunctionNames.includes(key.name)
) {
return value.name;
}
}
}

return tFunctionNames.find((name) => path.scope.bindings[name]);
}
8 changes: 4 additions & 4 deletions src/extractors/useTranslationHook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
getFirstOrNull,
evaluateIfConfident,
referencesImport,
getAliasedTBindingName,
} from './commons';
import extractTFunction from './tFunction';

Expand Down Expand Up @@ -56,11 +57,10 @@ export default function extractUseTranslationHook(

const id = parentPath.get('id');

const tBindingKey =
config.tFunctionNames.find((name) => id.scope.bindings[name]) || 't';
if (!tBindingKey) return [];
const tBindingName = getAliasedTBindingName(id, config.tFunctionNames);
if (!tBindingName) return [];

const tBinding = id.scope.bindings[tBindingKey];
const tBinding = id.scope.bindings[tBindingName];
if (!tBinding) return [];

let keyPrefix: string | null = null;
Expand Down
6 changes: 6 additions & 0 deletions tests/__fixtures__/testCustomHook/customNames.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ export function MyComponent3() {
const [myT] = useThirdPartyTranslation(foo);
return <p>{myT('key in ns3')}</p>
}

export function MyComponent4() {
const { translate: aliasedTranslate } = I18Next.useThirdPartyTranslation('ns4');
someFunc(aliasedTranslate);
return <p>{aliasedTranslate('key in ns4')}</p>
}
3 changes: 2 additions & 1 deletion tests/__fixtures__/testCustomHook/customNames.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
[{ "key0": "", "key1": "" }, { "ns": "ns0" }],
[{ "key in ns1": "" }, { "ns": "ns1" }],
[{ "key in ns2": "" }, { "ns": "ns2" }],
[{ "key in ns3": "" }, { "ns": "ns3" }]
[{ "key in ns3": "" }, { "ns": "ns3" }],
[{ "key in ns4": "" }, { "ns": "ns4" }]
]
}
6 changes: 6 additions & 0 deletions tests/__fixtures__/testCustomHook/namespace.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ export function MyComponent3() {
const [t] = useThirdPartyTranslation(foo);
return <p>{t('key in ns3')}</p>
}

export function MyComponent4() {
const { t: aliasedT } = I18Next.useThirdPartyTranslation('ns4');
someFunc(t);
return <p>{aliasedT('key in ns4')}</p>
}
3 changes: 2 additions & 1 deletion tests/__fixtures__/testCustomHook/namespace.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
[{"key0": "", "key1": ""}, {"ns": "ns0"}],
[{"key in ns1": ""}, {"ns": "ns1"}],
[{"key in ns2": ""}, {"ns": "ns2"}],
[{"key in ns3": ""}, {"ns": "ns3"}]
[{"key in ns3": ""}, {"ns": "ns3"}],
[{"key in ns4": ""}, {"ns": "ns4"}]
]
}
6 changes: 6 additions & 0 deletions tests/__fixtures__/testUseTranslationHook/keyPrefix.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ export function MyComponent5() {
const [t] = useTranslation('ns4', { keyPrefix: 'deep7.deep8' });
return <p>{t('ns5:key11')}</p>
}

export function MyComponent6() {
const { t: aliasedT } = useTranslation('ns6', { keyPrefix: 'deep1.deep2' });
return <p>{aliasedT('key12')}</p>
}

3 changes: 2 additions & 1 deletion tests/__fixtures__/testUseTranslationHook/keyPrefix.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[{ "deep1": {"deep2": {"key2": "", "key3": ""}}}, {"ns": "ns1"}],
[{ "deep3": {"deep4": {"key4": { "key5": "", "key6": "" }}}}, {"ns": "ns2"}],
[{ "deep5": {"deep6": {"key7": { "key8": "" }, "key9": {"key10": ""}}}}, {"ns": "ns3"}],
[{ "key11": ""}, {"ns": "deep7.deep8.ns5"}]
[{ "key11": ""}, {"ns": "deep7.deep8.ns5"}],
[{ "deep1": {"deep2": {"key12": ""}}}, {"ns": "ns6"}]
]
}
5 changes: 5 additions & 0 deletions tests/__fixtures__/testUseTranslationHook/namespace.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ export function MyComponent4() {
someFunc(t);
return <p>{t('key0')}</p>
}

export function MyComponent5() {
const { t: aliasedT } = useTranslation('ns4');
return <p>{aliasedT('key0')}</p>
}
3 changes: 2 additions & 1 deletion tests/__fixtures__/testUseTranslationHook/namespace.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
[{"key0": "", "key1": ""}, {"ns": "ns0"}],
[{"key0": ""}, {"ns": "ns1"}],
[{"key0": ""}, {"ns": "ns2"}],
[{"key0": ""}, {"ns": "ns3"}]
[{"key0": ""}, {"ns": "ns3"}],
[{"key0": ""}, {"ns": "ns4"}]
]
}
10 changes: 10 additions & 0 deletions tests/__fixtures__/testUseTranslationHook/simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,13 @@ export function MyComponent5() {
const { t } = ReactI18Next.useTranslation();
t('from wildcard import');
}

export function MyComponent6() {
const { t: aliasedT } = ReactI18Next.useTranslation();
aliasedT('from wildcard import but aliased');
}

export const MyComponent7 = () => {
const { t: aliasedT } = useTranslation();
return <p>{aliasedT('key5')}</p>
}
4 changes: 3 additions & 1 deletion tests/__fixtures__/testUseTranslationHook/simple.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"key1": "",
"key2": "",
"key3": { "key4": "" },
"from wildcard import": ""
"from wildcard import": "",
"from wildcard import but aliased": "",
"key5": ""
}
}

0 comments on commit 5f47b46

Please sign in to comment.