diff --git a/fsutils/translation_prune_orphans.py b/fsutils/translation_prune_orphans.py
new file mode 100644
index 0000000000..48bb2d5d82
--- /dev/null
+++ b/fsutils/translation_prune_orphans.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python3
+
+from __future__ import annotations
+
+import argparse
+from pathlib import Path
+
+REPO = Path(__file__).resolve().parent.parent
+SKINS_ROOT = REPO / "indra/newview/skins"
+
+
+def relative_files(base: Path) -> set[str]:
+ if not base.is_dir():
+ return set()
+ return {
+ path.relative_to(base).as_posix()
+ for path in base.rglob("*")
+ if path.is_file()
+ }
+
+
+def prune_skin(skin_dir: Path, *, delete: bool) -> int:
+ en_dir = skin_dir / "xui" / "en"
+ if not en_dir.is_dir():
+ return 0
+
+ en_files = relative_files(en_dir)
+ removed = 0
+ xui = skin_dir / "xui"
+
+ for locale_dir in sorted(xui.iterdir()):
+ if not locale_dir.is_dir() or locale_dir.name == "en":
+ continue
+
+ for path in sorted(locale_dir.rglob("*")):
+ if not path.is_file():
+ continue
+ rel = path.relative_to(locale_dir).as_posix()
+ if rel in en_files:
+ continue
+
+ print(f"{'delete' if delete else 'would delete'}: {skin_dir.name}/xui/{locale_dir.name}/{rel}")
+ if delete:
+ path.unlink()
+ removed += 1
+
+ if delete:
+ for path in sorted(locale_dir.rglob("*"), reverse=True):
+ if path.is_dir() and not any(path.iterdir()):
+ path.rmdir()
+
+ return removed
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(
+ description="Delete translation files not present in each skin's xui/en/ folder.",
+ )
+ parser.add_argument(
+ "--delete",
+ action="store_true",
+ help="Actually delete files (default is dry run).",
+ )
+ parser.add_argument(
+ "--skin",
+ action="append",
+ metavar="NAME",
+ help="Only process named skin(s); repeatable.",
+ )
+ args = parser.parse_args()
+
+ wanted = set(args.skin) if args.skin else None
+ total = 0
+
+ for skin_dir in sorted(SKINS_ROOT.iterdir()):
+ if not skin_dir.is_dir():
+ continue
+ if wanted and skin_dir.name not in wanted:
+ continue
+ total += prune_skin(skin_dir, delete=args.delete)
+
+ mode = "deleted" if args.delete else "would delete"
+ print(f"\n{total} file(s) {mode}")
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/indra/newview/skins/default/xui/az/floater_post_process.xml b/indra/newview/skins/default/xui/az/floater_post_process.xml
deleted file mode 100644
index 6dd6617336..0000000000
--- a/indra/newview/skins/default/xui/az/floater_post_process.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
-
-
- Işıqlılıq
-
-
- Doyulma
-
-
- Kontrast
-
-
- Kontrastın əsas rəngi
-
-
-
-
-
-
-
-
-
- Işığın qüvvət dərəcəsi
-
-
- Pozulma ölçüsü
-
-
- Pozulma gücü
-
-
-
-
-
- Işığın şiddəti
-
-
- Şəfəqin ölçüsü
-
-
- Şəfəqin gücü
-
-
-
-
-
-
-
-
-
-
diff --git a/indra/newview/skins/default/xui/az/floater_sound_devices.xml b/indra/newview/skins/default/xui/az/floater_sound_devices.xml
deleted file mode 100644
index 7a0d00fb40..0000000000
--- a/indra/newview/skins/default/xui/az/floater_sound_devices.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- Səsli söhbət
-
-
diff --git a/indra/newview/skins/default/xui/az/floater_voice_effect.xml b/indra/newview/skins/default/xui/az/floater_voice_effect.xml
deleted file mode 100644
index 1dae5983d3..0000000000
--- a/indra/newview/skins/default/xui/az/floater_voice_effect.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-
-
-
- (Səs dəyişimi yoxdur)
-
-
- (Aktiv)
-
-
- (Abunə yoxdur)
-
-
- (Yeni!)
-
-
- Aerna
-
-
- Beast
-
-
- Buff
-
-
- Buzz
-
-
- Camille
-
-
- Creepy
-
-
- CreepyBot
-
-
- Cyber
-
-
- DeepBot
-
-
- Demon
-
-
- Pəri
-
-
- Flirty
-
-
- Foxy
-
-
- Hellouin_2010_bonus
-
-
- Helium
-
-
- Husky
-
-
- Boğuq pıçıltı
-
-
- Daxili şəbəkə
-
-
- Julia
-
-
- Tərənnüm
-
-
- Macho
-
-
- Micro
-
-
- Mini
-
-
- Model
-
-
- Nano
-
-
- Nightmare
-
-
- PopBot
-
-
- Rachel
-
-
- Radio
-
-
- Robot
-
-
- Roxanne
-
-
- Bozarma
-
-
- Sabrina
-
-
- Samantha
-
-
- Sexy
-
-
- Shorty
-
-
- Az
-
-
- Sneaky
-
-
- Stallion
-
-
- Sultry
-
-
- Thunder
-
-
- Vixen
-
-
- WhinyBot
-
-
- Dinləmək
-
-
- Nümunəni yazın, sonra səsin necə səslənəcəyini eşitmək üçün basın.
-
-
-
-
- [[URL] Abunə ol]
-
-
-
-
-
-
diff --git a/indra/newview/skins/default/xui/az/panel_login_first.xml b/indra/newview/skins/default/xui/az/panel_login_first.xml
deleted file mode 100644
index 80d54d6d12..0000000000
--- a/indra/newview/skins/default/xui/az/panel_login_first.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
- Qeydiyyat
-
-
- Şifrəni unutdunuz
-
-
-
-
-
diff --git a/indra/newview/skins/default/xui/pt/floater_post_process.xml b/indra/newview/skins/default/xui/pt/floater_post_process.xml
deleted file mode 100644
index 382491c632..0000000000
--- a/indra/newview/skins/default/xui/pt/floater_post_process.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
- Brilho
-
-
- Saturação
-
-
- Contraste
-
-
- Cor base do contraste
-
-
-
-
-
-
-
-
-
- Multiplicador de amplificação de luz
-
-
- Tamanho do ruído
-
-
- Intensidade do ruído
-
-
-
-
-
- Extração de luminosidade
-
-
- Tamanho do bloom
-
-
- Intensidade do bloom
-
-
-
-
-
-
-
-
-
diff --git a/indra/newview/skins/default/xui/pt/floater_sound_devices.xml b/indra/newview/skins/default/xui/pt/floater_sound_devices.xml
deleted file mode 100644
index 52228a9ae7..0000000000
--- a/indra/newview/skins/default/xui/pt/floater_sound_devices.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
- Chat por voz
-
-
-
diff --git a/indra/newview/skins/default/xui/pt/floater_voice_effect.xml b/indra/newview/skins/default/xui/pt/floater_voice_effect.xml
deleted file mode 100644
index 4bedf24dd0..0000000000
--- a/indra/newview/skins/default/xui/pt/floater_voice_effect.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-
-
-
- (Sem modulação de voz)
-
-
- (Ativo)
-
-
- (não assinado)
-
-
- (Novo!)
-
-
- Arena
-
-
- Besta
-
-
- Musculoso
-
-
- Buzz
-
-
- Camille
-
-
- Assustador
-
-
- Bot assustador
-
-
- Cyber
-
-
- Bot grave
-
-
- Demônio
-
-
- Elfa
-
-
- Sedutor
-
-
- Sensual
-
-
- Bonus_Halloween_2010
-
-
- Hélio
-
-
- Rouco
-
-
- Sussurro rouco
-
-
- Interfone
-
-
- Julia
-
-
- Canto suave
-
-
- Macho
-
-
- Micro
-
-
- Pequeno
-
-
- Modelo
-
-
- Nano
-
-
- Pesadelo
-
-
- PopBot
-
-
- Rachel
-
-
- Rádio
-
-
- Robô
-
-
- Roxanne
-
-
- Tremor
-
-
- Sabrina
-
-
- Samantha
-
-
- Sexy
-
-
- Shorty
-
-
- Menor
-
-
- Sorrateiro
-
-
- Garanhão
-
-
- Sedutor
-
-
- Trovão
-
-
- Sedutora
-
-
- Bot reclamador
-
-
- Para pré-visualizar
-
-
- Grave um exemplo e clique em um efeito para aplicá-lo à sua voz.
-
-
-
-
- [[URL] Assinar agora]
-
-
-
-
-
-
diff --git a/indra/newview/skins/default/xui/pt/panel_login_first.xml b/indra/newview/skins/default/xui/pt/panel_login_first.xml
deleted file mode 100644
index 862c986300..0000000000
--- a/indra/newview/skins/default/xui/pt/panel_login_first.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
- https://accounts.secondlife.com/forgot_password/?lang=pt-BR
-
-
- https://join.secondlife.com/?lang=pt-BR
-
-
-
-
-
-
-
-
-
-
- Esqueceu a senha
-
-
- Cadastre-se
-
-
-
-
-
-
-
-
- Seu primeiro passo é na Learning Island. Procure o portal!
-
-
- Depois, explore a Social Island e conheça outros residentes!
-
-
-
-
-
-
diff --git a/indra/newview/skins/default/xui/pt/panel_voice_effect.xml b/indra/newview/skins/default/xui/pt/panel_voice_effect.xml
deleted file mode 100644
index c7074a0564..0000000000
--- a/indra/newview/skins/default/xui/pt/panel_voice_effect.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- Voice Morph desativado
-
-
- Experimentar Voice Morph ▶
-
-
- Assinar Voice Morph ▶
-
-
-
-
-
diff --git a/indra/newview/skins/default/xui/zh/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/zh/floater_texture_fetch_debugger.xml
deleted file mode 100644
index f657ab0dd8..0000000000
--- a/indra/newview/skins/default/xui/zh/floater_texture_fetch_debugger.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-
-
-
- 1. 已取得紋理總數:[NUM]
-
-
- 2. 總取得請求數:[NUM]
-
-
- 3. 快取總讀取數:[NUM]
-
-
- 4. 可見紋理總數:[NUM]
-
-
- 5. 可見紋理取得總請求數:[NUM]
-
-
- 6. 總取得資料量:[SIZE1] KB,解碼資料量:[SIZE2] KB,[PIXEL] 百萬畫素
-
-
- 7. 可見資料總量:[SIZE1] KB,解碼資料量:[SIZE2] KB
-
-
- 8. 總彩現資料量:[SIZE1] KB,解碼資料量:[SIZE2] KB,[PIXEL] 百萬畫素
-
-
- 9. 快取讀取總時間:[TIME] 秒
-
-
- 10. 快取寫入總時間:[TIME] 秒
-
-
- 11. 解碼總時間:[TIME] 秒
-
-
- 12. 建立 gl 紋理總時間:[TIME] 秒
-
-
- 13. HTTP 取得總時間:[TIME] 秒
-
-
- 14. 所有取得操作總時間:[TIME] 秒
-
-
- 15. 自快取重新取得可見紋理,時間:[TIME] 秒,取得量:[SIZE] KB,[PIXEL] 百萬畫素
-
-
- 16. 從快取重新取得所有紋理,時間:[TIME] 秒,取得量:[SIZE] KB,[PIXEL] 百萬畫素
-
-
- 17. 自 HTTP 重新取得可見紋理,時間:[TIME] 秒,取得量:[SIZE] KB,[PIXEL] 百萬畫素
-
-
- 18. 自 HTTP 重新取得所有紋理,時間:[TIME] 秒,取得量:[SIZE] KB,[PIXEL] 百萬畫素
-
-
-
- 20. 紋理來源:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file