sync from local backup
This commit is contained in:
@@ -0,0 +1,364 @@
|
||||
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.');
|
||||
Reference in New Issue
Block a user