Compare commits

...

8 commits

Author SHA1 Message Date
Vadim
82669bc5e5 allow more free actions 2025-08-11 12:31:38 +02:00
Vadim
e4bb7588ef reworked DialogSwitchListItem 2025-08-11 12:25:38 +02:00
Vadim
709d19bb73 brought back enabled adapter 2025-08-11 12:04:58 +02:00
Vadim
a7c0282e5a fixed pro features width 2025-08-11 11:42:16 +02:00
Vadim
5204327fcc Update metering_screen.png 2025-08-11 11:20:13 +02:00
Vadim
4032a510a6 fixed offering padding 2025-08-11 11:20:10 +02:00
Vadim
c0881e5b24 Merge branch 'main' of https://github.com/vodemn/m3_lightmeter into feature/ML-248 2025-08-11 11:10:43 +02:00
Vadim
056cf4f44b
ML-247 Revise translations + Add PL locale (#249)
* wip

* wip

* reviewed punctuation

* Create intl_pl.arb

* Update metering_screen.png

* fixed polish translations

* shortened Russian translations

* Added missing translations

* Update intl_ru.arb
2025-08-11 11:09:29 +02:00
26 changed files with 567 additions and 265 deletions

View file

@ -1,4 +1,4 @@
enum SupportedLocale { de, en, fr, ru, zh }
enum SupportedLocale { de, en, fr, pl, ru, zh }
extension SupportedLocaleExtension on SupportedLocale {
String get intlName => toString().replaceAll("SupportedLocale.", "");
@ -11,6 +11,8 @@ extension SupportedLocaleExtension on SupportedLocale {
return 'English';
case SupportedLocale.fr:
return 'Français';
case SupportedLocale.pl:
return 'Polski';
case SupportedLocale.ru:
return 'Русский';
case SupportedLocale.zh:

View file

@ -1,7 +1,7 @@
{
"@@locale": "de",
"fastestExposurePair": "Schnellstes",
"slowestExposurePair": "Langsamstes",
"fastestExposurePair": "Kürzeste",
"slowestExposurePair": "Längste",
"ev": "EV",
"evValue": "{value} EV",
"@evValue": {
@ -14,11 +14,11 @@
"iso": "ISO",
"filmSpeed": "Film Empfindlichkeit",
"nd": "ND",
"ndFilterFactor": "Neutraldichtefilter-Faktor",
"noExposurePairs": "Es gibt keine Belichtungspaare für die ausgewählten Einstellungen.",
"noCamerasDetected": "Scheinbar sind keine Kameras an das Gerät angeschlossen.",
"noCameraPermission": "Kamera-Erlaubnis nicht erteilt.",
"otherCameraError": "Beim Verbinden der Kamera ist ein Fehler aufgetreten.",
"ndFilterFactor": "ND-Filter Stärke",
"noExposurePairs": "Keine Belichtungspaare für diese Einstellungen verfügbar",
"noCamerasDetected": "Keine Kamera gefunden",
"noCameraPermission": "Kamera-Erlaubnis nicht erteilt",
"otherCameraError": "Kamera-Verbindungsfehler",
"none": "Keiner",
"cancel": "Abbrechen",
"select": "Auswählen",
@ -31,23 +31,23 @@
"halfStops": "1/2",
"thirdStops": "1/3",
"calibration": "Kalibration",
"calibrationMessage": "Die Genauigkeit der Messungen sind vollständig von der Hardware des Geräts abhängig. Deshalb ist es empfehlenswert diese App zu testen und EV-Kalibrationswerte einzustellen, die korrekte Messungen produzieren.",
"calibrationMessageCameraOnly": "Die Genauigkeit der Messungen sind vollständig von der Kamera des Geräts abhängig. Deshalb ist es empfehlenswert diese App zu testen und EV-Kalibrationswerte einzustellen, die korrekte Messungen produzieren.",
"calibrationMessage": "Die Messgenauigkeit hängt von der Gerätehardware ab. Testen Sie die App und kalibrieren Sie EV-Werte für beste Ergebnisse",
"calibrationMessageCameraOnly": "Die Messgenauigkeit hängt von der Kamera ab. Testen Sie die App und kalibrieren Sie EV-Werte für beste Ergebnisse",
"camera": "Kamera",
"lightSensor": "Lichtsensor",
"showEv100": "EV\u2081\u2080\u2080 anzeigen",
"meteringScreenLayout": "Messansicht Layout",
"meteringScreenLayoutHint": "Verstecke Elemente von der Messansicht, damit sie nicht den Platz für Belichtungspaare verschwenden.",
"meteringScreenLayoutHint": "Blenden Sie unnötige Elemente aus, um Platz zu sparen",
"meteringScreenLayoutHintEquipmentProfiles": "Ausrüstungsprofil Auswahl",
"meteringScreenFeatureExtremeExposurePairs": "Schnellste & langsamste Belichtungspaare",
"meteringScreenFeatureFilmPicker": "Film Auswahl",
"cameraFeatures": "Kamerafunktionen",
"cameraFeatureSpotMetering": "Punkt-Messung",
"cameraFeatureSpotMeteringHint": "Halte die Kameraansicht gedrückt um den Messpunkt zu entfernen",
"cameraFeatureSpotMeteringHint": "Lange drücken zum Entfernen des Messpunkts",
"cameraFeatureHistogram": "Histogramm",
"cameraFeatureHistogramHint": "Verwendung des Histogramms kann den Batterieverbrauch erhöhen",
"cameraFeatureHistogramHint": "Kann den Batterieverbrauch erhöhen",
"cameraFeaturesShowFocalLength": "Brennweite anzeigen",
"cameraFeaturesShowFocalLengthHint": "Zeigt die 35mm-äquivalente Brennweite statt des Zoomfaktors an",
"cameraFeaturesShowFocalLengthHint": "35mm-Äquivalent statt Zoomfaktor",
"film": "Film",
"filmPush": "Film (push)",
"filmPull": "Film (pull)",
@ -57,20 +57,20 @@
"equipmentProfileAllValues": "Alle",
"apertureValues": "Blend-Werte",
"apertureValue": "Blend-Wert",
"apertureValuesFilterDescription": "Wähle die anzuzeigenden Blend-Werte aus. Die Werte sind normalerweise von dem verwendeten Objektiv bestimmt.",
"apertureValuesFilterDescription": "Wählen Sie den Blendenbereich für Ihr Objektiv",
"ndFilters": "ND Filter",
"ndFiltersFilterDescription": "Wähle die anzuzeigenden ND Filter aus. (Beispielsweise die Meistverwendeten)",
"ndFiltersFilterDescription": "Wählen Sie verfügbare ND-Filter",
"shutterSpeedValues": "Belichtungszeiten",
"shutterSpeedValue": "Belichtungszeit",
"shutterSpeedValuesFilterDescription": "Wähle die anzuzeigenden Belichtungszeiten aus. Die Werte sind normalerweise von der Kamera bestimmt.",
"shutterSpeedValuesFilterDescription": "Wählen Sie den Verschlusszeitenbereich für Ihre Kamera",
"shutterSpeedManualShort": "B",
"shutterSpeedManual": "Manuell",
"isoValues": "ISO Werte",
"isoValuesFilterDescription": "Wähle die anzuzeigenden ISO Werte aus. (Beispielsweise die Meistverwendeten)",
"isoValuesFilterDescription": "Wählen Sie verfügbare ISO-Werte",
"lensZoom": "Objektiv-Zoom",
"lensZoomDescription": "Wähle den Zoom, relativ zur Handykamera, dass mit dem Sucher der Kamera übereinstimmt.",
"lensZoomDescription": "Zoom an Kamerasucher anpassen",
"exposureOffset": "Belichtungskorrektur",
"exposureOffsetDescription": "Stellen Sie die Belichtungskorrektur ein, um die genauesten Ergebnisse für die jeweilige Kamera zu erzielen.",
"exposureOffsetDescription": "Belichtungskorrektur für genaue Ergebnisse anpassen",
"equipmentProfile": "Ausrüstungsprofil",
"equipmentProfiles": "Ausrüstungsprofile",
"tapToAdd": "Tippe zum Hinzufügen",
@ -94,7 +94,7 @@
"sourceCode": "Source code",
"reportIssue": "Problem melden",
"writeEmail": "Email schreiben",
"youDontHaveMailApp": "Es ist keine Email App installiert.",
"youDontHaveMailApp": "Keine E-Mail-App gefunden",
"copyEmail": "Email kopieren",
"version": "Version",
"versionNumber": "{version} ({buildNumber})",
@ -125,7 +125,7 @@
"featureEquipmentProfiles": "Ausrüstungsprofile",
"featureTimer": "Eingebauter Timer für Langzeitbelichtungen",
"featureMeteringScreenLayout": "Anpassbare Messansicht",
"proFeaturesSupportText": "Durch den Kauf von Lightmeter Pro unterstützen Sie den Entwickler und ermöglichen das Hinzufügen weiterer Funktionen.",
"proFeaturesSupportText": "Der Kauf von Lightmeter Pro unterstützt die Entwicklung und ermöglicht neue Funktionen",
"getNowFor": "Jetzt für {price} kaufen",
"@getNowFor": {
"price": {
@ -174,7 +174,7 @@
"note": "Notiz",
"notSet": "Nicht gesetzt",
"location": "Standort",
"noMapsAppFound": "Keine Kartenanwendung gefunden.",
"noMapsAppFound": "Keine Kartenanwendung gefunden",
"logbook": "Fototagebuch",
"noPhotos": "Keine Fotos",
"continuePurchase": "Weiter",
@ -182,12 +182,19 @@
"yearly": "Jährlich",
"lifetime": "Für immer",
"pricePerMonth": "{price}/Monat",
"pricePerYear": "{price}/Jahr",
"@pricePerMonth": {
"placeholders": {
"price": {
"type": "String"
}
}
},
"pricePerYear": "{price}/Jahr",
"@pricePerYear": {
"placeholders": {
"price": {
"type": "String"
}
}
}
}

View file

@ -1,7 +1,7 @@
{
"@@locale": "en",
"fastestExposurePair": "Fastest",
"slowestExposurePair": "Slowest",
"fastestExposurePair": "Fastest exposure",
"slowestExposurePair": "Slowest exposure",
"ev": "EV",
"evValue": "{value} EV",
"@evValue": {
@ -14,11 +14,11 @@
"iso": "ISO",
"filmSpeed": "Film sensitivity",
"nd": "ND",
"ndFilterFactor": "Neutral density filter factor",
"noExposurePairs": "There are no exposure pairs for the selected settings.",
"noCamerasDetected": "Seems like your device doesn't have any cameras connected.",
"noCameraPermission": "Camera permission is not granted.",
"otherCameraError": "An error occurred when connecting to the camera.",
"ndFilterFactor": "ND filter strength",
"noExposurePairs": "No exposure pairs available for current settings",
"noCamerasDetected": "No cameras detected on this device",
"noCameraPermission": "Camera permission is not granted",
"otherCameraError": "Camera connection error",
"none": "None",
"cancel": "Cancel",
"select": "Select",
@ -31,23 +31,23 @@
"halfStops": "1/2",
"thirdStops": "1/3",
"calibration": "Calibration",
"calibrationMessage": "The accuracy of the readings measured by this application depends entirely on the hardware of the device. Therefore, consider testing this application and setting up EV calibration values that will give you the desired measurement results.",
"calibrationMessageCameraOnly": "The accuracy of the readings measured by this application depends entirely on the rear camera of the device. Therefore, consider testing this application and setting up an EV calibration value that will give you the desired measurement results.",
"calibrationMessage": "Measurement accuracy depends on your device's hardware. Test the app and calibrate EV values for optimal results",
"calibrationMessageCameraOnly": "Measurement accuracy depends on your device's camera. Test the app and calibrate EV values for optimal results",
"camera": "Camera",
"lightSensor": "Light sensor",
"showEv100": "Show EV\u2081\u2080\u2080",
"meteringScreenLayout": "Metering screen layout",
"meteringScreenLayoutHint": "Hide elements on the metering screen that you don't need so that they don't waste exposure pairs list space.",
"meteringScreenLayoutHint": "Hide unnecessary elements to save space for exposure pairs",
"meteringScreenLayoutHintEquipmentProfiles": "Equipment profile picker",
"meteringScreenFeatureExtremeExposurePairs": "Fastest & shortest exposure pairs",
"meteringScreenFeatureFilmPicker": "Film picker",
"cameraFeatures": "Camera features",
"cameraFeatureSpotMetering": "Spot metering",
"cameraFeatureSpotMeteringHint": "Long press the camera view to remove metering spot",
"cameraFeatureSpotMeteringHint": "Long press to remove metering spot",
"cameraFeatureHistogram": "Histogram",
"cameraFeatureHistogramHint": "Enabling histogram can encrease battery drain",
"cameraFeatureHistogramHint": "May increase battery usage",
"cameraFeaturesShowFocalLength": "Show Focal Length",
"cameraFeaturesShowFocalLengthHint": "Displays 35mm equivalent focal length instead of zoom factor",
"cameraFeaturesShowFocalLengthHint": "Shows 35mm equivalent instead of zoom factor",
"film": "Film",
"filmPush": "Film (push)",
"filmPull": "Film (pull)",
@ -57,20 +57,20 @@
"equipmentProfileAllValues": "All",
"apertureValues": "Aperture values",
"apertureValue": "Aperture value",
"apertureValuesFilterDescription": "Select the range of aperture values to display. This is usually determined by the lens you are using.",
"apertureValuesFilterDescription": "Select aperture range for your lens",
"ndFilters": "ND filters",
"ndFiltersFilterDescription": "Select the ND filters to display. These may be your most commonly used ND filters or the ones that fit your lens.",
"ndFiltersFilterDescription": "Select available ND filters",
"shutterSpeedValues": "Shutter speed values",
"shutterSpeedValue": "Shutter speed value",
"shutterSpeedValuesFilterDescription": "Select the range of shutter speed values to display. This is usually determined by the camera body you are using.",
"shutterSpeedValuesFilterDescription": "Select shutter speed range for your camera",
"shutterSpeedManualShort": "B",
"shutterSpeedManual": "Manual",
"isoValues": "ISO values",
"isoValuesFilterDescription": "Select the ISO values to display. These may be your most commonly used values or those supported by your camera.",
"isoValuesFilterDescription": "Select available ISO values",
"lensZoom": "Lens zoom",
"lensZoomDescription": "Set the zoom level relative to the phone's camera to match your camera's viewfinder.",
"lensZoomDescription": "Adjust zoom to match your camera's viewfinder",
"exposureOffset": "Exposure offset",
"exposureOffsetDescription": "Set the exposure offset to get the most accurate results for the given camera.",
"exposureOffsetDescription": "Adjust exposure offset for accurate results",
"equipmentProfile": "Equipment profile",
"equipmentProfiles": "Equipment profiles",
"tapToAdd": "Tap to add",
@ -94,7 +94,7 @@
"sourceCode": "Source code",
"reportIssue": "Report an issue",
"writeEmail": "Write an email",
"youDontHaveMailApp": "You don't have any mail app installed.",
"youDontHaveMailApp": "No email app found",
"copyEmail": "Copy email",
"version": "Version",
"versionNumber": "{version} ({buildNumber})",
@ -125,7 +125,7 @@
"featureEquipmentProfiles": "Equipment profiles",
"featureTimer": "Built-in timer for long exposure",
"featureMeteringScreenLayout": "Customizable main screen",
"proFeaturesSupportText": "By purchasing Lightmeter Pro you support the development and make it possible to add new features to the app.",
"proFeaturesSupportText": "Purchasing Lightmeter Pro supports development and enables new features",
"getNowFor": "Get now for {price}",
"@getNowFor": {
"price": {
@ -174,7 +174,7 @@
"note": "Note",
"notSet": "Not set",
"location": "Location",
"noMapsAppFound": "No maps application found.",
"noMapsAppFound": "No maps application found",
"logbook": "Logbook",
"noPhotos": "No photos",
"continuePurchase": "Continue",
@ -182,12 +182,19 @@
"yearly": "Yearly",
"lifetime": "Lifetime",
"pricePerMonth": "{price}/month",
"pricePerYear": "{price}/year",
"@pricePerMonth": {
"placeholders": {
"price": {
"type": "String"
}
}
},
"pricePerYear": "{price}/year",
"@pricePerYear": {
"placeholders": {
"price": {
"type": "String"
}
}
}
}

View file

@ -1,7 +1,7 @@
{
"@@locale": "fr",
"fastestExposurePair": "Le plus rapide",
"slowestExposurePair": "Le plus lent",
"fastestExposurePair": "Plus rapide",
"slowestExposurePair": "Plus lente",
"ev": "EV",
"evValue": "{value} EV",
"@evValue": {
@ -14,11 +14,11 @@
"iso": "ISO",
"filmSpeed": "Sensibilité du film",
"nd": "ND",
"ndFilterFactor": "Facteur de filtre de densité neutre",
"noExposurePairs": "Il n'y a pas de paires d'exposition pour les réglages sélectionnés.",
"noCamerasDetected": "Il semble que votre appareil n'a pas de caméras connectées.",
"noCameraPermission": "L'accès à la caméra n'est pas accordé.",
"otherCameraError": "Une erreur s'est produite lors de la connexion à la caméra.",
"ndFilterFactor": "Densité du filtre ND",
"noExposurePairs": "Aucune paire d'exposition disponible pour ces réglages",
"noCamerasDetected": "Aucune caméra détectée",
"noCameraPermission": "L'accès à la caméra n'est pas accordé",
"otherCameraError": "Erreur de connexion caméra",
"none": "Aucun",
"cancel": "Annuler",
"select": "Sélectionner",
@ -31,23 +31,23 @@
"halfStops": "1/2",
"thirdStops": "1/3",
"calibration": "Calibration",
"calibrationMessage": "La précision des lectures mesurées par cette application dépend entièrement du matériel de l'appareil. Par conséquent, envisagez de tester cette application et de configurer les valeurs d'étalonnage des EV qui vous donneront les résultats de mesure souhaités.",
"calibrationMessageCameraOnly": "La précision des lectures mesurées par cette application dépend entièrement de la caméra arrière de l'appareil. Par conséquent, envisagez de tester cette application et de configurer une valeur d'étalonnage EV qui vous donnera les résultats de mesure souhaités.",
"calibrationMessage": "La précision dépend du matériel de l'appareil. Testez l'app et calibrez les valeurs EV pour de meilleurs résultats",
"calibrationMessageCameraOnly": "La précision dépend de la caméra de l'appareil. Testez l'app et calibrez les valeurs EV pour de meilleurs résultats",
"camera": "Caméra",
"lightSensor": "Capteur de lumière",
"showEv100": "Montrer EV\u2081\u2080\u2080",
"meteringScreenLayout": "Disposition de l'écran de mesure",
"meteringScreenLayoutHint": "Masquer les éléments sur l'écran de mesure dont vous n'avez pas besoin pour qu'ils ne gaspillent pas de l'espace dans les paires d'exposition.",
"meteringScreenLayoutHint": "Masquez les éléments inutiles pour économiser l'espace",
"meteringScreenLayoutHintEquipmentProfiles": "Sélecteur de profil de l'équipement",
"meteringScreenFeatureExtremeExposurePairs": "Paires d'exposition les plus rapides et les plus courtes",
"meteringScreenFeatureFilmPicker": "Sélecteur de film",
"cameraFeatures": "Fonctionnalités de la caméra",
"cameraFeatureSpotMetering": "Mesure spot",
"cameraFeatureSpotMeteringHint": "Appuyez longuement sur la vue de l'appareil photo pour supprimer le spot de mesure",
"cameraFeatureSpotMeteringHint": "Appui long pour supprimer le point de mesure",
"cameraFeatureHistogram": "Histogramme",
"cameraFeatureHistogramHint": "L'activation de l'histogramme peut augmenter la consommation de la batterie",
"cameraFeatureHistogramHint": "Peut augmenter la consommation de batterie",
"cameraFeaturesShowFocalLength": "Afficher la focale",
"cameraFeaturesShowFocalLengthHint": "Affiche la focale équivalente 35 mm au lieu du facteur de zoom",
"cameraFeaturesShowFocalLengthHint": "Équivalent 35mm au lieu du zoom",
"film": "Pellicule",
"filmPush": "Pellicule (push)",
"filmPull": "Pellicule (pull)",
@ -57,20 +57,20 @@
"equipmentProfileAllValues": "Tout",
"apertureValues": "Valeurs Aperture",
"apertureValue": "Valeur Aperture",
"apertureValuesFilterDescription": "Sélectionnez la plage de valeurs d'ouverture à afficher. Cela est généralement déterminé par l'objectif que vous utilisez.",
"apertureValuesFilterDescription": "Sélectionnez la plage d'ouverture pour votre objectif",
"ndFilters": "Filtres ND",
"ndFiltersFilterDescription": "Sélectionnez les filtres ND à afficher. Ce sont peut-être vos filtres ND les plus couramment utilisés ou ceux qui correspondent à votre lentille.",
"ndFiltersFilterDescription": "Sélectionnez les filtres ND disponibles",
"shutterSpeedValues": "Valeurs de la vitesse d'obturation",
"shutterSpeedValue": "Valeur de la vitesse d'obturation",
"shutterSpeedValuesFilterDescription": "Sélectionnez la plage de valeurs de vitesse d'obturation à afficher. Cela est généralement déterminé par le corps de l'appareil que vous utilisez.",
"shutterSpeedValuesFilterDescription": "Sélectionnez la plage de vitesses pour votre appareil",
"shutterSpeedManualShort": "B",
"shutterSpeedManual": "Manuelle",
"isoValues": "Valeurs ISO",
"isoValuesFilterDescription": "Sélectionnez les valeurs ISO à afficher. Ce sont peut-être vos valeurs les plus couramment utilisées ou celles prises en charge par votre caméra.",
"isoValuesFilterDescription": "Sélectionnez les valeurs ISO disponibles",
"lensZoom": "Zoom sur l'objectif",
"lensZoomDescription": "Réglez le niveau de zoom par rapport à l'appareil photo du téléphone pour qu'il corresponde au viseur de votre appareil photo.",
"lensZoomDescription": "Ajustez le zoom pour correspondre au viseur",
"exposureOffset": "Décalage dexposition",
"exposureOffsetDescription": "Définissez le décalage dexposition pour obtenir les résultats les plus précis selon lappareil photo.",
"exposureOffsetDescription": "Ajustez l'offset d'exposition pour des résultats précis",
"equipmentProfile": "Profil de l'équipement",
"equipmentProfiles": "Profils de l'équipement",
"tapToAdd": "Appuie pour ajouter",
@ -94,7 +94,7 @@
"sourceCode": "Code source",
"reportIssue": "Rapporter un problème",
"writeEmail": "Écrire un email",
"youDontHaveMailApp": "Vous n'avez installé aucune application de messagerie.",
"youDontHaveMailApp": "Aucune app email trouvée",
"copyEmail": "Copier un e-mail",
"version": "Version",
"versionNumber": "{version} ({buildNumber})",
@ -113,7 +113,7 @@
"unlock": "Déverrouiller",
"featuresFree": "Gratuit",
"featuresPro": "Pro",
"proFeaturesPromoText": "Lightmeter Pro offre tout ce dont vous avez besoin pour obtenir les meilleurs clichés!",
"proFeaturesPromoText": "Lightmeter Pro offre tout ce dont vous avez besoin pour obtenir les meilleurs clichés !",
"proFeaturesWhatsIncluded": "Qu'est-ce qui est inclus?",
"featureReflectedLightMetering": "Mesure de la lumière réfléchie",
"featureIncidentLightMetering": "Mesure de la lumière incidente",
@ -126,7 +126,7 @@
"featureEquipmentProfiles": "Profils de l'équipement",
"featureTimer": "Minuteur intégré pour longues expositions",
"featureMeteringScreenLayout": "Écran principal personnalisable",
"proFeaturesSupportText": "En achetant Lightmeter Pro, vous soutenez le développement et permettez l'ajout de nouvelles fonctionnalités à l'application.",
"proFeaturesSupportText": "L'achat de Lightmeter Pro soutient le développement et permet de nouvelles fonctionnalités",
"getNowFor": "Acheter maintenant {price}",
"@getNowFor": {
"price": {
@ -148,6 +148,16 @@
"tooltipUseCamera": "Utiliser la caméra",
"tooltipOpenSettings": "Ouvrir les paramètres",
"exposurePair": "Paire d'exposition",
"whatsnew": "Quoi de neuf ?",
"changesInVersion": "Changements dans la version {version} :",
"@changesInVersion": {
"placeholders": {
"version": {
"type": "String"
}
}
},
"close": "Fermer",
"films": "Films",
"filmsInUse": "Films en usage",
"filmsCustom": "Films personnalisés",
@ -157,7 +167,7 @@
"filmFormulaExponential": "T=t^Rf",
"filmFormulaExponentialRf": "Rf",
"filmFormulaExponentialRfPlaceholder": "1.3",
"name": "Titre",
"name": "Nom",
"addEquipmentProfileTitle": "Ajouter un profil",
"editEquipmentProfileTitle": "Editer le profil",
"editPhotoTitle": "Modifier la photo",
@ -165,7 +175,7 @@
"note": "Note",
"notSet": "Non défini",
"location": "Emplacement",
"noMapsAppFound": "Aucune application de cartes trouvée.",
"noMapsAppFound": "Aucune application de cartes trouvée",
"logbook": "Carnet photo",
"noPhotos": "Aucune photo",
"continuePurchase": "Continuer",
@ -173,12 +183,19 @@
"yearly": "Annuel",
"lifetime": "Pour toujours",
"pricePerMonth": "{price}/mois",
"pricePerYear": "{price}/an",
"@pricePerMonth": {
"placeholders": {
"price": {
"type": "String"
}
}
},
"pricePerYear": "{price}/an",
"@pricePerYear": {
"placeholders": {
"price": {
"type": "String"
}
}
}
}

200
lib/l10n/intl_pl.arb Normal file
View file

@ -0,0 +1,200 @@
{
"@@locale": "pl",
"fastestExposurePair": "Najszybsza",
"slowestExposurePair": "Najwolniejsza",
"ev": "EV",
"evValue": "{value} EV",
"@evValue": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"iso": "ISO",
"filmSpeed": "Czułość filmu",
"nd": "ND",
"ndFilterFactor": "Siła filtra ND",
"noExposurePairs": "Brak dostępnych par ekspozycji dla bieżących ustawień",
"noCamerasDetected": "Nie wykryto aparatu na tym urządzeniu",
"noCameraPermission": "Brak uprawnień do kamery",
"otherCameraError": "Błąd połączenia z kamerą",
"none": "Brak",
"cancel": "Anuluj",
"select": "Wybierz",
"save": "Zapisz",
"saveNewPhotos": "Zapisuj nowe zdjęcia",
"settings": "Ustawienia",
"metering": "Pomiar",
"fractionalStops": "Wartości ułamkowe",
"showFractionalStops": "Pokaż wartości ułamkowe",
"halfStops": "1/2",
"thirdStops": "1/3",
"calibration": "Kalibracja",
"calibrationMessage": "Dokładność pomiaru zależy od sprzętu urządzenia. Przetestuj aplikację i skalibruj wartości EV dla optymalnych wyników",
"calibrationMessageCameraOnly": "Dokładność pomiaru zależy od kamery urządzenia. Przetestuj aplikację i skalibruj wartości EV dla optymalnych wyników",
"camera": "Kamera",
"lightSensor": "Czujnik światła",
"showEv100": "Pokaż EV\u2081\u2080\u2080",
"meteringScreenLayout": "Układ ekranu pomiaru",
"meteringScreenLayoutHint": "Ukryj niepotrzebne elementy, aby zaoszczędzić miejsce na pary ekspozycji",
"meteringScreenLayoutHintEquipmentProfiles": "Wybór profilu sprzętu",
"meteringScreenFeatureExtremeExposurePairs": "Najszybsze i najkrótsze pary ekspozycji",
"meteringScreenFeatureFilmPicker": "Wybór filmu",
"cameraFeatures": "Funkcje kamery",
"cameraFeatureSpotMetering": "Pomiar punktowy",
"cameraFeatureSpotMeteringHint": "Długie naciśnięcie aby usunąć punkt pomiaru",
"cameraFeatureHistogram": "Histogram",
"cameraFeatureHistogramHint": "Może zwiększyć zużycie baterii",
"cameraFeaturesShowFocalLength": "Pokaż ogniskową",
"cameraFeaturesShowFocalLengthHint": "Pokazuje ekwiwalent 35mm zamiast współczynnika zoomu",
"film": "Film",
"filmPush": "Film (push)",
"filmPull": "Film (pull)",
"filmReciprocityHint": "Stosuje korekcję dla czasów naświetlania dłuższych niż 1 sekunda",
"equipmentProfileName": "Nazwa profilu sprzętu",
"equipmentProfileNameHint": "Praktica MTL5B",
"equipmentProfileAllValues": "Wszystkie",
"apertureValues": "Wartości przysłony",
"apertureValue": "Wartość przysłony",
"apertureValuesFilterDescription": "Wybierz zakres przysłony dla swojego obiektywu",
"ndFilters": "Filtry ND",
"ndFiltersFilterDescription": "Wybierz dostępne filtry ND",
"shutterSpeedValues": "Czasy naświetlania",
"shutterSpeedValue": "Czas naświetlania",
"shutterSpeedValuesFilterDescription": "Wybierz zakres czasów naświetlania dla swojej kamery",
"shutterSpeedManualShort": "B",
"shutterSpeedManual": "Ręczny",
"isoValues": "Wartości ISO",
"isoValuesFilterDescription": "Wybierz dostępne wartości ISO",
"lensZoom": "Zoom obiektywu",
"lensZoomDescription": "Dostosuj zoom aby dopasować do wizjera kamery",
"exposureOffset": "Kompensacja ekspozycji",
"exposureOffsetDescription": "Dostosuj kompensację ekspozycji dla dokładnych wyników",
"equipmentProfile": "Sprzęt",
"equipmentProfiles": "Sprzęt",
"tapToAdd": "Dotknij aby dodać",
"general": "Ogólne",
"keepScreenOn": "Utrzymuj ekran włączony",
"haptics": "Wibracje",
"autostartTimer": "Automatyczne uruchomienie timera",
"volumeKeysAction": "Migawka przyciskami głośności",
"language": "Język",
"chooseLanguage": "Wybierz język",
"theme": "Motyw",
"chooseTheme": "Wybierz motyw",
"themeLight": "Jasny",
"themeDark": "Ciemny",
"themeSystemDefault": "Systemowy",
"dynamicColor": "Kolor dynamiczny",
"primaryColor": "Kolor główny",
"choosePrimaryColor": "Wybierz kolor główny",
"about": "O aplikacji",
"restorePurchases": "Przywróć zakupy",
"sourceCode": "Kod źródłowy",
"reportIssue": "Zgłoś problem",
"writeEmail": "Napisz email",
"youDontHaveMailApp": "Nie znaleziono aplikacji email",
"copyEmail": "Kopiuj email",
"version": "Wersja",
"versionNumber": "{version} ({buildNumber})",
"@versionNumber": {
"placeholders": {
"version": {
"type": "String"
},
"buildNumber": {
"type": "String"
}
}
},
"proFeaturesTitle": "Lightmeter Pro",
"getPro": "Kup Pro",
"featuresFree": "Darmowe",
"featuresPro": "Pro",
"proFeaturesPromoText": "Lightmeter Pro zapewnia wszystko czego potrzebujesz do najlepszych zdjęć!",
"proFeaturesWhatsIncluded": "Co jest zawarte?",
"featureReflectedLightMetering": "Pomiar światła odbitego",
"featureIncidentLightMetering": "Pomiar światła padającego",
"featureIsoAndNdValues": "Szeroki zakres wartości ISO i filtrów ND",
"featureTheme": "Personalizacja motywu",
"featureSpotMeteringAndHistorgram": "Pomiar punktowy i histogram",
"featureFocalLength35mm": "Ekwiwalent ogniskowej 35mm zamiast zoomu",
"featureListOfFilms": "Lista 20+ filmów z formułami wzajemności",
"featureCustomFilms": "Możliwość tworzenia własnych filmów",
"featureEquipmentProfiles": "Profile sprzętu",
"featureTimer": "Wbudowany timer do długich ekspozycji",
"featureMeteringScreenLayout": "Konfigurowalny ekran główny",
"proFeaturesSupportText": "Kupując Lightmeter Pro wspierasz rozwój i umożliwiasz nowe funkcje",
"getNowFor": "Kup teraz za {price}",
"@getNowFor": {
"placeholders": {
"price": {
"type": "String"
}
}
},
"tooltipAdd": "Dodaj",
"tooltipClose": "Zamknij",
"tooltipExpand": "Rozwiń",
"tooltipCollapse": "Zwiń",
"tooltipCopy": "Kopiuj",
"tooltipDelete": "Usuń",
"tooltipSelectAll": "Zaznacz wszystko",
"tooltipDesecelectAll": "Odznacz wszystko",
"tooltipResetToZero": "Resetuj do zera",
"tooltipUseLightSensor": "Użyj czujnika światła",
"tooltipUseCamera": "Użyj kamery",
"tooltipOpenSettings": "Otwórz ustawienia",
"exposurePair": "Para ekspozycji",
"whatsnew": "Co nowego?",
"changesInVersion": "Zmiany w wersji {version}:",
"@changesInVersion": {
"placeholders": {
"version": {
"type": "String"
}
}
},
"close": "Zamknij",
"films": "Filmy",
"filmsInUse": "Używane filmy",
"filmsCustom": "Własne filmy",
"addFilmTitle": "Dodaj film",
"editFilmTitle": "Edytuj film",
"filmFormula": "Formuła",
"filmFormulaExponential": "T=t^Rf",
"filmFormulaExponentialRf": "Rf",
"filmFormulaExponentialRfPlaceholder": "1.3",
"name": "Nazwa",
"addEquipmentProfileTitle": "Dodaj sprzęt",
"editEquipmentProfileTitle": "Edytuj sprzęt",
"editPhotoTitle": "Edytuj zdjęcie",
"ndFilter": "Filtr ND",
"note": "Notatka",
"notSet": "Nie ustawiono",
"location": "Lokalizacja",
"noMapsAppFound": "Nie znaleziono aplikacji map",
"logbook": "Dziennik",
"noPhotos": "Brak zdjęć",
"continuePurchase": "Kontynuuj",
"monthly": "Miesięcznie",
"yearly": "Rocznie",
"lifetime": "Dożywotnie",
"pricePerMonth": "{price}/miesiąc",
"@pricePerMonth": {
"placeholders": {
"price": {
"type": "String"
}
}
},
"pricePerYear": "{price}/rok",
"@pricePerYear": {
"placeholders": {
"price": {
"type": "String"
}
}
}
}

View file

@ -15,15 +15,15 @@
"filmSpeed": "Чувствительность плёнки",
"nd": "ND",
"ndFilterFactor": "Степень затемнения нейтрального фильтра",
"noExposurePairs": "Для выбранных настроек нет пар экспозиции.",
"noCamerasDetected": "Похоже, ваше устройство не имеет камеры.",
"noCameraPermission": "Нет разрешения на доступ к камере.",
"otherCameraError": "Произошла ошибка при подключении к камере.",
"noExposurePairs": "Для выбранных настроек нет доступных пар экспозиции",
"noCamerasDetected": "Камера на устройстве не обнаружена",
"noCameraPermission": "Отсутствует разрешение на использование камеры.",
"otherCameraError": "Произошла ошибка при работе с камерой",
"none": "Нет",
"cancel": "Отменить",
"select": "Выбрать",
"save": "Сохранить",
"saveNewPhotos": "Сохранять новые фото",
"saveNewPhotos": "Сохранять новые фотографии",
"settings": "Настройки",
"metering": "Измерения",
"fractionalStops": "Дробные значения",
@ -37,17 +37,17 @@
"lightSensor": "Датчик освещённости",
"showEv100": "Показывать EV\u2081\u2080\u2080",
"meteringScreenLayout": "Элементы главного экрана",
"meteringScreenLayoutHint": "Здесь вы можете скрыть некоторые ненужные или неиспользуемые элементы с главного экрана.",
"meteringScreenLayoutHint": "Вы можете скрыть ненужные элементы с главного экрана для экономии места.",
"meteringScreenLayoutHintEquipmentProfiles": "Выбор профиля оборудования",
"meteringScreenFeatureExtremeExposurePairs": "Длинная и короткая выдержки",
"meteringScreenFeatureFilmPicker": "Выбор пленки",
"cameraFeatures": "Возможности камеры",
"cameraFeatureSpotMetering": "Точечный замер",
"cameraFeatureSpotMeteringHint": "Используйте долгое нажатие, чтобы удалить точку замера",
"cameraFeatureSpotMeteringHint": "Для удаления точки замера используйте долгое нажатие",
"cameraFeatureHistogram": "Гистограмма",
"cameraFeatureHistogramHint": "Использование гистограммы может увеличить расход аккумулятора",
"cameraFeatureHistogramHint": "Включение гистограммы может увеличить расход батареи",
"cameraFeaturesShowFocalLength": "Показать фокусное расстояние",
"cameraFeaturesShowFocalLengthHint": "Показывает эквивалент фокусного расстояния (35 мм) вместо коэффициента зума",
"cameraFeaturesShowFocalLengthHint": "Показывает 35-мм эквивалент фокусного расстояния вместо зума",
"film": "Пленка",
"filmPush": "Пленка (push)",
"filmPull": "Пленка (pull)",
@ -57,28 +57,28 @@
"equipmentProfileAllValues": "Все",
"apertureValues": "Значения диафрагмы",
"apertureValue": "Значение диафрагмы",
"apertureValuesFilterDescription": "Выберите диапазон значений диафрагмы для отображения. Обычно определяется объективом, который вы используете.",
"apertureValuesFilterDescription": "Выберите диапазон диафрагмы для вашего объектива",
"ndFilters": "ND фильтры",
"ndFiltersFilterDescription": "Выберите ND фильтры для отображения. Это могут быть наиболее часто используемые ND фильтры или фильтры, подходящие под ваш объектив.",
"ndFiltersFilterDescription": "Выберите доступные ND фильтры",
"shutterSpeedValues": "Значения выдержки",
"shutterSpeedValue": "Значение выдержки",
"shutterSpeedValuesFilterDescription": "Выберите диапазон значений выдержки. Обычно ограничивается возможностями вашей камеры.",
"shutterSpeedValuesFilterDescription": "Выберите диапазон выдержек для вашей камеры",
"shutterSpeedManualShort": "B",
"shutterSpeedManual": "Ручная",
"isoValues": "Значения ISO",
"isoValuesFilterDescription": "Выберите значения ISO для отображения. Это может быть наиболее часто используемые значения или значения, поддерживаемые вашей камерой.",
"isoValuesFilterDescription": "Выберите доступные значения ISO",
"lensZoom": "Зум объектива",
"lensZoomDescription": "Установите уровень зума относительно камеры телефона, чтобы он соответствовал видоискателю вашей камеры.",
"lensZoomDescription": "Настройте зум относительно камеры телефона для соответствия видоискателю камеры",
"exposureOffset": "Смещение экспозиции",
"exposureOffsetDescription": "Установите смещение экспозиции для получения наиболее точных результатов с данной камерой.",
"exposureOffsetDescription": "Настройте смещение экспозиции для получения точных результатов с вашей камерой",
"equipmentProfile": "Оборудование",
"equipmentProfiles": "Профили оборудования",
"tapToAdd": "Нажмите, чтобы добавить",
"general": "Общие",
"keepScreenOn": "Запрет блокировки",
"keepScreenOn": "Оставлять экран включенным",
"haptics": "Вибрация",
"autostartTimer": "Автозапуск таймера",
"volumeKeysAction": "Затвор по кнопкам громкости",
"volumeKeysAction": "Спуск затвора кнопками громкости",
"language": "Язык",
"chooseLanguage": "Выберите язык",
"theme": "Тема",
@ -94,7 +94,7 @@
"sourceCode": "Исходный код",
"reportIssue": "Сообщить о проблеме",
"writeEmail": "Написать на почту",
"youDontHaveMailApp": "У вас не установлено почтовое приложение.",
"youDontHaveMailApp": "На устройстве не установлено почтовое приложение",
"copyEmail": "Скопировать адрес",
"version": "Версия",
"versionNumber": "{version} ({buildNumber})",
@ -125,7 +125,7 @@
"featureEquipmentProfiles": "Профили оборудования",
"featureTimer": "Встроенный таймер для длинных выдержек",
"featureMeteringScreenLayout": "Настраиваемый главный экран",
"proFeaturesSupportText": "Покупая Lightmeter Pro, вы поддерживаете разработку и делаете возможным добавление новых функций в приложение.",
"proFeaturesSupportText": "Покупая Lightmeter Pro, вы поддерживаете разработку и помогаете добавлять новые функции",
"getNowFor": "Купить за {price}",
"@getNowFor": {
"price": {
@ -141,12 +141,22 @@
"tooltipCopy": "Скопировать",
"tooltipDelete": "Удалить",
"tooltipSelectAll": "Выбрать все",
"tooltipDesecelectAll": "Отменить все",
"tooltipResetToZero": "Сбросить до 0",
"tooltipDesecelectAll": "Снять все выделения",
"tooltipResetToZero": "Сбросить в ноль",
"tooltipUseLightSensor": "Использовать датчик освещенности",
"tooltipUseCamera": "Использовать камеру",
"tooltipOpenSettings": "Открыть настройки",
"exposurePair": "Пара экспозиции",
"whatsnew": "Что нового?",
"changesInVersion": "Изменения в версии {version}:",
"@changesInVersion": {
"placeholders": {
"version": {
"type": "String"
}
}
},
"close": "Закрыть",
"films": "Плёнки",
"filmsInUse": "Используемые плёнки",
"filmsCustom": "Пользовательские плёнки",
@ -164,7 +174,7 @@
"note": "Заметка",
"notSet": "Не задано",
"location": "Местоположение",
"noMapsAppFound": "Приложение карт не найдено.",
"noMapsAppFound": "На устройстве не найдено приложение карт",
"logbook": "Фотожурнал",
"noPhotos": "Нет фотографий",
"continuePurchase": "Продолжить",
@ -172,12 +182,19 @@
"yearly": "Ежегодно",
"lifetime": "Навсегда",
"pricePerMonth": "{price}/месяц",
"pricePerYear": "{price}/год",
"@pricePerMonth": {
"placeholders": {
"price": {
"type": "String"
}
}
},
"pricePerYear": "{price}/год",
"@pricePerYear": {
"placeholders": {
"price": {
"type": "String"
}
}
}
}
}

View file

@ -1,7 +1,7 @@
{
"@@locale": "zh",
"fastestExposurePair": "最快曝光组合",
"slowestExposurePair": "最慢曝光组合",
"fastestExposurePair": "最快",
"slowestExposurePair": "最慢",
"ev": "EV",
"evValue": "{value} EV",
"@evValue": {
@ -14,11 +14,11 @@
"iso": "ISO",
"filmSpeed": "胶片感光度",
"nd": "ND",
"ndFilterFactor": "ND 滤镜系数",
"noExposurePairs": "所选设置没有曝光配对",
"noCamerasDetected": "您的设备似乎没有连接到任何摄像头",
"ndFilterFactor": "ND 滤镜强度",
"noExposurePairs": "当前设置无可用曝光组合",
"noCamerasDetected": "未检测到摄像头",
"noCameraPermission": "未获得摄像头权限",
"otherCameraError": "连接摄像头时发生错误",
"otherCameraError": "摄像头连接错误",
"none": "无",
"cancel": "取消",
"select": "选择",
@ -31,23 +31,23 @@
"halfStops": "1/2",
"thirdStops": "1/3",
"calibration": "校准",
"calibrationMessage": "此应用测量读数的准确性取决于设备的后置摄像头。如需更精确的测量结果或测量结果存在偏差,请手动校准 EV 。",
"calibrationMessageCameraOnly": "此应用测量读数的准确性取决于设备的后置摄像头。如需更精确的测量结果或测量结果存在偏差,请手动校准 EV 。",
"calibrationMessage": "测量精度取决于设备硬件。请测试并校准 EV 值以获得最佳结果。",
"calibrationMessageCameraOnly": "测量精度取决于设备摄像头。请测试并校准 EV 值以获得最佳结果。",
"camera": "相机",
"lightSensor": "光线传感器",
"showEv100": "显示 EV\u2081\u2080\u2080",
"meteringScreenLayout": "布局",
"meteringScreenLayoutHint": "隐藏不需要的元素,让主界面更加整洁",
"meteringScreenLayoutHint": "隐藏不需要的元素以节省空间",
"meteringScreenLayoutHintEquipmentProfiles": "选择设备配置",
"meteringScreenFeatureExtremeExposurePairs": "最快 & 最慢曝光组合",
"meteringScreenFeatureFilmPicker": "胶片选择",
"cameraFeatures": "相机功能",
"cameraFeatureSpotMetering": "点测光",
"cameraFeatureSpotMeteringHint": "长按相机视图可移除测光点",
"cameraFeatureSpotMeteringHint": "长按移除测光点",
"cameraFeatureHistogram": "直方图",
"cameraFeatureHistogramHint": "启用直方图会增加电池消耗",
"cameraFeatureHistogramHint": "可能增加电池消耗",
"cameraFeaturesShowFocalLength": "显示焦距",
"cameraFeaturesShowFocalLengthHint": "显示 35mm 等效焦距而非变焦倍数",
"cameraFeaturesShowFocalLengthHint": "35mm 等效焦距而非变焦倍数",
"film": "胶片",
"filmPush": "胶片 (push)",
"filmPull": "胶片 (pull)",
@ -57,20 +57,20 @@
"equipmentProfileAllValues": "全部",
"apertureValues": "光圈值",
"apertureValue": "光圈值",
"apertureValuesFilterDescription": "选择要显示的光圈值范围。取决于使用的镜头。",
"apertureValuesFilterDescription": "选择镜头光圈范围",
"ndFilters": "ND 滤镜",
"ndFiltersFilterDescription": "选择要显示的 ND 滤镜系数。取决于使用的 ND 滤镜",
"ndFiltersFilterDescription": "选择用的 ND 滤镜",
"shutterSpeedValues": "快门速度",
"shutterSpeedValue": "快门速度",
"shutterSpeedValuesFilterDescription": "选择要显示的快门速度范围。取决于相机机身。",
"shutterSpeedValuesFilterDescription": "选择相机快门范围",
"shutterSpeedManualShort": "B门",
"shutterSpeedManual": "手动",
"isoValues": "ISO",
"isoValuesFilterDescription": "选择要显示的 ISO 范围。",
"isoValuesFilterDescription": "选择可用的 ISO 值",
"lensZoom": "镜头变焦",
"lensZoomDescription": "设置相对于手机摄像头的变焦焦距,使其与相机取景相匹配。",
"lensZoomDescription": "调整变焦以匹配相机取景器",
"exposureOffset": "曝光补偿",
"exposureOffsetDescription": "设置曝光补偿,以获得针对所用相机的最准确结果。",
"exposureOffsetDescription": "调整曝光补偿以获得准确结果",
"equipmentProfile": "设备配置",
"equipmentProfiles": "设备配置",
"tapToAdd": "点击添加",
@ -94,7 +94,7 @@
"sourceCode": "源代码",
"reportIssue": "报告问题",
"writeEmail": "Email",
"youDontHaveMailApp": "您没有安装任何邮件App。",
"youDontHaveMailApp": "未找到邮件应用",
"copyEmail": "复制电子邮件",
"version": "Version",
"versionNumber": "{version} ({buildNumber})",
@ -124,7 +124,7 @@
"featureEquipmentProfiles": "设备配置文件",
"featureTimer": "内置长曝光计时器",
"featureMeteringScreenLayout": "可自定义的主界面",
"proFeaturesSupportText": "通过购买Lightmeter Pro支持软件的开发让软件持续添加新功能",
"proFeaturesSupportText": "购买 Lightmeter Pro 支持开发并启用新功能",
"getNowFor": "立即获取 {price}",
"@getNowFor": {
"price": {
@ -141,12 +141,22 @@
"tooltipDelete": "删除",
"tooltipSelectAll": "全选",
"tooltipDesecelectAll": "取消全选",
"resetToZero": "重置为零",
"tooltipResetToZero": "重置为零",
"tooltipUseLightSensor": "使用光线传感器",
"tooltipUseCamera": "使用摄像头",
"tooltipOpenSettings": "打开设置",
"exposurePair": "曝光对",
"films": "Films",
"whatsnew": "有什么新功能?",
"changesInVersion": "版本 {version} 的更改:",
"@changesInVersion": {
"placeholders": {
"version": {
"type": "String"
}
}
},
"close": "关闭",
"films": "胶片",
"filmsInUse": "使用的胶片",
"filmsCustom": "自定义胶片",
"addFilmTitle": "添加胶片",
@ -155,6 +165,7 @@
"filmFormulaExponential": "T=t^Rf",
"filmFormulaExponentialRf": "Rf",
"filmFormulaExponentialRfPlaceholder": "1.3",
"name": "名称",
"addEquipmentProfileTitle": "添加设备",
"editEquipmentProfileTitle": "编辑设备",
"editPhotoTitle": "编辑照片",
@ -162,7 +173,7 @@
"note": "备注",
"notSet": "未设置",
"location": "位置",
"noMapsAppFound": "未找到地图应用程序",
"noMapsAppFound": "未找到地图应用程序",
"logbook": "拍照日志",
"noPhotos": "没有照片",
"continuePurchase": "继续",
@ -170,12 +181,19 @@
"yearly": "年付",
"lifetime": "永久",
"pricePerMonth": "{price}/月",
"pricePerYear": "{price}/年",
"@pricePerMonth": {
"placeholders": {
"price": {
"type": "String"
}
}
},
"pricePerYear": "{price}/年",
"@pricePerYear": {
"placeholders": {
"price": {
"type": "String"
}
}
}
}

View file

@ -6,6 +6,7 @@ import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/equipment_profile_edit/flow_equipment_profile_edit.dart';
import 'package:lightmeter/screens/shared/sliver_placeholder/widget_sliver_placeholder.dart';
import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart';
import 'package:lightmeter/utils/guard_pro_tap.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
class EquipmentProfilesScreen extends StatefulWidget {
@ -41,9 +42,14 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> with
}
void _addProfile() {
Navigator.of(context).pushNamed(
NavigationRoutes.equipmentProfileEditScreen.name,
arguments: const EquipmentProfileEditArgs(editType: EquipmentProfileEditType.add),
guardProTap(
context,
() {
Navigator.of(context).pushNamed(
NavigationRoutes.equipmentProfileEditScreen.name,
arguments: const EquipmentProfileEditArgs(editType: EquipmentProfileEditType.add),
);
},
);
}

View file

@ -107,24 +107,18 @@ class _Products extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
if (monthly case final monthly?)
Padding(
padding: const EdgeInsets.only(bottom: Dimens.paddingS),
child: _ProductItem(
title: S.of(context).monthly,
price: S.of(context).pricePerMonth(monthly.price),
isSelected: selected == monthly,
onPressed: () => onProductSelected(monthly),
),
_ProductItem(
title: S.of(context).monthly,
price: S.of(context).pricePerMonth(monthly.price),
isSelected: selected == monthly,
onPressed: () => onProductSelected(monthly),
),
if (yearly case final yearly?)
Padding(
padding: const EdgeInsets.only(bottom: Dimens.paddingS),
child: _ProductItem(
title: S.of(context).yearly,
price: S.of(context).pricePerYear(yearly.price),
isSelected: selected == yearly,
onPressed: () => onProductSelected(yearly),
),
_ProductItem(
title: S.of(context).yearly,
price: S.of(context).pricePerYear(yearly.price),
isSelected: selected == yearly,
onPressed: () => onProductSelected(yearly),
),
if (lifetime case final lifetime?)
_ProductItem(
@ -133,7 +127,7 @@ class _Products extends StatelessWidget {
isSelected: selected == lifetime,
onPressed: () => onProductSelected(lifetime),
),
],
].intersperse(const SizedBox(height: Dimens.grid8)).toList(growable: false),
);
}
}
@ -220,3 +214,16 @@ class _ProductAnimatedText extends StatelessWidget {
);
}
}
extension on List<Widget> {
Iterable<Widget> intersperse(Widget element) sync* {
final iterator = this.iterator;
if (iterator.moveNext()) {
yield iterator.current;
while (iterator.moveNext()) {
yield element;
yield iterator.current;
}
}
}
}

View file

@ -256,10 +256,7 @@ class _FeatureHighlight extends StatelessWidget {
).width +
Dimens.paddingM * 2,
),
padding: const EdgeInsets.symmetric(
horizontal: Dimens.paddingM,
vertical: Dimens.paddingS,
),
padding: const EdgeInsets.symmetric(vertical: Dimens.paddingS),
decoration: BoxDecoration(
color: highlight ? Theme.of(context).colorScheme.secondaryContainer : null,
borderRadius: roundedTop
@ -274,7 +271,7 @@ class _FeatureHighlight extends StatelessWidget {
)
: null,
),
child: child,
child: Center(child: child),
);
}
}

View file

@ -7,6 +7,8 @@ import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/logbook_photos/components/grid_tile/widget_grid_tile_logbook_photo.dart';
import 'package:lightmeter/screens/shared/icon_placeholder/widget_icon_placeholder.dart';
import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart';
import 'package:lightmeter/utils/context_utils.dart';
import 'package:lightmeter/utils/guard_pro_tap.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
class LogbookPhotosScreen extends StatefulWidget {
@ -30,8 +32,15 @@ class _LogbookPhotosScreenState extends State<LogbookPhotosScreen> with SingleTi
child: SwitchListTile(
secondary: const Icon(Icons.book_outlined),
title: Text(S.of(context).saveNewPhotos),
value: LogbookPhotos.isEnabledOf(context),
onChanged: LogbookPhotosProvider.of(context).saveLogbookPhotos,
value: LogbookPhotos.isEnabledOf(context) && context.isPro,
onChanged: (value) {
guardProTap(
context,
() {
Navigator.of(context).pushNamed(NavigationRoutes.proFeaturesScreen.name);
},
);
},
),
),
),

View file

@ -4,7 +4,6 @@ import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/screens/shared/animated_circular_button/widget_button_circular_animated.dart';
import 'package:lightmeter/screens/shared/bottom_controls_bar/widget_bottom_controls_bar.dart';
import 'package:lightmeter/utils/context_utils.dart';
class MeteringBottomControls extends StatelessWidget {
final double? ev;
@ -76,7 +75,7 @@ class _EvValueText extends StatelessWidget {
}
String _text(BuildContext context) {
final bool showEv100 = context.isPro && UserPreferencesProvider.showEv100Of(context);
final bool showEv100 = UserPreferencesProvider.showEv100Of(context);
final StringBuffer buffer = StringBuffer()
..writeAll([
(showEv100 ? ev100 : ev).toStringAsFixed(1),

View file

@ -1,35 +1,56 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/camera_feature.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/services_provider.dart';
import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/screens/settings/components/shared/dialog_switch/widget_dialog_switch.dart';
import 'package:lightmeter/screens/settings/components/shared/iap_list_tile/widget_list_tile_iap.dart';
class CameraFeaturesListTile extends StatelessWidget {
const CameraFeaturesListTile({super.key});
@override
Widget build(BuildContext context) {
return IAPListTile(
return ListTile(
leading: const Icon(Icons.camera_alt_outlined),
title: Text(S.of(context).cameraFeatures),
onTap: () {
UserPreferencesProvider.cameraConfigOf(context).entries.map(
(entry) => DialogSwitchListItem(
value: CameraFeature.spotMetering,
title: S.of(context).cameraFeatureSpotMetering,
subtitle: S.of(context).cameraFeatureSpotMeteringHint,
initialValue: UserPreferencesProvider.cameraFeatureOf(context, CameraFeature.spotMetering),
isProRequired: true,
),
);
showDialog(
context: context,
builder: (_) => DialogSwitch<CameraFeature>(
icon: Icons.camera_alt_outlined,
title: S.of(context).cameraFeatures,
values: UserPreferencesProvider.cameraConfigOf(context),
titleAdapter: (context, feature) => switch (feature) {
CameraFeature.spotMetering => S.of(context).cameraFeatureSpotMetering,
CameraFeature.histogram => S.of(context).cameraFeatureHistogram,
CameraFeature.showFocalLength => S.of(context).cameraFeaturesShowFocalLength,
},
subtitleAdapter: (context, feature) => switch (feature) {
CameraFeature.spotMetering => S.of(context).cameraFeatureSpotMeteringHint,
CameraFeature.histogram => S.of(context).cameraFeatureHistogramHint,
CameraFeature.showFocalLength => S.of(context).cameraFeaturesShowFocalLengthHint,
},
items: [
DialogSwitchListItem(
value: CameraFeature.showFocalLength,
title: S.of(context).cameraFeaturesShowFocalLength,
subtitle: S.of(context).cameraFeaturesShowFocalLengthHint,
initialValue: UserPreferencesProvider.cameraFeatureOf(context, CameraFeature.showFocalLength),
isEnabled: ServicesProvider.of(context).userPreferencesService.cameraFocalLength != null,
),
DialogSwitchListItem(
value: CameraFeature.spotMetering,
title: S.of(context).cameraFeatureSpotMetering,
subtitle: S.of(context).cameraFeatureSpotMeteringHint,
initialValue: UserPreferencesProvider.cameraFeatureOf(context, CameraFeature.spotMetering),
isProRequired: true,
),
DialogSwitchListItem(
value: CameraFeature.histogram,
title: S.of(context).cameraFeatureHistogram,
subtitle: S.of(context).cameraFeatureHistogramHint,
initialValue: UserPreferencesProvider.cameraFeatureOf(context, CameraFeature.histogram),
isProRequired: true,
),
],
onSave: UserPreferencesProvider.of(context).setCameraFeature,
),
);

View file

@ -1,14 +1,13 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/navigation/routes.dart';
import 'package:lightmeter/screens/settings/components/shared/iap_list_tile/widget_list_tile_iap.dart';
class LogbookListTile extends StatelessWidget {
const LogbookListTile({super.key});
@override
Widget build(BuildContext context) {
return IAPListTile(
return ListTile(
leading: const Icon(Icons.book_outlined),
title: Text(S.of(context).logbook),
onTap: () {

View file

@ -1,8 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/settings/components/general/components/timer/bloc_list_tile_timer.dart';
import 'package:lightmeter/screens/settings/components/shared/iap_switch_list_tile/widget_iap_switch_list_tile.dart';
import 'package:lightmeter/utils/context_utils.dart';
import 'package:lightmeter/utils/guard_pro_tap.dart';
class TimerListTile extends StatelessWidget {
const TimerListTile({super.key});
@ -10,11 +12,17 @@ class TimerListTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<TimerListTileBloc, bool>(
builder: (context, state) => IAPSwitchListTile(
builder: (context, state) => SwitchListTile(
secondary: const Icon(Icons.timer_outlined),
title: Text(S.of(context).autostartTimer),
value: state,
onChanged: context.read<TimerListTileBloc>().onChanged,
value: context.isPro && state,
contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
onChanged: (value) {
guardProTap(
context,
() => context.read<TimerListTileBloc>().onChanged(value),
);
},
),
);
}

View file

@ -1,14 +1,13 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/navigation/routes.dart';
import 'package:lightmeter/screens/settings/components/shared/iap_list_tile/widget_list_tile_iap.dart';
class EquipmentProfilesListTile extends StatelessWidget {
const EquipmentProfilesListTile({super.key});
@override
Widget build(BuildContext context) {
return IAPListTile(
return ListTile(
leading: const Icon(Icons.camera_outlined),
title: Text(S.of(context).equipmentProfiles),
onTap: () {

View file

@ -1,17 +1,24 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/navigation/routes.dart';
import 'package:lightmeter/screens/settings/components/shared/iap_list_tile/widget_list_tile_iap.dart';
import 'package:lightmeter/utils/guard_pro_tap.dart';
class FilmsListTile extends StatelessWidget {
const FilmsListTile({super.key});
@override
Widget build(BuildContext context) {
return IAPListTile(
return ListTile(
leading: const Icon(Icons.camera_roll_outlined),
title: Text(S.of(context).films),
onTap: () => Navigator.of(context).pushNamed(NavigationRoutes.filmsListScreen.name),
onTap: () {
guardProTap(
context,
() {
Navigator.of(context).pushNamed(NavigationRoutes.filmsListScreen.name);
},
);
},
);
}
}

View file

@ -22,8 +22,16 @@ class MeteringScreenLayoutListTile extends StatelessWidget {
icon: Icons.layers_outlined,
title: S.of(context).meteringScreenLayout,
description: S.of(context).meteringScreenLayoutHint,
values: UserPreferencesProvider.meteringScreenConfigOf(context),
titleAdapter: _toStringLocalized,
items: UserPreferencesProvider.meteringScreenConfigOf(context)
.entries
.map(
(entry) => DialogSwitchListItem(
value: entry.key,
title: _toStringLocalized(context, entry.key),
initialValue: UserPreferencesProvider.meteringScreenFeatureOf(context, entry.key),
),
)
.toList(growable: false),
onSave: (value) {
if (!value[MeteringScreenLayoutFeature.equipmentProfiles]!) {
EquipmentProfilesProvider.of(context).selectProfile(EquipmentProfiles.of(context).first);

View file

@ -1,17 +1,18 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/screens/settings/components/shared/iap_switch_list_tile/widget_iap_switch_list_tile.dart';
import 'package:lightmeter/res/dimens.dart';
class ShowEv100ListTile extends StatelessWidget {
const ShowEv100ListTile({super.key});
@override
Widget build(BuildContext context) {
return IAPSwitchListTile(
return SwitchListTile(
secondary: const Icon(Icons.adjust_outlined),
title: Text(S.of(context).showEv100),
value: UserPreferencesProvider.showEv100Of(context),
contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
onChanged: (_) => UserPreferencesProvider.of(context).toggleShowEv100(),
);
}

View file

@ -1,25 +1,41 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/utils/context_utils.dart';
import 'package:lightmeter/utils/guard_pro_tap.dart';
typedef StringAdapter<T> = String Function(BuildContext context, T value);
class DialogSwitchListItem<T> {
final T value;
final String title;
final String? subtitle;
final bool initialValue;
final bool isEnabled;
final bool isProRequired;
const DialogSwitchListItem({
required this.value,
required this.title,
this.subtitle,
required this.initialValue,
this.isEnabled = true,
this.isProRequired = false,
});
}
class DialogSwitch<T> extends StatefulWidget {
final IconData icon;
final String title;
final String? description;
final Map<T, bool> values;
final StringAdapter<T> titleAdapter;
final StringAdapter<T>? subtitleAdapter;
final List<DialogSwitchListItem<T>> items;
final ValueChanged<Map<T, bool>> onSave;
const DialogSwitch({
required this.icon,
required this.title,
this.description,
required this.values,
required this.titleAdapter,
this.subtitleAdapter,
required this.items,
required this.onSave,
super.key,
});
@ -29,7 +45,11 @@ class DialogSwitch<T> extends StatefulWidget {
}
class _DialogSwitchState<T> extends State<DialogSwitch<T>> {
late final Map<T, bool> _features = Map.from(widget.values);
late final Map<T, bool> _features = Map.fromEntries(
widget.items.map(
(item) => MapEntry(item.value, item.initialValue),
),
);
@override
Widget build(BuildContext context) {
@ -52,23 +72,15 @@ class _DialogSwitchState<T> extends State<DialogSwitch<T>> {
],
ListView(
shrinkWrap: true,
children: _features.entries.map(
(entry) {
children: widget.items.map(
(item) {
final value = _features[item.value]!;
return SwitchListTile(
contentPadding: EdgeInsets.symmetric(horizontal: Dimens.dialogTitlePadding.left),
title: Text(widget.titleAdapter(context, entry.key)),
subtitle: widget.subtitleAdapter != null
? Text(
widget.subtitleAdapter!.call(context, entry.key),
style: Theme.of(context).listTileTheme.subtitleTextStyle,
)
: null,
value: _features[entry.key]!,
onChanged: (value) {
setState(() {
_features.update(entry.key, (_) => value);
});
},
title: Text(item.title),
subtitle: item.subtitle != null ? Text(item.subtitle!) : null,
value: item.isProRequired ? context.isPro && value : value,
onChanged: item.isEnabled ? (value) => _setItem(item, value) : null,
);
},
).toList(),
@ -92,4 +104,18 @@ class _DialogSwitchState<T> extends State<DialogSwitch<T>> {
],
);
}
void _setItem(DialogSwitchListItem<T> item, bool value) {
void setItemState() {
setState(() {
_features.update(item.value, (_) => value);
});
}
if (item.isProRequired) {
guardProTap(context, setItemState);
} else {
setItemState();
}
}
}

View file

@ -1,29 +0,0 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/navigation/routes.dart';
import 'package:lightmeter/utils/context_utils.dart';
class IAPListTile extends StatelessWidget {
final Icon leading;
final Text title;
final VoidCallback onTap;
const IAPListTile({
required this.leading,
required this.title,
required this.onTap,
super.key,
});
@override
Widget build(BuildContext context) {
return ListTile(
leading: leading,
title: title,
onTap: context.isPro
? onTap
: () {
Navigator.of(context).pushNamed(NavigationRoutes.proFeaturesScreen.name);
},
);
}
}

View file

@ -1,37 +0,0 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/navigation/routes.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/utils/context_utils.dart';
class IAPSwitchListTile extends StatelessWidget {
final Icon secondary;
final Text title;
final Text? subtitle;
final bool value;
final ValueChanged<bool>? onChanged;
const IAPSwitchListTile({
required this.secondary,
required this.title,
this.subtitle,
required this.value,
required this.onChanged,
super.key,
});
@override
Widget build(BuildContext context) {
return SwitchListTile(
secondary: secondary,
title: title,
subtitle: subtitle,
value: context.isPro && value,
contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
onChanged: context.isPro
? onChanged
: (_) {
Navigator.of(context).pushNamed(NavigationRoutes.proFeaturesScreen.name);
},
);
}
}

View file

@ -0,0 +1,11 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/navigation/routes.dart';
import 'package:lightmeter/utils/context_utils.dart';
void guardProTap(BuildContext context, VoidCallback callback) {
if (context.isPro) {
callback();
} else {
Navigator.of(context).pushNamed(NavigationRoutes.proFeaturesScreen.name);
}
}

View file

@ -5,6 +5,7 @@ void main() {
test('intlName', () {
expect(SupportedLocale.en.intlName, 'en');
expect(SupportedLocale.fr.intlName, 'fr');
expect(SupportedLocale.pl.intlName, 'pl');
expect(SupportedLocale.ru.intlName, 'ru');
expect(SupportedLocale.zh.intlName, 'zh');
expect(SupportedLocale.de.intlName, 'de');
@ -13,6 +14,7 @@ void main() {
test('localizedName', () {
expect(SupportedLocale.en.localizedName, 'English');
expect(SupportedLocale.fr.localizedName, 'Français');
expect(SupportedLocale.pl.localizedName, 'Polski');
expect(SupportedLocale.ru.localizedName, 'Русский');
expect(SupportedLocale.zh.localizedName, '简体中文');
expect(SupportedLocale.de.localizedName, 'Deutsch');

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB