From aeeed27c185702527774c306632263a768c351f5 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Fri, 14 Sep 2018 13:02:33 -0400 Subject: [PATCH] Bug 1491378 - Update pdf.js to version 2.0.854. r=bdahl --HG-- extra : amend_source : ee59d0c96de5440583dda33be3b191b60e3fb0c4 --- browser/extensions/pdfjs/README.mozilla | 4 +- browser/extensions/pdfjs/content/build/pdf.js | 64 +++++++++---------- .../pdfjs/content/build/pdf.worker.js | 62 +++++++++--------- .../extensions/pdfjs/content/web/viewer.js | 21 ++++-- browser/extensions/pdfjs/moz.yaml | 2 +- .../locales/en-US/pdfviewer/viewer.properties | 21 ++++-- 6 files changed, 95 insertions(+), 79 deletions(-) diff --git a/browser/extensions/pdfjs/README.mozilla b/browser/extensions/pdfjs/README.mozilla index 59dcbe84cd11..03c45de6286f 100644 --- a/browser/extensions/pdfjs/README.mozilla +++ b/browser/extensions/pdfjs/README.mozilla @@ -1,5 +1,5 @@ This is the PDF.js project output, https://github.com/mozilla/pdf.js -Current extension version is: 2.0.843 +Current extension version is: 2.0.854 -Taken from upstream commit: bf368f3a +Taken from upstream commit: d0b5aa08 diff --git a/browser/extensions/pdfjs/content/build/pdf.js b/browser/extensions/pdfjs/content/build/pdf.js index b7b3ab6092a0..ce9692c74a38 100644 --- a/browser/extensions/pdfjs/content/build/pdf.js +++ b/browser/extensions/pdfjs/content/build/pdf.js @@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap "use strict"; -var pdfjsVersion = '2.0.843'; -var pdfjsBuild = 'bf368f3a'; +var pdfjsVersion = '2.0.854'; +var pdfjsBuild = 'd0b5aa08'; var pdfjsSharedUtil = __w_pdfjs_require__(1); var pdfjsDisplayAPI = __w_pdfjs_require__(7); var pdfjsDisplayTextLayer = __w_pdfjs_require__(19); @@ -185,7 +185,8 @@ var _streams_polyfill = __w_pdfjs_require__(4); var _url_polyfill = __w_pdfjs_require__(6); -var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; +const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; +const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; const NativeImageDecoding = { NONE: 'none', DECODE: 'decode', @@ -201,7 +202,7 @@ const PermissionFlag = { ASSEMBLE: 0x400, PRINT_HIGH_QUALITY: 0x800 }; -var TextRenderingMode = { +const TextRenderingMode = { FILL: 0, STROKE: 1, FILL_STROKE: 2, @@ -213,12 +214,12 @@ var TextRenderingMode = { FILL_STROKE_MASK: 3, ADD_TO_PATH_FLAG: 4 }; -var ImageKind = { +const ImageKind = { GRAYSCALE_1BPP: 1, RGB_24BPP: 2, RGBA_32BPP: 3 }; -var AnnotationType = { +const AnnotationType = { TEXT: 1, LINK: 2, FREETEXT: 3, @@ -246,7 +247,7 @@ var AnnotationType = { THREED: 25, REDACT: 26 }; -var AnnotationFlag = { +const AnnotationFlag = { INVISIBLE: 0x01, HIDDEN: 0x02, PRINT: 0x04, @@ -258,7 +259,7 @@ var AnnotationFlag = { TOGGLENOVIEW: 0x100, LOCKEDCONTENTS: 0x200 }; -var AnnotationFieldFlag = { +const AnnotationFieldFlag = { READONLY: 0x0000001, REQUIRED: 0x0000002, NOEXPORT: 0x0000004, @@ -279,14 +280,14 @@ var AnnotationFieldFlag = { RADIOSINUNISON: 0x2000000, COMMITONSELCHANGE: 0x4000000 }; -var AnnotationBorderStyleType = { +const AnnotationBorderStyleType = { SOLID: 1, DASHED: 2, BEVELED: 3, INSET: 4, UNDERLINE: 5 }; -var StreamType = { +const StreamType = { UNKNOWN: 0, FLATE: 1, LZW: 2, @@ -298,7 +299,7 @@ var StreamType = { CCF: 8, RL: 9 }; -var FontType = { +const FontType = { UNKNOWN: 0, TYPE1: 1, TYPE1C: 2, @@ -316,12 +317,12 @@ const VerbosityLevel = { WARNINGS: 1, INFOS: 5 }; -var CMapCompressionType = { +const CMapCompressionType = { NONE: 0, BINARY: 1, STREAM: 2 }; -var OPS = { +const OPS = { dependency: 1, setLineWidth: 2, setLineCap: 3, @@ -414,6 +415,18 @@ var OPS = { paintSolidColorImageMask: 90, constructPath: 91 }; +const UNSUPPORTED_FEATURES = { + unknown: 'unknown', + forms: 'forms', + javaScript: 'javaScript', + smask: 'smask', + shadingPattern: 'shadingPattern', + font: 'font' +}; +const PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; let verbosity = VerbosityLevel.WARNINGS; function setVerbosityLevel(level) { if (Number.isInteger(level)) { @@ -444,14 +457,6 @@ function assert(cond, msg) { unreachable(msg); } } -var UNSUPPORTED_FEATURES = { - unknown: 'unknown', - forms: 'forms', - javaScript: 'javaScript', - smask: 'smask', - shadingPattern: 'shadingPattern', - font: 'font' -}; function isSameOrigin(baseUrl, otherUrl) { try { var base = new _url_polyfill.URL(baseUrl); @@ -464,7 +469,7 @@ function isSameOrigin(baseUrl, otherUrl) { var other = new _url_polyfill.URL(otherUrl, base); return base.origin === other.origin; } -function isValidProtocol(url) { +function _isValidProtocol(url) { if (!url) { return false; } @@ -485,7 +490,7 @@ function createValidAbsoluteUrl(url, baseUrl) { } try { var absoluteUrl = baseUrl ? new _url_polyfill.URL(url, baseUrl) : new _url_polyfill.URL(url); - if (isValidProtocol(absoluteUrl)) { + if (_isValidProtocol(absoluteUrl)) { return absoluteUrl; } } catch (ex) {} @@ -511,10 +516,6 @@ function getLookupTableFactory(initializer) { return lookup; }; } -var PasswordResponses = { - NEED_PASSWORD: 1, - INCORRECT_PASSWORD: 2 -}; var PasswordException = function PasswordExceptionClosure() { function PasswordException(msg, code) { this.name = 'PasswordException'; @@ -725,7 +726,6 @@ function getInheritableProperty({ dict, key, getArray = false, stopWhenFound = t } return values; } -var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; var Util = function UtilClosure() { function Util() {} var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')']; @@ -831,7 +831,7 @@ function toRomanNumerals(number, lowerCase = false) { const romanStr = romanBuf.join(''); return lowerCase ? romanStr.toLowerCase() : romanStr; } -var PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC]; +const PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC]; function stringToPDFString(str) { var i, n = str.length, @@ -4226,7 +4226,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { } return worker.messageHandler.sendWithPromise('GetDocRequest', { docId, - apiVersion: '2.0.843', + apiVersion: '2.0.854', source: { data: source.data, url: source.url, @@ -5553,8 +5553,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() { }(); var version, build; { - exports.version = version = '2.0.843'; - exports.build = build = 'bf368f3a'; + exports.version = version = '2.0.854'; + exports.build = build = 'd0b5aa08'; } exports.getDocument = getDocument; exports.LoopbackPort = LoopbackPort; diff --git a/browser/extensions/pdfjs/content/build/pdf.worker.js b/browser/extensions/pdfjs/content/build/pdf.worker.js index 8b0b00eb5bef..4f738ec72632 100644 --- a/browser/extensions/pdfjs/content/build/pdf.worker.js +++ b/browser/extensions/pdfjs/content/build/pdf.worker.js @@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap "use strict"; -var pdfjsVersion = '2.0.843'; -var pdfjsBuild = 'bf368f3a'; +var pdfjsVersion = '2.0.854'; +var pdfjsBuild = 'd0b5aa08'; var pdfjsCoreWorker = __w_pdfjs_require__(1); exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler; @@ -327,7 +327,7 @@ var WorkerMessageHandler = { var cancelXHRs = null; var WorkerTasks = []; let apiVersion = docParams.apiVersion; - let workerVersion = '2.0.843'; + let workerVersion = '2.0.854'; if (apiVersion !== workerVersion) { throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`); } @@ -726,7 +726,8 @@ var _streams_polyfill = __w_pdfjs_require__(5); var _url_polyfill = __w_pdfjs_require__(7); -var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; +const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; +const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; const NativeImageDecoding = { NONE: 'none', DECODE: 'decode', @@ -742,7 +743,7 @@ const PermissionFlag = { ASSEMBLE: 0x400, PRINT_HIGH_QUALITY: 0x800 }; -var TextRenderingMode = { +const TextRenderingMode = { FILL: 0, STROKE: 1, FILL_STROKE: 2, @@ -754,12 +755,12 @@ var TextRenderingMode = { FILL_STROKE_MASK: 3, ADD_TO_PATH_FLAG: 4 }; -var ImageKind = { +const ImageKind = { GRAYSCALE_1BPP: 1, RGB_24BPP: 2, RGBA_32BPP: 3 }; -var AnnotationType = { +const AnnotationType = { TEXT: 1, LINK: 2, FREETEXT: 3, @@ -787,7 +788,7 @@ var AnnotationType = { THREED: 25, REDACT: 26 }; -var AnnotationFlag = { +const AnnotationFlag = { INVISIBLE: 0x01, HIDDEN: 0x02, PRINT: 0x04, @@ -799,7 +800,7 @@ var AnnotationFlag = { TOGGLENOVIEW: 0x100, LOCKEDCONTENTS: 0x200 }; -var AnnotationFieldFlag = { +const AnnotationFieldFlag = { READONLY: 0x0000001, REQUIRED: 0x0000002, NOEXPORT: 0x0000004, @@ -820,14 +821,14 @@ var AnnotationFieldFlag = { RADIOSINUNISON: 0x2000000, COMMITONSELCHANGE: 0x4000000 }; -var AnnotationBorderStyleType = { +const AnnotationBorderStyleType = { SOLID: 1, DASHED: 2, BEVELED: 3, INSET: 4, UNDERLINE: 5 }; -var StreamType = { +const StreamType = { UNKNOWN: 0, FLATE: 1, LZW: 2, @@ -839,7 +840,7 @@ var StreamType = { CCF: 8, RL: 9 }; -var FontType = { +const FontType = { UNKNOWN: 0, TYPE1: 1, TYPE1C: 2, @@ -857,12 +858,12 @@ const VerbosityLevel = { WARNINGS: 1, INFOS: 5 }; -var CMapCompressionType = { +const CMapCompressionType = { NONE: 0, BINARY: 1, STREAM: 2 }; -var OPS = { +const OPS = { dependency: 1, setLineWidth: 2, setLineCap: 3, @@ -955,6 +956,18 @@ var OPS = { paintSolidColorImageMask: 90, constructPath: 91 }; +const UNSUPPORTED_FEATURES = { + unknown: 'unknown', + forms: 'forms', + javaScript: 'javaScript', + smask: 'smask', + shadingPattern: 'shadingPattern', + font: 'font' +}; +const PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; let verbosity = VerbosityLevel.WARNINGS; function setVerbosityLevel(level) { if (Number.isInteger(level)) { @@ -985,14 +998,6 @@ function assert(cond, msg) { unreachable(msg); } } -var UNSUPPORTED_FEATURES = { - unknown: 'unknown', - forms: 'forms', - javaScript: 'javaScript', - smask: 'smask', - shadingPattern: 'shadingPattern', - font: 'font' -}; function isSameOrigin(baseUrl, otherUrl) { try { var base = new _url_polyfill.URL(baseUrl); @@ -1005,7 +1010,7 @@ function isSameOrigin(baseUrl, otherUrl) { var other = new _url_polyfill.URL(otherUrl, base); return base.origin === other.origin; } -function isValidProtocol(url) { +function _isValidProtocol(url) { if (!url) { return false; } @@ -1026,7 +1031,7 @@ function createValidAbsoluteUrl(url, baseUrl) { } try { var absoluteUrl = baseUrl ? new _url_polyfill.URL(url, baseUrl) : new _url_polyfill.URL(url); - if (isValidProtocol(absoluteUrl)) { + if (_isValidProtocol(absoluteUrl)) { return absoluteUrl; } } catch (ex) {} @@ -1052,10 +1057,6 @@ function getLookupTableFactory(initializer) { return lookup; }; } -var PasswordResponses = { - NEED_PASSWORD: 1, - INCORRECT_PASSWORD: 2 -}; var PasswordException = function PasswordExceptionClosure() { function PasswordException(msg, code) { this.name = 'PasswordException'; @@ -1266,7 +1267,6 @@ function getInheritableProperty({ dict, key, getArray = false, stopWhenFound = t } return values; } -var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; var Util = function UtilClosure() { function Util() {} var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')']; @@ -1372,7 +1372,7 @@ function toRomanNumerals(number, lowerCase = false) { const romanStr = romanBuf.join(''); return lowerCase ? romanStr.toLowerCase() : romanStr; } -var PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC]; +const PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC]; function stringToPDFString(str) { var i, n = str.length, @@ -13321,7 +13321,7 @@ var JpegImage = function JpegImageClosure() { } } let transform = this._decodeTransform; - if (!transform && numComponents === 4 && !isSourcePDF) { + if (!isSourcePDF && numComponents === 4 && !transform) { transform = new Int32Array([-256, 255, -256, 255, -256, 255, -256, 255]); } if (transform) { diff --git a/browser/extensions/pdfjs/content/web/viewer.js b/browser/extensions/pdfjs/content/web/viewer.js index 3037bc1aa76b..1317b5338793 100644 --- a/browser/extensions/pdfjs/content/web/viewer.js +++ b/browser/extensions/pdfjs/content/web/viewer.js @@ -4100,15 +4100,20 @@ class PDFFindBar { if (!this.findResultsCount) { return; } - let matchesCountMsg = ''; + let matchesCountMsg = '', + limit = MATCHES_COUNT_LIMIT; if (total) { - if (total > MATCHES_COUNT_LIMIT) { - matchesCountMsg = this.l10n.get('find_matches_count_limit', { limit: MATCHES_COUNT_LIMIT.toLocaleString() }, 'More than {{limit}} matches'); + if (total > limit) { + matchesCountMsg = this.l10n.get('find_matches_count_limit', { + n: limit, + limit: limit.toLocaleString() + }, 'More than {{limit}} match' + (limit !== 1 ? 'es' : '')); } else { matchesCountMsg = this.l10n.get('find_matches_count', { + n: total, current: current.toLocaleString(), total: total.toLocaleString() - }, '{{current}} of {{total}} matches'); + }, '{{current}} of {{total}} match' + (total !== 1 ? 'es' : '')); } } Promise.resolve(matchesCountMsg).then(msg => { @@ -4544,16 +4549,20 @@ class PDFFindController { } _requestMatchesCount() { const { pageIdx, matchIdx } = this.selected; - let current = 0; + let current = 0, + total = this.matchesCountTotal; if (matchIdx !== -1) { for (let i = 0; i < pageIdx; i++) { current += this.pageMatches[i] && this.pageMatches[i].length || 0; } current += matchIdx + 1; } + if (current > total) { + current = total = 0; + } return { current, - total: this.matchesCountTotal + total }; } _updateUIResultsCount() { diff --git a/browser/extensions/pdfjs/moz.yaml b/browser/extensions/pdfjs/moz.yaml index 4ac61ba11197..95754c232268 100644 --- a/browser/extensions/pdfjs/moz.yaml +++ b/browser/extensions/pdfjs/moz.yaml @@ -20,7 +20,7 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: version 2.0.843 + release: version 2.0.854 # The package's license, where possible using the mnemonic from # https://spdx.org/licenses/ diff --git a/browser/locales/en-US/pdfviewer/viewer.properties b/browser/locales/en-US/pdfviewer/viewer.properties index 39f1a99bcf66..efeea65701ec 100644 --- a/browser/locales/en-US/pdfviewer/viewer.properties +++ b/browser/locales/en-US/pdfviewer/viewer.properties @@ -168,13 +168,20 @@ find_match_case_label=Match case find_entire_word_label=Whole words find_reached_top=Reached top of document, continued from bottom find_reached_bottom=Reached end of document, continued from top -# LOCALIZATION NOTE (find_matches_count): "{{current}}" and "{{total}}" will be -# replaced by a number representing the index of the currently active find result, -# respectively a number representing the total number of matches in the document. -find_matches_count={{current}} of {{total}} matches -# LOCALIZATION NOTE (find_matches_count_limit): "{{limit}}" will be replaced by -# a numerical value. -find_matches_count_limit=More than {{limit}} matches +# LOCALIZATION NOTE (find_matches_count): The supported plural forms are +# [zero|one|two|few|many|other], with [other] as the default value. +# "{{current}}" and "{{total}}" will be replaced by a number representing the +# index of the currently active find result, respectively a number representing +# the total number of matches in the document. +find_matches_count={[ plural(n) ]} +find_matches_count[one]={{current}} of {{total}} match +find_matches_count[other]={{current}} of {{total}} matches +# LOCALIZATION NOTE (find_matches_count_limit): The supported plural forms are +# [zero|one|two|few|many|other], with [other] as the default value. +# "{{limit}}" will be replaced by a numerical value. +find_matches_count_limit={[ plural(n) ]} +find_matches_count_limit[one]=More than {{limit}} match +find_matches_count_limit[other]=More than {{limit}} matches find_not_found=Phrase not found # Error panel labels