UNPKG

webpack-angular-translate

Version:

Webpack plugin that extracts the translation-ids with the default texts.

160 lines (140 loc) 5.26 kB
import { HtmlTranslationExtractionContext, AngularElement, } from "./html-translation-extractor"; import { AngularExpressionMatch } from "./ng-filters"; import { Attribute } from "./element-context"; import { SUPPRESS_ATTRIBUTE_NAME } from "./translate-html-parser"; const translateAttributeRegex = /^translate-attr-.*$/; export default function translateDirectiveTranslationExtractor( element: AngularElement, context: HtmlTranslationExtractionContext ) { let translateDirective: boolean; let translationId: string; const translateAttribute = element.attributes.find( (attribute) => attribute.name === "translate" ); if (element.tagName === "translate") { translateDirective = true; } if (translateAttribute) { translateDirective = true; translationId = translateAttribute.value; } for (const attribute of element.attributes) { handleAttributesWithTranslateExpressions(attribute, context); } if (translateDirective) { const hasTranslateAttributes = handleTranslateAttributes(element, context); const defaultTextAttribute = element.attributes.find( (attr) => attr.name === "translate-default" ); if (!translationId) { if (element.texts.length === 1) { translationId = element.texts[0].text; } else if (element.texts.length > 1) { context.emitError( "The element does not specify a translation id but has multiple child text elements. Specify the translation id on the element to define the translation id.", element.startPosition ); return; } } // <any translate='test'></any> if (translationId) { context.registerTranslation({ translationId, defaultText: defaultTextAttribute ? defaultTextAttribute.value : undefined, position: element.startPosition, }); } else if (!hasTranslateAttributes) { // no translate-attr-* and the element has not specified a translation id, someone is using the directive incorrectly context.emitSuppressableError( "the element uses the translate directive but does not specify a translation id nor has any translated attributes (translate-attr-*). Specify a translation id or remove the translate-directive.", element.startPosition ); } } else { handleTexts(element, context); } } translateDirectiveTranslationExtractor.mayContainTranslations = function ( content: string ): boolean { return content.indexOf("translate") !== -1; }; type KeyedAttributes = { [name: string]: Attribute }; function handleTranslateAttributes( element: AngularElement, context: HtmlTranslationExtractionContext ) { const keyedAttributes = element.attributes.reduce((obj, attribute) => { obj[attribute.name] = attribute; return obj; }, {} as KeyedAttributes); // translate-attr-ATTR const translateAttributes = element.attributes.filter((attr) => translateAttributeRegex.test(attr.name) ); for (const attribute of translateAttributes) { const attributeName = attribute.name.substr("translate-attr-".length); const defaultTextAttribute = keyedAttributes[`translate-default-attr-${attributeName}`]; context.registerTranslation({ translationId: attribute.value, defaultText: defaultTextAttribute ? defaultTextAttribute.value : undefined, position: attribute.startPosition, }); } return translateAttributes.length > 0; } // <any attr='{{ x | translate }}'></any> function handleAttributesWithTranslateExpressions( attribute: Attribute, context: HtmlTranslationExtractionContext ) { for (const expression of attribute.expressions) { handleAngularExpression(expression, context, attribute.startPosition); } } function handleAngularExpression( expression: AngularExpressionMatch, context: HtmlTranslationExtractionContext, position: number ) { let translationId = expression.value; // e.g { translate | var} instead of a string constant if (!(/^".*"$/.test(translationId) || /^'.*'$/.test(translationId))) { context.emitSuppressableError( `A dynamic filter expression is used in the text or an attribute of the element '${context.asHtml()}'. Add the '${SUPPRESS_ATTRIBUTE_NAME}' attribute to suppress the error (ensure that you have registered the translation manually, consider using i18n.registerTranslation).`, position ); } else if (expression.previousFilters) { context.emitSuppressableError( `Another filter is used before the translate filter in the element ${context.asHtml()}. Add the '${SUPPRESS_ATTRIBUTE_NAME}' to suppress the error (ensure that you have registered the translation manually, consider using i18n.registerTranslation).`, position ); } else { // trim the quotes translationId = translationId.substring(1, translationId.length - 1); context.registerTranslation({ translationId, position, }); } } function handleTexts( element: AngularElement, context: HtmlTranslationExtractionContext ) { for (const text of element.texts) { for (const expression of text.expressions) { handleAngularExpression(expression, context, text.startPosition); } } }