diff --git a/.gitignore b/.gitignore index 2954a9f..3b87454 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ AGENTS.md # paraglide compiles the message runtime into the source tree /src/lib/paraglide /.inlang + +# Claude Code scratch: throwaway probe scripts, never committed +/.scratch diff --git a/badge.mjs b/badge.mjs deleted file mode 100644 index 2777c55..0000000 --- a/badge.mjs +++ /dev/null @@ -1,20 +0,0 @@ -import { chromium } from 'playwright'; -const browser = await chromium.launch(); -for (const [label, supporter] of [['plain', false], ['supporter', true]]) { - const ctx = await browser.newContext({ viewport: { width: 1280, height: 950 } }); - if (supporter) await ctx.addInitScript(() => localStorage.setItem('supporter_cache_v1', JSON.stringify({ valid: true, expires: null, checkedAt: 1785578719118 }))); - const page = await ctx.newPage(); - await page.goto('http://localhost:5186/en/weather/week/berlin/', { waitUntil: 'load', timeout: 120000 }); - await page.waitForTimeout(9000); - const btn = page.getByRole('button', { name: /Support Drizz|Supporter extras/ }).first(); - await btn.screenshot({ path: `/tmp/badge-${label}.png` }); - await ctx.close(); -} -// locked panel -const ctx = await browser.newContext({ viewport: { width: 1280, height: 950 } }); -const page = await ctx.newPage(); -await page.goto('http://localhost:5186/en/weather/seasonal/berlin/', { waitUntil: 'load', timeout: 120000 }); -await page.waitForTimeout(6000); -await page.locator('h2').first().locator('xpath=..').screenshot({ path: '/tmp/badge-panel.png' }).catch(() => {}); -console.log('ok'); -await browser.close(); diff --git a/messages/de.json b/messages/de.json index eb8dd0d..ac3f4f8 100644 --- a/messages/de.json +++ b/messages/de.json @@ -152,5 +152,56 @@ "calm_3": "Den ganzen Tag so gut wie windstill.", "uv_1": "UV-Index bis {value} ({label}) - mittags an Sonnenschutz denken.", "uv_2": "Mittags brennt die Sonne: UV {value}, {label}.", - "uv_3": "Mittags besser in den Schatten - der UV-Index erreicht {value} ({label})." + "uv_3": "Mittags besser in den Schatten - der UV-Index erreicht {value} ({label}).", + "legal_about": "Über uns", + "legal_imprint": "Impressum", + "legal_privacy": "Datenschutz", + "legal_terms": "Bedingungen", + "legal_nav": "Rechtliches", + "city_weather": "Wetter in {city}", + "var_temperature": "Temperatur", + "var_temperature_short": "Temp", + "var_icons": "Wettersymbole", + "var_icons_short": "Symbole", + "var_apparent": "Gefühlte Temp.", + "var_apparent_short": "Gefühlt", + "var_dew_point": "Taupunkt", + "var_dew_point_short": "Tau", + "var_cloud": "Bewölkung", + "var_cloud_short": "Wolken", + "var_cloud_low": "Bewölkung tief", + "var_cloud_low_short": "Tief", + "var_cloud_mid": "Bewölkung mittel", + "var_cloud_mid_short": "Mittel", + "var_cloud_high": "Bewölkung hoch", + "var_cloud_high_short": "Hoch", + "var_precipitation": "Niederschlag", + "var_precipitation_short": "Nied.", + "var_pop": "Niederschlagswahrsch.", + "var_pop_short": "Wahrsch.", + "var_rain": "Regen", + "var_rain_short": "Regen", + "var_showers": "Schauer", + "var_showers_short": "Schauer", + "var_snowfall": "Schneefall", + "var_snowfall_short": "Schnee", + "var_wind": "Windgeschwindigkeit", + "var_wind_short": "Wind", + "var_wind_dir": "Windrichtung", + "var_wind_dir_short": "Richt.", + "var_gusts": "Windböen", + "var_gusts_short": "Böen", + "var_humidity": "Luftfeuchte", + "var_humidity_short": "RF", + "var_pressure": "Luftdruck (MSL)", + "var_pressure_short": "MSLP", + "var_surface_pressure": "Bodendruck", + "var_surface_pressure_short": "Psfc", + "var_uv": "UV-Index", + "var_uv_short": "UV", + "var_visibility": "Sichtweite", + "var_visibility_short": "Sicht", + "var_cape": "CAPE", + "var_cape_short": "CAPE", + "var_time": "Zeit" } diff --git a/messages/en.json b/messages/en.json index 488bbb3..9d9bfe3 100644 --- a/messages/en.json +++ b/messages/en.json @@ -152,5 +152,56 @@ "calm_3": "Next to no wind all day.", "uv_1": "UV peaks at {value} ({label}), so cover up around midday.", "uv_2": "The sun bites around noon: UV {value}, {label}.", - "uv_3": "Worth some shade in the middle of the day - UV reaches {value} ({label})." + "uv_3": "Worth some shade in the middle of the day - UV reaches {value} ({label}).", + "legal_about": "About", + "legal_imprint": "Imprint", + "legal_privacy": "Privacy", + "legal_terms": "Terms", + "legal_nav": "Legal", + "city_weather": "{city} weather", + "var_temperature": "Temperature", + "var_temperature_short": "Temp", + "var_icons": "Weather icons", + "var_icons_short": "Icons", + "var_apparent": "Apparent Temp", + "var_apparent_short": "Feels", + "var_dew_point": "Dew Point", + "var_dew_point_short": "Dew", + "var_cloud": "Cloud Cover", + "var_cloud_short": "Cloud", + "var_cloud_low": "Cloud Cover Low", + "var_cloud_low_short": "Low", + "var_cloud_mid": "Cloud Cover Mid", + "var_cloud_mid_short": "Mid", + "var_cloud_high": "Cloud Cover High", + "var_cloud_high_short": "High", + "var_precipitation": "Precipitation", + "var_precipitation_short": "Precip", + "var_pop": "Precip. Probability", + "var_pop_short": "PoP", + "var_rain": "Rain", + "var_rain_short": "Rain", + "var_showers": "Showers", + "var_showers_short": "Shwr", + "var_snowfall": "Snowfall", + "var_snowfall_short": "Snow", + "var_wind": "Wind Speed", + "var_wind_short": "Wind", + "var_wind_dir": "Wind direction", + "var_wind_dir_short": "Dir", + "var_gusts": "Wind Gusts", + "var_gusts_short": "Gusts", + "var_humidity": "Humidity", + "var_humidity_short": "RH", + "var_pressure": "Pressure (MSL)", + "var_pressure_short": "MSLP", + "var_surface_pressure": "Surface Pressure", + "var_surface_pressure_short": "Psfc", + "var_uv": "UV Index", + "var_uv_short": "UV", + "var_visibility": "Visibility", + "var_visibility_short": "Vis", + "var_cape": "CAPE", + "var_cape_short": "CAPE", + "var_time": "Time" } diff --git a/messages/es.json b/messages/es.json index 3a8ff6d..0afb764 100644 --- a/messages/es.json +++ b/messages/es.json @@ -152,5 +152,56 @@ "calm_3": "Prácticamente sin viento en todo el día.", "uv_1": "El índice UV llega a {value} ({label}), así que protégete al mediodía.", "uv_2": "El sol aprieta al mediodía: UV {value}, {label}.", - "uv_3": "Conviene buscar sombra al mediodía: el UV alcanza {value} ({label})." + "uv_3": "Conviene buscar sombra al mediodía: el UV alcanza {value} ({label}).", + "legal_about": "Acerca de", + "legal_imprint": "Aviso legal", + "legal_privacy": "Privacidad", + "legal_terms": "Condiciones", + "legal_nav": "Legal", + "city_weather": "El tiempo en {city}", + "var_temperature": "Temperatura", + "var_temperature_short": "Temp", + "var_icons": "Iconos", + "var_icons_short": "Iconos", + "var_apparent": "Sensación térmica", + "var_apparent_short": "Sensación", + "var_dew_point": "Punto de rocío", + "var_dew_point_short": "Rocío", + "var_cloud": "Nubosidad", + "var_cloud_short": "Nubes", + "var_cloud_low": "Nubosidad baja", + "var_cloud_low_short": "Baja", + "var_cloud_mid": "Nubosidad media", + "var_cloud_mid_short": "Media", + "var_cloud_high": "Nubosidad alta", + "var_cloud_high_short": "Alta", + "var_precipitation": "Precipitación", + "var_precipitation_short": "Precip.", + "var_pop": "Prob. de precipitación", + "var_pop_short": "Prob.", + "var_rain": "Lluvia", + "var_rain_short": "Lluvia", + "var_showers": "Chubascos", + "var_showers_short": "Chub.", + "var_snowfall": "Nevadas", + "var_snowfall_short": "Nieve", + "var_wind": "Velocidad del viento", + "var_wind_short": "Viento", + "var_wind_dir": "Dirección del viento", + "var_wind_dir_short": "Dir.", + "var_gusts": "Rachas de viento", + "var_gusts_short": "Rachas", + "var_humidity": "Humedad", + "var_humidity_short": "HR", + "var_pressure": "Presión (MSL)", + "var_pressure_short": "MSLP", + "var_surface_pressure": "Presión en superficie", + "var_surface_pressure_short": "Psfc", + "var_uv": "Índice UV", + "var_uv_short": "UV", + "var_visibility": "Visibilidad", + "var_visibility_short": "Vis.", + "var_cape": "CAPE", + "var_cape_short": "CAPE", + "var_time": "Hora" } diff --git a/messages/fr.json b/messages/fr.json index 0e79b85..5d504a2 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -152,5 +152,56 @@ "calm_3": "Quasiment aucun vent de la journée.", "uv_1": "Indice UV jusqu'à {value} ({label}) : protégez-vous en milieu de journée.", "uv_2": "Le soleil tape à la mi-journée : UV {value}, {label}.", - "uv_3": "Mieux vaut chercher l'ombre à midi : l'UV atteint {value} ({label})." + "uv_3": "Mieux vaut chercher l'ombre à midi : l'UV atteint {value} ({label}).", + "legal_about": "À propos", + "legal_imprint": "Mentions légales", + "legal_privacy": "Confidentialité", + "legal_terms": "Conditions", + "legal_nav": "Informations légales", + "city_weather": "Météo à {city}", + "var_temperature": "Température", + "var_temperature_short": "Temp", + "var_icons": "Icônes météo", + "var_icons_short": "Icônes", + "var_apparent": "Ressenti", + "var_apparent_short": "Ressenti", + "var_dew_point": "Point de rosée", + "var_dew_point_short": "Rosée", + "var_cloud": "Nébulosité", + "var_cloud_short": "Nuages", + "var_cloud_low": "Nébulosité basse", + "var_cloud_low_short": "Basse", + "var_cloud_mid": "Nébulosité moyenne", + "var_cloud_mid_short": "Moyenne", + "var_cloud_high": "Nébulosité haute", + "var_cloud_high_short": "Haute", + "var_precipitation": "Précipitations", + "var_precipitation_short": "Précip.", + "var_pop": "Probabilité de précip.", + "var_pop_short": "Prob.", + "var_rain": "Pluie", + "var_rain_short": "Pluie", + "var_showers": "Averses", + "var_showers_short": "Averses", + "var_snowfall": "Chutes de neige", + "var_snowfall_short": "Neige", + "var_wind": "Vitesse du vent", + "var_wind_short": "Vent", + "var_wind_dir": "Direction du vent", + "var_wind_dir_short": "Dir.", + "var_gusts": "Rafales", + "var_gusts_short": "Rafales", + "var_humidity": "Humidité", + "var_humidity_short": "HR", + "var_pressure": "Pression (MSL)", + "var_pressure_short": "MSLP", + "var_surface_pressure": "Pression au sol", + "var_surface_pressure_short": "Psfc", + "var_uv": "Indice UV", + "var_uv_short": "UV", + "var_visibility": "Visibilité", + "var_visibility_short": "Vis.", + "var_cape": "CAPE", + "var_cape_short": "CAPE", + "var_time": "Heure" } diff --git a/messages/it.json b/messages/it.json index d36b1f0..1498c91 100644 --- a/messages/it.json +++ b/messages/it.json @@ -152,5 +152,56 @@ "calm_3": "Praticamente senza vento per tutto il giorno.", "uv_1": "Indice UV fino a {value} ({label}): proteggiti a metà giornata.", "uv_2": "Il sole picchia a mezzogiorno: UV {value}, {label}.", - "uv_3": "Meglio cercare ombra a metà giornata: l'UV arriva a {value} ({label})." + "uv_3": "Meglio cercare ombra a metà giornata: l'UV arriva a {value} ({label}).", + "legal_about": "Informazioni", + "legal_imprint": "Note legali", + "legal_privacy": "Privacy", + "legal_terms": "Condizioni", + "legal_nav": "Informazioni legali", + "city_weather": "Meteo a {city}", + "var_temperature": "Temperatura", + "var_temperature_short": "Temp", + "var_icons": "Icone meteo", + "var_icons_short": "Icone", + "var_apparent": "Percepita", + "var_apparent_short": "Percepita", + "var_dew_point": "Punto di rugiada", + "var_dew_point_short": "Rugiada", + "var_cloud": "Nuvolosità", + "var_cloud_short": "Nuvole", + "var_cloud_low": "Nuvolosità bassa", + "var_cloud_low_short": "Bassa", + "var_cloud_mid": "Nuvolosità media", + "var_cloud_mid_short": "Media", + "var_cloud_high": "Nuvolosità alta", + "var_cloud_high_short": "Alta", + "var_precipitation": "Precipitazioni", + "var_precipitation_short": "Precip.", + "var_pop": "Probabilità di precip.", + "var_pop_short": "Prob.", + "var_rain": "Pioggia", + "var_rain_short": "Pioggia", + "var_showers": "Rovesci", + "var_showers_short": "Rovesci", + "var_snowfall": "Nevicate", + "var_snowfall_short": "Neve", + "var_wind": "Velocità del vento", + "var_wind_short": "Vento", + "var_wind_dir": "Direzione del vento", + "var_wind_dir_short": "Dir.", + "var_gusts": "Raffiche", + "var_gusts_short": "Raffiche", + "var_humidity": "Umidità", + "var_humidity_short": "UR", + "var_pressure": "Pressione (MSL)", + "var_pressure_short": "MSLP", + "var_surface_pressure": "Pressione al suolo", + "var_surface_pressure_short": "Psfc", + "var_uv": "Indice UV", + "var_uv_short": "UV", + "var_visibility": "Visibilità", + "var_visibility_short": "Vis.", + "var_cape": "CAPE", + "var_cape_short": "CAPE", + "var_time": "Ora" } diff --git a/rowcheck.mjs b/rowcheck.mjs deleted file mode 100644 index 160b77d..0000000 --- a/rowcheck.mjs +++ /dev/null @@ -1,20 +0,0 @@ -import { chromium } from 'playwright'; -const browser = await chromium.launch(); -const out = {}; -for (const [label, vp, mobile] of [['mobile', { width: 390, height: 844 }, true], ['desktop', { width: 1280, height: 950 }, false]]) { - const ctx = await browser.newContext({ viewport: vp, isMobile: mobile, hasTouch: mobile }); - const page = await ctx.newPage(); - await page.goto('http://localhost:5186/en/weather/week/berlin/', { waitUntil: 'load', timeout: 120000 }); - await page.waitForTimeout(14000); - out[label] = await page.evaluate(() => ({ - rows: [...document.querySelectorAll('tr')].map((r) => ({ - label: r.querySelector('.hdr')?.textContent?.trim().replace(/\s+/g, ' ').slice(0, 10) || '-', - h: Math.round(r.getBoundingClientRect().height) - })), - tableHeight: Math.round(document.querySelector('table').getBoundingClientRect().height) - })); - await page.screenshot({ path: `/tmp/rows-${label}.png`, clip: { x: 0, y: 0, width: vp.width, height: Math.min(820, vp.height) } }); - await ctx.close(); -} -console.log(JSON.stringify(out, null, 1)); -await browser.close(); diff --git a/scroll.mjs b/scroll.mjs deleted file mode 100644 index 6c90a9c..0000000 --- a/scroll.mjs +++ /dev/null @@ -1,15 +0,0 @@ -import { chromium } from 'playwright'; -const browser = await chromium.launch(); -const page = await browser.newPage({ viewport: { width: 1280, height: 950 } }); -await page.goto('http://localhost:5186/en/weather/week/berlin/', { waitUntil: 'load', timeout: 120000 }); -await page.waitForTimeout(14000); - -// scroll right down to the footer and click a link there -await page.evaluate(() => { const m = document.querySelector('main'); m.scrollTop = m.scrollHeight; }); -await page.waitForTimeout(700); -const before = await page.evaluate(() => document.querySelector('main').scrollTop); -await page.locator('footer a[href*="/weather/14-day"]').first().click(); -await page.waitForTimeout(7000); -const after = await page.evaluate(() => document.querySelector('main').scrollTop); -console.log(JSON.stringify({ scrollBeforeClick: Math.round(before), scrollAfterNav: Math.round(after), url: page.url() })); -await browser.close(); diff --git a/src/lib/components/localized-content.svelte b/src/lib/components/localized-content.svelte new file mode 100644 index 0000000..9a65515 --- /dev/null +++ b/src/lib/components/localized-content.svelte @@ -0,0 +1,29 @@ + + + diff --git a/src/lib/components/navigation/footer.svelte b/src/lib/components/navigation/footer.svelte index c592d01..87609a2 100644 --- a/src/lib/components/navigation/footer.svelte +++ b/src/lib/components/navigation/footer.svelte @@ -89,7 +89,7 @@ {city.label} weather{m.city_weather({ city: city.label })} {/each} @@ -102,21 +102,21 @@ class="mt-10 flex flex-col items-start justify-between gap-3 border-t border-border/70 pt-5 text-xs text-muted-foreground sm:flex-row sm:items-center" > © {year} Drizz.li -