my-homelab-configs/apps/website/save_lang.php

72 lines
2.4 KiB
PHP

<?php
header('Content-Type: application/json');
function translation_response(int $status, array $body): never {
http_response_code($status);
echo json_encode($body, JSON_UNESCAPED_SLASHES);
exit;
}
function clean_translation_value(string $value, int $maxLength = 2000): string {
$value = strip_tags($value);
$value = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $value) ?? '';
$value = trim($value);
if (strlen($value) > $maxLength) {
$value = substr($value, 0, $maxLength);
}
return $value;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
translation_response(405, ['error' => 'Method not allowed']);
}
if ((int) ($_SERVER['CONTENT_LENGTH'] ?? 0) > 131072) {
translation_response(413, ['error' => 'Request too large']);
}
$body = json_decode(file_get_contents('php://input'), true);
if (!is_array($body) || !isset($body['lang'], $body['translations']) || !is_array($body['translations'])) {
translation_response(400, ['error' => 'Missing lang or translations']);
}
$lang = preg_replace('/[^a-z]/', '', strtolower($body['lang']));
$translations = $body['translations'];
if (strlen($lang) < 2 || strlen($lang) > 5) {
translation_response(400, ['error' => 'Invalid lang code']);
}
$base = include __DIR__ . '/lang/en.php';
if (file_exists(__DIR__ . "/lang/$lang.php")) {
translation_response(409, ['error' => 'Static language already exists']);
}
foreach ($translations as $key => $value) {
if (is_string($key) && array_key_exists($key, $base) && (is_string($value) || is_numeric($value))) {
$base[$key] = clean_translation_value((string) $value);
}
}
$content = json_encode($base, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . "\n";
if ($content === false) {
translation_response(500, ['error' => 'Could not encode language file']);
}
$langDir = getenv('WEBSITE_LANG_WRITE_DIR') ?: (sys_get_temp_dir() . '/website-lang');
if (!is_dir($langDir) && !mkdir($langDir, 0755, true)) {
translation_response(500, ['error' => 'Could not create language directory']);
}
$path = "$langDir/$lang.json";
$tmpPath = "$path.tmp." . bin2hex(random_bytes(6));
if (file_put_contents($tmpPath, $content, LOCK_EX) === false || !rename($tmpPath, $path)) {
@unlink($tmpPath);
translation_response(500, ['error' => 'Could not write language file']);
}
echo json_encode(['success' => true, 'lang' => $lang]);