import json
import os
from datetime import datetime, timezone
from pathlib import Path
try:
import opencc
converter = opencc.OpenCC('s2t')
print("OpenCC loaded successfully.")
except ImportError:
converter = None
print("Warning: opencc-python-reimplemented not found. Traditional Chinese conversion will be skipped (content will remain Simplified).")
BUILD_DATE_ISO = datetime.now(timezone.utc).isoformat(timespec='seconds')
def compute_card_dates(card_abs_path, new_lang_data):
old_data = None
if os.path.exists(card_abs_path):
try:
with open(card_abs_path, 'r', encoding='utf-8') as f:
old_data = json.load(f)
except Exception:
old_data = None
if old_data is None:
return (BUILD_DATE_ISO, BUILD_DATE_ISO)
old_no_dates = {k: v for k, v in old_data.items() if k not in ('datePublished', 'dateModified')}
if old_no_dates == new_lang_data:
return (
old_data.get('datePublished') or BUILD_DATE_ISO,
old_data.get('dateModified') or BUILD_DATE_ISO,
)
return (
old_data.get('datePublished') or BUILD_DATE_ISO,
BUILD_DATE_ISO,
)
current_dir = os.path.join(os.getcwd(), 'src', 'data')
input_path = os.path.join(current_dir, 'prompt.json')
meta_cards_path = os.path.join(current_dir, 'meta_cards.json')
meta_faqs_path = os.path.join(current_dir, 'meta_faqs.json')
output_dir_path = os.path.join(current_dir, 'default')
output_dir_path_cards = os.path.join(current_dir, 'cards')
allLanguages = ["zh-Hans", "en", "zh-Hant", "ja", "ko", "es", "pt", "hi", "ind", "vi", "th", "fr", "de", "it", "ru", "ar", "tr", "bn"]
with open(input_path, 'r', encoding='utf-8') as file:
data = json.load(file)
meta_map = {}
if os.path.exists(meta_cards_path):
try:
with open(meta_cards_path, 'r', encoding='utf-8') as meta_file:
meta_data = json.load(meta_file)
for item in meta_data:
if isinstance(item, dict) and 'id' in item:
meta_map[item['id']] = {
'description': item.get('description', {}),
'title': item.get('title', {})
}
except Exception as e:
print(f"Warn: failed to load meta_description.json: {e}")
faq_map = {}
if os.path.exists(meta_faqs_path):
try:
with open(meta_faqs_path, 'r', encoding='utf-8') as faq_file:
faq_data = json.load(faq_file)
for id_key, locales in faq_data.items():
if not isinstance(locales, dict):
continue
try:
item_id = int(id_key)
except (ValueError, TypeError):
continue
faq_map[item_id] = locales
except Exception as e:
print(f"Warn: failed to load meta_faqs.json: {e}")
max_id = -1
for item in data:
if item['id'] > max_id:
max_id = item['id']
favor_ids = [2, 209, 251]
other_ids = [185, 197, 109, 20, 1]
favor_data = [item for item in data if item['id'] in favor_ids]
other_data = [item for item in data if item['id'] in other_ids]
def get_lang_content(item, target_lang):
if target_lang == 'zh-Hans':
return item.get('zh')
elif target_lang == 'zh-Hant':
content = item.get('zh')
if content:
if converter:
converted = {}
for k, v in content.items():
if isinstance(v, str):
converted[k] = converter.convert(v)
else:
converted[k] = v
return converted
return content
return None
return item.get(target_lang)
def get_meta_content(item_id, field, target_lang):
meta_dict = meta_map.get(item_id, {}).get(field, {})
if target_lang == 'zh-Hans':
return meta_dict.get('zh', "")
elif target_lang == 'zh-Hant':
content = meta_dict.get('zh', "")
if content and converter:
return converter.convert(content)
return content
return meta_dict.get(target_lang, "")
def get_faq_content(item_id, target_lang):
locales = faq_map.get(item_id, {})
faq = locales.get(target_lang)
return faq if isinstance(faq, list) else []
def process_and_save_data(filtered_data, file_prefix, ids_order):
for lang in allLanguages:
processed_data = []
for item in filtered_data:
content = get_lang_content(item, lang)
if content:
count = item['weight']
new_item = {
lang: content,
'id': item['id'],
'tags': item.get('tags'),
'website': item.get('website'),
'count': count
}
processed_data.append(new_item)
processed_data_sorted = sorted(processed_data, key=lambda x: ids_order.index(x['id']))
output_file_path = os.path.join(output_dir_path, f'{file_prefix}_{lang}.json')
with open(output_file_path, 'w', encoding='utf-8') as file:
json.dump(processed_data_sorted, file, ensure_ascii=False, separators=(',', ':'))
os.makedirs(output_dir_path, exist_ok=True)
process_and_save_data(favor_data, 'favor', favor_ids)
process_and_save_data(other_data, 'other', other_ids)
os.makedirs(output_dir_path_cards, exist_ok=True)
def compute_related_map(all_data, top_n=3):
"""计算每条 prompt 的 top-N 相关 prompt IDs。
算法:overlap_tag_count × 100000 + weight,降序取前 top_n
tag 重叠度优先,同重叠度按热度
返回 { prompt_id: [related_id_1, ...] }
"""
related = {}
for cur in all_data:
cur_id = cur.get('id')
cur_tags = set(cur.get('tags') or [])
if cur_id is None:
continue
if not cur_tags:
related[cur_id] = []
continue
candidates = []
for other in all_data:
oid = other.get('id')
if oid == cur_id or oid is None:
continue
other_tags = set(other.get('tags') or [])
overlap = len(cur_tags & other_tags)
if overlap == 0:
continue
score = overlap * 100_000 + int(other.get('weight') or 0)
candidates.append((score, oid))
candidates.sort(key=lambda x: -x[0])
related[cur_id] = [cid for _, cid in candidates[:top_n]]
return related
def save_data_by_id_and_language(data):
related_map = compute_related_map(data)
by_id = {item.get('id'): item for item in data if item.get('id') is not None}
for item in data:
for lang in allLanguages:
content = get_lang_content(item, lang)
if content:
related_full = []
for rid in related_map.get(item["id"], []):
related_item = by_id.get(rid)
if related_item is None:
continue
rcontent = get_lang_content(related_item, lang)
if not rcontent:
continue
related_full.append({
"id": rid,
"title": rcontent.get("title", ""),
"remark": rcontent.get("remark", ""),
})
lang_data = {
"id": item["id"],
lang: content,
"tags": item.get("tags", []),
"website": item.get("website", ""),
"count": item.get("weight", 0),
"related": related_full,
"metaTitle": get_meta_content(item["id"], 'title', lang),
"metaDescription": get_meta_content(item["id"], 'description', lang),
"faq": get_faq_content(item["id"], lang),
}
output_file_path = os.path.join(output_dir_path_cards, f'{item["id"]}_{lang}.json')
date_pub, date_mod = compute_card_dates(output_file_path, lang_data)
lang_data["datePublished"] = date_pub
lang_data["dateModified"] = date_mod
with open(output_file_path, 'w', encoding='utf-8') as file:
json.dump(lang_data, file, ensure_ascii=False, separators=(',', ':'))
save_data_by_id_and_language(data)
output_dir = current_dir
languages = allLanguages
output_data = {lang: [] for lang in languages}
for element in data:
for lang in languages:
lang_data = get_lang_content(element, lang)
if lang_data:
new_element = {
lang: lang_data,
'website': element['website'],
'tags': element['tags'],
'id': element['id'],
'weight': element['weight']
}
output_data[lang].append(new_element)
for lang in languages:
output_path = os.path.join(output_dir, f'prompt_{lang}.json')
if os.path.exists(output_path):
os.remove(output_path)
with open(output_path, 'w', encoding='utf-8') as file:
json.dump(output_data[lang], file, ensure_ascii=False, separators=(',', ':'))
def replace_and_write(source_file, destination_file, replacements):
with open(source_file, 'r', encoding='utf-8') as file:
file_data = file.read()
for original_text, replacement_text in replacements:
file_data = file_data.replace(original_text, replacement_text)
with open(destination_file, 'w', encoding='utf-8') as file:
file.write(file_data)
source_file = os.path.join(os.getcwd(), 'src', 'pages', 'index.tsx')
for lang in languages[1:]:
target_file = os.path.join(os.getcwd(), 'i18n', lang, 'docusaurus-plugin-content-pages', 'index.tsx')
os.makedirs(os.path.dirname(target_file), exist_ok=True)
if os.path.exists(target_file):
os.remove(target_file)
replacements = [
('favor_zh-Hans', f'favor_{lang}'),
('other_zh-Hans', f'other_{lang}'),
]
replace_and_write(source_file, target_file, replacements)