Security News
Fluent Assertions Faces Backlash After Abandoning Open Source Licensing
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
@oracle/oraclejet-icu-l10n
Advanced tools
This utility parses message bundles written in ICU format and converts them to formatter functions to be called by the application to get localized strings.
Message bundle files must be JSON, and only top-level properties are supported (no nesting). The string values must follow the ICU format described at http://userguide.icu-project.org/formatparse/messages
Any keys which start with "@" will be ignored, and will not be written to the output file(s).
{
"greeting": "Hello {name}",
"invitation": "{gender_of_host, select, female {{num_guests, plural, ..."
}
Run the l10nBundleBuilder.js
script with arguments:
$ l10nBundleBuilder.js <root-message-bundle.json> <root-bundle-locale> <output-dir>
$ l10nBundleBuilder.js --rootDir=resources/nls --bundleName=app-strings.json --locale=en-US --outDir=dist
The parser reads the given root bundle and converts the message to a TS module containing a single default export object. Within the object, each message name will be the key to the formatter function.
const bundle = {
"greeting": function(p) { ... },
"invitation": function(p) { ... }
};
export default bundle;
The AMD output would be
define(["require", "exports"], function (require, exports) {
const bundle = {
"greeting": function(p) { ... },
"invitation": function(p) { ... }
};
exports.default = bundle;
});
In addition to the root bundle, the parser will traverse all directories at the same level, looking for other NLS directories which contain message bundle files whose name matches that of the root bundle. If found, it combines all messages starting from the root bundle up to the most specific bundle, with the most specific ones taking precendence.
Custom hooks allows an external script to alter the output of the generated bundle.
For example, if you want each bundle key to return a custom type rather than
just the plain translation string, define a custom hook JS file and pass it using
the --hooks
switch:
$ l10nBundleBuilder.js --rootDir=resources/nls --bundleName=app-strings.json --outDir=dist --hooks=./custom-hooks.js
custom-hooks.js
module.exports = {
typeImport: {
CustomMessageType: '../../resources/CustomMessageType'
},
otherImports: {
escape: '../../str',
ext: '../../utils'
},
// remap some of the parameter names to different keys
convertor:
'(args: ParamsType): CustomMessageType => ({bundle: ext(args.bundleId), key: escape(args.id), params: args.params, value: args.translation})'
};
The typeImport
field defines the custom type import that will be added to the
Typescript file generated. This should use a single key:value mapping that contains
the type definition for your custom type begin returned.
You can optionally define otherImports
to include other imports into the bundle.
This map can contain an unlimited number of imports. In the example above, the
functions escape
and ext
are imported because they're used by the convertor.
The convertor
string defines the contents of your convertor function that'll
be run in place of the default behavior of returning just the translation string.
The return of this function should match the custom type defined by typeImport
.
Note the use of the
ParamsType
as the argument to the convertor. This type is automatically added by the bundler to help your convertor understand the type of parameters that it can expect to be called with.ParamsType
is defined as such, and is included in each bundle file
type ParamsType = { bundleId: string, id: string, params: { [key: string]: any } | undefined, translation: string };
CustomMessageType.d.ts
export declare type CustomMessageType = {
bundle: string;
key: string;
params: { [key: string]: any } | undefined;
value: string;
};
This will produce a bundle with key/values similar to
"welcome": ():CustomMessageType => convert({bundleId:ext("app-strings.json"),id:escape("welcome"),params:undefined,translation:"Welcome"}),
The convertor
function takes ParamsType
and returns a custom object type
conforming to CustomMessageType
.
The root directory of your ICU bundles
ex.
--rootDir=resources/nls
The bundle file name that should be processed
ex.
--bundleName=app-strings.json
A path to a file containing custom hooks
ex.
--hooks=./hooks.js
The locale of the root bundle
ex.
--locale=en-US
The directory where the resource bundles will be written
ex.
--outDir=src/resources/nls
The type of module to produce for the bundles. Supported values are esm
, amd
, or legacy-amd
.
If not specified, only the original Typescript source files will be produced, and
no transpilation is performed.
ex.
--module=esm
For backwards compatibility with previous forms of the bundle in AMD, the
legacy-amd
format will produce a bundle with all keys at the root, similar to using named exports. There will also be no TypeScript or type definitions present for the bundle. This option overrides the--exportType
argument.
The type of export to be used. Possible values named
or default
. If not given,
default
is used.
ex.
--exportType=named
Note that in v2.0.0 of the builder, default exports are used, causing TypeScript to place all of the keys into an object named "default" at the top level. If you want all of the bundle keys at the top-level, use
--exportType=named
to produce
export greeting = bundle.greeting; export invitation = bundle.invitation;
and the resulting AMD output
define(['require', 'exports'], function (require, exports) {
exports.greeting = bundle.greeting;
exports.invitation = bundle.invitation;
});
Indicates the bundle is an override, and only the root locale and those explicitly stated in
--supportedLocales
will be built. All other NLS directories will not be processed.
ex.
--optional --supportedLocales=en
A comma-separated list of additional locales to build. If a given locale doesn't
have a corresponding NLS directory underneath rootDir
, then it will be built
using the root bundle.
ex.
--supportedLocales=en,en-XB
In 1.0.0, AMD bundles were constructed with
define({ ...bundle contents... })
Default exports now follow ES module format, and contents are underneath the
default
property
define(["require", "exports"], function (require, exports) {
"use strict";
exports.__esModule = true;
exports.default = {
...bundle contents...
};
});
All bundles are now created in Typescript and transpiled to their target module
formats. The TS sources replace the d.ts
files previously created in 1.0.0, and
an additional BundleType
is exported. This type can be imported for type-safe
usage during design-time.
import type { BundleType as App1Bundle } from './resources/nls/app1bundle';
import type { BundleType as App2Bundle } from './resources/nls/app2bundle';
Typescript type imports are only used during design-time, and removed from the output when transpiled.
A new module file is created in <outDir>/supportedLocales.ts
which exports an
array of all the supported locales built for the bundle. See --supportedLocales
option above. The array can be imported
with
import supportedLocales from './<rootDir>/supportedLocales';
Custom hooks implemented. See Custom Hooks above.
Add the option to declare --exportType=named
to generate keys at the top level
of the exports instead of the default
export type.
Parameter types can be defined in metadata instead of just inferred from the root bundle.
Keys starting with the @
character are used to specify metadata, and is associated with the key whose name follows it:
"input_message_error": "Error: {MESSAGE}",
"@input_message_error": {
"placeholders": {
"MESSAGE": {
"type": "text",
"description": "translated error message"
}
},
"description": "Error with an embedded message"
}
Metadata is optional. It should be supplied in the following cases:
Date values are to be passed as string parameters to the message bundle. They can be any valid string, as defined by Date time string format.
FAQs
JET ICU Message Format Parser
We found that @oracle/oraclejet-icu-l10n demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers 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
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.