diff --git a/Components/Sources/Components/Components/Editors/Source Editor/Formatter Extensions/WKSourceEditorFormatter+ButtonActions.swift b/Components/Sources/Components/Components/Editors/Source Editor/Formatter Extensions/WKSourceEditorFormatter+ButtonActions.swift index 8dd3b76589f..63c93b0c8ef 100644 --- a/Components/Sources/Components/Components/Editors/Source Editor/Formatter Extensions/WKSourceEditorFormatter+ButtonActions.swift +++ b/Components/Sources/Components/Components/Editors/Source Editor/Formatter Extensions/WKSourceEditorFormatter+ButtonActions.swift @@ -16,19 +16,63 @@ extension WKSourceEditorFormatter { func toggleFormatting(startingFormattingString: String, endingFormattingString: String, action: WKSourceEditorFormatterButtonAction, in textView: UITextView) { - switch action { - case .remove: - expandSelectedRangeUpToNearestFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) - - if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) { - removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) + if textView.selectedRange.length == 0 { + switch action { + case .remove: + expandSelectedRangeUpToNearestFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) + + if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) { + removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) + } + case .add: + if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) { + removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) + } else { + addStringFormattingCharacters(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) + } } - case .add: - if textView.selectedRange.length == 0 && - selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) { - removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) - } else { - addStringFormattingCharacters(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) + } else { + + switch action { + case .remove: + + if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) { + removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) + } else { + + // Note the flipped formatting string params. + // For example, this takes selected 'text' from: + // Testing Strikethrough text here + // To: + // Testing Strikethrough text here + // We have to add formatters in reverse order to remove formatting from 'text' + + addStringFormattingCharacters(startingFormattingString: endingFormattingString, endingFormattingString: startingFormattingString, in: textView) + } + + case .add: + + // Note: gross workaround to prevent italics misfire from continuing below + if startingFormattingString == "''" && endingFormattingString == "''" { + if selectedRangeIsSurroundedByFormattingString(formattingString: "''", in: textView) && + selectedRangeIsSurroundedByFormattingString(formattingString: "'''", in: textView) { + addStringFormattingCharacters(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) + return + } + } + + // Note the flipped formatting string params. + // For example, this takes selected 'text' from: + // Testing Strikethrough text here + // To: + // Testing Strikethrough text here + // We have to check and remove formatters in reverse order to add formatting to 'text' + + if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: endingFormattingString, endingFormattingString: startingFormattingString, in: textView) { + removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: endingFormattingString, endingFormattingString: startingFormattingString, in: textView) + } else { + addStringFormattingCharacters(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) + } } } } diff --git a/Components/Sources/ComponentsObjC/WKSourceEditorFormatterBoldItalics.m b/Components/Sources/ComponentsObjC/WKSourceEditorFormatterBoldItalics.m index f376e5eec50..262e928431d 100644 --- a/Components/Sources/ComponentsObjC/WKSourceEditorFormatterBoldItalics.m +++ b/Components/Sources/ComponentsObjC/WKSourceEditorFormatterBoldItalics.m @@ -278,40 +278,17 @@ - (void)updateFonts:(WKSourceEditorFonts *)fonts inAttributedString:(NSMutableAt #pragma mark - Public - (BOOL)attributedString:(NSMutableAttributedString *)attributedString isBoldInRange:(NSRange)range { - __block BOOL isBold = NO; - if (range.length == 0) { - - if (attributedString.length > range.location) { - NSDictionary *attrs = [attributedString attributesAtIndex:range.location effectiveRange:nil]; - - if (attrs[WKSourceEditorCustomKeyFontBoldItalics] != nil || attrs[WKSourceEditorCustomKeyFontBold] != nil) { - isBold = YES; - } else { - // Edge case, check previous character if we are up against a closing bold or italic - if (attrs[WKSourceEditorCustomKeyColorOrange]) { - attrs = [attributedString attributesAtIndex:range.location - 1 effectiveRange:nil]; - if (attrs[WKSourceEditorCustomKeyFontBoldItalics] != nil || attrs[WKSourceEditorCustomKeyFontBold] != nil) { - isBold = YES; - } - } - } - } - - } else { - [attributedString enumerateAttributesInRange:range options:nil usingBlock:^(NSDictionary * _Nonnull attrs, NSRange loopRange, BOOL * _Nonnull stop) { - if ((attrs[WKSourceEditorCustomKeyFontBoldItalics] != nil || attrs[WKSourceEditorCustomKeyFontBold] != nil) && - (loopRange.location == range.location && loopRange.length == range.length)) { - isBold = YES; - stop = YES; - } - }]; - } - - - return isBold; + return [self attributedString:attributedString isFormattedInRange:range formattingKey:WKSourceEditorCustomKeyFontBold]; } + - (BOOL)attributedString:(NSMutableAttributedString *)attributedString isItalicsInRange:(NSRange)range { - __block BOOL isItalics = NO; + return [self attributedString:attributedString isFormattedInRange:range formattingKey:WKSourceEditorCustomKeyFontItalics]; +} + +#pragma mark - Private + +- (BOOL)attributedString:(NSMutableAttributedString *)attributedString isFormattedInRange:(NSRange)range formattingKey: (NSString *)formattingKey { + __block BOOL isFormatted = NO; if (range.length == 0) { @@ -319,29 +296,38 @@ - (BOOL)attributedString:(NSMutableAttributedString *)attributedString isItalics NSDictionary *attrs = [attributedString attributesAtIndex:range.location effectiveRange:nil]; if (attrs[WKSourceEditorCustomKeyFontBoldItalics] != nil || attrs[WKSourceEditorCustomKeyFontItalics] != nil) { - isItalics = YES; + isFormatted = YES; } else { // Edge case, check previous character if we are up against a closing bold or italic if (attrs[WKSourceEditorCustomKeyColorOrange]) { attrs = [attributedString attributesAtIndex:range.location - 1 effectiveRange:nil]; - if (attrs[WKSourceEditorCustomKeyFontBoldItalics] != nil || attrs[WKSourceEditorCustomKeyFontItalics] != nil) { - isItalics = YES; + if (attrs[WKSourceEditorCustomKeyFontBold] != nil || attrs[WKSourceEditorCustomKeyFontItalics] != nil) { + isFormatted = YES; } } } } } else { + + __block NSRange unionRange = NSMakeRange(NSNotFound, 0); [attributedString enumerateAttributesInRange:range options:nil usingBlock:^(NSDictionary * _Nonnull attrs, NSRange loopRange, BOOL * _Nonnull stop) { - if ((attrs[WKSourceEditorCustomKeyFontBoldItalics] != nil || attrs[WKSourceEditorCustomKeyFontItalics] != nil) && - (loopRange.location == range.location && loopRange.length == range.length)) { - isItalics = YES; + if (attrs[WKSourceEditorCustomKeyFontBoldItalics] != nil || attrs[formattingKey] != nil) { + if (unionRange.location == NSNotFound) { + unionRange = loopRange; + } else { + unionRange = NSUnionRange(unionRange, loopRange); + } stop = YES; } }]; + + if (NSEqualRanges(unionRange, range)) { + isFormatted = YES; + } } - return isItalics; + return isFormatted; } @end diff --git a/Components/Sources/ComponentsObjC/WKSourceEditorFormatterTemplate.m b/Components/Sources/ComponentsObjC/WKSourceEditorFormatterTemplate.m index 5d6272f4a8c..b2e5bc1e321 100644 --- a/Components/Sources/ComponentsObjC/WKSourceEditorFormatterTemplate.m +++ b/Components/Sources/ComponentsObjC/WKSourceEditorFormatterTemplate.m @@ -33,8 +33,8 @@ - (instancetype)initWithColors:(WKSourceEditorColors *)colors fonts:(WKSourceEdi WKSourceEditorCustomKeyVerticalTemplate: [NSNumber numberWithBool:YES] }; - _horizontalTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"\\{{2}[^\\{\\}\\n]*\\}{2}" options:0 error:nil]; - _verticalStartTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"^\\{{2}[^\\{\\}\\n]*$" options:NSRegularExpressionAnchorsMatchLines error:nil]; + _horizontalTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"\\{{2}[^\\{\\}\\n]*(?:\\{{2}[^\\{\\}\\n]*\\}{2})*[^\\{\\}\\n]*\\}{2}" options:0 error:nil]; + _verticalStartTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"^(?:.*)(\\{{2}[^\\{\\}\\n]*)$" options:NSRegularExpressionAnchorsMatchLines error:nil]; _verticalParameterTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"^\\s*\\|.*$" options:NSRegularExpressionAnchorsMatchLines error:nil]; _verticalEndTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"^([^\\{\\}\n]*\\}{2})(?:.)*$" options:NSRegularExpressionAnchorsMatchLines error:nil]; } @@ -64,11 +64,12 @@ - (void)addSyntaxHighlightingToAttributedString:(nonnull NSMutableAttributedStri options:0 range:range usingBlock:^(NSTextCheckingResult *_Nullable result, NSMatchingFlags flags, BOOL *_Nonnull stop) { - NSRange matchRange = [result rangeAtIndex:0]; + NSRange fullMatch = [result rangeAtIndex:0]; + NSRange openingTemplateRange = [result rangeAtIndex:1]; - if (matchRange.location != NSNotFound) { - [attributedString addAttributes:self.verticalTemplateAttributes range:matchRange]; - } + if (fullMatch.location != NSNotFound && openingTemplateRange.location != NSNotFound) { + [attributedString addAttributes:self.verticalTemplateAttributes range:openingTemplateRange]; + } }]; [self.verticalParameterTemplateRegex enumerateMatchesInString:attributedString.string @@ -86,12 +87,14 @@ - (void)addSyntaxHighlightingToAttributedString:(nonnull NSMutableAttributedStri options:0 range:range usingBlock:^(NSTextCheckingResult *_Nullable result, NSMatchingFlags flags, BOOL *_Nonnull stop) { + NSRange fullMatch = [result rangeAtIndex:0]; NSRange closingTemplateRange = [result rangeAtIndex:1]; - if (fullMatch.location != NSNotFound && closingTemplateRange.location != NSNotFound) { - [attributedString addAttributes:self.verticalTemplateAttributes range:closingTemplateRange]; - } + if (fullMatch.location != NSNotFound && closingTemplateRange.location != NSNotFound) { + [attributedString addAttributes:self.verticalTemplateAttributes range:closingTemplateRange]; + } + }]; } @@ -149,13 +152,21 @@ - (BOOL)attributedString:(NSMutableAttributedString *)attributedString isHorizon } } else { + __block NSRange unionRange = NSMakeRange(NSNotFound, 0); [attributedString enumerateAttributesInRange:range options:nil usingBlock:^(NSDictionary * _Nonnull attrs, NSRange loopRange, BOOL * _Nonnull stop) { - if ((attrs[WKSourceEditorCustomKeyHorizontalTemplate] != nil) && - (loopRange.location == range.location && loopRange.length == range.length)) { - isTemplate = YES; - stop = YES; + if (attrs[WKSourceEditorCustomKeyHorizontalTemplate] != nil) { + if (unionRange.location == NSNotFound) { + unionRange = loopRange; + } else { + unionRange = NSUnionRange(unionRange, loopRange); } + stop = YES; + } }]; + + if (NSEqualRanges(unionRange, range)) { + isTemplate = YES; + } } return isTemplate; diff --git a/Components/Tests/ComponentsTests/WKSourceEditorFormatterButtonActionTests.swift b/Components/Tests/ComponentsTests/WKSourceEditorFormatterButtonActionTests.swift index 30cf8aae558..a62c02d02f1 100644 --- a/Components/Tests/ComponentsTests/WKSourceEditorFormatterButtonActionTests.swift +++ b/Components/Tests/ComponentsTests/WKSourceEditorFormatterButtonActionTests.swift @@ -42,7 +42,7 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase { XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four") } - func testSingleBoldRemove() throws { + func testCursorBoldRemove() throws { let text = "One '''Two''' Three Four" mediator.textView.attributedText = NSAttributedString(string: text) mediator.textView.selectedRange = NSRange(location: 8, length: 0) // Just a cursor inside Two @@ -50,7 +50,7 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase { XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four") } - func testSingleItalicsRemove() throws { + func testCursorItalicsRemove() throws { let text = "One Two '''Three''' Four" mediator.textView.attributedText = NSAttributedString(string: text) mediator.textView.selectedRange = NSRange(location: 14, length: 0) @@ -77,7 +77,7 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase { XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four") } - func testSingleBoldInsertAndRemove() throws { + func testCursorBoldInsertAndRemove() throws { let text = "One Two Three Four" mediator.textView.attributedText = NSAttributedString(string: text) mediator.textView.selectedRange = NSRange(location: 4, length: 0) // Just a cursor before Two @@ -87,7 +87,7 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase { XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four") } - func testSingleItalicsInsertAndRemove() throws { + func testCursorItalicsInsertAndRemove() throws { let text = "One Two Three Four" mediator.textView.attributedText = NSAttributedString(string: text) mediator.textView.selectedRange = NSRange(location: 4, length: 0) // Just a cursor before Two @@ -97,6 +97,46 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase { XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four") } + func testBoldInnerRemoveAndInsert() throws { + let text = "One '''Two Three Four''' Five" + mediator.textView.attributedText = NSAttributedString(string: text) + mediator.textView.selectedRange = NSRange(location: 11, length: 5) // Selected Three + mediator.boldItalicsFormatter?.toggleBoldFormatting(action: .remove, in: mediator.textView) + XCTAssertEqual(mediator.textView.attributedText.string, "One '''Two '''Three''' Four''' Five") + mediator.boldItalicsFormatter?.toggleBoldFormatting(action: .remove, in: mediator.textView) + XCTAssertEqual(mediator.textView.attributedText.string, "One '''Two Three Four''' Five") + } + + func testItalicsInnerRemoveAndInsert() throws { + let text = "One ''Two Three Four'' Five" + mediator.textView.attributedText = NSAttributedString(string: text) + mediator.textView.selectedRange = NSRange(location: 10, length: 5) // Selected Three + mediator.boldItalicsFormatter?.toggleItalicsFormatting(action: .remove, in: mediator.textView) + XCTAssertEqual(mediator.textView.attributedText.string, "One ''Two ''Three'' Four'' Five") + mediator.boldItalicsFormatter?.toggleItalicsFormatting(action: .remove, in: mediator.textView) + XCTAssertEqual(mediator.textView.attributedText.string, "One ''Two Three Four'' Five") + } + + func testBoldItalicsInnerRemoveBoldAndInsert() throws { + let text = "One '''''Two Three Four''''' Five" + mediator.textView.attributedText = NSAttributedString(string: text) + mediator.textView.selectedRange = NSRange(location: 13, length: 5) // Selected Three + mediator.boldItalicsFormatter?.toggleBoldFormatting(action: .remove, in: mediator.textView) + XCTAssertEqual(mediator.textView.attributedText.string, "One '''''Two '''Three''' Four''''' Five") + mediator.boldItalicsFormatter?.toggleBoldFormatting(action: .remove, in: mediator.textView) + XCTAssertEqual(mediator.textView.attributedText.string, "One '''''Two Three Four''''' Five") + } + + func testBoldItalicsInnerRemoveItalicsAndInsert() throws { + let text = "One '''''Two Three Four''''' Five" + mediator.textView.attributedText = NSAttributedString(string: text) + mediator.textView.selectedRange = NSRange(location: 13, length: 5) // Selected Three + mediator.boldItalicsFormatter?.toggleItalicsFormatting(action: .remove, in: mediator.textView) + XCTAssertEqual(mediator.textView.attributedText.string, "One '''''Two ''Three'' Four''''' Five") + mediator.boldItalicsFormatter?.toggleItalicsFormatting(action: .remove, in: mediator.textView) + XCTAssertEqual(mediator.textView.attributedText.string, "One '''''Two Three Four''''' Five") + } + func testTemplateInsert() throws { let text = "One Two Three Four" mediator.textView.attributedText = NSAttributedString(string: text) @@ -113,7 +153,7 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase { XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four") } - func testSingleTemplateInsertAndRemove() throws { + func testCursorTemplateInsertAndRemove() throws { let text = "One Two Three Four" mediator.textView.attributedText = NSAttributedString(string: text) mediator.textView.selectedRange = NSRange(location: 4, length: 0) // Just a cursor before Two diff --git a/Components/Tests/ComponentsTests/WKSourceEditorFormatterTests.swift b/Components/Tests/ComponentsTests/WKSourceEditorFormatterTests.swift index d421a5bd65f..b7a0745cf4b 100644 --- a/Components/Tests/ComponentsTests/WKSourceEditorFormatterTests.swift +++ b/Components/Tests/ComponentsTests/WKSourceEditorFormatterTests.swift @@ -636,7 +636,43 @@ final class WKSourceEditorFormatterTests: XCTestCase { XCTAssertEqual(refClosingAttributes[.foregroundColor] as! UIColor, colors.baseForegroundColor, "Incorrect ref formatting") } - func testVerticalStartTemplate() { + func testHorizontalNestedTemplate() { + let string = "Ford Island ({{lang-haw|Poka {{okina}}Ailana}}) is an" + let mutAttributedString = NSMutableAttributedString(string: string) + + for formatter in formatters { + formatter.addSyntaxHighlighting(to: mutAttributedString, in: NSRange(location: 0, length: string.count)) + } + + var base1Range = NSRange(location: 0, length: 0) + let base1Attributes = mutAttributedString.attributes(at: 0, effectiveRange: &base1Range) + + var templateRange = NSRange(location: 0, length: 0) + let templateAttributes = mutAttributedString.attributes(at: 13, effectiveRange: &templateRange) + + var base2Range = NSRange(location: 0, length: 0) + let base2Attributes = mutAttributedString.attributes(at: 46, effectiveRange: &base2Range) + + // "Ford Island (" + XCTAssertEqual(base1Range.location, 0, "Incorrect base formatting") + XCTAssertEqual(base1Range.length, 13, "Incorrect base formatting") + XCTAssertEqual(base1Attributes[.font] as! UIFont, fonts.baseFont, "Incorrect base formatting") + XCTAssertEqual(base1Attributes[.foregroundColor] as! UIColor, colors.baseForegroundColor, "Incorrect base formatting") + + // "{{lang-haw|Poka {{okina}}Ailana}}" + XCTAssertEqual(templateRange.location, 13, "Incorrect template formatting") + XCTAssertEqual(templateRange.length, 33, "Incorrect template formatting") + XCTAssertEqual(templateAttributes[.font] as! UIFont, fonts.baseFont, "Incorrect template formatting") + XCTAssertEqual(templateAttributes[.foregroundColor] as! UIColor, colors.purpleForegroundColor, "Incorrect template formatting") + + // ") is an" + XCTAssertEqual(base2Range.location, 46, "Incorrect base formatting") + XCTAssertEqual(base2Range.length, 7, "Incorrect base formatting") + XCTAssertEqual(base2Attributes[.font] as! UIFont, fonts.baseFont, "Incorrect base formatting") + XCTAssertEqual(base2Attributes[.foregroundColor] as! UIColor, colors.baseForegroundColor, "Incorrect base formatting") + } + + func testVerticalStartTemplate1() { let string = "{{Infobox officeholder" let mutAttributedString = NSMutableAttributedString(string: string) @@ -654,6 +690,33 @@ final class WKSourceEditorFormatterTests: XCTestCase { XCTAssertEqual(templateAttributes[.foregroundColor] as! UIColor, colors.purpleForegroundColor, "Incorrect template formatting") } + func testVerticalStartTemplate2() { + let string = "ending of previous sentence. {{cite web" + let mutAttributedString = NSMutableAttributedString(string: string) + + for formatter in formatters { + formatter.addSyntaxHighlighting(to: mutAttributedString, in: NSRange(location: 0, length: string.count)) + } + + var baseRange = NSRange(location: 0, length: 0) + let baseAttributes = mutAttributedString.attributes(at: 0, effectiveRange: &baseRange) + + var templateRange = NSRange(location: 0, length: 0) + let templateAttributes = mutAttributedString.attributes(at: 29, effectiveRange: &templateRange) + + // "ending of previous sentence. " + XCTAssertEqual(baseRange.location, 0, "Incorrect base formatting") + XCTAssertEqual(baseRange.length, 29, "Incorrect base formatting") + XCTAssertEqual(baseAttributes[.font] as! UIFont, fonts.baseFont, "Incorrect base formatting") + XCTAssertEqual(baseAttributes[.foregroundColor] as! UIColor, colors.baseForegroundColor, "Incorrect base formatting") + + // "ending of previous sentence. " + XCTAssertEqual(templateRange.location, 29, "Incorrect template formatting") + XCTAssertEqual(templateRange.length, 10, "Incorrect template formatting") + XCTAssertEqual(templateAttributes[.font] as! UIFont, fonts.baseFont, "Incorrect template formatting") + XCTAssertEqual(templateAttributes[.foregroundColor] as! UIColor, colors.purpleForegroundColor, "Incorrect base formatting") + } + func testVerticalParameterTemplate() { let string = "| genus = Felis" let mutAttributedString = NSMutableAttributedString(string: string) diff --git a/Components/Tests/ComponentsTests/WKSourceEditorTextFrameworkMediatorTests.swift b/Components/Tests/ComponentsTests/WKSourceEditorTextFrameworkMediatorTests.swift index 9380a2e08bc..484bc98bf65 100644 --- a/Components/Tests/ComponentsTests/WKSourceEditorTextFrameworkMediatorTests.swift +++ b/Components/Tests/ComponentsTests/WKSourceEditorTextFrameworkMediatorTests.swift @@ -61,6 +61,25 @@ final class WKSourceEditorTextFrameworkMediatorTests: XCTestCase { XCTAssertFalse(selectionStates9.isItalics) } + func testSelectionSpanningNonFormattedState1() throws { + let text = "Testing '''bold with {{template}}''' selection that spans nonbold." + mediator.textView.attributedText = NSAttributedString(string: text) + + // "bold with {{template}}" + let selectionStates = mediator.selectionState(selectedDocumentRange: NSRange(location: 11, length: 22)) + XCTAssertTrue(selectionStates.isBold) + XCTAssertFalse(selectionStates.isHorizontalTemplate) + } + + func testSelectionSpanningNonFormattedState2() throws { + let text = "Testing {{template | '''bold'''}} selection that spans nonbold." + mediator.textView.attributedText = NSAttributedString(string: text) + + // "template | '''bold'''" + let selectionStates1 = mediator.selectionState(selectedDocumentRange: NSRange(location: 10, length: 21)) + XCTAssertFalse(selectionStates1.isBold) + XCTAssertTrue(selectionStates1.isHorizontalTemplate) + } func testClosingBoldSelectionStateCursor() throws { let text = "One '''Two''' Three" mediator.textView.attributedText = NSAttributedString(string: text) @@ -138,6 +157,15 @@ final class WKSourceEditorTextFrameworkMediatorTests: XCTestCase { XCTAssertFalse(selectionStates1.isHorizontalTemplate) } + func testHorizontalTemplateButtonSelectionStateFormattedRange() throws { + let text = "Testing inner formatted {{cite web | url=https://en.wikipedia.org | title = The '''Free''' Encyclopedia}} template example." + mediator.textView.attributedText = NSAttributedString(string: text) + + // "cite web | url=https://en.wikipedia.org | title = The '''Free''' Encyclopedia" + let selectionStates = mediator.selectionState(selectedDocumentRange: NSRange(location: 26, length: 77)) + XCTAssertTrue(selectionStates.isHorizontalTemplate) + } + func testStrikethroughSelectionState() throws { let text = "Testing Strikethrough Testing." mediator.textView.attributedText = NSAttributedString(string: text) diff --git a/Wikipedia/Localizations/da.lproj/Localizable.strings b/Wikipedia/Localizations/da.lproj/Localizable.strings index c2741fddef6..f5cd2276272 100644 --- a/Wikipedia/Localizations/da.lproj/Localizable.strings +++ b/Wikipedia/Localizations/da.lproj/Localizable.strings @@ -214,9 +214,20 @@ "diff-thanks-send-button-title" = "Send 'Tak'"; "diff-thanks-sent" = "Din 'Tak' blev sendt til $1"; "dim-images" = "Mørklæg billeder"; +"edit-bold-accessibility-label" = "Tilføj fed formatering"; +"edit-bold-remove-accessibility-label" = "Fjern fed formatering"; "edit-clear-formatting-accessibility-label" = "Fjern formatering"; "edit-comment-accessibility-label" = "Tilføj kommentarsyntaks"; +"edit-comment-remove-accessibility-label" = "Fjern kommentarsyntaks"; +"edit-decrease-indent-depth-accessibility-label" = "Formindsk indrykningsdybden"; +"edit-direction-down-accessibility-label" = "Flyt markøren ned"; +"edit-direction-left-accessibility-label" = "Flyt markøren til venstre"; +"edit-direction-right-accessibility-label" = "Flyt markøren til højre"; +"edit-direction-up-accessibility-label" = "Flyt markøren op"; +"edit-increase-indent-depth-accessibility-label" = "Øg indrykningsdybden"; "edit-link-display-text-title" = "Vis tekst"; +"edit-link-remove-link-title" = "Fjern link"; +"edit-link-title" = "Rediger link"; "edit-menu-item" = "Rediger"; "edit-minor-learn-more-text" = "Lær mere om mindre ændringer"; "edit-minor-text" = "Dette er en mindre ændring"; @@ -315,6 +326,7 @@ "field-token-title" = "Bekræftelseskode"; "field-username-placeholder" = "indtast brugernavn"; "field-username-title" = "Brugernavn"; +"filter-options-all" = "Alle"; "find-infolabel-number-matches" = "$1 / $2"; "find-replace-header" = "Find og erstat"; "find-textfield-accessibility" = "Find"; @@ -397,6 +409,37 @@ "no-internet-connection" = "Ingen internetforbindelse"; "no-internet-connection-article-reload-button" = "Vend tilbage til seneste gemte version"; "notifications-center-feed-news-notification-button-text" = "Slå push-notifikationer til"; +"notifications-center-filters-read-status-item-title-all" = "Alle"; +"notifications-center-filters-read-status-item-title-read" = "Læst"; +"notifications-center-filters-read-status-item-title-unread" = "Ulæst"; +"notifications-center-filters-read-status-section-title" = "Læsestatus"; +"notifications-center-filters-title" = "Filtre"; +"notifications-center-filters-types-item-title-all" = "Alle typer"; +"notifications-center-go-to-article" = "Artikel"; +"notifications-center-go-to-article-talk-format" = "$1 diskussionsside"; +"notifications-center-go-to-diff" = "Forskel"; +"notifications-center-go-to-talk-page" = "Diskussionsside"; +"notifications-center-go-to-user-page" = "$1's brugerside"; +"notifications-center-go-to-wikidata-item" = "Wikidata-emne"; +"notifications-center-go-to-your-talk-page" = "Din diskussionsside"; +"notifications-center-header-alert-from-agent" = "Advarsel fra $1"; +"notifications-center-inbox-title" = "Projekter"; +"notifications-center-inbox-wikimedia-projects-section-footer" = "Kun projekter, du har oprettet en konto til, vises her"; +"notifications-center-inbox-wikimedia-projects-section-title" = "Wikimedia-projekter"; +"notifications-center-inbox-wikipedias-section-title" = "Wikipedias"; +"notifications-center-language-project-name-format" = "$1 $2"; +"notifications-center-mark" = "Markér"; +"notifications-center-mark-all-as-read" = "Markér alle som læste"; +"notifications-center-mark-as-read" = "Markér som læst"; +"notifications-center-mark-as-unread" = "Markér som ulæst"; +"notifications-center-more-action-accessibility-label" = "Mere"; +"notifications-center-onboarding-modal-continue-action" = "Fortsæt"; +"notifications-center-status-all" = "Alle"; +"notifications-center-status-all-notifications" = "Alle meddelelser"; +"notifications-center-subheader-welcome" = "Velkommen!"; +"notifications-center-swipe-more" = "Mere"; +"notifications-center-type-title-welcome" = "Velkommen"; +"notifications-push-fallback-body-text" = "Ny aktivitet på Wikipedia"; "number-billions" = "$1 mia."; "number-millions" = "$1 mio."; "number-thousands" = "$1K"; @@ -451,6 +494,17 @@ "potd-widget-title" = "Dagens billede"; "preference-summary-eventlogging-opt-in" = "Tillad Wikimedia Foundation at indsamle oplysninger om, hvordan du bruger appen, for at gøre appen bedre."; "preference-title-eventlogging-opt-in" = "Send anvendelsesrapporter"; +"project-name-mediawiki" = "MediaWiki"; +"project-name-wikibooks" = "Wikibooks"; +"project-name-wikidata" = "Wikidata"; +"project-name-wikimedia-commons" = "Wikimedia Commons"; +"project-name-wikinews" = "Wikinews"; +"project-name-wikiquote" = "Wikiquote"; +"project-name-wikisource" = "Wikisource"; +"project-name-wikispecies" = "Wikispecies"; +"project-name-wikiversity" = "Wikiversity"; +"project-name-wikivoyage" = "Wikivoyage"; +"project-name-wiktionary" = "Wiktionary"; "reading-list-add-generic-hint-title" = "Tilføj denne artikel til en læseliste?"; "reading-list-add-hint-title" = "Tilføj »$1« til læselisten?"; "reading-list-add-saved-button-title" = "Ja, tilføj dem til mine læselister"; @@ -511,7 +565,9 @@ "reading-themes-controls-syntax-highlighting" = "Syntaksfremhævelse"; "reference-title" = "Reference $1"; "relative-date-days-ago" = "{{PLURAL:$1|0=I dag|1=I går|$1 dage siden}}"; +"relative-date-hours-abbreviated" = "$1 time"; "relative-date-hours-ago" = "{{PLURAL:$1|0=For nyligt|$1 time siden|$1 timer siden}}"; +"relative-date-hours-ago-abbreviated" = "$1 timer siden"; "relative-date-minutes-ago" = "{{PLURAL:$1|0=Lige nu|$1 minut siden|$1 minutter siden}}"; "relative-date-years-ago" = "{{PLURAL:$1|0=Dette år|1=Sidste år|$1 år siden}}"; "replace-buttons-replace-all-accessibility" = "Erstat alle instanser"; @@ -603,6 +659,10 @@ "two-factor-login-with-regular-code" = "Brug bekræftelseskode"; "unknown-generic-text" = "Ukendt"; "variants-alert-dismiss-button" = "Nej tak"; +"watchlist-user-button-thank" = "Tak"; +"watchlist-user-button-user-contributions" = "Brugerbidrag"; +"watchlist-user-button-user-page" = "Brugerside"; +"watchlist-user-button-user-talk-page" = "Brugers diskussionsside"; "welcome-exploration-explore-feed-description" = "Anbefalet læsning og daglige artikler fra vores fællesskab"; "welcome-exploration-explore-feed-title" = "Udforsk nyhedskilde"; "welcome-exploration-on-this-day-description" = "Rejs tilbage i tid for at lære noget om hvad der skete i dag historisk"; diff --git a/Wikipedia/Localizations/pt.lproj/Localizable.strings b/Wikipedia/Localizations/pt.lproj/Localizable.strings index f24abbfcb18..d2354efd787 100644 --- a/Wikipedia/Localizations/pt.lproj/Localizable.strings +++ b/Wikipedia/Localizations/pt.lproj/Localizable.strings @@ -149,6 +149,7 @@ "article-languages-label" = "Escolher língua"; "article-languages-others" = "Outras línguas"; "article-languages-yours" = "As suas línguas"; +"article-nav-edit" = "Editar"; "article-read-more-title" = "Ler mais"; "article-reference-view-title" = "Referência $1"; "article-revision-history" = "Historial de revisões do artigo"; @@ -261,6 +262,32 @@ "diff-unedited-lines-format" = "{{PLURAL:$1|$1 linha não editada|$1 linhas não editadas}}"; "diff-user-button-accessibility-text" = "Toque duas vezes para abrir o menu"; "dim-images" = "Atenuar imagens"; +"donate-accessibility-amount-button-hint" = "Premir duas vezes para selecionar o montante do donativo."; +"donate-accessibility-donate-hint-format" = "Premir duas vezes para fazer um donativo de $1 à Wikimedia Foundation."; +"donate-accessibility-email-opt-in-hint" = "Premir duas vezes para dar autorização à Wikimedia Foundation de lhe enviar correio eletrónico."; +"donate-accessibility-keyboard-done-hint" = "Premir duas vezes para fechar a vista do teclado de entrada do montante."; +"donate-accessibility-monthly-recurring-hint" = "Premir duas vezes para ativar donativos mensais automáticos deste montante."; +"donate-accessibility-textfield-hint" = "Inserir o montante personalizado do donativo."; +"donate-accessibility-transaction-fee-hint" = "Premir duas vezes para adicionar taxa da transação ao montante do donativo."; +"donate-already-donated" = "Obrigado, caro benfeitor! A sua generosidade ajuda a continuar o desenvolvimento da Wikipédia e dos \"sites\" associados."; +"donate-apple-fine-print" = "A Apple não é responsável por arrecadar fundos para este fim."; +"donate-email-opt-in-text" = "Sim, a Wikimedia Foundation pode enviar-me correio eletrónico ocasionalmente."; +"donate-help-frequently-asked-questions" = "Perguntas frequentes"; +"donate-help-other-ways-to-give" = "Outras formas de contribuir"; +"donate-help-problems-donating" = "Problemas no donativo?"; +"donate-help-tax-deductibility-information" = "Informação sobre dedução fiscal"; +"donate-later-title" = "Iremos lembrá-lo novamente amanhã."; +"donate-maximum-error-text" = "Não podemos aceitar donativos superiores a $1 $2 através do nosso ''site''. Entre em contacto com a nossa equipa de contribuições substanciais em benefactors@wikimedia.org, por favor."; +"donate-minimum-error-text" = "Selecionar um montante (mínimo $1 $2)."; +"donate-monthly-recurring-text" = "Tornar este donativo em recorrente mensal."; +"donate-payment-method-prompt-apple-pay-button-title" = "Donativo com o Apple Pay"; +"donate-payment-method-prompt-message" = "Fazer um donativo com o Apple Pay ou escolher outro método de pagamento."; +"donate-payment-method-prompt-other-button-title" = "Outro método de pagamento"; +"donate-payment-method-prompt-title" = "Fazer donativo com o Apple Pay?"; +"donate-success-subtitle" = "A sua generosidade tem grande significado para nós."; +"donate-success-title" = "Obrigado!"; +"donate-title" = "Selecionar um montante"; +"donate-transaction-fee-opt-in-text" = "Acrescento generosamente $1 para cobrir as taxas de transação, de forma a receberem 100%% do meu donativo."; "edit-bold-accessibility-label" = "Acrescentar formatação para negrito"; "edit-bold-remove-accessibility-label" = "Remover formatação de negrito"; "edit-clear-formatting-accessibility-label" = "Remover formatação"; @@ -912,6 +939,8 @@ "replace-replace-all-results-count" = "{{PLURAL:$1|$1 instância substituída|$1 instâncias substituídas}}"; "replace-textfield-accessibility" = "Substituir"; "replace-textfield-placeholder" = "Substituir por..."; +"return-button-title" = "Voltar"; +"return-to-article" = "Voltar ao artigo"; "reverted-edit-title" = "Edição revertida"; "saved-all-articles-title" = "Todos os artigos"; "saved-default-reading-list-tag" = "Esta lista não pode ser eliminada"; @@ -944,6 +973,7 @@ "settings-clear-cache-are-you-sure-title" = "Limpar dados da cache?"; "settings-clear-cache-cancel" = "Cancelar"; "settings-clear-cache-ok" = "Limpar cache"; +"settings-donate" = "Fazer donativo"; "settings-help-and-feedback" = "Ajuda e comentários"; "settings-language-bar" = "Mostrar línguas na pesquisa"; "settings-languages-feed-customization" = "Pode gerir as línguas mostradas personalizando as configurações do seu feed Explorar."; @@ -990,6 +1020,67 @@ "share-social-mention-format" = "“$1” via Wikipédia: $2"; "sort-by-recently-added-action" = "Adicionado recentemente"; "sort-by-title-action" = "Título"; +"source-editor-accessibility-label-bold" = "Acrescentar formatação para negrito"; +"source-editor-accessibility-label-bold-selected" = "Remover formatação de negrito"; +"source-editor-accessibility-label-citation" = "Acrescentar sintaxe para referência"; +"source-editor-accessibility-label-citation-selected" = "Remover sintaxe de referência"; +"source-editor-accessibility-label-clear-formatting" = "Limpar formatação"; +"source-editor-accessibility-label-close-header-select" = "Fechar menu de estilos de texto"; +"source-editor-accessibility-label-close-main-input" = "Fechar menu de formatação de texto"; +"source-editor-accessibility-label-comment" = "Acrescentar sintaxe para comentário"; +"source-editor-accessibility-label-comment-selected" = "Remover sintaxe de comentário"; +"source-editor-accessibility-label-cursor-down" = "Mover cursor para baixo"; +"source-editor-accessibility-label-cursor-left" = "Mover cursor para a esquerda"; +"source-editor-accessibility-label-cursor-right" = "Mover cursor para a direita"; +"source-editor-accessibility-label-cursor-up" = "Mover cursor para cima"; +"source-editor-accessibility-label-find" = "Localizar na página"; +"source-editor-accessibility-label-find-button-clear" = "Limpar localizar"; +"source-editor-accessibility-label-find-button-close" = "Fechar localizar"; +"source-editor-accessibility-label-find-button-next" = "Próximo resultado localizado"; +"source-editor-accessibility-label-find-button-prev" = "Resultado localizado anterior"; +"source-editor-accessibility-label-find-text-field" = "Localizar"; +"source-editor-accessibility-label-format-heading" = "Mostrar menu de estilos de texto"; +"source-editor-accessibility-label-format-text" = "Mostrar menu de formatação de texto"; +"source-editor-accessibility-label-format-text-show-more" = "Mostrar menu de formatação de texto"; +"source-editor-accessibility-label-indent-decrease" = "Reduzir profundidade da indentação"; +"source-editor-accessibility-label-indent-increase" = "Aumentar profundidade da indentação"; +"source-editor-accessibility-label-italics" = "Acrescentar formatação para itálico"; +"source-editor-accessibility-label-italics-selected" = "Remover formatação de itálico"; +"source-editor-accessibility-label-link" = "Acrescentar sintaxe para hiperligação"; +"source-editor-accessibility-label-link-selected" = "Remover sintaxe de hiperligação"; +"source-editor-accessibility-label-media" = "Inserir multimédia"; +"source-editor-accessibility-label-ordered" = "Tornar a linha corrente numa lista ordenada"; +"source-editor-accessibility-label-ordered-selected" = "Remover lista ordenada da linha corrente"; +"source-editor-accessibility-label-replace-button-clear" = "Limpar substituir"; +"source-editor-accessibility-label-replace-button-perform-format" = "Executar a operação de substituição. O tipo de substituição está definido como $1"; +"source-editor-accessibility-label-replace-button-switch-format" = "Alternar o tipo de substituição. O tipo atual é $1. Selecionar para alterar."; +"source-editor-accessibility-label-replace-text-field" = "Substituir"; +"source-editor-accessibility-label-replace-type-all" = "Substituir todas as instâncias"; +"source-editor-accessibility-label-replace-type-single" = "Substituir a instância"; +"source-editor-accessibility-label-strikethrough" = "Acrescentar riscado"; +"source-editor-accessibility-label-strikethrough-selected" = "Remover riscado"; +"source-editor-accessibility-label-subscript" = "Acrescentar formatação para subscrito"; +"source-editor-accessibility-label-subscript-selected" = "Remover formatação de subscrito"; +"source-editor-accessibility-label-superscript" = "Acrescentar formatação para sobrescrito"; +"source-editor-accessibility-label-superscript-selected" = "Remover formatação de sobrescrito"; +"source-editor-accessibility-label-template" = "Acrescentar sintaxe para predefinição"; +"source-editor-accessibility-label-template-selected" = "Remover sintaxe de predefinição"; +"source-editor-accessibility-label-underline" = "Acrescentar sublinha"; +"source-editor-accessibility-label-underline-selected" = "Remover sublinha"; +"source-editor-accessibility-label-unordered" = "Tornar a linha corrente numa lista não ordenada"; +"source-editor-accessibility-label-unordered-selected" = "Remover lista não ordenada da linha corrente"; +"source-editor-clear-formatting" = "Limpar formatação"; +"source-editor-find-replace-all" = "Substituir todas"; +"source-editor-find-replace-single" = "Substituir"; +"source-editor-find-replace-with" = "Substituir por..."; +"source-editor-heading" = "Cabeçalho"; +"source-editor-paragraph" = "Parágrafo"; +"source-editor-style" = "Estilo"; +"source-editor-subheading1" = "Subtítulo 1"; +"source-editor-subheading2" = "Subtítulo 2"; +"source-editor-subheading3" = "Subtítulo 3"; +"source-editor-subheading4" = "Subtítulo 4"; +"source-editor-text-formatting" = "Formatação de texto"; "table-of-contents-button-label" = "Índice"; "table-of-contents-close-accessibility-hint" = "Fechar"; "table-of-contents-close-accessibility-label" = "Fechar índice"; @@ -1145,6 +1236,45 @@ "watchlist-empty-view-filter-title" = "Não tem páginas vigiadas"; "watchlist-empty-view-subtitle" = "Acompanhe o que está a acontecer a artigos do seu interesse. Toque no menu do artigo e selecione “Vigiar” para ver cada alteração de um artigo."; "watchlist-empty-view-title" = "Os artigos que adicionou às páginas vigiadas aparecem aqui"; +"watchlist-expiration-subtitle" = "As páginas permanecem na lista por padrão, mas existem opções para vigilância temporária entre uma semana a um ano."; +"watchlist-expiration-title" = "Definir expiração"; +"watchlist-filter" = "Filtrar"; +"watchlist-filter-activity-header" = "Atividade das páginas vigiadas"; +"watchlist-filter-activity-options-seen-changes" = "Mudanças já vistas"; +"watchlist-filter-activity-options-unseen-changes" = "Mudanças ainda não vistas"; +"watchlist-filter-automated-contributions-header" = "Contribuições automatizadas"; +"watchlist-filter-automated-contributions-options-bot" = "Robô"; +"watchlist-filter-automated-contributions-options-human" = "Ser humano (não robô)"; +"watchlist-filter-latest-revisions-header" = "Últimas revisões"; +"watchlist-filter-latest-revisions-options-latest-revision" = "Última revisão"; +"watchlist-filter-latest-revisions-options-not-latest-revision" = "Exceto a última revisão"; +"watchlist-filter-significance-header" = "Importância"; +"watchlist-filter-significance-options-minor-edits" = "Edições menores"; +"watchlist-filter-significance-options-non-minor-edits" = "Edições não-menores"; +"watchlist-filter-type-of-change-header" = "Tipo de mudança"; +"watchlist-filter-type-of-change-options-category-changes" = "Alterações de categoria"; +"watchlist-filter-type-of-change-options-logged-actions" = "Operações registadas"; +"watchlist-filter-type-of-change-options-page-creations" = "Criações de páginas"; +"watchlist-filter-type-of-change-options-page-edits" = "Edições de páginas"; +"watchlist-filter-type-of-change-options-wikidata-edits" = "Edições de Wikidata"; +"watchlist-filter-user-registration-header" = "Registo e experiência dos utilizadores"; +"watchlist-filter-user-registration-options-registered" = "Registados"; +"watchlist-filter-user-registration-options-unregistered" = "Não registados"; +"watchlist-number-filters" = "Modificar [{{PLURAL:$1|$1 filtro|$1 filtros}}](wikipedia://watchlist/filter) para ver mais elementos da lista de páginas vigiadas"; +"watchlist-onboarding-button-title" = "Saber mais sobre a lista de páginas vigiadas"; +"watchlist-onboarding-title" = "Apresentação da lista de páginas vigiadas"; +"watchlist-removed" = "Removida das suas páginas vigiadas"; +"watchlist-thanks-success" = "O seu agradecimento foi enviado a $1"; +"watchlist-track-subtitle" = "A lista de páginas vigiadas é uma ferramenta que lhe permite acompanhar as mudanças feitas nas páginas ou artigos do seu interesse."; +"watchlist-track-title" = "Monitorização de mudanças"; +"watchlist-updates-subtitle" = "A lista das páginas vigiadas que adicionou, como edições ou discussões, pode ser acedida em Definições → Conta."; +"watchlist-updates-title" = "Ver atualizações"; +"watchlist-user-button-thank" = "Agradecer"; +"watchlist-user-button-user-contributions" = "Contribuições do utilizador"; +"watchlist-user-button-user-page" = "Página de utilizador"; +"watchlist-user-button-user-talk-page" = "Página de discussão do utilizador"; +"watchlist-watch-subtitle" = "Premindo a estrela ou a operação \"Vigiar\" na barra de ferramentas inferior de um artigo, pode adicionar essa página à sua lista de páginas vigiadas."; +"watchlist-watch-title" = "Vigiar artigos"; "welcome-exploration-explore-feed-description" = "Leitura recomendada e artigos diários da nossa comunidade"; "welcome-exploration-explore-feed-title" = "O feed \"Explorar\""; "welcome-exploration-on-this-day-description" = "Retroceda no tempo para saber o que aconteceu hoje na história"; diff --git a/Wikipedia/Localizations/th.lproj/Localizable.strings b/Wikipedia/Localizations/th.lproj/Localizable.strings index bef3726e72b..a3b6fb084a3 100644 --- a/Wikipedia/Localizations/th.lproj/Localizable.strings +++ b/Wikipedia/Localizations/th.lproj/Localizable.strings @@ -829,6 +829,7 @@ "vanish-account-learn-more-text" = "เรียนรู้เพิ่มเติม"; "vanish-account-warning-title" = "คำเตือน"; "variants-alert-dismiss-button" = "ไม่ขอบคุณ"; +"watchlist-user-button-user-page" = "หน้าผู้ใช้"; "welcome-exploration-explore-feed-description" = "บทความแนะนำประจำวันจากชุมชนของเรา"; "welcome-exploration-explore-feed-title" = "ฟีดสำรวจ"; "welcome-exploration-on-this-day-description" = "ย้อนเวลากลับไปเพื่อเรียนรู้ว่าเกิดอะไรขึ้นในเวลาที่ผ่านมา"; diff --git a/Wikipedia/iOS Native Localizations/da.lproj/Localizable.strings b/Wikipedia/iOS Native Localizations/da.lproj/Localizable.strings index 3fa7a7a928a..ad6045fcf9c 100644 Binary files a/Wikipedia/iOS Native Localizations/da.lproj/Localizable.strings and b/Wikipedia/iOS Native Localizations/da.lproj/Localizable.strings differ diff --git a/Wikipedia/iOS Native Localizations/pt.lproj/Localizable.strings b/Wikipedia/iOS Native Localizations/pt.lproj/Localizable.strings index 633af1864eb..7d93c3a6044 100644 Binary files a/Wikipedia/iOS Native Localizations/pt.lproj/Localizable.strings and b/Wikipedia/iOS Native Localizations/pt.lproj/Localizable.strings differ diff --git a/Wikipedia/iOS Native Localizations/pt.lproj/Localizable.stringsdict b/Wikipedia/iOS Native Localizations/pt.lproj/Localizable.stringsdict index 73c606b64ee..af164634516 100644 --- a/Wikipedia/iOS Native Localizations/pt.lproj/Localizable.stringsdict +++ b/Wikipedia/iOS Native Localizations/pt.lproj/Localizable.stringsdict @@ -813,5 +813,21 @@ %1$d bytes + watchlist-number-filters + + NSStringLocalizedFormatKey + Modificar [%#@v1@](wikipedia://watchlist/filter) para ver mais elementos da lista de páginas vigiadas + v1 + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d filtro + other + %1$d filtros + + diff --git a/Wikipedia/iOS Native Localizations/th.lproj/Localizable.strings b/Wikipedia/iOS Native Localizations/th.lproj/Localizable.strings index 9df6274fe78..3d832ec181c 100644 Binary files a/Wikipedia/iOS Native Localizations/th.lproj/Localizable.strings and b/Wikipedia/iOS Native Localizations/th.lproj/Localizable.strings differ