UNPKG

@intlayer/core

Version:

Includes core Intlayer functions like translation, dictionary, and utility functions shared across multiple packages.

222 lines (220 loc) 8.26 kB
import { getCondition } from "../getCondition.mjs"; import { getEnumeration } from "../getEnumeration.mjs"; import { getGender } from "../getGender.mjs"; import { getInsertion } from "../getInsertion.mjs"; import { getNesting } from "../getNesting.mjs"; import { getPlural } from "../getPlural.mjs"; import { getTranslation } from "../getTranslation.mjs"; import * as NodeTypes from "@intlayer/types/nodeType"; //#region src/interpreter/getContent/plugins.ts /** --------------------------------------------- * FALLBACK PLUGIN * * Used to fallback a tree-shaken plugin * --------------------------------------------- */ const fallbackPlugin = { id: "fallback-plugin", canHandle: () => false, transform: (node) => node }; /** Translation plugin. Replaces node with a locale string if nodeType = Translation. */ const translationPlugin = (locale, fallback) => process.env["INTLAYER_NODE_TYPE_TRANSLATION"] === "false" ? fallbackPlugin : { id: "translation-plugin", canHandle: (node) => typeof node === "object" && node?.nodeType === NodeTypes.TRANSLATION, transform: (node, props, deepTransformNode) => { const original = node[NodeTypes.TRANSLATION] ?? {}; const result = {}; for (const key in original) { const childProps = { ...props, children: original[key], keyPath: [...props.keyPath, { type: NodeTypes.TRANSLATION, key }] }; result[key] = deepTransformNode(original[key], childProps); } return getTranslation(result, locale, fallback); } }; /** Enumeration plugin. Replaces node with a function that takes quantity => string. */ const enumerationPlugin = process.env["INTLAYER_NODE_TYPE_ENUMERATION"] === "false" ? fallbackPlugin : { id: "enumeration-plugin", canHandle: (node) => typeof node === "object" && node?.nodeType === NodeTypes.ENUMERATION, transform: (node, props, deepTransformNode) => { const original = node[NodeTypes.ENUMERATION]; const result = {}; for (const key in original) { const child = original[key]; result[key] = deepTransformNode(child, { ...props, children: child, keyPath: [...props.keyPath, { type: NodeTypes.ENUMERATION, key }] }); } return (arg) => { const subResult = getEnumeration(result, typeof arg === "number" ? arg : arg.count); if (typeof subResult === "function" && typeof arg === "object") return subResult(arg); return subResult; }; } }; /** * Plural plugin. Replaces node with a function that takes a count (or * `{ count, ...values }`) => string, picking the matching CLDR plural form * for the active locale and interpolating `{{count}}` (and other values). */ const pluralPlugin = (locale) => process.env["INTLAYER_NODE_TYPE_PLURAL"] === "false" ? fallbackPlugin : { id: "plural-plugin", canHandle: (node) => typeof node === "object" && node?.nodeType === NodeTypes.PLURAL, transform: (node, props, deepTransformNode) => { const original = node[NodeTypes.PLURAL]; const result = {}; /** String plugin for plural. Replaces string node with a component that renders the insertion. */ const pluralStringPlugin = { id: "plural-string-plugin", canHandle: (node) => typeof node === "string", transform: (node, subProps, deepTransformNode) => { const transformedResult = deepTransformNode(node, { ...subProps, children: node, plugins: [...(props.plugins ?? []).filter((plugin) => plugin.id !== "intlayer-node-plugin")] }); return (values) => { const children = getInsertion(transformedResult, values); return deepTransformNode(children, { ...subProps, plugins: props.plugins, children }); }; } }; for (const key in original) { const child = original[key]; result[key] = deepTransformNode(child, { ...props, children: child, keyPath: [...props.keyPath, { type: NodeTypes.PLURAL, key }], plugins: [pluralStringPlugin, ...props.plugins ?? []] }); } const effectiveLocale = String(locale ?? props.locale ?? "en"); return (arg) => { const count = typeof arg === "number" ? arg : arg.count; const values = typeof arg === "number" ? { count: arg } : arg; const subResult = getPlural(result, count, effectiveLocale); if (typeof subResult === "function") return subResult(values); return subResult; }; } }; /** Condition plugin. Replaces node with a function that takes boolean => string. */ const conditionPlugin = process.env["INTLAYER_NODE_TYPE_CONDITION"] === "false" ? fallbackPlugin : { id: "condition-plugin", canHandle: (node) => typeof node === "object" && node?.nodeType === NodeTypes.CONDITION, transform: (node, props, deepTransformNode) => { const original = node[NodeTypes.CONDITION]; const result = {}; for (const key in original) { const child = original[key]; result[key] = deepTransformNode(child, { ...props, children: child, keyPath: [...props.keyPath, { type: NodeTypes.CONDITION, key }] }); } return (arg) => { const subResult = getCondition(result, typeof arg === "boolean" ? arg : arg.value); if (typeof subResult === "function" && typeof arg === "object") return subResult(arg); return subResult; }; } }; /** Insertion plugin. Replaces node with a function that takes quantity => string. */ const insertionPlugin = process.env["INTLAYER_NODE_TYPE_INSERTION"] === "false" ? fallbackPlugin : { id: "insertion-plugin", canHandle: (node) => typeof node === "object" && node?.nodeType === NodeTypes.INSERTION, transform: (node, props, deepTransformNode) => { const newKeyPath = [...props.keyPath, { type: NodeTypes.INSERTION }]; const children = node[NodeTypes.INSERTION]; /** Insertion string plugin. Replaces string node with a component that render the insertion. */ const insertionStringPlugin = { id: "insertion-string-plugin", canHandle: (node) => typeof node === "string", transform: (node, subProps, deepTransformNode) => { const transformedResult = deepTransformNode(node, { ...subProps, children: node, plugins: [...(props.plugins ?? []).filter((plugin) => plugin.id !== "intlayer-node-plugin")] }); return (values) => { const children = getInsertion(transformedResult, values); return deepTransformNode(children, { ...subProps, plugins: props.plugins, children }); }; } }; return deepTransformNode(children, { ...props, children, keyPath: newKeyPath, plugins: [insertionStringPlugin, ...props.plugins ?? []] }); } }; /** Gender plugin. Replaces node with a function that takes gender => string. */ const genderPlugin = process.env["INTLAYER_NODE_TYPE_GENDER"] === "false" ? fallbackPlugin : { id: "gender-plugin", canHandle: (node) => typeof node === "object" && node?.nodeType === NodeTypes.GENDER, transform: (node, props, deepTransformNode) => { const original = node[NodeTypes.GENDER]; const result = {}; for (const key in original) { const child = original[key]; result[key] = deepTransformNode(child, { ...props, children: child, keyPath: [...props.keyPath, { type: NodeTypes.GENDER, key }] }); } return (value) => getGender(result, value); } }; /** Nested plugin. Replaces node with the result of `getNesting`. */ const nestedPlugin = (locale) => process.env["INTLAYER_NODE_TYPE_NESTED"] === "false" ? fallbackPlugin : { id: "nested-plugin", canHandle: (node) => typeof node === "object" && (node?.nodeType === NodeTypes.NESTED || node?.nodeType === "n"), transform: (node, props) => getNesting(node[NodeTypes.NESTED].dictionaryKey, node[NodeTypes.NESTED].path, { ...props, locale: locale ?? props.locale }) }; /** File plugin. Replaces node with the result of `getNesting`. */ const filePlugin = process.env["INTLAYER_NODE_TYPE_FILE"] === "false" ? fallbackPlugin : { id: "file-plugin", canHandle: (node) => typeof node === "object" && node?.nodeType === NodeTypes.FILE, transform: (node, props, deepTransform) => deepTransform(node.content, { ...props, children: node.content }) }; //#endregion export { conditionPlugin, enumerationPlugin, fallbackPlugin, filePlugin, genderPlugin, insertionPlugin, nestedPlugin, pluralPlugin, translationPlugin }; //# sourceMappingURL=plugins.mjs.map