Files
2026-08-05 23:59:22 +08:00

365 lines
13 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const fs = require('fs');
const path = require('path');
const localesDir = path.join(__dirname, 'src', 'locales');
const translations = {
'zh': {
"timestamp": {
"pageTitle": "时间戳转换",
"pageDescription": "Unix时间戳与日期时间快速互转",
"pageCategory": "开发",
"backToTools": "返回工具列表",
"timezoneLabel": "时区选择",
"tsToDate": "时间戳转日期",
"dateToTs": "日期转时间戳",
"tsInputPlaceholder": "请输入时间戳,如 1700000000",
"tsEmptyHint": "输入时间戳后自动显示转换结果",
"dateEmptyHint": "选择日期后自动显示时间戳",
"getCurrentTime": "获取当前时间",
"clear": "清空",
"copied": "已复制到剪贴板",
"result": {
"localTime": "本地时间",
"utcTime": "UTC 时间",
"iso8601": "ISO 8601",
"relative": "相对时间",
"weekday": "星期",
"secondsTs": "秒级时间戳",
"msTs": "毫秒级时间戳",
"isoString": "ISO 字符串",
"invalidDate": "无效日期",
"unknown": "未知"
},
"timezone": {
"local": "本地时间",
"utc": "UTC",
"shanghai": "Asia/Shanghai (北京)",
"tokyo": "Asia/Tokyo (东京)",
"newyork": "America/New_York (纽约)",
"london": "Europe/London (伦敦)",
"losangeles": "America/Los_Angeles (洛杉矶)"
},
"badge": {
"seconds": "秒级",
"ms": "毫秒级"
}
}
},
'en': {
"timestamp": {
"pageTitle": "Timestamp Converter",
"pageDescription": "Quick conversion between Unix timestamps and datetime",
"pageCategory": "Dev",
"backToTools": "Back to Tools",
"timezoneLabel": "Timezone",
"tsToDate": "Timestamp to Date",
"dateToTs": "Date to Timestamp",
"tsInputPlaceholder": "Enter a timestamp, e.g. 1700000000",
"tsEmptyHint": "Conversion results will appear after entering a timestamp",
"dateEmptyHint": "Timestamp will appear after selecting a date",
"getCurrentTime": "Get Current Time",
"clear": "Clear",
"copied": "Copied to clipboard",
"result": {
"localTime": "Local Time",
"utcTime": "UTC Time",
"iso8601": "ISO 8601",
"relative": "Relative Time",
"weekday": "Weekday",
"secondsTs": "Seconds Timestamp",
"msTs": "Milliseconds Timestamp",
"isoString": "ISO String",
"invalidDate": "Invalid Date",
"unknown": "Unknown"
},
"timezone": {
"local": "Local Time",
"utc": "UTC",
"shanghai": "Asia/Shanghai (Beijing)",
"tokyo": "Asia/Tokyo (Tokyo)",
"newyork": "America/New_York (New York)",
"london": "Europe/London (London)",
"losangeles": "America/Los_Angeles (Los Angeles)"
},
"badge": {
"seconds": "Seconds",
"ms": "Milliseconds"
}
}
},
'ja': {
"timestamp": {
"pageTitle": "タイムスタンプ変換",
"pageDescription": "Unixタイムスタンプと日時を素早く相互変換",
"pageCategory": "開発",
"backToTools": "ツール一覧に戻る",
"timezoneLabel": "タイムゾーン",
"tsToDate": "タイムスタンプ → 日付",
"dateToTs": "日付 → タイムスタンプ",
"tsInputPlaceholder": "タイムスタンプを入力してください(例: 1700000000)",
"tsEmptyHint": "タイムスタンプを入力すると変換結果が表示されます",
"dateEmptyHint": "日付を選択するとタイムスタンプが表示されます",
"getCurrentTime": "現在の時刻を取得",
"clear": "クリア",
"copied": "クリップボードにコピーしました",
"result": {
"localTime": "ローカル時間",
"utcTime": "UTC 時間",
"iso8601": "ISO 8601",
"relative": "相対時間",
"weekday": "曜日",
"secondsTs": "秒単位タイムスタンプ",
"msTs": "ミリ秒単位タイムスタンプ",
"isoString": "ISO 文字列",
"invalidDate": "無効な日付",
"unknown": "不明"
},
"timezone": {
"local": "ローカル時間",
"utc": "UTC",
"shanghai": "Asia/Shanghai (北京)",
"tokyo": "Asia/Tokyo (東京)",
"newyork": "America/New_York (ニューヨーク)",
"london": "Europe/London (ロンドン)",
"losangeles": "America/Los_Angeles (ロサンゼルス)"
},
"badge": {
"seconds": "秒単位",
"ms": "ミリ秒単位"
}
}
},
'ko': {
"timestamp": {
"pageTitle": "타임스탬프 변환",
"pageDescription": "Unix 타임스탬프와 날짜/시간을 빠르게 상호 변환",
"pageCategory": "개발",
"backToTools": "도구 목록으로 돌아가기",
"timezoneLabel": "시간대",
"tsToDate": "타임스탬프 → 날짜",
"dateToTs": "날짜 → 타임스탬프",
"tsInputPlaceholder": "타임스탬프를 입력하세요 (예: 1700000000)",
"tsEmptyHint": "타임스탬프를 입력하면 변환 결과가 표시됩니다",
"dateEmptyHint": "날짜를 선택하면 타임스탬프가 표시됩니다",
"getCurrentTime": "현재 시간 가져오기",
"clear": "지우기",
"copied": "클립보드에 복사됨",
"result": {
"localTime": "로컬 시간",
"utcTime": "UTC 시간",
"iso8601": "ISO 8601",
"relative": "상대 시간",
"weekday": "요일",
"secondsTs": "초 단위 타임스탬프",
"msTs": "밀리초 단위 타임스탬프",
"isoString": "ISO 문자열",
"invalidDate": "유효하지 않은 날짜",
"unknown": "알 수 없음"
},
"timezone": {
"local": "로컬 시간",
"utc": "UTC",
"shanghai": "Asia/Shanghai (베이징)",
"tokyo": "Asia/Tokyo (도쿄)",
"newyork": "America/New_York (뉴욕)",
"london": "Europe/London (런던)",
"losangeles": "America/Los_Angeles (로스앤젤레스)"
},
"badge": {
"seconds": "초 단위",
"ms": "밀리초 단위"
}
}
},
'ru': {
"timestamp": {
"pageTitle": "Преобразование временных меток",
"pageDescription": "Быстрая конвертация между Unix-временными метками и датой/временем",
"pageCategory": "Разработка",
"backToTools": "Назад к списку инструментов",
"timezoneLabel": "Часовой пояс",
"tsToDate": "Метка → Дата",
"dateToTs": "Дата → Метка",
"tsInputPlaceholder": "Введите временную метку, например 1700000000",
"tsEmptyHint": "Результаты появятся после ввода временной метки",
"dateEmptyHint": "Временная метка появится после выбора даты",
"getCurrentTime": "Получить текущее время",
"clear": "Очистить",
"copied": "Скопировано в буфер обмена",
"result": {
"localTime": "Местное время",
"utcTime": "Время UTC",
"iso8601": "ISO 8601",
"relative": "Относительное время",
"weekday": "День недели",
"secondsTs": "Метка в секундах",
"msTs": "Метка в миллисекундах",
"isoString": "ISO-строка",
"invalidDate": "Недопустимая дата",
"unknown": "Неизвестно"
},
"timezone": {
"local": "Местное время",
"utc": "UTC",
"shanghai": "Asia/Shanghai (Пекин)",
"tokyo": "Asia/Tokyo (Токио)",
"newyork": "America/New_York (Нью-Йорк)",
"london": "Europe/London (Лондон)",
"losangeles": "America/Los_Angeles (Лос-Анджелес)"
},
"badge": {
"seconds": "В секундах",
"ms": "В миллисекундах"
}
}
},
'zh-TW': {
"timestamp": {
"pageTitle": "時間戳轉換",
"pageDescription": "Unix時間戳與日期時間快速互轉",
"pageCategory": "開發",
"backToTools": "返回工具列表",
"timezoneLabel": "時區選擇",
"tsToDate": "時間戳轉日期",
"dateToTs": "日期轉時間戳",
"tsInputPlaceholder": "請輸入時間戳,如 1700000000",
"tsEmptyHint": "輸入時間戳後自動顯示轉換結果",
"dateEmptyHint": "選擇日期後自動顯示時間戳",
"getCurrentTime": "取得目前時間",
"clear": "清空",
"copied": "已複製到剪貼簿",
"result": {
"localTime": "本地時間",
"utcTime": "UTC 時間",
"iso8601": "ISO 8601",
"relative": "相對時間",
"weekday": "星期",
"secondsTs": "秒級時間戳",
"msTs": "毫秒級時間戳",
"isoString": "ISO 字串",
"invalidDate": "無效日期",
"unknown": "未知"
},
"timezone": {
"local": "本地時間",
"utc": "UTC",
"shanghai": "Asia/Shanghai (北京)",
"tokyo": "Asia/Tokyo (東京)",
"newyork": "America/New_York (紐約)",
"london": "Europe/London (倫敦)",
"losangeles": "America/Los_Angeles (洛杉磯)"
},
"badge": {
"seconds": "秒級",
"ms": "毫秒級"
}
}
}
};
function formatNested(obj, indent) {
const pad = ' '.repeat(indent);
const innerPad = ' '.repeat(indent + 2);
const keys = Object.keys(obj);
let result = '{\n';
keys.forEach((key, idx) => {
const val = obj[key];
if (typeof val === 'object' && val !== null) {
result += innerPad + '"' + key + '": ' + formatNested(val, indent + 2);
} else {
const escaped = String(val).replace(/"/g, '\\"');
result += innerPad + '"' + key + '": "' + escaped + '"';
}
if (idx < keys.length - 1) result += ',';
result += '\n';
});
result += pad + '}';
return result;
}
function formatTimestampBlock(obj) {
const pad2 = ' ';
const pad4 = ' ';
const keys = Object.keys(obj);
let result = pad2 + '"timestamp": {\n';
keys.forEach((key, idx) => {
const val = obj[key];
if (typeof val === 'object' && val !== null) {
const subKeys = Object.keys(val);
result += pad4 + '"' + key + '": {\n';
subKeys.forEach((sk, sIdx) => {
const sv = val[sk];
result += ' "' + sk + '": "' + String(sv).replace(/"/g, '\\"') + '"';
if (sIdx < subKeys.length - 1) result += ',';
result += '\n';
});
result += pad4 + '}';
} else {
result += pad4 + '"' + key + '": "' + String(val).replace(/"/g, '\\"') + '"';
}
if (idx < keys.length - 1) result += ',';
result += '\n';
});
result += pad2 + '}';
return result;
}
// Find the LAST line containing the final `}` - we need to:
// 1. Skip any closing } that closes a nested object inside an already-closed outer block
// 2. The actual outer } has nothing but whitespace/comments after it.
// Strategy: Find the position of last `}` at the end of file.
// Since JSON can have nested closing braces, we use brace-counting from the end.
function insertTimestampBeforeFinalBrace(content, timestampBlock) {
// Normalize line endings
const c = content.replace(/\r\n/g, '\n');
// Remove trailing whitespace/newlines
const trimmed = c.replace(/\s+$/, '');
// The last character should be '}'
if (!trimmed.endsWith('}')) {
throw new Error('File does not end with }');
}
// Find content before the final '}'
// Find last '}' position
const lastCloseIdx = trimmed.lastIndexOf('}');
const beforeClosing = trimmed.slice(0, lastCloseIdx);
// Remove trailing whitespace/newlines from beforeClosing to get to the last property
const beforeTrimmed = beforeClosing.replace(/\s+$/, '');
// Determine if we need a comma: check if the last char of beforeTrimmed ends with a comma
// But also: if beforeTrimmed ends with } (closing of nested object at top-level),
// we may still need a comma. E.g.: "xxx": { ... } } -> beforeTrimmed ends with "..."xxx": { ... }
// In that case beforeTrimmed ends with } (of a nested obj), we need to add comma before adding our timestamp
const needsComma = !beforeTrimmed.endsWith(',');
const result = beforeTrimmed + (needsComma ? ',' : '') + '\n' + timestampBlock + '\n}';
return result;
}
['zh', 'en', 'ja', 'ko', 'ru', 'zh-TW'].forEach(lang => {
const filePath = path.join(localesDir, lang + '.json');
const content = fs.readFileSync(filePath, 'utf8');
// Check if already has timestamp (by string pattern)
if (content.indexOf('"timestamp"') !== -1) {
console.log(lang + '.json already has "timestamp" entry, skipping');
return;
}
const timestampBlock = formatTimestampBlock(translations[lang].timestamp);
try {
const newContent = insertTimestampBeforeFinalBrace(content, timestampBlock);
fs.writeFileSync(filePath, newContent + '\n', 'utf8');
console.log(lang + '.json: updated OK');
} catch (e) {
console.error(lang + '.json: FAILED - ' + e.message);
}
});
console.log('Done.');