From 366389a2875d5cc091ec006899a984498818718d Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Sat, 1 Aug 2020 15:04:33 +0200 Subject: [PATCH] Adding the VariadicTranslatable to the tr generator --- shared/js/ui/react-elements/i18n/index.tsx | 2 +- tools/trgen/generator.ts | 2 +- tools/trgen/test/test_03.tsx | 3 +- tools/trgen/ts_generator.ts | 125 ++++++++++++--------- 4 files changed, 76 insertions(+), 56 deletions(-) diff --git a/shared/js/ui/react-elements/i18n/index.tsx b/shared/js/ui/react-elements/i18n/index.tsx index 074ef8f3..8519936f 100644 --- a/shared/js/ui/react-elements/i18n/index.tsx +++ b/shared/js/ui/react-elements/i18n/index.tsx @@ -31,7 +31,7 @@ export class Translatable extends React.Component<{ children: string, __cacheKey } } -export const VariadicTranslatable = (props: { text: string, children?: React.ReactElement[] | React.ReactElement }) => { +export const VariadicTranslatable = (props: { text: string, __cacheKey?: string, children?: React.ReactElement[] | React.ReactElement }) => { const args = Array.isArray(props.children) ? props.children : [props.children]; const argsUseCount = [...new Array(args.length)].map(() => 0); diff --git a/tools/trgen/generator.ts b/tools/trgen/generator.ts index fe401c70..b5d9e94e 100644 --- a/tools/trgen/generator.ts +++ b/tools/trgen/generator.ts @@ -5,5 +5,5 @@ export interface TranslationEntry { message: string; - type: "call" | "jsx-translatable" | "js-template"; + type: "call" | "jsx-translatable" | "jsx-variadic-translatable" | "js-template"; } \ No newline at end of file diff --git a/tools/trgen/test/test_03.tsx b/tools/trgen/test/test_03.tsx index 506661a1..fbd08155 100644 --- a/tools/trgen/test/test_03.tsx +++ b/tools/trgen/test/test_03.tsx @@ -1,7 +1,8 @@ -import {Translatable} from "../../../shared/js/ui/react-elements/i18n"; +import {Translatable, VariadicTranslatable} from "../../../shared/js/ui/react-elements/i18n"; import * as React from "react"; function test() { const element_0 = Hello World; const element_1 = {"Hello World"}; + const element_2 = <>XXX; } \ No newline at end of file diff --git a/tools/trgen/ts_generator.ts b/tools/trgen/ts_generator.ts index e6e89bf0..3faf06bb 100644 --- a/tools/trgen/ts_generator.ts +++ b/tools/trgen/ts_generator.ts @@ -69,28 +69,29 @@ function _generate(config: Configuration, node: ts.Node, result: TranslationEntr if(tag.kind !== SyntaxKind.Identifier) break call_analize; - if(tag.escapedText !== "Translatable") - break call_analize; + if(tag.escapedText === "Translatable") { + if(element.children.length !== 1) { + report(element, "Invalid child count: " + element.children.length); + break call_analize; + } + + const text = element.children[0] as ts.JsxText; + if(text.kind != SyntaxKind.JsxText) { + report(element, "Invalid child type " + SyntaxKind[text.kind]); + break call_analize; + } + + const { line, character } = node.getSourceFile().getLineAndCharacterOfPosition(node.getStart()); + result.push({ + filename: node.getSourceFile().fileName, + line: line, + character: character, + message: text.text, + type: "jsx-translatable" + }); + } else if(tag.escapedText === "VariadicTranslatable") { - if(element.children.length !== 1) { - report(element, "Invalid child count: " + element.children.length); - break call_analize; } - - const text = element.children[0] as ts.JsxText; - if(text.kind != SyntaxKind.JsxText) { - report(element, "Invalid child type " + SyntaxKind[text.kind]); - break call_analize; - } - - const { line, character } = node.getSourceFile().getLineAndCharacterOfPosition(node.getStart()); - result.push({ - filename: node.getSourceFile().fileName, - line: line, - character: character, - message: text.text, - type: "jsx-translatable" - }); } node.forEachChild(n => _generate(config, n, result)); @@ -276,6 +277,21 @@ export function transform(config: Configuration, context: ts.TransformationConte return result; } +const generate_jsx_cache_key = (cache: VolatileTransformConfig, config: Configuration, element: ts.JsxElement) => ts.updateJsxElement( + element, + ts.updateJsxOpeningElement( + element.openingElement, + element.openingElement.tagName, + element.openingElement.typeArguments, + ts.updateJsxAttributes(element.openingElement.attributes, [ + ...element.openingElement.attributes.properties, + ts.createJsxAttribute(ts.createIdentifier("__cacheKey"), ts.createStringLiteral(cache.tsx_name_generator(config))) + ]) + ), + element.children, + element.closingElement +); + export function replace_processor(config: Configuration, cache: VolatileTransformConfig, node: ts.Node, source_file: ts.SourceFile) : ts.Node { if(config.verbose) console.log("Process %s", SyntaxKind[node.kind]); @@ -331,20 +347,19 @@ export function replace_processor(config: Configuration, cache: VolatileTransfor if(tag.kind !== SyntaxKind.Identifier) return node; - /* TODO: VariadicTranslatable */ + const properties = {} as any; + + element.openingElement.attributes.properties.forEach((e: ts.JsxAttribute) => { + if(e.kind !== SyntaxKind.JsxAttribute) + throw new Error(source_location(e) + ": Invalid jsx attribute kind " + SyntaxKind[e.kind]); + + if(e.name.kind !== SyntaxKind.Identifier) + throw new Error(source_location(e) + ": Key isn't an identifier"); + + properties[e.name.escapedText as string] = e.initializer; + }); + if(tag.escapedText === "Translatable") { - const properties = {} as any; - - element.openingElement.attributes.properties.forEach((e: ts.JsxAttribute) => { - if(e.kind !== SyntaxKind.JsxAttribute) - throw new Error(source_location(e) + ": Invalid jsx attribute kind " + SyntaxKind[e.kind]); - - if(e.name.kind !== SyntaxKind.Identifier) - throw new Error(source_location(e) + ": Key isn't an identifier"); - - properties[e.name.escapedText as string] = e.initializer; - }); - if('trIgnore' in properties && properties.trIgnore.kind === SyntaxKind.JsxExpression) { const ignoreAttribute = properties.trIgnore as ts.JsxExpression; if(ignoreAttribute.expression.kind === SyntaxKind.TrueKeyword) @@ -369,26 +384,30 @@ export function replace_processor(config: Configuration, cache: VolatileTransfor type: "jsx-translatable" }); - /* - console.error( ts.updateJsxAttributes(element.openingElement.attributes, [ - ...element.openingElement.attributes.properties, - ts.createJsxAttribute(ts.createIdentifier("__cacheKey"), ts.createStringLiteral(cache.tsx_name_generator(config))) - ])); - */ - return ts.updateJsxElement( - element, - ts.updateJsxOpeningElement( - element.openingElement, - element.openingElement.tagName, - element.openingElement.typeArguments, - ts.updateJsxAttributes(element.openingElement.attributes, [ - ...element.openingElement.attributes.properties, - ts.createJsxAttribute(ts.createIdentifier("__cacheKey"), ts.createStringLiteral(cache.tsx_name_generator(config))) - ]) - ), - element.children, - element.closingElement - ); + return generate_jsx_cache_key(cache, config, element); + } else if(tag.escapedText === "VariadicTranslatable") { + if(!('text' in properties)) + throw new Error(source_location(element) + ": Missing text to translate"); + + const textAttribute = properties["text"] as ts.JsxExpression; + if(textAttribute.kind !== SyntaxKind.JsxExpression) + throw new Error(source_location(element) + ": Text attribute has an invalid type. Expected JsxExpression but received " + SyntaxKind[textAttribute.kind]); + + if(textAttribute.expression.kind !== SyntaxKind.StringLiteral) + throw new Error(source_location(element) + ": Text attribute value isn't a string literal. Expected StringLiteral but received " + SyntaxKind[textAttribute.expression.kind]); + + const literal = textAttribute.expression as ts.StringLiteral; + + let { line, character } = source_file.getLineAndCharacterOfPosition(node.getStart()); + cache.translations.push({ + message: literal.text, + line: line, + character: character, + filename: (source_file || {fileName: "unknown"}).fileName, + type: "jsx-variadic-translatable" + }); + + return generate_jsx_cache_key(cache, config, element); } }