diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml index 793d3d56..1aac6143 100644 --- a/.github/workflows/android-release.yml +++ b/.github/workflows/android-release.yml @@ -25,7 +25,7 @@ jobs: uses: subosito/flutter-action@v1 with: channel: 'stable' - flutter-version: '2.10.x' + flutter-version: '3.0.x' - name: Decrypt config files run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83d28538..dfcb1c10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: uses: subosito/flutter-action@v1 with: channel: 'stable' - flutter-version: '2.10.x' + flutter-version: '3.0.x' - run: dart --version - run: flutter --version diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index b23cc003..4cba8fe1 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -20,7 +20,7 @@ jobs: uses: subosito/flutter-action@v1 with: channel: 'stable' - flutter-version: '2.10.x' + flutter-version: '3.0.x' - name: Get dependencies run: flutter pub get diff --git a/AUTHORS.md b/AUTHORS.md index e457326d..ea77dc6e 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -12,6 +12,7 @@ - Thilina Herath - - Marko Milosevic - - Karthik Reddy (Axel) - +- Ogundoyin Toluwani - ## Translators diff --git a/README.md b/README.md index 293740c6..820a29d6 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Alternatively, you can use one of our test servers, just ask us for access. Install Flutter, and all its dependencies, and create a new virtual device: . -The app currently uses flutter 2.10 +The app currently uses flutter 3.0 ### 3 Create a new file ``wger.properties`` in ``android/fastlane/envfiles``: diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 74c94a8d..001b3a6c 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,13 +1,12 @@ - + - - + + @@ -15,55 +14,28 @@ - + - + - + - - - + - - + + - + - + \ No newline at end of file diff --git a/fastlane/metadata/android/pl/full_description.txt b/fastlane/metadata/android/pl/full_description.txt new file mode 100644 index 00000000..12a0b005 --- /dev/null +++ b/fastlane/metadata/android/pl/full_description.txt @@ -0,0 +1,39 @@ +Od miłośników fitnessu dla miłośników fitnessu – zorganizuj zdrowy tryb życia dzięki WGER, twojemu menadżerowi treningu! + +Znalazłeś już swoją najlepszą aplikację do fitnessu i lubisz tworzyć własne programy sportowe? Bez względu na to, jakim jesteś typem wysportowanej bestii – wszyscy mamy coś wspólnego: uwielbiamy śledzić nasze dane dotyczące zdrowia <3 + +Więc nie oceniamy Cię za to, że nadal zarządzasz swoją podróżą przez świat fitness za pomocą poręcznego małego zeszytu treningowego, ale witaj w 2021 roku! + +Opracowaliśmy dla Ciebie w 100% darmową cyfrową aplikację do monitorowania zdrowia i kondycji, dostosowaną do najistotniejszych funkcji, aby ułatwić Ci życie. Rozpocznij, kontynuuj trening i świętuj swoje postępy! + +WGER to projekt Open Source, dostarcza informacji o: +* Twoim ciele +* Twoim treningu +* Twoim postępie +* Twoich danych + +Twoje ciało: +Nie musisz wyszukiwać w wyszukiwarce składników ulubionych przysmaków – wybieraj codzienne posiłki spośród ponad 78000 produktów i poznaj wartości odżywcze. Dodaj posiłki do planu żywieniowego i prowadź przegląd swojej diety w kalendarzu. + +Twoje treningi: +Wiesz, co jest najlepsze dla Twojego ciała. Twórz własne treningi z rosnącej różnorodności spośród 200 różnych ćwiczeń. Następnie użyj trybu Gym Mode, aby poprowadzić Cię przez trening, jednocześnie rejestrując swoje ciężary za pomocą jednego dotknięcia. + +Twój postęp: +Nigdy nie trać z oczu swoich celów. Śledź swoją wagę i utrzymuj statystyki. + +Twoje dane: +WGER to Twój spersonalizowany dziennik fitness – ale to Ty jesteś właścicielem swoich danych. Użyj interfejsu API REST, aby uzyskać dostęp do danych i robić z nimi niesamowite rzeczy. + +Uwaga: ta bezpłatna aplikacja nie jest oparta na dodatkowych funduszach i nie prosimy o przekazywanie pieniędzy. Co więcej, jest to projekt społecznościowy, który stale się rozwija. Przygotuj się więc na nowe funkcje w każdej chwili! + +#OpenSource – co to oznacza? + +Open Source oznacza, że cały kod źródłowy tej aplikacji i serwer, z którym się łączy, jest bezpłatny i dostępny dla każdego: +* Czy chcesz uruchomić WGER na własnym serwerze dla siebie lub lokalnej siłowni? Zrób to! +* Czy brakuje Ci jakiejś funkcji i chcesz ją wdrożyć? Startuj z pomysłem! +* Czy chcesz sprawdzić, czy nic nie jest nigdzie wysyłane? Możesz! + +Dołącz do naszej społeczności i zostań częścią entuzjastów sportu i geeków IT z całego świata. Nieustannie pracujemy nad dostosowaniem i optymalizacją aplikacji dostosowanej do naszych potrzeb. Czekamy na twój wkład, więc możesz dołączyć w dowolnym momencie i podzielić się swoimi życzeniami i pomysłami! + +-> znajdź kod źródłowy na https://github.com/wger-project +-> zadawaj pytania lub po prostu przywitaj się na naszym serwerze Discord https://discord.gg/rPWFv6W diff --git a/fastlane/metadata/android/pl/short_description.txt b/fastlane/metadata/android/pl/short_description.txt new file mode 100644 index 00000000..c0f553f1 --- /dev/null +++ b/fastlane/metadata/android/pl/short_description.txt @@ -0,0 +1 @@ +Monitorowanie kondycji/treningu, odżywiania i wagi diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index bd5cb272..9fd2ce77 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -31,7 +31,7 @@ "@invalidUrl": { "description": "Error message when the user enters an invalid URL, e.g. in the login form" }, - "useCustomServer": "Używaj niestandardowe o serwera", + "useCustomServer": "Używaj niestandardowego serwera", "@useCustomServer": { "description": "Toggle button allowing users to switch between the default and a custom wger server" }, @@ -50,5 +50,511 @@ "login": "Zaloguj się", "@login": { "description": "Text for login button" + }, + "save": "Zapisz", + "@save": {}, + "customServerUrl": "Adres URL instancji wger", + "@customServerUrl": { + "description": "Label in the form where the users can enter their own wger instance" + }, + "customServerHint": "Wpisz adres własnego serwera, w przeciwnym razie zostanie użyty domyślny", + "@customServerHint": { + "description": "Hint text for the form where the users can enter their own wger instance" + }, + "reset": "Reset", + "@reset": { + "description": "Button text allowing the user to reset the entered values to the default" + }, + "macronutrients": "Makroelementy", + "@macronutrients": {}, + "energyShort": "E", + "@energyShort": { + "description": "The first letter or short name of the word 'Energy', used in overviews" + }, + "logged": "Zapisane", + "@logged": { + "description": "Header for the column of 'logged' nutritional values, i.e. what was eaten" + }, + "addImage": "Dodaj obraz", + "@addImage": {}, + "weekAverage": "Średnia z poprzedniego tygodnia", + "@weekAverage": { + "description": "Header for the column of '7 day average' nutritional values, i.e. what was logged last week" + }, + "total": "Sumarycznie", + "@total": { + "description": "Label used for total sums of e.g. calories or similar" + }, + "unit": "Jednostka", + "@unit": { + "description": "The unit used for a repetition (kg, time, etc.)" + }, + "aboutDescription": "Dziękujemy za używanie wger! Wger jest projektem open-source stworzonym przy współpracy entuzjastów fitnessu z całego świata.", + "@aboutDescription": { + "description": "Text in the about dialog" + }, + "aboutSourceTitle": "Kod źródłowy", + "@aboutSourceTitle": { + "description": "Title for source code section in the about dialog" + }, + "productFoundDescription": "Kod kreskowy odpowiada temu produktowi: {productName}. Czy chcesz kontynuować?", + "@productFoundDescription": { + "description": "Dialog info when product is found with barcode", + "type": "text", + "placeholders": { + "productName": {} + } + }, + "dataCopied": "Dane skopiowane do nowego dziennika", + "@dataCopied": { + "description": "Snackbar message to show on copying data to a new log entry" + }, + "noWeightEntries": "Nie masz wpisów dotyczących wagi", + "@noWeightEntries": { + "description": "Message shown when the user has no logged weight entries" + }, + "loadingText": "Ładowanie...", + "@loadingText": { + "description": "Text to show when entries are being loaded in the background: Loading..." + }, + "calendar": "Kalendarz", + "@calendar": {}, + "selectExercise": "Wybierz ćwiczenie", + "@selectExercise": { + "description": "Error message when the user hasn't selected an exercise in the form" + }, + "enterCharacters": "Wprowadź od {min} do {max} znaków", + "@enterCharacters": { + "description": "Error message when the user hasn't entered the correct number of characters in a form", + "type": "text", + "placeholders": { + "min": {}, + "max": {} + } + }, + "nrOfSets": "Ilość serii ćwiczenia: {nrOfSets}", + "@nrOfSets": { + "description": "Label shown on the slider where the user selects the nr of sets", + "type": "text", + "placeholders": { + "nrOfSets": {} + } + }, + "supersetWith": "Dodatkowa seria", + "@supersetWith": { + "description": "Text used between exercise cards when adding a new set. Translate as something like 'in a superset with'" + }, + "rirNotUsed": "Bez rezerwy powtórzeń", + "@rirNotUsed": { + "description": "Label used in RiR slider when the RiR value is not used/saved for the current setting or log" + }, + "weightUnit": "Jednostka wagi", + "@weightUnit": {}, + "repetitionUnit": "Jednostka powtórzeń", + "@repetitionUnit": {}, + "set": "Seria", + "@set": { + "description": "A set in a workout plan" + }, + "dayDescriptionHelp": "Opis tego, co jest robione w tym dniu (np. „dzień podciągania”) lub jakie części ciała są trenowane (np. „klatka piersiowa i ramiona”)", + "@dayDescriptionHelp": {}, + "setNr": "{nr} serii", + "@setNr": { + "description": "Header in form indicating the number of the current set. Can also be translated as something like 'Set Nr. xy'.", + "type": "text", + "placeholders": { + "nr": {} + } + }, + "sameRepetitions": "Jeśli wykonasz tą sama liczbę powtórzenia z tym samym ciężarem dla wszystkich serii, możesz po prostu wypełnić jeden wiersz. Na przykład dla 4 serii wystarczy wpisać 10 dla powtórzeń, automatycznie zmieni się to na „4 x 10”.", + "@sameRepetitions": {}, + "comment": "Komentarz", + "@comment": { + "description": "Comment, additional information" + }, + "impression": "Ocena treningu", + "@impression": { + "description": "General impression (e.g. for a workout session) such as good, bad, etc." + }, + "workoutSession": "Sesja treningowa", + "@workoutSession": { + "description": "A (logged) workout session" + }, + "newSet": "Nowa seria", + "@newSet": { + "description": "Header when adding a new set to a workout day" + }, + "selectExercises": "Jeśli chcesz zrobić super serię, możesz wyszukać kilka ćwiczeń, zostaną one zgrupowane razem", + "@selectExercises": {}, + "gymMode": "Tryb treningu", + "@gymMode": { + "description": "Label when starting the gym mode" + }, + "equipment": "Sprzęt", + "@equipment": { + "description": "Equipment needed to perform an exercise" + }, + "muscles": "Mięśnie", + "@muscles": { + "description": "(main) muscles trained by an exercise" + }, + "musclesSecondary": "Mięśnie pomocnicze", + "@musclesSecondary": { + "description": "secondary muscles trained by an exercise" + }, + "category": "Kategoria", + "@category": { + "description": "Category for an exercise, ingredient, etc." + }, + "newWorkout": "Nowy plan treningowy", + "@newWorkout": { + "description": "Header when adding a new workout" + }, + "noWorkoutPlans": "Nie masz planów treningowych", + "@noWorkoutPlans": { + "description": "Message shown when the user has no workout plans" + }, + "repetitions": "Powtórzenia", + "@repetitions": { + "description": "Repetitions for an exercise set" + }, + "reps": "Powtórzenia", + "@reps": { + "description": "Shorthand for repetitions, used when space constraints are tighter" + }, + "rir": "Rezerwa powtórzeń", + "@rir": { + "description": "Shorthand for Repetitions In Reserve" + }, + "successfullySaved": "Zapisane", + "@successfullySaved": { + "description": "Message when an item was successfully saved" + }, + "exercise": "Ćwiczenie", + "@exercise": { + "description": "An exercise for a workout" + }, + "searchExercise": "Wyszukaj ćwiczenie do dodania", + "@searchExercise": { + "description": "Label on set form. Selected exercises are added to the set" + }, + "logHelpEntries": "Jeśli w ciągu jednego dnia jest więcej niż jeden wpis z tą samą liczbą powtórzeń, ale z różnymi wagami, na wykresie pokazany jest tylko wpis o wyższej wadze.", + "@logHelpEntries": {}, + "logHelpEntriesUnits": "Zwróć uwagę, że na wykresie są tylko wpisy z jednostką masy (kg lub lb) i powtórzeniami, inne kombinacje, takie jak czas lub czas do błędu, są tutaj ignorowane.", + "@logHelpEntriesUnits": {}, + "description": "Opis", + "@description": {}, + "name": "Nazwa", + "@name": { + "description": "Name for a workout or nutritional plan" + }, + "addSet": "Dodaj serię", + "@addSet": { + "description": "Label for the button that adds a set (to a workout day)" + }, + "addMeal": "Dodaj posiłek", + "@addMeal": {}, + "fat": "Tłuszcz", + "@fat": {}, + "measurement": "Pomiar", + "@measurement": {}, + "measurements": "Pomiar", + "@measurements": { + "description": "Categories for the measurements such as biceps size, body fat, etc." + }, + "registerInstead": "Zarejestruj zamiast", + "@registerInstead": {}, + "loginInstead": "Zaloguj się zamiast tego", + "@loginInstead": {}, + "labelWorkoutPlans": "Plany treningowe", + "@labelWorkoutPlans": { + "description": "Title for screen workout plans" + }, + "labelBottomNavWorkout": "Trening", + "@labelBottomNavWorkout": { + "description": "Label used in bottom navigation, use a short word" + }, + "labelBottomNavNutrition": "Żywienie", + "@labelBottomNavNutrition": { + "description": "Label used in bottom navigation, use a short word" + }, + "labelWorkoutLogs": "Dzienniki treningowe", + "@labelWorkoutLogs": { + "description": "(Workout) logs" + }, + "labelWorkoutPlan": "Plan treningu", + "@labelWorkoutPlan": { + "description": "Title for screen workout plan" + }, + "successfullyDeleted": "Usunięto", + "@successfullyDeleted": { + "description": "Message when an item was successfully deleted" + }, + "labelDashboard": "Pulpit", + "@labelDashboard": { + "description": "Title for screen dashboard" + }, + "notes": "Notatki", + "@notes": { + "description": "Personal notes, e.g. for a workout session" + }, + "newDay": "Nowy dzień", + "@newDay": {}, + "pause": "Przerwa", + "@pause": { + "description": "Noun, not an imperative! Label used for the pause when using the gym mode" + }, + "todaysWorkout": "Twój dzisiejszy trening", + "@todaysWorkout": {}, + "date": "Data", + "@date": { + "description": "The date of a workout log or body weight entry" + }, + "jumpTo": "Wybierz ćwiczenie", + "@jumpTo": { + "description": "Imperative. Label used in popup allowing the user to jump to a specific exercise while in the gym mode" + }, + "noNutritionalPlans": "Nie masz planów żywieniowych", + "@noNutritionalPlans": { + "description": "Message shown when the user has no nutritional plans" + }, + "plateCalculator": "Obciążnik", + "@plateCalculator": { + "description": "Label used for the plate calculator in the gym mode" + }, + "plateCalculatorNotDivisible": "Nie można osiągnąć wagi z dostępnymi obciążeniami", + "@plateCalculatorNotDivisible": { + "description": "Error message when the current weight is not reachable with plates (e.g. 33.1 kg)" + }, + "mealLogged": "Posiłek zarejestrowany w dzienniku", + "@mealLogged": {}, + "logMeal": "Zaloguj ten posiłek", + "@logMeal": {}, + "addIngredient": "Dodaj składnik", + "@addIngredient": {}, + "nutritionalPlan": "Plan diety", + "@nutritionalPlan": {}, + "nutritionalDiary": "Dziennik żywieniowy", + "@nutritionalDiary": {}, + "nutritionalPlans": "Plany żywieniowe", + "@nutritionalPlans": {}, + "start": "Rozpocznij", + "@start": { + "description": "Label on button to start the gym mode (i.e., an imperative)" + }, + "timeStart": "Czas rozpoczęcia", + "@timeStart": { + "description": "The starting time of a workout" + }, + "timeEnd": "Czas zakończenia", + "@timeEnd": { + "description": "The end time of a workout" + }, + "ingredient": "Składnik", + "@ingredient": {}, + "energy": "Energia", + "@energy": { + "description": "Energy in a meal, ingredient etc. e.g. in kJ" + }, + "time": "Czas", + "@time": { + "description": "The time of a meal or workout" + }, + "anErrorOccurred": "Wystąpił błąd!", + "@anErrorOccurred": {}, + "weight": "Waga", + "@weight": { + "description": "The weight of a workout log or body weight entry" + }, + "kJ": "kJ", + "@kJ": { + "description": "Energy in a meal in kilo joules, kJ" + }, + "g": "g", + "@g": { + "description": "Abbreviation for gram" + }, + "protein": "Białko", + "@protein": {}, + "carbohydrates": "Węglowodany", + "@carbohydrates": {}, + "confirmDelete": "Czy na pewno chcesz usunąć '{toDelete}'?", + "@confirmDelete": { + "description": "Confirmation text before the user deletes an object", + "type": "text", + "placeholders": { + "toDelete": {} + } + }, + "planned": "Zaplanowane", + "@planned": { + "description": "Header for the column of 'planned' nutritional values, i.e. what should be eaten" + }, + "difference": "Różnice", + "@difference": {}, + "percentEnergy": "Procent energii", + "@percentEnergy": {}, + "gPerBodyKg": "g / kg", + "@gPerBodyKg": { + "description": "Label used for total sums of e.g. calories or similar in grams per Kg of body weight" + }, + "proteinShort": "B", + "@proteinShort": { + "description": "The first letter or short name of the word 'Protein', used in overviews" + }, + "carbohydratesShort": "W", + "@carbohydratesShort": { + "description": "The first letter or short name of the word 'Carbohydrates', used in overviews" + }, + "sugars": "Cukier", + "@sugars": {}, + "fatShort": "T", + "@fatShort": { + "description": "The first letter or short name of the word 'Fat', used in overviews" + }, + "saturatedFat": "Tłuszcz nasycony", + "@saturatedFat": {}, + "fibres": "Błonnik", + "@fibres": {}, + "sodium": "Sód", + "@sodium": {}, + "amount": "Ilość", + "@amount": { + "description": "The amount (e.g. in grams) of an ingredient in a meal" + }, + "newEntry": "Nowy", + "@newEntry": { + "description": "Title when adding a new entry such as a weight or log entry" + }, + "edit": "Edytuj", + "@edit": {}, + "delete": "Usuń", + "@delete": {}, + "newNutritionalPlan": "Nowy plan żywieniowy", + "@newNutritionalPlan": {}, + "toggleDetails": "Przełącz szczegóły", + "@toggleDetails": { + "description": "Switch to toggle detail / overview" + }, + "goToDetailPage": "Przejdź do strony szczegółów", + "@goToDetailPage": {}, + "aboutSourceText": "Zobacz kod źródłowy tej aplikacji i jej serwera na Githubie", + "@aboutSourceText": { + "description": "Text for source code section in the about dialog" + }, + "takePicture": "Zrób zdjęcie", + "@takePicture": {}, + "chooseFromLibrary": "Wybierz z galerii zdjęć", + "@chooseFromLibrary": {}, + "gallery": "Galeria", + "@gallery": {}, + "appUpdateTitle": "Wymagana aktualizacja", + "@appUpdateTitle": {}, + "appUpdateContent": "Ta wersja aplikacji nie jest kompatybilna z serwerem, zaktualizuj swoją aplikację.", + "@appUpdateContent": {}, + "productFound": "Znaleziono produkt", + "@productFound": { + "description": "Header label for dialog when product is found with barcode" + }, + "productNotFound": "Produkt nie znaleziony", + "@productNotFound": { + "description": "Header label for dialog when product is not found with barcode" + }, + "productNotFoundDescription": "Produkt z zeskanowanym kodem kreskowym {barcode} nie został znaleziony w bazie danych wger", + "@productNotFoundDescription": { + "description": "Dialog info when product is not found with barcode", + "type": "text", + "placeholders": { + "barcode": {} + } + }, + "scanBarcode": "Zeskanuj kod kreskowy", + "@scanBarcode": { + "description": "Label for scan barcode button" + }, + "close": "Zamknij", + "@close": { + "description": "Translation for close" + }, + "logIngredient": "Zapisz w dzienniku żywieniowym", + "@logIngredient": {}, + "searchIngredient": "Wyszukaj składnik", + "@searchIngredient": { + "description": "Label on ingredient search form" + }, + "measurementCategoriesHelpText": "Kategoria pomiaru, np. „biceps” lub „pomiar warstwy podskórnej tłuszczu”", + "@measurementCategoriesHelpText": {}, + "measurementEntriesHelpText": "Jednostka pomiaru np. „cm” lub „%”", + "@measurementEntriesHelpText": {}, + "value": "Wartość", + "@value": { + "description": "The value of a measurement entry" + }, + "timeStartAhead": "Czas rozpoczęcia nie może być wcześniejszy niż czas zakończenia", + "@timeStartAhead": {}, + "kcal": "kcal", + "@kcal": { + "description": "Energy in a meal in kilocalories, kcal" + }, + "aboutBugsTitle": "Masz problem lub pomysł?", + "@aboutBugsTitle": { + "description": "Title for bugs section in the about dialog" + }, + "aboutBugsText": "Skontaktuj się z nami, jeżeli coś zachowało się w niespodziewany sposób lub czujesz, że brakuje jakiejś funkcji.", + "@aboutBugsText": { + "description": "Text for bugs section in the about dialog" + }, + "aboutContactUsTitle": "Przywitaj się!", + "@aboutContactUsTitle": { + "description": "Title for contact us section in the about dialog" + }, + "aboutContactUsText": "Jeśli chcesz z nami porozmawiać, wskocz na serwer Discorda i przywitaj się", + "@aboutContactUsText": { + "description": "Text for contact us section in the about dialog" + }, + "aboutTranslationTitle": "Tłumaczenie", + "@aboutTranslationTitle": { + "description": "Title for translation section in the about dialog" + }, + "selectIngredient": "Wybierz składnik", + "@selectIngredient": { + "description": "Error message when the user hasn't selected an ingredient from the autocompleter" + }, + "recentlyUsedIngredients": "Ostatnio dodane składniki", + "@recentlyUsedIngredients": { + "description": "A message when a user adds a new ingredient to a meal." + }, + "selectImage": "Wybierz obraz", + "@selectImage": { + "description": "Label and error message when the user hasn't selected an image to save" + }, + "optionsLabel": "Opcje", + "@optionsLabel": { + "description": "Label for the popup with general app options" + }, + "aboutTranslationText": "Ta aplikacja jest tłumaczona poprzez Weblate. Jeśli też chcesz pomóc, kliknij link i zacznij tłumaczyć", + "@aboutTranslationText": { + "description": "Text for translation section in the about dialog" + }, + "goToToday": "Przejdź do dziś", + "@goToToday": { + "description": "Label on button to jump back to 'today' in the calendar widget" + }, + "enterRepetitionsOrWeight": "Proszę wypełnić powtórzenia lub wagę przynajmniej jednej serii", + "@enterRepetitionsOrWeight": { + "description": "Error message when the user hasn't filled in the forms for exercise sets" + }, + "enterValue": "proszę wprowadzić wartość", + "@enterValue": { + "description": "Error message when the user hasn't entered a value on a required field" + }, + "setUnitsAndRir": "Ustaw jednostki oraz liczbę powtórzeń rezerwy", + "@setUnitsAndRir": { + "description": "Label shown on the slider where the user can toggle showing units and RiR", + "type": "text" + }, + "enterValidNumber": "Proszę wprowadzić poprawny numer", + "@enterValidNumber": { + "description": "Error message when the user has submitted an invalid number (e.g. '3,.,.,.')" } } diff --git a/lib/l10n/app_uk.arb b/lib/l10n/app_uk.arb index 44401795..e7c81a5b 100644 --- a/lib/l10n/app_uk.arb +++ b/lib/l10n/app_uk.arb @@ -515,7 +515,7 @@ }, "takePicture": "Зробити знімок", "@takePicture": {}, - "chooseFromLibrary": "Вибрати з бібліотеки фотографій", + "chooseFromLibrary": "Вибрати з бібліотеки світлин", "@chooseFromLibrary": {}, "gallery": "Галерея", "@gallery": {}, diff --git a/lib/providers/helpers.dart b/lib/providers/helpers.dart index 458c6d97..aa22d97f 100644 --- a/lib/providers/helpers.dart +++ b/lib/providers/helpers.dart @@ -26,7 +26,7 @@ Uri makeUri( ]) { final Uri uriServer = Uri.parse(serverUrl); - final pathList = ['api', 'v2', path]; + final pathList = [uriServer.path, 'api', 'v2', path]; if (id != null) { pathList.add(id.toString()); } diff --git a/pubspec.lock b/pubspec.lock index 53fb73bb..c1ca163a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,14 +7,14 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "40.0.0" + version: "41.0.0" analyzer: dependency: transitive description: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "4.1.0" + version: "4.2.0" android_metadata: dependency: "direct main" description: @@ -28,7 +28,7 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.1.6" + version: "3.1.11" args: dependency: transitive description: @@ -63,7 +63,7 @@ packages: name: build_config url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0" build_daemon: dependency: transitive description: @@ -84,7 +84,7 @@ packages: name: build_runner url: "https://pub.dartlang.org" source: hosted - version: "2.1.11" + version: "2.2.0" build_runner_core: dependency: transitive description: @@ -105,21 +105,21 @@ packages: name: built_value url: "https://pub.dartlang.org" source: hosted - version: "8.3.3" + version: "8.4.0" camera: dependency: "direct main" description: name: camera url: "https://pub.dartlang.org" source: hosted - version: "0.9.8+1" + version: "0.10.0" camera_android: dependency: transitive description: name: camera_android url: "https://pub.dartlang.org" source: hosted - version: "0.9.8+3" + version: "0.10.0" camera_avfoundation: dependency: transitive description: @@ -140,7 +140,7 @@ packages: name: camera_web url: "https://pub.dartlang.org" source: hosted - version: "0.2.1+6" + version: "0.3.0" change: dependency: transitive description: @@ -224,7 +224,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" convert: dependency: transitive description: @@ -280,14 +280,14 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0" ffi: dependency: transitive description: name: ffi url: "https://pub.dartlang.org" source: hosted - version: "1.2.1" + version: "2.0.1" file: dependency: transitive description: @@ -320,7 +320,7 @@ packages: name: flutter_calendar_carousel url: "https://pub.dartlang.org" source: hosted - version: "2.3.1" + version: "2.4.0" flutter_driver: dependency: transitive description: flutter @@ -374,7 +374,7 @@ packages: name: flutter_lints url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.1" flutter_localizations: dependency: "direct main" description: flutter @@ -393,7 +393,7 @@ packages: name: flutter_plugin_android_lifecycle url: "https://pub.dartlang.org" source: hosted - version: "2.0.6" + version: "2.0.7" flutter_svg: dependency: "direct main" description: @@ -412,7 +412,7 @@ packages: name: flutter_typeahead url: "https://pub.dartlang.org" source: hosted - version: "3.2.7" + version: "4.0.0" flutter_web_plugins: dependency: transitive description: flutter @@ -513,7 +513,7 @@ packages: name: image_picker_ios url: "https://pub.dartlang.org" source: hosted - version: "0.8.5+5" + version: "0.8.5+6" image_picker_platform_interface: dependency: transitive description: @@ -546,21 +546,21 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3" + version: "0.6.4" json_annotation: dependency: "direct main" description: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "4.5.0" + version: "4.6.0" json_serializable: dependency: "direct dev" description: name: json_serializable url: "https://pub.dartlang.org" source: hosted - version: "6.2.0" + version: "6.3.1" klizma: dependency: transitive description: @@ -574,7 +574,7 @@ packages: name: lints url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "2.0.0" logging: dependency: transitive description: @@ -609,7 +609,7 @@ packages: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.3" + version: "0.1.4" meta: dependency: transitive description: @@ -679,7 +679,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" path_drawing: dependency: transitive description: @@ -714,14 +714,14 @@ packages: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.7" + version: "2.1.0" petitparser: dependency: transitive description: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "4.4.0" + version: "5.0.0" platform: dependency: transitive description: @@ -894,7 +894,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" stack_trace: dependency: transitive description: @@ -950,7 +950,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.8" + version: "0.4.9" timing: dependency: transitive description: @@ -978,7 +978,7 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.1.4" + version: "6.1.5" url_launcher_android: dependency: transitive description: @@ -1034,7 +1034,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" version: dependency: "direct main" description: @@ -1062,7 +1062,7 @@ packages: name: video_player_android url: "https://pub.dartlang.org" source: hosted - version: "2.3.6" + version: "2.3.7" video_player_avfoundation: dependency: transitive description: @@ -1090,14 +1090,14 @@ packages: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "7.5.0" + version: "8.2.2" wakelock: dependency: transitive description: name: wakelock url: "https://pub.dartlang.org" source: hosted - version: "0.6.1+2" + version: "0.6.2" wakelock_macos: dependency: transitive description: @@ -1174,14 +1174,14 @@ packages: name: webview_flutter_wkwebview url: "https://pub.dartlang.org" source: hosted - version: "2.7.5" + version: "2.9.1" win32: dependency: transitive description: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.5.2" + version: "2.7.0" xdg_directories: dependency: transitive description: @@ -1195,7 +1195,7 @@ packages: name: xml url: "https://pub.dartlang.org" source: hosted - version: "5.3.1" + version: "5.4.1" yaml: dependency: transitive description: @@ -1204,5 +1204,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.16.0 <3.0.0" - flutter: ">=2.10.0" + dart: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index fc1a890e..2d0cd9f7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,14 +32,14 @@ dependencies: sdk: flutter android_metadata: ^0.2.1 - camera: ^0.9.8 + camera: ^0.10.0 charts_flutter: ^0.12.0 collection: ^1.15.0-nullsafety.4 cupertino_icons: ^1.0.5 equatable: ^2.0.3 - flutter_calendar_carousel: ^2.2.0 + flutter_calendar_carousel: ^2.4.0 flutter_html: ^2.1.2 - flutter_typeahead: ^3.2.5 + flutter_typeahead: ^4.0.0 font_awesome_flutter: ">=9.1.0 <11.0.0" http: ^0.13.3 image_picker: ^0.8.4+9 @@ -62,12 +62,12 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.2.0 flutter_launcher_icons: ^0.9.3 - json_serializable: ^6.2.0 + json_serializable: ^6.3.1 mockito: ^5.2.0 - network_image_mock: ^2.0.1 - flutter_lints: ^1.0.4 + network_image_mock: ^2.1.1 + flutter_lints: ^2.0.1 cider: ^0.1.1 flutter_icons: diff --git a/test/other/base_provider_test.dart b/test/other/base_provider_test.dart index 2f6cbdf1..bd3c4715 100644 --- a/test/other/base_provider_test.dart +++ b/test/other/base_provider_test.dart @@ -58,5 +58,40 @@ void main() { provider.makeUrl('endpoint', id: 42, objectMethod: 'log_data', query: {'a': '2', 'b': 'c'}), ); }); + + test('Test the makeUrl helper with sub url', () async { + // Trailing slash is removed when saving the server URL + testAuthProvider.serverUrl = 'https://example.com/wger-url'; + final WgerBaseProvider provider = WgerBaseProvider(testAuthProvider); + + expect( + Uri.https('example.com', '/wger-url/api/v2/endpoint/'), + provider.makeUrl('endpoint'), + ); + expect( + Uri.https('example.com', '/wger-url/api/v2/endpoint/5/'), + provider.makeUrl('endpoint', id: 5), + ); + expect( + Uri.https('example.com', '/wger-url/api/v2/endpoint/5/log_data/'), + provider.makeUrl('endpoint', id: 5, objectMethod: 'log_data'), + ); + expect( + Uri.https('example.com', '/wger-url/api/v2/endpoint/', {'a': '2', 'b': 'c'}), + provider.makeUrl('endpoint', query: {'a': '2', 'b': 'c'}), + ); + expect( + Uri.https('example.com', '/wger-url/api/v2/endpoint/log_data/', {'a': '2', 'b': 'c'}), + provider.makeUrl('endpoint', objectMethod: 'log_data', query: {'a': '2', 'b': 'c'}), + ); + expect( + Uri.https('example.com', '/wger-url/api/v2/endpoint/42/', {'a': '2', 'b': 'c'}), + provider.makeUrl('endpoint', id: 42, query: {'a': '2', 'b': 'c'}), + ); + expect( + Uri.https('example.com', '/wger-url/api/v2/endpoint/42/log_data/', {'a': '2', 'b': 'c'}), + provider.makeUrl('endpoint', id: 42, objectMethod: 'log_data', query: {'a': '2', 'b': 'c'}), + ); + }); }); }