Skip to content

Instantly share code, notes, and snippets.

@pkuczynski
Last active March 8, 2023 12:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pkuczynski/2392b3392e790fc69627f4a1e43171f1 to your computer and use it in GitHub Desktop.
Save pkuczynski/2392b3392e790fc69627f4a1e43171f1 to your computer and use it in GitHub Desktop.
Sets react-intl defaultMessage based on existing translation file
// Requires `npm i jscodeshift @types/jscodeshift`
// Run: `npx jscodeshift -t react-intl-default-message.ts src/**/*.ts`
import en from './src/i18n/locales/en.json'
export const parser = 'tsx'
export default function transformer(file, api) {
const j = api.jscodeshift
const messageDesc = (nodePath) => {
const { node } = nodePath
const [messageDescriptor, ...otherArguments] = node.arguments
const { properties } = messageDescriptor
if (!properties) {
return node
}
const id = properties.find(p => p.key.name === 'id')
const description = properties.find(p => p.key.name === 'description')
const defaultMessage = en[id.value.value]
const object = j.objectExpression([
j.property(
'init',
j.identifier('id'),
j.literal(id.value.value)
),
j.property(
'init',
j.identifier('defaultMessage'),
j.literal(defaultMessage)
),
description && j.property(
'init',
j.identifier('description'),
j.literal(description.value.value)
)
].filter(Boolean))
node.arguments = [object, ...otherArguments]
return node
}
const jsxMessageDesc = (nodePath) => {
const { node } = nodePath
const { attributes } = node.openingElement
const id = attributes.find(p => p.name.name === 'id')
// const description = properties.find(p => p.name === 'description')
// const values = properties.find(p => p.name === 'values')
const defaultMessage = attributes.find(p => p.name.name === 'defaultMessage')
if (defaultMessage) {
defaultMessage.value.value = en[id.value.value]
}
else {
attributes.push(j.jsxAttribute(
j.jsxIdentifier('defaultMessage'),
j.literal(en[id.value.value])
))
}
return node
}
const root = j(file.source)
const intlFormatMessage = root
.find(j.CallExpression, {
callee: {
type: 'MemberExpression',
property: {
name: 'formatMessage'
}
}
})
const formatMessage = root
.find(j.CallExpression, { callee: { name: 'formatMessage' } })
const defineMessage = root
.find(j.CallExpression, { callee: { name: 'defineMessage' } })
const jsxFormattedMessage = root.findJSXElements('FormattedMessage')
const jsxFormattedHtmlMessage = root.findJSXElements('FormattedHtmlMessage')
const found = intlFormatMessage.length +
formatMessage.length +
defineMessage.length +
jsxFormattedMessage.length +
jsxFormattedHtmlMessage.length
if (found === 0) {
return file.source
}
if (intlFormatMessage.length > 0) {
intlFormatMessage.replaceWith(messageDesc)
}
if (formatMessage.length > 0) {
formatMessage.replaceWith(messageDesc)
}
if (defineMessage.length > 0) {
defineMessage.replaceWith(messageDesc)
}
if (jsxFormattedMessage.length > 0) {
jsxFormattedMessage.replaceWith(jsxMessageDesc)
}
if (jsxFormattedHtmlMessage.length > 0) {
jsxFormattedHtmlMessage.replaceWith(jsxMessageDesc)
}
return root.toSource({ quote: 'single' })
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment