Files
2026-08-28 11:43:34 -04:00

83 lines
3.0 KiB
Python

# Hardcoded string scanner for ObsiGate frontend JS files
# Finds user-visible strings that should be i18n'd but aren't.
# Also checks EN locale for French contamination.
#
# Usage:
# cd /c/dev/git/python/obsigate
# python3 << 'PYEOF' ... PYEOF
import re, os, json
js_dir = 'frontend/js'
# ── Part 1: Find hardcoded user-visible strings in JS ──
noise_patterns = [
r'\.css', r'data-', r'console\.', r'getElementById', r'querySelector',
r'\.json', r'/api/', r'CSS\.escape', r'encodeURI', r'font-size',
r'background:', r'padding:', r'border', r'SSE parse', r'\[Offline',
r'Failed to', r'Error ', r'Soft vault', r'\[Forge\]', r'CodeMirror',
r'\[PWA\]', r'\[SW\]', r'DragDrop', r'Dashboard:',
]
french_chars = re.compile(r'[àâäéèêëîïôöùûüçÀÂÄÉÈÊËÎÏÔÖÙÛÜÇ]')
ui_words = ['loading', 'error', 'search', 'save', 'delete', 'create',
'cancel', 'download', 'upload', 'share', 'copy', 'rename',
'open', 'close', 'file', 'folder', 'vault']
for fname in sorted(os.listdir(js_dir)):
if not fname.endswith('.js') or fname == 'i18n.js':
continue
fpath = os.path.join(js_dir, fname)
with open(fpath, 'r', encoding='utf-8') as f:
lines = f.readlines()
hardcoded = []
for i, line in enumerate(lines, 1):
strings = re.findall(r"'([^']+)'|\"([^\"]+)\"|`([^`]+)`", line)
for s_tuple in strings:
s = s_tuple[0] or s_tuple[1] or s_tuple[2]
if len(s) < 4: continue
if not re.search(r'[A-Za-zÀ-ÿ]', s): continue
if any(re.search(p, s) for p in noise_patterns): continue
if s.startswith('#') or s.startswith('.') or s.startswith('http'): continue
context = ''.join(lines[max(0,i-2):i+1])
if 't(' in context or 'data-i18n' in context or 'tr(' in context:
continue
has_fr = bool(french_chars.search(s))
is_ui = has_fr or any(w in s.lower() for w in ui_words)
if is_ui:
hardcoded.append((i, s.strip()[:120]))
if hardcoded:
print(f"\n=== {fname} ({len(hardcoded)}) ===")
for ln, s in hardcoded:
print(f" L{ln}: {s}")
# ── Part 2: Check EN locale for French contamination ──
with open('frontend/locales/fr.json', encoding='utf-8') as f:
fr = json.load(f)
with open('frontend/locales/en.json', encoding='utf-8') as f:
en = json.load(f)
print(f"\n=== Locale alignment: FR={len(fr)} EN={len(en)} ===")
only_fr = set(fr.keys()) - set(en.keys())
only_en = set(en.keys()) - set(fr.keys())
if only_fr: print(f"Keys in FR only: {sorted(only_fr)}")
if only_en: print(f"Keys in EN only: {sorted(only_en)}")
# EN values with French chars
fr_in_en = []
for k in sorted(fr.keys()):
if k in en and isinstance(en[k], str):
if french_chars.search(en[k]):
fr_in_en.append(k)
if fr_in_en:
print(f"\n=== EN keys with French text ({len(fr_in_en)}) ===")
for k in fr_in_en:
if not k.startswith('auto.') and not k.startswith('help.desc_'):
print(f" {k}: {en[k][:80]}")