
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
resource-script-formatjs
Advanced tools
Author Format.js terms declaration in **Resource Script** instead. Format.JS accessor class file can be generated from it. This class file make the call site cleaner, and Format.JS terms extraction works as expected.
Author Format.js terms declaration in Resource Script instead. Format.JS "accessor class file" can be generated from it. This class file make the call site cleaner, and Format.JS terms extraction works as expected.
yarn rs-to-formatjs ./my-file-1.rs.ts ./my-file-2.rs.ts
Produces these accessor files on the same location as original :
./my-file-1.rs.acc.ts ./my-file-2.rs.acc.ts
The files aren't formatted nicely so maybe you can run your own eslint or prettier style on them...
See how the Resorce Script looks like and how the accessor file looks like in the next section.
yarn add resource-script-formatjs
First you should survey roughly how these packages works, because it highlights i18n problems in production.
Common themes :
rosetta do this in different styles.)I prefer Format.JS since I would like to use ICU syntax.
I agree with making the terms as "contextual" as possible. But all the ways described are quite obtrusive to read when you want to focus on the UI code. (Both the imperative way and using React component way.)
Though, I understand the need for all the parameters needed to make everything works from extraction to runtime rendering.
The documentation advise against explicitly providing a string key and let it generate a hash because string key could cause collision.
However many of my use case wanted to have hierarchical key separated by . or /. It is both useful for the programmer and also the UI that allows collaborated translation. Tools can be written to display hierarchical keys in a tree so it is easier to navigate for the translators.
Also defining home.title and home.description does not make it actually hierarchical, they are 2 different strings. Renaming the middle of hierarchy is also difficult.
You also are committed to the name once you start using the hierarchy. But usually the name in the middle of hierarchy is tied to business logic, and requirement can change. It would feel quite bad if you define many terms under about. hierarchy then suddenly the about page moved to be under any other page, left the keys "stale".
At the call site I would like to be able to use something like these in place of any string I want. They are all compact one liners instead of the ways described in Format.JS documentation. There is also no intl in sight.
<div>{textResource.home.title} - {textResource.home.description}</div>
<div>{textResource.home.daysLeft(5)}</div>
<div>{textResource.home.yourNameIs("5argon")}</div>
This should be fully type checked by the power of TypeScript. You can't input string into daysLeft. You can't input number into yourNameIs. You cannot forget sending arguments into the terms that need them. I would like to utilize the power of TypeScript as much as possible.
textResource should be a representation of intl object, housing the right current language. Therefore it need to be a class instance that contains an actual intl object inside. In the case of React, this textResource may comes from React context which re-renders whenever the language is changed.
Then inside would be a proper declaration of what Format.JS required. Basically, they are all accessor mapped 1-to-1 to an actual call that needed to be there in the middle of code. This is an example of class design that would give the desired developer experience :
export default class TextResource {
private intl: IntlShape
get home() {
return {
/** Title text */
title: this.intl.formatMessage({
id: 'home.title',
description: 'Title text',
defaultMessage: 'Title',
}),
/** Description text */
description: this.intl.formatMessage({
id: 'home.description',
description: 'Description text',
defaultMessage: 'Description',
}),
/** Days left until release date */
daysLeft: (days: number) =>
this.intl.formatMessage(
{
id: 'home.daysLeft',
description: 'Days left until release date',
defaultMessage: 'Days Left : {days}',
},
{ days: days },
),
/** Visitor name */
yourNameIs: (name: string) =>
this.intl.formatMessage(
{
id: 'home.yourNameIs',
description: 'Visitor name',
defaultMessage: 'Your Name Is : {name}',
},
{ name: name },
),
}
}
}
As you can see, the call site is nice and type checked now, but we moved the ugliness into this accessor instead. Making this file is equally time consuming.
id that repeats the hierarchy you just made. (e.g. home. being repeated for all terms here.){days} ICU placeholder string.any. You can also mistype the object key here.That class declaration is inevitable for Format.JS to work, but for human programmer looking at the code, this can describe that class equally :
export const textResource = {
home: {
/** Title text */
title: 'Title',
/** Description text */
description: 'Description',
/** Days left until release date */
daysLeft: (days: number) => `Days Left : ${days}`,
/** Visitor name */
yourNameIs: (name: string) => `Your Name Is : ${name}`,
},
}
This is not just a template, it happened to be a valid TypeScript code as well.
prettier or eslint. Note that eslint can turn + string concatenation into templated string like above.Making this an ideal way of authoring terms to use in the code.
The format presented above is called Resource Script, which I originally made to solve this problem.
FAQs
Author Format.js terms declaration in **Resource Script** instead. Format.JS accessor class file can be generated from it. This class file make the call site cleaner, and Format.JS terms extraction works as expected.
The npm package resource-script-formatjs receives a total of 2 weekly downloads. As such, resource-script-formatjs popularity was classified as not popular.
We found that resource-script-formatjs demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.