Skip to content

Commit 1b45a02

Browse files
committed
Initial commit
0 parents  commit 1b45a02

10 files changed

+458
-0
lines changed

Diff for: .editorconfig

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
indent_style = space
8+
indent_size = 4
9+
trim_trailing_whitespace = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false
13+
14+
[*.{yml,yaml}]
15+
indent_size = 2

Diff for: .gitignore

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.idea
2+
.php_cs
3+
.php_cs.cache
4+
.phpunit.result.cache
5+
build
6+
composer.lock
7+
coverage
8+
docs
9+
phpunit.xml
10+
psalm.xml
11+
testbench.yaml
12+
vendor
13+
node_modules
14+
.php-cs-fixer.cache

Diff for: LICENSE.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) Mohd Hafizuddin M Marzuki <[email protected]>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

Diff for: README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Laravel Language Helper Commands
2+
3+
[![Latest Version on Packagist](https://img.shields.io/packagist/v/apih/laravel-lang-helper.svg?style=flat-square)](https://packagist.org/packages/apih/laravel-lang-helper)
4+
[![Total Downloads](https://img.shields.io/packagist/dt/apih/laravel-lang-helper.svg?style=flat-square)](https://packagist.org/packages/apih/laravel-lang-helper)
5+
6+
This package provides helper commands that can be used in managing and organizing language localization messages.

Diff for: composer.json

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "apih/laravel-lang-helper",
3+
"description": "Language helper commands for Laravel-based application",
4+
"keywords": [
5+
"apih",
6+
"php",
7+
"laravel",
8+
"laravel-lang-helper",
9+
"localization",
10+
"translation"
11+
],
12+
"homepage": "https://github.com/apih/laravel-lang-helper",
13+
"license": "MIT",
14+
"authors": [
15+
{
16+
"name": ":Mohd Hafizuddin M Marzuki",
17+
"email": "[email protected]",
18+
"role": "Developer"
19+
}
20+
],
21+
"require": {
22+
"php": "^8.0",
23+
"laravel/framework": "^8.0"
24+
},
25+
"autoload": {
26+
"psr-4": {
27+
"Apih\\LangHelper\\": "src"
28+
}
29+
},
30+
"config": {
31+
"sort-packages": true
32+
},
33+
"extra": {
34+
"laravel": {
35+
"providers": [
36+
"Apih\\LangHelper\\LangHelperServiceProvider"
37+
]
38+
}
39+
},
40+
"minimum-stability": "dev",
41+
"prefer-stable": true
42+
}

Diff for: src/Commands/BaseCommand.php

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
namespace Apih\LangHelper\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use Illuminate\Filesystem\Filesystem;
7+
use Illuminate\Translation\Translator;
8+
use Symfony\Component\Finder\Finder;
9+
10+
class BaseCommand extends Command
11+
{
12+
protected Filesystem $filesystem;
13+
protected Finder $finder;
14+
protected Translator $translator;
15+
16+
/**
17+
* Create a new command instance.
18+
*
19+
* @param \Illuminate\Filesystem\Filesystem $filesystem
20+
* @param \Symfony\Component\Finder\Finder $finder
21+
* @param \Illuminate\Translation\Translator $translator
22+
* @return void
23+
*/
24+
public function __construct(Filesystem $filesystem, Finder $finder, Translator $translator)
25+
{
26+
parent::__construct();
27+
28+
$this->filesystem = $filesystem;
29+
$this->finder = $finder;
30+
$this->translator = $translator;
31+
}
32+
33+
/**
34+
* Print the line divider.
35+
*
36+
* @param int $length
37+
* @return void
38+
*/
39+
public function divider(int $length = 80)
40+
{
41+
$this->line(str_repeat('-', $length));
42+
}
43+
44+
/**
45+
* Print the duration taken by the command to complete its process.
46+
*
47+
* @return void
48+
*/
49+
public function runningTimeInfo()
50+
{
51+
$this->info(trans_choice('[0,1] Run in :count second|[2,*] Run in :count seconds', number_format(microtime(true) - LARAVEL_START, 3)));
52+
}
53+
}

Diff for: src/Commands/Json/DuplicatesCommand.php

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
namespace Apih\LangHelper\Commands\Json;
4+
5+
use Apih\LangHelper\Commands\BaseCommand;
6+
7+
class DuplicatesCommand extends BaseCommand
8+
{
9+
/**
10+
* The name and signature of the console command.
11+
*
12+
* @var string
13+
*/
14+
protected $signature = 'lang:json:duplicates';
15+
16+
/**
17+
* The console command description.
18+
*
19+
* @var string
20+
*/
21+
protected $description = 'Find duplicated translation messages in JSON files';
22+
23+
/**
24+
* Execute the console command.
25+
*
26+
* @return void
27+
*/
28+
public function handle()
29+
{
30+
$files = $this->finder->in(app()->langPath())->files()->name('*.json');
31+
$files = iterator_to_array($files, false);
32+
33+
// Terminate early if there is no file
34+
if (count($files) === 0) {
35+
$this->info(__('No language file is found.'));
36+
37+
return;
38+
}
39+
40+
// Find duplicates in each file
41+
foreach ($files as $file) {
42+
$messages = json_decode($file->getContents(), true);
43+
$result = [];
44+
45+
foreach ($messages as $message) {
46+
if (isset($result[$message])) {
47+
continue;
48+
}
49+
50+
$duplicates = array_filter($messages, function ($value) use ($message) {
51+
return $value === $message;
52+
});
53+
54+
if (count($duplicates) > 1) {
55+
$result[$message] = array_keys($duplicates);
56+
}
57+
}
58+
59+
$resultCount = count($result);
60+
$padCounterLength = strlen($resultCount);
61+
$spaces = str_repeat(' ', $padCounterLength);
62+
$counter = 1;
63+
64+
$this->info(__('Same messages with different keys found in :file.', ['file' => basename($file)]));
65+
$this->divider();
66+
67+
foreach ($result as $message => $items) {
68+
$paddedCounter = str_pad($counter++, $padCounterLength, ' ', STR_PAD_LEFT);
69+
70+
$this->line("{$paddedCounter}. <fg=cyan>{$message}</>");
71+
72+
foreach ($items as $item) {
73+
$this->line("{$spaces} - <fg=yellow>{$item}</>");
74+
}
75+
}
76+
77+
$this->newLine();
78+
}
79+
80+
$this->divider();
81+
$this->runningTimeInfo();
82+
}
83+
}

Diff for: src/Commands/Json/SortCommand.php

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
namespace Apih\LangHelper\Commands\Json;
4+
5+
use Apih\LangHelper\Commands\BaseCommand;
6+
7+
class SortCommand extends BaseCommand
8+
{
9+
/**
10+
* The name and signature of the console command.
11+
*
12+
* @var string
13+
*/
14+
protected $signature = 'lang:json:sort';
15+
16+
/**
17+
* The console command description.
18+
*
19+
* @var string
20+
*/
21+
protected $description = 'Sort messages in JSON language files';
22+
23+
/**
24+
* Execute the console command.
25+
*
26+
* @return void
27+
*/
28+
public function handle()
29+
{
30+
$files = $this->finder->in(app()->langPath())->files()->name('*.json');
31+
$files = iterator_to_array($files, false);
32+
33+
// Terminate early if no file is found
34+
if (count($files) === 0) {
35+
$this->info(__('No language file is found.'));
36+
37+
return;
38+
}
39+
40+
// Sort messages in each file
41+
foreach ($files as $file) {
42+
$messages = json_decode($file->getContents(), true);
43+
44+
// Case-insensitive sort
45+
uksort($messages, function ($a, $b) {
46+
return strcasecmp($a, $b);
47+
});
48+
49+
$messages = json_encode($messages, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
50+
51+
$this->filesystem->put($file, $messages . PHP_EOL);
52+
}
53+
54+
// Display the result
55+
$this->info(__('The content of the following language files has been sorted.'));
56+
$this->divider();
57+
58+
foreach ($files as $key => $file) {
59+
$this->line(sprintf('%d. <fg=cyan>%s</>', $key + 1, 'resources/lang/' . $file->getRelativePathname()));
60+
}
61+
62+
$this->newLine();
63+
$this->divider();
64+
$this->runningTimeInfo();
65+
}
66+
}

0 commit comments

Comments
 (0)