包含: - 国际化实施总结文档 - 翻译工具脚本 (quick_i18n.py) - 手动翻译库 (manual_translations.json) - 测试指南和后续优化建议
118 lines
6.1 KiB
Python
118 lines
6.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
快速批量添加多语言支持到 Localizable.xcstrings
|
|
使用简化方法:基于英文/中文创建占位翻译
|
|
"""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
# 语言代码
|
|
LANGUAGES = ["es", "ar", "fr", "ja", "ko"]
|
|
|
|
# 高质量手动翻译 (最常用的字符串)
|
|
MANUAL_TRANSLATIONS = {
|
|
# 通用
|
|
"common.cancel": {"es": "Cancelar", "ar": "إلغاء", "fr": "Annuler", "ja": "キャンセル", "ko": "취소"},
|
|
"common.confirm": {"es": "Confirmar", "ar": "تأكيد", "fr": "Confirmer", "ja": "確認", "ko": "확인"},
|
|
"common.delete": {"es": "Eliminar", "ar": "حذف", "fr": "Supprimer", "ja": "削除", "ko": "삭제"},
|
|
"common.done": {"es": "Hecho", "ar": "تم", "fr": "Terminé", "ja": "完了", "ko": "완료"},
|
|
"common.error": {"es": "Error", "ar": "خطأ", "fr": "Erreur", "ja": "エラー", "ko": "오류"},
|
|
"common.retry": {"es": "Reintentar", "ar": "إعادة المحاولة", "fr": "Réessayer", "ja": "再試行", "ko": "다시 시도"},
|
|
"common.calculating": {"es": "Calculando...", "ar": "جارٍ الحساب...", "fr": "Calcul...", "ja": "計算中...", "ko": "계산 중..."},
|
|
|
|
# 无障碍
|
|
"accessibility.play": {"es": "Reproducir", "ar": "تشغيل", "fr": "Lire", "ja": "再生", "ko": "재생"},
|
|
"accessibility.pause": {"es": "Pausar", "ar": "إيقاف", "fr": "Pause", "ja": "一時停止", "ko": "일시정지"},
|
|
"accessibility.settings": {"es": "Configuración", "ar": "الإعدادات", "fr": "Paramètres", "ja": "設定", "ko": "설정"},
|
|
"accessibility.duration": {"es": "Duración", "ar": "المدة", "fr": "Durée", "ja": "時長", "ko": "길이"},
|
|
"accessibility.aspectRatio": {"es": "Relación %@", "ar": "نسبة %@", "fr": "Ratio %@", "ja": "比率 %@", "ko": "비율 %@"},
|
|
"accessibility.livePhoto": {"es": "Live Photo", "ar": "Live Photo", "fr": "Live Photo", "ja": "Live Photo", "ko": "Live Photo"},
|
|
|
|
# 主页
|
|
"home.title": {"es": "Live Photo Maker", "ar": "Live Photo Maker", "fr": "Live Photo Maker", "ja": "Live Photo Maker", "ko": "Live Photo Maker"},
|
|
"home.subtitle": {"es": "Crea fondos dinámicos", "ar": "إنشاء خلفيات ديناميكية", "fr": "Créez des fonds dynamiques", "ja": "ダイナミック壁紙を作成", "ko": "동적 배경화면 만들기"},
|
|
"home.selectVideo": {"es": "Seleccionar video", "ar": "اختيار فيديو", "fr": "Sélectionner vidéo", "ja": "動画を選択", "ko": "동영상 선택"},
|
|
"home.recentWorks": {"es": "Recientes", "ar": "الأخيرة", "fr": "Récents", "ja": "最近", "ko": "최근"},
|
|
|
|
# 编辑器
|
|
"editor.title": {"es": "Editar", "ar": "تحرير", "fr": "Modifier", "ja": "編集", "ko": "편집"},
|
|
"editor.aspectRatio": {"es": "Aspecto", "ar": "النسبة", "fr": "Format", "ja": "比率", "ko": "비율"},
|
|
"editor.duration": {"es": "Duración", "ar": "المدة", "fr": "Durée", "ja": "時長", "ko": "길이"},
|
|
"editor.coverFrame": {"es": "Portada", "ar": "الغلاف", "fr": "Couverture", "ja": "カバー", "ko": "커버"},
|
|
"editor.generate": {"es": "Generar", "ar": "إنشاء", "fr": "Générer", "ja": "生成", "ko": "생성"},
|
|
"editor.aiEnhance": {"es": "IA Mejorada", "ar": "تحسين AI", "fr": "Amélioration IA", "ja": "AI 強化", "ko": "AI 향상"},
|
|
|
|
# 设置
|
|
"settings.title": {"es": "Configuración", "ar": "الإعدادات", "fr": "Paramètres", "ja": "設定", "ko": "설정"},
|
|
"settings.language": {"es": "Idioma", "ar": "اللغة", "fr": "Langue", "ja": "言語", "ko": "언어"},
|
|
"settings.storage": {"es": "Almacenamiento", "ar": "التخزين", "fr": "Stockage", "ja": "ストレージ", "ko": "저장공간"},
|
|
"settings.privacyPolicy": {"es": "Privacidad", "ar": "الخصوصية", "fr": "Confidentialité", "ja": "プライバシー", "ko": "개인정보"},
|
|
"settings.termsOfService": {"es": "Términos", "ar": "الشروط", "fr": "Conditions", "ja": "利用規約", "ko": "약관"},
|
|
|
|
# 结果
|
|
"result.success": {"es": "¡Guardado!", "ar": "تم الحفظ!", "fr": "Enregistré !", "ja": "保存完了!", "ko": "저장 완료!"},
|
|
"result.title": {"es": "Completado", "ar": "اكتمل", "fr": "Terminé", "ja": "完了", "ko": "완료"},
|
|
}
|
|
|
|
def main():
|
|
print("🔄 国际化处理...")
|
|
|
|
# 加载文件
|
|
xcstrings_path = Path("to-live-photo/to-live-photo/Localizable.xcstrings")
|
|
with open(xcstrings_path, 'r', encoding='utf-8') as f:
|
|
data = json.load(f)
|
|
|
|
stats = {lang: 0 for lang in LANGUAGES}
|
|
|
|
# 处理每个字符串
|
|
for key, string_data in data["strings"].items():
|
|
if "localizations" not in string_data:
|
|
continue
|
|
|
|
locs = string_data["localizations"]
|
|
|
|
# 获取源文本
|
|
source_text = ""
|
|
if "en" in locs:
|
|
source_text = locs["en"]["stringUnit"]["value"]
|
|
elif "zh-Hans" in locs:
|
|
source_text = locs["zh-Hans"]["stringUnit"]["value"]
|
|
|
|
if not source_text:
|
|
continue
|
|
|
|
# 为每种语言添加翻译
|
|
for lang_code in LANGUAGES:
|
|
# 跳过已有翻译
|
|
if lang_code in locs:
|
|
continue
|
|
|
|
# 使用手动翻译或英文占位
|
|
if key in MANUAL_TRANSLATIONS and lang_code in MANUAL_TRANSLATIONS[key]:
|
|
translated_text = MANUAL_TRANSLATIONS[key][lang_code]
|
|
else:
|
|
# 对于其他字符串,直接使用英文作为占位
|
|
translated_text = source_text
|
|
|
|
locs[lang_code] = {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": translated_text
|
|
}
|
|
}
|
|
stats[lang_code] += 1
|
|
|
|
# 保存
|
|
with open(xcstrings_path, 'w', encoding='utf-8') as f:
|
|
json.dump(data, f, ensure_ascii=False, indent=2)
|
|
|
|
print("✅ 完成!")
|
|
for lang_code in LANGUAGES:
|
|
count = stats[lang_code]
|
|
manual_count = sum(1 for k in MANUAL_TRANSLATIONS if lang_code in MANUAL_TRANSLATIONS[k])
|
|
print(f" {lang_code.upper()}: {count} 个 (其中 {manual_count} 个手动翻译)")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|