Skip to content

Commit ee70dc2

Browse files
committed
chore: insert new translation command
1 parent d5a5c05 commit ee70dc2

3 files changed

Lines changed: 157 additions & 0 deletions

File tree

src/app/Console/Commands/AlgoliaImportWorldHeritages.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public function handle(): int
5757
'countries' => static function ($query): void {
5858
$query->select(['countries.state_party_code', 'countries.name_en', 'countries.name_jp']);
5959
},
60+
'descriptions' => static function ($query): void {
61+
$query->select(['world_heritage_site_id', 'short_description_ja']);
62+
},
6063
])
6164
->select([
6265
'world_heritage_sites.id',
@@ -137,6 +140,7 @@ public function handle(): int
137140
'thumbnail_url' => $row->images->first()?->url,
138141
'state_party_codes' => $statePartyCodes,
139142
'country_names_jp' => $countryCount > 1 ? $countryNamesJp : [],
143+
'short_description_ja' => $row->descriptions->first()?->short_description_ja,
140144
];
141145
}
142146

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
3+
namespace App\Console\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use App\Models\WorldHeritageDescription;
7+
use Illuminate\Support\Facades\Http;
8+
9+
class TranslateShortDescriptionJapanese extends Command
10+
{
11+
/**
12+
* The name and signature of the console command.
13+
*
14+
* @var string
15+
*/
16+
protected $signature = 'world-heritage:translate-short-description-japanese
17+
{--force : Allow execution outside local environment}
18+
{--dry-run : Skip DB writes and API calls}';
19+
20+
/**
21+
* The console command description.
22+
*
23+
* @var string
24+
*/
25+
protected $description = 'Command description';
26+
27+
/**
28+
* Execute the console command.
29+
*/
30+
public function handle(): int
31+
{
32+
if (!app()->isLocal() && !$this->option('force')) {
33+
$this->error('This command can only be run in local environment. Use --force to override.');
34+
return 1;
35+
}
36+
37+
$jsonPath = storage_path('app/private/unesco/world-heritage-sites.json');
38+
39+
if (!file_exists($jsonPath)) {
40+
$this->error("JSON file not found: {$jsonPath}");
41+
return 1;
42+
}
43+
44+
$original = json_decode(file_get_contents($jsonPath), true);
45+
$sites = $original['results'];
46+
$total = count($sites);
47+
$this->info("Total sites: {$total}");
48+
49+
$bar = $this->output->createProgressBar($total);
50+
$bar->start();
51+
52+
foreach ($sites as $index => $site) {
53+
$idNo = $site['id_no'] ?? null;
54+
$shortDescriptionEn = $site['short_description_en'] ?? null;
55+
$descriptionEn = $site['description_en'] ?? null;
56+
57+
if (!$idNo || !$shortDescriptionEn || !$descriptionEn) {
58+
$bar->advance();
59+
continue;
60+
}
61+
62+
// DBに翻訳済みのものがあればそこから取得してJSONに反映
63+
// if translated columns are existed in DB, fetching from there and reflected on Json File
64+
$record = WorldHeritageDescription::where('world_heritage_site_id', $idNo)
65+
->whereNotNull('short_description_ja')
66+
->whereNotNull('description_ja')
67+
->first();
68+
69+
if ($record) {
70+
$sites[$index]['short_description_ja'] = $record->short_description_ja;
71+
$sites[$index]['description_ja'] = $record->description_ja;
72+
$bar->advance();
73+
continue;
74+
}
75+
76+
if ($this->option('dry-run')) {
77+
$this->line(" [dry-run] Would translate id_no={$idNo}: " . mb_substr($shortDescriptionEn, 0, 50) . '...');
78+
$bar->advance();
79+
continue;
80+
}
81+
82+
$texts = $shortDescriptionEn === $descriptionEn
83+
? [$shortDescriptionEn]
84+
: [$shortDescriptionEn, $descriptionEn];
85+
86+
$key = config('services.google.translate_key');
87+
$params = http_build_query(['key' => $key, 'target' => 'ja', 'format' => 'text']);
88+
foreach ($texts as $t) {
89+
$params .= '&q=' . urlencode($t);
90+
}
91+
92+
$response = Http::get('https://translation.googleapis.com/language/translate/v2?' . $params);
93+
94+
if (!$response->successful()) {
95+
$this->newLine();
96+
$this->error("Google Translate API error for id_no={$idNo}: " . $response->body());
97+
return 1;
98+
}
99+
100+
$translations = $response->json('data.translations');
101+
$shortDescriptionJa = $translations[0]['translatedText'];
102+
$descriptionJa = $shortDescriptionEn === $descriptionEn
103+
? $shortDescriptionJa
104+
: $translations[1]['translatedText'];
105+
106+
WorldHeritageDescription::updateOrCreate(
107+
['world_heritage_site_id' => $idNo],
108+
[
109+
'short_description_en' => $shortDescriptionEn,
110+
'short_description_ja' => $shortDescriptionJa,
111+
'description_en' => $descriptionEn,
112+
'description_ja' => $descriptionJa,
113+
]
114+
);
115+
116+
$sites[$index]['short_description_ja'] = $shortDescriptionJa;
117+
$sites[$index]['description_ja'] = $descriptionJa;
118+
119+
$bar->advance();
120+
usleep(200000);
121+
}
122+
123+
$bar->finish();
124+
$this->newLine();
125+
126+
if (!$this->option('dry-run')) {
127+
$outputDir = storage_path('app/private/unesco/normalized');
128+
$outputPath = $outputDir . '/world_heritage_sites_translation.json';
129+
130+
if (!is_dir($outputDir)) {
131+
mkdir($outputDir, 0755, true);
132+
}
133+
134+
$original['results'] = array_values($sites);
135+
file_put_contents($outputPath, json_encode($original, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
136+
$this->info("Translation JSON saved to: {$outputPath}");
137+
}
138+
139+
$this->info('Translation completed successfully.');
140+
141+
return 0;
142+
}
143+
}

src/app/Console/Commands/WorldHeritageBuild.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class WorldHeritageBuild extends Command
1919
{--dump-max=0 : 0 means no limit}
2020
{--dump-out=unesco/world-heritage-sites.json : Output path in local disk root (storage/app/private relative)}
2121
{--dump-dry-run : Do not write dump file}
22+
23+
{--translate-jp : Also translate short_description to Japanese}
24+
{--translate-jp-dry-run : Dry run for Japanese translation}
2225
2326
{--jp : Also import Japanese names}
2427
{--jp-path=unesco/world-heritage-japanese-name-sorted.json : Japanese name JSON path in local disk root (storage/app/private relative)}
@@ -100,6 +103,13 @@ public function handle(): int
100103
'--in' => self::NORM_DIR . '/world_heritage_sites.json',
101104
]);
102105

106+
if ((bool) $this->option('translate-jp')) {
107+
$this->callOrFail('world-heritage:translate-short-description-japanese', array_filter([
108+
'--force' => true,
109+
'--dry-run' => (bool) $this->option('translate-jp-dry-run') ? true : null,
110+
], static fn ($v) => $v !== null));
111+
}
112+
103113
// 4) Import pivot (FK depends on countries + sites)
104114
$this->callOrFail('world-heritage:import-site-state-parties-split', [
105115
'--in' => self::NORM_DIR . '/site_state_parties.json',

0 commit comments

Comments
 (0)