lgtm
This commit is contained in:
parent
982e0cc89c
commit
cfaf58dfba
44 changed files with 793 additions and 201 deletions
|
|
@ -16,7 +16,7 @@
|
|||
// present in en.ts > server so they can be translated.
|
||||
//
|
||||
// The script parses the TypeScript source with the compiler API and walks the
|
||||
// AST — no runtime import, no transpilation, no temp files. Run it with:
|
||||
// AST: no runtime import, no transpilation, no temp files. Run it with:
|
||||
// node frontend/scripts/check-translations.mjs
|
||||
|
||||
import { readFileSync, readdirSync } from 'fs';
|
||||
|
|
@ -106,7 +106,7 @@ function parseFile(path) {
|
|||
}
|
||||
|
||||
// Recursively turn a TS literal expression into a plain JS value.
|
||||
// Returns undefined for nodes we don't understand — callers must check.
|
||||
// Returns undefined for nodes we don't understand. Callers must check.
|
||||
function literalToJs(node) {
|
||||
if (!node) return undefined;
|
||||
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
|
||||
|
|
@ -217,7 +217,7 @@ function readServerFeatureNames() {
|
|||
// Names of the Enum/Numeric feature *configs* (each needs a description + detail
|
||||
// translation). We take the FIRST `name:` field after every Feature::Enum( /
|
||||
// Feature::Numeric( opening. This deliberately skips macro-generated configs
|
||||
// whose name is a `concat!(...)` expression (the crime rates — handled via
|
||||
// whose name is a `concat!(...)` expression (the crime rates, handled via
|
||||
// deriveLegacyCrimeKeys instead) and stops the lazy match from running past such
|
||||
// a config into an unrelated FeatureGroup `name:` (which previously made the
|
||||
// group name "Properties" look like a required feature).
|
||||
|
|
@ -302,7 +302,7 @@ function checkLeafConsistency(path, enValue, trValue, lang) {
|
|||
const got = tokenMultiset(trValue, re);
|
||||
if (!multisetsEqual(want, got)) {
|
||||
fail(
|
||||
`[${lang}] ${path}: ${label} mismatch — en=${JSON.stringify(want)} ` +
|
||||
`[${lang}] ${path}: ${label} mismatch, en=${JSON.stringify(want)} ` +
|
||||
`${lang}=${JSON.stringify(got)}`
|
||||
);
|
||||
}
|
||||
|
|
@ -425,7 +425,7 @@ function checkRecordCoverage(file, varName, supportedCodes, serverKeys, required
|
|||
// Every key here must also be a translatable feature name in en.ts > server,
|
||||
// or a legacy crime key that maps onto the per-window server keys (see
|
||||
// deriveLegacyCrimeKeys / legacyCrimeFeatureKey). Otherwise the description is
|
||||
// unreachable — ts() looks up server.${name}.
|
||||
// unreachable: ts() looks up server.${name}.
|
||||
for (const key of union) {
|
||||
if (!serverKeys.has(key) && !legacyCrimeKeys.has(key)) {
|
||||
fail(`${file}: key "${key}" has no matching entry in en.ts > server`);
|
||||
|
|
@ -532,7 +532,7 @@ function main() {
|
|||
console.error(`\n${errors.length} translation error(s).`);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(`i18n OK — ${supportedCodes.length} languages, ${warnings.length} warning(s).`);
|
||||
console.log(`i18n OK: ${supportedCodes.length} languages, ${warnings.length} warning(s).`);
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const ROUTES = [
|
|||
output: 'property-price-map/index.html',
|
||||
title: 'Property price map for England - Compare postcodes before viewing',
|
||||
description:
|
||||
'Compare sold prices, estimated current value, price per square metre and local context across English postcodes before searching listings.',
|
||||
'Compare sold prices, estimated current value, price per square metre and local context across English postcodes to find the underpriced ones.',
|
||||
},
|
||||
{
|
||||
path: '/postcode-property-search',
|
||||
|
|
@ -127,7 +127,7 @@ const FAQ_SCHEMA_ITEMS = [
|
|||
{
|
||||
question: 'Where should I look once the obvious areas are too expensive?',
|
||||
answer:
|
||||
'Set your budget, property type, floor area, commute, schools, crime, noise, broadband, parks, and other must-haves. The map removes postcodes that fail those tests, so overlooked areas can surface before you start searching listings.',
|
||||
'Set your budget, property type, floor area, commute, schools, crime, noise, broadband, parks, and other must-haves. The map ranks every postcode in England on those measures, so overlooked, underpriced areas (the cheaper twins of the names everyone knows) rise to the top.',
|
||||
},
|
||||
{
|
||||
question: 'What should I do when my search returns too many or too few areas?',
|
||||
|
|
@ -145,9 +145,9 @@ const FAQ_SCHEMA_ITEMS = [
|
|||
'The estimate starts with the last HM Land Registry sale price, adjusts it to current-market terms using repeat-sales modelling and fallback models, then blends that result with a nearest-neighbour estimate from nearby, recently sold, same-type homes.',
|
||||
},
|
||||
{
|
||||
question: 'Does Perfect Postcode replace Rightmove, Zoopla and OnTheMarket?',
|
||||
question: 'How is Perfect Postcode different from Rightmove, Zoopla and OnTheMarket?',
|
||||
answer:
|
||||
'No. Perfect Postcode helps you choose the right postcode from area data; the listing portals are still where you check live availability, photos, agent contact, viewings and alerts.',
|
||||
'Listing portals show you individual homes that are for sale right now. Perfect Postcode is where you decide which postcode to buy in, ranking every postcode in England on 200+ data fields the portals never compare, from £/sqm to crime, schools and commute.',
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue