-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Description
What problem does this address?
Currently the @types/wordpress__i18n
package is marked as deprecated and says the types are included in the @wordpress/i18n
package directly.
Further there are no types, and the JSDocs types that exist now accept any
in places it definitely should not. For example sprintf
accepts objects for the ...args
.
Lastly proper enforcement of text domains is reasonably feasible with TS.
What is your proposed solution?
I'll propose the types or do the PR if someone will quickly work it up the chain for approval.
If it can get done quickly, I'll offer to retype some of the other common packages as we have built entire TS plugins at this point and had to deal with lots of any
issues.
Proposed solution
Here is my completely extendable TS wordpress/i18n functionality, including way to enforce custom text domains via addons/plugins
We are already using this currently in a custom internal @plugin/i18n
package. It works great in all cases described.
Problems Solved:
✅ Proper type enforcement on __
, sprintf
and other args.
✅ Throws errors when objects or non string|numbers are passed.
✅ Extendable from consuming plugins/themes
/**
* Base namespace for WordPress i18n types
*/
export namespace WordPress {
/**
* Base interface for text domains.
*/
export interface TextDomains {
'default': never;
}
// Add this type alias for better type inference
export type TextDomain = keyof TextDomains;
}
// Export the type separately to make it easier to extend
export type TextDomain = WordPress.TextDomain;
export const sprintf = (
format: string,
...args: Array< string | number >
) => {
return i18n.sprintf( format, ...args );
};
export const __ = ( text: string, domain: TextDomain ) => {
return i18n.__( text, domain );
};
export const _x = ( text: string, context: string, domain: TextDomain ) => {
return i18n._x( text, context, domain );
};
export const _n = (
single: string,
plural: string,
number: number,
domain: TextDomain
) => {
return i18n._n( single, plural, number, domain );
};
export const _nx = (
text: string,
context: string,
number: number,
domain: TextDomain
) => {
return i18n._nx( text, context, number, domain );
};
export const isRTL = () => i18n.isRTL();
And in your consumer
declare module '@wordpress/i18n' {
namespace WordPress {
interface TextDomains {
'popup-maker': never;
}
}
}
Then when you call __( '', 'something-else' );
or sprintf( '%s %d', { text: 'string' }, { number: 0 } )
it throws errors on the second arg.