From 43e490d9332d8b293e46e869b27b6bb96d66da97 Mon Sep 17 00:00:00 2001 From: logikonline Date: Tue, 17 Mar 2026 11:35:20 -0400 Subject: [PATCH] feat(i18n): add bulk AI translation for all languages Add "Translate All (AI)" button to pages language settings that translates all configured languages in one operation. Shows success/partial success messages with counts. Adds locale keys for all 29 languages. Also removes trailing newlines from locale files for consistency. --- modules/pages/config.go | 11 +++ options/locale/locale_cs-CZ.json | 5 +- options/locale/locale_de-DE.json | 5 +- options/locale/locale_el-GR.json | 5 +- options/locale/locale_en-US.json | 3 + options/locale/locale_es-ES.json | 5 +- options/locale/locale_fa-IR.json | 5 +- options/locale/locale_fi-FI.json | 5 +- options/locale/locale_fr-FR.json | 5 +- options/locale/locale_ga-IE.json | 5 +- options/locale/locale_hi-IN.json | 5 +- options/locale/locale_hu-HU.json | 5 +- options/locale/locale_id-ID.json | 5 +- options/locale/locale_is-IS.json | 5 +- options/locale/locale_it-IT.json | 5 +- options/locale/locale_ja-JP.json | 5 +- options/locale/locale_ko-KR.json | 5 +- options/locale/locale_lv-LV.json | 5 +- options/locale/locale_nl-NL.json | 5 +- options/locale/locale_pl-PL.json | 5 +- options/locale/locale_pt-BR.json | 5 +- options/locale/locale_pt-PT.json | 5 +- options/locale/locale_ru-RU.json | 5 +- options/locale/locale_si-LK.json | 5 +- options/locale/locale_sk-SK.json | 5 +- options/locale/locale_sv-SE.json | 5 +- options/locale/locale_tr-TR.json | 5 +- options/locale/locale_uk-UA.json | 5 +- options/locale/locale_zh-CN.json | 5 +- options/locale/locale_zh-TW.json | 5 +- routers/web/pages/pages.go | 37 ++++++++ routers/web/repo/setting/pages.go | 51 +++++++++++ services/pages/generate.go | 20 +++++ templates/pages/architecture-deep-dive.tmpl | 38 ++++----- templates/pages/bold-marketing.tmpl | 60 ++++++------- templates/pages/cli-terminal.tmpl | 38 ++++----- templates/pages/developer-tool.tmpl | 38 ++++----- templates/pages/documentation-first.tmpl | 38 ++++----- templates/pages/footer.tmpl | 6 +- templates/pages/header.tmpl | 8 +- templates/pages/minimalist-docs.tmpl | 58 ++++++------- templates/pages/open-source-hero.tmpl | 38 ++++----- templates/pages/saas-conversion.tmpl | 50 +++++------ templates/pages/visual-showcase.tmpl | 38 ++++----- templates/repo/settings/pages_languages.tmpl | 89 +++++++++++++++----- 45 files changed, 505 insertions(+), 256 deletions(-) diff --git a/modules/pages/config.go b/modules/pages/config.go index e7c746f731..dceb5c7fb8 100644 --- a/modules/pages/config.go +++ b/modules/pages/config.go @@ -258,6 +258,17 @@ type NavigationConfig struct { ShowRepository bool `yaml:"show_repository,omitempty"` ShowReleases bool `yaml:"show_releases,omitempty"` ShowIssues bool `yaml:"show_issues,omitempty"` + // Translatable labels for nav items and section headers (defaults to English) + LabelValueProps string `yaml:"label_value_props,omitempty" json:"label_value_props,omitempty"` + LabelFeatures string `yaml:"label_features,omitempty" json:"label_features,omitempty"` + LabelPricing string `yaml:"label_pricing,omitempty" json:"label_pricing,omitempty"` + LabelBlog string `yaml:"label_blog,omitempty" json:"label_blog,omitempty"` + LabelGallery string `yaml:"label_gallery,omitempty" json:"label_gallery,omitempty"` + LabelCompare string `yaml:"label_compare,omitempty" json:"label_compare,omitempty"` + LabelDocs string `yaml:"label_docs,omitempty" json:"label_docs,omitempty"` + LabelReleases string `yaml:"label_releases,omitempty" json:"label_releases,omitempty"` + LabelAPI string `yaml:"label_api,omitempty" json:"label_api,omitempty"` + LabelIssues string `yaml:"label_issues,omitempty" json:"label_issues,omitempty"` } // FooterConfig represents footer settings diff --git a/options/locale/locale_cs-CZ.json b/options/locale/locale_cs-CZ.json index 4f03b71813..a58ff8ebd2 100644 --- a/options/locale/locale_cs-CZ.json +++ b/options/locale/locale_cs-CZ.json @@ -4042,6 +4042,9 @@ "repo.settings.pages.translations": "P\u0159eklady", "repo.settings.pages.ai_translate": "AI p\u0159eklad", "repo.settings.pages.ai_translate_success": "P\u0159eklad byl \u00fasp\u011b\u0161n\u011b vygenerov\u00e1n AI. Zkontrolujte a upravte dle pot\u0159eby.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Smazat", "repo.settings.pages.save_translation": "Ulo\u017eit p\u0159eklad", "repo.settings.pages.translation_saved": "P\u0159eklad \u00fasp\u011b\u0161n\u011b ulo\u017een.", @@ -4390,4 +4393,4 @@ "actions.runners.waiting_jobs": "Čekající úlohy", "actions.runners.back_to_runners": "Zpět na runnery", "actions.runners.no_waiting_jobs": "Žádné úlohy nečekají na tento label" -} +} \ No newline at end of file diff --git a/options/locale/locale_de-DE.json b/options/locale/locale_de-DE.json index 107efc3850..37b33499cb 100644 --- a/options/locale/locale_de-DE.json +++ b/options/locale/locale_de-DE.json @@ -4248,6 +4248,9 @@ "repo.settings.pages.translations": "\u00dcbersetzungen", "repo.settings.pages.ai_translate": "KI-\u00dcbersetzung", "repo.settings.pages.ai_translate_success": "\u00dcbersetzung wurde erfolgreich von der KI generiert. \u00dcberpr\u00fcfen und bearbeiten Sie sie nach Bedarf.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "L\u00f6schen", "repo.settings.pages.save_translation": "\u00dcbersetzung speichern", "repo.settings.pages.translation_saved": "\u00dcbersetzung erfolgreich gespeichert.", @@ -4466,4 +4469,4 @@ "actions.runners.waiting_jobs": "Wartende Jobs", "actions.runners.back_to_runners": "Zurück zu Runners", "actions.runners.no_waiting_jobs": "Keine Jobs warten auf dieses Label" -} +} \ No newline at end of file diff --git a/options/locale/locale_el-GR.json b/options/locale/locale_el-GR.json index f19bc804bf..9a4cabb4a4 100644 --- a/options/locale/locale_el-GR.json +++ b/options/locale/locale_el-GR.json @@ -3735,6 +3735,9 @@ "repo.settings.pages.translations": "Μεταφράσεις", "repo.settings.pages.ai_translate": "Μετάφραση AI", "repo.settings.pages.ai_translate_success": "Η μετάφραση δημιουργήθηκε επιτυχώς από το AI. Ελέγξτε και επεξεργαστείτε όπως χρειάζεται.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Διαγραφή", "repo.settings.pages.save_translation": "Αποθήκευση μετάφρασης", "repo.settings.pages.translation_saved": "Η μετάφραση αποθηκεύτηκε επιτυχώς.", @@ -4083,4 +4086,4 @@ "actions.runners.waiting_jobs": "Αναμονή εργασιών", "actions.runners.back_to_runners": "Πίσω στους Runners", "actions.runners.no_waiting_jobs": "Δεν υπάρχουν εργασίες σε αναμονή για αυτή την ετικέτα" -} +} \ No newline at end of file diff --git a/options/locale/locale_en-US.json b/options/locale/locale_en-US.json index 766d3e6a87..1b2d574572 100644 --- a/options/locale/locale_en-US.json +++ b/options/locale/locale_en-US.json @@ -4584,6 +4584,9 @@ "repo.settings.pages.translations": "Translations", "repo.settings.pages.ai_translate": "AI Translate", "repo.settings.pages.ai_translate_success": "Translation has been generated successfully by AI. Review and edit as needed.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Delete", "repo.settings.pages.save_translation": "Save Translation", "repo.settings.pages.translation_saved": "Translation saved successfully.", diff --git a/options/locale/locale_es-ES.json b/options/locale/locale_es-ES.json index 808556308d..f7123b8131 100644 --- a/options/locale/locale_es-ES.json +++ b/options/locale/locale_es-ES.json @@ -3840,6 +3840,9 @@ "repo.settings.pages.translations": "Traducciones", "repo.settings.pages.ai_translate": "Traducir con IA", "repo.settings.pages.ai_translate_success": "La traducci\u00f3n se ha generado correctamente con IA. Rev\u00edsala y ed\u00edtala seg\u00fan sea necesario.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Eliminar", "repo.settings.pages.save_translation": "Guardar traducci\u00f3n", "repo.settings.pages.translation_saved": "Traducci\u00f3n guardada correctamente.", @@ -4058,4 +4061,4 @@ "actions.runners.waiting_jobs": "Trabajos en espera", "actions.runners.back_to_runners": "Volver a Runners", "actions.runners.no_waiting_jobs": "No hay trabajos esperando para esta etiqueta" -} +} \ No newline at end of file diff --git a/options/locale/locale_fa-IR.json b/options/locale/locale_fa-IR.json index 967789b996..cb710b22c2 100644 --- a/options/locale/locale_fa-IR.json +++ b/options/locale/locale_fa-IR.json @@ -2935,6 +2935,9 @@ "repo.settings.pages.translations": "ترجمه‌ها", "repo.settings.pages.ai_translate": "ترجمه هوش مصنوعی", "repo.settings.pages.ai_translate_success": "ترجمه با موفقیت توسط هوش مصنوعی تولید شد. در صورت نیاز بررسی و ویرایش کنید.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "حذف", "repo.settings.pages.save_translation": "ذخیره ترجمه", "repo.settings.pages.translation_saved": "ترجمه با موفقیت ذخیره شد.", @@ -3301,4 +3304,4 @@ "actions.runners.waiting_jobs": "کارهای در انتظار", "actions.runners.back_to_runners": "بازگشت به اجراکننده‌ها", "actions.runners.no_waiting_jobs": "هیچ کاری برای این برچسب در انتظار نیست" -} +} \ No newline at end of file diff --git a/options/locale/locale_fi-FI.json b/options/locale/locale_fi-FI.json index 581914ca76..96906d5e29 100644 --- a/options/locale/locale_fi-FI.json +++ b/options/locale/locale_fi-FI.json @@ -2233,6 +2233,9 @@ "repo.settings.pages.translations": "K\u00e4\u00e4nn\u00f6kset", "repo.settings.pages.ai_translate": "AI-k\u00e4\u00e4nn\u00f6s", "repo.settings.pages.ai_translate_success": "K\u00e4\u00e4nn\u00f6s on luotu onnistuneesti AI:n avulla. Tarkista ja muokkaa tarvittaessa.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Poista", "repo.settings.pages.save_translation": "Tallenna k\u00e4\u00e4nn\u00f6s", "repo.settings.pages.translation_saved": "K\u00e4\u00e4nn\u00f6s tallennettu onnistuneesti.", @@ -2581,4 +2584,4 @@ "actions.runners.waiting_jobs": "Odottavat työt", "actions.runners.back_to_runners": "Takaisin ajajiin", "actions.runners.no_waiting_jobs": "Ei odottavia töitä tälle tunnisteelle" -} +} \ No newline at end of file diff --git a/options/locale/locale_fr-FR.json b/options/locale/locale_fr-FR.json index d3f99a9156..7408c6b755 100644 --- a/options/locale/locale_fr-FR.json +++ b/options/locale/locale_fr-FR.json @@ -4186,6 +4186,9 @@ "repo.settings.pages.translations": "Traductions", "repo.settings.pages.ai_translate": "Traduction IA", "repo.settings.pages.ai_translate_success": "La traduction a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9e avec succ\u00e8s par l'IA. V\u00e9rifiez et modifiez si n\u00e9cessaire.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Supprimer", "repo.settings.pages.save_translation": "Enregistrer la traduction", "repo.settings.pages.translation_saved": "Traduction enregistr\u00e9e avec succ\u00e8s.", @@ -4404,4 +4407,4 @@ "actions.runners.waiting_jobs": "Tâches en attente", "actions.runners.back_to_runners": "Retour aux runners", "actions.runners.no_waiting_jobs": "Aucune tâche en attente pour ce label" -} +} \ No newline at end of file diff --git a/options/locale/locale_ga-IE.json b/options/locale/locale_ga-IE.json index 5e47135b56..a56463c1cb 100644 --- a/options/locale/locale_ga-IE.json +++ b/options/locale/locale_ga-IE.json @@ -4115,6 +4115,9 @@ "repo.settings.pages.translations": "Aistriúcháin", "repo.settings.pages.ai_translate": "Aistriúchán AI", "repo.settings.pages.ai_translate_success": "Ghin AI an t-aistriúchán go rathúil. Athbhreithnigh agus cuir in eagar de réir mar is gá.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Scrios", "repo.settings.pages.save_translation": "Sábháil aistriúchán", "repo.settings.pages.translation_saved": "Sábháladh an t-aistriúchán go rathúil.", @@ -4450,4 +4453,4 @@ "actions.runners.waiting_jobs": "Jabanna ag Fanacht", "actions.runners.back_to_runners": "Ar ais go Ritheoirí", "actions.runners.no_waiting_jobs": "Níl aon jabanna ag fanacht ar an lipéad seo" -} +} \ No newline at end of file diff --git a/options/locale/locale_hi-IN.json b/options/locale/locale_hi-IN.json index b66c28d431..e349fe9139 100644 --- a/options/locale/locale_hi-IN.json +++ b/options/locale/locale_hi-IN.json @@ -4021,6 +4021,9 @@ "repo.settings.pages.translations": "\u0905\u0928\u0941\u0935\u093e\u0926", "repo.settings.pages.ai_translate": "AI \u0905\u0928\u0941\u0935\u093e\u0926", "repo.settings.pages.ai_translate_success": "AI \u0926\u094d\u0935\u093e\u0930\u093e \u0905\u0928\u0941\u0935\u093e\u0926 \u0938\u092b\u0932\u0924\u093e\u092a\u0942\u0930\u094d\u0935\u0915 \u091c\u0928\u0930\u0947\u091f \u0915\u093f\u092f\u093e \u0917\u092f\u093e \u0939\u0948\u0964 \u0906\u0935\u0936\u094d\u092f\u0915\u0924\u093e\u0928\u0941\u0938\u093e\u0930 \u0938\u092e\u0940\u0915\u094d\u0937\u093e \u0915\u0930\u0947\u0902 \u0914\u0930 \u0938\u0902\u092a\u093e\u0926\u093f\u0924 \u0915\u0930\u0947\u0902\u0964", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "\u0939\u091f\u093e\u090f\u0901", "repo.settings.pages.save_translation": "\u0905\u0928\u0941\u0935\u093e\u0926 \u0938\u0939\u0947\u091c\u0947\u0902", "repo.settings.pages.translation_saved": "\u0905\u0928\u0941\u0935\u093e\u0926 \u0938\u092b\u0932\u0924\u093e\u092a\u0942\u0930\u094d\u0935\u0915 \u0938\u0939\u0947\u091c\u093e \u0917\u092f\u093e\u0964", @@ -4452,4 +4455,4 @@ "actions.runners.waiting_jobs": "प्रतीक्षारत कार्य", "actions.runners.back_to_runners": "रनर्स पर वापस जाएं", "actions.runners.no_waiting_jobs": "इस लेबल के लिए कोई कार्य प्रतीक्षा में नहीं है" -} +} \ No newline at end of file diff --git a/options/locale/locale_hu-HU.json b/options/locale/locale_hu-HU.json index 3b3e279797..4f31cdaa87 100644 --- a/options/locale/locale_hu-HU.json +++ b/options/locale/locale_hu-HU.json @@ -2150,6 +2150,9 @@ "repo.settings.pages.translations": "Ford\u00edt\u00e1sok", "repo.settings.pages.ai_translate": "AI ford\u00edt\u00e1s", "repo.settings.pages.ai_translate_success": "A ford\u00edt\u00e1st az AI sikeresen gener\u00e1lta. Tekintse \u00e1t \u00e9s szerkessze sz\u00fcks\u00e9g szerint.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "T\u00f6rl\u00e9s", "repo.settings.pages.save_translation": "Ford\u00edt\u00e1s ment\u00e9se", "repo.settings.pages.translation_saved": "Ford\u00edt\u00e1s sikeresen mentve.", @@ -2498,4 +2501,4 @@ "actions.runners.waiting_jobs": "Várakozó feladatok", "actions.runners.back_to_runners": "Vissza a futtatókhoz", "actions.runners.no_waiting_jobs": "Nincsenek várakozó feladatok ehhez a címkéhez" -} +} \ No newline at end of file diff --git a/options/locale/locale_id-ID.json b/options/locale/locale_id-ID.json index 57caf3c995..558245b868 100644 --- a/options/locale/locale_id-ID.json +++ b/options/locale/locale_id-ID.json @@ -1974,6 +1974,9 @@ "repo.settings.pages.translations": "Terjemahan", "repo.settings.pages.ai_translate": "Terjemahan AI", "repo.settings.pages.ai_translate_success": "Terjemahan telah berhasil dibuat oleh AI. Tinjau dan edit sesuai kebutuhan.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Hapus", "repo.settings.pages.save_translation": "Simpan terjemahan", "repo.settings.pages.translation_saved": "Terjemahan berhasil disimpan.", @@ -2309,4 +2312,4 @@ "actions.runners.waiting_jobs": "Pekerjaan Menunggu", "actions.runners.back_to_runners": "Kembali ke Runner", "actions.runners.no_waiting_jobs": "Tidak ada pekerjaan yang menunggu untuk label ini" -} +} \ No newline at end of file diff --git a/options/locale/locale_is-IS.json b/options/locale/locale_is-IS.json index b5abe813f3..20449a8c66 100644 --- a/options/locale/locale_is-IS.json +++ b/options/locale/locale_is-IS.json @@ -1862,6 +1862,9 @@ "repo.settings.pages.translations": "Þýðingar", "repo.settings.pages.ai_translate": "AI þýðing", "repo.settings.pages.ai_translate_success": "Þýðing hefur verið búin til af AI. Skoðaðu og breyttu eftir þörfum.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Eyða", "repo.settings.pages.save_translation": "Vista þýðingu", "repo.settings.pages.translation_saved": "Þýðing vistuð.", @@ -2197,4 +2200,4 @@ "actions.runners.waiting_jobs": "Bíðandi verk", "actions.runners.back_to_runners": "Til baka í keyrsluforrit", "actions.runners.no_waiting_jobs": "Engin verk bíða eftir þessu merki" -} +} \ No newline at end of file diff --git a/options/locale/locale_it-IT.json b/options/locale/locale_it-IT.json index 424c705f45..43659a7b38 100644 --- a/options/locale/locale_it-IT.json +++ b/options/locale/locale_it-IT.json @@ -3286,6 +3286,9 @@ "repo.settings.pages.translations": "Traduzioni", "repo.settings.pages.ai_translate": "Traduzione IA", "repo.settings.pages.ai_translate_success": "La traduzione \u00e8 stata generata con successo dall'IA. Rivedi e modifica secondo necessit\u00e0.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Elimina", "repo.settings.pages.save_translation": "Salva traduzione", "repo.settings.pages.translation_saved": "Traduzione salvata con successo.", @@ -3504,4 +3507,4 @@ "actions.runners.waiting_jobs": "Lavori in attesa", "actions.runners.back_to_runners": "Torna ai runner", "actions.runners.no_waiting_jobs": "Nessun lavoro in attesa per questa etichetta" -} +} \ No newline at end of file diff --git a/options/locale/locale_ja-JP.json b/options/locale/locale_ja-JP.json index 952b171f54..3224cb0bda 100644 --- a/options/locale/locale_ja-JP.json +++ b/options/locale/locale_ja-JP.json @@ -4230,6 +4230,9 @@ "repo.settings.pages.translations": "\u7ffb\u8a33", "repo.settings.pages.ai_translate": "AI\u7ffb\u8a33", "repo.settings.pages.ai_translate_success": "AI\u306b\u3088\u308b\u7ffb\u8a33\u304c\u6b63\u5e38\u306b\u751f\u6210\u3055\u308c\u307e\u3057\u305f\u3002\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u78ba\u8a8d\u30fb\u7de8\u96c6\u3057\u3066\u304f\u3060\u3055\u3044\u3002", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "\u524a\u9664", "repo.settings.pages.save_translation": "\u7ffb\u8a33\u3092\u4fdd\u5b58", "repo.settings.pages.translation_saved": "\u7ffb\u8a33\u304c\u6b63\u5e38\u306b\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f\u3002", @@ -4448,4 +4451,4 @@ "actions.runners.waiting_jobs": "待機中のジョブ", "actions.runners.back_to_runners": "ランナーに戻る", "actions.runners.no_waiting_jobs": "このラベルを待機しているジョブはありません" -} +} \ No newline at end of file diff --git a/options/locale/locale_ko-KR.json b/options/locale/locale_ko-KR.json index 9b3aa17267..7a45c30204 100644 --- a/options/locale/locale_ko-KR.json +++ b/options/locale/locale_ko-KR.json @@ -2245,6 +2245,9 @@ "repo.settings.pages.translations": "\ubc88\uc5ed", "repo.settings.pages.ai_translate": "AI \ubc88\uc5ed", "repo.settings.pages.ai_translate_success": "AI\uac00 \ubc88\uc5ed\uc744 \uc131\uacf5\uc801\uc73c\ub85c \uc0dd\uc131\ud588\uc2b5\ub2c8\ub2e4. \ud544\uc694\uc5d0 \ub530\ub77c \ud655\uc778\ud558\uace0 \ud3b8\uc9d1\ud558\uc138\uc694.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "\uc0ad\uc81c", "repo.settings.pages.save_translation": "\ubc88\uc5ed \uc800\uc7a5", "repo.settings.pages.translation_saved": "\ubc88\uc5ed\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc800\uc7a5\ub418\uc5c8\uc2b5\ub2c8\ub2e4.", @@ -2463,4 +2466,4 @@ "actions.runners.waiting_jobs": "대기 중인 작업", "actions.runners.back_to_runners": "러너로 돌아가기", "actions.runners.no_waiting_jobs": "이 레이블을 기다리는 작업이 없습니다" -} +} \ No newline at end of file diff --git a/options/locale/locale_lv-LV.json b/options/locale/locale_lv-LV.json index ce95b85cbb..5a25f44659 100644 --- a/options/locale/locale_lv-LV.json +++ b/options/locale/locale_lv-LV.json @@ -3756,6 +3756,9 @@ "repo.settings.pages.translations": "Tulkojumi", "repo.settings.pages.ai_translate": "AI tulkojums", "repo.settings.pages.ai_translate_success": "Tulkojums veiksmīgi ģenerēts ar AI. Pārskatiet un rediģējiet pēc nepieciešamības.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Dzēst", "repo.settings.pages.save_translation": "Saglabāt tulkojumu", "repo.settings.pages.translation_saved": "Tulkojums veiksmīgi saglabāts.", @@ -4091,4 +4094,4 @@ "actions.runners.waiting_jobs": "Gaidošie darbi", "actions.runners.back_to_runners": "Atpakaļ pie izpildītājiem", "actions.runners.no_waiting_jobs": "Nav darbu, kas gaida šo etiķeti" -} +} \ No newline at end of file diff --git a/options/locale/locale_nl-NL.json b/options/locale/locale_nl-NL.json index 09c94dac1c..99ab70dcf5 100644 --- a/options/locale/locale_nl-NL.json +++ b/options/locale/locale_nl-NL.json @@ -2904,6 +2904,9 @@ "repo.settings.pages.translations": "Vertalingen", "repo.settings.pages.ai_translate": "AI-vertaling", "repo.settings.pages.ai_translate_success": "Vertaling is succesvol gegenereerd door AI. Controleer en bewerk indien nodig.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Verwijderen", "repo.settings.pages.save_translation": "Vertaling opslaan", "repo.settings.pages.translation_saved": "Vertaling succesvol opgeslagen.", @@ -3252,4 +3255,4 @@ "actions.runners.waiting_jobs": "Wachtende taken", "actions.runners.back_to_runners": "Terug naar runners", "actions.runners.no_waiting_jobs": "Geen taken wachten op dit label" -} +} \ No newline at end of file diff --git a/options/locale/locale_pl-PL.json b/options/locale/locale_pl-PL.json index 98b86875a9..e4d970a93f 100644 --- a/options/locale/locale_pl-PL.json +++ b/options/locale/locale_pl-PL.json @@ -2875,6 +2875,9 @@ "repo.settings.pages.translations": "T\u0142umaczenia", "repo.settings.pages.ai_translate": "T\u0142umaczenie AI", "repo.settings.pages.ai_translate_success": "T\u0142umaczenie zosta\u0142o wygenerowane przez AI. Sprawd\u017a i edytuj w razie potrzeby.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Usu\u0144", "repo.settings.pages.save_translation": "Zapisz t\u0142umaczenie", "repo.settings.pages.translation_saved": "T\u0142umaczenie zapisane pomy\u015blnie.", @@ -3223,4 +3226,4 @@ "actions.runners.waiting_jobs": "Oczekujące zadania", "actions.runners.back_to_runners": "Powrót do runnerów", "actions.runners.no_waiting_jobs": "Brak zadań oczekujących na tę etykietę" -} +} \ No newline at end of file diff --git a/options/locale/locale_pt-BR.json b/options/locale/locale_pt-BR.json index 0aee9c0d08..783856655f 100644 --- a/options/locale/locale_pt-BR.json +++ b/options/locale/locale_pt-BR.json @@ -4028,6 +4028,9 @@ "repo.settings.pages.translations": "Tradu\u00e7\u00f5es", "repo.settings.pages.ai_translate": "Tradu\u00e7\u00e3o com IA", "repo.settings.pages.ai_translate_success": "A tradu\u00e7\u00e3o foi gerada com sucesso pela IA. Revise e edite conforme necess\u00e1rio.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Excluir", "repo.settings.pages.save_translation": "Salvar tradu\u00e7\u00e3o", "repo.settings.pages.translation_saved": "Tradu\u00e7\u00e3o salva com sucesso.", @@ -4245,4 +4248,4 @@ "actions.runners.waiting_jobs": "Trabalhos em espera", "actions.runners.back_to_runners": "Voltar para Runners", "actions.runners.no_waiting_jobs": "Nenhum trabalho aguardando para este rótulo" -} +} \ No newline at end of file diff --git a/options/locale/locale_pt-PT.json b/options/locale/locale_pt-PT.json index 0dee1ff1cb..534e58e807 100644 --- a/options/locale/locale_pt-PT.json +++ b/options/locale/locale_pt-PT.json @@ -4117,6 +4117,9 @@ "repo.settings.pages.translations": "Tradu\u00e7\u00f5es", "repo.settings.pages.ai_translate": "Tradu\u00e7\u00e3o com IA", "repo.settings.pages.ai_translate_success": "A tradu\u00e7\u00e3o foi gerada com sucesso pela IA. Reveja e edite conforme necess\u00e1rio.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Eliminar", "repo.settings.pages.save_translation": "Guardar tradu\u00e7\u00e3o", "repo.settings.pages.translation_saved": "Tradu\u00e7\u00e3o guardada com sucesso.", @@ -4464,4 +4467,4 @@ "actions.runners.waiting_jobs": "Trabalhos em espera", "actions.runners.back_to_runners": "Voltar aos Runners", "actions.runners.no_waiting_jobs": "Nenhum trabalho à espera para esta etiqueta" -} +} \ No newline at end of file diff --git a/options/locale/locale_ru-RU.json b/options/locale/locale_ru-RU.json index dea49db5c6..1d8a63e96f 100644 --- a/options/locale/locale_ru-RU.json +++ b/options/locale/locale_ru-RU.json @@ -3849,6 +3849,9 @@ "repo.settings.pages.translations": "\u041f\u0435\u0440\u0435\u0432\u043e\u0434\u044b", "repo.settings.pages.ai_translate": "\u0418\u0418-\u043f\u0435\u0440\u0435\u0432\u043e\u0434", "repo.settings.pages.ai_translate_success": "\u041f\u0435\u0440\u0435\u0432\u043e\u0434 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0418\u0418. \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0438 \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c", "repo.settings.pages.save_translation": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434", "repo.settings.pages.translation_saved": "\u041f\u0435\u0440\u0435\u0432\u043e\u0434 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d.", @@ -4054,4 +4057,4 @@ "actions.runners.waiting_jobs": "Ожидающие задачи", "actions.runners.back_to_runners": "Назад к раннерам", "actions.runners.no_waiting_jobs": "Нет задач, ожидающих эту метку" -} +} \ No newline at end of file diff --git a/options/locale/locale_si-LK.json b/options/locale/locale_si-LK.json index d676916d96..2d53711aa2 100644 --- a/options/locale/locale_si-LK.json +++ b/options/locale/locale_si-LK.json @@ -2921,6 +2921,9 @@ "repo.settings.pages.translations": "පරිවර්තන", "repo.settings.pages.ai_translate": "AI පරිවර්තනය", "repo.settings.pages.ai_translate_success": "AI විසින් පරිවර්තනය සාර්ථකව උත්පාදනය කරන ලදී. අවශ්‍ය පරිදි සමාලෝචනය කර සංස්කරණය කරන්න.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "මකන්න", "repo.settings.pages.save_translation": "පරිවර්තනය සුරකින්න", "repo.settings.pages.translation_saved": "පරිවර්තනය සාර්ථකව සුරැකිණි.", @@ -3256,4 +3259,4 @@ "actions.runners.waiting_jobs": "බලා සිටින කාර්යයන්", "actions.runners.back_to_runners": "ධාවකයන් වෙත ආපසු", "actions.runners.no_waiting_jobs": "මෙම ලේබලය සඳහා බලා සිටින කාර්යයන් නොමැත" -} +} \ No newline at end of file diff --git a/options/locale/locale_sk-SK.json b/options/locale/locale_sk-SK.json index 1c11da1c9a..88f18ef276 100644 --- a/options/locale/locale_sk-SK.json +++ b/options/locale/locale_sk-SK.json @@ -1947,6 +1947,9 @@ "repo.settings.pages.translations": "Preklady", "repo.settings.pages.ai_translate": "AI preklad", "repo.settings.pages.ai_translate_success": "Preklad bol \u00faspe\u0161ne vygenerovan\u00fd AI. Skontrolujte a upravte pod\u013ea potreby.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Odstr\u00e1ni\u0165", "repo.settings.pages.save_translation": "Ulo\u017ei\u0165 preklad", "repo.settings.pages.translation_saved": "Preklad \u00faspe\u0161ne ulo\u017een\u00fd.", @@ -2282,4 +2285,4 @@ "actions.runners.waiting_jobs": "Čakajúce úlohy", "actions.runners.back_to_runners": "Späť na bežcov", "actions.runners.no_waiting_jobs": "Žiadne úlohy nečakajú na tento štítok" -} +} \ No newline at end of file diff --git a/options/locale/locale_sv-SE.json b/options/locale/locale_sv-SE.json index 3b6400ee8d..f93da40b87 100644 --- a/options/locale/locale_sv-SE.json +++ b/options/locale/locale_sv-SE.json @@ -2505,6 +2505,9 @@ "repo.settings.pages.translations": "\u00d6vers\u00e4ttningar", "repo.settings.pages.ai_translate": "AI-\u00f6vers\u00e4ttning", "repo.settings.pages.ai_translate_success": "\u00d6vers\u00e4ttningen har genererats av AI. Granska och redigera vid behov.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Ta bort", "repo.settings.pages.save_translation": "Spara \u00f6vers\u00e4ttning", "repo.settings.pages.translation_saved": "\u00d6vers\u00e4ttningen har sparats.", @@ -2853,4 +2856,4 @@ "actions.runners.waiting_jobs": "Väntande jobb", "actions.runners.back_to_runners": "Tillbaka till runners", "actions.runners.no_waiting_jobs": "Inga jobb väntar på denna etikett" -} +} \ No newline at end of file diff --git a/options/locale/locale_tr-TR.json b/options/locale/locale_tr-TR.json index 2b08a578ec..3ef4ec0cd9 100644 --- a/options/locale/locale_tr-TR.json +++ b/options/locale/locale_tr-TR.json @@ -4114,6 +4114,9 @@ "repo.settings.pages.translations": "\u00c7eviriler", "repo.settings.pages.ai_translate": "AI \u00c7eviri", "repo.settings.pages.ai_translate_success": "\u00c7eviri AI taraf\u0131ndan ba\u015far\u0131yla olu\u015fturuldu. Gerekti\u011fi gibi inceleyin ve d\u00fczenleyin.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "Sil", "repo.settings.pages.save_translation": "\u00c7eviriyi kaydet", "repo.settings.pages.translation_saved": "\u00c7eviri ba\u015far\u0131yla kaydedildi.", @@ -4462,4 +4465,4 @@ "actions.runners.waiting_jobs": "Bekleyen İşler", "actions.runners.back_to_runners": "Çalıştırıcılara Dön", "actions.runners.no_waiting_jobs": "Bu etiket için bekleyen iş yok" -} +} \ No newline at end of file diff --git a/options/locale/locale_uk-UA.json b/options/locale/locale_uk-UA.json index 8a50ed2dda..f661d42ccd 100644 --- a/options/locale/locale_uk-UA.json +++ b/options/locale/locale_uk-UA.json @@ -3899,6 +3899,9 @@ "repo.settings.pages.translations": "\u041f\u0435\u0440\u0435\u043a\u043b\u0430\u0434\u0438", "repo.settings.pages.ai_translate": "\u0428\u0406-\u043f\u0435\u0440\u0435\u043a\u043b\u0430\u0434", "repo.settings.pages.ai_translate_success": "\u041f\u0435\u0440\u0435\u043a\u043b\u0430\u0434 \u0443\u0441\u043f\u0456\u0448\u043d\u043e \u0437\u0433\u0435\u043d\u0435\u0440\u043e\u0432\u0430\u043d\u043e \u0428\u0406. \u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0442\u0430 \u0432\u0456\u0434\u0440\u0435\u0434\u0430\u0433\u0443\u0439\u0442\u0435 \u0437\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438.", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438", "repo.settings.pages.save_translation": "\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u043f\u0435\u0440\u0435\u043a\u043b\u0430\u0434", "repo.settings.pages.translation_saved": "\u041f\u0435\u0440\u0435\u043a\u043b\u0430\u0434 \u0443\u0441\u043f\u0456\u0448\u043d\u043e \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043e.", @@ -4234,4 +4237,4 @@ "actions.runners.waiting_jobs": "Очікуючі завдання", "actions.runners.back_to_runners": "Назад до раннерів", "actions.runners.no_waiting_jobs": "Немає завдань, що очікують цю мітку" -} +} \ No newline at end of file diff --git a/options/locale/locale_zh-CN.json b/options/locale/locale_zh-CN.json index 556adf28d0..372a0ecd1f 100644 --- a/options/locale/locale_zh-CN.json +++ b/options/locale/locale_zh-CN.json @@ -4248,6 +4248,9 @@ "repo.settings.pages.translations": "\u7ffb\u8bd1", "repo.settings.pages.ai_translate": "AI\u7ffb\u8bd1", "repo.settings.pages.ai_translate_success": "AI\u5df2\u6210\u529f\u751f\u6210\u7ffb\u8bd1\u3002\u8bf7\u6839\u636e\u9700\u8981\u67e5\u770b\u548c\u7f16\u8f91\u3002", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "\u5220\u9664", "repo.settings.pages.save_translation": "\u4fdd\u5b58\u7ffb\u8bd1", "repo.settings.pages.translation_saved": "\u7ffb\u8bd1\u5df2\u6210\u529f\u4fdd\u5b58\u3002", @@ -4466,4 +4469,4 @@ "actions.runners.waiting_jobs": "等待中的任务", "actions.runners.back_to_runners": "返回运行器", "actions.runners.no_waiting_jobs": "没有等待此标签的任务" -} +} \ No newline at end of file diff --git a/options/locale/locale_zh-TW.json b/options/locale/locale_zh-TW.json index be536e151b..270eef054b 100644 --- a/options/locale/locale_zh-TW.json +++ b/options/locale/locale_zh-TW.json @@ -4156,6 +4156,9 @@ "repo.settings.pages.translations": "\u7ffb\u8b6f", "repo.settings.pages.ai_translate": "AI\u7ffb\u8b6f", "repo.settings.pages.ai_translate_success": "AI\u5df2\u6210\u529f\u7522\u751f\u7ffb\u8b6f\u3002\u8acb\u6839\u64da\u9700\u8981\u6aa2\u8996\u548c\u7de8\u8f2f\u3002", + "repo.settings.pages.ai_translate_all": "Translate All (AI)", + "repo.settings.pages.ai_translate_all_success": "Successfully translated %d languages.", + "repo.settings.pages.ai_translate_all_partial": "Translated %d of %d languages. %d failed.", "repo.settings.pages.delete_translation": "\u522a\u9664", "repo.settings.pages.save_translation": "\u5132\u5b58\u7ffb\u8b6f", "repo.settings.pages.translation_saved": "\u7ffb\u8b6f\u5df2\u6210\u529f\u5132\u5b58\u3002", @@ -4374,4 +4377,4 @@ "actions.runners.waiting_jobs": "等待中的工作", "actions.runners.back_to_runners": "返回執行器", "actions.runners.no_waiting_jobs": "沒有等待此標籤的工作" -} +} \ No newline at end of file diff --git a/routers/web/pages/pages.go b/routers/web/pages/pages.go index 8ac6dd1d01..6791be7a3e 100644 --- a/routers/web/pages/pages.go +++ b/routers/web/pages/pages.go @@ -1070,6 +1070,8 @@ func deepMergeConfig(base *pages_module.LandingConfig, overrideJSON string) (*pa } // deepMerge recursively merges src into dst. +// Maps are merged recursively; arrays are merged element-wise (preserving +// base fields like icons that the translation overlay may omit). func deepMerge(dst, src map[string]any) map[string]any { for key, srcVal := range src { if dstVal, ok := dst[key]; ok { @@ -1080,12 +1082,47 @@ func deepMerge(dst, src map[string]any) map[string]any { dst[key] = deepMerge(dstMap, srcMap) continue } + // Both are arrays: merge element-wise + srcArr, srcIsArr := srcVal.([]any) + dstArr, dstIsArr := dstVal.([]any) + if srcIsArr && dstIsArr { + dst[key] = deepMergeArrays(dstArr, srcArr) + continue + } } dst[key] = srcVal } return dst } +// deepMergeArrays merges two arrays element-wise. For each index, if both +// elements are maps, they are deep-merged (so translation fields override +// base fields while preserving untranslated fields like icons). Otherwise +// the source element replaces the base. +func deepMergeArrays(dst, src []any) []any { + result := make([]any, max(len(dst), len(src))) + for i := range result { + if i < len(src) && i < len(dst) { + srcMap, srcIsMap := src[i].(map[string]any) + dstMap, dstIsMap := dst[i].(map[string]any) + if srcIsMap && dstIsMap { + merged := make(map[string]any) + for k, v := range dstMap { + merged[k] = v + } + result[i] = deepMerge(merged, srcMap) + } else { + result[i] = src[i] + } + } else if i < len(src) { + result[i] = src[i] + } else { + result[i] = dst[i] + } + } + return result +} + // detectPageLanguage determines the active language for a landing page. // Priority: ?lang= query param > pages_lang cookie > Accept-Language header > default. func detectPageLanguage(ctx *context.Context, config *pages_module.LandingConfig) string { diff --git a/routers/web/repo/setting/pages.go b/routers/web/repo/setting/pages.go index 3685d99d7a..c0b72c819e 100644 --- a/routers/web/repo/setting/pages.go +++ b/routers/web/repo/setting/pages.go @@ -1305,6 +1305,57 @@ func PagesLanguagesPost(ctx *context.Context) { } } ctx.Flash.Success(ctx.Tr("repo.settings.pages.ai_translate_success")) + + case "ai_translate_all": + defaultLang := config.I18n.DefaultLang + if defaultLang == "" { + defaultLang = "en" + } + var successCount, failCount int + for _, lang := range config.I18n.Languages { + if lang == defaultLang { + continue + } + translated, err := pages_service.TranslateLandingPageContent(ctx, ctx.Repo.Repository, config, lang) + if err != nil { + log.Error("AI translation failed for %s: %v", lang, err) + failCount++ + continue + } + existing, err := pages_model.GetTranslation(ctx, ctx.Repo.Repository.ID, lang) + if err != nil { + log.Error("GetTranslation failed for %s: %v", lang, err) + failCount++ + continue + } + if existing != nil { + existing.ConfigJSON = translated + existing.AutoGenerated = true + if err := pages_model.UpdateTranslation(ctx, existing); err != nil { + log.Error("UpdateTranslation failed for %s: %v", lang, err) + failCount++ + continue + } + } else { + t := &pages_model.Translation{ + RepoID: ctx.Repo.Repository.ID, + Lang: lang, + ConfigJSON: translated, + AutoGenerated: true, + } + if err := pages_model.CreateTranslation(ctx, t); err != nil { + log.Error("CreateTranslation failed for %s: %v", lang, err) + failCount++ + continue + } + } + successCount++ + } + if failCount == 0 { + ctx.Flash.Success(ctx.Tr("repo.settings.pages.ai_translate_all_success", successCount)) + } else { + ctx.Flash.Warning(ctx.Tr("repo.settings.pages.ai_translate_all_partial", successCount, successCount+failCount, failCount)) + } } ctx.Redirect(ctx.Repo.Repository.Link() + "/settings/pages/languages") diff --git a/services/pages/generate.go b/services/pages/generate.go index 5f20fd620b..280e814df9 100644 --- a/services/pages/generate.go +++ b/services/pages/generate.go @@ -338,6 +338,26 @@ func buildTranslatableContent(config *pages_module.LandingConfig) string { } } + // Navigation labels (for translating nav items and section headers) + labelOrDefault := func(label, def string) string { + if label != "" { + return label + } + return def + } + content["navigation"] = map[string]any{ + "label_value_props": labelOrDefault(config.Navigation.LabelValueProps, "Value Props"), + "label_features": labelOrDefault(config.Navigation.LabelFeatures, "Features"), + "label_pricing": labelOrDefault(config.Navigation.LabelPricing, "Pricing"), + "label_blog": labelOrDefault(config.Navigation.LabelBlog, "Blog"), + "label_gallery": labelOrDefault(config.Navigation.LabelGallery, "Gallery"), + "label_compare": labelOrDefault(config.Navigation.LabelCompare, "Compare"), + "label_docs": labelOrDefault(config.Navigation.LabelDocs, "Docs"), + "label_releases": labelOrDefault(config.Navigation.LabelReleases, "Releases"), + "label_api": labelOrDefault(config.Navigation.LabelAPI, "API"), + "label_issues": labelOrDefault(config.Navigation.LabelIssues, "Issues"), + } + data, _ := json.Marshal(content) return string(data) } diff --git a/templates/pages/architecture-deep-dive.tmpl b/templates/pages/architecture-deep-dive.tmpl index 92fd5aec72..eb7e445149 100644 --- a/templates/pages/architecture-deep-dive.tmpl +++ b/templates/pages/architecture-deep-dive.tmpl @@ -1006,16 +1006,16 @@ {{range .Config.Footer.Links}} {{.Label}} {{end}} - {{if .Config.Navigation.ShowDocs}}Docs{{end}} - {{if .Config.Navigation.ShowAPI}}API{{end}} - {{if .Config.Navigation.ShowReleases}}Releases{{end}} - {{if .Config.Navigation.ShowIssues}}Issues{{end}} - {{if .Config.ValueProps}}Value Props{{end}} - {{if .Config.Features}}Features{{end}} - {{if .Config.Pricing.Plans}}Pricing{{end}} - {{if .Config.Blog.Enabled}}Blog{{end}} - {{if .Config.Gallery.Enabled}}Gallery{{end}} - {{if and .Config.Comparison.Enabled .Config.Comparison.HasData}}Compare{{end}} + {{if .Config.Navigation.ShowDocs}}{{if .Config.Navigation.LabelDocs}}{{.Config.Navigation.LabelDocs}}{{else}}Docs{{end}}{{end}} + {{if .Config.Navigation.ShowAPI}}{{if .Config.Navigation.LabelAPI}}{{.Config.Navigation.LabelAPI}}{{else}}API{{end}}{{end}} + {{if .Config.Navigation.ShowReleases}}{{if .Config.Navigation.LabelReleases}}{{.Config.Navigation.LabelReleases}}{{else}}Releases{{end}}{{end}} + {{if .Config.Navigation.ShowIssues}}{{if .Config.Navigation.LabelIssues}}{{.Config.Navigation.LabelIssues}}{{else}}Issues{{end}}{{end}} + {{if .Config.ValueProps}}{{if .Config.Navigation.LabelValueProps}}{{.Config.Navigation.LabelValueProps}}{{else}}Value Props{{end}}{{end}} + {{if .Config.Features}}{{if .Config.Navigation.LabelFeatures}}{{.Config.Navigation.LabelFeatures}}{{else}}Features{{end}}{{end}} + {{if .Config.Pricing.Plans}}{{if .Config.Navigation.LabelPricing}}{{.Config.Navigation.LabelPricing}}{{else}}Pricing{{end}}{{end}} + {{if .Config.Blog.Enabled}}{{if .Config.Navigation.LabelBlog}}{{.Config.Navigation.LabelBlog}}{{else}}Blog{{end}}{{end}} + {{if .Config.Gallery.Enabled}}{{if .Config.Navigation.LabelGallery}}{{.Config.Navigation.LabelGallery}}{{else}}Gallery{{end}}{{end}} + {{if and .Config.Comparison.Enabled .Config.Comparison.HasData}}{{if .Config.Navigation.LabelCompare}}{{.Config.Navigation.LabelCompare}}{{else}}Compare{{end}}{{end}} {{if .Config.Navigation.ShowRepository}} GitCaddy @@ -1071,7 +1071,7 @@
- +

{{if .Config.Blog.Headline}}{{.Config.Blog.Headline}}{{else}}All Posts{{end}}

{{if .Config.Blog.Subheadline}}

{{.Config.Blog.Subheadline}}

{{end}}
@@ -1275,7 +1275,7 @@
- +

{{if .Config.Brand.Name}}Why {{.Config.Brand.Name}}?{{else}}Why Choose Us{{end}}

Everything you need to get started quickly.

@@ -1299,7 +1299,7 @@
- +

Features

Powerful capabilities at your fingertips.

@@ -1360,7 +1360,7 @@
- +

{{if .Config.Pricing.Headline}}{{.Config.Pricing.Headline}}{{else}}Pricing{{end}}

{{if .Config.Pricing.Subheadline}}{{.Config.Pricing.Subheadline}}{{else}}Choose the plan that works for you{{end}}

@@ -1405,7 +1405,7 @@
- +

{{if .Config.Blog.Headline}}{{.Config.Blog.Headline}}{{else}}Latest Posts{{end}}

{{if .Config.Blog.Subheadline}}

{{.Config.Blog.Subheadline}}

{{end}}
@@ -1444,7 +1444,7 @@