• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

move-elevator / composer-translation-validator / 16137064113

08 Jul 2025 07:41AM UTC coverage: 78.302% (-16.2%) from 94.526%
16137064113

Pull #19

github

web-flow
Merge 5f8b3255c into 3e904fb25
Pull Request #19: refactor: improve output style

93 of 278 new or added lines in 7 files covered. (33.45%)

103 existing lines in 7 files now uncovered.

830 of 1060 relevant lines covered (78.3%)

4.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.74
/src/Validator/DuplicateKeysValidator.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace MoveElevator\ComposerTranslationValidator\Validator;
6

7
use MoveElevator\ComposerTranslationValidator\Parser\ParserInterface;
8
use MoveElevator\ComposerTranslationValidator\Parser\XliffParser;
9
use MoveElevator\ComposerTranslationValidator\Result\Issue;
10
use Symfony\Component\Console\Helper\Table;
11
use Symfony\Component\Console\Helper\TableSeparator;
12
use Symfony\Component\Console\Helper\TableStyle;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Output\OutputInterface;
15

16
class DuplicateKeysValidator extends AbstractValidator implements ValidatorInterface
17
{
18
    /**
19
     * @return array<string, int>
20
     */
21
    public function processFile(ParserInterface $file): array
3✔
22
    {
23
        $keys = $file->extractKeys();
3✔
24

25
        if (!$keys) {
3✔
26
            $this->logger?->error('The source file '.$file->getFileName().' is not valid.');
1✔
27

28
            return [];
1✔
29
        }
30

31
        $duplicateKeys = array_filter(array_count_values($keys), static fn ($count) => $count > 1);
2✔
32
        if (!empty($duplicateKeys)) {
2✔
33
            return $duplicateKeys;
1✔
34
        }
35

36
        return [];
1✔
37
    }
38

39
    /**
40
     * @param array<string, array<int, array{
41
     *      file: string,
42
     *      issues: array<string, int>,
43
     *      parser: string,
44
     *      type: string
45
     *  }>> $issueSets
46
     */
47
    public function renderIssueSets(InputInterface $input, OutputInterface $output, array $issueSets): void
5✔
48
    {
49
        $rows = [];
5✔
50
        $currentFile = null;
5✔
51

52
        foreach ($issueSets as $issues) {
5✔
53
            foreach ($issues as $duplicates) {
5✔
54
                if ($currentFile !== $duplicates['file'] && null !== $currentFile) {
5✔
55
                    $rows[] = new TableSeparator();
1✔
56
                }
57
                $currentFile = $duplicates['file'];
5✔
58
                foreach ($duplicates['issues'] as $key => $count) {
5✔
59
                    $rows[] = ['<fg=red>'.$duplicates['file'].'</>', $key, $count];
5✔
60
                    $duplicates['file'] = ''; // Reset file for subsequent rows
5✔
61
                }
62
            }
63
        }
64

65
        (new Table($output))
5✔
66
            ->setHeaders(['File', 'Key', 'Count duplicates'])
5✔
67
            ->setRows($rows)
5✔
68
            ->setStyle(
5✔
69
                (new TableStyle())
5✔
70
                    ->setCellHeaderFormat('%s')
5✔
71
            )
5✔
72
            ->render();
5✔
73
    }
74

75
    public function explain(): string
2✔
76
    {
77
        return 'This validator checks for duplicate keys in translation files. '
2✔
78
            .'If a key appears more than once in a file, it will be reported as an issue.';
2✔
79
    }
80

81
    /**
82
     * @return class-string<ParserInterface>[]
83
     */
84
    public function supportsParser(): array
1✔
85
    {
86
        return [XliffParser::class];
1✔
87
    }
88

NEW
UNCOV
89
    public function formatIssueMessage(Issue $issue, string $prefix = '', bool $isVerbose = false): string
×
90
    {
NEW
UNCOV
91
        $details = $issue->getDetails();
×
NEW
UNCOV
92
        $resultType = $this->resultTypeOnValidationFailure();
×
93

NEW
UNCOV
94
        $level = $resultType->toString();
×
NEW
UNCOV
95
        $color = $resultType->toColorString();
×
96

97
        // Details contains duplicate keys with their counts
NEW
UNCOV
98
        $messages = [];
×
NEW
UNCOV
99
        foreach ($details as $key => $count) {
×
NEW
UNCOV
100
            if (is_string($key) && is_int($count)) {
×
NEW
UNCOV
101
                $messages[] = "- <fg=$color>$level</> {$prefix}the translation key `$key` occurs multiple times ({$count}x)";
×
102
            }
103
        }
104

NEW
UNCOV
105
        return implode("\n", $messages);
×
106
    }
107
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc