feat(l10n): een poort die vertaalsleutels aanwijst die niemand meer opvraagt #1516
No reviewers
Labels
No labels
accepted
bug
declined
docs
duplicate
enhancement
good first issue
in-progress
needs-info
privacy
security
triage
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
LibreKAT/Ocideck!1516
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/l10n-wezenpoort"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Sluit #1512.
Waarom
Bij het opruimen van de weesgeraakte sleutel
Snijtekens(#1505) bleek een ruwe grep 249 kandidaten te geven. Dat getal was onbruikbaar: sleutels die via een variabele of generator worden opgehaald zien er in zo'n scan uit als wees terwijl ze het niet zijn. Elke wees kost wél 31 vertalingen aan onderhoud.Hoe de controle bewijst dat een sleutel gebruikt wordt
tool/check_l10n_orphans.dart, Flutter-vrij (dart:io+package:analyzer), ~20 s.De sleutelvoorraad komt via de AST uit de drie tabellen in
en.dart(3.522 sleutels). Bewijs van gebruik in twee lagen: eerst elke Dart-stringliteral inlib/,test/,tool/— AST-gemeten, dus inclusief aaneengeschakelde literals en de tekstdelen van interpolaties, wat doorgeefluiken (EditorField(label: 'Titel')) en registerregels (labelKey: 'applicationLanguage') meepakt. Alleen over wat dán nog overblijft de dure tekstlaag overassets/enweb/.Die tweede laag bleek nodig: er is een derde ophaalweg die niemand op papier had staan —
AppLocalizations.sourceFor(lang, labelNl)in de canvas-/matrix-/tree-/flow-specs, gevoed uitassets/improvement/templates/. "Bedreigingen" staat in geen enkele Dart-literal en is wél in gebruik.Wat bewust géén bewijs is
docs/, README en CHANGELOG (proza beschrijft de app — twee van de drie handmatig bevestigde wezen staan in de CHANGELOG en zouden anders wegvallen), de*_l10n_spec.json-bestanden (die hébben de sleutel gemaakt), de vertaaltabellen zelf, en de poort plus haar eigen test. Dat laatste is geen theorie:settingsLogoverdween uit de bevindingen zodra hij in een commentaarzin van de poort stond.Uitkomst: 181 wezen van 3.522
4 in
_stringsEn(t-sleutels), 48 en 129 in de twee Nederlandse tabellen. Grote clusters: ~22 OpenKAT-rapportbeschrijvingen, ~18 opslagteksten, 11 "(ontwerp)"-moduletegels, de teksten van het geschrapteactions-slidetype (#417), en herschreven zinnen waarvan de oude versie bleef staan. Steekproef van tien: allemaal echt wees.181 is een ondergrens, geen telling: een sleutel die als deeltekst van een andere string voorkomt wordt niet gemeld. De poort mag zwijgen over een wees, maar mag nooit iemand op zoektocht sturen naar een sleutel die wél gebruikt wordt.
In
check-full, met een ratchetHet bewijs is tekstueel, geen typecontrole: de poort weet dat een sleutel ergens vóórkomt, niet dat hij wordt uitgevoerd. Zo'n oordeel hoort niet in de poort die élke commit tegenhoudt. Wat wél tanden heeft is
orphanBaseline = 181— mag dalen, nooit stijgen — plus opname inmake ratchets.Getoetst in twee richtingen
test/l10n_orphan_check_test.dart(13 tests): vijf bouwen een mini-repo met een sleutel die wél gebruikt wordt (viad(),t(), een doorgeefluik, een aaneengeschakelde literal, een asset-label) en eisen nul bevindingen; vier planten een wees en eisen alarm, ook als alleen documentatie of alleen een spec-bestand hem noemt. Vier meten op de echte boom. Zonder die tweede richting commit je een poort die stilzwijgend niets doet — dat is hier eerder bijna gebeurd.Opruimen van de 181 is bewust een volgende stap.
Poorten
make checkgroen.make check-secretsgroen,make sastgroen (0 findings).De vertaalpoorten van deze repo keken maar één kant op. `make l10n-check` en `test/app_localizations_test.dart` bewaken dat elke GEBRUIKTE sleutel in alle 32 talen bestaat; of een sleutel nog wordt opgehaald vroeg niets. Elke wees kost 32 regels onderhoud voor tekst die geen mens ooit ziet. Waarom AST en niet een grep. Een ruwe grep gaf 249 kandidaten, waarvan een groot deel ruis: een zin die in de bron over twee regels aaneengeschakeld staat is één sleutel in de tabel maar staat nergens als één stuk tekst, en escapes lopen uit elkaar. De literals komen daarom uit de AST, net als in check_hardcoded_text. Waarom er ook tekstueel gezocht wordt. Naast d() en t() bestaat een derde ophaalweg: `AppLocalizations.sourceFor(lang, labelNl)`, waar de verbetermodule de labels van haar sjablonen doorheen haalt. Die labels komen uit gegevens (assets/improvement/templates/, improvement_templates_floor.g.dart) en staan in geen enkele Dart-literal. "Bedreigingen" is zo in gebruik zonder ergens als literal voor te komen. De tweede regel — komt de sleutel als tekst voor in lib/, test/, tool/, assets/ of web/ — vangt die weg, en meteen alles wat via een generator wordt samengesteld. Grof, en met opzet: hij levert valse negatieven op ("treffer(s)" zit in "meer treffer(s)") en dat is de goede kant om te falen. Deze poort mag zwijgen over een wees; ze mag nooit iemand op zoektocht sturen naar een sleutel die wél gebruikt wordt. Wat níet als bewijs telt: documentatie (proza beschrijft de app, het roept geen sleutel op — twee van de drie met de hand bevestigde wezen staan in de CHANGELOG), de l10n-specs die de sleutel juist gemáákt hebben, de vertaaltabellen zelf, en de poort en haar test: die noemen sleutels bij naam en wasten daarmee hun eigen bevindingen weg tot dat opviel. De test toetst twee richtingen. Nul bevindingen op een sleutel die wél gebruikt wordt (langs vijf routes), en alarm op een geplante wees — met tabel en regelnummer, en ook wanneer alleen documentatie, alleen een l10n-spec of alleen de andere taaltabellen hem noemen. Zonder die tweede richting is een poort die stilvalt altijd groen. Daarnaast één meting op de echte boom, zodat de drie met de hand bevestigde wezen vastliggen.