Skip to content

Instantly share code, notes, and snippets.

@ilyasozkurt
Last active March 30, 2024 14:23
Show Gist options
  • Save ilyasozkurt/258d0cbcdfe8657025c0c0f63f0af4ff to your computer and use it in GitHub Desktop.
Save ilyasozkurt/258d0cbcdfe8657025c0c0f63f0af4ff to your computer and use it in GitHub Desktop.
TranslateLangFiles.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use SplFileInfo;
class TranslateLangFiles extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'lang:translate {--source=} {--lang=} {--except=} {--include=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Translates the language files to other languages.';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
$this->source = $this->option('source') ?? config('app.locale');
$this->lang = $this->option('lang');
$this->except = $this->option('except');
$this->include = $this->option('include');
if (!$this->lang) {
$lang = $this->ask('What language do you want to translate to?');
if (!$lang) {
$this->error('You must provide a language');
return self::FAILURE;
}
if (!in_array($lang, array_keys(LaravelLocalization::getSupportedLocales()))) {
$this->error('Language not supported');
return self::FAILURE;
}
if ($lang == 'en') {
$this->error('You can\'t translate to english');
return self::FAILURE;
}
$this->lang = $lang;
}
if (!$this->except) {
$except = $this->ask('What files do you want to exclude? (separate by comma) (optional)');
if (!$except) {
$this->except = [];
} else {
$this->except = explode(',', $except);
}
}
if (!$this->include) {
$include = $this->ask('What files do you want to include? (separate by comma) (optional)');
if (!$include) {
$this->include = [];
} else {
$this->include = explode(',', $include);
}
}
$this->info('Translating from ' . $this->source . ' to ' . $this->lang);
foreach (File::allFiles(lang_path($this->source)) as $file) {
$this->processFile($file);
}
return self::SUCCESS;
}
public function processFile(SplFileInfo $file): void
{
$filename = $file->getFilename();
$filenameBody = $file->getFilenameWithoutExtension();
if (in_array($filename, $this->except) || in_array($filenameBody, $this->except)) {
$this->info('Skipping ' . $filename . ' because it is in the except list');
return;
}
if (count($this->include)) {
if (!in_array($filename, $this->include) && !in_array($filenameBody, $this->include)) {
$this->info('Translating ' . $filename . ' because it is in the include list');
$this->translateFile($file->getFilename(), $this->source, $this->lang);
return;
}
}
$this->info('Translating ' . $filename . ' because it is not in the except list');
$this->translateFile($file->getFilename(), $this->source, $this->lang);
}
/**
* @param string $file
* @param string $source
* @param string $target
* @return void
*/
public function translateFile(string $file, string $source, string $target): void
{
$fileContents = include lang_path($source . '/' . $file);
foreach ($fileContents as $key => $value) {
if (is_array($value)) {
foreach ($value as $key2 => $value2) {
if (is_array($value2)) {
foreach ($value2 as $key3 => $value3) {
$fileContents[$key][$key2][$key3] = $this->translateText($value3, $source, $target);
}
} else {
$fileContents[$key][$key2] = $this->translateText($value2, $source, $target);
}
}
} else {
$fileContents[$key] = $this->translateText($value, $source, $target);
}
}
$targetFile = lang_path($target . '/' . $file);
File::ensureDirectoryExists(pathinfo($targetFile, PATHINFO_DIRNAME));
File::replace($targetFile, '<?php return ' . var_export($fileContents, true) . ';');
}
/**
* @param string $value
* @param string $source
* @param string $target
* @return string
*/
public function translateText(string $value, string $source, string $target): string
{
$value = $this->encodeValueForTranslation($value);
$translated = $this->translateTextWithGoogleTranslate($value, $source, $target);
$translated = str_replace('<: ', '<:', $translated);
$translated = $this->decodeValueForSaving($translated);
$this->info('Translated: ' . $value . ' to ' . $translated);
return $translated;
}
/**
* @param string $content
* @param string $source
* @param string $target
* @return string
*/
public function translateTextWithGoogleTranslate(string $content, string $source, string $target): string
{
$response = Http::retry(3)
->throw()
->get('https://translate.googleapis.com/translate_a/single?client=gtx&sl=' . $source . '&tl=' . $target . '&dt=t&q=' . urlencode($content));
$response = json_decode($response->body());
$translatedText = '';
foreach ($response[0] as $translation) {
$translatedText .= $translation[0];
}
return !empty($translatedText) ? $translatedText : $content;
}
/**
* @param string $content
* @return string
*/
public function encodeValueForTranslation(string $content): string
{
return preg_replace('/:([a-zA-Z0-9_-]*)/', '<:$1>', $content);
}
/**
* @param string $content
* @return string
*/
public function decodeValueForSaving(string $content): string
{
return preg_replace('/<([:a-zA-Z0-9_-]*)>/', '$1', $content);
}
}
@vaix-dungpx
Copy link

Thanks You

@nahojj
Copy link

nahojj commented Oct 26, 2023

Your command only supports two arrays down. Here's a recursive approach to fix this.

public function translateFile(string $file, string $source, string $target): void
{
    $fileContents = include lang_path($source . '/' . $file);

    $fileContents = $this->recursiveTranslate($fileContents, $source, $target);

    $targetFile = lang_path($target . '/' . $file);

    File::ensureDirectoryExists(pathinfo($targetFile, PATHINFO_DIRNAME));
    File::replace($targetFile, '<?php return ' . var_export($fileContents, true) . ';');
}
protected function recursiveTranslate($data, string $source, string $target)
{
    if (is_array($data)) {
        foreach ($data as $key => $value) {
            $data[$key] = $this->recursiveTranslate($value, $source, $target);
        }
    } else {
        $data = $this->translateText($data, $source, $target);
    }

    return $data;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment