From f07570d8eedb09d53c4f2ec089dbef547b858e3f Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Wed, 2 Jul 2025 17:11:02 +0200 Subject: [PATCH] Weather done --- lib/Models/weatherData.dart | 217 ++++++++++ .../Sections/Weather/weather_page.dart | 382 ++++++++++++++++++ lib/Screens/section_page.dart | 6 +- lib/translations.dart | 120 +++++- 4 files changed, 714 insertions(+), 11 deletions(-) create mode 100644 lib/Models/weatherData.dart create mode 100644 lib/Screens/Sections/Weather/weather_page.dart diff --git a/lib/Models/weatherData.dart b/lib/Models/weatherData.dart new file mode 100644 index 0000000..dc112ab --- /dev/null +++ b/lib/Models/weatherData.dart @@ -0,0 +1,217 @@ +class WeatherData { + String? cod; + int? message; + int? cnt; + List? list; + City? city; + + WeatherData({this.cod, this.message, this.cnt, this.list, this.city}); + + factory WeatherData.fromJson(Map json) { + return WeatherData( + cod: json['cod'], + message: json['message'], + cnt: json['cnt'], + list: (json['list'] as List?)?.map((item) => WeatherForecast.fromJson(item)).toList(), + city: json['city'] != null ? City.fromJson(json['city']) : null, + ); + } +} + +class WeatherForecast { + int? dt; + MainWeatherData? main; + List? weather; + Clouds? clouds; + Wind? wind; + int? visibility; + dynamic pop; + Rain? rain; + Sys? sys; + String? dtTxt; + + WeatherForecast({ + this.dt, + this.main, + this.weather, + this.clouds, + this.wind, + this.visibility, + this.pop, + this.rain, + this.sys, + this.dtTxt, + }); + + factory WeatherForecast.fromJson(Map json) { + return WeatherForecast( + dt: json['dt'], + main: json['main'] != null ? MainWeatherData.fromJson(json['main']) : null, + weather: (json['weather'] as List?)?.map((item) => Weather.fromJson(item)).toList(), + clouds: json['clouds'] != null ? Clouds.fromJson(json['clouds']) : null, + wind: json['wind'] != null ? Wind.fromJson(json['wind']) : null, + visibility: json['visibility'], + pop: json['pop'], + rain: json['rain'] != null ? Rain.fromJson(json['rain']) : null, + sys: json['sys'] != null ? Sys.fromJson(json['sys']) : null, + dtTxt: json['dt_txt'], + ); + } +} + +class MainWeatherData { + double? temp; + double? feelsLike; + double? tempMin; + double? tempMax; + int? pressure; + int? seaLevel; + int? grndLevel; + int? humidity; + double? tempKf; + + MainWeatherData({ + this.temp, + this.feelsLike, + this.tempMin, + this.tempMax, + this.pressure, + this.seaLevel, + this.grndLevel, + this.humidity, + this.tempKf, + }); + + factory MainWeatherData.fromJson(Map json) { + return MainWeatherData( + temp: json['temp']?.toDouble(), + feelsLike: json['feels_like']?.toDouble(), + tempMin: json['temp_min']?.toDouble(), + tempMax: json['temp_max']?.toDouble(), + pressure: json['pressure'], + seaLevel: json['sea_level'], + grndLevel: json['grnd_level'], + humidity: json['humidity'], + tempKf: json['temp_kf']?.toDouble(), + ); + } +} + +class Weather { + int? id; + String? main; + String? description; + String? icon; + + Weather({this.id, this.main, this.description, this.icon}); + + factory Weather.fromJson(Map json) { + return Weather( + id: json['id'], + main: json['main'], + description: json['description'], + icon: json['icon'], + ); + } +} + +class Clouds { + int? all; + + Clouds({this.all}); + + factory Clouds.fromJson(Map json) { + return Clouds( + all: json['all'], + ); + } +} + +class Wind { + double? speed; + int? deg; + double? gust; + + Wind({this.speed, this.deg, this.gust}); + + factory Wind.fromJson(Map json) { + return Wind( + speed: json['speed']?.toDouble(), + deg: json['deg'], + gust: json['gust']?.toDouble(), + ); + } +} + +class Rain { + double? h3; + + Rain({this.h3}); + + factory Rain.fromJson(Map json) { + return Rain( + h3: json['3h']?.toDouble(), + ); + } +} + +class Sys { + String? pod; + + Sys({this.pod}); + + factory Sys.fromJson(Map json) { + return Sys( + pod: json['pod'], + ); + } +} + +class City { + int? id; + String? name; + Coord? coord; + String? country; + int? population; + int? timezone; + int? sunrise; + int? sunset; + + City({ + this.id, + this.name, + this.coord, + this.country, + this.population, + this.timezone, + this.sunrise, + this.sunset, + }); + + factory City.fromJson(Map json) { + return City( + id: json['id'], + name: json['name'], + coord: json['coord'] != null ? Coord.fromJson(json['coord']) : null, + country: json['country'], + population: json['population'], + timezone: json['timezone'], + sunrise: json['sunrise'], + sunset: json['sunset'], + ); + } +} + +class Coord { + double? lat; + double? lon; + + Coord({this.lat, this.lon}); + + factory Coord.fromJson(Map json) { + return Coord( + lat: json['lat']?.toDouble(), + lon: json['lon']?.toDouble(), + ); + } +} diff --git a/lib/Screens/Sections/Weather/weather_page.dart b/lib/Screens/Sections/Weather/weather_page.dart new file mode 100644 index 0000000..435c0bd --- /dev/null +++ b/lib/Screens/Sections/Weather/weather_page.dart @@ -0,0 +1,382 @@ +import 'dart:convert'; + +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:manager_api_new/api.dart'; +import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; +import 'package:mymuseum_visitapp/Models/visitContext.dart'; +import 'package:mymuseum_visitapp/Models/weatherData.dart'; +import 'package:mymuseum_visitapp/app_context.dart'; +import 'package:mymuseum_visitapp/constants.dart'; +import 'package:provider/provider.dart'; +import 'package:intl/intl.dart'; + +class WeatherPage extends StatefulWidget { + final WeatherDTO section; + WeatherPage({required this.section}); + + @override + State createState() => _WeatherPageState(); +} + +class _WeatherPageState extends State { + WeatherDTO weatherDTO = WeatherDTO(); + WeatherData? weatherData = null; + int nbrNextHours = 5; + + @override + void initState() { + /*print(widget.section!.data); + weatherDTO = WeatherDTO.fromJson(jsonDecode(widget.section!.data!))!; + print(weatherDTO);*/ + weatherDTO = widget.section; + if(weatherDTO.result != null) { + Map weatherResultInJson = jsonDecode(weatherDTO.result!); + weatherData = WeatherData.fromJson(weatherResultInJson); + } + + super.initState(); + } + + String formatTimestamp(int timestamp, AppContext appContext, bool isHourOnly, bool isDateOnly) { + + DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000); + + // Determine the date format based on the application language + String dateFormat = appContext.getContext().language.toString().toUpperCase() == "EN" ? + 'MM/dd/yyyy HH:mm' + : 'dd/MM/yyyy HH:mm'; + + if(isHourOnly) { + dateFormat = 'HH:mm'; + } + + if(isDateOnly) { + dateFormat = dateFormat.replaceAll('/yyyy HH:mm', ''); + } + + String formattedDate = DateFormat(dateFormat).format(dateTime); + + return formattedDate; + } + + String getTranslatedDayOfWeek(int timestamp, AppContext appContext, bool isDate) { + DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000); + + String dayToPrint = ""; + + print("dateTime.weekday"); + print(dateTime.weekday); + + switch(dateTime.weekday) { + case 1: + dayToPrint = TranslationHelper.getFromLocale("monday", appContext.getContext()); + break; + case 2: + dayToPrint = TranslationHelper.getFromLocale("tuesday", appContext.getContext()); + break; + case 3: + dayToPrint = TranslationHelper.getFromLocale("wednesday", appContext.getContext()); + break; + case 4: + dayToPrint = TranslationHelper.getFromLocale("thursday", appContext.getContext()); + break; + case 5: + dayToPrint = TranslationHelper.getFromLocale("friday", appContext.getContext()); + break; + case 6: + dayToPrint = TranslationHelper.getFromLocale("saturday", appContext.getContext()); + break; + case 7: + dayToPrint = TranslationHelper.getFromLocale("sunday", appContext.getContext()); + break; + } + + return isDate ? "${dayToPrint} ${formatTimestamp(timestamp, appContext, false, true)}" : dayToPrint; + } + + List getNextFiveDaysForecast(List allForecasts) { + List nextFiveDaysForecast = []; + DateTime today = DateTime.now(); + + List nextDay1All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 1))).day).toList(); + List nextDay2All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 2))).day).toList(); + List nextDay3All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 3))).day).toList(); + List nextDay4All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 4))).day).toList(); + List nextDay5All = allForecasts.where((af) => (DateTime.fromMillisecondsSinceEpoch(af.dt! * 1000)).day == (today.add(Duration(days: 5))).day).toList(); + + var nextDay1MiddayTest = nextDay1All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; + if(nextDay1All.isNotEmpty) { + WeatherForecast nextDay1AllSummary = nextDay1MiddayTest ?? nextDay1All.last; + nextFiveDaysForecast.add(nextDay1AllSummary); + } + + var nextDay2MiddayTest = nextDay2All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; + if(nextDay2All.isNotEmpty) { + WeatherForecast nextDay2Midday = nextDay2MiddayTest ?? nextDay2All.last; + nextFiveDaysForecast.add(nextDay2Midday); + } + + var nextDay3MiddayTest = nextDay3All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; + if(nextDay3All.isNotEmpty) { + WeatherForecast nextDay3Midday = nextDay3MiddayTest ?? nextDay3All.last; + nextFiveDaysForecast.add(nextDay3Midday); + } + + var nextDay4MiddayTest = nextDay4All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; + if(nextDay4All.isNotEmpty) { + WeatherForecast nextDay4Midday = nextDay4MiddayTest ?? nextDay4All.last; + nextFiveDaysForecast.add(nextDay4Midday); + } + + var nextDay5MiddayTest = nextDay5All.where((nd) => (DateTime.fromMillisecondsSinceEpoch(nd.dt! * 1000)).hour == 12).firstOrNull; + if(nextDay5All.isNotEmpty) { + WeatherForecast nextDay5Midday = nextDay5MiddayTest ?? nextDay5All.last; + nextFiveDaysForecast.add(nextDay5Midday); + } + + return nextFiveDaysForecast; + } + + @override + Widget build(BuildContext context) { + Size size = MediaQuery.of(context).size; + final appContext = Provider.of(context); + VisitAppContext visitAppContext = appContext.getContext(); + + var primaryColor = visitAppContext.configuration != null ? visitAppContext.configuration!.primaryColor != null ? Color(int.parse(visitAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)) : kSecondColor : kSecondColor; + + return Stack( + children: [ + weatherData == null ? const Center(child: Text("Aucune donnée à afficher")) : Container( // TODO translate ? + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), + gradient: LinearGradient( + begin: Alignment.topRight, + end: Alignment.bottomLeft, + stops: const [ + 0.2, + 0.5, + 0.9, + 0.95 + ], + colors: [ + Colors.blue[50]!, + Colors.blue[100]!, + Colors.blue[200]!, + Colors.blue[300]! + ] + ) + ), + //color: Colors.yellow, + //height: 300, + //width: 300, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(10.0), + child: Center(child: Text(weatherDTO.city!, style: const TextStyle(fontSize: kSectionTitleDetailSize, fontWeight: FontWeight.w500, color: Colors.black54, fontFamily: "Roboto"))), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text("${weatherData!.list!.first.main!.temp!.round().toString()}°", style: const TextStyle(fontSize: 55.0, fontWeight: FontWeight.w400, color: Colors.black54, fontFamily: "Roboto")), + ), + Container( + //color: Colors.green, + height: size.height * 0.2, + width: size.width * 0.45, + constraints: BoxConstraints(minWidth: 80), + child: Center( + child: CachedNetworkImage(imageUrl: "https://openweathermap.org/img/wn/${weatherData!.list!.first.weather!.first.icon!}@4x.png") + ) + ), + Container( + // color: Colors.green, + width: size.width * 0.2, + //color: Colors.red, + constraints: BoxConstraints(minWidth: 100), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + const Icon(Icons.water_drop_outlined, color: kSecondColor), + Text("${weatherData!.list!.first.pop!.round().toString()}%", style: const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w400, color: Colors.black54, fontFamily: "Roboto")), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + const Icon(Icons.air, color: kSecondColor), + Text("${(weatherData!.list!.first.wind!.speed! * 3.6).toStringAsFixed(1)}km/h", style: const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w400, color: Colors.black54, fontFamily: "Roboto")), + ], + ), + ), + ], + ), + ), + ]), + Container( + height: size.height * 0.25, + width: size.width, + /*decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), + //color: Colors.grey, + ),*/ + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(left: 15, bottom: 10), + child: Align(alignment: Alignment.centerLeft, child: Text(TranslationHelper.getFromLocale("weather.hourly", appContext.getContext()), style: const TextStyle(fontSize: 22, fontWeight: FontWeight.w400, color: Colors.black54, fontFamily: "Roboto"))), + ), + Container( + height: size.height * 0.18, + width: size.width, + //color: Colors.lightGreen, + child: ListView( + scrollDirection: Axis.horizontal, + children: List.generate( + nbrNextHours, + (index) { + final weatherForecast = weatherData!.list!.sublist(1)[index]; + return Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + height: size.height * 0.15, + width: size.width * 0.25, + constraints: const BoxConstraints(minWidth: 125, maxWidth: 250), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), + color: Colors.lightBlueAccent, + boxShadow: [ + BoxShadow( + color: kBackgroundGrey.withValues(alpha: 0.6), + spreadRadius: 0.75, + blurRadius: 3.1, + offset: Offset(0, 2.5), // changes position of shadow + ), + ], + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(formatTimestamp(weatherForecast.dt!, appContext, true, false), style: const TextStyle(fontSize: 12.0, fontWeight: FontWeight.w400, color: Colors.white, fontFamily: "Roboto")), + Center(child: CachedNetworkImage(imageUrl: "https://openweathermap.org/img/wn/${weatherForecast.weather!.first.icon!}.png")), + Text('${weatherForecast.main!.temp!.round().toString()}°', style: const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w600, color: Colors.white, fontFamily: "Roboto")), + ], + ), + ), + ); + }, + ), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(0.0), + child: Container( + height: size.height * 0.3, + width: size.width, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), + //color: Colors.amber, + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Align(alignment: Alignment.centerLeft, child: Text(TranslationHelper.getFromLocale("weather.nextdays", appContext.getContext()), style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w400, color: Colors.black54, fontFamily: "Roboto"))), + ), + Container( + height: size.height * 0.23, + width: size.width, + //color: Colors.lightGreen, + child: ListView( + scrollDirection: Axis.horizontal, + children:List.generate( + getNextFiveDaysForecast(weatherData!.list!).length, // nbrNextHours + (index) { + final weatherForecastNextDay = getNextFiveDaysForecast(weatherData!.list!)[index]; + return Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + height: size.height * 0.22, + width: size.width * 0.125, + constraints: const BoxConstraints(minWidth: 150, maxWidth: 250), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), + color: Colors.lightBlue, + boxShadow: [ + BoxShadow( + color: kBackgroundGrey.withValues(alpha: 0.5), + spreadRadius: 0.75, + blurRadius: 3.1, + offset: const Offset(0, 2.5), // changes position of shadow + ), + ], + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Center(child: CachedNetworkImage(imageUrl: "https://openweathermap.org/img/wn/${weatherForecastNextDay.weather!.first.icon!}@2x.png")), + Text('${weatherForecastNextDay.main!.temp!.round().toString()}°', style: const TextStyle(fontSize: 25.0, fontWeight: FontWeight.w600, color: Colors.white, fontFamily: "Roboto")), + Text(getTranslatedDayOfWeek(weatherForecastNextDay.dt!, appContext, true), style: const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w400, color: Colors.white, fontFamily: "Roboto")), + ], + ), + ), + ); + }, + ), + ), + ), + ], + ), + ), + ) + ], + ), + ), + Positioned( + top: 35, + left: 10, + child: SizedBox( + width: 50, + height: 50, + child: InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + decoration: BoxDecoration( + color: primaryColor, + shape: BoxShape.circle, + ), + child: const Icon(Icons.arrow_back, size: 23, color: Colors.white) + ), + ) + ), + ), + ], + ); + } +} + +//_webView \ No newline at end of file diff --git a/lib/Screens/section_page.dart b/lib/Screens/section_page.dart index bd83f6f..05eb390 100644 --- a/lib/Screens/section_page.dart +++ b/lib/Screens/section_page.dart @@ -22,6 +22,7 @@ import 'package:mymuseum_visitapp/Screens/Sections/Puzzle/puzzle_page.dart'; import 'package:mymuseum_visitapp/Screens/Sections/Quiz/quizz_page.dart'; import 'package:mymuseum_visitapp/Screens/Sections/Slider/slider_page.dart'; import 'package:mymuseum_visitapp/Screens/Sections/Video/video_page.dart'; +import 'package:mymuseum_visitapp/Screens/Sections/Weather/weather_page.dart'; import 'package:mymuseum_visitapp/Screens/Sections/Web/web_page.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/client.dart'; @@ -76,7 +77,7 @@ class _SectionPageState extends State { return Scaffold( key: _scaffoldKey, resizeToAvoidBottomInset: false, - appBar: test!.type == SectionType.Menu || test.type == SectionType.Agenda || test.type == SectionType.Weather ? CustomAppBar( + appBar: test!.type == SectionType.Menu || test.type == SectionType.Agenda ? CustomAppBar( title: sectionDTO != null ? TranslationHelper.get(sectionDTO!.title, visitAppContext) : "", isHomeButton: false, ) : null, @@ -118,6 +119,9 @@ class _SectionPageState extends State { value: mapContext, child: MapPage(section: mapDTO, icons: icons ?? []), ); + case SectionType.Weather: + WeatherDTO weatherDTO = WeatherDTO.fromJson(sectionResult)!; + return WeatherPage(section: weatherDTO); default: return const Center(child: Text("Unsupported type")); } diff --git a/lib/translations.dart b/lib/translations.dart index 4b0a4e8..6407246 100644 --- a/lib/translations.dart +++ b/lib/translations.dart @@ -25,7 +25,17 @@ List translations = [ "restart": "Recommencer", "downloadInProgress": "Téléchargement en cours", "downloadFinish": "Téléchargement terminé", - "upToDate": "Tout est à jour" + "upToDate": "Tout est à jour", + "weather.hourly": "Prochaines heures", + "weather.nextdays": "Prochains jours", + "agenda.all": "Tout", + "monday": "Lundi", + "tuesday": "Mardi", + "wednesday": "Mercredi", + "thursday": "Jeudi", + "friday": "Vendredi", + "saturday": "Samedi", + "sunday": "Dimanche" }), Translation(language: "EN", data: { "visitTitle": "List of tours", @@ -51,7 +61,17 @@ List translations = [ "restart": "Restart", "downloadInProgress": "Download in progress", "downloadFinish": "Download complete", - "upToDate": "Up to date" + "upToDate": "Up to date", + "weather.hourly": "Hourly", + "weather.nextdays": "Next days", + "agenda.all": "All", + "monday": "Monday", + "tuesday": "Tuesday", + "wednesday": "Wednesday", + "thursday": "Thursday", + "friday": "Friday", + "saturday": "Saturday", + "sunday": "Sunday" }), Translation(language: "DE", data: { "visitTitle": "Liste der Touren", @@ -77,7 +97,17 @@ List translations = [ "restart": "Neu starten", "downloadInProgress": "Download läuft", "downloadFinish": "Download abgeschlossen", - "upToDate": "Alles ist auf dem neuesten Stand" + "upToDate": "Alles ist auf dem neuesten Stand", + "weather.hourly": "Nächste Stunden", + "weather.nextdays": "Nächsten Tage", + "agenda.all": "Alle", + "monday": "Montag", + "tuesday": "Dienstag", + "wednesday": "Mittwoch", + "thursday": "Donnerstag", + "friday": "Freitag", + "saturday": "Samstag", + "sunday": "Sonntag" }), Translation(language: "NL", data: { "visitTitle": "Lijst met rondleidingen", @@ -103,7 +133,17 @@ List translations = [ "restart": "Herstarten", "downloadInProgress": "Download bezig", "downloadFinish": "Download voltooid", - "upToDate": "Alles is up-to-date" + "upToDate": "Alles is up-to-date", + "weather.hourly": "Volgende uren", + "weather.nextdays": "Volgende dagen", + "agenda.all": "Alle", + "monday": "Maandag", + "tuesday": "Dinsdag", + "wednesday": "Woensdag", + "thursday": "Donderdag", + "friday": "Vrijdag", + "saturday": "Zaterdag", + "sunday": "Zondag" }), Translation(language: "IT", data: { "visitTitle": "Elenco dei tour", @@ -129,7 +169,17 @@ List translations = [ "restart": "Ricomincia", "downloadInProgress": "Download in corso", "downloadFinish": "Download completato", - "upToDate": "Tutto è aggiornato" + "upToDate": "Tutto è aggiornato", + "weather.hourly": "Le prossime ore", + "weather.nextdays": "Prossimi giorni", + "agenda.all": "Tutto", + "monday": "Lunedì", + "tuesday": "Martedì", + "wednesday": "Mercoledì", + "thursday": "Giovedì", + "friday": "Venerdì", + "saturday": "Sabato", + "sunday": "Domenica" }), Translation(language: "ES", data: { "visitTitle": "Lista de recorridos", @@ -155,7 +205,17 @@ List translations = [ "restart": "Reanudar", "downloadInProgress": "Descarga en curso", "downloadFinish": "Descarga completada", - "upToDate": "Todo está al día" + "upToDate": "Todo está al día", + "weather.hourly": "Próximas horas", + "weather.nextdays": "Proximos dias", + "agenda.all": "Todo", + "monday": "Lunes", + "tuesday": "Martes", + "wednesday": "Miércoles", + "thursday": "Jueves", + "friday": "Viernes", + "saturday": "Sábado", + "sunday": "Domingo" }), Translation(language: "PL", data: { "visitTitle": "Lista wycieczek", @@ -181,7 +241,17 @@ List translations = [ "restart": "Uruchom ponownie", "downloadInProgress": "Pobieranie w toku", "downloadFinish": "Pobieranie zakończone", - "upToDate": "Wszystko jest aktualne" + "upToDate": "Wszystko jest aktualne", + "weather.hourly": "Następne godziny", + "weather.nextdays": "Następne dni", + "agenda.all": "Wszystko", + "monday": "Poniedziałek", + "tuesday": "Wtorek", + "wednesday": "Środa", + "thursday": "Czwartek", + "friday": "Piątek", + "saturday": "Sobota", + "sunday": "Niedziela" }), Translation(language: "CN", data: { "visitTitle": "旅游清单", @@ -207,7 +277,17 @@ List translations = [ "restart": "重新开始", "downloadInProgress": "下载中", "downloadFinish": "下载完成", - "upToDate": "已是最新" + "upToDate": "已是最新", + "weather.hourly": "接下来的几个小时", + "weather.nextdays": "未来几天", + "agenda.all": "全部", + "monday": "星期一", + "tuesday": "星期二", + "wednesday": "星期三", + "thursday": "星期四", + "friday": "星期五", + "saturday": "星期六", + "sunday": "星期日" }), Translation(language: "UK", data: { "visitTitle": "Список турів", @@ -233,7 +313,17 @@ List translations = [ "restart": "Перезапустіть", "downloadInProgress": "Завантаження триває", "downloadFinish": "Завантаження завершено", - "upToDate": "Все актуально" + "upToDate": "Все актуально", + "weather.hourly": "Наступні години", + "weather.nextdays": "Наступні дні", + "agenda.all": "все", + "monday": "Понеділок", + "tuesday": "Вівторок", + "wednesday": "Середа", + "thursday": "Четвер", + "friday": "П'ятниця", + "saturday": "Субота", + "sunday": "Неділя" }), Translation(language: "AR", data: { "visitTitle": "قائمة الجولات", @@ -259,6 +349,16 @@ List translations = [ "restart": "إعادة تشغيل", "downloadInProgress": "جارٍ التنزيل", "downloadFinish": "اكتمل التنزيل", - "upToDate": "كل شيء محدث" + "upToDate": "كل شيء محدث", + "weather.hourly": "الساعات القادمة", + "weather.nextdays": "الايام القادمة", + "agenda.all": "الجميع", + "monday": "الإثنين", + "tuesday": "الثلاثاء", + "wednesday": "الأربعاء", + "thursday": "الخميس", + "friday": "الجمعة", + "saturday": "السبت", + "sunday": "الأحد" }), ]; \ No newline at end of file