Skip to content

Commit 15b789e

Browse files
committed
Fully automate the generation of CLDR country data.
1 parent a4019ae commit 15b789e

File tree

1 file changed

+69
-42
lines changed

1 file changed

+69
-42
lines changed

scripts/generate_country_data.php

Lines changed: 69 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22

33
/**
4-
* Generates the json files stored in resources/country.
4+
* Generates the json files stored in resources/country and updates CountryRepository.php.
55
*/
66

77
set_time_limit(0);
@@ -18,10 +18,8 @@
1818
// use it instead to presort the generated locale specific data.
1919
die('The intl extension was not found.');
2020
}
21-
// Make sure we're starting from a clean slate.
22-
if (is_dir(__DIR__ . '/country')) {
23-
die('The country/ directory must not exist.');
24-
}
21+
22+
$countryDirectory = __DIR__ . '/../resources/country';
2523

2624
$englishData = json_decode(file_get_contents($dataDirectory . '/cldr-localenames-full/main/en/territories.json'), true);
2725
$englishData = $englishData['main']['en']['localeDisplayNames']['territories'];
@@ -30,28 +28,25 @@
3028
$localizations = generate_localizations($baseData, $englishData, $dataDirectory);
3129
$localizations = filter_duplicate_localizations($localizations);
3230

33-
// Prepare the filesystem.
34-
if (!mkdir($concurrentDirectory = __DIR__ . '/country') && !is_dir($concurrentDirectory)) {
35-
throw new \RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory));
31+
// Clean up existing JSON files.
32+
foreach (glob($countryDirectory . '/*.json') as $file) {
33+
unlink($file);
3634
}
37-
3835
// Write out the localizations.
3936
foreach ($localizations as $locale => $localizedCountries) {
4037
$collator = collator_create($locale);
4138
uasort($localizedCountries, static function ($a, $b) use ($collator) {
4239
return collator_compare($collator, $a, $b);
4340
});
44-
file_put_json(__DIR__ . '/country/' . $locale . '.json', $localizedCountries);
41+
file_put_json($countryDirectory . '/' . $locale . '.json', $localizedCountries);
4542
}
4643

4744
$availableLocales = array_keys($localizations);
4845
sort($availableLocales);
49-
// Base country definitions and available locales are stored
50-
// in PHP, then manually transferred to CountryRepository.
51-
$data = "<?php\n\n";
52-
$data .= export_locales($availableLocales);
53-
$data .= export_base_data($baseData);
54-
file_put_contents(__DIR__ . '/country_data.php', $data);
46+
47+
// Update CountryRepository.php with the new data.
48+
$repositoryPath = __DIR__ . '/../src/Country/CountryRepository.php';
49+
update_country_repository($repositoryPath, $availableLocales, $baseData);
5550

5651
echo "Done.\n";
5752

@@ -67,11 +62,64 @@ function file_put_json(string $filename, array $data): void
6762
}
6863

6964
/**
70-
* Exports base data.
65+
* Updates CountryRepository.php with new locale and base data.
7166
*/
72-
function export_base_data(array $baseData): string
67+
function update_country_repository(string $filePath, array $availableLocales, array $baseData): void
7368
{
74-
$export = '$baseData = [' . "\n";
69+
$content = file_get_contents($filePath);
70+
// Replace $availableLocales.
71+
$localesString = format_available_locales($availableLocales);
72+
$content = preg_replace(
73+
'/protected array \$availableLocales = \[.*?\];/s',
74+
'protected array $availableLocales = ' . $localesString . ';',
75+
$content
76+
);
77+
// Update the data in getBaseDefinitions().
78+
$baseDataString = format_base_data($baseData);
79+
$content = preg_replace(
80+
'/(protected function getBaseDefinitions\(\): array\s*\{[^\[]*return )\[.*?\];(\s*\})/s',
81+
'$1' . $baseDataString . ';$2',
82+
$content
83+
);
84+
85+
file_put_contents($filePath, $content);
86+
}
87+
88+
/**
89+
* Formats the available locales as PHP code.
90+
*/
91+
function format_available_locales(array $locales): string
92+
{
93+
$lines = [];
94+
$indent = ' ';
95+
$maxLineLength = 70;
96+
$currentLine = [];
97+
foreach ($locales as $locale) {
98+
$quoted = "'" . $locale . "'";
99+
$lineContent = implode(', ', array_merge($currentLine, [$quoted]));
100+
if (strlen($lineContent) > $maxLineLength) {
101+
// Line length reached, add line and start a new one.
102+
$lines[] = $indent . implode(', ', $currentLine) . ',';
103+
$currentLine = [$quoted];
104+
} else {
105+
// Add to current line
106+
$currentLine[] = $quoted;
107+
}
108+
}
109+
// Add the last line.
110+
if (!empty($currentLine)) {
111+
$lines[] = $indent . implode(', ', $currentLine) . ',';
112+
}
113+
114+
return "[\n" . implode("\n", $lines) . "\n ]";
115+
}
116+
117+
/**
118+
* Formats the base data as PHP code.
119+
*/
120+
function format_base_data(array $baseData): string
121+
{
122+
$lines = [];
75123
foreach ($baseData as $countryCode => $countryData) {
76124
$threeLetterCode = 'null';
77125
if (isset($countryData['three_letter_code'])) {
@@ -86,31 +134,10 @@ function export_base_data(array $baseData): string
86134
$currencyCode = "'" . $countryData['currency_code'] . "'";
87135
}
88136

89-
$export .= " '" . $countryCode . "' => [";
90-
$export .= $threeLetterCode . ", " . $numericCode . ', ' . $currencyCode;
91-
$export .= "],\n";
137+
$lines[] = " '" . $countryCode . "' => [" . $threeLetterCode . ", " . $numericCode . ', ' . $currencyCode . "],";
92138
}
93-
$export .= "];";
94-
95-
return $export;
96-
}
97-
98-
/**
99-
* Exports locales.
100-
*/
101-
function export_locales(array $data): string
102-
{
103-
// Wrap the values in single quotes.
104-
$data = array_map(static function ($value) {
105-
return "'" . $value . "'";
106-
}, $data);
107-
108-
$export = '// ' . count($data) . " available locales. \n";
109-
$export .= '$locales = [' . "\n";
110-
$export .= ' ' . implode(', ', $data) . "\n";
111-
$export .= "];\n\n";
112139

113-
return $export;
140+
return "[\n" . implode("\n", $lines) . "\n ]";
114141
}
115142

116143
/**

0 commit comments

Comments
 (0)